1
0
Fork 0

Remove "Tolerant" alias

- Now unnecessary
-  Makes type annotations more readable
pull/357/head
Rob Lourens 2017-05-24 11:26:53 -07:00
parent 836cdb77c0
commit 3dfe505727
17 changed files with 348 additions and 337 deletions

View File

@ -8,7 +8,7 @@ use LanguageServer\Index\Index;
use LanguageServer\ParserKind; use LanguageServer\ParserKind;
use LanguageServer\PhpDocument; use LanguageServer\PhpDocument;
use LanguageServer\DefinitionResolver; use LanguageServer\DefinitionResolver;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
@ -58,7 +58,7 @@ foreach($frameworks as $framework) {
$definitions = []; $definitions = [];
$definitionResolver = new DefinitionResolver($index); $definitionResolver = new DefinitionResolver($index);
$parser = new Tolerant\Parser(); $parser = new PhpParser\Parser();
try { try {
$document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);

View File

@ -13,7 +13,8 @@ use LanguageServer\Protocol\{
CompletionItemKind CompletionItemKind
}; };
use function LanguageServer\{strStartsWith}; use function LanguageServer\{strStartsWith};
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
class CompletionProvider class CompletionProvider
{ {
@ -127,7 +128,7 @@ class CompletionProvider
$offset = $node === null ? -1 : $pos->toOffset($node->getFileContents()); $offset = $node === null ? -1 : $pos->toOffset($node->getFileContents());
if ($node !== null && $offset > $node->getEndPosition() && if ($node !== null && $offset > $node->getEndPosition() &&
$node->parent->getLastChild() instanceof Tolerant\MissingToken $node->parent->getLastChild() instanceof PhpParser\MissingToken
) { ) {
$node = $node->parent; $node = $node->parent;
} }
@ -135,14 +136,14 @@ class CompletionProvider
$list = new CompletionList; $list = new CompletionList;
$list->isIncomplete = true; $list->isIncomplete = true;
if ($node instanceof Tolerant\Node\Expression\Variable && if ($node instanceof Node\Expression\Variable &&
$node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression && $node->parent instanceof Node\Expression\ObjectCreationExpression &&
$node->name instanceof Tolerant\MissingToken $node->name instanceof PhpParser\MissingToken
) { ) {
$node = $node->parent; $node = $node->parent;
} }
if ($node === null || $node instanceof Tolerant\Node\Statement\InlineHtml || $pos == new Position(0, 0)) { if ($node === null || $node instanceof Node\Statement\InlineHtml || $pos == new Position(0, 0)) {
$item = new CompletionItem('<?php', CompletionItemKind::KEYWORD); $item = new CompletionItem('<?php', CompletionItemKind::KEYWORD);
$item->textEdit = new TextEdit( $item->textEdit = new TextEdit(
new Range($pos, $pos), new Range($pos, $pos),
@ -152,9 +153,9 @@ class CompletionProvider
} }
// VARIABLES // VARIABLES
elseif ( elseif (
$node instanceof Tolerant\Node\Expression\Variable && $node instanceof Node\Expression\Variable &&
!( !(
$node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression &&
$node->parent->memberName === $node) $node->parent->memberName === $node)
) { ) {
// Find variables, parameters and use statements in the scope // Find variables, parameters and use statements in the scope
@ -176,7 +177,7 @@ class CompletionProvider
// MEMBER ACCESS EXPRESSIONS // MEMBER ACCESS EXPRESSIONS
// $a->c# // $a->c#
// $a-># // $a->#
elseif ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { elseif ($node instanceof Node\Expression\MemberAccessExpression) {
$prefixes = FqnUtilities::getFqnsFromType( $prefixes = FqnUtilities::getFqnsFromType(
$this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression)
); );
@ -204,8 +205,8 @@ class CompletionProvider
// A\B\C::foo# // A\B\C::foo#
// TODO: $a::# // TODO: $a::#
elseif ( elseif (
($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression ||
($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression
) { ) {
$prefixes = FqnUtilities::getFqnsFromType( $prefixes = FqnUtilities::getFqnsFromType(
$classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier) $classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier)
@ -227,13 +228,13 @@ class CompletionProvider
} }
} }
} elseif (ParserHelpers::isConstantFetch($node) || } elseif (ParserHelpers::isConstantFetch($node) ||
($creation = $node->parent) instanceof Tolerant\Node\Expression\ObjectCreationExpression || ($creation = $node->parent) instanceof Node\Expression\ObjectCreationExpression ||
(($creation = $node) instanceof Tolerant\Node\Expression\ObjectCreationExpression)) { (($creation = $node) instanceof Node\Expression\ObjectCreationExpression)) {
$class = isset($creation) ? $creation->classTypeDesignator : $node; $class = isset($creation) ? $creation->classTypeDesignator : $node;
$prefix = $class instanceof Tolerant\Node\QualifiedName $prefix = $class instanceof Node\QualifiedName
? (string)Tolerant\ResolvedName::buildName($class->nameParts, $class->getFileContents()) ? (string)PhpParser\ResolvedName::buildName($class->nameParts, $class->getFileContents())
: $class->getText($node->getFileContents()); : $class->getText($node->getFileContents());
$namespaceDefinition = $node->getNamespaceDefinition(); $namespaceDefinition = $node->getNamespaceDefinition();
@ -248,11 +249,11 @@ class CompletionProvider
$fqnContainsPrefix = empty($prefix) || strpos($fqn, $prefix) !== false; $fqnContainsPrefix = empty($prefix) || strpos($fqn, $prefix) !== false;
if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && $fqnContainsPrefix) { if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && $fqnContainsPrefix) {
if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) {
$namespacePrefix = (string)Tolerant\ResolvedName::buildName($namespaceDefinition->name->nameParts, $node->getFileContents()); $namespacePrefix = (string)PhpParser\ResolvedName::buildName($namespaceDefinition->name->nameParts, $node->getFileContents());
$isAliased = false; $isAliased = false;
$isNotFullyQualified = !($class instanceof Tolerant\Node\QualifiedName) || !$class->isFullyQualifiedName(); $isNotFullyQualified = !($class instanceof Node\QualifiedName) || !$class->isFullyQualifiedName();
if ($isNotFullyQualified) { if ($isNotFullyQualified) {
foreach ($namespaceImportTable as $alias => $name) { foreach ($namespaceImportTable as $alias => $name) {
if (strStartsWith($fqn, $name)) { if (strStartsWith($fqn, $name)) {
@ -297,7 +298,7 @@ class CompletionProvider
} }
} }
} elseif (ParserHelpers::isConstantFetch($node)) { } elseif (ParserHelpers::isConstantFetch($node)) {
$prefix = (string) ($node->getResolvedName() ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); $prefix = (string) ($node->getResolvedName() ?? PhpParser\ResolvedName::buildName($node->nameParts, $node->getFileContents()));
foreach (self::KEYWORDS as $keyword) { foreach (self::KEYWORDS as $keyword) {
$item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD);
$item->insertText = $keyword . ' '; $item->insertText = $keyword . ' ';
@ -333,11 +334,11 @@ class CompletionProvider
* 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
* of that variable * of that variable
* *
* @param Tolerant\Node $node * @param Node $node
* @param string $namePrefix Prefix to filter * @param string $namePrefix Prefix to filter
* @return array <Tolerant\Node\Expr\Variable|Tolerant\Node\Param|Tolerant\Node\Expr\ClosureUse> * @return array <Node\Expr\Variable|Node\Param|Node\Expr\ClosureUse>
*/ */
private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix = ''): array private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): array
{ {
$vars = []; $vars = [];
@ -375,7 +376,7 @@ class CompletionProvider
} }
} }
if ($level instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && $level->anonymousFunctionUseClause !== null) { if ($level instanceof Node\Expression\AnonymousFunctionCreationExpression && $level->anonymousFunctionUseClause !== null) {
foreach ($level->anonymousFunctionUseClause->useVariableNameList->getValues() as $use) { foreach ($level->anonymousFunctionUseClause->useVariableNameList->getValues() as $use) {
$useName = $use->getName(); $useName = $use->getName();
if (empty($namePrefix) || strpos($useName, $namePrefix) !== false) { if (empty($namePrefix) || strpos($useName, $namePrefix) !== false) {
@ -393,24 +394,24 @@ class CompletionProvider
* *
* @param Node $node * @param Node $node
* @param string $namePrefix Prefix to filter * @param string $namePrefix Prefix to filter
* @return Tolerant\Node\Expression\Variable[] * @return Node\Expression\Variable[]
*/ */
private function findVariableDefinitionsInNode(Tolerant\Node $node, string $namePrefix = ''): array private function findVariableDefinitionsInNode(Node $node, string $namePrefix = ''): array
{ {
$vars = []; $vars = [];
// If the child node is a variable assignment, save it // If the child node is a variable assignment, save it
$isAssignmentToVariable = function ($node) use ($namePrefix) { $isAssignmentToVariable = function ($node) use ($namePrefix) {
return $node instanceof Tolerant\Node\Expression\AssignmentExpression return $node instanceof Node\Expression\AssignmentExpression
&& $node->leftOperand instanceof Tolerant\Node\Expression\Variable && $node->leftOperand instanceof Node\Expression\Variable
&& (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false);
}; };
$isNotFunctionLike = function($node) { $isNotFunctionLike = function($node) {
return !( return !(
ParserHelpers::isFunctionLike($node) || ParserHelpers::isFunctionLike($node) ||
$node instanceof Tolerant\Node\Statement\ClassDeclaration || $node instanceof Node\Statement\ClassDeclaration ||
$node instanceof Tolerant\Node\Statement\InterfaceDeclaration || $node instanceof Node\Statement\InterfaceDeclaration ||
$node instanceof Tolerant\Node\Statement\TraitDeclaration $node instanceof Node\Statement\TraitDeclaration
); );
}; };

View File

@ -10,7 +10,7 @@ use phpDocumentor\Reflection\DocBlockFactory;
use Webmozart\PathUtil\Path; use Webmozart\PathUtil\Path;
use Sabre\Uri; use Sabre\Uri;
use function Sabre\Event\coroutine; use function Sabre\Event\coroutine;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) { foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
if (file_exists($file)) { if (file_exists($file)) {
@ -30,7 +30,7 @@ class ComposerScripts
$finder = new FileSystemFilesFinder; $finder = new FileSystemFilesFinder;
$contentRetriever = new FileSystemContentRetriever; $contentRetriever = new FileSystemContentRetriever;
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$parser = new Tolerant\Parser(); $parser = new PhpParser\Parser();
$definitionResolver = new DefinitionResolver($index); $definitionResolver = new DefinitionResolver($index);
$stubsLocation = null; $stubsLocation = null;

View File

@ -5,7 +5,8 @@ namespace LanguageServer;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Protocol\SymbolInformation;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
use phpDocumentor\Reflection\{ use phpDocumentor\Reflection\{
DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types
}; };
@ -46,7 +47,7 @@ class DefinitionResolver
/** /**
* Builds the declaration line for a given node. Declarations with multiple lines are trimmed. * Builds the declaration line for a given node. Declarations with multiple lines are trimmed.
* *
* @param Tolerant\Node $node * @param Node $node
* @return string * @return string
*/ */
public function getDeclarationLineFromNode($node): string public function getDeclarationLineFromNode($node): string
@ -82,13 +83,13 @@ class DefinitionResolver
/** /**
* Gets the documentation string for a node, if it has one * Gets the documentation string for a node, if it has one
* *
* @param Tolerant\Node $node * @param Node $node
* @return string|null * @return string|null
*/ */
public function getDocumentationFromNode($node) public function getDocumentationFromNode($node)
{ {
// Any NamespaceDefinition comments likely apply to the file, not the declaration itself. // Any NamespaceDefinition comments likely apply to the file, not the declaration itself.
if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { if ($node instanceof Node\Statement\NamespaceDefinition) {
return null; return null;
} }
@ -100,7 +101,7 @@ class DefinitionResolver
} }
// For parameters, parse the function-like declaration to get documentation for a parameter // For parameters, parse the function-like declaration to get documentation for a parameter
if ($node instanceof Tolerant\Node\Parameter) { if ($node instanceof Node\Parameter) {
$variableName = $node->getName(); $variableName = $node->getName();
$functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node);
@ -129,10 +130,10 @@ class DefinitionResolver
/** /**
* Gets Doc Block with resolved names for a Node * Gets Doc Block with resolved names for a Node
* *
* @param Tolerant\Node $node * @param Node $node
* @return DocBlock | null * @return DocBlock | null
*/ */
private function getDocBlock(Tolerant\Node $node) private function getDocBlock(Node $node)
{ {
// TODO make more efficient (caching, ensure import table is in right format to begin with) // TODO make more efficient (caching, ensure import table is in right format to begin with)
$docCommentText = $node->getDocCommentText(); $docCommentText = $node->getDocCommentText();
@ -161,7 +162,7 @@ class DefinitionResolver
/** /**
* Create a Definition for a definition node * Create a Definition for a definition node
* *
* @param Tolerant\Node $node * @param Node $node
* @param string $fqn * @param string $fqn
* @return Definition * @return Definition
*/ */
@ -171,30 +172,30 @@ class DefinitionResolver
$def->fqn = $fqn; $def->fqn = $fqn;
// Determines whether the suggestion will show after "new" // Determines whether the suggestion will show after "new"
$def->canBeInstantiated = $node instanceof Tolerant\Node\Statement\ClassDeclaration; $def->canBeInstantiated = $node instanceof Node\Statement\ClassDeclaration;
// Interfaces, classes, traits, namespaces, functions, and global const elements // Interfaces, classes, traits, namespaces, functions, and global const elements
$def->isGlobal = ( $def->isGlobal = (
$node instanceof Tolerant\Node\Statement\InterfaceDeclaration || $node instanceof Node\Statement\InterfaceDeclaration ||
$node instanceof Tolerant\Node\Statement\ClassDeclaration || $node instanceof Node\Statement\ClassDeclaration ||
$node instanceof Tolerant\Node\Statement\TraitDeclaration || $node instanceof Node\Statement\TraitDeclaration ||
($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null) || ($node instanceof Node\Statement\NamespaceDefinition && $node->name !== null) ||
$node instanceof Tolerant\Node\Statement\FunctionDeclaration || $node instanceof Node\Statement\FunctionDeclaration ||
($node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration) ($node instanceof Node\ConstElement && $node->parent->parent instanceof Node\Statement\ConstDeclaration)
); );
// Static methods and static property declarations // Static methods and static property declarations
$def->isStatic = ( $def->isStatic = (
($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) || ($node instanceof Node\MethodDeclaration && $node->isStatic()) ||
(($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null (($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null
&& $propertyDeclaration->isStatic()) && $propertyDeclaration->isStatic())
); );
if ($node instanceof Tolerant\Node\Statement\ClassDeclaration && if ($node instanceof Node\Statement\ClassDeclaration &&
// TODO - this should be bette rrpreented in the parser API // TODO - this should be bette rrpreented in the parser API
$node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null)
{ {
@ -202,7 +203,7 @@ class DefinitionResolver
// TODO - why is this represented as an array? // TODO - why is this represented as an array?
// TODO interface implementations. // TODO interface implementations.
} elseif ( } elseif (
$node instanceof Tolerant\Node\Statement\InterfaceDeclaration && $node instanceof Node\Statement\InterfaceDeclaration &&
// TODO - this should be better represented in the parser API // TODO - this should be better represented in the parser API
$node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null
) { ) {
@ -226,7 +227,7 @@ class DefinitionResolver
/** /**
* Given any node, returns the Definition object of the symbol that is referenced * Given any node, returns the Definition object of the symbol that is referenced
* *
* @param Tolerant\Node $node Any reference node * @param Node $node Any reference node
* @return Definition|null * @return Definition|null
*/ */
public function resolveReferenceNodeToDefinition($node) public function resolveReferenceNodeToDefinition($node)
@ -235,8 +236,8 @@ class DefinitionResolver
// Variables are not indexed globally, as they stay in the file scope anyway. // Variables are not indexed globally, as they stay in the file scope anyway.
// Ignore variable nodes that are part of ScopedPropertyAccessExpression, // Ignore variable nodes that are part of ScopedPropertyAccessExpression,
// as the scoped property access expression node is handled separately. // as the scoped property access expression node is handled separately.
if ($node instanceof Tolerant\Node\Expression\Variable && if ($node instanceof Node\Expression\Variable &&
!($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) !($parent instanceof Node\Expression\ScopedPropertyAccessExpression))
{ {
// Resolve $this to the containing class definition. // Resolve $this to the containing class definition.
if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) {
@ -259,7 +260,7 @@ class DefinitionResolver
// If the node is a function or constant, it could be namespaced, but PHP falls back to global // If the node is a function or constant, it could be namespaced, but PHP falls back to global
// http://php.net/manual/en/language.namespaces.fallback.php // http://php.net/manual/en/language.namespaces.fallback.php
// TODO - verify that this is not a method // TODO - verify that this is not a method
$globalFallback = ParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; $globalFallback = ParserHelpers::isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression;
// Return the Definition object from the index index // Return the Definition object from the index index
return $this->index->getDefinition($fqn, $globalFallback); return $this->index->getDefinition($fqn, $globalFallback);
} }
@ -273,11 +274,11 @@ class DefinitionResolver
*/ */
public function resolveReferenceNodeToFqn($node) { public function resolveReferenceNodeToFqn($node) {
// TODO all name tokens should be a part of a node // TODO all name tokens should be a part of a node
if ($node instanceof Tolerant\Node\QualifiedName) { if ($node instanceof Node\QualifiedName) {
return $this->resolveQualifiedNameNodeToFqn($node); return $this->resolveQualifiedNameNodeToFqn($node);
} }
else if ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { else if ($node instanceof Node\Expression\MemberAccessExpression) {
return $this->resolveMemberAccessExpressionNodeToFqn($node); return $this->resolveMemberAccessExpressionNodeToFqn($node);
} }
else if (ParserHelpers::isConstantFetch($node)) { else if (ParserHelpers::isConstantFetch($node)) {
@ -285,13 +286,13 @@ class DefinitionResolver
} }
else if ( else if (
// A\B::C - constant access expression // A\B::C - constant access expression
$node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression $node instanceof Node\Expression\ScopedPropertyAccessExpression
&& !($node->memberName instanceof Tolerant\Node\Expression\Variable) && !($node->memberName instanceof Node\Expression\Variable)
) { ) {
return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node);
} else if ( } else if (
// A\B::$c - static property access expression // A\B::$c - static property access expression
$node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression
) { ) {
return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node->parent); return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node->parent);
} }
@ -299,36 +300,36 @@ class DefinitionResolver
return null; return null;
} }
private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { private function resolveQualifiedNameNodeToFqn(Node\QualifiedName $node) {
$parent = $node->parent; $parent = $node->parent;
if ($parent instanceof Tolerant\Node\TraitSelectOrAliasClause) { if ($parent instanceof Node\TraitSelectOrAliasClause) {
return null; return null;
} }
// Add use clause references // Add use clause references
if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause if (($useClause = $parent) instanceof Node\NamespaceUseGroupClause
|| $useClause instanceof Tolerant\Node\NamespaceUseClause || $useClause instanceof Node\NamespaceUseClause
) { ) {
$contents = $node->getFileContents(); $contents = $node->getFileContents();
if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { if ($useClause instanceof Node\NamespaceUseGroupClause) {
$prefix = $useClause->parent->parent->namespaceName; $prefix = $useClause->parent->parent->namespaceName;
if ($prefix === null) { if ($prefix === null) {
return null; return null;
} }
$name = Tolerant\ResolvedName::buildName($prefix->nameParts, $contents); $name = PhpParser\ResolvedName::buildName($prefix->nameParts, $contents);
$name->addNameParts($node->nameParts, $contents); $name->addNameParts($node->nameParts, $contents);
$name = (string)$name; $name = (string)$name;
if ($useClause->functionOrConst === null) { if ($useClause->functionOrConst === null) {
$useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); $useClause = $node->getFirstAncestor(Node\Statement\NamespaceUseDeclaration::class);
if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === PhpParser\TokenKind::FunctionKeyword) {
$name .= '()'; $name .= '()';
} }
} }
return $name; return $name;
} else { } else {
$name = (string) Tolerant\ResolvedName::buildName($node->nameParts, $contents); $name = (string) PhpParser\ResolvedName::buildName($node->nameParts, $contents);
if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === PhpParser\TokenKind::FunctionKeyword) {
$name .= '()'; $name .= '()';
} }
} }
@ -339,14 +340,14 @@ class DefinitionResolver
// For extends, implements, type hints and classes of classes of static calls use the name directly // For extends, implements, type hints and classes of classes of static calls use the name directly
$name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName());
if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($node->parent instanceof Node\Expression\CallExpression) {
$name .= '()'; $name .= '()';
} }
return $name; return $name;
} }
private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression\MemberAccessExpression $access) { private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAccessExpression $access) {
if ($access->memberName instanceof Tolerant\Node\Expression) { if ($access->memberName instanceof Node\Expression) {
// Cannot get definition if right-hand side is expression // Cannot get definition if right-hand side is expression
return null; return null;
} }
@ -382,7 +383,7 @@ class DefinitionResolver
$classFqn = substr((string)$varType->getFqsen(), 1); $classFqn = substr((string)$varType->getFqsen(), 1);
} }
$memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($access->getFileContents())); $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($access->getFileContents()));
if ($access->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($access->parent instanceof Node\Expression\CallExpression) {
$memberSuffix .= '()'; $memberSuffix .= '()';
} }
@ -412,14 +413,14 @@ class DefinitionResolver
return $classFqn . $memberSuffix; return $classFqn . $memberSuffix;
} }
private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { private function resolveScopedPropertyAccessExpressionNodeToFqn(Node\Expression\ScopedPropertyAccessExpression $scoped) {
if ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\Expression\Variable) { if ($scoped->scopeResolutionQualifier instanceof Node\Expression\Variable) {
$varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier);
if ($varType === null) { if ($varType === null) {
return null; return null;
} }
$className = substr((string)$varType->getFqsen(), 1); $className = substr((string)$varType->getFqsen(), 1);
} elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { } elseif ($scoped->scopeResolutionQualifier instanceof Node\QualifiedName) {
$className = (string)$scoped->scopeResolutionQualifier->getResolvedName(); $className = (string)$scoped->scopeResolutionQualifier->getResolvedName();
} else { } else {
return null; return null;
@ -427,7 +428,7 @@ class DefinitionResolver
if ($className === 'self' || $className === 'static' || $className === 'parent') { if ($className === 'self' || $className === 'static' || $className === 'parent') {
// self and static are resolved to the containing class // self and static are resolved to the containing class
$classNode = $scoped->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); $classNode = $scoped->getFirstAncestor(Node\Statement\ClassDeclaration::class);
if ($classNode === null) { if ($classNode === null) {
return null; return null;
} }
@ -440,11 +441,11 @@ class DefinitionResolver
} else { } else {
$className = (string)$classNode->getNamespacedName(); $className = (string)$classNode->getNamespacedName();
} }
} elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { } elseif ($scoped->scopeResolutionQualifier instanceof Node\QualifiedName) {
$className = $scoped->scopeResolutionQualifier->getResolvedName(); $className = $scoped->scopeResolutionQualifier->getResolvedName();
} }
if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { if ($scoped->memberName instanceof Node\Expression\Variable) {
if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($scoped->parent instanceof Node\Expression\CallExpression) {
return null; return null;
} }
$memberName = $scoped->memberName->getName(); $memberName = $scoped->memberName->getName();
@ -455,7 +456,7 @@ class DefinitionResolver
} else { } else {
$name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents());
} }
if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($scoped->parent instanceof Node\Expression\CallExpression) {
$name .= '()'; $name .= '()';
} }
return $name; return $name;
@ -465,12 +466,12 @@ class DefinitionResolver
* Returns FQN of the class a node is contained in * Returns FQN of the class a node is contained in
* Returns null if the class is anonymous or the node is not contained in a class * Returns null if the class is anonymous or the node is not contained in a class
* *
* @param Tolerant\Node $node * @param Node $node
* @return string|null * @return string|null
*/ */
private static function getContainingClassFqn(Tolerant\Node $node) private static function getContainingClassFqn(Node $node)
{ {
$classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
if ($classNode === null) { if ($classNode === null) {
return null; return null;
} }
@ -480,18 +481,18 @@ class DefinitionResolver
/** /**
* Returns the assignment or parameter node where a variable was defined * Returns the assignment or parameter node where a variable was defined
* *
* @param Tolerant\Node\Expression\Variable | Tolerant\Node\Expression\ClosureUse $var The variable access * @param Node\Expression\Variable | Node\Expression\ClosureUse $var The variable access
* @return Tolerant\Node\Expression\Assign | Tolerant\Node\Expression\AssignOp|Node\Param | Tolerant\Node\Expression\ClosureUse|null * @return Node\Expression\Assign | Node\Expression\AssignOp|Node\Param | Node\Expression\ClosureUse|null
*/ */
public function resolveVariableToNode($var) public function resolveVariableToNode($var)
{ {
$n = $var; $n = $var;
// When a use is passed, start outside the closure to not return immediately // When a use is passed, start outside the closure to not return immediately
// Use variable vs variable parsing? // Use variable vs variable parsing?
if ($var instanceof Tolerant\Node\UseVariableName) { if ($var instanceof Node\UseVariableName) {
$n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class)->parent; $n = $var->getFirstAncestor(Node\Expression\AnonymousFunctionCreationExpression::class)->parent;
$name = $var->getName(); $name = $var->getName();
} else if ($var instanceof Tolerant\Node\Expression\Variable || $var instanceof Tolerant\Node\Parameter) { } else if ($var instanceof Node\Expression\Variable || $var instanceof Node\Parameter) {
$name = $var->getName(); $name = $var->getName();
} else { } else {
throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var));
@ -509,7 +510,7 @@ class DefinitionResolver
} }
} }
// If it is a closure, also check use statements // If it is a closure, also check use statements
if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && if ($n instanceof Node\Expression\AnonymousFunctionCreationExpression &&
$n->anonymousFunctionUseClause !== null && $n->anonymousFunctionUseClause !== null &&
$n->anonymousFunctionUseClause->useVariableNameList !== null) { $n->anonymousFunctionUseClause->useVariableNameList !== null) {
foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use
@ -523,13 +524,13 @@ class DefinitionResolver
} }
// Check each previous sibling node for a variable assignment to that variable // Check each previous sibling node for a variable assignment to that variable
while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) {
if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { if ($n instanceof Node\Statement\ExpressionStatement) {
$n = $n->expression; $n = $n->expression;
} }
if ( if (
// TODO - clean this up // TODO - clean this up
($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) ($n instanceof Node\Expression\AssignmentExpression && $n->operator->kind === PhpParser\TokenKind::EqualsToken)
&& $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name && $n->leftOperand instanceof Node\Expression\Variable && $n->leftOperand->getName() === $name
) { ) {
return $n; return $n;
} }
@ -543,12 +544,12 @@ class DefinitionResolver
* Given an expression node, resolves that expression recursively to a type. * Given an expression node, resolves that expression recursively to a type.
* If the type could not be resolved, returns Types\Mixed. * If the type could not be resolved, returns Types\Mixed.
* *
* @param Tolerant\Node\Expression $expr * @param Node\Expression $expr
* @return \phpDocumentor\Reflection\Type|null * @return \phpDocumentor\Reflection\Type|null
*/ */
public function resolveExpressionNodeToType($expr) public function resolveExpressionNodeToType($expr)
{ {
if ($expr == null || $expr instanceof Tolerant\MissingToken || $expr instanceof Tolerant\SkippedToken) { if ($expr == null || $expr instanceof PhpParser\MissingToken || $expr instanceof PhpParser\SkippedToken) {
// TODO some members are null or Missing/SkippedToken // TODO some members are null or Missing/SkippedToken
// How do we handle this more generally? // How do we handle this more generally?
return new Types\Mixed; return new Types\Mixed;
@ -556,42 +557,42 @@ class DefinitionResolver
// PARENTHESIZED EXPRESSION // PARENTHESIZED EXPRESSION
// Retrieve inner expression from parenthesized expression // Retrieve inner expression from parenthesized expression
while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { while ($expr instanceof Node\Expression\ParenthesizedExpression) {
$expr = $expr->expression; $expr = $expr->expression;
} }
// VARIABLE // VARIABLE
// $this -> Type\this // $this -> Type\this
// $myVariable -> type of corresponding assignment expression // $myVariable -> type of corresponding assignment expression
if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { if ($expr instanceof Node\Expression\Variable || $expr instanceof Node\UseVariableName) {
if ($expr->getName() === 'this') { if ($expr->getName() === 'this') {
return new Types\This; return new Types\This;
} }
// Find variable definition (parameter or assignment expression) // Find variable definition (parameter or assignment expression)
$defNode = $this->resolveVariableToNode($expr); $defNode = $this->resolveVariableToNode($expr);
if ($defNode instanceof Tolerant\Node\Expression\AssignmentExpression || $defNode instanceof Tolerant\Node\UseVariableName) { if ($defNode instanceof Node\Expression\AssignmentExpression || $defNode instanceof Node\UseVariableName) {
return $this->resolveExpressionNodeToType($defNode); return $this->resolveExpressionNodeToType($defNode);
} }
if ($defNode instanceof Tolerant\Node\Parameter) { if ($defNode instanceof Node\Parameter) {
return $this->getTypeFromNode($defNode); return $this->getTypeFromNode($defNode);
} }
} }
// FUNCTION CALL // FUNCTION CALL
// Function calls are resolved to type corresponding to their FQN // Function calls are resolved to type corresponding to their FQN
if ($expr instanceof Tolerant\Node\Expression\CallExpression && if ($expr instanceof Node\Expression\CallExpression &&
!( !(
$expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression ||
$expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) $expr->callableExpression instanceof Node\Expression\MemberAccessExpression)
) { ) {
// Find the function definition // Find the function definition
if ($expr->callableExpression instanceof Tolerant\Node\Expression) { if ($expr->callableExpression instanceof Node\Expression) {
// Cannot get type for dynamic function call // Cannot get type for dynamic function call
return new Types\Mixed; return new Types\Mixed;
} }
if ($expr->callableExpression instanceof Tolerant\Node\QualifiedName) { if ($expr->callableExpression instanceof Node\QualifiedName) {
$fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName(); $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName();
$fqn .= '()'; $fqn .= '()';
$def = $this->index->getDefinition($fqn, true); $def = $this->index->getDefinition($fqn, true);
@ -603,13 +604,13 @@ class DefinitionResolver
// TRUE / FALSE / NULL // TRUE / FALSE / NULL
// Resolve true and false reserved words to Types\Boolean // Resolve true and false reserved words to Types\Boolean
if ($expr instanceof Tolerant\Node\ReservedWord) { if ($expr instanceof Node\ReservedWord) {
$token = $expr->children->kind; $token = $expr->children->kind;
if ($token === Tolerant\TokenKind::TrueReservedWord || $token === Tolerant\TokenKind::FalseReservedWord) { if ($token === PhpParser\TokenKind::TrueReservedWord || $token === PhpParser\TokenKind::FalseReservedWord) {
return new Types\Boolean; return new Types\Boolean;
} }
if ($token === Tolerant\TokenKind::NullReservedWord) { if ($token === PhpParser\TokenKind::NullReservedWord) {
return new Types\Null_; return new Types\Null_;
} }
} }
@ -625,8 +626,8 @@ class DefinitionResolver
} }
// MEMBER ACCESS EXPRESSION // MEMBER ACCESS EXPRESSION
if ($expr instanceof Tolerant\Node\Expression\MemberAccessExpression) { if ($expr instanceof Node\Expression\MemberAccessExpression) {
if ($expr->memberName instanceof Tolerant\Node\Expression) { if ($expr->memberName instanceof Node\Expression) {
return new Types\Mixed; return new Types\Mixed;
} }
$var = $expr->dereferencableExpression; $var = $expr->dereferencableExpression;
@ -648,7 +649,7 @@ class DefinitionResolver
$classFqn = substr((string)$t->getFqsen(), 1); $classFqn = substr((string)$t->getFqsen(), 1);
} }
$fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents());
if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($expr->parent instanceof Node\Expression\CallExpression) {
$fqn .= '()'; $fqn .= '()';
} }
$def = $this->index->getDefinition($fqn); $def = $this->index->getDefinition($fqn);
@ -659,7 +660,7 @@ class DefinitionResolver
} }
// SCOPED PROPERTY ACCESS EXPRESSION // SCOPED PROPERTY ACCESS EXPRESSION
if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) {
$classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier);
if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) {
return new Types\Mixed; return new Types\Mixed;
@ -668,7 +669,7 @@ class DefinitionResolver
// TODO is there a cleaner way to do this? // TODO is there a cleaner way to do this?
$fqn .= $expr->memberName->getText() ?? $expr->memberName->getText($expr->getFileContents()); $fqn .= $expr->memberName->getText() ?? $expr->memberName->getText($expr->getFileContents());
if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($expr->parent instanceof Node\Expression\CallExpression) {
$fqn .= '()'; $fqn .= '()';
} }
@ -682,26 +683,26 @@ class DefinitionResolver
// OBJECT CREATION EXPRESSION // OBJECT CREATION EXPRESSION
// new A() => resolves to the type of the class type designator (A) // new A() => resolves to the type of the class type designator (A)
// TODO: new $this->a => resolves to the string represented by "a" // TODO: new $this->a => resolves to the string represented by "a"
if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { if ($expr instanceof Node\Expression\ObjectCreationExpression) {
return $this->resolveClassNameToType($expr->classTypeDesignator); return $this->resolveClassNameToType($expr->classTypeDesignator);
} }
// CLONE EXPRESSION // CLONE EXPRESSION
// clone($a) => resolves to the type of $a // clone($a) => resolves to the type of $a
if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { if ($expr instanceof Node\Expression\CloneExpression) {
return $this->resolveExpressionNodeToType($expr->expression); return $this->resolveExpressionNodeToType($expr->expression);
} }
// ASSIGNMENT EXPRESSION // ASSIGNMENT EXPRESSION
// $a = $myExpression => resolves to the type of the right-hand operand // $a = $myExpression => resolves to the type of the right-hand operand
if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { if ($expr instanceof Node\Expression\AssignmentExpression) {
return $this->resolveExpressionNodeToType($expr->rightOperand); return $this->resolveExpressionNodeToType($expr->rightOperand);
} }
// TERNARY EXPRESSION // TERNARY EXPRESSION
// $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression
// $condition ?: $elseExpression => resolves to type of $condition or $elseExpression // $condition ?: $elseExpression => resolves to type of $condition or $elseExpression
if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { if ($expr instanceof Node\Expression\TernaryExpression) {
// ?: // ?:
if ($expr->ifExpression === null) { if ($expr->ifExpression === null) {
return new Types\Compound([ return new Types\Compound([
@ -718,7 +719,7 @@ class DefinitionResolver
// NULL COALLESCE // NULL COALLESCE
// $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand // $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand
if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { if ($expr instanceof Node\Expression\BinaryExpression && $expr->operator->kind === PhpParser\TokenKind::QuestionQuestionToken) {
// ?? operator // ?? operator
return new Types\Compound([ return new Types\Compound([
$this->resolveExpressionNodeToType($expr->leftOperand), $this->resolveExpressionNodeToType($expr->leftOperand),
@ -735,10 +736,10 @@ class DefinitionResolver
if ( if (
ParserHelpers::isBooleanExpression($expr) ParserHelpers::isBooleanExpression($expr)
|| ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) || ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::BoolCastToken)
|| ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) || ($expr instanceof Node\Expression\UnaryOpExpression && $expr->operator->kind === PhpParser\TokenKind::ExclamationToken)
|| $expr instanceof Tolerant\Node\Expression\EmptyIntrinsicExpression || $expr instanceof Node\Expression\EmptyIntrinsicExpression
|| $expr instanceof Tolerant\Node\Expression\IssetIntrinsicExpression || $expr instanceof Node\Expression\IssetIntrinsicExpression
) { ) {
return new Types\Boolean; return new Types\Boolean;
} }
@ -750,10 +751,10 @@ class DefinitionResolver
// //
// TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__) // TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__)
if ( if (
($expr instanceof Tolerant\Node\Expression\BinaryExpression && ($expr instanceof Node\Expression\BinaryExpression &&
($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || ($expr->operator->kind === PhpParser\TokenKind::DotToken || $expr->operator->kind === PhpParser\TokenKind::DotEqualsToken)) ||
$expr instanceof Tolerant\Node\StringLiteral || $expr instanceof Node\StringLiteral ||
($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::StringCastToken)
) { ) {
return new Types\String_; return new Types\String_;
} }
@ -765,18 +766,18 @@ class DefinitionResolver
// Resolve to Types\Float // Resolve to Types\Float
// [assignment] /= // [assignment] /=
if ( if (
$expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr instanceof Node\Expression\BinaryExpression &&
($operator = $expr->operator->kind) ($operator = $expr->operator->kind)
&& ($operator === Tolerant\TokenKind::PlusToken || && ($operator === PhpParser\TokenKind::PlusToken ||
$operator === Tolerant\TokenKind::AsteriskAsteriskToken || $operator === PhpParser\TokenKind::AsteriskAsteriskToken ||
$operator === Tolerant\TokenKind::AsteriskToken || $operator === PhpParser\TokenKind::AsteriskToken ||
$operator === Tolerant\TokenKind::MinusToken || $operator === PhpParser\TokenKind::MinusToken ||
// Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression) // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression)
$operator === Tolerant\TokenKind::AsteriskEqualsToken|| $operator === PhpParser\TokenKind::AsteriskEqualsToken||
$operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || $operator === PhpParser\TokenKind::AsteriskAsteriskEqualsToken ||
$operator === Tolerant\TokenKind::MinusEqualsToken || $operator === PhpParser\TokenKind::MinusEqualsToken ||
$operator === Tolerant\TokenKind::PlusEqualsToken $operator === PhpParser\TokenKind::PlusEqualsToken
) )
) { ) {
if ( if (
@ -787,8 +788,8 @@ class DefinitionResolver
} }
return new Types\Float_; return new Types\Float_;
} else if ( } else if (
$expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr instanceof Node\Expression\BinaryExpression &&
$expr->operator->kind === Tolerant\TokenKind::SlashEqualsToken $expr->operator->kind === PhpParser\TokenKind::SlashEqualsToken
) { ) {
return new Types\Float_; return new Types\Float_;
} }
@ -799,13 +800,13 @@ class DefinitionResolver
// TODO: Magic constants (__LINE__) // TODO: Magic constants (__LINE__)
if ( if (
// TODO: consider different Node types of float/int, also better property name (not "children") // TODO: consider different Node types of float/int, also better property name (not "children")
($expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::IntegerLiteralToken) || ($expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::IntegerLiteralToken) ||
$expr instanceof Tolerant\Node\Expression\BinaryExpression && ( $expr instanceof Node\Expression\BinaryExpression && (
($operator = $expr->operator->kind) ($operator = $expr->operator->kind)
&& ($operator === Tolerant\TokenKind::LessThanEqualsGreaterThanToken || && ($operator === PhpParser\TokenKind::LessThanEqualsGreaterThanToken ||
$operator === Tolerant\TokenKind::AmpersandToken || $operator === PhpParser\TokenKind::AmpersandToken ||
$operator === Tolerant\TokenKind::CaretToken || $operator === PhpParser\TokenKind::CaretToken ||
$operator === Tolerant\TokenKind::BarToken) $operator === PhpParser\TokenKind::BarToken)
) )
) { ) {
return new Types\Integer; return new Types\Integer;
@ -816,9 +817,9 @@ class DefinitionResolver
// [operator] / // [operator] /
// [cast] (double) // [cast] (double)
if ( if (
$expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || $expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::FloatingLiteralToken ||
($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) || ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::DoubleCastToken) ||
($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::SlashToken) ($expr instanceof Node\Expression\BinaryExpression && $expr->operator->kind === PhpParser\TokenKind::SlashToken)
) { ) {
return new Types\Float_; return new Types\Float_;
} }
@ -827,7 +828,7 @@ class DefinitionResolver
// Resolve to Types\Array (Types\Compound of value and key types) // Resolve to Types\Array (Types\Compound of value and key types)
// [a, b, c] // [a, b, c]
// [1=>"hello", "hi"=>1, 4=>[]]s // [1=>"hello", "hi"=>1, 4=>[]]s
if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { if ($expr instanceof Node\Expression\ArrayCreationExpression) {
$valueTypes = []; $valueTypes = [];
$keyTypes = []; $keyTypes = [];
if ($expr->arrayElements !== null) { if ($expr->arrayElements !== null) {
@ -858,7 +859,7 @@ class DefinitionResolver
// SUBSCRIPT EXPRESSION // SUBSCRIPT EXPRESSION
// $myArray[3] // $myArray[3]
// $myArray{"hello"} // $myArray{"hello"}
if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { if ($expr instanceof Node\Expression\SubscriptExpression) {
$varType = $this->resolveExpressionNodeToType($expr->postfixExpression); $varType = $this->resolveExpressionNodeToType($expr->postfixExpression);
if (!($varType instanceof Types\Array_)) { if (!($varType instanceof Types\Array_)) {
return new Types\Mixed; return new Types\Mixed;
@ -868,12 +869,12 @@ class DefinitionResolver
// SCRIPT INCLUSION EXPRESSION // SCRIPT INCLUSION EXPRESSION
// include, require, include_once, require_once // include, require, include_once, require_once
if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { if ($expr instanceof Node\Expression\ScriptInclusionExpression) {
// TODO: resolve path to PhpDocument and find return statement // TODO: resolve path to PhpDocument and find return statement
return new Types\Mixed; return new Types\Mixed;
} }
if ($expr instanceof Tolerant\Node\QualifiedName) { if ($expr instanceof Node\QualifiedName) {
return $this->resolveClassNameToType($expr); return $this->resolveClassNameToType($expr);
} }
@ -885,15 +886,15 @@ class DefinitionResolver
* Takes any class name node (from a static method call, or new node) and returns a Type object * Takes any class name node (from a static method call, or new node) and returns a Type object
* Resolves keywords like self, static and parent * Resolves keywords like self, static and parent
* *
* @param Tolerant\Node || Tolerant\Token $class * @param Node || PhpParser\Token $class
* @return Type * @return Type
*/ */
public function resolveClassNameToType($class): Type public function resolveClassNameToType($class): Type
{ {
if ($class instanceof Tolerant\Node\Expression) { if ($class instanceof Node\Expression) {
return new Types\Mixed; return new Types\Mixed;
} }
if ($class instanceof Tolerant\Token && $class->kind === Tolerant\TokenKind::ClassKeyword) { if ($class instanceof PhpParser\Token && $class->kind === PhpParser\TokenKind::ClassKeyword) {
// Anonymous class // Anonymous class
return new Types\Object_; return new Types\Object_;
} }
@ -903,7 +904,7 @@ class DefinitionResolver
return new Types\Static_; return new Types\Static_;
} }
if ($className === 'self' || $className === 'parent') { if ($className === 'self' || $className === 'parent') {
$classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); $classNode = $class->getFirstAncestor(Node\Statement\ClassDeclaration::class);
if ($className === 'parent') { if ($className === 'parent') {
if ($classNode === null || $classNode->classBaseClause === null) { if ($classNode === null || $classNode->classBaseClause === null) {
return new Types\Object_; return new Types\Object_;
@ -933,7 +934,7 @@ class DefinitionResolver
* If it is unknown, will be Types\Mixed. * If it is unknown, will be Types\Mixed.
* Returns null if the node does not have a type. * Returns null if the node does not have a type.
* *
* @param Tolerant\Node $node * @param Node $node
* @return \phpDocumentor\Reflection\Type|null * @return \phpDocumentor\Reflection\Type|null
*/ */
public function getTypeFromNode($node) public function getTypeFromNode($node)
@ -948,7 +949,7 @@ class DefinitionResolver
// Get the type of the parameter: // Get the type of the parameter:
// 1. Doc block // 1. Doc block
// 2. Parameter type and default // 2. Parameter type and default
if ($node instanceof Tolerant\Node\Parameter) { if ($node instanceof Node\Parameter) {
// Parameters // Parameters
// Get the doc block for the the function call // Get the doc block for the the function call
// /** // /**
@ -968,7 +969,7 @@ class DefinitionResolver
// function foo(MyClass $a) // function foo(MyClass $a)
if ($node->typeDeclaration !== null) { if ($node->typeDeclaration !== null) {
// Use PHP7 return type hint // Use PHP7 return type hint
if ($node->typeDeclaration instanceof Tolerant\Token) { if ($node->typeDeclaration instanceof PhpParser\Token) {
// Resolve a string like "bool" to a type object // Resolve a string like "bool" to a type object
$type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents())); $type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents()));
} else { } else {
@ -1003,9 +1004,9 @@ class DefinitionResolver
// Use @return tag // Use @return tag
return $returnTags[0]->getType(); return $returnTags[0]->getType();
} }
if ($node->returnType !== null && !($node->returnType instanceof Tolerant\MissingToken)) { if ($node->returnType !== null && !($node->returnType instanceof PhpParser\MissingToken)) {
// Use PHP7 return type hint // Use PHP7 return type hint
if ($node->returnType instanceof Tolerant\Token) { if ($node->returnType instanceof PhpParser\Token) {
// Resolve a string like "bool" to a type object // Resolve a string like "bool" to a type object
return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents()));
} }
@ -1022,7 +1023,7 @@ class DefinitionResolver
ParserHelpers::tryGetPropertyDeclaration($node) ?? ParserHelpers::tryGetPropertyDeclaration($node) ??
ParserHelpers::tryGetConstOrClassConstDeclaration($node) ParserHelpers::tryGetConstOrClassConstDeclaration($node)
) !== null || ) !== null ||
($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) ($node = $node->parent) instanceof Node\Expression\AssignmentExpression)
{ {
$declarationNode = $declarationNode ?? $node; $declarationNode = $declarationNode ?? $node;
@ -1037,14 +1038,14 @@ class DefinitionResolver
} }
// Resolve the expression // Resolve the expression
if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { if ($declarationNode instanceof Node\PropertyDeclaration) {
// TODO should have default // TODO should have default
if (isset($node->parent->rightOperand)) { if (isset($node->parent->rightOperand)) {
return $this->resolveExpressionNodeToType($node->parent->rightOperand); return $this->resolveExpressionNodeToType($node->parent->rightOperand);
} }
} else if ($node instanceof Tolerant\Node\ConstElement) { } else if ($node instanceof Node\ConstElement) {
return $this->resolveExpressionNodeToType($node->assignment); return $this->resolveExpressionNodeToType($node->assignment);
} else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { } else if ($node instanceof Node\Expression\AssignmentExpression) {
return $this->resolveExpressionNodeToType($node->rightOperand); return $this->resolveExpressionNodeToType($node->rightOperand);
} }
// TODO: read @property tags of class // TODO: read @property tags of class
@ -1061,7 +1062,7 @@ class DefinitionResolver
* 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 Tolerant\Node $node * @param Node $node
* @return string|null * @return string|null
*/ */
public static function getDefinedFqn($node) public static function getDefinedFqn($node)
@ -1074,23 +1075,23 @@ class DefinitionResolver
// interface C { } A\B\C // interface C { } A\B\C
// trait C { } A\B\C // trait C { } A\B\C
if ( if (
$node instanceof Tolerant\Node\Statement\ClassDeclaration || $node instanceof Node\Statement\ClassDeclaration ||
$node instanceof Tolerant\Node\Statement\InterfaceDeclaration || $node instanceof Node\Statement\InterfaceDeclaration ||
$node instanceof Tolerant\Node\Statement\TraitDeclaration $node instanceof Node\Statement\TraitDeclaration
) { ) {
return (string) $node->getNamespacedName(); return (string) $node->getNamespacedName();
} }
// INPUT OUTPUT: // INPUT OUTPUT:
// namespace A\B; A\B // namespace A\B; A\B
else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { else if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) {
$name = (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents());
return \count($name) > 0 ? $name : null; return \count($name) > 0 ? $name : null;
} }
// INPUT OUTPUT: // INPUT OUTPUT:
// namespace A\B; // namespace A\B;
// function a(); A\B\a(); // function a(); A\B\a();
else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { else if ($node instanceof Node\Statement\FunctionDeclaration) {
// Function: use functionName() as the name // Function: use functionName() as the name
$name = (string)$node->getNamespacedName(); $name = (string)$node->getNamespacedName();
return \count($name) > 0 ? $name . '()' : null; return \count($name) > 0 ? $name . '()' : null;
@ -1101,13 +1102,13 @@ class DefinitionResolver
// function a () {} A\B\C->a() // function a () {} A\B\C->a()
// static function b() {} A\B\C::b() // static function b() {} A\B\C::b()
// } // }
else if ($node instanceof Tolerant\Node\MethodDeclaration) { else if ($node instanceof Node\MethodDeclaration) {
// Class method: use ClassName->methodName() as name // Class method: use ClassName->methodName() as name
$class = $node->getFirstAncestor( $class = $node->getFirstAncestor(
Tolerant\Node\Expression\ObjectCreationExpression::class, Node\Expression\ObjectCreationExpression::class,
Tolerant\Node\Statement\ClassDeclaration::class, Node\Statement\ClassDeclaration::class,
Tolerant\Node\Statement\InterfaceDeclaration::class, Node\Statement\InterfaceDeclaration::class,
Tolerant\Node\Statement\TraitDeclaration::class Node\Statement\TraitDeclaration::class
); );
if (!isset($class->name)) { if (!isset($class->name)) {
// Ignore anonymous classes // Ignore anonymous classes
@ -1130,10 +1131,10 @@ class DefinitionResolver
($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && ($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null &&
($classDeclaration = ($classDeclaration =
$node->getFirstAncestor( $node->getFirstAncestor(
Tolerant\Node\Expression\ObjectCreationExpression::class, Node\Expression\ObjectCreationExpression::class,
Tolerant\Node\Statement\ClassDeclaration::class, Node\Statement\ClassDeclaration::class,
Tolerant\Node\Statement\InterfaceDeclaration::class, Node\Statement\InterfaceDeclaration::class,
Tolerant\Node\Statement\TraitDeclaration::class Node\Statement\TraitDeclaration::class
) )
) !== null && isset($classDeclaration->name)) ) !== null && isset($classDeclaration->name))
{ {
@ -1154,17 +1155,17 @@ class DefinitionResolver
// const $a, $b = 4 A\B\C::$a(), A\B\C::$b // const $a, $b = 4 A\B\C::$a(), A\B\C::$b
// } // }
else if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { else if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) {
if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { if ($constDeclaration instanceof Node\Statement\ConstDeclaration) {
// Basic constant: use CONSTANT_NAME as name // Basic constant: use CONSTANT_NAME as name
return (string)$node->getNamespacedName(); return (string)$node->getNamespacedName();
} }
// Class constant: use ClassName::CONSTANT_NAME as name // Class constant: use ClassName::CONSTANT_NAME as name
$classDeclaration = $constDeclaration->getFirstAncestor( $classDeclaration = $constDeclaration->getFirstAncestor(
Tolerant\Node\Expression\ObjectCreationExpression::class, Node\Expression\ObjectCreationExpression::class,
Tolerant\Node\Statement\ClassDeclaration::class, Node\Statement\ClassDeclaration::class,
Tolerant\Node\Statement\InterfaceDeclaration::class, Node\Statement\InterfaceDeclaration::class,
Tolerant\Node\Statement\TraitDeclaration::class Node\Statement\TraitDeclaration::class
); );
if (!isset($classDeclaration->name)) { if (!isset($classDeclaration->name)) {

View File

@ -3,7 +3,7 @@
namespace LanguageServer; namespace LanguageServer;
use phpDocumentor\Reflection\{Type, Types}; use phpDocumentor\Reflection\{Type, Types};
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
class FqnUtilities class FqnUtilities
{ {

View File

@ -3,68 +3,69 @@ declare(strict_types=1);
namespace LanguageServer; namespace LanguageServer;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
class ParserHelpers { class ParserHelpers {
public static function isConstantFetch(Tolerant\Node $node) : bool { public static function isConstantFetch(Node $node) : bool {
$parent = $node->parent; $parent = $node->parent;
return return
( (
$node instanceof Tolerant\Node\QualifiedName && $node instanceof Node\QualifiedName &&
( (
// $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || // $node->parent instanceof Node\Statement\ExpressionStatement ||
$parent instanceof Tolerant\Node\Expression || $parent instanceof Node\Expression ||
$parent instanceof Tolerant\Node\DelimitedList\ExpressionList || $parent instanceof Node\DelimitedList\ExpressionList ||
$parent instanceof Tolerant\Node\ArrayElement || $parent instanceof Node\ArrayElement ||
($parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || ($parent instanceof Node\Parameter && $node->parent->default === $node) ||
$parent instanceof Tolerant\Node\StatementNode || $parent instanceof Node\StatementNode ||
$parent instanceof Tolerant\Node\CaseStatementNode $parent instanceof Node\CaseStatementNode
) && ) &&
!( !(
$parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $parent instanceof Node\Expression\MemberAccessExpression ||
$parent instanceof Tolerant\Node\Expression\CallExpression || $parent instanceof Node\Expression\CallExpression ||
$parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || $parent instanceof Node\Expression\ObjectCreationExpression ||
$parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $parent instanceof Node\Expression\ScopedPropertyAccessExpression ||
self::isFunctionLike($parent) || self::isFunctionLike($parent) ||
( (
$parent instanceof Tolerant\Node\Expression\BinaryExpression && $parent instanceof Node\Expression\BinaryExpression &&
$parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword $parent->operator->kind === PhpParser\TokenKind::InstanceOfKeyword
) )
)); ));
} }
public static function getFunctionLikeDeclarationFromParameter(Tolerant\Node\Parameter $node) { public static function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) {
return $node->parent->parent; return $node->parent->parent;
} }
public static function isFunctionLike(Tolerant\Node $node) { public static function isFunctionLike(Node $node) {
return return
$node instanceof Tolerant\Node\Statement\FunctionDeclaration || $node instanceof Node\Statement\FunctionDeclaration ||
$node instanceof Tolerant\Node\MethodDeclaration || $node instanceof Node\MethodDeclaration ||
$node instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression; $node instanceof Node\Expression\AnonymousFunctionCreationExpression;
} }
public static function isBooleanExpression($expression) : bool { public static function isBooleanExpression($expression) : bool {
if (!($expression instanceof Tolerant\Node\Expression\BinaryExpression)) { if (!($expression instanceof Node\Expression\BinaryExpression)) {
return false; return false;
} }
switch ($expression->operator->kind) { switch ($expression->operator->kind) {
case Tolerant\TokenKind::InstanceOfKeyword: case PhpParser\TokenKind::InstanceOfKeyword:
case Tolerant\TokenKind::GreaterThanToken: case PhpParser\TokenKind::GreaterThanToken:
case Tolerant\TokenKind::GreaterThanEqualsToken: case PhpParser\TokenKind::GreaterThanEqualsToken:
case Tolerant\TokenKind::LessThanToken: case PhpParser\TokenKind::LessThanToken:
case Tolerant\TokenKind::LessThanEqualsToken: case PhpParser\TokenKind::LessThanEqualsToken:
case Tolerant\TokenKind::AndKeyword: case PhpParser\TokenKind::AndKeyword:
case Tolerant\TokenKind::AmpersandAmpersandToken: case PhpParser\TokenKind::AmpersandAmpersandToken:
case Tolerant\TokenKind::LessThanEqualsGreaterThanToken: case PhpParser\TokenKind::LessThanEqualsGreaterThanToken:
case Tolerant\TokenKind::OrKeyword: case PhpParser\TokenKind::OrKeyword:
case Tolerant\TokenKind::BarBarToken: case PhpParser\TokenKind::BarBarToken:
case Tolerant\TokenKind::XorKeyword: case PhpParser\TokenKind::XorKeyword:
case Tolerant\TokenKind::ExclamationEqualsEqualsToken: case PhpParser\TokenKind::ExclamationEqualsEqualsToken:
case Tolerant\TokenKind::ExclamationEqualsToken: case PhpParser\TokenKind::ExclamationEqualsToken:
case Tolerant\TokenKind::CaretToken: case PhpParser\TokenKind::CaretToken:
case Tolerant\TokenKind::EqualsEqualsEqualsToken: case PhpParser\TokenKind::EqualsEqualsEqualsToken:
case Tolerant\TokenKind::EqualsToken: case PhpParser\TokenKind::EqualsToken:
return true; return true;
} }
return false; return false;
@ -73,13 +74,13 @@ class ParserHelpers {
/** /**
* Tries to get the parent property declaration given a Node * Tries to get the parent property declaration given a Node
* @param Tolerant\Node $node * @param Node $node
* @return Tolerant\Node\PropertyDeclaration | null $node * @return Node\PropertyDeclaration | null $node
*/ */
public static function tryGetPropertyDeclaration(Tolerant\Node $node) { public static function tryGetPropertyDeclaration(Node $node) {
if ($node instanceof Tolerant\Node\Expression\Variable && if ($node instanceof Node\Expression\Variable &&
(($propertyDeclaration = $node->parent->parent) instanceof Tolerant\Node\PropertyDeclaration || (($propertyDeclaration = $node->parent->parent) instanceof Node\PropertyDeclaration ||
($propertyDeclaration = $propertyDeclaration->parent) instanceof Tolerant\Node\PropertyDeclaration) ($propertyDeclaration = $propertyDeclaration->parent) instanceof Node\PropertyDeclaration)
) { ) {
return $propertyDeclaration; return $propertyDeclaration;
} }
@ -88,14 +89,14 @@ class ParserHelpers {
/** /**
* Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node * Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node
* @param Tolerant\Node $node * @param Node $node
* @return Tolerant\Node\Statement\ConstDeclaration | Tolerant\Node\ClassConstDeclaration | null $node * @return Node\Statement\ConstDeclaration | Node\ClassConstDeclaration | null $node
*/ */
public static function tryGetConstOrClassConstDeclaration(Tolerant\Node $node) { public static function tryGetConstOrClassConstDeclaration(Node $node) {
if ( if (
$node instanceof Tolerant\Node\ConstElement && ( $node instanceof Node\ConstElement && (
($constDeclaration = $node->parent->parent) instanceof Tolerant\Node\ClassConstDeclaration || ($constDeclaration = $node->parent->parent) instanceof Node\ClassConstDeclaration ||
$constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration ) $constDeclaration instanceof Node\Statement\ConstDeclaration )
) { ) {
return $constDeclaration; return $constDeclaration;
} }
@ -105,15 +106,15 @@ class ParserHelpers {
/** /**
* Returns true if the node is a usage of `define`. * Returns true if the node is a usage of `define`.
* e.g. define('TEST_DEFINE_CONSTANT', false); * e.g. define('TEST_DEFINE_CONSTANT', false);
* @param Tolerant\Node $node * @param Node $node
* @return bool * @return bool
*/ */
public static function isConstDefineExpression(Tolerant\Node $node): bool { public static function isConstDefineExpression(Node $node): bool {
return $node instanceof Tolerant\Node\Expression\CallExpression return $node instanceof Node\Expression\CallExpression
&& $node->callableExpression instanceof Tolerant\Node\QualifiedName && $node->callableExpression instanceof Node\QualifiedName
&& strtolower($node->callableExpression->getText()) === 'define' && strtolower($node->callableExpression->getText()) === 'define'
&& isset($node->argumentExpressionList->children[0]) && isset($node->argumentExpressionList->children[0])
&& $node->argumentExpressionList->children[0]->expression instanceof Tolerant\Node\StringLiteral && $node->argumentExpressionList->children[0]->expression instanceof Node\StringLiteral
&& isset($node->argumentExpressionList->children[2]); && isset($node->argumentExpressionList->children[2]);
} }
} }

View File

@ -7,7 +7,8 @@ use LanguageServer\Index\Index;
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
Diagnostic, Position, Range Diagnostic, Position, Range
}; };
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
class PhpDocument class PhpDocument
@ -15,7 +16,7 @@ class PhpDocument
/** /**
* The PHPParser instance * The PHPParser instance
* *
* @var Tolerant\Parser * @var PhpParser\Parser
*/ */
private $parser; private $parser;
@ -55,7 +56,7 @@ class PhpDocument
/** /**
* The AST of the document * The AST of the document
* *
* @var Tolerant\Node * @var Node
*/ */
private $stmts; private $stmts;
@ -69,14 +70,14 @@ class PhpDocument
/** /**
* Map from fully qualified name (FQN) to Node * Map from fully qualified name (FQN) to Node
* *
* @var Tolerant\Node * @var Node
*/ */
private $definitionNodes; private $definitionNodes;
/** /**
* Map from fully qualified name (FQN) to array of nodes that reference the symbol * Map from fully qualified name (FQN) to array of nodes that reference the symbol
* *
* @var Tolerant\Node[][] * @var Node[][]
*/ */
private $referenceNodes; private $referenceNodes;
@ -91,7 +92,7 @@ class PhpDocument
* @param string $uri The URI of the document * @param string $uri The URI of the document
* @param string $content The content of the document * @param string $content The content of the document
* @param Index $index The Index to register definitions and references to * @param Index $index The Index to register definitions and references to
* @param Tolerant\Parser $parser The PhpParser instance * @param PhpParser\Parser $parser The PhpParser instance
* @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks * @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks
* @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace * @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace
*/ */
@ -115,7 +116,7 @@ class PhpDocument
* Get all references of a fully qualified name * Get all references of a fully qualified name
* *
* @param string $fqn The fully qualified name of the symbol * @param string $fqn The fully qualified name of the symbol
* @return Tolerant\Node[] * @return Node[]
*/ */
public function getReferenceNodesByFqn(string $fqn) public function getReferenceNodesByFqn(string $fqn)
{ {
@ -220,7 +221,7 @@ class PhpDocument
/** /**
* Returns the AST of the document * Returns the AST of the document
* *
* @return Tolerant\Node | null * @return Node | null
*/ */
public function getStmts() public function getStmts()
{ {
@ -231,7 +232,7 @@ class PhpDocument
* Returns the node at a specified position * Returns the node at a specified position
* *
* @param Position $position * @param Position $position
* @return Tolerant\Node|null * @return Node|null
*/ */
public function getNodeAtPosition(Position $position) public function getNodeAtPosition(Position $position)
{ {
@ -267,7 +268,7 @@ class PhpDocument
* Returns the definition node for a fully qualified name * Returns the definition node for a fully qualified name
* *
* @param string $fqn * @param string $fqn
* @return Tolerant\Node|null * @return Node|null
*/ */
public function getDefinitionNodeByFqn(string $fqn) public function getDefinitionNodeByFqn(string $fqn)
{ {
@ -277,7 +278,7 @@ class PhpDocument
/** /**
* Returns a map from fully qualified name (FQN) to Nodes defined in this document * Returns a map from fully qualified name (FQN) to Nodes defined in this document
* *
* @return Tolerant\Node[] * @return Node[]
*/ */
public function getDefinitionNodes() public function getDefinitionNodes()
{ {

View File

@ -8,7 +8,7 @@ use LanguageServer\Index\ProjectIndex;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use Sabre\Event\Promise; use Sabre\Event\Promise;
use function Sabre\Event\coroutine; use function Sabre\Event\coroutine;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
/** /**
* Takes care of loading documents and managing "open" documents * Takes care of loading documents and managing "open" documents
@ -38,7 +38,7 @@ class PhpDocumentLoader
private $parser; private $parser;
/** /**
* @var Tolerant\Parser * @var PhpParser\Parser
*/ */
private $tolerantParser; private $tolerantParser;
@ -66,7 +66,7 @@ class PhpDocumentLoader
$this->contentRetriever = $contentRetriever; $this->contentRetriever = $contentRetriever;
$this->projectIndex = $projectIndex; $this->projectIndex = $projectIndex;
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
$this->parser = new Tolerant\Parser(); $this->parser = new PhpParser\Parser();
$this->docBlockFactory = DocBlockFactory::createInstance(); $this->docBlockFactory = DocBlockFactory::createInstance();
} }

View File

@ -2,7 +2,8 @@
namespace LanguageServer\Protocol; namespace LanguageServer\Protocol;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
/** /**
* 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,12 @@ class Location
/** /**
* Returns the location of the node * Returns the location of the node
* *
* @param Tolerant\Node $node * @param Node $node
* @return self * @return self
*/ */
public static function fromNode($node) public static function fromNode($node)
{ {
$range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); $range = PhpParser\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents());
return new self($node->getUri(), new Range( return new self($node->getUri(), new Range(
new Position($range->start->line, $range->start->character), new Position($range->start->line, $range->start->character),
new Position($range->end->line, $range->end->character) new Position($range->end->line, $range->end->character)

View File

@ -2,7 +2,8 @@
namespace LanguageServer\Protocol; namespace LanguageServer\Protocol;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
/** /**
* A range in a text document expressed as (zero-based) start and end positions. * A range in a text document expressed as (zero-based) start and end positions.
@ -26,12 +27,12 @@ class Range
/** /**
* Returns the range the node spans * Returns the range the node spans
* *
* @param Tolerant\Node $node * @param Node $node
* @return self * @return self
*/ */
public static function fromNode($node) public static function fromNode($node)
{ {
$range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); $range = PhpParser\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents());
return new self( return new self(
new Position($range->start->line, $range->start->character), new Position($range->start->line, $range->start->character),

View File

@ -2,7 +2,8 @@
namespace LanguageServer\Protocol; namespace LanguageServer\Protocol;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
use Exception; use Exception;
/** /**
@ -42,16 +43,16 @@ class SymbolInformation
/** /**
* Converts a Node to a SymbolInformation * Converts a Node to a SymbolInformation
* *
* @param Tolerant\Node $node * @param 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 SymbolInformation|null * @return SymbolInformation|null
*/ */
public static function fromNode($node, string $fqn = null) public static function fromNode($node, string $fqn = null)
{ {
$symbol = new self; $symbol = new self;
if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { if ($node instanceof Node\Statement\ClassDeclaration) {
$symbol->kind = SymbolKind::CLASS_; $symbol->kind = SymbolKind::CLASS_;
} else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { } else if ($node instanceof Node\Statement\TraitDeclaration) {
$symbol->kind = SymbolKind::CLASS_; $symbol->kind = SymbolKind::CLASS_;
} }
else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) {
@ -59,49 +60,49 @@ class SymbolInformation
// define('TEST_DEFINE_CONSTANT', false); // define('TEST_DEFINE_CONSTANT', false);
$symbol->kind = SymbolKind::CONSTANT; $symbol->kind = SymbolKind::CONSTANT;
$symbol->name = $node->argumentExpressionList->children[0]->expression->getStringContentsText(); $symbol->name = $node->argumentExpressionList->children[0]->expression->getStringContentsText();
} else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { } else if ($node instanceof Node\Statement\InterfaceDeclaration) {
$symbol->kind = SymbolKind::INTERFACE; $symbol->kind = SymbolKind::INTERFACE;
} else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { } else if ($node instanceof Node\Statement\NamespaceDefinition) {
$symbol->kind = SymbolKind::NAMESPACE; $symbol->kind = SymbolKind::NAMESPACE;
} else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { } else if ($node instanceof Node\Statement\FunctionDeclaration) {
$symbol->kind = SymbolKind::FUNCTION; $symbol->kind = SymbolKind::FUNCTION;
} else if ($node instanceof Tolerant\Node\MethodDeclaration) { } else if ($node instanceof Node\MethodDeclaration) {
$nameText = $node->getName(); $nameText = $node->getName();
if ($nameText === '__construct' || $nameText === '__destruct') { if ($nameText === '__construct' || $nameText === '__destruct') {
$symbol->kind = SymbolKind::CONSTRUCTOR; $symbol->kind = SymbolKind::CONSTRUCTOR;
} else { } else {
$symbol->kind = SymbolKind::METHOD; $symbol->kind = SymbolKind::METHOD;
} }
} else if ($node instanceof Tolerant\Node\Expression\Variable && $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class) !== null) { } else if ($node instanceof Node\Expression\Variable && $node->getFirstAncestor(Node\PropertyDeclaration::class) !== null) {
$symbol->kind = SymbolKind::PROPERTY; $symbol->kind = SymbolKind::PROPERTY;
} else if ($node instanceof Tolerant\Node\ConstElement) { } else if ($node instanceof Node\ConstElement) {
$symbol->kind = SymbolKind::CONSTANT; $symbol->kind = SymbolKind::CONSTANT;
} }
else if ( else if (
( (
($node instanceof Tolerant\Node\Expression\AssignmentExpression) ($node instanceof Node\Expression\AssignmentExpression)
&& $node->leftOperand instanceof Tolerant\Node\Expression\Variable && $node->leftOperand instanceof Node\Expression\Variable
) )
|| $node instanceof Tolerant\Node\UseVariableName || $node instanceof Node\UseVariableName
|| $node instanceof Tolerant\Node\Parameter || $node instanceof Node\Parameter
) { ) {
$symbol->kind = SymbolKind::VARIABLE; $symbol->kind = SymbolKind::VARIABLE;
} else { } else {
return null; return null;
} }
if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { if ($node instanceof Node\Expression\AssignmentExpression) {
if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { if ($node->leftOperand instanceof Node\Expression\Variable) {
$symbol->name = $node->leftOperand->getName(); $symbol->name = $node->leftOperand->getName();
} elseif ($node->leftOperand instanceof Tolerant\Token) { } elseif ($node->leftOperand instanceof PhpParser\Token) {
$symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$"); $symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$");
} }
} else if ($node instanceof Tolerant\Node\UseVariableName) { } else if ($node instanceof Node\UseVariableName) {
$symbol->name = $node->getName(); $symbol->name = $node->getName();
} else if (isset($node->name)) { } else if (isset($node->name)) {
if ($node->name instanceof Tolerant\Node\QualifiedName) { if ($node->name instanceof Node\QualifiedName) {
$symbol->name = (string)Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); $symbol->name = (string)PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents());
} else { } else {
$symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$"); $symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$");
} }

View File

@ -10,7 +10,8 @@ use LanguageServer\Index\ReadableIndex;
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
FormattingOptions, Hover, Location, MarkedString, Position, Range, ReferenceContext, SymbolDescriptor, SymbolLocationInformation, TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier FormattingOptions, Hover, Location, MarkedString, Position, Range, ReferenceContext, SymbolDescriptor, SymbolLocationInformation, TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier
}; };
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
use Sabre\Event\Promise; use Sabre\Event\Promise;
use Sabre\Uri; use Sabre\Uri;
use function LanguageServer\{ use function LanguageServer\{
@ -183,24 +184,24 @@ class TextDocument
// by traversing the AST // by traversing the AST
if ( if (
($node instanceof Tolerant\Node\Expression\Variable && !($node->getParent()->getParent() instanceof Tolerant\Node\PropertyDeclaration)) ($node instanceof Node\Expression\Variable && !($node->getParent()->getParent() instanceof Node\PropertyDeclaration))
|| $node instanceof Tolerant\Node\Parameter || $node instanceof Node\Parameter
|| $node instanceof Tolerant\Node\UseVariableName || $node instanceof Node\UseVariableName
) { ) {
if (isset($node->name) && $node->name instanceof Tolerant\Node\Expression) { if (isset($node->name) && $node->name instanceof Node\Expression) {
return null; return null;
} }
// Find function/method/closure scope // Find function/method/closure scope
$n = $node; $n = $node;
$n = $n->getFirstAncestor(Tolerant\Node\Statement\FunctionDeclaration::class, Tolerant\Node\MethodDeclaration::class, Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class, Tolerant\Node\SourceFileNode::class); $n = $n->getFirstAncestor(Node\Statement\FunctionDeclaration::class, Node\MethodDeclaration::class, Node\Expression\AnonymousFunctionCreationExpression::class, Node\SourceFileNode::class);
if ($n === null) { if ($n === null) {
$n = $node->getFirstAncestor(Tolerant\Node\Statement\ExpressionStatement::class)->getParent(); $n = $node->getFirstAncestor(Node\Statement\ExpressionStatement::class)->getParent();
} }
foreach ($n->getDescendantNodes() as $descendantNode) { foreach ($n->getDescendantNodes() as $descendantNode) {
if ($descendantNode instanceof Tolerant\Node\Expression\Variable && if ($descendantNode instanceof Node\Expression\Variable &&
$descendantNode->getName() === $node->getName() $descendantNode->getName() === $node->getName()
) { ) {
$locations[] = Location::fromNode($descendantNode); $locations[] = Location::fromNode($descendantNode);

View File

@ -7,12 +7,13 @@ use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, Te
use LanguageServer\Index\Index; use LanguageServer\Index\Index;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use Sabre\Uri; use Sabre\Uri;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
class TreeAnalyzer { class TreeAnalyzer {
private $parser; private $parser;
/** @var Tolerant\Node */ /** @var Node */
private $stmts; private $stmts;
private $diagnostics; private $diagnostics;
@ -21,7 +22,7 @@ class TreeAnalyzer {
/** /**
* TreeAnalyzer constructor. * TreeAnalyzer constructor.
* @param Tolerant\Parser $parser * @param PhpParser\Parser $parser
* @param $content * @param $content
* @param $docBlockFactory * @param $docBlockFactory
* @param DefinitionResolver $definitionResolver * @param DefinitionResolver $definitionResolver
@ -40,7 +41,7 @@ class TreeAnalyzer {
$this->collectDefinitionsAndReferences($this->stmts); $this->collectDefinitionsAndReferences($this->stmts);
} }
public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { public function collectDefinitionsAndReferences(Node $stmts) {
foreach ($stmts::CHILD_NAMES as $name) { foreach ($stmts::CHILD_NAMES as $name) {
$node = $stmts->$name; $node = $stmts->$name;
@ -50,19 +51,19 @@ class TreeAnalyzer {
if (\is_array($node)) { if (\is_array($node)) {
foreach ($node as $child) { foreach ($node as $child) {
if ($child instanceof Tolerant\Node) { if ($child instanceof Node) {
$this->update($child); $this->update($child);
} }
} }
continue; continue;
} }
if ($node instanceof Tolerant\Node) { if ($node instanceof Node) {
$this->update($node); $this->update($node);
} }
if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { if (($_error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) {
$range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); $range = PhpParser\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content);
$this->diagnostics[] = new Diagnostic( $this->diagnostics[] = new Diagnostic(
$_error->message, $_error->message,
@ -88,14 +89,14 @@ class TreeAnalyzer {
$parent = $node->parent; $parent = $node->parent;
if (!( if (!(
( (
// $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || // $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression ||
($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || ($node instanceof Node\Expression\ScopedPropertyAccessExpression ||
$node instanceof Tolerant\Node\Expression\MemberAccessExpression) $node instanceof Node\Expression\MemberAccessExpression)
&& !( && !(
$node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Node\Expression\CallExpression ||
$node->memberName instanceof Tolerant\Token $node->memberName instanceof PhpParser\Token
)) ))
|| ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) || ($parent instanceof Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()))
) { ) {
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node);
@ -103,9 +104,9 @@ class TreeAnalyzer {
$this->addReference($fqn, $node); $this->addReference($fqn, $node);
if ( if (
$node instanceof Tolerant\Node\QualifiedName $node instanceof Node\QualifiedName
&& ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) && ($node->isQualifiedName() || $node->parent instanceof Node\NamespaceUseClause)
&& !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() && !($parent instanceof Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart()
) )
) { ) {
// Add references for each referenced namespace // Add references for each referenced namespace
@ -120,10 +121,10 @@ class TreeAnalyzer {
// to the global version because PHP falls back to global at runtime // to the global version because PHP falls back to global at runtime
// http://php.net/manual/en/language.namespaces.fallback.php // http://php.net/manual/en/language.namespaces.fallback.php
if (ParserHelpers::isConstantFetch($node) || if (ParserHelpers::isConstantFetch($node) ||
($parent instanceof Tolerant\Node\Expression\CallExpression ($parent instanceof Node\Expression\CallExpression
&& !( && !(
$node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node instanceof Node\Expression\ScopedPropertyAccessExpression ||
$node instanceof Tolerant\Node\Expression\MemberAccessExpression $node instanceof Node\Expression\MemberAccessExpression
))) { ))) {
$parts = explode('\\', $fqn); $parts = explode('\\', $fqn);
if (count($parts) > 1) { if (count($parts) > 1) {
@ -141,7 +142,7 @@ class TreeAnalyzer {
return $this->diagnostics ?? []; return $this->diagnostics ?? [];
} }
private function addReference(string $fqn, Tolerant\Node $node) private function addReference(string $fqn, Node $node)
{ {
if (!isset($this->referenceNodes[$fqn])) { if (!isset($this->referenceNodes[$fqn])) {
$this->referenceNodes[$fqn] = []; $this->referenceNodes[$fqn] = [];

View File

@ -6,13 +6,13 @@ namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Index\Index; use LanguageServer\Index\Index;
use LanguageServer\DefinitionResolver; use LanguageServer\DefinitionResolver;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
class DefinitionResolverTest extends TestCase class DefinitionResolverTest extends TestCase
{ {
public function testCreateDefinitionFromNode() public function testCreateDefinitionFromNode()
{ {
$parser = new Tolerant\Parser; $parser = new PhpParser\Parser;
$doc = new MockPhpDocument; $doc = new MockPhpDocument;
$stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri()); $stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri());
@ -25,7 +25,7 @@ class DefinitionResolverTest extends TestCase
public function testGetTypeFromNode() public function testGetTypeFromNode()
{ {
$parser = new Tolerant\Parser; $parser = new PhpParser\Parser;
$doc = new MockPhpDocument; $doc = new MockPhpDocument;
$stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri()); $stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri());
@ -39,7 +39,7 @@ class DefinitionResolverTest extends TestCase
public function testGetDefinedFqnForIncompleteDefine() public function testGetDefinedFqnForIncompleteDefine()
{ {
// define('XXX') (only one argument) must not introduce a new symbol // define('XXX') (only one argument) must not introduce a new symbol
$parser = new Tolerant\Parser; $parser = new PhpParser\Parser;
$doc = new MockPhpDocument; $doc = new MockPhpDocument;
$stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE');", $doc->getUri()); $stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE');", $doc->getUri());
@ -52,7 +52,7 @@ class DefinitionResolverTest extends TestCase
public function testGetDefinedFqnForDefine() public function testGetDefinedFqnForDefine()
{ {
$parser = new Tolerant\Parser; $parser = new PhpParser\Parser;
$doc = new MockPhpDocument; $doc = new MockPhpDocument;
$stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri()); $stmts = $parser->parseSourceFile("<?php\ndefine('TEST_DEFINE', true);", $doc->getUri());

View File

@ -10,7 +10,8 @@ use LanguageServer\{
}; };
use LanguageServer\Index\{Index}; use LanguageServer\Index\{Index};
use function LanguageServer\pathToUri; use function LanguageServer\pathToUri;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
class DefinitionCollectorTest extends TestCase class DefinitionCollectorTest extends TestCase
{ {
@ -37,21 +38,21 @@ class DefinitionCollectorTest extends TestCase
'TestNamespace\\Example->__destruct()' 'TestNamespace\\Example->__destruct()'
], array_keys($defNodes)); ], array_keys($defNodes));
$this->assertInstanceOf(Tolerant\Node\ConstElement::class, $defNodes['TestNamespace\\TEST_CONST']); $this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\\TEST_CONST']);
$this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\TestClass']); $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\TestClass']);
$this->assertInstanceOf(Tolerant\Node\ConstElement::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']); $this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']);
// TODO - should we parse properties more strictly? // TODO - should we parse properties more strictly?
$this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']); $this->assertInstanceOf(Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']);
$this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass->testProperty']); $this->assertInstanceOf(Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass->testProperty']);
$this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']); $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']);
$this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass->testMethod()']); $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass->testMethod()']);
$this->assertInstanceOf(Tolerant\Node\Statement\TraitDeclaration::class, $defNodes['TestNamespace\\TestTrait']); $this->assertInstanceOf(Node\Statement\TraitDeclaration::class, $defNodes['TestNamespace\\TestTrait']);
$this->assertInstanceOf(Tolerant\Node\Statement\InterfaceDeclaration::class, $defNodes['TestNamespace\\TestInterface']); $this->assertInstanceOf(Node\Statement\InterfaceDeclaration::class, $defNodes['TestNamespace\\TestInterface']);
$this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\test_function()']); $this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\test_function()']);
$this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\ChildClass']); $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\ChildClass']);
$this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\Example']); $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\Example']);
$this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__construct()']); $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__construct()']);
$this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__destruct()']); $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__destruct()']);
} }
public function testDoesNotCollectReferences() public function testDoesNotCollectReferences()
@ -60,8 +61,8 @@ class DefinitionCollectorTest extends TestCase
$defNodes = $this->collectDefinitions($path); $defNodes = $this->collectDefinitions($path);
$this->assertEquals(['TestNamespace', 'TestNamespace\\whatever()'], array_keys($defNodes)); $this->assertEquals(['TestNamespace', 'TestNamespace\\whatever()'], array_keys($defNodes));
$this->assertInstanceOf(Tolerant\Node\Statement\NamespaceDefinition::class, $defNodes['TestNamespace']); $this->assertInstanceOf(Node\Statement\NamespaceDefinition::class, $defNodes['TestNamespace']);
$this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\whatever()']); $this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\whatever()']);
} }
/** /**
@ -70,7 +71,7 @@ class DefinitionCollectorTest extends TestCase
private function collectDefinitions($path): array private function collectDefinitions($path): array
{ {
$uri = pathToUri($path); $uri = pathToUri($path);
$parser = new Tolerant\Parser(); $parser = new PhpParser\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$index = new Index; $index = new Index;

View File

@ -12,7 +12,8 @@ use LanguageServer\Index\{
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
Position Position
}; };
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use function LanguageServer\isVendored; use function LanguageServer\isVendored;
@ -21,7 +22,7 @@ class PhpDocumentTest extends TestCase
{ {
public function createDocument(string $uri, string $content) public function createDocument(string $uri, string $content)
{ {
$parser = new Tolerant\Parser(); $parser = new PhpParser\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$index = new Index; $index = new Index;
$definitionResolver = new DefinitionResolver($index); $definitionResolver = new DefinitionResolver($index);
@ -44,7 +45,7 @@ class PhpDocumentTest extends TestCase
} }
private function assertQualifiedName($node) { private function assertQualifiedName($node) {
$this->assertInstanceOf(Tolerant\Node\QualifiedName::class, $node); $this->assertInstanceOf(Node\QualifiedName::class, $node);
} }
public function testIsVendored() public function testIsVendored()

View File

@ -19,7 +19,7 @@ use AdvancedJsonRpc;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
use Sabre\Event\Loop; use Sabre\Event\Loop;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser;
$frameworksDir = realpath(__DIR__ . '/../../validation/frameworks'); $frameworksDir = realpath(__DIR__ . '/../../validation/frameworks');
@ -94,7 +94,7 @@ class ValidationTest extends TestCase
global $frameworksDir; global $frameworksDir;
$index = new Index(); $index = new Index();
$parser = new Tolerant\Parser(); $parser = new PhpParser\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$definitionResolver = new DefinitionResolver($index); $definitionResolver = new DefinitionResolver($index);