summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorKaloyan Raev2013-11-06 08:02:18 (EST)
committer Gerrit Code Review @ Eclipse.org2013-11-12 13:10:14 (EST)
commitbe8c295e314470319b695cded73add35e4fd297e (patch)
tree5f76003f9295ac2aa312a0c360e07fc1fcf5ec97
parent034edb0e4d6730afa62660ea15a48931679f0f12 (diff)
downloadorg.eclipse.pdt-be8c295e314470319b695cded73add35e4fd297e.zip
org.eclipse.pdt-be8c295e314470319b695cded73add35e4fd297e.tar.gz
org.eclipse.pdt-be8c295e314470319b695cded73add35e4fd297e.tar.bz2
Bug 421328 - Performance issue with TraitUtils.parse()refs/changes/20/18220/4
The AST visitor used in TraitUtils.parse() is optimized for performance to traverse only the nodes where use statements can be legally found and not go deeper in the AST tree. Tests added to the suite. Bug: 421328 Change-Id: I5902222bce4b3b7f31eb2dd9862a7e6d20e75fb3 Signed-off-by: Kaloyan Raev <kaloyan.r@zend.com>
-rw-r--r--plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/compiler/ast/visitor/TraitUseStatementASTVisitor.java100
-rw-r--r--plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/typeinference/TraitUtils.java5
-rw-r--r--tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/AllTests.java2
-rw-r--r--tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/compiler_ast/parser/TraitUseStatementASTVisitorTests.java117
-rw-r--r--tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testComposedTraits.pdtt39
-rw-r--r--tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testIllegal.pdtt19
-rw-r--r--tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testNamespace.pdtt45
-rw-r--r--tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testSimple.pdtt28
8 files changed, 353 insertions, 2 deletions
diff --git a/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/compiler/ast/visitor/TraitUseStatementASTVisitor.java b/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/compiler/ast/visitor/TraitUseStatementASTVisitor.java
new file mode 100644
index 0000000..b969f76
--- /dev/null
+++ b/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/compiler/ast/visitor/TraitUseStatementASTVisitor.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Zend Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zend Technologies - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.php.internal.core.compiler.ast.visitor;
+
+import org.eclipse.dltk.ast.ASTNode;
+import org.eclipse.dltk.ast.ASTVisitor;
+import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
+import org.eclipse.dltk.ast.declarations.TypeDeclaration;
+import org.eclipse.dltk.ast.expressions.Expression;
+import org.eclipse.dltk.ast.statements.Block;
+import org.eclipse.dltk.ast.statements.Statement;
+import org.eclipse.php.internal.core.compiler.ast.nodes.ClassDeclaration;
+import org.eclipse.php.internal.core.compiler.ast.nodes.NamespaceDeclaration;
+import org.eclipse.php.internal.core.compiler.ast.nodes.TraitUseStatement;
+
+/**
+ * AST visitor for finding trait use statements in PHP source modules.
+ *
+ * <p>
+ * This visitor is optimized for performance to look not deeper than the
+ * necessary level in the AST tree. As described in the <a
+ * href="http://php.net/manual/en/language.oop5.traits.php">PHP Manual</a> trait
+ * use statements can be legally placed only in the scope of class declarations.
+ * </p>
+ *
+ * @author Kaloyan Raev
+ */
+public abstract class TraitUseStatementASTVisitor extends ASTVisitor {
+
+ /**
+ * The visitor must always look inside {@link ModuleDeclaration}s.
+ */
+ @Override
+ public boolean visit(ModuleDeclaration s) throws Exception {
+ return true;
+ }
+
+ /**
+ * The visitor must look into an {@link Expression} only if it is a
+ * {@link Block} (because it can be a block of a class declaration).
+ */
+ @Override
+ public boolean visit(Expression s) throws Exception {
+ return s instanceof Block;
+ }
+
+ /**
+ * The visitor must look into a {@link TypeDeclaration} only if it is a
+ * {@link NamespaceDeclaration} or a {@link ClassDeclaration}.
+ */
+ @Override
+ public boolean visit(TypeDeclaration s) throws Exception {
+ return s instanceof NamespaceDeclaration
+ || s instanceof ClassDeclaration;
+ }
+
+ /**
+ * The visitor must check if a {@link Statement} is a
+ * {@link TraitUseStatement}. If yes then call
+ * {@link #visit(TraitUseStatement)}. Otherwise the visitor must not look
+ * deeper in the AST tree.
+ */
+ @Override
+ public boolean visit(Statement s) throws Exception {
+ if (s instanceof TraitUseStatement) {
+ return visit((TraitUseStatement) s);
+ }
+ return false;
+ }
+
+ /**
+ * Subclasses must implement this method to process the found
+ * {@link TraitUseStatement} nodes.
+ *
+ * @param s
+ * the visited AST node
+ * @return <code>true</code> if the visitor should traverse the children of
+ * this node, <code>false</code> - otherwise.
+ * @throws Exception
+ */
+ public abstract boolean visit(TraitUseStatement s) throws Exception;
+
+ /**
+ * In all other cases the visitor must not look deeper into the AST tree -
+ * there is no chance to find an {@link TraitUseStatement} there.
+ */
+ @Override
+ public boolean visitGeneral(ASTNode node) throws Exception {
+ return false;
+ }
+
+}
diff --git a/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/typeinference/TraitUtils.java b/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/typeinference/TraitUtils.java
index 6b0aa39..976af52 100644
--- a/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/typeinference/TraitUtils.java
+++ b/plugins/org.eclipse.php.core/src/org/eclipse/php/internal/core/typeinference/TraitUtils.java
@@ -19,7 +19,7 @@ import org.eclipse.dltk.internal.core.SourceField;
import org.eclipse.dltk.internal.core.SourceMethod;
import org.eclipse.php.core.compiler.PHPFlags;
import org.eclipse.php.internal.core.compiler.ast.nodes.*;
-import org.eclipse.php.internal.core.compiler.ast.visitor.PHPASTVisitor;
+import org.eclipse.php.internal.core.compiler.ast.visitor.TraitUseStatementASTVisitor;
import org.eclipse.php.internal.core.model.PhpModelAccess;
/**
@@ -37,7 +37,8 @@ public class TraitUtils {
final ISourceRange sourceRange = type.getSourceRange();
ModuleDeclaration moduleDeclaration = SourceParserUtil
.getModuleDeclaration(sourceModule);
- moduleDeclaration.traverse(new PHPASTVisitor() {
+ moduleDeclaration.traverse(new TraitUseStatementASTVisitor() {
+ @Override
public boolean visit(TraitUseStatement s) throws Exception {
if (s.sourceStart() > sourceRange.getOffset()
&& s.sourceEnd() < sourceRange.getOffset()
diff --git a/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/AllTests.java b/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/AllTests.java
index 2e21e6c..c5829de 100644
--- a/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/AllTests.java
+++ b/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/AllTests.java
@@ -19,6 +19,7 @@ import org.eclipse.php.core.tests.compiler_ast.parser.CompilerParserTests;
import org.eclipse.php.core.tests.compiler_ast.parser.FindUseStatementByAliasTests;
import org.eclipse.php.core.tests.compiler_ast.parser.FindUseStatementByNamespaceTests;
import org.eclipse.php.core.tests.compiler_ast.parser.GetUseStatementsByTests;
+import org.eclipse.php.core.tests.compiler_ast.parser.TraitUseStatementASTVisitorTests;
import org.eclipse.php.core.tests.compiler_ast.phpdoc.PHPDocAwareDeclarationTests;
import org.eclipse.php.core.tests.compiler_ast.phpdoc.PHPDocParserTests;
import org.eclipse.php.core.tests.document.lexer.DocumentLexerTests;
@@ -52,6 +53,7 @@ public class AllTests {
suite.addTest(FindUseStatementByAliasTests.suite());
suite.addTest(FindUseStatementByNamespaceTests.suite());
suite.addTest(GetUseStatementsByTests.suite());
+ suite.addTest(TraitUseStatementASTVisitorTests.suite());
suite.addTest(ErrorReportingTests.suite());
suite.addTest(ASTRewriteTests.suite());
suite.addTest(ASTMatcherTests.suite());
diff --git a/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/compiler_ast/parser/TraitUseStatementASTVisitorTests.java b/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/compiler_ast/parser/TraitUseStatementASTVisitorTests.java
new file mode 100644
index 0000000..e2bf11c
--- /dev/null
+++ b/tests/org.eclipse.php.core.tests/src/org/eclipse/php/core/tests/compiler_ast/parser/TraitUseStatementASTVisitorTests.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Zend Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Zend Technologies - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.php.core.tests.compiler_ast.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
+import org.eclipse.php.core.tests.AbstractPDTTTest;
+import org.eclipse.php.core.tests.PdttFile;
+import org.eclipse.php.internal.core.PHPVersion;
+import org.eclipse.php.internal.core.compiler.ast.nodes.TraitUseStatement;
+import org.eclipse.php.internal.core.compiler.ast.parser.AbstractPHPSourceParser;
+import org.eclipse.php.internal.core.compiler.ast.parser.PHPSourceParserFactory;
+import org.eclipse.php.internal.core.compiler.ast.visitor.TraitUseStatementASTVisitor;
+import org.eclipse.php.internal.core.project.ProjectOptions;
+
+public class TraitUseStatementASTVisitorTests extends AbstractPDTTTest {
+
+ protected static final Map<PHPVersion, String[]> TESTS = new LinkedHashMap<PHPVersion, String[]>();
+ static {
+ TESTS.put(
+ PHPVersion.PHP5_4,
+ new String[] { "/workspace/astutils/trait_use_statement_visitor/php54" });
+ };
+
+ public TraitUseStatementASTVisitorTests(String description) {
+ super(description);
+ }
+
+ public static Test suite() {
+
+ TestSuite suite = new TestSuite("Trait Use Statement Tests");
+
+ for (final PHPVersion phpVersion : TESTS.keySet()) {
+ TestSuite phpVerSuite = new TestSuite(phpVersion.getAlias());
+ final AbstractPHPSourceParser parser = PHPSourceParserFactory
+ .createParser(phpVersion);
+
+ for (String testsDirectory : TESTS.get(phpVersion)) {
+
+ for (final String fileName : getPDTTFiles(testsDirectory)) {
+ try {
+ final PdttFile pdttFile = new PdttFile(fileName);
+ phpVerSuite.addTest(new CompilerParserTests(phpVersion
+ .getAlias() + " - /" + fileName) {
+
+ protected void runTest() throws Throwable {
+
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(
+ pdttFile.getFile().trim().getBytes());
+ ModuleDeclaration moduleDeclaration = (ModuleDeclaration) parser
+ .parse(new InputStreamReader(
+ inputStream),
+ null,
+ ProjectOptions
+ .useShortTags((IProject) null));
+
+ final StringBuilder builder = new StringBuilder();
+
+ moduleDeclaration
+ .traverse(new TraitUseStatementASTVisitor() {
+ @Override
+ public boolean visit(
+ TraitUseStatement s)
+ throws Exception {
+ builder.append(s);
+ return false;
+ }
+ });
+
+ String actual = builder.toString();
+ String expected = pdttFile.getExpected();
+
+ assertContents(expected, actual);
+ }
+ });
+ } catch (final Exception e) {
+ // dummy test indicating PDTT file parsing failure
+ phpVerSuite.addTest(new TestCase(fileName) {
+ protected void runTest() throws Throwable {
+ throw e;
+ }
+ });
+ }
+ }
+ }
+ suite.addTest(phpVerSuite);
+ }
+
+ // Create a setup wrapper
+ TestSetup setup = new TestSetup(suite) {
+ protected void setUp() throws Exception {
+ }
+
+ protected void tearDown() throws Exception {
+ }
+ };
+ return setup;
+ }
+}
diff --git a/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testComposedTraits.pdtt b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testComposedTraits.pdtt
new file mode 100644
index 0000000..c53d889
--- /dev/null
+++ b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testComposedTraits.pdtt
@@ -0,0 +1,39 @@
+--TEST--
+Get trait use statements in an example of composed traits
+--FILE--
+<?php
+trait Hello {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+}
+
+trait World {
+ public function sayWorld() {
+ echo 'World!';
+ }
+}
+
+trait HelloWorld {
+ use Hello, World;
+}
+
+class MyHelloWorld {
+ use HelloWorld;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+$o->sayWorld();
+?>
+--EXPECT--
+<TraitUseStatement start="187" end="204">
+ <FullyQualifiedReference start="191" end="196" name="Hello">
+ </FullyQualifiedReference>
+ <FullyQualifiedReference start="198" end="203" name="World">
+ </FullyQualifiedReference>
+</TraitUseStatement>
+<TraitUseStatement start="233" end="248">
+ <FullyQualifiedReference start="237" end="247" name="HelloWorld">
+ </FullyQualifiedReference>
+</TraitUseStatement>
diff --git a/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testIllegal.pdtt b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testIllegal.pdtt
new file mode 100644
index 0000000..5da326d
--- /dev/null
+++ b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testIllegal.pdtt
@@ -0,0 +1,19 @@
+--TEST--
+Get trait use statements in an example where the "use" keyword is used, but none of the usages is a legal trait use statement.
+--FILE--
+<?php
+use My\Full\NSname;
+
+namespace MyProject {
+ use Languages\Danish;
+
+ $obj = new Danish;
+}
+
+class HelloWorld {
+ public function hello() {
+ use Hello;
+ }
+}
+?>
+--EXPECT--
diff --git a/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testNamespace.pdtt b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testNamespace.pdtt
new file mode 100644
index 0000000..5eccfaf
--- /dev/null
+++ b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testNamespace.pdtt
@@ -0,0 +1,45 @@
+--TEST--
+Get trait use statements in an example of traits inside namespaces
+--FILE--
+<?php
+namespace NSOne {
+ trait Hello {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+ }
+
+ trait World {
+ public function sayWorld() {
+ echo 'World!';
+ }
+ }
+
+ trait HelloWorld {
+ use Hello, World;
+ }
+}
+
+namespace NSTwo {
+ class MyHelloWorld {
+ use NSOne\HelloWorld;
+ }
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+$o->sayWorld();
+?>
+--EXPECT--
+<TraitUseStatement start="219" end="236">
+ <FullyQualifiedReference start="223" end="228" name="Hello">
+ </FullyQualifiedReference>
+ <FullyQualifiedReference start="230" end="235" name="World">
+ </FullyQualifiedReference>
+</TraitUseStatement>
+<TraitUseStatement start="288" end="309">
+ <FullyQualifiedReference start="292" end="308" name="NSOne\HelloWorld">
+ <NamespaceReference start="292" end="297" name="NSOne" global="false" local="false">
+ </NamespaceReference>
+ </FullyQualifiedReference>
+</TraitUseStatement>
diff --git a/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testSimple.pdtt b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testSimple.pdtt
new file mode 100644
index 0000000..fe24e4c
--- /dev/null
+++ b/tests/org.eclipse.php.core.tests/workspace/astutils/trait_use_statement_visitor/php54/testSimple.pdtt
@@ -0,0 +1,28 @@
+--TEST--
+Get trait use statements in a simple example
+--FILE--
+<?php
+trait ezcReflectionReturnInfo {
+ function getReturnType() { /*1*/ }
+ function getReturnDescription() { /*2*/ }
+}
+
+class ezcReflectionMethod extends ReflectionMethod {
+ use ezcReflectionReturnInfo;
+ /* ... */
+}
+
+class ezcReflectionFunction extends ReflectionFunction {
+ use ezcReflectionReturnInfo;
+ /* ... */
+}
+?>
+--EXPECT--
+<TraitUseStatement start="183" end="211">
+ <FullyQualifiedReference start="187" end="210" name="ezcReflectionReturnInfo">
+ </FullyQualifiedReference>
+</TraitUseStatement>
+<TraitUseStatement start="290" end="318">
+ <FullyQualifiedReference start="294" end="317" name="ezcReflectionReturnInfo">
+ </FullyQualifiedReference>
+</TraitUseStatement>