From 15eed5515853d8f99974d3849cc97a9bcf61db8c Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sat, 4 Mar 2017 20:56:01 -0800 Subject: [PATCH] Symbol support for Microsoft/tolerant-php-parser --- src/ParserResourceFactory.php | 2 +- src/Protocol/Location.php | 15 +- src/Protocol/TolerantSymbolInformation.php | 52 +++-- src/TolerantDefinitionResolver.php | 260 ++++++++++++++------- src/TolerantTreeAnalyzer.php | 18 +- src/TreeAnalyzer.php | 2 +- src/TreeAnalyzerInterface.php | 2 +- tests/Server/ServerTestCase.php | 4 +- tests/Server/Workspace/SymbolTest.php | 2 +- 9 files changed, 241 insertions(+), 116 deletions(-) diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 6077848..8aac4a4 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,7 +6,7 @@ use Microsoft\PhpParser as Tolerant; use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::PHP_PARSER; + const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; public function getParser() { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { diff --git a/src/Protocol/Location.php b/src/Protocol/Location.php index a1d9861..6cafecd 100644 --- a/src/Protocol/Location.php +++ b/src/Protocol/Location.php @@ -3,6 +3,7 @@ namespace LanguageServer\Protocol; use PhpParser\Node; +use Microsoft\PhpParser as Tolerant; /** * Represents a location inside a resource, such as a line inside a text file. @@ -22,12 +23,20 @@ class Location /** * Returns the location of the node * - * @param Node $node + * @param Node | Tolerant\Node $node * @return self */ - public static function fromNode(Node $node) + public static function fromNode($node) { - return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($node)); + if ($node instanceof Node) { + return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($node)); + } else { + $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); + return new self($node->getUri(), new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + )); + } } public function __construct(string $uri = null, Range $range = null) diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php index df86df1..5450418 100644 --- a/src/Protocol/TolerantSymbolInformation.php +++ b/src/Protocol/TolerantSymbolInformation.php @@ -10,58 +10,66 @@ use Exception; * Represents information about programming constructs like variables, classes, * interfaces etc. */ -class TolerantSymbolInformation extends SymbolInformation +class TolerantSymbolInformation { /** * Converts a Node to a SymbolInformation * * @param Tolerant\Node $node * @param string $fqn If given, $containerName will be extracted from it - * @return self|null + * @return SymbolInformation|null */ public static function fromNode($node, string $fqn = null) { - $parent = $node->getAttribute('parentNode'); - $symbol = new self; - if ($node instanceof Node\Stmt\Class_) { + $symbol = new SymbolInformation(); + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Trait_) { + } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Interface_) { + } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $symbol->kind = SymbolKind::INTERFACE; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { + } else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { $symbol->kind = SymbolKind::NAMESPACE; - } else if ($node instanceof Node\Stmt\Function_) { + } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { $symbol->kind = SymbolKind::FUNCTION; - } else if ($node instanceof Node\Stmt\ClassMethod) { + } else if ($node instanceof Tolerant\Node\MethodDeclaration) { $symbol->kind = SymbolKind::METHOD; - } else if ($node instanceof Node\Stmt\PropertyProperty) { + } else if ($node instanceof Tolerant\Node\Expression\Variable && $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class) !== null) { $symbol->kind = SymbolKind::PROPERTY; - } else if ($node instanceof Node\Const_) { + } else if ($node instanceof Tolerant\Node\ConstElement) { $symbol->kind = SymbolKind::CONSTANT; - } else if ( + } + + else if ( ( - ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) - && $node->var instanceof Node\Expr\Variable + ($node instanceof Tolerant\Node\Expression\AssignmentExpression) + && $node->leftOperand instanceof Tolerant\Node\Expression\Variable ) - || $node instanceof Node\Expr\ClosureUse - || $node instanceof Node\Param + || $node instanceof Tolerant\Node\UseVariableName + || $node instanceof Tolerant\Node\Parameter ) { $symbol->kind = SymbolKind::VARIABLE; } else { return null; } + if ($node instanceof Node\Name) { $symbol->name = (string)$node; - } else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { - $symbol->name = $node->var->name; - } else if ($node instanceof Node\Expr\ClosureUse) { - $symbol->name = $node->var; + } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { + $symbol->name = $node->leftOperand->getName(); + } elseif ($node->leftOperand instanceof Tolerant\Token) { + $symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$"); + } + + } else if ($node instanceof Tolerant\Node\UseVariableName) { + $symbol->name = $node->getName(); } else if (isset($node->name)) { - $symbol->name = (string)$node->name; + $symbol->name = trim((string)$node->name->getText($node->getFileContents()), "$"); } else { return null; } + $symbol->location = Location::fromNode($node); if ($fqn !== null) { $parts = preg_split('/(::|->|\\\\)/', $fqn); diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 65f1f2f..6b0ba78 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -6,9 +6,12 @@ namespace LanguageServer; use LanguageServer\Protocol\TolerantSymbolInformation; use PhpParser\Node; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; -use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; +use phpDocumentor\Reflection\{ + DocBlockFactory, Types, Type, Fqsen, TypeResolver +}; use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; +use Microsoft\PhpParser as Tolerant; class TolerantDefinitionResolver implements DefinitionResolverInterface { @@ -38,99 +41,157 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface } /** - * Builds the declaration line for a given node + * Builds the declaration line for a given node. * - * @param Node $node + * + * @param Tolerant\Node $node * @return string */ public function getDeclarationLineFromNode($node): string { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - // Properties and constants can have multiple declarations - // Use the parent node (that includes the modifiers), but only render the requested declaration - $child = $node; - /** @var Node */ - $node = $node->getAttribute('parentNode'); - $defLine = clone $node; - $defLine->props = [$child]; - } else { - $defLine = clone $node; + // TODO Tolerant\Node\Statement\FunctionStaticDeclaration::class + + // we should have a better way of determining whether something is a property or constant + // If part of a declaration list -> get the parent declaration + if ( + // PropertyDeclaration // public $a, $b, $c; + $node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null + ) { + $defLine = $propertyDeclaration->getText(); + $defLineStart = $propertyDeclaration->getStart(); + + $defLine = \substr_replace( + $defLine, + $node->getFullText(), + $propertyDeclaration->propertyElements->getFullStart() - $defLineStart, + $propertyDeclaration->propertyElements->getWidth() + ); + } elseif ( + // ClassConstDeclaration or ConstDeclaration // const A = 1, B = 2; + $node instanceof Tolerant\Node\ConstElement && + ($constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class)) + ) { + $defLine = $constDeclaration->getText(); + $defLineStart = $constDeclaration->getStart(); + + $defLine = \substr_replace( + $defLine, + $node->getFullText(), + $constDeclaration->constElements->getFullStart() - $defLineStart, + $constDeclaration->constElements->getWidth() + ); } - // Don't include the docblock in the declaration string - $defLine->setAttribute('comments', []); - if (isset($defLine->stmts)) { - $defLine->stmts = []; + + // Get the current node + else { + $defLine = $node->getText(); } - $defText = $this->prettyPrinter->prettyPrint([$defLine]); - return strstr($defText, "\n", true) ?: $defText; + + $defLine = \strtok($defLine, "\n"); + + return $defLine; } /** * Gets the documentation string for a node, if it has one * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public function getDocumentationFromNode($node) { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - $node = $node->getAttribute('parentNode'); + // For properties and constants, set the node to the declaration node, rather than the individual property. + // This is because they get defined as part of a list. + $constOrPropertyDeclaration = $node->getFirstAncestor( + Tolerant\Node\PropertyDeclaration::class, + Tolerant\Node\Statement\ConstDeclaration::class, + Tolerant\Node\ClassConstDeclaration::class + ); + if ($constOrPropertyDeclaration !== null) { + $node = $constOrPropertyDeclaration; } - if ($node instanceof Node\Param) { - $fn = $node->getAttribute('parentNode'); - $docBlock = $fn->getAttribute('docBlock'); + + // For parameters, parse the documentation to get the parameter tag. + if ($node instanceof Tolerant\Node\Parameter) { + $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); + $variableName = $node->variableName->getText($node->getFileContents()); + $docBlock = $this->getDocBlock($functionLikeDeclaration); + if ($docBlock !== null) { - $tags = $docBlock->getTagsByName('param'); - foreach ($tags as $tag) { - if ($tag->getVariableName() === $node->name) { - return $tag->getDescription()->render(); - } - } + $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); + return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; + } - } else { - $docBlock = $node->getAttribute('docBlock'); + } + // for everything else, get the doc block summary corresponding to the current node. + else { + $docBlock = $this->getDocBlock($node); if ($docBlock !== null) { return $docBlock->getSummary(); } } } + function getDocBlock(Tolerant\Node $node) { + // TODO context information + static $docBlockFactory; + $docBlockFactory = $docBlockFactory ?? DocBlockFactory::createInstance(); + $docCommentText = $node->getDocCommentText(); + return $docCommentText !== null ? $docBlockFactory->create($docCommentText) : null; + } + /** * Create a Definition for a definition node * - * @param Node $node + * @param Tolerant\Node $node * @param string $fqn * @return Definition */ public function createDefinitionFromNode($node, string $fqn = null): Definition { - $parent = $node->getAttribute('parentNode'); $def = new Definition; - $def->canBeInstantiated = $node instanceof Node\Stmt\Class_; + + // this determines whether the suggestion will show after "new" + $def->isClass = $node instanceof Tolerant\Node\Statement\ClassDeclaration; + $def->isGlobal = ( - $node instanceof Node\Stmt\ClassLike - || ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) - || $node instanceof Node\Stmt\Function_ - || $parent instanceof Node\Stmt\Const_ + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration + || $node instanceof Tolerant\Node\Statement\ClassDeclaration + || $node instanceof Tolerant\Node\Statement\TraitDeclaration + + || $node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null + + || $node instanceof Tolerant\Node\Statement\FunctionDeclaration + + || $node instanceof Tolerant\Node\Statement\ConstDeclaration + || $node instanceof Tolerant\Node\ClassConstDeclaration ); + $def->isStatic = ( - ($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) - || ($node instanceof Node\Stmt\PropertyProperty && $parent->isStatic()) + ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) + || ($node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && + $propertyDeclaration->isStatic()) ); $def->fqn = $fqn; - if ($node instanceof Node\Stmt\Class_) { + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $def->extends = []; - if ($node->extends) { - $def->extends[] = (string)$node->extends; + if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { + $def->extends[] = (string)$node->classBaseClause->baseClass; } - } else if ($node instanceof Node\Stmt\Interface_) { + // TODO what about class interfaces + } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $def->extends = []; - foreach ($node->extends as $n) { - $def->extends[] = (string)$n; + if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { + foreach ($node->interfaceBaseClause->interfaceNameList->getChildNodes() as $n) { + $def->extends[] = (string)$n; + } } } $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); - $def->type = $this->getTypeFromNode($node); +// $def->type = $this->getTypeFromNode($node); //TODO + $def->type = new Types\Mixed; $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); return $def; @@ -796,60 +857,97 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface * Returns the fully qualified name (FQN) that is defined by a node * Returns null if the node does not declare any symbol that can be referenced by an FQN * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public static function getDefinedFqn($node) { - $parent = $node->getAttribute('parentNode'); + $parent = $node->getParent(); // Anonymous classes don't count as a definition - if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { - // Class, interface or trait declaration - return (string)$node->namespacedName; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { - return (string)$node; - } else if ($node instanceof Node\Stmt\Function_) { + // INPUT OUTPUT: + // namespace A\B; + // class C { } A\B\C + // interface C { } A\B\C + // trait C { } A\B\C + if ( + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration + ) { + return (string) $node->getNamespacedName(); + } + + // INPUT OUTPUT: + // namespace A\B; A\B + else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { + return (string) $node->name; + } + // INPUT OUTPUT: + // namespace A\B; + // function a(); A\B\a(); + else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name - return (string)$node->namespacedName . '()'; - } else if ($node instanceof Node\Stmt\ClassMethod) { + return (string)$node->getNamespacedName() . '()'; + } + // INPUT OUTPUT + // namespace A\B; + // class C { + // function a () {} A\B\C::a() + // static function b() {} A\B\C->b() + // } + else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name - $class = $node->getAttribute('parentNode'); + $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); if (!isset($class->name)) { // Ignore anonymous classes return null; } if ($node->isStatic()) { - return (string)$class->namespacedName . '::' . (string)$node->name . '()'; + return (string)$class->getNamespacedName() . '::' . $node->getName() . '()'; } else { - return (string)$class->namespacedName . '->' . (string)$node->name . '()'; + return (string)$class->getNamespacedName() . '->' . $node->getName() . '()'; } - } else if ($node instanceof Node\Stmt\PropertyProperty) { - $property = $node->getAttribute('parentNode'); - $class = $property->getAttribute('parentNode'); - if (!isset($class->name)) { - // Ignore anonymous classes - return null; - } - if ($property->isStatic()) { + } + + // INPUT OUTPUT + // namespace A\B; + // class C { + // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b + // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b + // } + else if ( + $node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && + ($classDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class)) !== null) + { + if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name - return (string)$class->namespacedName . '::$' . (string)$node->name; - } else { + return (string)$classDeclaration->getNamespacedName() . '::$' . (string)$node->getName(); + } elseif (($name = $node->getName()) !== null) { // Instance Property: use ClassName->propertyName as name - return (string)$class->namespacedName . '->' . (string)$node->name; + return (string)$classDeclaration->getNamespacedName() . '->' . $name; } - } else if ($node instanceof Node\Const_) { - $parent = $node->getAttribute('parentNode'); - if ($parent instanceof Node\Stmt\Const_) { + } + + // INPUT OUTPUT + // namespace A\B; + // const FOO = 5; A\B\FOO + // class C { + // const $a, $b = 4 A\B\C::$a(), A\B\C::$b + // } + else if ($node instanceof Tolerant\Node\ConstElement) { + $constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class); + if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name - return (string)$node->namespacedName; + return (string)$node->getNamespacedName(); } - if ($parent instanceof Node\Stmt\ClassConst) { + if ($constDeclaration instanceof Tolerant\Node\ClassConstDeclaration) { // Class constant: use ClassName::CONSTANT_NAME as name - $class = $parent->getAttribute('parentNode'); - if (!isset($class->name) || $class->name instanceof Node\Expr) { + $classDeclaration = $constDeclaration->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if (!isset($classDeclaration->name)) { return null; } - return (string)$class->namespacedName . '::' . $node->name; + return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); } } } diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 095281d..1d94d09 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -22,20 +22,29 @@ use Microsoft\PhpParser as Tolerant; class TolerantTreeAnalyzer implements TreeAnalyzerInterface { private $parser; + /** @var Tolerant\Node */ private $stmts; - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri) { + /** + * TolerantTreeAnalyzer constructor. + * @param Tolerant\Parser $parser + * @param $content + * @param $docBlockFactory + * @param TolerantDefinitionResolver $definitionResolver + * @param $uri + */ + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; $this->content = $content; - $this->$stmts = $this->parser->parse($content); + $this->stmts = $this->parser->parseSourceFile($content, $uri); // TODO - docblock errors foreach ($this->stmts->getDescendantNodes() as $node) { - $fqn = DefinitionResolver::getDefinedFqn($node); + $fqn = $definitionResolver::getDefinedFqn($node); // Only index definitions with an FQN (no variables) if ($fqn === null) { continue; @@ -47,7 +56,8 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface { public function getDiagnostics() { $diagnostics = []; - foreach (Tolerant\DiagnosticsProvider::getDiagnostics($tolerantStmts) as $_error) { + $content = $this->stmts->getFileContents(); + foreach (Tolerant\DiagnosticsProvider::getDiagnostics($this->stmts) as $_error) { $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); $diagnostics[] = new Diagnostic( diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index d4f4d5e..ddb78ab 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -28,7 +28,7 @@ class TreeAnalyzer implements TreeAnalyzerInterface { private $diagnostics; - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri) { + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; diff --git a/src/TreeAnalyzerInterface.php b/src/TreeAnalyzerInterface.php index 695ac41..a534a72 100644 --- a/src/TreeAnalyzerInterface.php +++ b/src/TreeAnalyzerInterface.php @@ -20,7 +20,7 @@ use Sabre\Uri; use Microsoft\PhpParser as Tolerant; interface TreeAnalyzerInterface { - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri); + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri); public function getDiagnostics(); diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 0dcac39..a553dde 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -88,8 +88,8 @@ abstract class ServerTestCase extends TestCase 'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))), // Namespaced - 'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 10), new Position( 2, 23))), - 'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 10), new Position( 2, 29))), + 'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 0), new Position( 2, 24))), + '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\\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))), diff --git a/tests/Server/Workspace/SymbolTest.php b/tests/Server/Workspace/SymbolTest.php index d3d13b6..9fecceb 100644 --- a/tests/Server/Workspace/SymbolTest.php +++ b/tests/Server/Workspace/SymbolTest.php @@ -29,7 +29,7 @@ class SymbolTest extends ServerTestCase $referencesUri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php')); // @codingStandardsIgnoreStart $this->assertEquals([ - new SymbolInformation('TestNamespace', SymbolKind::NAMESPACE, new Location($referencesUri, new Range(new Position(2, 10), new Position(2, 23))), ''), + new SymbolInformation('TestNamespace', SymbolKind::NAMESPACE, new Location($referencesUri, new Range(new Position(2, 0), new Position(2, 24))), ''), // Namespaced new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'), new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'),