1
0
Fork 0

Add support for inherited members (#218)

in completion, definition, references, hover etc
pull/219/head v4.1.0
Felix Becker 2016-12-16 01:40:17 +01:00 committed by GitHub
parent cc9d5e987b
commit a4a13e6528
14 changed files with 145 additions and 23 deletions

View File

@ -1,4 +1,4 @@
<?php <?php
$obj = new TestClass; $obj = new ChildClass;
$obj-> $obj->

View File

@ -38,3 +38,6 @@ if ($abc instanceof TestInterface) {
// Nested expression // Nested expression
$obj->testProperty->testMethod(); $obj->testProperty->testMethod();
TestClass::$staticTestProperty[123]->testProperty; TestClass::$staticTestProperty[123]->testProperty;
$child = new ChildClass;
echo $child->testMethod();

View File

@ -96,3 +96,5 @@ new class {
$testVariable = 123; $testVariable = 123;
} }
}; };
class ChildClass extends TestClass {}

View File

@ -38,3 +38,6 @@ if ($abc instanceof TestInterface) {
// Nested expressions // Nested expressions
$obj->testProperty->testMethod(); $obj->testProperty->testMethod();
TestClass::$staticTestProperty[123]->testProperty; TestClass::$staticTestProperty[123]->testProperty;
$child = new ChildClass;
echo $child->testMethod();

View File

@ -96,3 +96,5 @@ new class {
$testVariable = 123; $testVariable = 123;
} }
}; };
class ChildClass extends TestClass {}

View File

@ -145,8 +145,10 @@ class CompletionProvider
$this->definitionResolver->resolveExpressionNodeToType($node->var) $this->definitionResolver->resolveExpressionNodeToType($node->var)
); );
} else { } else {
// Static member reference
$prefixes = [$node->class instanceof Node\Name ? (string)$node->class : '']; $prefixes = [$node->class instanceof Node\Name ? (string)$node->class : ''];
} }
$prefixes = $this->expandParentFqns($prefixes);
// If we are just filtering by the class, add the appropiate operator to the prefix // If we are just filtering by the class, add the appropiate operator to the prefix
// to filter the type of symbol // to filter the type of symbol
foreach ($prefixes as &$prefix) { foreach ($prefixes as &$prefix) {
@ -158,6 +160,7 @@ class CompletionProvider
$prefix .= '::$'; $prefix .= '::$';
} }
} }
unset($prefix);
foreach ($this->index->getDefinitions() as $fqn => $def) { foreach ($this->index->getDefinitions() as $fqn => $def) {
foreach ($prefixes as $prefix) { foreach ($prefixes as $prefix) {
@ -287,6 +290,26 @@ class CompletionProvider
return $list; return $list;
} }
/**
* Adds the FQNs of all parent classes to an array of FQNs of classes
*
* @param string[] $fqns
* @return string[]
*/
private function expandParentFqns(array $fqns): array
{
$expanded = $fqns;
foreach ($fqns as $fqn) {
$def = $this->index->getDefinition($fqn);
if ($def) {
foreach ($this->expandParentFqns($def->extends) as $parent) {
$expanded[] = $parent;
}
}
}
return $expanded;
}
/** /**
* Will walk the AST upwards until a function-like node is met * Will walk the AST upwards until a function-like node is met
* and at each level walk all previous siblings and their children to search for definitions * and at each level walk all previous siblings and their children to search for definitions

View File

@ -30,6 +30,13 @@ class Definition
*/ */
public $fqn; public $fqn;
/**
* For class or interfaces, the FQNs of extended classes and implemented interfaces
*
* @var string[]
*/
public $extends;
/** /**
* Only true for classes, interfaces, traits, functions and non-class constants * Only true for classes, interfaces, traits, functions and non-class constants
* This is so methods and properties are not suggested in the global scope * This is so methods and properties are not suggested in the global scope

View File

@ -115,6 +115,17 @@ class DefinitionResolver
|| ($node instanceof Node\Stmt\PropertyProperty && $node->getAttribute('parentNode')->isStatic()) || ($node instanceof Node\Stmt\PropertyProperty && $node->getAttribute('parentNode')->isStatic())
); );
$def->fqn = $fqn; $def->fqn = $fqn;
if ($node instanceof Node\Stmt\Class_) {
$def->extends = [];
if ($node->extends) {
$def->extends[] = (string)$node->extends;
}
} else if ($node instanceof Node\Stmt\Interface_) {
$def->extends = [];
foreach ($node->extends as $n) {
$def->extends[] = (string)$n;
}
}
$def->symbolInformation = SymbolInformation::fromNode($node, $fqn); $def->symbolInformation = SymbolInformation::fromNode($node, $fqn);
$def->type = $this->getTypeFromNode($node); $def->type = $this->getTypeFromNode($node);
$def->declarationLine = $this->getDeclarationLineFromNode($node); $def->declarationLine = $this->getDeclarationLineFromNode($node);
@ -248,7 +259,31 @@ class DefinitionResolver
} else { } else {
$classFqn = substr((string)$varType->getFqsen(), 1); $classFqn = substr((string)$varType->getFqsen(), 1);
} }
$name = $classFqn . '->' . (string)$node->name; $memberSuffix = '->' . (string)$node->name;
if ($node instanceof Node\Expr\MethodCall) {
$memberSuffix .= '()';
}
// Find the right class that implements the member
$implementorFqns = [$classFqn];
while ($implementorFqn = array_shift($implementorFqns)) {
// If the member FQN exists, return it
if ($this->index->getDefinition($implementorFqn . $memberSuffix)) {
return $implementorFqn . $memberSuffix;
}
// Get Definition of implementor class
$implementorDef = $this->index->getDefinition($implementorFqn);
// If it doesn't exist, return the initial guess
if ($implementorDef === null) {
break;
}
// Repeat for parent class
if ($implementorDef->extends) {
foreach ($implementorDef->extends as $extends) {
$implementorFqns[] = $extends;
}
}
}
return $classFqn . $memberSuffix;
} else if ($parent instanceof Node\Expr\FuncCall) { } else if ($parent instanceof Node\Expr\FuncCall) {
if ($parent->name instanceof Node\Expr) { if ($parent->name instanceof Node\Expr) {
return null; return null;
@ -290,6 +325,9 @@ class DefinitionResolver
} else { } else {
return null; return null;
} }
if (!isset($name)) {
return null;
}
if ( if (
$node instanceof Node\Expr\MethodCall $node instanceof Node\Expr\MethodCall
|| $node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\StaticCall
@ -297,9 +335,6 @@ class DefinitionResolver
) { ) {
$name .= '()'; $name .= '()';
} }
if (!isset($name)) {
return null;
}
return $name; return $name;
} }

View File

@ -49,7 +49,8 @@ class DefinitionCollectorTest extends TestCase
'TestNamespace\\TestClass->testMethod()', 'TestNamespace\\TestClass->testMethod()',
'TestNamespace\\TestTrait', 'TestNamespace\\TestTrait',
'TestNamespace\\TestInterface', 'TestNamespace\\TestInterface',
'TestNamespace\\test_function()' 'TestNamespace\\test_function()',
'TestNamespace\\ChildClass'
], array_keys($defNodes)); ], array_keys($defNodes));
$this->assertInstanceOf(Node\Const_::class, $defNodes['TestNamespace\\TEST_CONST']); $this->assertInstanceOf(Node\Const_::class, $defNodes['TestNamespace\\TEST_CONST']);
$this->assertInstanceOf(Node\Stmt\Class_::class, $defNodes['TestNamespace\\TestClass']); $this->assertInstanceOf(Node\Stmt\Class_::class, $defNodes['TestNamespace\\TestClass']);
@ -61,6 +62,7 @@ class DefinitionCollectorTest extends TestCase
$this->assertInstanceOf(Node\Stmt\Trait_::class, $defNodes['TestNamespace\\TestTrait']); $this->assertInstanceOf(Node\Stmt\Trait_::class, $defNodes['TestNamespace\\TestTrait']);
$this->assertInstanceOf(Node\Stmt\Interface_::class, $defNodes['TestNamespace\\TestInterface']); $this->assertInstanceOf(Node\Stmt\Interface_::class, $defNodes['TestNamespace\\TestInterface']);
$this->assertInstanceOf(Node\Stmt\Function_::class, $defNodes['TestNamespace\\test_function()']); $this->assertInstanceOf(Node\Stmt\Function_::class, $defNodes['TestNamespace\\test_function()']);
$this->assertInstanceOf(Node\Stmt\Class_::class, $defNodes['TestNamespace\\ChildClass']);
} }
public function testDoesNotCollectReferences() public function testDoesNotCollectReferences()

View File

@ -71,6 +71,7 @@ abstract class ServerTestCase extends TestCase
// Global // Global
'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))), 'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
'TestClass' => new Location($globalSymbolsUri, new Range(new Position(20, 0), new Position(61, 1))), 'TestClass' => new Location($globalSymbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
'ChildClass' => new Location($globalSymbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
'TestTrait' => new Location($globalSymbolsUri, new Range(new Position(63, 0), new Position(66, 1))), 'TestTrait' => new Location($globalSymbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
'TestInterface' => new Location($globalSymbolsUri, new Range(new Position(68, 0), new Position(71, 1))), 'TestInterface' => new Location($globalSymbolsUri, new Range(new Position(68, 0), new Position(71, 1))),
'TestClass::TEST_CLASS_CONST' => new Location($globalSymbolsUri, new Range(new Position(27, 10), new Position(27, 32))), 'TestClass::TEST_CLASS_CONST' => new Location($globalSymbolsUri, new Range(new Position(27, 10), new Position(27, 32))),
@ -86,6 +87,7 @@ abstract class ServerTestCase extends TestCase
'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 0), new Position( 2, 30))), 'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 0), new Position( 2, 30))),
'TestNamespace\\TEST_CONST' => new Location($symbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))), 'TestNamespace\\TEST_CONST' => new Location($symbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
'TestNamespace\\TestClass' => new Location($symbolsUri, new Range(new Position(20, 0), new Position(61, 1))), 'TestNamespace\\TestClass' => new Location($symbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
'TestNamespace\\ChildClass' => new Location($symbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
'TestNamespace\\TestTrait' => new Location($symbolsUri, new Range(new Position(63, 0), new Position(66, 1))), 'TestNamespace\\TestTrait' => new Location($symbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
'TestNamespace\\TestInterface' => new Location($symbolsUri, new Range(new Position(68, 0), new Position(71, 1))), 'TestNamespace\\TestInterface' => new Location($symbolsUri, new Range(new Position(68, 0), new Position(71, 1))),
'TestNamespace\\TestClass::TEST_CLASS_CONST' => new Location($symbolsUri, new Range(new Position(27, 10), new Position(27, 32))), 'TestNamespace\\TestClass::TEST_CLASS_CONST' => new Location($symbolsUri, new Range(new Position(27, 10), new Position(27, 32))),
@ -104,14 +106,18 @@ abstract class ServerTestCase extends TestCase
0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15))) 0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15)))
], ],
'TestNamespace\\TestClass' => [ 'TestNamespace\\TestClass' => [
0 => new Location($referencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); 0 => new Location($symbolsUri , new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {}
1 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); 1 => new Location($referencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass();
2 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; 2 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod();
3 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; 3 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty;
4 => new Location($referencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) 4 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST;
5 => new Location($referencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass 5 => new Location($referencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param)
6 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; 6 => new Location($referencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass
7 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass; 7 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty;
8 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass;
],
'TestNamespace\\TestChild' => [
0 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 25))), // echo $child->testProperty;
], ],
'TestNamespace\\TestInterface' => [ 'TestNamespace\\TestInterface' => [
0 => new Location($symbolsUri, new Range(new Position(20, 27), new Position(20, 40))), // class TestClass implements TestInterface 0 => new Location($symbolsUri, new Range(new Position(20, 27), new Position(20, 40))), // class TestClass implements TestInterface
@ -137,7 +143,8 @@ abstract class ServerTestCase extends TestCase
], ],
'TestNamespace\\TestClass::testMethod()' => [ 'TestNamespace\\TestClass::testMethod()' => [
0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); 0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod();
1 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 32))) // $obj->testProperty->testMethod(); 1 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 32))), // $obj->testProperty->testMethod();
2 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 25))) // $child->testMethod();
], ],
'TestNamespace\\test_function()' => [ 'TestNamespace\\test_function()' => [
0 => new Location($referencesUri, new Range(new Position(10, 0), new Position(10, 13))), 0 => new Location($referencesUri, new Range(new Position(10, 0), new Position(10, 13))),
@ -150,13 +157,17 @@ abstract class ServerTestCase extends TestCase
1 => new Location($globalReferencesUri, new Range(new Position(29, 5), new Position(29, 15))) 1 => new Location($globalReferencesUri, new Range(new Position(29, 5), new Position(29, 15)))
], ],
'TestClass' => [ 'TestClass' => [
0 => new Location($globalReferencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); 0 => new Location($globalSymbolsUri, new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {}
1 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); 1 => new Location($globalReferencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass();
2 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; 2 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod();
3 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; 3 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty;
4 => new Location($globalReferencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) 4 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST;
5 => new Location($globalReferencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass 5 => new Location($globalReferencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param)
6 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; 6 => new Location($globalReferencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass
7 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty;
],
'TestChild' => [
0 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 25))), // echo $child->testProperty;
], ],
'TestInterface' => [ 'TestInterface' => [
0 => new Location($globalSymbolsUri, new Range(new Position(20, 27), new Position(20, 40))), // class TestClass implements TestInterface 0 => new Location($globalSymbolsUri, new Range(new Position(20, 27), new Position(20, 40))), // class TestClass implements TestInterface
@ -182,7 +193,8 @@ abstract class ServerTestCase extends TestCase
], ],
'TestClass::testMethod()' => [ 'TestClass::testMethod()' => [
0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); 0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod();
1 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 32))) // $obj->testProperty->testMethod(); 1 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 32))), // $obj->testProperty->testMethod();
2 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 25))) // $child->testMethod();
], ],
'test_function()' => [ 'test_function()' => [
0 => new Location($globalReferencesUri, new Range(new Position(10, 0), new Position(10, 13))), 0 => new Location($globalReferencesUri, new Range(new Position(10, 0), new Position(10, 13))),

View File

@ -165,6 +165,15 @@ class CompletionTest extends TestCase
null, null,
'\TestClass' '\TestClass'
), ),
new CompletionItem(
'ChildClass',
CompletionItemKind::CLASS_,
null,
null,
null,
null,
'\ChildClass'
),
// Namespaced, `use`d TestClass definition (inserted as TestClass) // Namespaced, `use`d TestClass definition (inserted as TestClass)
new CompletionItem( new CompletionItem(
'TestClass', 'TestClass',
@ -175,6 +184,15 @@ class CompletionTest extends TestCase
null, null,
'TestClass' 'TestClass'
), ),
new CompletionItem(
'ChildClass',
CompletionItemKind::CLASS_,
'TestNamespace',
null,
null,
null,
'\TestNamespace\ChildClass'
),
], true), $items); ], true), $items);
} }

View File

@ -161,6 +161,18 @@ class GlobalTest extends ServerTestCase
$this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result); $this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result);
} }
public function testDefinitionForMethodOnChildClass()
{
// $child->testMethod();
// Get definition for testMethod
$reference = $this->getReferenceLocations('TestClass::testMethod()')[2];
$result = $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
$this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result);
}
public function testDefinitionForProperties() public function testDefinitionForProperties()
{ {
// echo $obj->testProperty; // echo $obj->testProperty;

View File

@ -29,6 +29,7 @@ class DocumentSymbolTest extends ServerTestCase
new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestTrait'), 'TestNamespace'), new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestTrait'), 'TestNamespace'),
new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'), new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'),
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'), new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'),
new SymbolInformation('ChildClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\ChildClass'), 'TestNamespace'),
], $result); ], $result);
// @codingStandardsIgnoreEnd // @codingStandardsIgnoreEnd
} }

View File

@ -41,6 +41,7 @@ class SymbolTest extends ServerTestCase
new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestTrait'), 'TestNamespace'), new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestTrait'), 'TestNamespace'),
new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'), new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'),
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'), new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'),
new SymbolInformation('ChildClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\ChildClass'), 'TestNamespace'),
new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\whatever()'), 'TestNamespace'), new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\whatever()'), 'TestNamespace'),
// Global // Global
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TEST_CONST'), ''), new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TEST_CONST'), ''),
@ -53,6 +54,7 @@ class SymbolTest extends ServerTestCase
new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestTrait'), ''), new SymbolInformation('TestTrait', SymbolKind::CLASS_, $this->getDefinitionLocation('TestTrait'), ''),
new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestInterface'), ''), new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestInterface'), ''),
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('test_function()'), ''), new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('test_function()'), ''),
new SymbolInformation('ChildClass', SymbolKind::CLASS_, $this->getDefinitionLocation('ChildClass'), ''),
new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('whatever()'), ''), new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('whatever()'), ''),
new SymbolInformation('SecondTestNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('SecondTestNamespace'), '') new SymbolInformation('SecondTestNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('SecondTestNamespace'), '')