1
0
Fork 0

Symbol support for Microsoft/tolerant-php-parser

pull/357/head
Sara Itani 2017-03-04 20:56:01 -08:00
parent 722898f74d
commit 15eed55158
9 changed files with 241 additions and 116 deletions

View File

@ -6,7 +6,7 @@ use Microsoft\PhpParser as Tolerant;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
class ParserResourceFactory { class ParserResourceFactory {
const PARSER_KIND = ParserKind::PHP_PARSER; const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER;
public function getParser() { public function getParser() {
if (self::PARSER_KIND === ParserKind::PHP_PARSER) { if (self::PARSER_KIND === ParserKind::PHP_PARSER) {

View File

@ -3,6 +3,7 @@
namespace LanguageServer\Protocol; namespace LanguageServer\Protocol;
use PhpParser\Node; use PhpParser\Node;
use Microsoft\PhpParser as Tolerant;
/** /**
* Represents a location inside a resource, such as a line inside a text file. * 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 * Returns the location of the node
* *
* @param Node $node * @param Node | Tolerant\Node $node
* @return self * @return self
*/ */
public static function fromNode(Node $node) public static function fromNode($node)
{ {
if ($node instanceof Node) {
return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($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) public function __construct(string $uri = null, Range $range = null)

View File

@ -10,58 +10,66 @@ use Exception;
* Represents information about programming constructs like variables, classes, * Represents information about programming constructs like variables, classes,
* interfaces etc. * interfaces etc.
*/ */
class TolerantSymbolInformation extends SymbolInformation class TolerantSymbolInformation
{ {
/** /**
* Converts a Node to a SymbolInformation * Converts a Node to a SymbolInformation
* *
* @param Tolerant\Node $node * @param Tolerant\Node $node
* @param string $fqn If given, $containerName will be extracted from it * @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) public static function fromNode($node, string $fqn = null)
{ {
$parent = $node->getAttribute('parentNode'); $symbol = new SymbolInformation();
$symbol = new self; if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) {
if ($node instanceof Node\Stmt\Class_) {
$symbol->kind = SymbolKind::CLASS_; $symbol->kind = SymbolKind::CLASS_;
} else if ($node instanceof Node\Stmt\Trait_) { } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) {
$symbol->kind = SymbolKind::CLASS_; $symbol->kind = SymbolKind::CLASS_;
} else if ($node instanceof Node\Stmt\Interface_) { } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) {
$symbol->kind = SymbolKind::INTERFACE; $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; $symbol->kind = SymbolKind::NAMESPACE;
} else if ($node instanceof Node\Stmt\Function_) { } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) {
$symbol->kind = SymbolKind::FUNCTION; $symbol->kind = SymbolKind::FUNCTION;
} else if ($node instanceof Node\Stmt\ClassMethod) { } else if ($node instanceof Tolerant\Node\MethodDeclaration) {
$symbol->kind = SymbolKind::METHOD; $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; $symbol->kind = SymbolKind::PROPERTY;
} else if ($node instanceof Node\Const_) { } else if ($node instanceof Tolerant\Node\ConstElement) {
$symbol->kind = SymbolKind::CONSTANT; $symbol->kind = SymbolKind::CONSTANT;
} else if ( }
else if (
( (
($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) ($node instanceof Tolerant\Node\Expression\AssignmentExpression)
&& $node->var instanceof Node\Expr\Variable && $node->leftOperand instanceof Tolerant\Node\Expression\Variable
) )
|| $node instanceof Node\Expr\ClosureUse || $node instanceof Tolerant\Node\UseVariableName
|| $node instanceof Node\Param || $node instanceof Tolerant\Node\Parameter
) { ) {
$symbol->kind = SymbolKind::VARIABLE; $symbol->kind = SymbolKind::VARIABLE;
} else { } else {
return null; return null;
} }
if ($node instanceof Node\Name) { if ($node instanceof Node\Name) {
$symbol->name = (string)$node; $symbol->name = (string)$node;
} else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) {
$symbol->name = $node->var->name; if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) {
} else if ($node instanceof Node\Expr\ClosureUse) { $symbol->name = $node->leftOperand->getName();
$symbol->name = $node->var; } 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)) { } else if (isset($node->name)) {
$symbol->name = (string)$node->name; $symbol->name = trim((string)$node->name->getText($node->getFileContents()), "$");
} else { } else {
return null; return null;
} }
$symbol->location = Location::fromNode($node); $symbol->location = Location::fromNode($node);
if ($fqn !== null) { if ($fqn !== null) {
$parts = preg_split('/(::|->|\\\\)/', $fqn); $parts = preg_split('/(::|->|\\\\)/', $fqn);

View File

@ -6,9 +6,12 @@ namespace LanguageServer;
use LanguageServer\Protocol\TolerantSymbolInformation; use LanguageServer\Protocol\TolerantSymbolInformation;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\PrettyPrinter\Standard as PrettyPrinter; 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\Protocol\SymbolInformation;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
use Microsoft\PhpParser as Tolerant;
class TolerantDefinitionResolver implements DefinitionResolverInterface 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 * @return string
*/ */
public function getDeclarationLineFromNode($node): string public function getDeclarationLineFromNode($node): string
{ {
if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { // TODO Tolerant\Node\Statement\FunctionStaticDeclaration::class
// Properties and constants can have multiple declarations
// Use the parent node (that includes the modifiers), but only render the requested declaration // we should have a better way of determining whether something is a property or constant
$child = $node; // If part of a declaration list -> get the parent declaration
/** @var Node */ if (
$node = $node->getAttribute('parentNode'); // PropertyDeclaration // public $a, $b, $c;
$defLine = clone $node; $node instanceof Tolerant\Node\Expression\Variable &&
$defLine->props = [$child]; ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null
} else { ) {
$defLine = clone $node; $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', []); // Get the current node
if (isset($defLine->stmts)) { else {
$defLine->stmts = []; $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 * Gets the documentation string for a node, if it has one
* *
* @param Node $node * @param Tolerant\Node $node
* @return string|null * @return string|null
*/ */
public function getDocumentationFromNode($node) public function getDocumentationFromNode($node)
{ {
if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { // For properties and constants, set the node to the declaration node, rather than the individual property.
$node = $node->getAttribute('parentNode'); // 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'); // For parameters, parse the documentation to get the parameter tag.
$docBlock = $fn->getAttribute('docBlock'); if ($node instanceof Tolerant\Node\Parameter) {
$functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node);
$variableName = $node->variableName->getText($node->getFileContents());
$docBlock = $this->getDocBlock($functionLikeDeclaration);
if ($docBlock !== null) { if ($docBlock !== null) {
$tags = $docBlock->getTagsByName('param'); $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName);
foreach ($tags as $tag) { return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null;
if ($tag->getVariableName() === $node->name) {
return $tag->getDescription()->render();
} }
} }
} // for everything else, get the doc block summary corresponding to the current node.
} else { else {
$docBlock = $node->getAttribute('docBlock'); $docBlock = $this->getDocBlock($node);
if ($docBlock !== null) { if ($docBlock !== null) {
return $docBlock->getSummary(); 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 * Create a Definition for a definition node
* *
* @param Node $node * @param Tolerant\Node $node
* @param string $fqn * @param string $fqn
* @return Definition * @return Definition
*/ */
public function createDefinitionFromNode($node, string $fqn = null): Definition public function createDefinitionFromNode($node, string $fqn = null): Definition
{ {
$parent = $node->getAttribute('parentNode');
$def = new Definition; $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 = ( $def->isGlobal = (
$node instanceof Node\Stmt\ClassLike $node instanceof Tolerant\Node\Statement\InterfaceDeclaration
|| ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) || $node instanceof Tolerant\Node\Statement\ClassDeclaration
|| $node instanceof Node\Stmt\Function_ || $node instanceof Tolerant\Node\Statement\TraitDeclaration
|| $parent instanceof Node\Stmt\Const_
|| $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 = ( $def->isStatic = (
($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic())
|| ($node instanceof Node\Stmt\PropertyProperty && $parent->isStatic()) || ($node instanceof Tolerant\Node\Expression\Variable &&
($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null &&
$propertyDeclaration->isStatic())
); );
$def->fqn = $fqn; $def->fqn = $fqn;
if ($node instanceof Node\Stmt\Class_) { if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) {
$def->extends = []; $def->extends = [];
if ($node->extends) { if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) {
$def->extends[] = (string)$node->extends; $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 = []; $def->extends = [];
foreach ($node->extends as $n) { if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) {
foreach ($node->interfaceBaseClause->interfaceNameList->getChildNodes() as $n) {
$def->extends[] = (string)$n; $def->extends[] = (string)$n;
} }
} }
}
$def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); $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->declarationLine = $this->getDeclarationLineFromNode($node);
$def->documentation = $this->getDocumentationFromNode($node); $def->documentation = $this->getDocumentationFromNode($node);
return $def; return $def;
@ -796,60 +857,97 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
* Returns the fully qualified name (FQN) that is defined by a node * 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 * 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 * @return string|null
*/ */
public static function getDefinedFqn($node) public static function getDefinedFqn($node)
{ {
$parent = $node->getAttribute('parentNode'); $parent = $node->getParent();
// Anonymous classes don't count as a definition // Anonymous classes don't count as a definition
if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { // INPUT OUTPUT:
// Class, interface or trait declaration // namespace A\B;
return (string)$node->namespacedName; // class C { } A\B\C
} else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { // interface C { } A\B\C
return (string)$node; // trait C { } A\B\C
} else if ($node instanceof Node\Stmt\Function_) { 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 // Function: use functionName() as the name
return (string)$node->namespacedName . '()'; return (string)$node->getNamespacedName() . '()';
} else if ($node instanceof Node\Stmt\ClassMethod) { }
// 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 method: use ClassName->methodName() as name
$class = $node->getAttribute('parentNode'); $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class);
if (!isset($class->name)) { if (!isset($class->name)) {
// Ignore anonymous classes // Ignore anonymous classes
return null; return null;
} }
if ($node->isStatic()) { if ($node->isStatic()) {
return (string)$class->namespacedName . '::' . (string)$node->name . '()'; return (string)$class->getNamespacedName() . '::' . $node->getName() . '()';
} else { } 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 // Static Property: use ClassName::$propertyName as name
return (string)$class->namespacedName . '::$' . (string)$node->name; return (string)$classDeclaration->getNamespacedName() . '::$' . (string)$node->getName();
} else { } elseif (($name = $node->getName()) !== null) {
// Instance Property: use ClassName->propertyName as name // 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 // 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 constant: use ClassName::CONSTANT_NAME as name
$class = $parent->getAttribute('parentNode'); $classDeclaration = $constDeclaration->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class);
if (!isset($class->name) || $class->name instanceof Node\Expr) { if (!isset($classDeclaration->name)) {
return null; return null;
} }
return (string)$class->namespacedName . '::' . $node->name; return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName();
} }
} }
} }

View File

@ -22,20 +22,29 @@ use Microsoft\PhpParser as Tolerant;
class TolerantTreeAnalyzer implements TreeAnalyzerInterface { class TolerantTreeAnalyzer implements TreeAnalyzerInterface {
private $parser; private $parser;
/** @var Tolerant\Node */
private $stmts; 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->uri = $uri;
$this->parser = $parser; $this->parser = $parser;
$this->docBlockFactory = $docBlockFactory; $this->docBlockFactory = $docBlockFactory;
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
$this->content = $content; $this->content = $content;
$this->$stmts = $this->parser->parse($content); $this->stmts = $this->parser->parseSourceFile($content, $uri);
// TODO - docblock errors // TODO - docblock errors
foreach ($this->stmts->getDescendantNodes() as $node) { foreach ($this->stmts->getDescendantNodes() as $node) {
$fqn = DefinitionResolver::getDefinedFqn($node); $fqn = $definitionResolver::getDefinedFqn($node);
// Only index definitions with an FQN (no variables) // Only index definitions with an FQN (no variables)
if ($fqn === null) { if ($fqn === null) {
continue; continue;
@ -47,7 +56,8 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface {
public function getDiagnostics() { public function getDiagnostics() {
$diagnostics = []; $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); $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content);
$diagnostics[] = new Diagnostic( $diagnostics[] = new Diagnostic(

View File

@ -28,7 +28,7 @@ class TreeAnalyzer implements TreeAnalyzerInterface {
private $diagnostics; private $diagnostics;
public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri) { public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) {
$this->uri = $uri; $this->uri = $uri;
$this->parser = $parser; $this->parser = $parser;
$this->docBlockFactory = $docBlockFactory; $this->docBlockFactory = $docBlockFactory;

View File

@ -20,7 +20,7 @@ use Sabre\Uri;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser as Tolerant;
interface TreeAnalyzerInterface { interface TreeAnalyzerInterface {
public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri); public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri);
public function getDiagnostics(); public function getDiagnostics();

View File

@ -88,8 +88,8 @@ abstract class ServerTestCase extends TestCase
'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))), 'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))),
// Namespaced // Namespaced
'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 10), new Position( 2, 23))), 'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 0), new Position( 2, 24))),
'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 10), new Position( 2, 29))), '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\\ChildClass' => new Location($symbolsUri, new Range(new Position(99, 0), new Position(99, 37))),

View File

@ -29,7 +29,7 @@ class SymbolTest extends ServerTestCase
$referencesUri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php')); $referencesUri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php'));
// @codingStandardsIgnoreStart // @codingStandardsIgnoreStart
$this->assertEquals([ $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 // Namespaced
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'), new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'),
new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'), new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'),