SymbolTableImpl implements SymbolTable { Symbol getSymbol(QualifiedName qualifiedName) { return symbolByQualifiedName.get(qualifiedName); } private  SymbolTableImpl(); static SymbolTableImpl create(CompilationUnitTree compilationUnit); static SymbolTableImpl create(CompilationUnitTree compilationUnit, ProjectSymbolData projectSymbolData, @Nullable PhpFile file); @Override ImmutableSet<Scope> getScopes(); @Nullable @Override Scope getScopeFor(Tree tree); ImmutableList<Symbol> getSymbols(); @Override List<Symbol> getSymbols(Symbol.Kind kind); List<Symbol> getSymbols(String name); @Override @CheckForNull Symbol getSymbol(Tree tree); Collection<ClassSymbolData> classSymbolDatas(); Collection<FunctionSymbolData> functionSymbolDatas();  }
@Test public void retrieve_symbol_by_tree() { ExpressionTree dollarAUsage = ((AssignmentExpressionTree) ((ExpressionStatementTree) ((FunctionDeclarationTree) cut.script().statements().get(5)).body().statements().get(3)).expression()).variable(); Symbol symbol = SYMBOL_MODEL.getSymbol(dollarAUsage); assertThat(symbol).isNotNull(); assertThat(symbol.name()).isEqualTo("$a"); }
@Test public void nested_function_inside_method() { SymbolTableImpl symbolTable = symbolTableFor("<?php class A { private function nesting() { function nested() {} } }"); Symbol symbol = symbolTable.getSymbol("nested"); assertThat(symbol).isNotNull(); }
@Test public void undeclared_class_usage() { SymbolTableImpl symbolTable = symbolTableFor("<?php $dbh = new PDO('odbc:sample', 'db2inst1', 'ibmdb2');"); Symbol symbol = symbolTable.getSymbol("pdo"); assertThat(symbol).isInstanceOf(UndeclaredSymbol.class); SyntaxToken usage = Iterables.getOnlyElement(symbol.usages()); assertThat(usage.line()).isEqualTo(1); assertThat(usage.column()).isEqualTo(17); }
@Test public void undeclared_class_usage_with_fully_qualified_name() { SymbolTableImpl symbolTable = symbolTableFor("<?php $dbh = new \\PDO('odbc:sample', 'db2inst1', 'ibmdb2');"); Symbol symbol = symbolTable.getSymbol("pdo"); assertThat(symbol).isInstanceOf(UndeclaredSymbol.class); SyntaxToken usage = Iterables.getOnlyElement(symbol.usages()); assertThat(usage.line()).isEqualTo(1); assertThat(usage.column()).isEqualTo(18); }
@Test public void undeclared_class_usage_in_namespace() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace A { $a = new A('odbc:sample', 'db2inst1', 'ibmdb2'); }"); Symbol symbol = symbolTable.getSymbol("A\\A"); assertThat(symbol).isInstanceOf(UndeclaredSymbol.class); SyntaxToken usage = Iterables.getOnlyElement(symbol.usages()); assertThat(usage.line()).isEqualTo(1); assertThat(usage.column()).isEqualTo(30); }
@Test public void undeclared_function_usage() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace A { $a = f(); $b = f(); } f();"); Symbol symbol = symbolTable.getSymbol("f"); assertThat(symbol).isNotNull(); assertThat(symbol).isInstanceOf(UndeclaredSymbol.class); assertSymbolUsages(symbolTable, "f", 1, 1, 1); }
@Test public void test_type_symbol() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class A {} class B extends A {} } "); Symbol classA = symbolTable.getSymbol("n\\a"); Symbol classB = symbolTable.getSymbol("n\\b"); assertThat(classA.name()).isEqualTo("a"); assertThat(classA).isInstanceOf(TypeSymbol.class); assertThat(classB).isInstanceOf(TypeSymbol.class); assertThat(((TypeSymbol) classB).superClass()).isEqualTo(classA); assertThat(((TypeSymbol) classA).superClass()).isNull(); }
@Test public void test_undeclared_superclass() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class B extends A {} } "); Symbol classA = symbolTable.getSymbol("n\\a"); Symbol classB = symbolTable.getSymbol("n\\b"); assertThat(classA).isInstanceOf(UndeclaredSymbol.class); assertThat(classB).isInstanceOf(TypeSymbol.class); assertThat(((TypeSymbol) classB).superClass()).isEqualTo(classA); }
@Test public void test_superclass_with_qualified_name() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { use M; class B extends M\\A implements \\M\\C {} } namespace M { class A {} interface C {} }"); TypeSymbol classA = (TypeSymbol) symbolTable.getSymbol("m\\a"); TypeSymbol classB = (TypeSymbol) symbolTable.getSymbol("n\\b"); assertThat(classB.superClass()).isEqualTo(classA); assertThat(classB.interfaces()).extracting(i -> i.qualifiedName().toString()).containsExactly("m\\c"); }
@Test public void test_class_symbol_with_interfaces() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class B implements I1, I2 {} interface I1 {} } "); TypeSymbol classB = (TypeSymbol) symbolTable.getSymbol("n\\b"); Symbol iface1 = symbolTable.getSymbol("n\\i1"); Symbol iface2 = symbolTable.getSymbol("n\\i2"); assertThat(classB.interfaces()).containsExactly(iface1, iface2); assertThat(iface1).isInstanceOf(TypeSymbol.class); assertThat(iface2).isInstanceOf(UndeclaredSymbol.class); }
@Test public void test_class_symbol_members() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class A { const A; function foo() {} } } class B { function bar() {} }"); TypeSymbol classA = (TypeSymbol) symbolTable.getSymbol("n\\a"); assertThat(classA.kind()).isEqualTo(Kind.CLASS); assertThat(classA.members()).extracting(m -> m.qualifiedName().toString()) .containsExactly("n\\a::a", "n\\a::foo"); assertThat(classA.members()).extracting(MemberSymbol::owner).allMatch(classA::equals); TypeSymbol classB = (TypeSymbol) symbolTable.getSymbol("b"); assertThat(classB.members()).extracting(m -> m.qualifiedName().toString()) .containsExactly("b::bar"); assertThat(classB.members()).extracting(MemberSymbol::owner).allMatch(classB::equals); }
@Test public void test_class_symbol_members_case_insensitive() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class A { const A; function Foo() {} } } "); TypeSymbol classA = (TypeSymbol) symbolTable.getSymbol("n\\a"); assertThat(classA.members()).extracting(m -> m.qualifiedName().simpleName()).containsExactly("a", "foo"); }
@Test public void static_invocation() { SymbolTableImpl symbolTable = symbolTableFor("<?php use Cake\\Utility\\Security as CakeSecurity; CakeSecurity::encrypt($data, $key); "); Symbol symbol = symbolTable.getSymbol("cake\\utility\\security"); assertThat(symbol).isNotNull(); assertThat(symbol.kind()).isEqualTo(Kind.CLASS); assertThat(symbol).isExactlyInstanceOf(UndeclaredSymbol.class); }
@Test public void new_expression_wo_brackets() { SymbolTableImpl symbolTable = symbolTableFor("<?php new A; "); Symbol a = symbolTable.getSymbol("a"); assertThat(a).isNotNull(); assertThat(a.usages()).hasSize(1); }
@Test public void anonymous_class() { SymbolTableImpl symbolTable = symbolTableFor("<?php new class() extends A implements I1, I2 {};"); Symbol symbol = symbolTable.getSymbol("a"); assertThat(symbol).isNotNull(); assertThat(symbol.kind()).isEqualTo(Kind.CLASS); assertThat(symbol).isExactlyInstanceOf(UndeclaredSymbol.class); assertThat(symbolTable.getSymbol("i1")).isNotNull(); assertThat(symbolTable.getSymbol("i2")).isNotNull(); }
@Test public void traits() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { class A { use trait1, trait2; } }"); assertThat(symbolTable.getSymbol("n\\trait1")).isNotNull(); assertThat(symbolTable.getSymbol("n\\trait2")).isNotNull(); }
@Test public void use_in_trait() { SymbolTableImpl symbolTable = symbolTableFor("<?php namespace N { trait A { use trait1, trait2; } }"); assertThat(symbolTable.getSymbol("n\\a")).isNotNull(); assertThat(symbolTable.getSymbol("n\\trait1")).isNotNull(); assertThat(symbolTable.getSymbol("n\\trait2")).isNotNull(); }
@Test public void lexical_vars_tree_symbol_association() { FunctionExpressionTree functionExpression = (FunctionExpressionTree) ((AssignmentExpressionTree)((ExpressionStatementTree) cut.script().statements().get(7)).expression()).value(); Symbol symbol = SYMBOL_MODEL.getSymbol(functionExpression.lexicalVars().variables().get(0)); assertThat(symbol).isNotNull(); assertThat(((PHPTree)symbol.declaration()).getLine()).isEqualTo(3); }
@Test public void global_statement_with_compound_variable() { SymbolTableImpl symbolTable = symbolTableFor("<?php global ${foo()};"); assertThat(symbolTable.getSymbol("foo")).isNotNull(); }