From 13241a7be995824f7d8bc2fe96b6cdf673e01a51 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 2 Feb 2017 16:43:33 -0800 Subject: [PATCH 001/149] initialize tolerant-php-parser --- .gitignore | 1 + composer.json | 9 ++++++++- src/CompletionProvider.php | 1 + src/ComposerScripts.php | 4 +++- src/PhpDocument.php | 7 +++++-- src/PhpDocumentLoader.php | 8 ++++++++ src/Server/TextDocument.php | 7 ------- tests/NodeVisitor/DefinitionCollectorTest.php | 7 +++++-- tests/PhpDocumentTest.php | 4 +++- 9 files changed, 34 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 4791ea27..e7997bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ vendor/ .phpls/ composer.lock stubs +*.ast \ No newline at end of file diff --git a/composer.json b/composer.json index 268a9897..77924407 100644 --- a/composer.json +++ b/composer.json @@ -38,9 +38,16 @@ "webmozart/glob": "^4.1", "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", - "composer/composer": "^1.3" + "composer/composer": "^1.3", + "Microsoft/tolerant-php-parser": "master" }, "minimum-stability": "dev", + "repositories": [ + { + "type": "git", + "url": "https://github.com/Microsoft/tolerant-php-parser.git" + } + ], "prefer-stable": true, "autoload": { "psr-4": { diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 99a5d57f..2e3443e1 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -121,6 +121,7 @@ public function __construct(DefinitionResolver $definitionResolver, ReadableInde */ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionList { + // This can be made much more performant if the tree follows specific invariants. $node = $doc->getNodeAtPosition($pos); if ($node instanceof Node\Expr\Error) { diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index c84a176d..fa321bf4 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -10,6 +10,7 @@ use Webmozart\PathUtil\Path; use Sabre\Uri; use function Sabre\Event\coroutine; +use Microsoft\PhpParser as Tolerant; foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) { if (file_exists($file)) { @@ -30,6 +31,7 @@ public static function parseStubs() $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); $parser = new Parser; + $tolerantParser = new Tolerant\Parser(); $definitionResolver = new DefinitionResolver($index); $stubsLocation = null; @@ -55,7 +57,7 @@ public static function parseStubs() $parts['scheme'] = 'phpstubs'; $uri = Uri\build($parts); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); + $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); } $index->setComplete(); diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 3a25c236..b8110f91 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -17,6 +17,7 @@ use PhpParser\NodeVisitor\NameResolver; use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Uri; +use Microsoft\PhpParser as Tolerant; class PhpDocument { @@ -108,12 +109,14 @@ public function __construct( string $content, Index $index, Parser $parser, + Tolerant\Parser $tolerantParser, DocBlockFactory $docBlockFactory, DefinitionResolver $definitionResolver ) { $this->uri = $uri; $this->index = $index; $this->parser = $parser; + $this->tolerantParser = $tolerantParser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; $this->updateContent($content); @@ -133,7 +136,7 @@ public function getReferenceNodesByFqn(string $fqn) /** * Updates the content on this document. * Re-parses a source file, updates symbols and reports parsing errors - * that may have occured as diagnostics. + * that may have occurred as diagnostics. * * @param string $content * @return void @@ -168,7 +171,7 @@ public function updateContent(string $content) $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::ERROR, 'php'); } - // $stmts can be null in case of a fatal parsing error + // $stmts can be null in case of a fatal parsing error <- Interesting. When do fatal parsing errors occur? if ($stmts) { $traverser = new NodeTraverser; diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index 728225d8..64bd35c5 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -8,6 +8,7 @@ use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Event\Promise; use function Sabre\Event\coroutine; +use Microsoft\PhpParser as Tolerant; /** * Takes care of loading documents and managing "open" documents @@ -36,6 +37,11 @@ class PhpDocumentLoader */ private $parser; + /** + * @var Tolerant\Parser + */ + private $tolerantParser; + /** * @var DocBlockFactory */ @@ -60,6 +66,7 @@ public function __construct( $this->projectIndex = $projectIndex; $this->definitionResolver = $definitionResolver; $this->parser = new Parser; + $this->tolerantParser = new Tolerant\Parser(); $this->docBlockFactory = DocBlockFactory::createInstance(); } @@ -130,6 +137,7 @@ public function create(string $uri, string $content): PhpDocument $content, $this->projectIndex->getIndexForUri($uri), $this->parser, + $this->tolerantParser, $this->docBlockFactory, $this->definitionResolver ); diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index aa76ec23..3141a99c 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -3,7 +3,6 @@ namespace LanguageServer\Server; -use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use PhpParser\{Node, NodeTraverser}; use LanguageServer\{LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider}; use LanguageServer\NodeVisitor\VariableReferencesCollector; @@ -49,11 +48,6 @@ class TextDocument */ protected $project; - /** - * @var PrettyPrinter - */ - protected $prettyPrinter; - /** * @var DefinitionResolver */ @@ -97,7 +91,6 @@ public function __construct( ) { $this->documentLoader = $documentLoader; $this->client = $client; - $this->prettyPrinter = new PrettyPrinter(); $this->definitionResolver = $definitionResolver; $this->completionProvider = new CompletionProvider($this->definitionResolver, $index); $this->index = $index; diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index 3ee9995d..7243ad30 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -14,6 +14,7 @@ use LanguageServer\Tests\MockProtocolStream; use LanguageServer\NodeVisitor\{ReferencesAdder, DefinitionCollector}; use function LanguageServer\pathToUri; +use Microsoft\PhpParser as Tolerant; class DefinitionCollectorTest extends TestCase { @@ -22,11 +23,12 @@ public function testCollectsSymbols() $path = realpath(__DIR__ . '/../../fixtures/symbols.php'); $uri = pathToUri($path); $parser = new Parser; + $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; $definitionResolver = new DefinitionResolver($index); $content = file_get_contents($path); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); + $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); $stmts = $parser->parse($content); $traverser = new NodeTraverser; @@ -70,11 +72,12 @@ public function testDoesNotCollectReferences() $path = realpath(__DIR__ . '/../../fixtures/references.php'); $uri = pathToUri($path); $parser = new Parser; + $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; $definitionResolver = new DefinitionResolver($index); $content = file_get_contents($path); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); + $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); $stmts = $parser->parse($content); $traverser = new NodeTraverser; diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 011a2310..81f998f3 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -13,16 +13,18 @@ use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use PhpParser\Node; use function LanguageServer\isVendored; +use Microsoft\PhpParser as Tolerant; class PhpDocumentTest extends TestCase { public function createDocument(string $uri, string $content) { $parser = new Parser; + $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; $definitionResolver = new DefinitionResolver($index); - return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); + return new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); } public function testParsesVariableVariables() From 027801ebbaba9f47c34d4d53b00134c4ce60e423 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 1 Mar 2017 15:08:34 -0800 Subject: [PATCH 002/149] update parser branch for development --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 77924407..4856aa53 100644 --- a/composer.json +++ b/composer.json @@ -39,13 +39,13 @@ "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "master" + "Microsoft/tolerant-php-parser": "dev-lang-server" }, "minimum-stability": "dev", "repositories": [ { "type": "git", - "url": "https://github.com/Microsoft/tolerant-php-parser.git" + "url": "https://github.com/mousetraps/tolerant-php-parser.git" } ], "prefer-stable": true, From df315df04b756d47526050dcbe24bbc03d49f7b3 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 1 Mar 2017 15:41:18 -0800 Subject: [PATCH 003/149] start refactoring definition resolver --- src/CompletionProvider.php | 8 +- src/ComposerScripts.php | 2 +- src/DefinitionResolver.php | 2 +- src/DefinitionResolverFactory.php | 19 + src/DefinitionResolverInterface.php | 76 ++ src/LanguageServer.php | 4 +- src/NodeVisitor/DefinitionCollector.php | 6 +- src/NodeVisitor/ReferencesCollector.php | 7 +- src/ParserKind.php | 10 + src/PhpDocument.php | 16 +- src/PhpDocumentLoader.php | 10 +- src/Server/TextDocument.php | 20 +- src/TolerantDefinitionResolver.php | 880 ++++++++++++++++++ tests/NodeVisitor/DefinitionCollectorTest.php | 8 +- tests/PhpDocumentLoaderTest.php | 6 +- tests/PhpDocumentTest.php | 6 +- tests/Server/ServerTestCase.php | 6 +- tests/Server/TextDocument/CompletionTest.php | 6 +- .../Definition/GlobalFallbackTest.php | 6 +- tests/Server/TextDocument/DidChangeTest.php | 6 +- tests/Server/TextDocument/DidCloseTest.php | 6 +- tests/Server/TextDocument/FormattingTest.php | 6 +- tests/Server/TextDocument/ParseErrorsTest.php | 6 +- .../References/GlobalFallbackTest.php | 6 +- 24 files changed, 1070 insertions(+), 58 deletions(-) create mode 100644 src/DefinitionResolverFactory.php create mode 100644 src/DefinitionResolverInterface.php create mode 100644 src/ParserKind.php create mode 100644 src/TolerantDefinitionResolver.php diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2e3443e1..93b09a47 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -88,7 +88,7 @@ class CompletionProvider ]; /** - * @var DefinitionResolver + * @var DefinitionResolverInterface */ private $definitionResolver; @@ -103,10 +103,10 @@ class CompletionProvider private $index; /** - * @param DefinitionResolver $definitionResolver - * @param ReadableIndex $index + * @param DefinitionResolverInterface $definitionResolver + * @param ReadableIndex $index */ - public function __construct(DefinitionResolver $definitionResolver, ReadableIndex $index) + public function __construct(DefinitionResolverInterface $definitionResolver, ReadableIndex $index) { $this->definitionResolver = $definitionResolver; $this->index = $index; diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index fa321bf4..717af195 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -32,7 +32,7 @@ public static function parseStubs() $docBlockFactory = DocBlockFactory::createInstance(); $parser = new Parser; $tolerantParser = new Tolerant\Parser(); - $definitionResolver = new DefinitionResolver($index); + $definitionResolver = DefinitionResolverFactory::create($index); $stubsLocation = null; foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index ec295a53..67399dda 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -9,7 +9,7 @@ use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; -class DefinitionResolver +class DefinitionResolver implements DefinitionResolverInterface { /** * @var \LanguageServer\Index\ReadableIndex diff --git a/src/DefinitionResolverFactory.php b/src/DefinitionResolverFactory.php new file mode 100644 index 00000000..ee64b4f8 --- /dev/null +++ b/src/DefinitionResolverFactory.php @@ -0,0 +1,19 @@ +globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex); // The DefinitionResolver should look in stubs, the project source and dependencies - $this->definitionResolver = new DefinitionResolver($this->globalIndex); + $this->definitionResolver = DefinitionResolverFactory::create($this->globalIndex); $this->documentLoader = new PhpDocumentLoader( $this->contentRetriever, diff --git a/src/NodeVisitor/DefinitionCollector.php b/src/NodeVisitor/DefinitionCollector.php index 51981395..57de95f4 100644 --- a/src/NodeVisitor/DefinitionCollector.php +++ b/src/NodeVisitor/DefinitionCollector.php @@ -4,7 +4,9 @@ namespace LanguageServer\NodeVisitor; use PhpParser\{NodeVisitorAbstract, Node}; -use LanguageServer\{Definition, DefinitionResolver}; +use LanguageServer\{ + Definition, DefinitionResolver, DefinitionResolverInterface +}; use LanguageServer\Protocol\SymbolInformation; /** @@ -29,7 +31,7 @@ class DefinitionCollector extends NodeVisitorAbstract private $definitionResolver; - public function __construct(DefinitionResolver $definitionResolver) + public function __construct(DefinitionResolverInterface $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/NodeVisitor/ReferencesCollector.php b/src/NodeVisitor/ReferencesCollector.php index e7b9f065..d586b5b3 100644 --- a/src/NodeVisitor/ReferencesCollector.php +++ b/src/NodeVisitor/ReferencesCollector.php @@ -3,6 +3,7 @@ namespace LanguageServer\NodeVisitor; +use LanguageServer\DefinitionResolverInterface; use PhpParser\{NodeVisitorAbstract, Node}; use LanguageServer\DefinitionResolver; @@ -20,14 +21,14 @@ class ReferencesCollector extends NodeVisitorAbstract public $nodes = []; /** - * @var DefinitionResolver + * @var DefinitionResolverInterface */ private $definitionResolver; /** - * @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve reference nodes to definitions + * @param DefinitionResolverInterface $definitionResolver The DefinitionResolver to resolve reference nodes to definitions */ - public function __construct(DefinitionResolver $definitionResolver) + public function __construct(DefinitionResolverInterface $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/ParserKind.php b/src/ParserKind.php new file mode 100644 index 00000000..3a1e498f --- /dev/null +++ b/src/ParserKind.php @@ -0,0 +1,10 @@ +uri = $uri; $this->index = $index; diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index 64bd35c5..b49e63de 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -48,19 +48,19 @@ class PhpDocumentLoader private $docBlockFactory; /** - * @var DefinitionResolver + * @var DefinitionResolverInterface */ private $definitionResolver; /** - * @param ContentRetriever $contentRetriever - * @param ProjectIndex $project - * @param DefinitionResolver $definitionResolver + * @param ContentRetriever $contentRetriever + * @param ProjectIndex $project + * @param DefinitionResolverInterface $definitionResolver */ public function __construct( ContentRetriever $contentRetriever, ProjectIndex $projectIndex, - DefinitionResolver $definitionResolver + DefinitionResolverInterface $definitionResolver ) { $this->contentRetriever = $contentRetriever; $this->projectIndex = $projectIndex; diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 3141a99c..55341a39 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -4,7 +4,9 @@ namespace LanguageServer\Server; use PhpParser\{Node, NodeTraverser}; -use LanguageServer\{LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider}; +use LanguageServer\{ + DefinitionResolverInterface, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider +}; use LanguageServer\NodeVisitor\VariableReferencesCollector; use LanguageServer\Protocol\{ SymbolLocationInformation, @@ -49,7 +51,7 @@ class TextDocument protected $project; /** - * @var DefinitionResolver + * @var DefinitionResolverInterface */ protected $definitionResolver; @@ -74,16 +76,16 @@ class TextDocument protected $composerLock; /** - * @param PhpDocumentLoader $documentLoader - * @param DefinitionResolver $definitionResolver - * @param LanguageClient $client - * @param ReadableIndex $index - * @param \stdClass $composerJson - * @param \stdClass $composerLock + * @param PhpDocumentLoader $documentLoader + * @param DefinitionResolverInterface $definitionResolver + * @param LanguageClient $client + * @param ReadableIndex $index + * @param \stdClass $composerJson + * @param \stdClass $composerLock */ public function __construct( PhpDocumentLoader $documentLoader, - DefinitionResolver $definitionResolver, + DefinitionResolverInterface $definitionResolver, LanguageClient $client, ReadableIndex $index, \stdClass $composerJson = null, diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php new file mode 100644 index 00000000..ebd8e652 --- /dev/null +++ b/src/TolerantDefinitionResolver.php @@ -0,0 +1,880 @@ +index = $index; + $this->typeResolver = new TypeResolver; + $this->prettyPrinter = new PrettyPrinter; + } + + /** + * Builds the declaration line for a given node + * + * @param Node $node + * @return string + */ + public function getDeclarationLineFromNode(Node $node): string + { + if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { + // Properties and constants can have multiple declarations + // Use the parent node (that includes the modifiers), but only render the requested declaration + $child = $node; + /** @var Node */ + $node = $node->getAttribute('parentNode'); + $defLine = clone $node; + $defLine->props = [$child]; + } else { + $defLine = clone $node; + } + // Don't include the docblock in the declaration string + $defLine->setAttribute('comments', []); + if (isset($defLine->stmts)) { + $defLine->stmts = []; + } + $defText = $this->prettyPrinter->prettyPrint([$defLine]); + return strstr($defText, "\n", true) ?: $defText; + } + + /** + * Gets the documentation string for a node, if it has one + * + * @param Node $node + * @return string|null + */ + public function getDocumentationFromNode(Node $node) + { + if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { + $node = $node->getAttribute('parentNode'); + } + if ($node instanceof Node\Param) { + $fn = $node->getAttribute('parentNode'); + $docBlock = $fn->getAttribute('docBlock'); + if ($docBlock !== null) { + $tags = $docBlock->getTagsByName('param'); + foreach ($tags as $tag) { + if ($tag->getVariableName() === $node->name) { + return $tag->getDescription()->render(); + } + } + } + } else { + $docBlock = $node->getAttribute('docBlock'); + if ($docBlock !== null) { + return $docBlock->getSummary(); + } + } + } + + /** + * Create a Definition for a definition node + * + * @param Node $node + * @param string $fqn + * @return Definition + */ + public function createDefinitionFromNode(Node $node, string $fqn = null): Definition + { + $parent = $node->getAttribute('parentNode'); + $def = new Definition; + $def->canBeInstantiated = $node instanceof Node\Stmt\Class_; + $def->isGlobal = ( + $node instanceof Node\Stmt\ClassLike + || ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) + || $node instanceof Node\Stmt\Function_ + || $parent instanceof Node\Stmt\Const_ + ); + $def->isStatic = ( + ($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) + || ($node instanceof Node\Stmt\PropertyProperty && $parent->isStatic()) + ); + $def->fqn = $fqn; + if ($node instanceof Node\Stmt\Class_) { + $def->extends = []; + if ($node->extends) { + $def->extends[] = (string)$node->extends; + } + } else if ($node instanceof Node\Stmt\Interface_) { + $def->extends = []; + foreach ($node->extends as $n) { + $def->extends[] = (string)$n; + } + } + $def->symbolInformation = SymbolInformation::fromNode($node, $fqn); + $def->type = $this->getTypeFromNode($node); + $def->declarationLine = $this->getDeclarationLineFromNode($node); + $def->documentation = $this->getDocumentationFromNode($node); + return $def; + } + + /** + * Given any node, returns the Definition object of the symbol that is referenced + * + * @param Node $node Any reference node + * @return Definition|null + */ + public function resolveReferenceNodeToDefinition(Node $node) + { + // Variables are not indexed globally, as they stay in the file scope anyway + if ($node instanceof Node\Expr\Variable) { + // Resolve $this + if ($node->name === 'this' && $fqn = $this->getContainingClassFqn($node)) { + return $this->index->getDefinition($fqn, false); + } + // Resolve the variable to a definition node (assignment, param or closure use) + $defNode = self::resolveVariableToNode($node); + if ($defNode === null) { + return null; + } + return $this->createDefinitionFromNode($defNode); + } + // Other references are references to a global symbol that have an FQN + // Find out the FQN + $fqn = $this->resolveReferenceNodeToFqn($node); + if ($fqn === null) { + return null; + } + // 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 + $parent = $node->getAttribute('parentNode'); + $globalFallback = $parent instanceof Node\Expr\ConstFetch || $parent instanceof Node\Expr\FuncCall; + // Return the Definition object from the index index + return $this->index->getDefinition($fqn, $globalFallback); + } + + /** + * Returns all possible FQNs in a type + * + * @param Type $type + * @return string[] + */ + public static function getFqnsFromType(Type $type): array + { + $fqns = []; + if ($type instanceof Types\Object_) { + $fqsen = $type->getFqsen(); + if ($fqsen !== null) { + $fqns[] = substr((string)$fqsen, 1); + } + } + if ($type instanceof Types\Compound) { + for ($i = 0; $t = $type->get($i); $i++) { + foreach (self::getFqnsFromType($type) as $fqn) { + $fqns[] = $fqn; + } + } + } + return $fqns; + } + + /** + * Given any node, returns the FQN of the symbol that is referenced + * Returns null if the FQN could not be resolved or the reference node references a variable + * + * @param Node $node + * @return string|null + */ + public function resolveReferenceNodeToFqn(Node $node) + { + $parent = $node->getAttribute('parentNode'); + + if ( + $node instanceof Node\Name && ( + $parent instanceof Node\Stmt\ClassLike + || $parent instanceof Node\Param + || $parent instanceof Node\FunctionLike + || $parent instanceof Node\Stmt\GroupUse + || $parent instanceof Node\Expr\New_ + || $parent instanceof Node\Expr\StaticCall + || $parent instanceof Node\Expr\ClassConstFetch + || $parent instanceof Node\Expr\StaticPropertyFetch + || $parent instanceof Node\Expr\Instanceof_ + ) + ) { + // For extends, implements, type hints and classes of classes of static calls use the name directly + $name = (string)$node; + // Only the name node should be considered a reference, not the UseUse node itself + } else if ($parent instanceof Node\Stmt\UseUse) { + $name = (string)$parent->name; + $grandParent = $parent->getAttribute('parentNode'); + if ($grandParent instanceof Node\Stmt\GroupUse) { + $name = $grandParent->prefix . '\\' . $name; + } else if ($grandParent instanceof Node\Stmt\Use_ && $grandParent->type === Node\Stmt\Use_::TYPE_FUNCTION) { + $name .= '()'; + } + } else if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { + if ($node->name instanceof Node\Expr) { + // Cannot get definition if right-hand side is expression + return null; + } + // Get the type of the left-hand expression + $varType = $this->resolveExpressionNodeToType($node->var); + if ($varType instanceof Types\Compound) { + // For compound types, use the first FQN we find + // (popular use case is ClassName|null) + for ($i = 0; $t = $varType->get($i); $i++) { + if ( + $t instanceof Types\This + || $t instanceof Types\Object_ + || $t instanceof Types\Static_ + || $t instanceof Types\Self_ + ) { + $varType = $t; + break; + } + } + } + if ( + $varType instanceof Types\This + || $varType instanceof Types\Static_ + || $varType instanceof Types\Self_ + ) { + // $this/static/self is resolved to the containing class + $classFqn = self::getContainingClassFqn($node); + } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { + // Left-hand expression could not be resolved to a class + return null; + } else { + $classFqn = substr((string)$varType->getFqsen(), 1); + } + $memberSuffix = '->' . (string)$node->name; + if ($node instanceof Node\Expr\MethodCall) { + $memberSuffix .= '()'; + } + // Find the right class that implements the member + $implementorFqns = [$classFqn]; + while ($implementorFqn = array_shift($implementorFqns)) { + // If the member FQN exists, return it + if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { + return $implementorFqn . $memberSuffix; + } + // Get Definition of implementor class + $implementorDef = $this->index->getDefinition($implementorFqn); + // If it doesn't exist, return the initial guess + if ($implementorDef === null) { + break; + } + // Repeat for parent class + if ($implementorDef->extends) { + foreach ($implementorDef->extends as $extends) { + $implementorFqns[] = $extends; + } + } + } + return $classFqn . $memberSuffix; + } else if ($parent instanceof Node\Expr\FuncCall && $node instanceof Node\Name) { + if ($parent->name instanceof Node\Expr) { + return null; + } + $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); + } else if ($parent instanceof Node\Expr\ConstFetch && $node instanceof Node\Name) { + $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); + } else if ( + $node instanceof Node\Expr\ClassConstFetch + || $node instanceof Node\Expr\StaticPropertyFetch + || $node instanceof Node\Expr\StaticCall + ) { + if ($node->class instanceof Node\Expr || $node->name instanceof Node\Expr) { + // Cannot get definition of dynamic names + return null; + } + $className = (string)$node->class; + if ($className === 'self' || $className === 'static' || $className === 'parent') { + // self and static are resolved to the containing class + $classNode = getClosestNode($node, Node\Stmt\Class_::class); + if ($classNode === null) { + return null; + } + if ($className === 'parent') { + // parent is resolved to the parent class + if (!isset($n->extends)) { + return null; + } + $className = (string)$classNode->extends; + } else { + $className = (string)$classNode->namespacedName; + } + } + if ($node instanceof Node\Expr\StaticPropertyFetch) { + $name = (string)$className . '::$' . $node->name; + } else { + $name = (string)$className . '::' . $node->name; + } + } else { + return null; + } + if (!isset($name)) { + return null; + } + if ( + $node instanceof Node\Expr\MethodCall + || $node instanceof Node\Expr\StaticCall + || $parent instanceof Node\Expr\FuncCall + ) { + $name .= '()'; + } + return $name; + } + + /** + * 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 + * + * @param Node $node + * @return string|null + */ + private static function getContainingClassFqn(Node $node) + { + $classNode = getClosestNode($node, Node\Stmt\Class_::class); + if ($classNode === null || $classNode->isAnonymous()) { + return null; + } + return (string)$classNode->namespacedName; + } + + /** + * Returns the assignment or parameter node where a variable was defined + * + * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access + * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null + */ + public static function resolveVariableToNode(Node\Expr $var) + { + $n = $var; + // When a use is passed, start outside the closure to not return immediatly + if ($var instanceof Node\Expr\ClosureUse) { + $n = $var->getAttribute('parentNode')->getAttribute('parentNode'); + $name = $var->var; + } else if ($var instanceof Node\Expr\Variable || $var instanceof Node\Param) { + $name = $var->name; + } else { + throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); + } + // Traverse the AST up + do { + // If a function is met, check the parameters and use statements + if ($n instanceof Node\FunctionLike) { + foreach ($n->getParams() as $param) { + if ($param->name === $name) { + return $param; + } + } + // If it is a closure, also check use statements + if ($n instanceof Node\Expr\Closure) { + foreach ($n->uses as $use) { + if ($use->var === $name) { + return $use; + } + } + } + break; + } + // Check each previous sibling node for a variable assignment to that variable + while ($n->getAttribute('previousSibling') && $n = $n->getAttribute('previousSibling')) { + if ( + ($n instanceof Node\Expr\Assign || $n instanceof Node\Expr\AssignOp) + && $n->var instanceof Node\Expr\Variable && $n->var->name === $name + ) { + return $n; + } + } + } while (isset($n) && $n = $n->getAttribute('parentNode')); + // Return null if nothing was found + return null; + } + + /** + * Given an expression node, resolves that expression recursively to a type. + * If the type could not be resolved, returns Types\Mixed. + * + * @param \PhpParser\Node\Expr $expr + * @return \phpDocumentor\Reflection\Type + */ + public function resolveExpressionNodeToType(Node\Expr $expr): Type + { + if ($expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\ClosureUse) { + if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { + return new Types\This; + } + // Find variable definition + $defNode = $this->resolveVariableToNode($expr); + if ($defNode instanceof Node\Expr) { + return $this->resolveExpressionNodeToType($defNode); + } + if ($defNode instanceof Node\Param) { + return $this->getTypeFromNode($defNode); + } + } + if ($expr instanceof Node\Expr\FuncCall) { + // Find the function definition + if ($expr->name instanceof Node\Expr) { + // Cannot get type for dynamic function call + return new Types\Mixed; + } + $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } + } + if ($expr instanceof Node\Expr\ConstFetch) { + if (strtolower((string)$expr->name) === 'true' || strtolower((string)$expr->name) === 'false') { + return new Types\Boolean; + } + if (strtolower((string)$expr->name) === 'null') { + return new Types\Null_; + } + // Resolve constant + $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } + } + if ($expr instanceof Node\Expr\MethodCall || $expr instanceof Node\Expr\PropertyFetch) { + if ($expr->name instanceof Node\Expr) { + return new Types\Mixed; + } + // Resolve object + $objType = $this->resolveExpressionNodeToType($expr->var); + if (!($objType instanceof Types\Compound)) { + $objType = new Types\Compound([$objType]); + } + for ($i = 0; $t = $objType->get($i); $i++) { + if ($t instanceof Types\This) { + $classFqn = self::getContainingClassFqn($expr); + if ($classFqn === null) { + return new Types\Mixed; + } + } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { + return new Types\Mixed; + } else { + $classFqn = substr((string)$t->getFqsen(), 1); + } + $fqn = $classFqn . '->' . $expr->name; + if ($expr instanceof Node\Expr\MethodCall) { + $fqn .= '()'; + } + $def = $this->index->getDefinition($fqn); + if ($def !== null) { + return $def->type; + } + } + } + if ( + $expr instanceof Node\Expr\StaticCall + || $expr instanceof Node\Expr\StaticPropertyFetch + || $expr instanceof Node\Expr\ClassConstFetch + ) { + $classType = self::resolveClassNameToType($expr->class); + if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null || $expr->name instanceof Node\Expr) { + return new Types\Mixed; + } + $fqn = substr((string)$classType->getFqsen(), 1) . '::'; + if ($expr instanceof Node\Expr\StaticPropertyFetch) { + $fqn .= '$'; + } + $fqn .= $expr->name; + if ($expr instanceof Node\Expr\StaticCall) { + $fqn .= '()'; + } + $def = $this->index->getDefinition($fqn); + if ($def === null) { + return new Types\Mixed; + } + return $def->type; + } + if ($expr instanceof Node\Expr\New_) { + return self::resolveClassNameToType($expr->class); + } + if ($expr instanceof Node\Expr\Clone_ || $expr instanceof Node\Expr\Assign) { + return $this->resolveExpressionNodeToType($expr->expr); + } + if ($expr instanceof Node\Expr\Ternary) { + // ?: + if ($expr->if === null) { + return new Types\Compound([ + $this->resolveExpressionNodeToType($expr->cond), + $this->resolveExpressionNodeToType($expr->else) + ]); + } + // Ternary is a compound of the two possible values + return new Types\Compound([ + $this->resolveExpressionNodeToType($expr->if), + $this->resolveExpressionNodeToType($expr->else) + ]); + } + if ($expr instanceof Node\Expr\BinaryOp\Coalesce) { + // ?? operator + return new Types\Compound([ + $this->resolveExpressionNodeToType($expr->left), + $this->resolveExpressionNodeToType($expr->right) + ]); + } + if ( + $expr instanceof Node\Expr\Instanceof_ + || $expr instanceof Node\Expr\Cast\Bool_ + || $expr instanceof Node\Expr\BooleanNot + || $expr instanceof Node\Expr\Empty_ + || $expr instanceof Node\Expr\Isset_ + || $expr instanceof Node\Expr\BinaryOp\Greater + || $expr instanceof Node\Expr\BinaryOp\GreaterOrEqual + || $expr instanceof Node\Expr\BinaryOp\Smaller + || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual + || $expr instanceof Node\Expr\BinaryOp\BooleanAnd + || $expr instanceof Node\Expr\BinaryOp\BooleanOr + || $expr instanceof Node\Expr\BinaryOp\LogicalAnd + || $expr instanceof Node\Expr\BinaryOp\LogicalOr + || $expr instanceof Node\Expr\BinaryOp\LogicalXor + || $expr instanceof Node\Expr\BinaryOp\NotEqual + || $expr instanceof Node\Expr\BinaryOp\NotIdentical + ) { + return new Types\Boolean; + } + if ( + $expr instanceof Node\Expr\Cast\String_ + || $expr instanceof Node\Expr\BinaryOp\Concat + || $expr instanceof Node\Expr\AssignOp\Concat + || $expr instanceof Node\Scalar\String_ + || $expr instanceof Node\Scalar\Encapsed + || $expr instanceof Node\Scalar\EncapsedStringPart + || $expr instanceof Node\Scalar\MagicConst\Class_ + || $expr instanceof Node\Scalar\MagicConst\Dir + || $expr instanceof Node\Scalar\MagicConst\Function_ + || $expr instanceof Node\Scalar\MagicConst\Method + || $expr instanceof Node\Scalar\MagicConst\Namespace_ + || $expr instanceof Node\Scalar\MagicConst\Trait_ + ) { + return new Types\String_; + } + if ( + $expr instanceof Node\Expr\BinaryOp\Minus + || $expr instanceof Node\Expr\BinaryOp\Plus + || $expr instanceof Node\Expr\BinaryOp\Pow + || $expr instanceof Node\Expr\BinaryOp\Mul + ) { + if ( + $this->resolveExpressionNodeToType($expr->left) instanceof Types\Integer + && $this->resolveExpressionNodeToType($expr->right) instanceof Types\Integer + ) { + return new Types\Integer; + } + return new Types\Float_; + } + + if ( + $expr instanceof Node\Expr\AssignOp\Minus + || $expr instanceof Node\Expr\AssignOp\Plus + || $expr instanceof Node\Expr\AssignOp\Pow + || $expr instanceof Node\Expr\AssignOp\Mul + ) { + if ( + $this->resolveExpressionNodeToType($expr->var) instanceof Types\Integer + && $this->resolveExpressionNodeToType($expr->expr) instanceof Types\Integer + ) { + return new Types\Integer; + } + return new Types\Float_; + } + + if ( + $expr instanceof Node\Scalar\LNumber + || $expr instanceof Node\Expr\Cast\Int_ + || $expr instanceof Node\Scalar\MagicConst\Line + || $expr instanceof Node\Expr\BinaryOp\Spaceship + || $expr instanceof Node\Expr\BinaryOp\BitwiseAnd + || $expr instanceof Node\Expr\BinaryOp\BitwiseOr + || $expr instanceof Node\Expr\BinaryOp\BitwiseXor + ) { + return new Types\Integer; + } + if ( + $expr instanceof Node\Expr\BinaryOp\Div + || $expr instanceof Node\Scalar\DNumber + || $expr instanceof Node\Expr\Cast\Double + ) { + return new Types\Float_; + } + if ($expr instanceof Node\Expr\Array_) { + $valueTypes = []; + $keyTypes = []; + foreach ($expr->items as $item) { + $valueTypes[] = $this->resolveExpressionNodeToType($item->value); + $keyTypes[] = $item->key ? $this->resolveExpressionNodeToType($item->key) : new Types\Integer; + } + $valueTypes = array_unique($keyTypes); + $keyTypes = array_unique($keyTypes); + if (empty($valueTypes)) { + $valueType = null; + } else if (count($valueTypes) === 1) { + $valueType = $valueTypes[0]; + } else { + $valueType = new Types\Compound($valueTypes); + } + if (empty($keyTypes)) { + $keyType = null; + } else if (count($keyTypes) === 1) { + $keyType = $keyTypes[0]; + } else { + $keyType = new Types\Compound($keyTypes); + } + return new Types\Array_($valueType, $keyType); + } + if ($expr instanceof Node\Expr\ArrayDimFetch) { + $varType = $this->resolveExpressionNodeToType($expr->var); + if (!($varType instanceof Types\Array_)) { + return new Types\Mixed; + } + return $varType->getValueType(); + } + if ($expr instanceof Node\Expr\Include_) { + // TODO: resolve path to PhpDocument and find return statement + return new Types\Mixed; + } + return new Types\Mixed; + } + + /** + * 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 + * + * @param Node $class + * @return Type + */ + private static function resolveClassNameToType(Node $class): Type + { + if ($class instanceof Node\Expr) { + return new Types\Mixed; + } + if ($class instanceof Node\Stmt\Class_) { + // Anonymous class + return new Types\Object_; + } + $className = (string)$class; + if ($className === 'static') { + return new Types\Static_; + } + if ($className === 'self' || $className === 'parent') { + $classNode = getClosestNode($class, Node\Stmt\Class_::class); + if ($className === 'parent') { + if ($classNode === null || $classNode->extends === null) { + return new Types\Object_; + } + // parent is resolved to the parent class + $classFqn = (string)$classNode->extends; + } else { + if ($classNode === null) { + return new Types\Self_; + } + // self is resolved to the containing class + $classFqn = (string)$classNode->namespacedName; + } + return new Types\Object_(new Fqsen('\\' . $classFqn)); + } + return new Types\Object_(new Fqsen('\\' . $className)); + } + + /** + * Returns the type a reference to this symbol will resolve to. + * For properties and constants, this is the type of the property/constant. + * For functions and methods, this is the return type. + * For parameters, this is the type of the parameter. + * For classes and interfaces, this is the class type (object). + * For variables / assignments, this is the documented type or type the assignment resolves to. + * Can also be a compound type. + * If it is unknown, will be Types\Mixed. + * Returns null if the node does not have a type. + * + * @param Node $node + * @return \phpDocumentor\Reflection\Type|null + */ + public function getTypeFromNode(Node $node) + { + if ($node instanceof Node\Param) { + // Parameters + $docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock'); + if ($docBlock !== null) { + // Use @param tag + foreach ($docBlock->getTagsByName('param') as $paramTag) { + if ($paramTag->getVariableName() === $node->name) { + if ($paramTag->getType() === null) { + break; + } + return $paramTag->getType(); + } + } + } + $type = null; + if ($node->type !== null) { + // Use PHP7 return type hint + if (is_string($node->type)) { + // Resolve a string like "bool" to a type object + $type = $this->typeResolver->resolve($node->type); + } else { + $type = new Types\Object_(new Fqsen('\\' . (string)$node->type)); + } + } + if ($node->default !== null) { + $defaultType = $this->resolveExpressionNodeToType($node->default); + if (isset($type) && !is_a($type, get_class($defaultType))) { + $type = new Types\Compound([$type, $defaultType]); + } else { + $type = $defaultType; + } + } + return $type ?? new Types\Mixed; + } + if ($node instanceof Node\FunctionLike) { + // Functions/methods + $docBlock = $node->getAttribute('docBlock'); + if ( + $docBlock !== null + && !empty($returnTags = $docBlock->getTagsByName('return')) + && $returnTags[0]->getType() !== null + ) { + // Use @return tag + return $returnTags[0]->getType(); + } + if ($node->returnType !== null) { + // Use PHP7 return type hint + if (is_string($node->returnType)) { + // Resolve a string like "bool" to a type object + return $this->typeResolver->resolve($node->returnType); + } + return new Types\Object_(new Fqsen('\\' . (string)$node->returnType)); + } + // Unknown return type + return new Types\Mixed; + } + if ($node instanceof Node\Expr\Variable) { + $node = $node->getAttribute('parentNode'); + } + if ( + $node instanceof Node\Stmt\PropertyProperty + || $node instanceof Node\Const_ + || $node instanceof Node\Expr\Assign + || $node instanceof Node\Expr\AssignOp + ) { + if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { + $docBlockHolder = $node->getAttribute('parentNode'); + } else { + $docBlockHolder = $node; + } + // Property, constant or variable + // Use @var tag + if ( + isset($docBlockHolder) + && ($docBlock = $docBlockHolder->getAttribute('docBlock')) + && !empty($varTags = $docBlock->getTagsByName('var')) + && ($type = $varTags[0]->getType()) + ) { + return $type; + } + // Resolve the expression + if ($node instanceof Node\Stmt\PropertyProperty) { + if ($node->default) { + return $this->resolveExpressionNodeToType($node->default); + } + } else if ($node instanceof Node\Const_) { + return $this->resolveExpressionNodeToType($node->value); + } else { + return $this->resolveExpressionNodeToType($node); + } + // TODO: read @property tags of class + // TODO: Try to infer the type from default value / constant value + // Unknown + return new Types\Mixed; + } + return null; + } + + /** + * Returns the fully qualified name (FQN) that is defined by a node + * Returns null if the node does not declare any symbol that can be referenced by an FQN + * + * @param Node $node + * @return string|null + */ + public static function getDefinedFqn(Node $node) + { + $parent = $node->getAttribute('parentNode'); + // Anonymous classes don't count as a definition + if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { + // Class, interface or trait declaration + return (string)$node->namespacedName; + } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { + return (string)$node; + } else if ($node instanceof Node\Stmt\Function_) { + // Function: use functionName() as the name + return (string)$node->namespacedName . '()'; + } else if ($node instanceof Node\Stmt\ClassMethod) { + // Class method: use ClassName->methodName() as name + $class = $node->getAttribute('parentNode'); + if (!isset($class->name)) { + // Ignore anonymous classes + return null; + } + if ($node->isStatic()) { + return (string)$class->namespacedName . '::' . (string)$node->name . '()'; + } else { + return (string)$class->namespacedName . '->' . (string)$node->name . '()'; + } + } else if ($node instanceof Node\Stmt\PropertyProperty) { + $property = $node->getAttribute('parentNode'); + $class = $property->getAttribute('parentNode'); + if (!isset($class->name)) { + // Ignore anonymous classes + return null; + } + if ($property->isStatic()) { + // Static Property: use ClassName::$propertyName as name + return (string)$class->namespacedName . '::$' . (string)$node->name; + } else { + // Instance Property: use ClassName->propertyName as name + return (string)$class->namespacedName . '->' . (string)$node->name; + } + } else if ($node instanceof Node\Const_) { + $parent = $node->getAttribute('parentNode'); + if ($parent instanceof Node\Stmt\Const_) { + // Basic constant: use CONSTANT_NAME as name + return (string)$node->namespacedName; + } + if ($parent instanceof Node\Stmt\ClassConst) { + // Class constant: use ClassName::CONSTANT_NAME as name + $class = $parent->getAttribute('parentNode'); + if (!isset($class->name) || $class->name instanceof Node\Expr) { + return null; + } + return (string)$class->namespacedName . '::' . $node->name; + } + } + } +} diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index 7243ad30..4dda8768 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -7,7 +7,9 @@ use PhpParser\{NodeTraverser, Node}; use PhpParser\NodeVisitor\NameResolver; use phpDocumentor\Reflection\DocBlockFactory; -use LanguageServer\{LanguageClient, PhpDocument, PhpDocumentLoader, Parser, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, LanguageClient, PhpDocument, PhpDocumentLoader, Parser, DefinitionResolver +}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\ClientCapabilities; use LanguageServer\Index\{ProjectIndex, Index, DependenciesIndex}; @@ -26,7 +28,7 @@ public function testCollectsSymbols() $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = new DefinitionResolver($index); + $definitionResolver = DefinitionResolverFactory::create($index); $content = file_get_contents($path); $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); $stmts = $parser->parse($content); @@ -75,7 +77,7 @@ public function testDoesNotCollectReferences() $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = new DefinitionResolver($index); + $definitionResolver = DefinitionResolverFactory::create($index); $content = file_get_contents($path); $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); $stmts = $parser->parse($content); diff --git a/tests/PhpDocumentLoaderTest.php b/tests/PhpDocumentLoaderTest.php index 7be062d0..76974176 100644 --- a/tests/PhpDocumentLoaderTest.php +++ b/tests/PhpDocumentLoaderTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver +}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Protocol\{ @@ -32,7 +34,7 @@ public function setUp() $this->loader = new PhpDocumentLoader( new FileSystemContentRetriever, $projectIndex, - new DefinitionResolver($projectIndex) + DefinitionResolverFactory::create($projectIndex) ); } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 81f998f3..341e01b0 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase; use phpDocumentor\Reflection\DocBlockFactory; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{LanguageClient, PhpDocument, DefinitionResolver, Parser}; +use LanguageServer\{ + DefinitionResolverFactory, LanguageClient, PhpDocument, DefinitionResolver, Parser +}; use LanguageServer\NodeVisitor\NodeAtPositionFinder; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{SymbolKind, Position, ClientCapabilities}; @@ -23,7 +25,7 @@ public function createDocument(string $uri, string $content) $tolerantParser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = new DefinitionResolver($index); + $definitionResolver = DefinitionResolverFactory::create($index); return new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); } diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 679191f9..75d59d14 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{Server, LanguageClient, PhpDocumentLoader, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver +}; use LanguageServer\Index\{ProjectIndex, StubsIndex, GlobalIndex, DependenciesIndex, Index}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{Position, Location, Range, ClientCapabilities}; @@ -50,7 +52,7 @@ public function setUp() $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = new DefinitionResolver($projectIndex); + $definitionResolver = DefinitionResolverFactory::create($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index dd9e6804..d08ee630 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver +}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex, GlobalIndex, StubsIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{ @@ -36,7 +38,7 @@ public function setUp() { $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); - $definitionResolver = new DefinitionResolver($projectIndex); + $definitionResolver = DefinitionResolverFactory::create($projectIndex); $contentRetriever = new FileSystemContentRetriever; $this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait(); diff --git a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php index f3c0771d..661b222e 100644 --- a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php @@ -5,7 +5,9 @@ use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; -use LanguageServer\{Server, LanguageClient, PhpDocumentLoader, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver +}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{TextDocumentIdentifier, Position, Range, Location, ClientCapabilities}; @@ -18,7 +20,7 @@ public function setUp() $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = new DefinitionResolver($projectIndex); + $definitionResolver = DefinitionResolverFactory::create($projectIndex); $contentRetriever = new FileSystemContentRetriever; $loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/DidChangeTest.php b/tests/Server/TextDocument/DidChangeTest.php index bdd3b22d..4b42ae20 100644 --- a/tests/Server/TextDocument/DidChangeTest.php +++ b/tests/Server/TextDocument/DidChangeTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver +}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Protocol\{ @@ -24,7 +26,7 @@ public function test() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = new DefinitionResolver($projectIndex); + $definitionResolver = DefinitionResolverFactory::create($projectIndex); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $phpDocument = $loader->open('whatever', "open('whatever', "textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); } diff --git a/tests/Server/TextDocument/References/GlobalFallbackTest.php b/tests/Server/TextDocument/References/GlobalFallbackTest.php index ac7b3557..d6a22c22 100644 --- a/tests/Server/TextDocument/References/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/References/GlobalFallbackTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\{Server, LanguageClient, PhpDocumentLoader, DefinitionResolver}; +use LanguageServer\{ + DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver +}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range, ClientCapabilities}; @@ -17,7 +19,7 @@ public function setUp() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = new DefinitionResolver($projectIndex); + $definitionResolver = DefinitionResolverFactory::create($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); From 591ecbd7d3c914b5e128779ca81c0ce3ba97e606 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 1 Mar 2017 15:55:29 -0800 Subject: [PATCH 004/149] Extract static FQN methods to FqnUtilities --- src/CompletionProvider.php | 2 +- src/DefinitionResolver.php | 27 +------------ src/FqnUtilities.php | 53 +++++++++++++++++++++++++ src/NodeVisitor/DefinitionCollector.php | 4 +- src/Server/TextDocument.php | 8 ++-- src/TolerantDefinitionResolver.php | 25 ------------ 6 files changed, 61 insertions(+), 58 deletions(-) create mode 100644 src/FqnUtilities.php diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 93b09a47..5ce8bec8 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -142,7 +142,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi // If the name is an Error node, just filter by the class if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { // For instances, resolve the variable type - $prefixes = DefinitionResolver::getFqnsFromType( + $prefixes = FqnUtilities::getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->var) ); } else { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 67399dda..1692c6ef 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -170,31 +170,6 @@ public function resolveReferenceNodeToDefinition(Node $node) return $this->index->getDefinition($fqn, $globalFallback); } - /** - * Returns all possible FQNs in a type - * - * @param Type $type - * @return string[] - */ - public static function getFqnsFromType(Type $type): array - { - $fqns = []; - if ($type instanceof Types\Object_) { - $fqsen = $type->getFqsen(); - if ($fqsen !== null) { - $fqns[] = substr((string)$fqsen, 1); - } - } - if ($type instanceof Types\Compound) { - for ($i = 0; $t = $type->get($i); $i++) { - foreach (self::getFqnsFromType($type) as $fqn) { - $fqns[] = $fqn; - } - } - } - return $fqns; - } - /** * Given any node, returns the FQN of the symbol that is referenced * Returns null if the FQN could not be resolved or the reference node references a variable @@ -366,7 +341,7 @@ private static function getContainingClassFqn(Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - public static function resolveVariableToNode(Node\Expr $var) + private static function resolveVariableToNode(Node\Expr $var) { $n = $var; // When a use is passed, start outside the closure to not return immediatly diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php new file mode 100644 index 00000000..f4b53754 --- /dev/null +++ b/src/FqnUtilities.php @@ -0,0 +1,53 @@ +getFqsen(); + if ($fqsen !== null) { + $fqns[] = substr((string)$fqsen, 1); + } + } + if ($type instanceof Types\Compound) { + for ($i = 0; $t = $type->get($i); $i++) { + foreach (self::getFqnsFromType($type) as $fqn) { + $fqns[] = $fqn; + } + } + } + return $fqns; + } +} \ No newline at end of file diff --git a/src/NodeVisitor/DefinitionCollector.php b/src/NodeVisitor/DefinitionCollector.php index 57de95f4..7579ce9a 100644 --- a/src/NodeVisitor/DefinitionCollector.php +++ b/src/NodeVisitor/DefinitionCollector.php @@ -5,7 +5,7 @@ use PhpParser\{NodeVisitorAbstract, Node}; use LanguageServer\{ - Definition, DefinitionResolver, DefinitionResolverInterface + Definition, DefinitionResolver, DefinitionResolverInterface, FqnUtilities }; use LanguageServer\Protocol\SymbolInformation; @@ -38,7 +38,7 @@ public function __construct(DefinitionResolverInterface $definitionResolver) public function enterNode(Node $node) { - $fqn = DefinitionResolver::getDefinedFqn($node); + $fqn = FqnUtilities::getDefinedFqn($node); // Only index definitions with an FQN (no variables) if ($fqn === null) { return; diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 55341a39..1d4d0d54 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -5,7 +5,7 @@ use PhpParser\{Node, NodeTraverser}; use LanguageServer\{ - DefinitionResolverInterface, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider + DefinitionResolverInterface, FqnUtilities, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider }; use LanguageServer\NodeVisitor\VariableReferencesCollector; use LanguageServer\Protocol\{ @@ -221,7 +221,7 @@ public function references( } } else { // Definition with a global FQN - $fqn = DefinitionResolver::getDefinedFqn($node); + $fqn = FqnUtilities::getDefinedFqn($node); // Wait until indexing finished if (!$this->index->isComplete()) { yield waitForEvent($this->index, 'complete'); @@ -266,7 +266,7 @@ public function definition(TextDocumentIdentifier $textDocument, Position $posit return []; } // Handle definition nodes - $fqn = DefinitionResolver::getDefinedFqn($node); + $fqn = FqnUtilities::getDefinedFqn($node); while (true) { if ($fqn) { $def = $this->index->getDefinition($fqn); @@ -307,7 +307,7 @@ public function hover(TextDocumentIdentifier $textDocument, Position $position): if ($node === null) { return new Hover([]); } - $definedFqn = DefinitionResolver::getDefinedFqn($node); + $definedFqn = FqnUtilities::getDefinedFqn($node); while (true) { if ($definedFqn) { // Support hover for definitions diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index ebd8e652..23fd7ec2 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -170,31 +170,6 @@ public function resolveReferenceNodeToDefinition(Node $node) return $this->index->getDefinition($fqn, $globalFallback); } - /** - * Returns all possible FQNs in a type - * - * @param Type $type - * @return string[] - */ - public static function getFqnsFromType(Type $type): array - { - $fqns = []; - if ($type instanceof Types\Object_) { - $fqsen = $type->getFqsen(); - if ($fqsen !== null) { - $fqns[] = substr((string)$fqsen, 1); - } - } - if ($type instanceof Types\Compound) { - for ($i = 0; $t = $type->get($i); $i++) { - foreach (self::getFqnsFromType($type) as $fqn) { - $fqns[] = $fqn; - } - } - } - return $fqns; - } - /** * Given any node, returns the FQN of the symbol that is referenced * Returns null if the FQN could not be resolved or the reference node references a variable From b1eb43516d9e58c68eca006371b91db730fe3473 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 1 Mar 2017 16:01:06 -0800 Subject: [PATCH 005/149] update definition resolver interfaces --- src/DefinitionResolver.php | 16 ++++++------ src/DefinitionResolverInterface.php | 38 ++++++++++++++++++----------- src/TolerantDefinitionResolver.php | 16 ++++++------ 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 1692c6ef..426b5522 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -42,7 +42,7 @@ public function __construct(ReadableIndex $index) * @param Node $node * @return string */ - public function getDeclarationLineFromNode(Node $node): string + public function getDeclarationLineFromNode($node): string { if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { // Properties and constants can have multiple declarations @@ -70,7 +70,7 @@ public function getDeclarationLineFromNode(Node $node): string * @param Node $node * @return string|null */ - public function getDocumentationFromNode(Node $node) + public function getDocumentationFromNode($node) { if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { $node = $node->getAttribute('parentNode'); @@ -101,7 +101,7 @@ public function getDocumentationFromNode(Node $node) * @param string $fqn * @return Definition */ - public function createDefinitionFromNode(Node $node, string $fqn = null): Definition + public function createDefinitionFromNode($node, string $fqn = null): Definition { $parent = $node->getAttribute('parentNode'); $def = new Definition; @@ -141,7 +141,7 @@ public function createDefinitionFromNode(Node $node, string $fqn = null): Defini * @param Node $node Any reference node * @return Definition|null */ - public function resolveReferenceNodeToDefinition(Node $node) + public function resolveReferenceNodeToDefinition($node) { // Variables are not indexed globally, as they stay in the file scope anyway if ($node instanceof Node\Expr\Variable) { @@ -177,7 +177,7 @@ public function resolveReferenceNodeToDefinition(Node $node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn(Node $node) + public function resolveReferenceNodeToFqn($node) { $parent = $node->getAttribute('parentNode'); @@ -393,7 +393,7 @@ private static function resolveVariableToNode(Node\Expr $var) * @param \PhpParser\Node\Expr $expr * @return \phpDocumentor\Reflection\Type */ - public function resolveExpressionNodeToType(Node\Expr $expr): Type + public function resolveExpressionNodeToType($expr): Type { if ($expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\ClosureUse) { if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { @@ -691,7 +691,7 @@ private static function resolveClassNameToType(Node $class): Type * @param Node $node * @return \phpDocumentor\Reflection\Type|null */ - public function getTypeFromNode(Node $node) + public function getTypeFromNode($node) { if ($node instanceof Node\Param) { // Parameters @@ -798,7 +798,7 @@ public function getTypeFromNode(Node $node) * @param Node $node * @return string|null */ - public static function getDefinedFqn(Node $node) + public static function getDefinedFqn($node) { $parent = $node->getAttribute('parentNode'); // Anonymous classes don't count as a definition diff --git a/src/DefinitionResolverInterface.php b/src/DefinitionResolverInterface.php index dba49355..767f4e0e 100644 --- a/src/DefinitionResolverInterface.php +++ b/src/DefinitionResolverInterface.php @@ -4,59 +4,60 @@ use phpDocumentor\Reflection\Type; use PhpParser\Node; +use Microsoft\PhpParser as Tolerant; interface DefinitionResolverInterface { /** * Builds the declaration line for a given node * - * @param Node $node + * @param Node | Tolerant\Node $node * @return string */ - public function getDeclarationLineFromNode(Node $node) : string; + public function getDeclarationLineFromNode($node) : string; /** * Gets the documentation string for a node, if it has one * - * @param Node $node + * @param Node | Tolerant\Node $node * @return string|null */ - public function getDocumentationFromNode(Node $node); + public function getDocumentationFromNode($node); /** * Create a Definition for a definition node * - * @param Node $node + * @param Node | Tolerant\Node $node * @param string $fqn * @return Definition */ - public function createDefinitionFromNode(Node $node, string $fqn = null) : Definition; + public function createDefinitionFromNode($node, string $fqn = null) : Definition; /** * Given any node, returns the Definition object of the symbol that is referenced * - * @param Node $node Any reference node + * @param Node | Tolerant\Node $node Any reference node * @return Definition|null */ - public function resolveReferenceNodeToDefinition(Node $node); + public function resolveReferenceNodeToDefinition($node); /** * Given any node, returns the FQN of the symbol that is referenced * Returns null if the FQN could not be resolved or the reference node references a variable * - * @param Node $node + * @param Node | Tolerant\Node $node * @return string|null */ - public function resolveReferenceNodeToFqn(Node $node); + public function resolveReferenceNodeToFqn($node); /** * Given an expression node, resolves that expression recursively to a type. * If the type could not be resolved, returns Types\Mixed. * - * @param \PhpParser\Node\Expr $expr + * @param \PhpParser\Node\Expr | Tolerant\Node $expr * @return \phpDocumentor\Reflection\Type */ - public function resolveExpressionNodeToType(Node\Expr $expr) : Type; + public function resolveExpressionNodeToType($expr) : Type; /** * Returns the type a reference to this symbol will resolve to. @@ -69,8 +70,17 @@ public function resolveExpressionNodeToType(Node\Expr $expr) : Type; * If it is unknown, will be Types\Mixed. * Returns null if the node does not have a type. * - * @param Node $node + * @param Node | Tolerant\Node $node * @return \phpDocumentor\Reflection\Type|null */ - public function getTypeFromNode(Node $node); + public function getTypeFromNode($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 + * + * @param Node | Tolerant\Node $node + * @return string|null + */ + public static function getDefinedFqn($node); } \ No newline at end of file diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 23fd7ec2..e09a6ca7 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -42,7 +42,7 @@ public function __construct(ReadableIndex $index) * @param Node $node * @return string */ - public function getDeclarationLineFromNode(Node $node): string + public function getDeclarationLineFromNode($node): string { if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { // Properties and constants can have multiple declarations @@ -70,7 +70,7 @@ public function getDeclarationLineFromNode(Node $node): string * @param Node $node * @return string|null */ - public function getDocumentationFromNode(Node $node) + public function getDocumentationFromNode($node) { if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { $node = $node->getAttribute('parentNode'); @@ -101,7 +101,7 @@ public function getDocumentationFromNode(Node $node) * @param string $fqn * @return Definition */ - public function createDefinitionFromNode(Node $node, string $fqn = null): Definition + public function createDefinitionFromNode($node, string $fqn = null): Definition { $parent = $node->getAttribute('parentNode'); $def = new Definition; @@ -141,7 +141,7 @@ public function createDefinitionFromNode(Node $node, string $fqn = null): Defini * @param Node $node Any reference node * @return Definition|null */ - public function resolveReferenceNodeToDefinition(Node $node) + public function resolveReferenceNodeToDefinition($node) { // Variables are not indexed globally, as they stay in the file scope anyway if ($node instanceof Node\Expr\Variable) { @@ -177,7 +177,7 @@ public function resolveReferenceNodeToDefinition(Node $node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn(Node $node) + public function resolveReferenceNodeToFqn($node) { $parent = $node->getAttribute('parentNode'); @@ -393,7 +393,7 @@ public static function resolveVariableToNode(Node\Expr $var) * @param \PhpParser\Node\Expr $expr * @return \phpDocumentor\Reflection\Type */ - public function resolveExpressionNodeToType(Node\Expr $expr): Type + public function resolveExpressionNodeToType($expr): Type { if ($expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\ClosureUse) { if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { @@ -691,7 +691,7 @@ private static function resolveClassNameToType(Node $class): Type * @param Node $node * @return \phpDocumentor\Reflection\Type|null */ - public function getTypeFromNode(Node $node) + public function getTypeFromNode($node) { if ($node instanceof Node\Param) { // Parameters @@ -798,7 +798,7 @@ public function getTypeFromNode(Node $node) * @param Node $node * @return string|null */ - public static function getDefinedFqn(Node $node) + public static function getDefinedFqn($node) { $parent = $node->getAttribute('parentNode'); // Anonymous classes don't count as a definition From e7b04f751869e0a4aae7c133f4152d113fbdf0d1 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 1 Mar 2017 16:14:13 -0800 Subject: [PATCH 006/149] extract symbol information --- src/Protocol/SymbolInformation.php | 2 +- src/Protocol/TolerantSymbolInformation.php | 73 ++++++++++++++++++++++ src/TolerantDefinitionResolver.php | 3 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/Protocol/TolerantSymbolInformation.php diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index 5d442f0b..a608ebd4 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -46,7 +46,7 @@ class SymbolInformation * @param string $fqn If given, $containerName will be extracted from it * @return self|null */ - public static function fromNode(Node $node, string $fqn = null) + public static function fromNode($node, string $fqn = null) { $parent = $node->getAttribute('parentNode'); $symbol = new self; diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php new file mode 100644 index 00000000..df86df10 --- /dev/null +++ b/src/Protocol/TolerantSymbolInformation.php @@ -0,0 +1,73 @@ +getAttribute('parentNode'); + $symbol = new self; + if ($node instanceof Node\Stmt\Class_) { + $symbol->kind = SymbolKind::CLASS_; + } else if ($node instanceof Node\Stmt\Trait_) { + $symbol->kind = SymbolKind::CLASS_; + } else if ($node instanceof Node\Stmt\Interface_) { + $symbol->kind = SymbolKind::INTERFACE; + } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { + $symbol->kind = SymbolKind::NAMESPACE; + } else if ($node instanceof Node\Stmt\Function_) { + $symbol->kind = SymbolKind::FUNCTION; + } else if ($node instanceof Node\Stmt\ClassMethod) { + $symbol->kind = SymbolKind::METHOD; + } else if ($node instanceof Node\Stmt\PropertyProperty) { + $symbol->kind = SymbolKind::PROPERTY; + } else if ($node instanceof Node\Const_) { + $symbol->kind = SymbolKind::CONSTANT; + } else if ( + ( + ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) + && $node->var instanceof Node\Expr\Variable + ) + || $node instanceof Node\Expr\ClosureUse + || $node instanceof Node\Param + ) { + $symbol->kind = SymbolKind::VARIABLE; + } else { + return null; + } + if ($node instanceof Node\Name) { + $symbol->name = (string)$node; + } else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { + $symbol->name = $node->var->name; + } else if ($node instanceof Node\Expr\ClosureUse) { + $symbol->name = $node->var; + } else if (isset($node->name)) { + $symbol->name = (string)$node->name; + } else { + return null; + } + $symbol->location = Location::fromNode($node); + if ($fqn !== null) { + $parts = preg_split('/(::|->|\\\\)/', $fqn); + array_pop($parts); + $symbol->containerName = implode('\\', $parts); + } + return $symbol; + } +} diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index e09a6ca7..65f1f2f8 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -3,6 +3,7 @@ namespace LanguageServer; +use LanguageServer\Protocol\TolerantSymbolInformation; use PhpParser\Node; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; @@ -128,7 +129,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition $def->extends[] = (string)$n; } } - $def->symbolInformation = SymbolInformation::fromNode($node, $fqn); + $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); $def->type = $this->getTypeFromNode($node); $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); From 2280e7889b9638ffb584f248d632eed2bf51a371 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sat, 4 Mar 2017 17:44:04 -0800 Subject: [PATCH 007/149] extract to tree analyzer interface --- src/PhpDocument.php | 74 ++++++++----------------- src/TreeAnalyzer.php | 125 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 52 deletions(-) create mode 100644 src/TreeAnalyzer.php diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 25f210dd..f382b3d9 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -96,11 +96,19 @@ class PhpDocument */ private $diagnostics; + /** + * Microsoft\PhpParser\Parser instance + * + * @var Tolerant\Parser + */ + private $tolerantParser; + /** * @param string $uri The URI of the document * @param string $content The content of the document * @param Index $index The Index to register definitions and references to * @param Parser $parser The PHPParser instance + * @param Parser $tolerantParser The tolerant PHP Parser instance * @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks * @param DefinitionResolverInterface $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace */ @@ -163,64 +171,26 @@ public function updateContent(string $content) $this->definitions = null; $this->definitionNodes = null; - $errorHandler = new ErrorHandler\Collecting; - $stmts = $this->parser->parse($content, $errorHandler); - - $this->diagnostics = []; - foreach ($errorHandler->getErrors() as $error) { - $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::ERROR, 'php'); - } - - // $stmts can be null in case of a fatal parsing error <- Interesting. When do fatal parsing errors occur? - if ($stmts) { - $traverser = new NodeTraverser; - - // Resolve aliased names to FQNs - $traverser->addVisitor(new NameResolver($errorHandler)); - - // Add parentNode, previousSibling, nextSibling attributes - $traverser->addVisitor(new ReferencesAdder($this)); + $treeAnalyzer = new TreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); - // Add column attributes to nodes - $traverser->addVisitor(new ColumnCalculator($content)); + $this->diagnostics = $treeAnalyzer->getDiagnostics(); - // Parse docblocks and add docBlock attributes to nodes - $docBlockParser = new DocBlockParser($this->docBlockFactory); - $traverser->addVisitor($docBlockParser); + $this->definitions = $treeAnalyzer->getDefinitions(); - $traverser->traverse($stmts); + $this->definitionNodes = $treeAnalyzer->getDefinitionNodes(); - // Report errors from parsing docblocks - foreach ($docBlockParser->errors as $error) { - $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::WARNING, 'php'); - } - - $traverser = new NodeTraverser; - - // Collect all definitions - $definitionCollector = new DefinitionCollector($this->definitionResolver); - $traverser->addVisitor($definitionCollector); - - // Collect all references - $referencesCollector = new ReferencesCollector($this->definitionResolver); - $traverser->addVisitor($referencesCollector); - - $traverser->traverse($stmts); - - // Register this document on the project for all the symbols defined in it - $this->definitions = $definitionCollector->definitions; - $this->definitionNodes = $definitionCollector->nodes; - foreach ($definitionCollector->definitions as $fqn => $definition) { - $this->index->setDefinition($fqn, $definition); - } - // Register this document on the project for references - $this->referenceNodes = $referencesCollector->nodes; - foreach ($referencesCollector->nodes as $fqn => $nodes) { - $this->index->addReferenceUri($fqn, $this->uri); - } + $this->referenceNodes = $treeAnalyzer->getReferenceNodes(); + + foreach ($this->definitions as $fqn => $definition) { + $this->index->setDefinition($fqn, $definition); + } - $this->stmts = $stmts; + // Register this document on the project for references + foreach ($this->referenceNodes as $fqn => $nodes) { + $this->index->addReferenceUri($fqn, $this->uri); } + + $this->stmts = $treeAnalyzer->getStmts(); } /** diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php new file mode 100644 index 00000000..def47c68 --- /dev/null +++ b/src/TreeAnalyzer.php @@ -0,0 +1,125 @@ +uri = $uri; + $this->parser = $parser; + $this->docBlockFactory = $docBlockFactory; + $this->definitionResolver = $definitionResolver; + $this->content = $content; + $errorHandler = new ErrorHandler\Collecting; + $stmts = $this->parser->parse($content, $errorHandler); + + $this->diagnostics = []; + foreach ($errorHandler->getErrors() as $error) { + $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::ERROR, 'php'); + } + + // $stmts can be null in case of a fatal parsing error <- Interesting. When do fatal parsing errors occur? + if ($stmts) { + $traverser = new NodeTraverser; + + // Resolve aliased names to FQNs + $traverser->addVisitor(new NameResolver($errorHandler)); + + // Add parentNode, previousSibling, nextSibling attributes + $traverser->addVisitor(new ReferencesAdder($this)); + + // Add column attributes to nodes + $traverser->addVisitor(new ColumnCalculator($content)); + + // Parse docblocks and add docBlock attributes to nodes + $docBlockParser = new DocBlockParser($this->docBlockFactory); + $traverser->addVisitor($docBlockParser); + + $traverser->traverse($stmts); + + // Report errors from parsing docblocks + foreach ($docBlockParser->errors as $error) { + $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::WARNING, 'php'); + } + + $traverser = new NodeTraverser; + + // Collect all definitions + $definitionCollector = new DefinitionCollector($this->definitionResolver); + $traverser->addVisitor($definitionCollector); + + // Collect all references + $referencesCollector = new ReferencesCollector($this->definitionResolver); + $traverser->addVisitor($referencesCollector); + + $traverser->traverse($stmts); + + // Register this document on the project for all the symbols defined in it + $this->definitions = $definitionCollector->definitions; + $this->definitionNodes = $definitionCollector->nodes; + foreach ($definitionCollector->definitions as $fqn => $definition) { + // $this->index->setDefinition($fqn, $definition); + } + // Register this document on the project for references + $this->referenceNodes = $referencesCollector->nodes; + foreach ($referencesCollector->nodes as $fqn => $nodes) { + // $this->index->addReferenceUri($fqn, $this->uri); + } + + $this->stmts = $stmts; + } + } + + public function getDiagnostics() { + return $this->diagnostics; + } + + public function getDefinitions() { + return $this->definitions ?? []; + } + + public function getDefinitionNodes() { + return $this->definitionNodes ?? []; + } + + public function getReferenceNodes() { + return $this->referenceNodes ?? []; + } + + public function getStmts() { + return $this->stmts; + } + /** + * Returns the URI of the document + * + * @return string + */ + public function getUri(): string + { + return $this->uri; + } +} From 722898f74d1d0ba0f2f44354d0206d4c0fe57bf8 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sat, 4 Mar 2017 18:36:17 -0800 Subject: [PATCH 008/149] refactor --- src/ComposerScripts.php | 7 +- src/DefinitionResolverFactory.php | 19 ---- src/LanguageServer.php | 2 +- src/ParserResourceFactory.php | 26 ++++++ src/PhpDocument.php | 18 ++-- src/PhpDocumentLoader.php | 4 +- src/TolerantTreeAnalyzer.php | 88 +++++++++++++++++++ src/TreeAnalyzer.php | 2 +- src/TreeAnalyzerInterface.php | 34 +++++++ tests/NodeVisitor/DefinitionCollectorTest.php | 16 ++-- tests/PhpDocumentLoaderTest.php | 4 +- tests/PhpDocumentTest.php | 9 +- tests/Server/ServerTestCase.php | 4 +- tests/Server/TextDocument/CompletionTest.php | 4 +- .../Definition/GlobalFallbackTest.php | 4 +- tests/Server/TextDocument/DidChangeTest.php | 4 +- tests/Server/TextDocument/DidCloseTest.php | 4 +- tests/Server/TextDocument/FormattingTest.php | 4 +- tests/Server/TextDocument/ParseErrorsTest.php | 4 +- .../References/GlobalFallbackTest.php | 4 +- 20 files changed, 189 insertions(+), 72 deletions(-) delete mode 100644 src/DefinitionResolverFactory.php create mode 100644 src/ParserResourceFactory.php create mode 100644 src/TolerantTreeAnalyzer.php create mode 100644 src/TreeAnalyzerInterface.php diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index 717af195..6109fb21 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -30,9 +30,8 @@ public static function parseStubs() $finder = new FileSystemFilesFinder; $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); - $parser = new Parser; - $tolerantParser = new Tolerant\Parser(); - $definitionResolver = DefinitionResolverFactory::create($index); + $parser = ParserResourceFactory::getParser(); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $stubsLocation = null; foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) { @@ -57,7 +56,7 @@ public static function parseStubs() $parts['scheme'] = 'phpstubs'; $uri = Uri\build($parts); - $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); + $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); } $index->setComplete(); diff --git a/src/DefinitionResolverFactory.php b/src/DefinitionResolverFactory.php deleted file mode 100644 index ee64b4f8..00000000 --- a/src/DefinitionResolverFactory.php +++ /dev/null @@ -1,19 +0,0 @@ -globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex); // The DefinitionResolver should look in stubs, the project source and dependencies - $this->definitionResolver = DefinitionResolverFactory::create($this->globalIndex); + $this->definitionResolver = ParserResourceFactory::getDefinitionResolver($this->globalIndex); $this->documentLoader = new PhpDocumentLoader( $this->contentRetriever, diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php new file mode 100644 index 00000000..60778484 --- /dev/null +++ b/src/ParserResourceFactory.php @@ -0,0 +1,26 @@ +uri = $uri; $this->index = $index; $this->parser = $parser; - $this->tolerantParser = $tolerantParser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; $this->updateContent($content); @@ -171,7 +161,11 @@ public function updateContent(string $content) $this->definitions = null; $this->definitionNodes = null; - $treeAnalyzer = new TreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); + $treeAnalyzerClass = $this->parser instanceof Parser + ? TreeAnalyzer::class + : TolerantTreeAnalyzer::class; + + $treeAnalyzer = new $treeAnalyzerClass($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); $this->diagnostics = $treeAnalyzer->getDiagnostics(); diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index b49e63de..88ed5253 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -65,8 +65,7 @@ public function __construct( $this->contentRetriever = $contentRetriever; $this->projectIndex = $projectIndex; $this->definitionResolver = $definitionResolver; - $this->parser = new Parser; - $this->tolerantParser = new Tolerant\Parser(); + $this->parser = ParserResourceFactory::getParser(); $this->docBlockFactory = DocBlockFactory::createInstance(); } @@ -137,7 +136,6 @@ public function create(string $uri, string $content): PhpDocument $content, $this->projectIndex->getIndexForUri($uri), $this->parser, - $this->tolerantParser, $this->docBlockFactory, $this->definitionResolver ); diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php new file mode 100644 index 00000000..095281d8 --- /dev/null +++ b/src/TolerantTreeAnalyzer.php @@ -0,0 +1,88 @@ +uri = $uri; + $this->parser = $parser; + $this->docBlockFactory = $docBlockFactory; + $this->definitionResolver = $definitionResolver; + $this->content = $content; + $this->$stmts = $this->parser->parse($content); + + // TODO - docblock errors + + foreach ($this->stmts->getDescendantNodes() as $node) { + $fqn = DefinitionResolver::getDefinedFqn($node); + // Only index definitions with an FQN (no variables) + if ($fqn === null) { + continue; + } + $this->definitionNodes[$fqn] = $node; + $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + } + } + + public function getDiagnostics() { + $diagnostics = []; + foreach (Tolerant\DiagnosticsProvider::getDiagnostics($tolerantStmts) as $_error) { + $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); + + $diagnostics[] = new Diagnostic( + $_error->message, + new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->start->character) + ) + ); + } + return $diagnostics; + } + + public function getDefinitions() { + return $this->definitions ?? []; + } + + public function getDefinitionNodes() { + return $this->definitionNodes ?? []; + } + + public function getReferenceNodes() { + return $this->referenceNodes ?? []; + } + + public function getStmts() { + return $this->stmts; + } + /** + * Returns the URI of the document + * + * @return string + */ + public function getUri(): string + { + return $this->uri; + } +} diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index def47c68..d4f4d5e1 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -19,7 +19,7 @@ use Sabre\Uri; use Microsoft\PhpParser as Tolerant; -class TreeAnalyzer { +class TreeAnalyzer implements TreeAnalyzerInterface { private $parser; private $stmts; diff --git a/src/TreeAnalyzerInterface.php b/src/TreeAnalyzerInterface.php new file mode 100644 index 00000000..695ac41c --- /dev/null +++ b/src/TreeAnalyzerInterface.php @@ -0,0 +1,34 @@ +parse($content); $traverser = new NodeTraverser; @@ -73,13 +72,12 @@ public function testDoesNotCollectReferences() { $path = realpath(__DIR__ . '/../../fixtures/references.php'); $uri = pathToUri($path); - $parser = new Parser; - $tolerantParser = new Tolerant\Parser(); + $parser = ParserResourceFactory::getParser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = DefinitionResolverFactory::create($index); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $content = file_get_contents($path); - $document = new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); + $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); $stmts = $parser->parse($content); $traverser = new NodeTraverser; diff --git a/tests/PhpDocumentLoaderTest.php b/tests/PhpDocumentLoaderTest.php index 76974176..8ae56d84 100644 --- a/tests/PhpDocumentLoaderTest.php +++ b/tests/PhpDocumentLoaderTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver + ParserResourceFactory, Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; @@ -34,7 +34,7 @@ public function setUp() $this->loader = new PhpDocumentLoader( new FileSystemContentRetriever, $projectIndex, - DefinitionResolverFactory::create($projectIndex) + ParserResourceFactory::getDefinitionResolver($projectIndex) ); } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 341e01b0..94399f0c 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -7,7 +7,7 @@ use phpDocumentor\Reflection\DocBlockFactory; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, LanguageClient, PhpDocument, DefinitionResolver, Parser + ParserResourceFactory, LanguageClient, PhpDocument, DefinitionResolver, Parser }; use LanguageServer\NodeVisitor\NodeAtPositionFinder; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -21,12 +21,11 @@ class PhpDocumentTest extends TestCase { public function createDocument(string $uri, string $content) { - $parser = new Parser; - $tolerantParser = new Tolerant\Parser(); + $parser = ParserResourceFactory::getParser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = DefinitionResolverFactory::create($index); - return new PhpDocument($uri, $content, $index, $parser, $tolerantParser, $docBlockFactory, $definitionResolver); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); } public function testParsesVariableVariables() diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 75d59d14..0dcac39f 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{ProjectIndex, StubsIndex, GlobalIndex, DependenciesIndex, Index}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -52,7 +52,7 @@ public function setUp() $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = DefinitionResolverFactory::create($projectIndex); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index d08ee630..a48ab952 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver + ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex, GlobalIndex, StubsIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -38,7 +38,7 @@ public function setUp() { $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); - $definitionResolver = DefinitionResolverFactory::create($projectIndex); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait(); diff --git a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php index 661b222e..b0510f66 100644 --- a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php @@ -6,7 +6,7 @@ use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; use LanguageServer\{ - DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -20,7 +20,7 @@ public function setUp() $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = DefinitionResolverFactory::create($projectIndex); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/DidChangeTest.php b/tests/Server/TextDocument/DidChangeTest.php index 4b42ae20..3e66e940 100644 --- a/tests/Server/TextDocument/DidChangeTest.php +++ b/tests/Server/TextDocument/DidChangeTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver + ParserResourceFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; @@ -26,7 +26,7 @@ public function test() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = DefinitionResolverFactory::create($projectIndex); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $phpDocument = $loader->open('whatever', "open('whatever', "textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); } diff --git a/tests/Server/TextDocument/References/GlobalFallbackTest.php b/tests/Server/TextDocument/References/GlobalFallbackTest.php index d6a22c22..1fc9daa1 100644 --- a/tests/Server/TextDocument/References/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/References/GlobalFallbackTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - DefinitionResolverFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -19,7 +19,7 @@ public function setUp() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = DefinitionResolverFactory::create($projectIndex); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); From 15eed5515853d8f99974d3849cc97a9bcf61db8c Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sat, 4 Mar 2017 20:56:01 -0800 Subject: [PATCH 009/149] Symbol support for Microsoft/tolerant-php-parser --- src/ParserResourceFactory.php | 2 +- src/Protocol/Location.php | 15 +- src/Protocol/TolerantSymbolInformation.php | 52 +++-- src/TolerantDefinitionResolver.php | 260 ++++++++++++++------- src/TolerantTreeAnalyzer.php | 18 +- src/TreeAnalyzer.php | 2 +- src/TreeAnalyzerInterface.php | 2 +- tests/Server/ServerTestCase.php | 4 +- tests/Server/Workspace/SymbolTest.php | 2 +- 9 files changed, 241 insertions(+), 116 deletions(-) diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 60778484..8aac4a47 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,7 +6,7 @@ use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::PHP_PARSER; + const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; public function getParser() { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { diff --git a/src/Protocol/Location.php b/src/Protocol/Location.php index a1d98616..6cafecdd 100644 --- a/src/Protocol/Location.php +++ b/src/Protocol/Location.php @@ -3,6 +3,7 @@ namespace LanguageServer\Protocol; use PhpParser\Node; +use Microsoft\PhpParser as Tolerant; /** * Represents a location inside a resource, such as a line inside a text file. @@ -22,12 +23,20 @@ class Location /** * Returns the location of the node * - * @param Node $node + * @param Node | Tolerant\Node $node * @return self */ - public static function fromNode(Node $node) + public static function fromNode($node) { - return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($node)); + if ($node instanceof Node) { + return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($node)); + } else { + $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); + return new self($node->getUri(), new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + )); + } } public function __construct(string $uri = null, Range $range = null) diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php index df86df10..54504185 100644 --- a/src/Protocol/TolerantSymbolInformation.php +++ b/src/Protocol/TolerantSymbolInformation.php @@ -10,58 +10,66 @@ * Represents information about programming constructs like variables, classes, * interfaces etc. */ -class TolerantSymbolInformation extends SymbolInformation +class TolerantSymbolInformation { /** * Converts a Node to a SymbolInformation * * @param Tolerant\Node $node * @param string $fqn If given, $containerName will be extracted from it - * @return self|null + * @return SymbolInformation|null */ public static function fromNode($node, string $fqn = null) { - $parent = $node->getAttribute('parentNode'); - $symbol = new self; - if ($node instanceof Node\Stmt\Class_) { + $symbol = new SymbolInformation(); + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Trait_) { + } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Interface_) { + } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $symbol->kind = SymbolKind::INTERFACE; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { + } else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { $symbol->kind = SymbolKind::NAMESPACE; - } else if ($node instanceof Node\Stmt\Function_) { + } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { $symbol->kind = SymbolKind::FUNCTION; - } else if ($node instanceof Node\Stmt\ClassMethod) { + } else if ($node instanceof Tolerant\Node\MethodDeclaration) { $symbol->kind = SymbolKind::METHOD; - } else if ($node instanceof Node\Stmt\PropertyProperty) { + } else if ($node instanceof Tolerant\Node\Expression\Variable && $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class) !== null) { $symbol->kind = SymbolKind::PROPERTY; - } else if ($node instanceof Node\Const_) { + } else if ($node instanceof Tolerant\Node\ConstElement) { $symbol->kind = SymbolKind::CONSTANT; - } else if ( + } + + else if ( ( - ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) - && $node->var instanceof Node\Expr\Variable + ($node instanceof Tolerant\Node\Expression\AssignmentExpression) + && $node->leftOperand instanceof Tolerant\Node\Expression\Variable ) - || $node instanceof Node\Expr\ClosureUse - || $node instanceof Node\Param + || $node instanceof Tolerant\Node\UseVariableName + || $node instanceof Tolerant\Node\Parameter ) { $symbol->kind = SymbolKind::VARIABLE; } else { return null; } + if ($node instanceof Node\Name) { $symbol->name = (string)$node; - } else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { - $symbol->name = $node->var->name; - } else if ($node instanceof Node\Expr\ClosureUse) { - $symbol->name = $node->var; + } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { + $symbol->name = $node->leftOperand->getName(); + } elseif ($node->leftOperand instanceof Tolerant\Token) { + $symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$"); + } + + } else if ($node instanceof Tolerant\Node\UseVariableName) { + $symbol->name = $node->getName(); } else if (isset($node->name)) { - $symbol->name = (string)$node->name; + $symbol->name = trim((string)$node->name->getText($node->getFileContents()), "$"); } else { return null; } + $symbol->location = Location::fromNode($node); if ($fqn !== null) { $parts = preg_split('/(::|->|\\\\)/', $fqn); diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 65f1f2f8..6b0ba784 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -6,9 +6,12 @@ use LanguageServer\Protocol\TolerantSymbolInformation; use PhpParser\Node; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; -use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; +use phpDocumentor\Reflection\{ + DocBlockFactory, Types, Type, Fqsen, TypeResolver +}; use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; +use Microsoft\PhpParser as Tolerant; class TolerantDefinitionResolver implements DefinitionResolverInterface { @@ -38,99 +41,157 @@ public function __construct(ReadableIndex $index) } /** - * Builds the declaration line for a given node + * Builds the declaration line for a given node. * - * @param Node $node + * + * @param Tolerant\Node $node * @return string */ public function getDeclarationLineFromNode($node): string { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - // Properties and constants can have multiple declarations - // Use the parent node (that includes the modifiers), but only render the requested declaration - $child = $node; - /** @var Node */ - $node = $node->getAttribute('parentNode'); - $defLine = clone $node; - $defLine->props = [$child]; - } else { - $defLine = clone $node; + // TODO Tolerant\Node\Statement\FunctionStaticDeclaration::class + + // we should have a better way of determining whether something is a property or constant + // If part of a declaration list -> get the parent declaration + if ( + // PropertyDeclaration // public $a, $b, $c; + $node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null + ) { + $defLine = $propertyDeclaration->getText(); + $defLineStart = $propertyDeclaration->getStart(); + + $defLine = \substr_replace( + $defLine, + $node->getFullText(), + $propertyDeclaration->propertyElements->getFullStart() - $defLineStart, + $propertyDeclaration->propertyElements->getWidth() + ); + } elseif ( + // ClassConstDeclaration or ConstDeclaration // const A = 1, B = 2; + $node instanceof Tolerant\Node\ConstElement && + ($constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class)) + ) { + $defLine = $constDeclaration->getText(); + $defLineStart = $constDeclaration->getStart(); + + $defLine = \substr_replace( + $defLine, + $node->getFullText(), + $constDeclaration->constElements->getFullStart() - $defLineStart, + $constDeclaration->constElements->getWidth() + ); } - // Don't include the docblock in the declaration string - $defLine->setAttribute('comments', []); - if (isset($defLine->stmts)) { - $defLine->stmts = []; + + // Get the current node + else { + $defLine = $node->getText(); } - $defText = $this->prettyPrinter->prettyPrint([$defLine]); - return strstr($defText, "\n", true) ?: $defText; + + $defLine = \strtok($defLine, "\n"); + + return $defLine; } /** * Gets the documentation string for a node, if it has one * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public function getDocumentationFromNode($node) { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - $node = $node->getAttribute('parentNode'); + // For properties and constants, set the node to the declaration node, rather than the individual property. + // This is because they get defined as part of a list. + $constOrPropertyDeclaration = $node->getFirstAncestor( + Tolerant\Node\PropertyDeclaration::class, + Tolerant\Node\Statement\ConstDeclaration::class, + Tolerant\Node\ClassConstDeclaration::class + ); + if ($constOrPropertyDeclaration !== null) { + $node = $constOrPropertyDeclaration; } - if ($node instanceof Node\Param) { - $fn = $node->getAttribute('parentNode'); - $docBlock = $fn->getAttribute('docBlock'); + + // For parameters, parse the documentation to get the parameter tag. + if ($node instanceof Tolerant\Node\Parameter) { + $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); + $variableName = $node->variableName->getText($node->getFileContents()); + $docBlock = $this->getDocBlock($functionLikeDeclaration); + if ($docBlock !== null) { - $tags = $docBlock->getTagsByName('param'); - foreach ($tags as $tag) { - if ($tag->getVariableName() === $node->name) { - return $tag->getDescription()->render(); - } - } + $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); + return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; + } - } else { - $docBlock = $node->getAttribute('docBlock'); + } + // for everything else, get the doc block summary corresponding to the current node. + else { + $docBlock = $this->getDocBlock($node); if ($docBlock !== null) { return $docBlock->getSummary(); } } } + function getDocBlock(Tolerant\Node $node) { + // TODO context information + static $docBlockFactory; + $docBlockFactory = $docBlockFactory ?? DocBlockFactory::createInstance(); + $docCommentText = $node->getDocCommentText(); + return $docCommentText !== null ? $docBlockFactory->create($docCommentText) : null; + } + /** * Create a Definition for a definition node * - * @param Node $node + * @param Tolerant\Node $node * @param string $fqn * @return Definition */ public function createDefinitionFromNode($node, string $fqn = null): Definition { - $parent = $node->getAttribute('parentNode'); $def = new Definition; - $def->canBeInstantiated = $node instanceof Node\Stmt\Class_; + + // this determines whether the suggestion will show after "new" + $def->isClass = $node instanceof Tolerant\Node\Statement\ClassDeclaration; + $def->isGlobal = ( - $node instanceof Node\Stmt\ClassLike - || ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) - || $node instanceof Node\Stmt\Function_ - || $parent instanceof Node\Stmt\Const_ + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration + || $node instanceof Tolerant\Node\Statement\ClassDeclaration + || $node instanceof Tolerant\Node\Statement\TraitDeclaration + + || $node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null + + || $node instanceof Tolerant\Node\Statement\FunctionDeclaration + + || $node instanceof Tolerant\Node\Statement\ConstDeclaration + || $node instanceof Tolerant\Node\ClassConstDeclaration ); + $def->isStatic = ( - ($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) - || ($node instanceof Node\Stmt\PropertyProperty && $parent->isStatic()) + ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) + || ($node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && + $propertyDeclaration->isStatic()) ); $def->fqn = $fqn; - if ($node instanceof Node\Stmt\Class_) { + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $def->extends = []; - if ($node->extends) { - $def->extends[] = (string)$node->extends; + if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { + $def->extends[] = (string)$node->classBaseClause->baseClass; } - } else if ($node instanceof Node\Stmt\Interface_) { + // TODO what about class interfaces + } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $def->extends = []; - foreach ($node->extends as $n) { - $def->extends[] = (string)$n; + if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { + foreach ($node->interfaceBaseClause->interfaceNameList->getChildNodes() as $n) { + $def->extends[] = (string)$n; + } } } $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); - $def->type = $this->getTypeFromNode($node); +// $def->type = $this->getTypeFromNode($node); //TODO + $def->type = new Types\Mixed; $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); return $def; @@ -796,60 +857,97 @@ public function getTypeFromNode($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 * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public static function getDefinedFqn($node) { - $parent = $node->getAttribute('parentNode'); + $parent = $node->getParent(); // Anonymous classes don't count as a definition - if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { - // Class, interface or trait declaration - return (string)$node->namespacedName; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { - return (string)$node; - } else if ($node instanceof Node\Stmt\Function_) { + // INPUT OUTPUT: + // namespace A\B; + // class C { } A\B\C + // interface C { } A\B\C + // trait C { } A\B\C + if ( + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration + ) { + return (string) $node->getNamespacedName(); + } + + // INPUT OUTPUT: + // namespace A\B; A\B + else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { + return (string) $node->name; + } + // INPUT OUTPUT: + // namespace A\B; + // function a(); A\B\a(); + else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name - return (string)$node->namespacedName . '()'; - } else if ($node instanceof Node\Stmt\ClassMethod) { + return (string)$node->getNamespacedName() . '()'; + } + // INPUT OUTPUT + // namespace A\B; + // class C { + // function a () {} A\B\C::a() + // static function b() {} A\B\C->b() + // } + else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name - $class = $node->getAttribute('parentNode'); + $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); if (!isset($class->name)) { // Ignore anonymous classes return null; } if ($node->isStatic()) { - return (string)$class->namespacedName . '::' . (string)$node->name . '()'; + return (string)$class->getNamespacedName() . '::' . $node->getName() . '()'; } else { - return (string)$class->namespacedName . '->' . (string)$node->name . '()'; - } - } else if ($node instanceof Node\Stmt\PropertyProperty) { - $property = $node->getAttribute('parentNode'); - $class = $property->getAttribute('parentNode'); - if (!isset($class->name)) { - // Ignore anonymous classes - return null; + return (string)$class->getNamespacedName() . '->' . $node->getName() . '()'; } - if ($property->isStatic()) { + } + + // INPUT OUTPUT + // namespace A\B; + // class C { + // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b + // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b + // } + else if ( + $node instanceof Tolerant\Node\Expression\Variable && + ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && + ($classDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class)) !== null) + { + if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name - return (string)$class->namespacedName . '::$' . (string)$node->name; - } else { + return (string)$classDeclaration->getNamespacedName() . '::$' . (string)$node->getName(); + } elseif (($name = $node->getName()) !== null) { // Instance Property: use ClassName->propertyName as name - return (string)$class->namespacedName . '->' . (string)$node->name; + return (string)$classDeclaration->getNamespacedName() . '->' . $name; } - } else if ($node instanceof Node\Const_) { - $parent = $node->getAttribute('parentNode'); - if ($parent instanceof Node\Stmt\Const_) { + } + + // INPUT OUTPUT + // namespace A\B; + // const FOO = 5; A\B\FOO + // class C { + // const $a, $b = 4 A\B\C::$a(), A\B\C::$b + // } + else if ($node instanceof Tolerant\Node\ConstElement) { + $constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class); + if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name - return (string)$node->namespacedName; + return (string)$node->getNamespacedName(); } - if ($parent instanceof Node\Stmt\ClassConst) { + if ($constDeclaration instanceof Tolerant\Node\ClassConstDeclaration) { // Class constant: use ClassName::CONSTANT_NAME as name - $class = $parent->getAttribute('parentNode'); - if (!isset($class->name) || $class->name instanceof Node\Expr) { + $classDeclaration = $constDeclaration->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if (!isset($classDeclaration->name)) { return null; } - return (string)$class->namespacedName . '::' . $node->name; + return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); } } } diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 095281d8..1d94d094 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -22,20 +22,29 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface { private $parser; + /** @var Tolerant\Node */ private $stmts; - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri) { + /** + * TolerantTreeAnalyzer constructor. + * @param Tolerant\Parser $parser + * @param $content + * @param $docBlockFactory + * @param TolerantDefinitionResolver $definitionResolver + * @param $uri + */ + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; $this->content = $content; - $this->$stmts = $this->parser->parse($content); + $this->stmts = $this->parser->parseSourceFile($content, $uri); // TODO - docblock errors foreach ($this->stmts->getDescendantNodes() as $node) { - $fqn = DefinitionResolver::getDefinedFqn($node); + $fqn = $definitionResolver::getDefinedFqn($node); // Only index definitions with an FQN (no variables) if ($fqn === null) { continue; @@ -47,7 +56,8 @@ public function __construct(Parser $parser, $content, $docBlockFactory, $definit public function getDiagnostics() { $diagnostics = []; - foreach (Tolerant\DiagnosticsProvider::getDiagnostics($tolerantStmts) as $_error) { + $content = $this->stmts->getFileContents(); + foreach (Tolerant\DiagnosticsProvider::getDiagnostics($this->stmts) as $_error) { $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); $diagnostics[] = new Diagnostic( diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index d4f4d5e1..ddb78aba 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -28,7 +28,7 @@ class TreeAnalyzer implements TreeAnalyzerInterface { private $diagnostics; - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri) { + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; diff --git a/src/TreeAnalyzerInterface.php b/src/TreeAnalyzerInterface.php index 695ac41c..a534a728 100644 --- a/src/TreeAnalyzerInterface.php +++ b/src/TreeAnalyzerInterface.php @@ -20,7 +20,7 @@ use Microsoft\PhpParser as Tolerant; interface TreeAnalyzerInterface { - public function __construct(Parser $parser, $content, $docBlockFactory, $definitionResolver, $uri); + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri); public function getDiagnostics(); diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 0dcac39f..a553dde0 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -88,8 +88,8 @@ public function setUp() 'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))), // Namespaced - 'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 10), new Position( 2, 23))), - 'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 10), new Position( 2, 29))), + 'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 0), new Position( 2, 24))), + 'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 0), new Position( 2, 30))), 'TestNamespace\\TEST_CONST' => new Location($symbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))), 'TestNamespace\\TestClass' => new Location($symbolsUri, new Range(new Position(20, 0), new Position(61, 1))), 'TestNamespace\\ChildClass' => new Location($symbolsUri, new Range(new Position(99, 0), new Position(99, 37))), diff --git a/tests/Server/Workspace/SymbolTest.php b/tests/Server/Workspace/SymbolTest.php index d3d13b6b..9fecceb8 100644 --- a/tests/Server/Workspace/SymbolTest.php +++ b/tests/Server/Workspace/SymbolTest.php @@ -29,7 +29,7 @@ public function testEmptyQueryReturnsAllSymbols() $referencesUri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php')); // @codingStandardsIgnoreStart $this->assertEquals([ - new SymbolInformation('TestNamespace', SymbolKind::NAMESPACE, new Location($referencesUri, new Range(new Position(2, 10), new Position(2, 23))), ''), + new SymbolInformation('TestNamespace', SymbolKind::NAMESPACE, new Location($referencesUri, new Range(new Position(2, 0), new Position(2, 24))), ''), // Namespaced new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'), new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'), From cdf8fc36e1fffcdd4f510288d50c37ed1bcde9dc Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sun, 5 Mar 2017 16:34:01 -0800 Subject: [PATCH 010/149] add getNodeAtPosition, fix definition collector tests --- src/ParserResourceFactory.php | 13 ++- src/PhpDocument.php | 24 +++--- tests/NodeVisitor/DefinitionCollectorTest.php | 85 ++++++++----------- tests/PhpDocumentTest.php | 10 ++- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 8aac4a47..05cb1469 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -8,7 +8,7 @@ class ParserResourceFactory { const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; - public function getParser() { + public static function getParser() { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { return new Parser; } else { @@ -16,11 +16,20 @@ public function getParser() { } } - public function getDefinitionResolver(ReadableIndex $index) { + public static function getDefinitionResolver(ReadableIndex $index) { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { return new DefinitionResolver($index); } else { return new TolerantDefinitionResolver($index); } } + + public static function getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri) + { + if (self::PARSER_KIND === ParserKind::PHP_PARSER) { + return new TreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); + } else { + return new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); + } + } } diff --git a/src/PhpDocument.php b/src/PhpDocument.php index d653341b..534f88fd 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -64,7 +64,7 @@ class PhpDocument /** * The AST of the document * - * @var Node[] + * @var Node[] | Tolerant\Node */ private $stmts; @@ -161,11 +161,7 @@ public function updateContent(string $content) $this->definitions = null; $this->definitionNodes = null; - $treeAnalyzerClass = $this->parser instanceof Parser - ? TreeAnalyzer::class - : TolerantTreeAnalyzer::class; - - $treeAnalyzer = new $treeAnalyzerClass($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); + $treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); $this->diagnostics = $treeAnalyzer->getDiagnostics(); @@ -251,11 +247,17 @@ public function getNodeAtPosition(Position $position) if ($this->stmts === null) { return null; } - $traverser = new NodeTraverser; - $finder = new NodeAtPositionFinder($position); - $traverser->addVisitor($finder); - $traverser->traverse($this->stmts); - return $finder->node; + + if (\is_array($this->stmts)) { + $traverser = new NodeTraverser; + $finder = new NodeAtPositionFinder($position); + $traverser->addVisitor($finder); + $traverser->traverse($this->stmts); + return $finder->node; + } else { + $offset = $position->toOffset($this->stmts->getFileContents()); + return $this->stmts->getDescendantNodeAtPosition($offset); + } } /** diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index 16c49359..d53f43bb 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -4,17 +4,12 @@ namespace LanguageServer\Tests\Server\TextDocument; use PHPUnit\Framework\TestCase; -use PhpParser\{NodeTraverser, Node}; -use PhpParser\NodeVisitor\NameResolver; +use PhpParser\{Node}; use phpDocumentor\Reflection\DocBlockFactory; use LanguageServer\{ - ParserResourceFactory, LanguageClient, PhpDocument, PhpDocumentLoader, Parser, DefinitionResolver + ParserResourceFactory }; -use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Protocol\ClientCapabilities; -use LanguageServer\Index\{ProjectIndex, Index, DependenciesIndex}; -use LanguageServer\Tests\MockProtocolStream; -use LanguageServer\NodeVisitor\{ReferencesAdder, DefinitionCollector}; +use LanguageServer\Index\{Index}; use function LanguageServer\pathToUri; use Microsoft\PhpParser as Tolerant; @@ -23,23 +18,7 @@ class DefinitionCollectorTest extends TestCase public function testCollectsSymbols() { $path = realpath(__DIR__ . '/../../fixtures/symbols.php'); - $uri = pathToUri($path); - $parser = ParserResourceFactory::getParser(); - $docBlockFactory = DocBlockFactory::createInstance(); - $index = new Index; - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - $content = file_get_contents($path); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); - $stmts = $parser->parse($content); - - $traverser = new NodeTraverser; - $traverser->addVisitor(new NameResolver); - $traverser->addVisitor(new ReferencesAdder($document)); - $definitionCollector = new DefinitionCollector($definitionResolver); - $traverser->addVisitor($definitionCollector); - $traverser->traverse($stmts); - - $defNodes = $definitionCollector->nodes; + $defNodes = $this->collectDefinitions($path); $this->assertEquals([ 'TestNamespace', @@ -55,43 +34,47 @@ public function testCollectsSymbols() 'TestNamespace\\test_function()', 'TestNamespace\\ChildClass' ], array_keys($defNodes)); - $this->assertInstanceOf(Node\Const_::class, $defNodes['TestNamespace\\TEST_CONST']); - $this->assertInstanceOf(Node\Stmt\Class_::class, $defNodes['TestNamespace\\TestClass']); - $this->assertInstanceOf(Node\Const_::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']); - $this->assertInstanceOf(Node\Stmt\PropertyProperty::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']); - $this->assertInstanceOf(Node\Stmt\PropertyProperty::class, $defNodes['TestNamespace\\TestClass->testProperty']); - $this->assertInstanceOf(Node\Stmt\ClassMethod::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']); - $this->assertInstanceOf(Node\Stmt\ClassMethod::class, $defNodes['TestNamespace\\TestClass->testMethod()']); - $this->assertInstanceOf(Node\Stmt\Trait_::class, $defNodes['TestNamespace\\TestTrait']); - $this->assertInstanceOf(Node\Stmt\Interface_::class, $defNodes['TestNamespace\\TestInterface']); - $this->assertInstanceOf(Node\Stmt\Function_::class, $defNodes['TestNamespace\\test_function()']); - $this->assertInstanceOf(Node\Stmt\Class_::class, $defNodes['TestNamespace\\ChildClass']); + + + $this->assertInstanceOf(Tolerant\Node\ConstElement::class, $defNodes['TestNamespace\\TEST_CONST']); + $this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\TestClass']); + $this->assertInstanceOf(Tolerant\Node\ConstElement::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']); + // TODO - should we parse properties more strictly? + $this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']); + $this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass->testProperty']); + $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']); + $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass->testMethod()']); + $this->assertInstanceOf(Tolerant\Node\Statement\TraitDeclaration::class, $defNodes['TestNamespace\\TestTrait']); + $this->assertInstanceOf(Tolerant\Node\Statement\InterfaceDeclaration::class, $defNodes['TestNamespace\\TestInterface']); + $this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\test_function()']); + $this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\ChildClass']); } public function testDoesNotCollectReferences() { $path = realpath(__DIR__ . '/../../fixtures/references.php'); + $defNodes = $this->collectDefinitions($path); + + $this->assertEquals(['TestNamespace', 'TestNamespace\\whatever()'], array_keys($defNodes)); + $this->assertInstanceOf(Tolerant\Node\Statement\NamespaceDefinition::class, $defNodes['TestNamespace']); + $this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\whatever()']); + } + + /** + * @param $path + * @return Node + */ + private function collectDefinitions($path):array + { $uri = pathToUri($path); $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $content = file_get_contents($path); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); - $stmts = $parser->parse($content); - - $traverser = new NodeTraverser; - $traverser->addVisitor(new NameResolver); - $traverser->addVisitor(new ReferencesAdder($document)); - $definitionCollector = new DefinitionCollector($definitionResolver); - $traverser->addVisitor($definitionCollector); - $traverser->traverse($stmts); - $defNodes = $definitionCollector->nodes; - - $this->assertEquals(['TestNamespace', 'TestNamespace\\whatever()'], array_keys($defNodes)); - $this->assertInstanceOf(Node\Name::class, $defNodes['TestNamespace']); - $this->assertInstanceOf(Node\Stmt\Namespace_::class, $defNodes['TestNamespace']->getAttribute('parentNode')); - $this->assertInstanceOf(Node\Stmt\Function_::class, $defNodes['TestNamespace\\whatever()']); + $treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); + return $treeAnalyzer->getDefinitionNodes(); } } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 94399f0c..0dc9a6de 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -39,10 +39,18 @@ public function testGetNodeAtPosition() { $document = $this->createDocument('whatever', "getNodeAtPosition(new Position(1, 13)); - $this->assertInstanceOf(Node\Name\FullyQualified::class, $node); + $this->assertQualifiedName($node); $this->assertEquals('SomeClass', (string)$node); } + private function assertQualifiedName($node) { + if ($node instanceof Node) { + $this->assertInstanceOf(Node\Name\FullyQualified::class, $node); + } else { + $this->assertInstanceOf(Tolerant\Node\QualifiedName::class, $node); + } + } + public function testIsVendored() { $document = $this->createDocument('file:///dir/vendor/x.php', " Date: Sun, 5 Mar 2017 20:22:13 -0800 Subject: [PATCH 011/149] Hover and Go-To definition (in progress) --- fixtures/global_symbols.php | 2 +- src/PhpDocument.php | 6 +- src/Protocol/Range.php | 22 +- src/TolerantDefinitionResolver.php | 609 +++++++++++------- .../TextDocument/Definition/GlobalTest.php | 3 +- tests/Server/TextDocument/HoverTest.php | 12 +- 6 files changed, 395 insertions(+), 259 deletions(-) diff --git a/fixtures/global_symbols.php b/fixtures/global_symbols.php index 6494848a..d3899b09 100644 --- a/fixtures/global_symbols.php +++ b/fixtures/global_symbols.php @@ -55,7 +55,7 @@ public static function staticTestMethod() * @param TestClass $testParameter Lorem sunt velit incididunt mollit * @return TestClass */ - public function testMethod($testParameter): TestInterface + public function testMethod($testParameter) : TestInterface { $this->testProperty = $testParameter; } diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 534f88fd..6c3cf007 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -256,7 +256,11 @@ public function getNodeAtPosition(Position $position) return $finder->node; } else { $offset = $position->toOffset($this->stmts->getFileContents()); - return $this->stmts->getDescendantNodeAtPosition($offset); + $node = $this->stmts->getDescendantNodeAtPosition($offset); + if ($node->getStart() > $offset) { + return null; + } + return $node; } } diff --git a/src/Protocol/Range.php b/src/Protocol/Range.php index e4fe527b..908dd679 100644 --- a/src/Protocol/Range.php +++ b/src/Protocol/Range.php @@ -3,6 +3,7 @@ namespace LanguageServer\Protocol; use PhpParser\{Error, Node}; +use Microsoft\PhpParser as Tolerant; /** * A range in a text document expressed as (zero-based) start and end positions. @@ -26,15 +27,24 @@ class Range /** * Returns the range the node spans * - * @param Node $node + * @param Node | Tolerant\Node $node * @return self */ - public static function fromNode(Node $node) + public static function fromNode($node) { - return new self( - new Position($node->getAttribute('startLine') - 1, $node->getAttribute('startColumn') - 1), - new Position($node->getAttribute('endLine') - 1, $node->getAttribute('endColumn')) - ); + if ($node instanceof Node) { + return new self( + new Position($node->getAttribute('startLine') - 1, $node->getAttribute('startColumn') - 1), + new Position($node->getAttribute('endLine') - 1, $node->getAttribute('endColumn')) + ); + } else { + $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); + + return new self( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + ); + } } /** diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 6b0ba784..f5692aba 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -7,7 +7,7 @@ use PhpParser\Node; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use phpDocumentor\Reflection\{ - DocBlockFactory, Types, Type, Fqsen, TypeResolver + DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver }; use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; @@ -65,7 +65,7 @@ public function getDeclarationLineFromNode($node): string $defLine, $node->getFullText(), $propertyDeclaration->propertyElements->getFullStart() - $defLineStart, - $propertyDeclaration->propertyElements->getWidth() + $propertyDeclaration->propertyElements->getFullWidth() ); } elseif ( // ClassConstDeclaration or ConstDeclaration // const A = 1, B = 2; @@ -79,7 +79,7 @@ public function getDeclarationLineFromNode($node): string $defLine, $node->getFullText(), $constDeclaration->constElements->getFullStart() - $defLineStart, - $constDeclaration->constElements->getWidth() + $constDeclaration->constElements->getFullWidth() ); } @@ -89,6 +89,7 @@ public function getDeclarationLineFromNode($node): string } $defLine = \strtok($defLine, "\n"); + $defLine = \strtok($defLine, "\r"); return $defLine; } @@ -115,11 +116,12 @@ public function getDocumentationFromNode($node) // For parameters, parse the documentation to get the parameter tag. if ($node instanceof Tolerant\Node\Parameter) { $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); - $variableName = $node->variableName->getText($node->getFileContents()); + $variableName = substr($node->variableName->getText($node->getFileContents()), 1); $docBlock = $this->getDocBlock($functionLikeDeclaration); if ($docBlock !== null) { $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); + var_dump($parameterDocBlockTag); return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; } @@ -190,8 +192,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition } } $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); -// $def->type = $this->getTypeFromNode($node); //TODO - $def->type = new Types\Mixed; + $def->type = $this->getTypeFromNode($node); //TODO $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); return $def; @@ -200,15 +201,15 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition /** * Given any node, returns the Definition object of the symbol that is referenced * - * @param Node $node Any reference node + * @param Tolerant\Node $node Any reference node * @return Definition|null */ public function resolveReferenceNodeToDefinition($node) { // Variables are not indexed globally, as they stay in the file scope anyway - if ($node instanceof Node\Expr\Variable) { + if ($node instanceof Tolerant\Node\Expression\Variable) { // Resolve $this - if ($node->name === 'this' && $fqn = $this->getContainingClassFqn($node)) { + if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); } // Resolve the variable to a definition node (assignment, param or closure use) @@ -226,8 +227,7 @@ public function resolveReferenceNodeToDefinition($node) } // 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 - $parent = $node->getAttribute('parentNode'); - $globalFallback = $parent instanceof Node\Expr\ConstFetch || $parent instanceof Node\Expr\FuncCall; + $globalFallback = $this->isConstantFetch($node) || $node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class) !== null; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -241,39 +241,63 @@ public function resolveReferenceNodeToDefinition($node) */ public function resolveReferenceNodeToFqn($node) { - $parent = $node->getAttribute('parentNode'); +// TODO all name tokens should be a part of a node + $parent = $node->getParent(); - if ( - $node instanceof Node\Name && ( - $parent instanceof Node\Stmt\ClassLike - || $parent instanceof Node\Param - || $parent instanceof Node\FunctionLike - || $parent instanceof Node\Stmt\GroupUse - || $parent instanceof Node\Expr\New_ - || $parent instanceof Node\Expr\StaticCall - || $parent instanceof Node\Expr\ClassConstFetch - || $parent instanceof Node\Expr\StaticPropertyFetch - || $parent instanceof Node\Expr\Instanceof_ - ) - ) { + if ($node instanceof Tolerant\Node\QualifiedName) { // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = (string)$node; - // Only the name node should be considered a reference, not the UseUse node itself - } else if ($parent instanceof Node\Stmt\UseUse) { - $name = (string)$parent->name; - $grandParent = $parent->getAttribute('parentNode'); - if ($grandParent instanceof Node\Stmt\GroupUse) { - $name = $grandParent->prefix . '\\' . $name; - } else if ($grandParent instanceof Node\Stmt\Use_ && $grandParent->type === Node\Stmt\Use_::TYPE_FUNCTION) { - $name .= '()'; - } - } else if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { - if ($node->name instanceof Node\Expr) { + $name = (string)$node->getResolvedName() ?? $node->getText(); + if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { + if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { + $prefix = $useClause->parent->parent->namespaceName; + $prefix = $prefix === null ? "" : $prefix->getText(); + + $name = $prefix . "\\" . $name; + + if ($useClause->functionOrConst === null) { + $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); + } + } + + if ($useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $name .= "()"; + } + } + + return $name; + } + /*elseif ($node instanceof Tolerant\Node\Expression\CallExpression || ($node = $node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class)) !== null) { + if ($node->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { + $qualifier = $node->callableExpression->scopeResolutionQualifier; + if ($qualifier instanceof Tolerant\Token) { + // resolve this/self/parent + } elseif ($qualifier instanceof Tolerant\Node\QualifiedName) { + $name = $qualifier->getResolvedName() ?? $qualifier->getNamespacedName(); + $name .= "::"; + $memberName = $node->callableExpression->memberName; + if ($memberName instanceof Tolerant\Token) { + $name .= $memberName->getText($node->getFileContents()); + } elseif ($memberName instanceof Tolerant\Node\Expression\Variable) { + $name .= $memberName->getText(); + } else { + return null; + } + $name .= "()"; + return $name; + } + } + }*/ + + else if (($node instanceof Tolerant\Node\Expression\CallExpression && + ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) || ( + ($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression + )) { + if ($access->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition if right-hand side is expression return null; } // Get the type of the left-hand expression - $varType = $this->resolveExpressionNodeToType($node->var); + $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); if ($varType instanceof Types\Compound) { // For compound types, use the first FQN we find // (popular use case is ClassName|null) @@ -302,8 +326,8 @@ public function resolveReferenceNodeToFqn($node) } else { $classFqn = substr((string)$varType->getFqsen(), 1); } - $memberSuffix = '->' . (string)$node->name; - if ($node instanceof Node\Expr\MethodCall) { + $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); + if ($node instanceof Tolerant\Node\Expression\CallExpression) { $memberSuffix .= '()'; } // Find the right class that implements the member @@ -327,74 +351,86 @@ public function resolveReferenceNodeToFqn($node) } } return $classFqn . $memberSuffix; - } else if ($parent instanceof Node\Expr\FuncCall && $node instanceof Node\Name) { + } + else if ($parent->parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\DelimitedList\QualifiedNameParts) { if ($parent->name instanceof Node\Expr) { return null; } - $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); - } else if ($parent instanceof Node\Expr\ConstFetch && $node instanceof Node\Name) { - $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); - } else if ( - $node instanceof Node\Expr\ClassConstFetch - || $node instanceof Node\Expr\StaticPropertyFetch - || $node instanceof Node\Expr\StaticCall + $name = (string)($parent->getNamespacedName()); + } + else if ($this->isConstantFetch($node)) { + $name = (string)($node->getNamespacedName()); + } + else if ( + ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + || ($node instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) ) { - if ($node->class instanceof Node\Expr || $node->name instanceof Node\Expr) { + if ($scoped->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition of dynamic names return null; } - $className = (string)$node->class; + $className = (string)$scoped->scopeResolutionQualifier->getText(); if ($className === 'self' || $className === 'static' || $className === 'parent') { // self and static are resolved to the containing class - $classNode = getClosestNode($node, Node\Stmt\Class_::class); + $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); if ($classNode === null) { return null; } if ($className === 'parent') { // parent is resolved to the parent class - if (!isset($n->extends)) { + if (!isset($node->extends)) { return null; } $className = (string)$classNode->extends; } else { - $className = (string)$classNode->namespacedName; + $className = (string)$classNode->getNamespacedName(); } } - if ($node instanceof Node\Expr\StaticPropertyFetch) { - $name = (string)$className . '::$' . $node->name; + if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { + $name = (string)$className . '::$' . $scoped->memberName->getName(); } else { - $name = (string)$className . '::' . $node->name; + $name = (string)$className . '::' . $scoped->memberName->getText($node->getFileContents()); } - } else { + } + else { return null; } if (!isset($name)) { return null; } if ( - $node instanceof Node\Expr\MethodCall - || $node instanceof Node\Expr\StaticCall - || $parent instanceof Node\Expr\FuncCall + $node instanceof Tolerant\Node\Expression\CallExpression ) { $name .= '()'; } return $name; } + private function isConstantFetch(Tolerant\Node $node) : bool { + return + ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression) && + !( + $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || + ($node->parent instanceof Tolerant\Node\Expression\BinaryExpression && $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword) + ); + } + /** * 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 * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ - private static function getContainingClassFqn(Node $node) + private static function getContainingClassFqn(Tolerant\Node $node) { - $classNode = getClosestNode($node, Node\Stmt\Class_::class); - if ($classNode === null || $classNode->isAnonymous()) { + $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if ($classNode === null) { return null; } - return (string)$classNode->namespacedName; + return (string)$classNode->getNamespacedName(); } /** @@ -403,31 +439,34 @@ private static function getContainingClassFqn(Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - public static function resolveVariableToNode(Node\Expr $var) + private static function resolveVariableToNode(Tolerant\Node $var) { $n = $var; - // When a use is passed, start outside the closure to not return immediatly - if ($var instanceof Node\Expr\ClosureUse) { - $n = $var->getAttribute('parentNode')->getAttribute('parentNode'); - $name = $var->var; - } else if ($var instanceof Node\Expr\Variable || $var instanceof Node\Param) { - $name = $var->name; + // When a use is passed, start outside the closure to not return immediately + if ($var instanceof Tolerant\Node\UseVariableName) { + $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class); + $name = $var->getName(); + } else if ($var instanceof Tolerant\Node\Expression\Variable || $var instanceof Tolerant\Node\Parameter) { + $name = $var->getName(); } else { throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); } // Traverse the AST up do { // If a function is met, check the parameters and use statements - if ($n instanceof Node\FunctionLike) { - foreach ($n->getParams() as $param) { - if ($param->name === $name) { - return $param; + if (self::isFunctionLike($n)) { + if ($n->parameters !== null) { + + foreach ($n->parameters->getElements() as $param) { + if ($param->getName() === $name) { + return $param; + } } } // If it is a closure, also check use statements - if ($n instanceof Node\Expr\Closure) { - foreach ($n->uses as $use) { - if ($use->var === $name) { + if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression) { + foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use) { + if ($use->getName() === $name) { return $use; } } @@ -435,19 +474,37 @@ public static function resolveVariableToNode(Node\Expr $var) break; } // Check each previous sibling node for a variable assignment to that variable - while ($n->getAttribute('previousSibling') && $n = $n->getAttribute('previousSibling')) { + while ($n->getPreviousSibling() && $n = $n->getPreviousSibling()) { + if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { + $n = $n->expression; + } if ( - ($n instanceof Node\Expr\Assign || $n instanceof Node\Expr\AssignOp) - && $n->var instanceof Node\Expr\Variable && $n->var->name === $name + ($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) + && $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name ) { return $n; } } - } while (isset($n) && $n = $n->getAttribute('parentNode')); + } while (isset($n) && $n = $n->getParent()); // Return null if nothing was found return null; } + function getFunctionLikeDeclarationFromParameter(Tolerant\Node $node) { + return $node->getFirstAncestor( + Tolerant\Node\Statement\FunctionDeclaration::class, + Tolerant\Node\MethodDeclaration::class, + Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class + ); + } + + static function isFunctionLike(Tolerant\Node $node) { + return + $node instanceof Tolerant\Node\Statement\FunctionDeclaration || + $node instanceof Tolerant\Node\MethodDeclaration || + $node instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression; + } + /** * Given an expression node, resolves that expression recursively to a type. * If the type could not be resolved, returns Types\Mixed. @@ -457,51 +514,86 @@ public static function resolveVariableToNode(Node\Expr $var) */ public function resolveExpressionNodeToType($expr): Type { - if ($expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\ClosureUse) { - if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { + if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { + if ($expr instanceof Tolerant\Node\Expression\Variable && $expr->getName() === 'this') { return new Types\This; } // Find variable definition $defNode = $this->resolveVariableToNode($expr); - if ($defNode instanceof Node\Expr) { + if ($defNode instanceof Tolerant\Node\Expression) { return $this->resolveExpressionNodeToType($defNode); } - if ($defNode instanceof Node\Param) { + if ($defNode instanceof Tolerant\Node\Parameter) { return $this->getTypeFromNode($defNode); } } - if ($expr instanceof Node\Expr\FuncCall) { + if ($expr instanceof Tolerant\Node\Expression\CallExpression && + !($expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression)) { + // Find the function definition - if ($expr->name instanceof Node\Expr) { + if ($expr->callableExpression instanceof Tolerant\Node\Expression) { // Cannot get type for dynamic function call return new Types\Mixed; } - $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; - } - } - if ($expr instanceof Node\Expr\ConstFetch) { - if (strtolower((string)$expr->name) === 'true' || strtolower((string)$expr->name) === 'false') { - return new Types\Boolean; + + if ($expr->callableExpression instanceof Tolerant\Node\QualifiedName) { + $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName(); + $fqn .= "()"; + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } } - if (strtolower((string)$expr->name) === 'null') { - return new Types\Null_; + + /* + $isScopedPropertyAccess = $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression; + $prefix = $isScopedPropertyAccess ? + $expr->callableExpression->scopeResolutionQualifier : $expr->callableExpression->dereferencableExpression; + + if ($prefix instanceof Tolerant\Node\QualifiedName) { + $name = $prefix->getNamespacedName() ?? $prefix->getText(); + } elseif ($prefix instanceof Tolerant\Token) { + // TODO DOES THIS EVER HAPPEN? + $name = $prefix->getText($expr->getText()); } + + if (isset($name)) { + $memberNameText = $expr->callableExpression->memberName instanceof Node + ? $expr->callableExpression->memberName->getText() : $expr->callableExpression->memberName->getText($expr->getFileContents()); + $fqn = $name . ($isScopedPropertyAccess ? "::" : "->") . $memberNameText . "()"; + + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } + }*/ + } + if (strtolower((string)$expr->getText()) === 'true' || strtolower((string)$expr->getText()) === 'false') { + return new Types\Boolean; + } + + if ($this->isConstantFetch($expr)) { // Resolve constant - $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; + if ($expr instanceof Tolerant\Node\QualifiedName) { + $fqn = (string)$expr->getNamespacedName(); + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } } } - if ($expr instanceof Node\Expr\MethodCall || $expr instanceof Node\Expr\PropertyFetch) { - if ($expr->name instanceof Node\Expr) { + if (($expr instanceof Tolerant\Node\Expression\CallExpression && + ($access = $expr->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) + || ($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { + if ($access->memberName instanceof Tolerant\Node\Expression) { return new Types\Mixed; } + + $var = $access->dereferencableExpression; + // Resolve object - $objType = $this->resolveExpressionNodeToType($expr->var); + $objType = $this->resolveExpressionNodeToType($var); if (!($objType instanceof Types\Compound)) { $objType = new Types\Compound([$objType]); } @@ -516,8 +608,8 @@ public function resolveExpressionNodeToType($expr): Type } else { $classFqn = substr((string)$t->getFqsen(), 1); } - $fqn = $classFqn . '->' . $expr->name; - if ($expr instanceof Node\Expr\MethodCall) { + $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); + if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } $def = $this->index->getDefinition($fqn); @@ -527,20 +619,19 @@ public function resolveExpressionNodeToType($expr): Type } } if ( - $expr instanceof Node\Expr\StaticCall - || $expr instanceof Node\Expr\StaticPropertyFetch - || $expr instanceof Node\Expr\ClassConstFetch + $expr instanceof Tolerant\Node\Expression\CallExpression && ($scopedAccess = $expr->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + || ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { - $classType = self::resolveClassNameToType($expr->class); - if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null || $expr->name instanceof Node\Expr) { + $classType = self::resolveClassNameToType($scopedAccess->scopeResolutionQualifier); + if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { return new Types\Mixed; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; - if ($expr instanceof Node\Expr\StaticPropertyFetch) { + if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && $expr->memberName instanceof Tolerant\Node\Expression\Variable) { $fqn .= '$'; } - $fqn .= $expr->name; - if ($expr instanceof Node\Expr\StaticCall) { + $fqn .= $scopedAccess->memberName->getText() ?? $scopedAccess->memberName->getText($expr->getFileContents()); // TODO is there a cleaner way to do this? + if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } $def = $this->index->getDefinition($fqn); @@ -549,121 +640,110 @@ public function resolveExpressionNodeToType($expr): Type } return $def->type; } - if ($expr instanceof Node\Expr\New_) { - return self::resolveClassNameToType($expr->class); + if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { + return self::resolveClassNameToType($expr->classTypeDesignator); } - if ($expr instanceof Node\Expr\Clone_ || $expr instanceof Node\Expr\Assign) { - return $this->resolveExpressionNodeToType($expr->expr); + if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { + return $this->resolveExpressionNodeToType($expr->expression); } - if ($expr instanceof Node\Expr\Ternary) { + if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { + return $this->resolveExpressionNodeToType($expr->rightOperand); + } + if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { // ?: - if ($expr->if === null) { + if ($expr->ifExpression === null) { return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->cond), - $this->resolveExpressionNodeToType($expr->else) + $this->resolveExpressionNodeToType($expr->condition), // why? + $this->resolveExpressionNodeToType($expr->elseExpression) ]); } // Ternary is a compound of the two possible values return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->if), - $this->resolveExpressionNodeToType($expr->else) + $this->resolveExpressionNodeToType($expr->ifExpression), + $this->resolveExpressionNodeToType($expr->elseExpression) ]); } - if ($expr instanceof Node\Expr\BinaryOp\Coalesce) { + if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { // ?? operator return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->left), - $this->resolveExpressionNodeToType($expr->right) + $this->resolveExpressionNodeToType($expr->leftOperand), + $this->resolveExpressionNodeToType($expr->rightOperand) ]); } if ( - $expr instanceof Node\Expr\Instanceof_ - || $expr instanceof Node\Expr\Cast\Bool_ - || $expr instanceof Node\Expr\BooleanNot - || $expr instanceof Node\Expr\Empty_ - || $expr instanceof Node\Expr\Isset_ - || $expr instanceof Node\Expr\BinaryOp\Greater - || $expr instanceof Node\Expr\BinaryOp\GreaterOrEqual - || $expr instanceof Node\Expr\BinaryOp\Smaller - || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual - || $expr instanceof Node\Expr\BinaryOp\BooleanAnd - || $expr instanceof Node\Expr\BinaryOp\BooleanOr - || $expr instanceof Node\Expr\BinaryOp\LogicalAnd - || $expr instanceof Node\Expr\BinaryOp\LogicalOr - || $expr instanceof Node\Expr\BinaryOp\LogicalXor - || $expr instanceof Node\Expr\BinaryOp\NotEqual - || $expr instanceof Node\Expr\BinaryOp\NotIdentical + $this->isBooleanExpression($expr) + + || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) + || ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) + || $expr instanceof Tolerant\Node\Expression\EmptyIntrinsicExpression + || $expr instanceof Tolerant\Node\Expression\IssetIntrinsicExpression ) { return new Types\Boolean; } if ( - $expr instanceof Node\Expr\Cast\String_ - || $expr instanceof Node\Expr\BinaryOp\Concat - || $expr instanceof Node\Expr\AssignOp\Concat - || $expr instanceof Node\Scalar\String_ - || $expr instanceof Node\Scalar\Encapsed - || $expr instanceof Node\Scalar\EncapsedStringPart - || $expr instanceof Node\Scalar\MagicConst\Class_ - || $expr instanceof Node\Scalar\MagicConst\Dir - || $expr instanceof Node\Scalar\MagicConst\Function_ - || $expr instanceof Node\Scalar\MagicConst\Method - || $expr instanceof Node\Scalar\MagicConst\Namespace_ - || $expr instanceof Node\Scalar\MagicConst\Trait_ + ($expr instanceof Tolerant\Node\Expression\BinaryExpression && + ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || + $expr instanceof Tolerant\Node\StringLiteral || + ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) + + // TODO +// || $expr instanceof Node\Expr\Scalar\String_ +// || $expr instanceof Node\Expr\Scalar\Encapsed +// || $expr instanceof Node\Expr\Scalar\EncapsedStringPart +// || $expr instanceof Node\Expr\Scalar\MagicConst\Class_ +// || $expr instanceof Node\Expr\Scalar\MagicConst\Dir +// || $expr instanceof Node\Expr\Scalar\MagicConst\Function_ +// || $expr instanceof Node\Expr\Scalar\MagicConst\Method +// || $expr instanceof Node\Expr\Scalar\MagicConst\Namespace_ +// || $expr instanceof Node\Expr\Scalar\MagicConst\Trait_ ) { return new Types\String_; } if ( - $expr instanceof Node\Expr\BinaryOp\Minus - || $expr instanceof Node\Expr\BinaryOp\Plus - || $expr instanceof Node\Expr\BinaryOp\Pow - || $expr instanceof Node\Expr\BinaryOp\Mul - ) { - if ( - $this->resolveExpressionNodeToType($expr->left) instanceof Types\Integer - && $this->resolveExpressionNodeToType($expr->right) instanceof Types\Integer - ) { - return new Types\Integer; - } - return new Types\Float_; - } - - if ( - $expr instanceof Node\Expr\AssignOp\Minus - || $expr instanceof Node\Expr\AssignOp\Plus - || $expr instanceof Node\Expr\AssignOp\Pow - || $expr instanceof Node\Expr\AssignOp\Mul + $expr instanceof Tolerant\Node\Expression\BinaryExpression && + ($operator = $expr->operator->kind) + && ($operator === Tolerant\TokenKind::PlusToken || + $operator === Tolerant\TokenKind::AsteriskAsteriskToken || + $operator === Tolerant\TokenKind::AsteriskToken || + $operator === Tolerant\TokenKind::MinusToken || + $operator === Tolerant\TokenKind::AsteriskEqualsToken|| + $operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || + $operator === Tolerant\TokenKind::MinusEqualsToken || + $operator === Tolerant\TokenKind::PlusEqualsToken // TODO - this should be a type of assigment expression + ) ) { if ( - $this->resolveExpressionNodeToType($expr->var) instanceof Types\Integer - && $this->resolveExpressionNodeToType($expr->expr) instanceof Types\Integer + $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer_ + && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer_ ) { return new Types\Integer; } return new Types\Float_; } - if ( - $expr instanceof Node\Scalar\LNumber - || $expr instanceof Node\Expr\Cast\Int_ - || $expr instanceof Node\Scalar\MagicConst\Line - || $expr instanceof Node\Expr\BinaryOp\Spaceship - || $expr instanceof Node\Expr\BinaryOp\BitwiseAnd - || $expr instanceof Node\Expr\BinaryOp\BitwiseOr - || $expr instanceof Node\Expr\BinaryOp\BitwiseXor + // TODO better naming + ($expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::IntegerLiteralToken) || + $expr instanceof Tolerant\Node\Expression\BinaryExpression && ( + ($operator = $expr->operator->kind) + && ($operator === Tolerant\TokenKind::LessThanEqualsGreaterThanToken || + $operator === Tolerant\TokenKind::AmpersandToken || + $operator === Tolerant\TokenKind::CaretToken || + $operator === Tolerant\TokenKind::BarToken) + ) ) { return new Types\Integer; } if ( - $expr instanceof Node\Expr\BinaryOp\Div - || $expr instanceof Node\Scalar\DNumber - || $expr instanceof Node\Expr\Cast\Double + $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken + || + ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) ) { return new Types\Float_; } - if ($expr instanceof Node\Expr\Array_) { + if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; - foreach ($expr->items as $item) { + foreach ($expr->arrayElements->getElements() as $item) { $valueTypes[] = $this->resolveExpressionNodeToType($item->value); $keyTypes[] = $item->key ? $this->resolveExpressionNodeToType($item->key) : new Types\Integer; } @@ -685,48 +765,74 @@ public function resolveExpressionNodeToType($expr): Type } return new Types\Array_($valueType, $keyType); } - if ($expr instanceof Node\Expr\ArrayDimFetch) { - $varType = $this->resolveExpressionNodeToType($expr->var); + if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { + $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; } return $varType->getValueType(); } - if ($expr instanceof Node\Expr\Include_) { + if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { // TODO: resolve path to PhpDocument and find return statement return new Types\Mixed; } return new Types\Mixed; } + private function isBooleanExpression($expression) : bool { + if (!($expression instanceof Tolerant\Node\Expression\BinaryExpression)) { + return false; + } + switch ($expression->operator->kind) { + case Tolerant\TokenKind::InstanceOfKeyword: + case Tolerant\TokenKind::GreaterThanToken: + case Tolerant\TokenKind::GreaterThanEqualsToken: + case Tolerant\TokenKind::LessThanToken: + case Tolerant\TokenKind::LessThanEqualsToken: + case Tolerant\TokenKind::AndKeyword: + case Tolerant\TokenKind::AmpersandAmpersandToken: + case Tolerant\TokenKind::LessThanEqualsGreaterThanToken: + case Tolerant\TokenKind::OrKeyword: + case Tolerant\TokenKind::BarBarToken: + case Tolerant\TokenKind::XorKeyword: + case Tolerant\TokenKind::ExclamationEqualsEqualsToken: + case Tolerant\TokenKind::ExclamationEqualsToken: + case Tolerant\TokenKind::CaretToken: + case Tolerant\TokenKind::EqualsEqualsEqualsToken: + case Tolerant\TokenKind::EqualsToken: + return true; + } + return false; + } + /** * 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 * - * @param Node $class + * @param Tolerant\Node || Tolerant\Token $class * @return Type */ - private static function resolveClassNameToType(Node $class): Type + private static function resolveClassNameToType($class): Type { - if ($class instanceof Node\Expr) { + if ($class instanceof Tolerant\Node\Expression) { return new Types\Mixed; } - if ($class instanceof Node\Stmt\Class_) { + if ($class instanceof Tolerant\Token && $class->kind === Tolerant\TokenKind::ClassKeyword) { // Anonymous class return new Types\Object_; } - $className = (string)$class; + $className = (string)$class->getResolvedName(); if ($className === 'static') { return new Types\Static_; } if ($className === 'self' || $className === 'parent') { - $classNode = getClosestNode($class, Node\Stmt\Class_::class); + $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); if ($className === 'parent') { - if ($classNode === null || $classNode->extends === null) { + if ($classNode === null || $classNode->classBaseClause === null || $classNode->classBaseClause->baseClass === null) { return new Types\Object_; } // parent is resolved to the parent class - $classFqn = (string)$classNode->extends; + $classFqn = (string)$classNode->classBaseClause->baseClass->getResolvedName(); } else { if ($classNode === null) { return new Types\Self_; @@ -750,33 +856,33 @@ private static function resolveClassNameToType(Node $class): Type * If it is unknown, will be Types\Mixed. * Returns null if the node does not have a type. * - * @param Node $node + * @param Tolerant\Node $node * @return \phpDocumentor\Reflection\Type|null */ public function getTypeFromNode($node) { - if ($node instanceof Node\Param) { + // For parameters, get the type of the parameter [first from doc block, then from param type] + if ($node instanceof Tolerant\Node\Parameter) { // Parameters - $docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock'); + // Get the doc block for the the function call + $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); + $variableName = $node->variableName->getText($node->getFileContents()); + $docBlock = $this->getDocBlock($functionLikeDeclaration); + if ($docBlock !== null) { - // Use @param tag - foreach ($docBlock->getTagsByName('param') as $paramTag) { - if ($paramTag->getVariableName() === $node->name) { - if ($paramTag->getType() === null) { - break; - } - return $paramTag->getType(); - } + $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); + if ($parameterDocBlockTag !== null && $parameterDocBlockTag->getType() !== null) { + return $parameterDocBlockTag->getType(); } } - $type = null; - if ($node->type !== null) { + + if ($node->typeDeclaration !== null) { // Use PHP7 return type hint - if (is_string($node->type)) { + if ($node->typeDeclaration instanceof Tolerant\Token) { // Resolve a string like "bool" to a type object - $type = $this->typeResolver->resolve($node->type); + $type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents())); } else { - $type = new Types\Object_(new Fqsen('\\' . (string)$node->type)); + $type = new Types\Object_(new Fqsen('\\' . (string)$node->typeDeclaration->getResolvedName())); } } if ($node->default !== null) { @@ -789,9 +895,10 @@ public function getTypeFromNode($node) } return $type ?? new Types\Mixed; } - if ($node instanceof Node\FunctionLike) { + // for functions and methods, get the return type [first from doc block, then from return type] + if ($this->isFunctionLike($node)) { // Functions/methods - $docBlock = $node->getAttribute('docBlock'); + $docBlock = $this->getDocBlock($node); if ( $docBlock !== null && !empty($returnTags = $docBlock->getTagsByName('return')) @@ -802,47 +909,47 @@ public function getTypeFromNode($node) } if ($node->returnType !== null) { // Use PHP7 return type hint - if (is_string($node->returnType)) { + if ($node->returnType instanceof Tolerant\Token) { // Resolve a string like "bool" to a type object - return $this->typeResolver->resolve($node->returnType); + return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); } - return new Types\Object_(new Fqsen('\\' . (string)$node->returnType)); + return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); } // Unknown return type return new Types\Mixed; } - if ($node instanceof Node\Expr\Variable) { - $node = $node->getAttribute('parentNode'); + + // for variables / assignments, get the documented type the assignment resolves to. + if ($node instanceof Tolerant\Node\Expression\Variable) { + $node = $node->getFirstAncestor(Tolerant\Node\Expression\AssignmentExpression::class) ?? $node; } if ( - $node instanceof Node\Stmt\PropertyProperty - || $node instanceof Node\Const_ - || $node instanceof Node\Expr\Assign - || $node instanceof Node\Expr\AssignOp - ) { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - $docBlockHolder = $node->getAttribute('parentNode'); - } else { - $docBlockHolder = $node; - } + ($declarationNode = $node->getFirstAncestor( + Tolerant\Node\PropertyDeclaration::class, + Tolerant\Node\Statement\ConstDeclaration::class, + Tolerant\Node\ClassConstDeclaration::class)) !== null || + $node instanceof Tolerant\Node\Expression\AssignmentExpression) + { + $declarationNode = $declarationNode ?? $node; + // Property, constant or variable // Use @var tag if ( - isset($docBlockHolder) - && ($docBlock = $docBlockHolder->getAttribute('docBlock')) + ($docBlock = $this->getDocBlock($declarationNode)) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { return $type; } // Resolve the expression - if ($node instanceof Node\Stmt\PropertyProperty) { - if ($node->default) { - return $this->resolveExpressionNodeToType($node->default); + if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { + // TODO should have default + if (isset($node->rightOperand)) { + return $this->resolveExpressionNodeToType($node->rightOperand); } - } else if ($node instanceof Node\Const_) { - return $this->resolveExpressionNodeToType($node->value); - } else { + } else if ($node instanceof Tolerant\Node\ConstElement) { + return $this->resolveExpressionNodeToType($node->assignment); + } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { return $this->resolveExpressionNodeToType($node); } // TODO: read @property tags of class @@ -853,6 +960,20 @@ public function getTypeFromNode($node) return null; } + /** + * @param DocBlock $docBlock + * @param $variableName + * @return DocBlock\Tags\Param | null + */ + private function getDocBlockTagForParameter($docBlock, $variableName) { + $tags = $docBlock->getTagsByName('param'); + foreach ($tags as $tag) { + if ($tag->getVariableName() === $variableName) { + return $tag; + } + } + } + /** * 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 diff --git a/tests/Server/TextDocument/Definition/GlobalTest.php b/tests/Server/TextDocument/Definition/GlobalTest.php index b5d7425e..e800ec14 100644 --- a/tests/Server/TextDocument/Definition/GlobalTest.php +++ b/tests/Server/TextDocument/Definition/GlobalTest.php @@ -24,8 +24,9 @@ public function testDefinitionEmptyResult() // namespace keyword $result = $this->textDocument->definition( new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), - new Position(2, 4) + new Position(1, 0) )->wait(); + var_dump($result); $this->assertEquals([], $result); } diff --git a/tests/Server/TextDocument/HoverTest.php b/tests/Server/TextDocument/HoverTest.php index 7d61354a..47b0199d 100644 --- a/tests/Server/TextDocument/HoverTest.php +++ b/tests/Server/TextDocument/HoverTest.php @@ -21,7 +21,7 @@ public function testHoverForClassLike() $reference->range->start )->wait(); $this->assertEquals(new Hover([ - new MarkedString('php', "range), $result); } @@ -36,7 +36,7 @@ public function testHoverForClassLikeDefinition() $definition->range->start )->wait(); $this->assertEquals(new Hover([ - new MarkedString('php', "range), $result); } @@ -51,7 +51,7 @@ public function testHoverForMethod() $reference->range->end )->wait(); $this->assertEquals(new Hover([ - new MarkedString('php', "range), $result); } @@ -153,7 +153,7 @@ public function testHoverForVariable() $uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php')); $result = $this->textDocument->hover(new TextDocumentIdentifier($uri), new Position(13, 7))->wait(); $this->assertEquals(new Hover( - [new MarkedString('php', "textDocument->hover(new TextDocumentIdentifier($uri), new Position(22, 11))->wait(); $this->assertEquals(new Hover( [ - new MarkedString('php', "textDocument->hover(new TextDocumentIdentifier($uri), new Position(59, 11))->wait(); $this->assertEquals(new Hover([ - new MarkedString('php', " Date: Sun, 5 Mar 2017 23:23:33 -0800 Subject: [PATCH 012/149] small fixes, add diagnostic mode --- src/LoggedTolerantDefinitionResolver.php | 201 +++++++++++++++++++++++ src/ParserKind.php | 1 + src/ParserResourceFactory.php | 6 +- src/TolerantDefinitionResolver.php | 56 ++++--- tests/Server/ServerTestCase.php | 2 +- 5 files changed, 241 insertions(+), 25 deletions(-) create mode 100644 src/LoggedTolerantDefinitionResolver.php diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php new file mode 100644 index 00000000..9b8609c3 --- /dev/null +++ b/src/LoggedTolerantDefinitionResolver.php @@ -0,0 +1,201 @@ +getString($param1) . ", " . $this->getString($param2) . ")\n"; + if (self::$logger === true) { + echo $callStr; + } + $result = parent::$methodName($param1, $param2); + } else { + $callStr .= $this->getString($param1) . ")\n"; + if (self::$logger === true) { + echo $callStr; + } + $result = parent::$methodName($param1); + } + + if (self::$logger === true) { + if ($result instanceof Definition) { + $resultText = $result->fqn; + } elseif ($result instanceof DocBlock) { + $resultText = $result->getDescription(); + } else { + $resultText = $result ?? "NULL"; + } + echo "> RESULT[$methodName]: " . $resultText . "\n"; + } + return $result; + } + + private function getString($param) { + if ($param instanceof Tolerant\Node) { + return "[" . $param->getNodeKindName() . "] " . $param->getText(); + } + return (string)$param; + } + + /** + * Builds the declaration line for a given node. + * + * + * @param Tolerant\Node $node + * @return string + */ + public function getDeclarationLineFromNode($node): string + { + return $this->logMethod('getDeclarationLineFromNode', $node); + } + + /** + * Gets the documentation string for a node, if it has one + * + * @param Tolerant\Node $node + * @return string|null + */ + public function getDocumentationFromNode($node) + { + return $this->logMethod('getDocumentationFromNode', $node); + } + + function getDocBlock(Tolerant\Node $node) { + return $this->logMethod('getDocBlock', $node); + + } + + /** + * Create a Definition for a definition node + * + * @param Tolerant\Node $node + * @param string $fqn + * @return Definition + */ + public function createDefinitionFromNode($node, string $fqn = null): Definition + { + return $this->logMethod('createDefinitionFromNode', $node, $fqn); + } + + /** + * Given any node, returns the Definition object of the symbol that is referenced + * + * @param Tolerant\Node $node Any reference node + * @return Definition|null + */ + public function resolveReferenceNodeToDefinition($node) + { + self::$logger = true; + return $this->logMethod('resolveReferenceNodeToDefinition', $node); + } + + /** + * Given any node, returns the FQN of the symbol that is referenced + * Returns null if the FQN could not be resolved or the reference node references a variable + * + * @param Tolerant\Node $node + * @return string|null + */ + public function resolveReferenceNodeToFqn($node) { + return $this->logMethod('resolveReferenceNodeToFqn', $node); + } + + /** + * Returns the assignment or parameter node where a variable was defined + * + * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access + * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null + */ + public function resolveVariableToNode(Tolerant\Node $var) + { + return $this->logMethod('resolveVariableToNode', $var); + } + + /** + * Given an expression node, resolves that expression recursively to a type. + * If the type could not be resolved, returns Types\Mixed. + * + * @param \PhpParser\Node\Expr $expr + * @return \phpDocumentor\Reflection\Type + */ + public function resolveExpressionNodeToType($expr): Type + { + return $this->logMethod('resolveExpressionNodeToType', $expr); + } + + /** + * 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 + * + * @param Tolerant\Node || Tolerant\Token $class + * @return Type + */ + public function resolveClassNameToType($class): Type + { + return $this->logMethod('resolveClassNameToType', $class); + } + + /** + * Returns the type a reference to this symbol will resolve to. + * For properties and constants, this is the type of the property/constant. + * For functions and methods, this is the return type. + * For parameters, this is the type of the parameter. + * For classes and interfaces, this is the class type (object). + * For variables / assignments, this is the documented type or type the assignment resolves to. + * Can also be a compound type. + * If it is unknown, will be Types\Mixed. + * Returns null if the node does not have a type. + * + * @param Tolerant\Node $node + * @return \phpDocumentor\Reflection\Type|null + */ + public function getTypeFromNode($node) + { + return $this->logMethod('getTypeFromNode', $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 + * + * @param Tolerant\Node $node + * @return string|null + */ + public static function getDefinedFqn($node) + { + $result = parent::getDefinedFqn($node); + if (self::$logger === true) { + echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; + var_dump($result); + } + return $result; + } +} diff --git a/src/ParserKind.php b/src/ParserKind.php index 3a1e498f..b09145e5 100644 --- a/src/ParserKind.php +++ b/src/ParserKind.php @@ -7,4 +7,5 @@ class ParserKind { const PHP_PARSER = 1; const TOLERANT_PHP_PARSER = 2; + const DIAGNOSTIC_TOLERANT_PHP_PARSER = 3; } \ No newline at end of file diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 05cb1469..02cd1740 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,7 +6,7 @@ use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; + const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; public static function getParser() { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { @@ -19,8 +19,10 @@ public static function getParser() { public static function getDefinitionResolver(ReadableIndex $index) { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { return new DefinitionResolver($index); - } else { + } elseif (self::PARSER_KIND === ParserKind::TOLERANT_PHP_PARSER) { return new TolerantDefinitionResolver($index); + } elseif (self::PARSER_KIND === ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER) { + return new LoggedTolerantDefinitionResolver($index); } } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index f5692aba..4440bc7a 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -155,6 +155,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition $def = new Definition; // this determines whether the suggestion will show after "new" + // TODO name $def->isClass = $node instanceof Tolerant\Node\Statement\ClassDeclaration; $def->isGlobal = ( @@ -162,12 +163,13 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition || $node instanceof Tolerant\Node\Statement\ClassDeclaration || $node instanceof Tolerant\Node\Statement\TraitDeclaration + // TODO namespaces? || $node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null || $node instanceof Tolerant\Node\Statement\FunctionDeclaration || $node instanceof Tolerant\Node\Statement\ConstDeclaration - || $node instanceof Tolerant\Node\ClassConstDeclaration + // || $node instanceof Tolerant\Node\ClassConstDeclaration ); $def->isStatic = ( @@ -206,14 +208,20 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition */ public function resolveReferenceNodeToDefinition($node) { + $parent = $node->getParent(); + if ($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { + $node = $parent; + } // Variables are not indexed globally, as they stay in the file scope anyway if ($node instanceof Tolerant\Node\Expression\Variable) { // Resolve $this if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); } + // TODO running throug thid for class constants or properties + // Resolve the variable to a definition node (assignment, param or closure use) - $defNode = self::resolveVariableToNode($node); + $defNode = $this->resolveVariableToNode($node); if ($defNode === null) { return null; } @@ -239,11 +247,11 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) - { -// TODO all name tokens should be a part of a node - $parent = $node->getParent(); + public function resolveReferenceNodeToFqn($node) { + + $parent = $node->getParent(); +// TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { // For extends, implements, type hints and classes of classes of static calls use the name directly $name = (string)$node->getResolvedName() ?? $node->getText(); @@ -260,10 +268,14 @@ public function resolveReferenceNodeToFqn($node) } if ($useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { - $name .= "()"; + $name .= '()'; } } + if ($node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class) !== null) { + $name .= '()'; + } +// does this work for function calls? return $name; } /*elseif ($node instanceof Tolerant\Node\Expression\CallExpression || ($node = $node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class)) !== null) { @@ -352,7 +364,7 @@ public function resolveReferenceNodeToFqn($node) } return $classFqn . $memberSuffix; } - else if ($parent->parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\DelimitedList\QualifiedNameParts) { + else if ($parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\QualifiedName) { if ($parent->name instanceof Node\Expr) { return null; } @@ -365,10 +377,10 @@ public function resolveReferenceNodeToFqn($node) ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || ($node instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) ) { - if ($scoped->memberName instanceof Tolerant\Node\Expression) { +// if ($scoped->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition of dynamic names - return null; - } +// return null; +// } $className = (string)$scoped->scopeResolutionQualifier->getText(); if ($className === 'self' || $className === 'static' || $className === 'parent') { // self and static are resolved to the containing class @@ -408,6 +420,7 @@ public function resolveReferenceNodeToFqn($node) private function isConstantFetch(Tolerant\Node $node) : bool { return + $node instanceof Tolerant\Node\QualifiedName && ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression) && !( $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression || @@ -439,10 +452,11 @@ private static function getContainingClassFqn(Tolerant\Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - private static function resolveVariableToNode(Tolerant\Node $var) + public function resolveVariableToNode(Tolerant\Node $var) { $n = $var; // When a use is passed, start outside the closure to not return immediately + // Use variable vs variable parsing? if ($var instanceof Tolerant\Node\UseVariableName) { $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class); $name = $var->getName(); @@ -539,7 +553,7 @@ public function resolveExpressionNodeToType($expr): Type if ($expr->callableExpression instanceof Tolerant\Node\QualifiedName) { $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName(); - $fqn .= "()"; + $fqn .= '()'; $def = $this->index->getDefinition($fqn, true); if ($def !== null) { return $def->type; @@ -575,12 +589,10 @@ public function resolveExpressionNodeToType($expr): Type if ($this->isConstantFetch($expr)) { // Resolve constant - if ($expr instanceof Tolerant\Node\QualifiedName) { - $fqn = (string)$expr->getNamespacedName(); - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; - } + $fqn = (string)$expr->getNamespacedName(); + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; } } if (($expr instanceof Tolerant\Node\Expression\CallExpression && @@ -622,7 +634,7 @@ public function resolveExpressionNodeToType($expr): Type $expr instanceof Tolerant\Node\Expression\CallExpression && ($scopedAccess = $expr->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { - $classType = self::resolveClassNameToType($scopedAccess->scopeResolutionQualifier); + $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { return new Types\Mixed; } @@ -641,7 +653,7 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { - return self::resolveClassNameToType($expr->classTypeDesignator); + return $this->resolveClassNameToType($expr->classTypeDesignator); } if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { return $this->resolveExpressionNodeToType($expr->expression); @@ -812,7 +824,7 @@ private function isBooleanExpression($expression) : bool { * @param Tolerant\Node || Tolerant\Token $class * @return Type */ - private static function resolveClassNameToType($class): Type + public function resolveClassNameToType($class): Type { if ($class instanceof Tolerant\Node\Expression) { return new Types\Mixed; diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index a553dde0..597cfb64 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -195,7 +195,7 @@ public function setUp() 3 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 49))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestClass::staticTestProperty' => [ - 0 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 35))), // echo TestClass::$staticTestProperty; + 0 => new Location($globalReferencesUri, new Range(new Position( 8, 16), new Position( 8, 35))), // echo TestClass::$staticTestProperty; 1 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestClass::staticTestMethod()' => [ From 1316761e5e51c8f931f623c895e7ed5b2ffdb8e1 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 11:01:10 -0800 Subject: [PATCH 013/149] fix scoped expression definition resolution --- src/TolerantDefinitionResolver.php | 21 +++++++++++++-------- tests/Server/ServerTestCase.php | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 4440bc7a..a9e51f40 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -209,11 +209,8 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition public function resolveReferenceNodeToDefinition($node) { $parent = $node->getParent(); - if ($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { - $node = $parent; - } // Variables are not indexed globally, as they stay in the file scope anyway - if ($node instanceof Tolerant\Node\Expression\Variable) { + if ($node instanceof Tolerant\Node\Expression\Variable && !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) { // Resolve $this if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); @@ -374,14 +371,15 @@ public function resolveReferenceNodeToFqn($node) { $name = (string)($node->getNamespacedName()); } else if ( - ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - || ($node instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) + ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + || ($node->parent instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->parent->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) ) { // if ($scoped->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition of dynamic names // return null; // } - $className = (string)$scoped->scopeResolutionQualifier->getText(); + $className = $scoped->scopeResolutionQualifier->getText(); if ($className === 'self' || $className === 'static' || $className === 'parent') { // self and static are resolved to the containing class $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); @@ -393,16 +391,23 @@ public function resolveReferenceNodeToFqn($node) { if (!isset($node->extends)) { return null; } - $className = (string)$classNode->extends; + $className = (string)$classNode->extends->getResolvedName(); } else { $className = (string)$classNode->getNamespacedName(); } + } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + $className = $scoped->scopeResolutionQualifier->getResolvedName(); } if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { $name = (string)$className . '::$' . $scoped->memberName->getName(); } else { $name = (string)$className . '::' . $scoped->memberName->getText($node->getFileContents()); } + + if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { + $name .= '()'; + } + return $name; } else { return null; diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 597cfb64..93da08fb 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -199,7 +199,7 @@ public function setUp() 1 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestClass::staticTestMethod()' => [ - 0 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 29))) + 0 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) ], 'TestClass::testMethod()' => [ 0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); From d21e7e70087e119ef560d2ca03c82fa93f769aa0 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 11:07:05 -0800 Subject: [PATCH 014/149] Fix qualified name resolution --- src/TolerantDefinitionResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index a9e51f40..e227ed12 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -251,7 +251,7 @@ public function resolveReferenceNodeToFqn($node) { // TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = (string)$node->getResolvedName() ?? $node->getText(); + $name = (string)($node->getResolvedName() ?? $node->getText()); if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { $prefix = $useClause->parent->parent->namespaceName; @@ -269,7 +269,7 @@ public function resolveReferenceNodeToFqn($node) { } } - if ($node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class) !== null) { + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; } // does this work for function calls? From 4653f100a79f382c2652b613ae364d6ab2216769 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 13:59:12 -0800 Subject: [PATCH 015/149] fix variableName symbol info, offsets in tests --- src/Protocol/TolerantSymbolInformation.php | 2 ++ tests/Server/ServerTestCase.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php index 54504185..168d9065 100644 --- a/src/Protocol/TolerantSymbolInformation.php +++ b/src/Protocol/TolerantSymbolInformation.php @@ -66,6 +66,8 @@ public static function fromNode($node, string $fqn = null) $symbol->name = $node->getName(); } else if (isset($node->name)) { $symbol->name = trim((string)$node->name->getText($node->getFileContents()), "$"); + } else if (isset($node->variableName)) { + $symbol->name = $node->variableName->getText($node); } else { return null; } diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 93da08fb..15d2338b 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -149,7 +149,7 @@ public function setUp() 1 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestNamespace\\TestClass::staticTestMethod()' => [ - 0 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 29))) + 0 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) ], 'TestNamespace\\TestClass::testMethod()' => [ 0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); @@ -181,7 +181,7 @@ public function setUp() ], 'TestInterface' => [ 0 => new Location($globalSymbolsUri, new Range(new Position(20, 27), new Position(20, 40))), // class TestClass implements TestInterface - 1 => new Location($globalSymbolsUri, new Range(new Position(57, 48), new Position(57, 61))), // public function testMethod($testParameter): TestInterface + 1 => new Location($globalSymbolsUri, new Range(new Position(57, 49), new Position(57, 61))), // public function testMethod($testParameter) : TestInterface 2 => new Location($globalReferencesUri, new Range(new Position(33, 20), new Position(33, 33))) // if ($abc instanceof TestInterface) ], 'TestClass::TEST_CLASS_CONST' => [ From 1ff1b38ec2ec0ee38c6db8d255a9bd32e3dd99d5 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 14:21:36 -0800 Subject: [PATCH 016/149] fix subscript expression resolution --- src/TolerantDefinitionResolver.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index e227ed12..9cf4aaf1 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -121,7 +121,6 @@ public function getDocumentationFromNode($node) if ($docBlock !== null) { $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); - var_dump($parameterDocBlockTag); return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; } @@ -640,17 +639,19 @@ public function resolveExpressionNodeToType($expr): Type || ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); + var_dump($classType); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { return new Types\Mixed; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; - if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && $expr->memberName instanceof Tolerant\Node\Expression\Variable) { - $fqn .= '$'; - } +// if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && $expr->memberName instanceof Tolerant\Node\Expression\Variable) { +// $fqn .= '$'; +// } $fqn .= $scopedAccess->memberName->getText() ?? $scopedAccess->memberName->getText($expr->getFileContents()); // TODO is there a cleaner way to do this? if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } + var_dump($fqn); $def = $this->index->getDefinition($fqn); if ($def === null) { return new Types\Mixed; @@ -783,7 +784,9 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Array_($valueType, $keyType); } if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { + var_dump("SUBSCRIPT"); $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); + var_dump($varType); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; } From d02253c9f6b474bcb76d295c1ae0812627797cc7 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 15:34:43 -0800 Subject: [PATCH 017/149] fix base class logic --- src/TolerantDefinitionResolver.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 9cf4aaf1..f453e6ed 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -181,13 +181,13 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $def->extends = []; if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { - $def->extends[] = (string)$node->classBaseClause->baseClass; + $def->extends[] = (string)$node->classBaseClause->baseClass->getResolvedName(); } // TODO what about class interfaces } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $def->extends = []; if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { - foreach ($node->interfaceBaseClause->interfaceNameList->getChildNodes() as $n) { + foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { $def->extends[] = (string)$n; } } @@ -306,6 +306,7 @@ public function resolveReferenceNodeToFqn($node) { } // Get the type of the left-hand expression $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); + var_dump($varType); if ($varType instanceof Types\Compound) { // For compound types, use the first FQN we find // (popular use case is ClassName|null) @@ -333,6 +334,7 @@ public function resolveReferenceNodeToFqn($node) { return null; } else { $classFqn = substr((string)$varType->getFqsen(), 1); + var_dump($classFqn); } $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); if ($node instanceof Tolerant\Node\Expression\CallExpression) { @@ -340,9 +342,12 @@ public function resolveReferenceNodeToFqn($node) { } // Find the right class that implements the member $implementorFqns = [$classFqn]; + while ($implementorFqn = array_shift($implementorFqns)) { + var_dump($implementorFqn . $memberSuffix); // If the member FQN exists, return it if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { + return $implementorFqn . $memberSuffix; } // Get Definition of implementor class @@ -358,6 +363,10 @@ public function resolveReferenceNodeToFqn($node) { } } } + + var_dump("SUFFIX"); + var_dump($classFqn); + var_dump($memberSuffix); return $classFqn . $memberSuffix; } else if ($parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\QualifiedName) { From afca7ea7e06d682d7cbae6268b12a9dabd9859b0 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 16:08:06 -0800 Subject: [PATCH 018/149] fix definitions namespaced function calls --- src/LoggedTolerantDefinitionResolver.php | 1 + src/TolerantDefinitionResolver.php | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php index 9b8609c3..42764d89 100644 --- a/src/LoggedTolerantDefinitionResolver.php +++ b/src/LoggedTolerantDefinitionResolver.php @@ -112,6 +112,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition */ public function resolveReferenceNodeToDefinition($node) { + var_dump(array_keys($this->index->getDefinitions())); self::$logger = true; return $this->logMethod('resolveReferenceNodeToDefinition', $node); } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index f453e6ed..96def0e3 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -18,7 +18,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface /** * @var \LanguageServer\Index\ReadableIndex */ - private $index; + protected $index; /** * @var \phpDocumentor\Reflection\TypeResolver @@ -244,14 +244,14 @@ public function resolveReferenceNodeToDefinition($node) * @return string|null */ public function resolveReferenceNodeToFqn($node) { - - $parent = $node->getParent(); // TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = (string)($node->getResolvedName() ?? $node->getText()); + $name = $node->getResolvedName(); + if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { + $name = (string)($name ?? $node->getText()); if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { $prefix = $useClause->parent->parent->namespaceName; $prefix = $prefix === null ? "" : $prefix->getText(); @@ -267,6 +267,9 @@ public function resolveReferenceNodeToFqn($node) { $name .= '()'; } } + else { + $name = (string)($name ?? (string)$node->getNamespacedName()); + } if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; @@ -333,6 +336,7 @@ public function resolveReferenceNodeToFqn($node) { // Left-hand expression could not be resolved to a class return null; } else { + var_dump("AAAHHHHH"); $classFqn = substr((string)$varType->getFqsen(), 1); var_dump($classFqn); } From e45648daab479a561b1b0502d67ff8cbee7f41e0 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 16:12:26 -0800 Subject: [PATCH 019/149] fix global constant fallback --- src/TolerantDefinitionResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 96def0e3..7a4a37b2 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -438,7 +438,7 @@ public function resolveReferenceNodeToFqn($node) { private function isConstantFetch(Tolerant\Node $node) : bool { return $node instanceof Tolerant\Node\QualifiedName && - ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression) && + ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression || $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList) && !( $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || From 167b6ac6f24e16fd962f9fd16b15ea1c72dd2b6a Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 6 Mar 2017 21:31:13 -0800 Subject: [PATCH 020/149] Update getDocBlock to use context information. All Definition tests pass! --- src/LoggedTolerantDefinitionResolver.php | 2 +- src/TolerantDefinitionResolver.php | 55 +++++++++++++++++------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php index 42764d89..7fb79820 100644 --- a/src/LoggedTolerantDefinitionResolver.php +++ b/src/LoggedTolerantDefinitionResolver.php @@ -52,7 +52,7 @@ public function logMethod($methodName, $param1, $param2 = -1) { } else { $resultText = $result ?? "NULL"; } - echo "> RESULT[$methodName]: " . $resultText . "\n"; + echo "> RESULT[$callStr]: " . $resultText . "\n"; } return $result; } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 7a4a37b2..a6ba05b0 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -30,6 +30,11 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface */ private $prettyPrinter; + /** + * @var DocBlockFactory + */ + private $docBlockFactory; + /** * @param ReadableIndex $index */ @@ -38,6 +43,7 @@ public function __construct(ReadableIndex $index) $this->index = $index; $this->typeResolver = new TypeResolver; $this->prettyPrinter = new PrettyPrinter; + $this->docBlockFactory = DocBlockFactory::createInstance(); } /** @@ -135,11 +141,20 @@ public function getDocumentationFromNode($node) } function getDocBlock(Tolerant\Node $node) { - // TODO context information - static $docBlockFactory; - $docBlockFactory = $docBlockFactory ?? DocBlockFactory::createInstance(); + // TODO make more efficient + $namespaceDefinition = $node->getNamespaceDefinition(); + $context = null; + if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { + $name = (string)$namespaceDefinition->name->getNamespacedName(); + list($namespaceImportTable,,) = $namespaceDefinition->name->getImportTablesForCurrentScope($namespaceDefinition); + foreach ($namespaceImportTable as $alias=>$name) { + $namespaceImportTable[$alias] = (string)$name; + } + $context = new Types\Context($name, $namespaceImportTable); + } + $docCommentText = $node->getDocCommentText(); - return $docCommentText !== null ? $docBlockFactory->create($docCommentText) : null; + return $docCommentText !== null ? $this->docBlockFactory->create($docCommentText, $context) : null; } /** @@ -309,7 +324,7 @@ public function resolveReferenceNodeToFqn($node) { } // Get the type of the left-hand expression $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); - var_dump($varType); +// var_dump($varType); if ($varType instanceof Types\Compound) { // For compound types, use the first FQN we find // (popular use case is ClassName|null) @@ -336,8 +351,11 @@ public function resolveReferenceNodeToFqn($node) { // Left-hand expression could not be resolved to a class return null; } else { - var_dump("AAAHHHHH"); +// var_dump("AAAHHHHH"); $classFqn = substr((string)$varType->getFqsen(), 1); + + // TODO +// $classFqn = $node->getNamespaceDefinition()->name->getNamespacedName() . (string)$varType->getFqsen(); var_dump($classFqn); } $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); @@ -348,7 +366,7 @@ public function resolveReferenceNodeToFqn($node) { $implementorFqns = [$classFqn]; while ($implementorFqn = array_shift($implementorFqns)) { - var_dump($implementorFqn . $memberSuffix); +// var_dump($implementorFqn . $memberSuffix); // If the member FQN exists, return it if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { @@ -368,9 +386,9 @@ public function resolveReferenceNodeToFqn($node) { } } - var_dump("SUFFIX"); - var_dump($classFqn); - var_dump($memberSuffix); +// var_dump("SUFFIX"); +// var_dump($classFqn); +// var_dump($memberSuffix); return $classFqn . $memberSuffix; } else if ($parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\QualifiedName) { @@ -618,11 +636,12 @@ public function resolveExpressionNodeToType($expr): Type if ($access->memberName instanceof Tolerant\Node\Expression) { return new Types\Mixed; } - $var = $access->dereferencableExpression; + var_dump("HERE!!!"); // Resolve object $objType = $this->resolveExpressionNodeToType($var); +// var_dump($objType); if (!($objType instanceof Types\Compound)) { $objType = new Types\Compound([$objType]); } @@ -636,12 +655,16 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } else { $classFqn = substr((string)$t->getFqsen(), 1); + var_dump($classFqn); } $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } + var_dump($fqn); +// var_dump($fqn); $def = $this->index->getDefinition($fqn); + var_dump($def); if ($def !== null) { return $def->type; } @@ -652,7 +675,7 @@ public function resolveExpressionNodeToType($expr): Type || ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); - var_dump($classType); +// var_dump($classType); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { return new Types\Mixed; } @@ -664,7 +687,7 @@ public function resolveExpressionNodeToType($expr): Type if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } - var_dump($fqn); +// var_dump($fqn); $def = $this->index->getDefinition($fqn); if ($def === null) { return new Types\Mixed; @@ -797,9 +820,9 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Array_($valueType, $keyType); } if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { - var_dump("SUBSCRIPT"); +// var_dump("SUBSCRIPT"); $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); - var_dump($varType); +// var_dump($varType); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; } @@ -972,6 +995,8 @@ public function getTypeFromNode($node) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { +// var_dump("BOOYAH"); +// var_dump($type); return $type; } // Resolve the expression From 4324530389c3b7be3d7e4102db68a8e4a5bc85d8 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 9 Mar 2017 15:56:41 -0800 Subject: [PATCH 021/149] Find all references support --- src/DefinitionResolver.php | 7 +++ src/PhpDocument.php | 2 +- src/Server/TextDocument.php | 39 +++++++------ src/TolerantDefinitionResolver.php | 23 ++++---- src/TolerantTreeAnalyzer.php | 56 +++++++++++++++++++ tests/Server/ServerTestCase.php | 8 +-- .../References/NamespacedTest.php | 1 + 7 files changed, 104 insertions(+), 32 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 426b5522..b479e254 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -132,6 +132,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition $def->type = $this->getTypeFromNode($node); $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); +// var_dump($def); return $def; } @@ -440,6 +441,8 @@ public function resolveExpressionNodeToType($expr): Type } // Resolve object $objType = $this->resolveExpressionNodeToType($expr->var); + // var_dump((string)$expr->var->name); +// var_dump($objType); if (!($objType instanceof Types\Compound)) { $objType = new Types\Compound([$objType]); } @@ -453,6 +456,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } else { $classFqn = substr((string)$t->getFqsen(), 1); + // var_dump($classFqn); } $fqn = $classFqn . '->' . $expr->name; if ($expr instanceof Node\Expr\MethodCall) { @@ -771,6 +775,9 @@ public function getTypeFromNode($node) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { + if ((string)$type === "\\TestNamespace\\TestClass") { + var_dump($type); + } return $type; } // Resolve the expression diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 6c3cf007..23387f58 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -257,7 +257,7 @@ public function getNodeAtPosition(Position $position) } else { $offset = $position->toOffset($this->stmts->getFileContents()); $node = $this->stmts->getDescendantNodeAtPosition($offset); - if ($node->getStart() > $offset) { + if ($node !== null && $node->getStart() > $offset) { return null; } return $node; diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 1d4d0d54..632c2e34 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -3,9 +3,11 @@ namespace LanguageServer\Server; +use Microsoft\PhpParser as Tolerant; +use phpDocumentor\Reflection\DocBlock\Tags\Param; use PhpParser\{Node, NodeTraverser}; use LanguageServer\{ - DefinitionResolverInterface, FqnUtilities, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider + DefinitionResolverInterface, FqnUtilities, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider, TolerantDefinitionResolver, TolerantTreeAnalyzer }; use LanguageServer\NodeVisitor\VariableReferencesCollector; use LanguageServer\Protocol\{ @@ -197,31 +199,35 @@ public function references( // Variables always stay in the boundary of the file and need to be searched inside their function scope // by traversing the AST if ( - $node instanceof Node\Expr\Variable - || $node instanceof Node\Param - || $node instanceof Node\Expr\ClosureUse + + ($node instanceof Tolerant\Node\Expression\Variable && !($node->getParent()->getParent() instanceof Tolerant\Node\PropertyDeclaration)) + || $node instanceof Tolerant\Node\Parameter + || $node instanceof Tolerant\Node\UseVariableName ) { - if ($node->name instanceof Node\Expr) { + if (isset($node->name) && $node->name instanceof Tolerant\Node\Expression) { return null; } // Find function/method/closure scope $n = $node; - while (isset($n) && !($n instanceof Node\FunctionLike)) { - $n = $n->getAttribute('parentNode'); - } - if (!isset($n)) { - $n = $node->getAttribute('ownerDocument'); + + $n = $n->getFirstAncestor(Tolerant\Node\Statement\FunctionDeclaration::class, Tolerant\Node\MethodDeclaration::class, Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class, Tolerant\Node\SourceFileNode::class); + + if ($n === null) { + $n = $node->getFirstAncestor(Tolerant\Node\Statement\ExpressionStatement::class)->getParent(); } - $traverser = new NodeTraverser; - $refCollector = new VariableReferencesCollector($node->name); - $traverser->addVisitor($refCollector); - $traverser->traverse($n->getStmts()); - foreach ($refCollector->nodes as $ref) { - $locations[] = Location::fromNode($ref); + + foreach ($n->getDescendantNodes() as $descendantNode) { + if ($descendantNode instanceof Tolerant\Node\Expression\Variable && + $descendantNode->getName() === $node->getName() + ) { + var_dump($descendantNode->getName()); + $locations[] = Location::fromNode($descendantNode); + } } } else { // Definition with a global FQN $fqn = FqnUtilities::getDefinedFqn($node); + // var_dump($fqn); // Wait until indexing finished if (!$this->index->isComplete()) { yield waitForEvent($this->index, 'complete'); @@ -240,6 +246,7 @@ public function references( $refs = $document->getReferenceNodesByFqn($fqn); if ($refs !== null) { foreach ($refs as $ref) { + // var_dump($ref->getNodeKindName()); $locations[] = Location::fromNode($ref); } } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index a6ba05b0..e4130e1e 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -229,7 +229,7 @@ public function resolveReferenceNodeToDefinition($node) if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); } - // TODO running throug thid for class constants or properties + // TODO running through thid for class constants or properties // Resolve the variable to a definition node (assignment, param or closure use) $defNode = $this->resolveVariableToNode($node); @@ -246,7 +246,7 @@ public function resolveReferenceNodeToDefinition($node) } // 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 - $globalFallback = $this->isConstantFetch($node) || $node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class) !== null; + $globalFallback = $this->isConstantFetch($node) || $node->parent instanceof Tolerant\Node\Expression\CallExpression; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -278,7 +278,7 @@ public function resolveReferenceNodeToFqn($node) { } } - if ($useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { $name .= '()'; } } @@ -356,7 +356,7 @@ public function resolveReferenceNodeToFqn($node) { // TODO // $classFqn = $node->getNamespaceDefinition()->name->getNamespacedName() . (string)$varType->getFqsen(); - var_dump($classFqn); +// var_dump($classFqn); } $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); if ($node instanceof Tolerant\Node\Expression\CallExpression) { @@ -453,8 +453,9 @@ public function resolveReferenceNodeToFqn($node) { return $name; } - private function isConstantFetch(Tolerant\Node $node) : bool { + public static function isConstantFetch(Tolerant\Node $node) : bool { return + ( $node instanceof Tolerant\Node\QualifiedName && ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression || $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList) && !( @@ -462,7 +463,7 @@ private function isConstantFetch(Tolerant\Node $node) : bool { $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || ($node->parent instanceof Tolerant\Node\Expression\BinaryExpression && $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword) - ); + )); } /** @@ -547,7 +548,7 @@ function getFunctionLikeDeclarationFromParameter(Tolerant\Node $node) { ); } - static function isFunctionLike(Tolerant\Node $node) { + public static function isFunctionLike(Tolerant\Node $node) { return $node instanceof Tolerant\Node\Statement\FunctionDeclaration || $node instanceof Tolerant\Node\MethodDeclaration || @@ -638,7 +639,7 @@ public function resolveExpressionNodeToType($expr): Type } $var = $access->dereferencableExpression; - var_dump("HERE!!!"); +// var_dump("HERE!!!"); // Resolve object $objType = $this->resolveExpressionNodeToType($var); // var_dump($objType); @@ -655,16 +656,16 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } else { $classFqn = substr((string)$t->getFqsen(), 1); - var_dump($classFqn); +// var_dump($classFqn); } $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); if ($expr instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } - var_dump($fqn); +// var_dump($fqn); // var_dump($fqn); $def = $this->index->getDefinition($fqn); - var_dump($def); +// var_dump($def); if ($def !== null) { return $def->type; } diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 1d94d094..48e83c3c 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -52,6 +52,54 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso $this->definitionNodes[$fqn] = $node; $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); } + + foreach ($this->stmts->getDescendantNodes() as $node) { + $parent = $node->parent; + if ( + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + && !( + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->memberName instanceof Tolerant\Token + )) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart()) + ) { + continue; + } + $fqn = $definitionResolver->resolveReferenceNodeToFqn($node); + if ($fqn === null) { + continue; + } + $this->addReference($fqn, $node); + + if ( + $node instanceof Tolerant\Node\QualifiedName + && $node->isQualifiedName() + && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } + } + + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if ($definitionResolver::isConstantFetch($node) || + ($parent instanceof Tolerant\Node\Expression\CallExpression + && !( + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); + } + } + } } public function getDiagnostics() { @@ -71,6 +119,14 @@ public function getDiagnostics() { return $diagnostics; } + private function addReference(string $fqn, Tolerant\Node $node) + { + if (!isset($this->referenceNodes[$fqn])) { + $this->referenceNodes[$fqn] = []; + } + $this->referenceNodes[$fqn][] = $node; + } + public function getDefinitions() { return $this->definitions ?? []; } diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 15d2338b..2d725e55 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -110,7 +110,7 @@ public function setUp() 'TestNamespace' => [ 0 => new Location($referencesUri, new Range(new Position(31, 13), new Position(31, 40))), // use function TestNamespace\test_function; 1 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass; - 2 => new Location($useUri, new Range(new Position( 5, 4), new Position( 5, 17))) // use TestNamespace\{TestTrait, TestInterface}; + 2 => new Location($useUri, new Range(new Position( 5, 4), new Position( 5, 18))) // use TestNamespace\{TestTrait, TestInterface}; ], 'TestNamespace\\TEST_CONST' => [ 0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15))) @@ -145,8 +145,8 @@ public function setUp() 3 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 49))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestNamespace\\TestClass::staticTestProperty' => [ - 0 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 35))), // echo TestClass::$staticTestProperty; - 1 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; + 0 => new Location($referencesUri, new Range(new Position( 8, 16), new Position( 8, 35))), // echo TestClass::$staticTestProperty; + 1 => new Location($referencesUri, new Range(new Position(39, 11), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestNamespace\\TestClass::staticTestMethod()' => [ 0 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) @@ -196,7 +196,7 @@ public function setUp() ], 'TestClass::staticTestProperty' => [ 0 => new Location($globalReferencesUri, new Range(new Position( 8, 16), new Position( 8, 35))), // echo TestClass::$staticTestProperty; - 1 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; + 1 => new Location($globalReferencesUri, new Range(new Position(39, 11), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty; ], 'TestClass::staticTestMethod()' => [ 0 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) diff --git a/tests/Server/TextDocument/References/NamespacedTest.php b/tests/Server/TextDocument/References/NamespacedTest.php index 1ee1ab4d..32b8c4bc 100644 --- a/tests/Server/TextDocument/References/NamespacedTest.php +++ b/tests/Server/TextDocument/References/NamespacedTest.php @@ -28,6 +28,7 @@ public function testReferencesForNamespaces() new TextDocumentIdentifier($definition->uri), $definition->range->end )->wait(); + // var_dump($result); $this->assertEquals(parent::getReferenceLocations('TestNamespace'), $result); } } From 0824e6d9b8f11b80eb07813224c3755f2a5a1708 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 15 Mar 2017 14:10:29 -0700 Subject: [PATCH 022/149] start adding validation tests --- .gitmodules | 9 +++ src/ParserResourceFactory.php | 2 +- tests/Validation/ValidationTest.php | 76 +++++++++++++++++++++++ validation/frameworks/drupal | 1 + validation/frameworks/php-language-server | 1 + validation/frameworks/wordpress | 1 + 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 tests/Validation/ValidationTest.php create mode 160000 validation/frameworks/drupal create mode 160000 validation/frameworks/php-language-server create mode 160000 validation/frameworks/wordpress diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..3f59547b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "validation/frameworks/php-language-server"] + path = validation/frameworks/php-language-server + url = https://github.com/felixfbecker/php-language-server +[submodule "validation/frameworks/wordpress"] + path = validation/frameworks/wordpress + url = https://github.com/wordpress/wordpress +[submodule "validation/frameworks/drupal"] + path = validation/frameworks/drupal + url = https://github.com/drupal/drupal diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 02cd1740..08615225 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,7 +6,7 @@ use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; + const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; public static function getParser() { if (self::PARSER_KIND === ParserKind::PHP_PARSER) { diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php new file mode 100644 index 00000000..79ca6c86 --- /dev/null +++ b/tests/Validation/ValidationTest.php @@ -0,0 +1,76 @@ +getSize(); + $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; + } + } + } + if (count($testProviderArray) === 0) { + throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); + } + return $testProviderArray; + } + + /** + * @dataProvider frameworkErrorProvider + */ + public function testFramworkErrors($testCaseFile, $frameworkName) { + $fileContents = file_get_contents($testCaseFile); + + $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); + $index = new Index; + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + + $directory = __DIR__ . "/output/$frameworkName/"; + $outFile = $directory . basename($testCaseFile); + + try { + $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Exception $e) { + if (!file_exists($dir = __DIR__ . "/output")) { + mkdir($dir); + } + if (!file_exists($directory)) { + mkdir($directory); + } + file_put_contents($outFile, $fileContents); + $this->fail((string)$e); + } + + if (file_exists($outFile)) { + unlink($outFile); + } + // echo json_encode($parser->getErrors($sourceFile)); + } +} \ No newline at end of file diff --git a/validation/frameworks/drupal b/validation/frameworks/drupal new file mode 160000 index 00000000..ac7313dd --- /dev/null +++ b/validation/frameworks/drupal @@ -0,0 +1 @@ +Subproject commit ac7313dda0644f35031428ff954b6d9e6f90e857 diff --git a/validation/frameworks/php-language-server b/validation/frameworks/php-language-server new file mode 160000 index 00000000..546660f9 --- /dev/null +++ b/validation/frameworks/php-language-server @@ -0,0 +1 @@ +Subproject commit 546660f957623b2cdc179fe107b28581d60ba190 diff --git a/validation/frameworks/wordpress b/validation/frameworks/wordpress new file mode 160000 index 00000000..afdef179 --- /dev/null +++ b/validation/frameworks/wordpress @@ -0,0 +1 @@ +Subproject commit afdef17903c52c15642be01169495e08a08b04a7 From 81ba7df91c6d429b64f8db6b58505b768f130bfa Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 15 Mar 2017 14:10:52 -0700 Subject: [PATCH 023/149] fix some crashes, perf issues --- src/TolerantDefinitionResolver.php | 46 +++++++++++++++++++----------- src/TolerantTreeAnalyzer.php | 2 +- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index e4130e1e..25ed3028 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -154,7 +154,14 @@ function getDocBlock(Tolerant\Node $node) { } $docCommentText = $node->getDocCommentText(); - return $docCommentText !== null ? $this->docBlockFactory->create($docCommentText, $context) : null; + if ($docCommentText !== null) { + try { + return $this->docBlockFactory->create($docCommentText, $context); + } catch (\InvalidArgumentException $e) { + return null; + } + } + return null; } /** @@ -194,23 +201,28 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition ); $def->fqn = $fqn; if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { - $def->extends = []; if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { + $def->extends = []; $def->extends[] = (string)$node->classBaseClause->baseClass->getResolvedName(); } // TODO what about class interfaces } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { - $def->extends = []; if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { + $def->extends = []; foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { - $def->extends[] = (string)$n; + $def->extends[] = $n->getText() ?? $n->getText($node->getFileContents()); } } } + $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); - $def->type = $this->getTypeFromNode($node); //TODO - $def->declarationLine = $this->getDeclarationLineFromNode($node); - $def->documentation = $this->getDocumentationFromNode($node); + + if ($def->symbolInformation !== null) { + $def->type = $this->getTypeFromNode($node); //TODO + $def->declarationLine = $this->getDeclarationLineFromNode($node); + $def->documentation = $this->getDocumentationFromNode($node); + } + return $def; } @@ -222,7 +234,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition */ public function resolveReferenceNodeToDefinition($node) { - $parent = $node->getParent(); + $parent = $node->parent; // Variables are not indexed globally, as they stay in the file scope anyway if ($node instanceof Tolerant\Node\Expression\Variable && !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) { // Resolve $this @@ -259,7 +271,7 @@ public function resolveReferenceNodeToDefinition($node) * @return string|null */ public function resolveReferenceNodeToFqn($node) { - $parent = $node->getParent(); + $parent = $node->parent; // TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { // For extends, implements, type hints and classes of classes of static calls use the name directly @@ -514,7 +526,7 @@ public function resolveVariableToNode(Tolerant\Node $var) } } // If it is a closure, also check use statements - if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression) { + if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && $n->anonymousFunctionUseClause !== null && $n->anonymousFunctionUseClause->useVariableNameList !== null) { foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use) { if ($use->getName() === $name) { return $use; @@ -535,7 +547,7 @@ public function resolveVariableToNode(Tolerant\Node $var) return $n; } } - } while (isset($n) && $n = $n->getParent()); + } while (isset($n) && $n = $n->parent); // Return null if nothing was found return null; } @@ -798,9 +810,11 @@ public function resolveExpressionNodeToType($expr): Type if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; - foreach ($expr->arrayElements->getElements() as $item) { - $valueTypes[] = $this->resolveExpressionNodeToType($item->value); - $keyTypes[] = $item->key ? $this->resolveExpressionNodeToType($item->key) : new Types\Integer; + if ($expr->arrayElements !== null) { + foreach ($expr->arrayElements->getElements() as $item) { + $valueTypes[] = $this->resolveExpressionNodeToType($item->elementValue); + $keyTypes[] = $item->elementKey ? $this->resolveExpressionNodeToType($item->elementKey) : new Types\Integer; + } } $valueTypes = array_unique($keyTypes); $keyTypes = array_unique($keyTypes); @@ -895,7 +909,7 @@ public function resolveClassNameToType($class): Type return new Types\Self_; } // self is resolved to the containing class - $classFqn = (string)$classNode->namespacedName; + $classFqn = (string)$classNode->getNamespacedName(); } return new Types\Object_(new Fqsen('\\' . $classFqn)); } @@ -1042,7 +1056,7 @@ private function getDocBlockTagForParameter($docBlock, $variableName) { */ public static function getDefinedFqn($node) { - $parent = $node->getParent(); + $parent = $node->parent; // Anonymous classes don't count as a definition // INPUT OUTPUT: // namespace A\B; diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 48e83c3c..5e28c60b 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -61,7 +61,7 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso $node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->memberName instanceof Tolerant\Token )) - || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart()) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()) ) { continue; } From 6e7f77be6d890f3e4ba98201e734a8c6464368bd Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 15 Mar 2017 14:11:49 -0700 Subject: [PATCH 024/149] add script to help profile --- Performance.php | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Performance.php diff --git a/Performance.php b/Performance.php new file mode 100644 index 00000000..8dd00787 --- /dev/null +++ b/Performance.php @@ -0,0 +1,56 @@ +getSize(); + $testProviderArray[] = $file->getPathname(); + } +} + +if (count($testProviderArray) === 0) { + throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); +} + +foreach ($testProviderArray as $idx=>$testCaseFile) { + if ($idx > 10) { + exit(); + } + + echo "$idx\n"; + + $fileContents = file_get_contents($testCaseFile); + + $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); + $index = new Index; + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + + try { + $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Exception $e) { + echo "AAAHH\n"; + continue; + } +} + From 7b633f5e0738b195e288bc39495ec7858c9d7d12 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 21 Mar 2017 15:25:49 -0700 Subject: [PATCH 025/149] minor perf improvements --- Performance.php | 2 +- src/TolerantDefinitionResolver.php | 2 +- src/TolerantTreeAnalyzer.php | 14 ++++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Performance.php b/Performance.php index 8dd00787..cfb0076b 100644 --- a/Performance.php +++ b/Performance.php @@ -33,7 +33,7 @@ } foreach ($testProviderArray as $idx=>$testCaseFile) { - if ($idx > 10) { + if ($idx > 20) { exit(); } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 25ed3028..12714054 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -536,7 +536,7 @@ public function resolveVariableToNode(Tolerant\Node $var) break; } // Check each previous sibling node for a variable assignment to that variable - while ($n->getPreviousSibling() && $n = $n->getPreviousSibling()) { + while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { $n = $n->expression; } diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 5e28c60b..c1722869 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -25,6 +25,8 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface { /** @var Tolerant\Node */ private $stmts; + private $diagnostics; + /** * TolerantTreeAnalyzer constructor. * @param Tolerant\Parser $parser @@ -100,15 +102,12 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso } } } - } - public function getDiagnostics() { - $diagnostics = []; - $content = $this->stmts->getFileContents(); foreach (Tolerant\DiagnosticsProvider::getDiagnostics($this->stmts) as $_error) { + $this->diagnostics = []; $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); - $diagnostics[] = new Diagnostic( + $this->diagnostics[] = new Diagnostic( $_error->message, new Range( new Position($range->start->line, $range->start->character), @@ -116,7 +115,10 @@ public function getDiagnostics() { ) ); } - return $diagnostics; + } + + public function getDiagnostics() { + return $this->diagnostics; } private function addReference(string $fqn, Tolerant\Node $node) From cd4c6d66d999bb51f01fb2d3b6c1f4fc40321b17 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Fri, 24 Mar 2017 10:30:07 -0700 Subject: [PATCH 026/149] Add validation test filesize threshold --- tests/Validation/ValidationTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 79ca6c86..1be9e69f 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -30,8 +30,9 @@ public function frameworkErrorProvider() { foreach (new RecursiveIteratorIterator($iterator) as $file) { if (strpos((string)$file, ".php") !== false) { - $totalSize += $file->getSize(); - $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; + if ($file->getSize() < 100000 ) { + $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; + } } } } From c84b91de2b628123cf9180bc3aacd9e8033e7a18 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Fri, 24 Mar 2017 10:30:34 -0700 Subject: [PATCH 027/149] Fix exception during definition resolution --- src/TolerantDefinitionResolver.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 12714054..7b60ff99 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -576,6 +576,11 @@ public static function isFunctionLike(Tolerant\Node $node) { */ public function resolveExpressionNodeToType($expr): Type { + if (!($expr instanceof Tolerant\Node)) { + // TODO some members are null or Missing/SkippedToken + // How do we handle this more generally? + return new Types\Mixed; + } if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { if ($expr instanceof Tolerant\Node\Expression\Variable && $expr->getName() === 'this') { return new Types\This; From 946b5b1cdba4cc86b5f4ddc7082f7a7a782f491b Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Fri, 24 Mar 2017 10:31:23 -0700 Subject: [PATCH 028/149] Fix exception during diagnostics parsing --- src/TolerantTreeAnalyzer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index c1722869..4e6b9942 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -103,8 +103,8 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso } } + $this->diagnostics = []; foreach (Tolerant\DiagnosticsProvider::getDiagnostics($this->stmts) as $_error) { - $this->diagnostics = []; $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); $this->diagnostics[] = new Diagnostic( From 4ac56d83a460954815889ebd045c1a6ff1cc6eb9 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 28 Mar 2017 13:53:53 -0700 Subject: [PATCH 029/149] Update logging - add diagnostics for old parser - include maxRecursion levels - include option to run functions multiple times to help profile --- src/DefinitionResolver.php | 4 +- src/LoggedDefinitionResolver.php | 9 + src/LoggedDefinitionResolverTrait.php | 237 ++++++++++++++++++++++ src/LoggedTolerantDefinitionResolver.php | 195 +----------------- src/ParserKind.php | 1 + src/ParserResourceFactory.php | 27 ++- validation/frameworks/tolerant-php-parser | 1 + 7 files changed, 268 insertions(+), 206 deletions(-) create mode 100644 src/LoggedDefinitionResolver.php create mode 100644 src/LoggedDefinitionResolverTrait.php create mode 160000 validation/frameworks/tolerant-php-parser diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index b479e254..fde79dbf 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -342,7 +342,7 @@ private static function getContainingClassFqn(Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - private static function resolveVariableToNode(Node\Expr $var) + private function resolveVariableToNode(Node\Expr $var) { $n = $var; // When a use is passed, start outside the closure to not return immediatly @@ -648,7 +648,7 @@ public function resolveExpressionNodeToType($expr): Type * @param Node $class * @return Type */ - private static function resolveClassNameToType(Node $class): Type + private function resolveClassNameToType(Node $class): Type { if ($class instanceof Node\Expr) { return new Types\Mixed; diff --git a/src/LoggedDefinitionResolver.php b/src/LoggedDefinitionResolver.php new file mode 100644 index 00000000..e0a42389 --- /dev/null +++ b/src/LoggedDefinitionResolver.php @@ -0,0 +1,9 @@ +getString($param1) . ", " . $this->getString($param2) . ")\n"; + echo $callStr; + } + $start = microtime(true); + for ($i = 0; $i < self::$repeat; $i++) { + + $result = parent::$methodName($param1, $param2); + } + + $end = microtime(true) - $start; + + } else { + if (self::$logger === true) { + $callStr .= $this->getString($param1) . ")\n"; + echo $callStr; + } + $start = microtime(true); + for ($i = 0; $i < self::$repeat; $i++) { + $result = parent::$methodName($param1); + } + $end = microtime(true) - $start; + } + self::$recursion--; + if (self::$recursion === 1) { + if (!isset(self::$times[$methodName])) { + self::$times[$methodName] = $end; + } else { + self::$times[$methodName] += $end; + } + } + + if (self::$logger === true) { + if ($result instanceof Definition) { + $resultText = $result->fqn; + } elseif ($result instanceof DocBlock) { + $resultText = $result->getDescription(); + } else { + $resultText = $result ?? "NULL"; + } + echo "> RESULT[$callStr]: " . $resultText . "\n"; + } + return $result; + } + + private function getString($param) { + if ($param instanceof Tolerant\Node) { + return "[" . $param->getNodeKindName() . "] " . $param->getText(); + } + return (string)$param; + } + + /** + * Builds the declaration line for a given node. + * + * + * @param Tolerant\Node $node + * @return string + */ + public function getDeclarationLineFromNode($node): string + { + return $this->logMethod('getDeclarationLineFromNode', $node); + } + + /** + * Gets the documentation string for a node, if it has one + * + * @param Tolerant\Node $node + * @return string|null + */ + public function getDocumentationFromNode($node) + { + return $this->logMethod('getDocumentationFromNode', $node); + } + + function getDocBlock(Tolerant\Node $node) { + return $this->logMethod('getDocBlock', $node); + + } + + /** + * Create a Definition for a definition node + * + * @param Tolerant\Node $node + * @param string $fqn + * @return Definition + */ + public function createDefinitionFromNode($node, string $fqn = null): Definition + { + return $this->logMethod('createDefinitionFromNode', $node, $fqn); + } + + /** + * Given any node, returns the Definition object of the symbol that is referenced + * + * @param Tolerant\Node $node Any reference node + * @return Definition|null + */ + public function resolveReferenceNodeToDefinition($node) + { +// var_dump(array_keys(self::$instance->index->getDefinitions())); + self::$logger = true; + return $this->logMethod('resolveReferenceNodeToDefinition', $node); + } + + /** + * Given any node, returns the FQN of the symbol that is referenced + * Returns null if the FQN could not be resolved or the reference node references a variable + * + * @param Tolerant\Node $node + * @return string|null + */ + public function resolveReferenceNodeToFqn($node) { + return $this->logMethod('resolveReferenceNodeToFqn', $node); + } + + /** + * Returns the assignment or parameter node where a variable was defined + * + * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access + * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null + */ + public function resolveVariableToNode(Tolerant\Node $var) + { + return $this->logMethod('resolveVariableToNode', $var); + } + + /** + * Given an expression node, resolves that expression recursively to a type. + * If the type could not be resolved, returns Types\Mixed. + * + * @param \PhpParser\Node\Expr $expr + * @return \phpDocumentor\Reflection\Type + */ + public function resolveExpressionNodeToType($expr): Type + { + return $this->logMethod('resolveExpressionNodeToType', $expr); + } + + /** + * 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 + * + * @param Tolerant\Node || Tolerant\Token $class + * @return Type + */ + public function resolveClassNameToType($class): Type + { + return $this->logMethod('resolveClassNameToType', $class); + } + + /** + * Returns the type a reference to this symbol will resolve to. + * For properties and constants, this is the type of the property/constant. + * For functions and methods, this is the return type. + * For parameters, this is the type of the parameter. + * For classes and interfaces, this is the class type (object). + * For variables / assignments, this is the documented type or type the assignment resolves to. + * Can also be a compound type. + * If it is unknown, will be Types\Mixed. + * Returns null if the node does not have a type. + * + * @param Tolerant\Node $node + * @return \phpDocumentor\Reflection\Type|null + */ + public function getTypeFromNode($node) + { + return $this->logMethod('getTypeFromNode', $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 + * + * @param Tolerant\Node $node + * @return string|null + */ + public static function getDefinedFqn($node) + { + $result = parent::getDefinedFqn($node); + if (self::$logger === true) { + echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; + var_dump($result); + } + return $result; + } + + public function printLogs() { + var_dump(self::$times); + var_dump(self::$maxRecursion); + } +} diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php index 7fb79820..9466ce06 100644 --- a/src/LoggedTolerantDefinitionResolver.php +++ b/src/LoggedTolerantDefinitionResolver.php @@ -3,200 +3,7 @@ namespace LanguageServer; -use LanguageServer\Protocol\TolerantSymbolInformation; -use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard as PrettyPrinter; -use phpDocumentor\Reflection\{ - DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver -}; -use LanguageServer\Protocol\SymbolInformation; -use LanguageServer\Index\ReadableIndex; -use Microsoft\PhpParser as Tolerant; - class LoggedTolerantDefinitionResolver extends TolerantDefinitionResolver { - - private static $logger = false; - - private static $stackLevel = 0; - /** - * @param ReadableIndex $index - */ - public function __construct(ReadableIndex $index) - { - self::$logger = false; - parent::__construct($index); - } - - public function logMethod($methodName, $param1, $param2 = -1) { - $callStr = "FUNCTION: $methodName("; - if ($param2 !== -1) { - $callStr .= $this->getString($param1) . ", " . $this->getString($param2) . ")\n"; - if (self::$logger === true) { - echo $callStr; - } - $result = parent::$methodName($param1, $param2); - } else { - $callStr .= $this->getString($param1) . ")\n"; - if (self::$logger === true) { - echo $callStr; - } - $result = parent::$methodName($param1); - } - - if (self::$logger === true) { - if ($result instanceof Definition) { - $resultText = $result->fqn; - } elseif ($result instanceof DocBlock) { - $resultText = $result->getDescription(); - } else { - $resultText = $result ?? "NULL"; - } - echo "> RESULT[$callStr]: " . $resultText . "\n"; - } - return $result; - } - - private function getString($param) { - if ($param instanceof Tolerant\Node) { - return "[" . $param->getNodeKindName() . "] " . $param->getText(); - } - return (string)$param; - } - - /** - * Builds the declaration line for a given node. - * - * - * @param Tolerant\Node $node - * @return string - */ - public function getDeclarationLineFromNode($node): string - { - return $this->logMethod('getDeclarationLineFromNode', $node); - } - - /** - * Gets the documentation string for a node, if it has one - * - * @param Tolerant\Node $node - * @return string|null - */ - public function getDocumentationFromNode($node) - { - return $this->logMethod('getDocumentationFromNode', $node); - } - - function getDocBlock(Tolerant\Node $node) { - return $this->logMethod('getDocBlock', $node); - - } - - /** - * Create a Definition for a definition node - * - * @param Tolerant\Node $node - * @param string $fqn - * @return Definition - */ - public function createDefinitionFromNode($node, string $fqn = null): Definition - { - return $this->logMethod('createDefinitionFromNode', $node, $fqn); - } - - /** - * Given any node, returns the Definition object of the symbol that is referenced - * - * @param Tolerant\Node $node Any reference node - * @return Definition|null - */ - public function resolveReferenceNodeToDefinition($node) - { - var_dump(array_keys($this->index->getDefinitions())); - self::$logger = true; - return $this->logMethod('resolveReferenceNodeToDefinition', $node); - } - - /** - * Given any node, returns the FQN of the symbol that is referenced - * Returns null if the FQN could not be resolved or the reference node references a variable - * - * @param Tolerant\Node $node - * @return string|null - */ - public function resolveReferenceNodeToFqn($node) { - return $this->logMethod('resolveReferenceNodeToFqn', $node); - } - - /** - * Returns the assignment or parameter node where a variable was defined - * - * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access - * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null - */ - public function resolveVariableToNode(Tolerant\Node $var) - { - return $this->logMethod('resolveVariableToNode', $var); - } - - /** - * Given an expression node, resolves that expression recursively to a type. - * If the type could not be resolved, returns Types\Mixed. - * - * @param \PhpParser\Node\Expr $expr - * @return \phpDocumentor\Reflection\Type - */ - public function resolveExpressionNodeToType($expr): Type - { - return $this->logMethod('resolveExpressionNodeToType', $expr); - } - - /** - * 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 - * - * @param Tolerant\Node || Tolerant\Token $class - * @return Type - */ - public function resolveClassNameToType($class): Type - { - return $this->logMethod('resolveClassNameToType', $class); - } - - /** - * Returns the type a reference to this symbol will resolve to. - * For properties and constants, this is the type of the property/constant. - * For functions and methods, this is the return type. - * For parameters, this is the type of the parameter. - * For classes and interfaces, this is the class type (object). - * For variables / assignments, this is the documented type or type the assignment resolves to. - * Can also be a compound type. - * If it is unknown, will be Types\Mixed. - * Returns null if the node does not have a type. - * - * @param Tolerant\Node $node - * @return \phpDocumentor\Reflection\Type|null - */ - public function getTypeFromNode($node) - { - return $this->logMethod('getTypeFromNode', $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 - * - * @param Tolerant\Node $node - * @return string|null - */ - public static function getDefinedFqn($node) - { - $result = parent::getDefinedFqn($node); - if (self::$logger === true) { - echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; - var_dump($result); - } - return $result; - } + use LoggedDefinitionResolverTrait; } diff --git a/src/ParserKind.php b/src/ParserKind.php index b09145e5..a7944a4e 100644 --- a/src/ParserKind.php +++ b/src/ParserKind.php @@ -8,4 +8,5 @@ class ParserKind const PHP_PARSER = 1; const TOLERANT_PHP_PARSER = 2; const DIAGNOSTIC_TOLERANT_PHP_PARSER = 3; + const DIAGNOSTIC_PHP_PARSER = 4; } \ No newline at end of file diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 08615225..d66dc843 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,10 +6,14 @@ use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; - + const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; + private static function getParserKind () { + global $parserKind; + return isset($parserKind) ? $parserKind : self::PARSER_KIND; + } + public static function getParser() { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { + if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) { return new Parser; } else { return new Tolerant\Parser; @@ -17,18 +21,21 @@ public static function getParser() { } public static function getDefinitionResolver(ReadableIndex $index) { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { - return new DefinitionResolver($index); - } elseif (self::PARSER_KIND === ParserKind::TOLERANT_PHP_PARSER) { - return new TolerantDefinitionResolver($index); - } elseif (self::PARSER_KIND === ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER) { - return new LoggedTolerantDefinitionResolver($index); + switch (self::getParserKind()) { + case ParserKind::PHP_PARSER: + return new DefinitionResolver($index); + case ParserKind::TOLERANT_PHP_PARSER: + return new TolerantDefinitionResolver($index); + case ParserKind::DIAGNOSTIC_PHP_PARSER: + return new LoggedDefinitionResolver($index); + case ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER: + return new LoggedTolerantDefinitionResolver($index); } } public static function getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri) { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { + if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) { return new TreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); } else { return new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); diff --git a/validation/frameworks/tolerant-php-parser b/validation/frameworks/tolerant-php-parser new file mode 160000 index 00000000..6ce1e1f9 --- /dev/null +++ b/validation/frameworks/tolerant-php-parser @@ -0,0 +1 @@ +Subproject commit 6ce1e1f978f1c17d555b83660b97899f0d9dbeec From a69c93b28b9c1be88ae48b44b3eab6be87bc51c3 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 28 Mar 2017 13:55:10 -0700 Subject: [PATCH 030/149] Print null docs in language server perf log --- src/Indexer.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Indexer.php b/src/Indexer.php index 34ad618f..28b7d1ed 100644 --- a/src/Indexer.php +++ b/src/Indexer.php @@ -6,6 +6,7 @@ use LanguageServer\Cache\Cache; use LanguageServer\FilesFinder\FilesFinder; use LanguageServer\Index\{DependenciesIndex, Index}; +use LanguageServer\Protocol\Message; use LanguageServer\Protocol\MessageType; use Webmozart\PathUtil\Path; use Composer\Semver\VersionParser; @@ -192,11 +193,19 @@ public function index(): Promise $mem = (int)(memory_get_usage(true) / (1024 * 1024)); $this->client->window->logMessage( MessageType::INFO, - "All $count PHP files parsed in $duration seconds. $mem MiB allocated." + "All $count PHP files parsed in $duration seconds. $mem MiB allocated. " . \count($this->nullDocs) . " null docs" ); + foreach ($this->nullDocs as $nullDoc) { + $this->client->window->logMessage( + MessageType::INFO, + $nullDoc + ); + } }); } + private $nullDocs = []; + /** * @param array $files * @return Promise @@ -215,6 +224,9 @@ private function indexFiles(array $files): Promise $this->client->window->logMessage(MessageType::LOG, "Parsing $uri"); try { $document = yield $this->documentLoader->load($uri); + if ($document->getStmts() === null) { + $this->nullDocs[] = $document->getUri(); + } if (!isVendored($document, $this->composerJson)) { $this->client->textDocument->publishDiagnostics($uri, $document->getDiagnostics()); } From 42dc2c966d09a7e992b9b1d2556e1717aa5cc697 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 28 Mar 2017 13:58:48 -0700 Subject: [PATCH 031/149] Update validation tests - assert non-null ASTs - additional submodules --- .gitmodules | 3 +++ src/PhpDocument.php | 4 ++-- tests/Validation/ValidationTest.php | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3f59547b..81bcac19 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "validation/frameworks/drupal"] path = validation/frameworks/drupal url = https://github.com/drupal/drupal +[submodule "validation/frameworks/tolerant-php-parser"] + path = validation/frameworks/tolerant-php-parser + url = https://github.com/microsoft/tolerant-php-parser diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 23387f58..4ccedf3b 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -229,9 +229,9 @@ public function getUri(): string /** * Returns the AST of the document * - * @return Node[] + * @return Node[] | Tolerant\Node | null */ - public function getStmts(): array + public function getStmts() { return $this->stmts; } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 1be9e69f..b3f829e0 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -30,7 +30,7 @@ public function frameworkErrorProvider() { foreach (new RecursiveIteratorIterator($iterator) as $file) { if (strpos((string)$file, ".php") !== false) { - if ($file->getSize() < 100000 ) { + if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } } @@ -69,6 +69,8 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { $this->fail((string)$e); } + $this->assertNotNull($document->getStmts()); + if (file_exists($outFile)) { unlink($outFile); } From 105f9bf8136a4256c397585ec205257142b4a0d0 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 28 Mar 2017 14:00:50 -0700 Subject: [PATCH 032/149] Include max-recursion comparison in perf test --- Performance.php | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Performance.php b/Performance.php index cfb0076b..1416c95d 100644 --- a/Performance.php +++ b/Performance.php @@ -5,6 +5,7 @@ use Exception; use LanguageServer\Index\Index; +use LanguageServer\ParserKind; use LanguageServer\ParserResourceFactory; use LanguageServer\PhpDocument; use phpDocumentor\Reflection\DocBlockFactory; @@ -32,25 +33,50 @@ throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); } +$start = microtime(true); + +$documents = []; foreach ($testProviderArray as $idx=>$testCaseFile) { - if ($idx > 20) { - exit(); + if ($idx > 100) { + break; } - echo "$idx\n"; + echo "$idx=>$testCaseFile\n"; $fileContents = file_get_contents($testCaseFile); - $parser = ParserResourceFactory::getParser(); - $docBlockFactory = DocBlockFactory::createInstance(); - $index = new Index; + $docBlockFactory = DocBlockFactory::createInstance(); + $index = new Index; + + $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; + + $maxRecursion = []; + foreach ($parserKinds as $kind) { + global $parserKind; + $parserKind = $kind; + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $parser = ParserResourceFactory::getParser(); + try { $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + if ($document->getStmts() === null) { + echo "AHHHHHHHHHH\n"; + } + if (isset($maxRecursion[$testCaseFile]) && $maxRecursion[$testCaseFile] !== ($max = $definitionResolver::$maxRecursion)) { + $documents[] = "$testCaseFile\n => OLD: $maxRecursion[$testCaseFile], NEW: $max"; + } + $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; +// $definitionResolver->printLogs(); } catch (\Exception $e) { - echo "AAAHH\n"; +// echo "AAAHH\n"; continue; } + } } +echo "------------------------------\n"; +var_dump($documents); + +echo "Time: " . (microtime(true) - $start) . PHP_EOL; From a5fec9452ba96c724c8a08ff77f9d8773a300a15 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 28 Mar 2017 14:02:26 -0700 Subject: [PATCH 033/149] Fix misc. issues in language server --- src/TolerantDefinitionResolver.php | 11 ++++--- src/TolerantTreeAnalyzer.php | 48 +++++++++++++++--------------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 7b60ff99..fbf30aa7 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -326,17 +326,17 @@ public function resolveReferenceNodeToFqn($node) { } }*/ - else if (($node instanceof Tolerant\Node\Expression\CallExpression && - ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) || ( + else if ( + $node instanceof Tolerant\Node\Expression\CallExpression && + (($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression || ($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression - )) { + )) { if ($access->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition if right-hand side is expression return null; } // Get the type of the left-hand expression $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); -// var_dump($varType); if ($varType instanceof Types\Compound) { // For compound types, use the first FQN we find // (popular use case is ClassName|null) @@ -363,7 +363,6 @@ public function resolveReferenceNodeToFqn($node) { // Left-hand expression could not be resolved to a class return null; } else { -// var_dump("AAAHHHHH"); $classFqn = substr((string)$varType->getFqsen(), 1); // TODO @@ -597,7 +596,7 @@ public function resolveExpressionNodeToType($expr): Type if ($expr instanceof Tolerant\Node\Expression\CallExpression && !($expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression)) { - + // Find the function definition if ($expr->callableExpression instanceof Tolerant\Node\Expression) { // Cannot get type for dynamic function call diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 4e6b9942..39dd7eaa 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -45,15 +45,28 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso // TODO - docblock errors - foreach ($this->stmts->getDescendantNodes() as $node) { - $fqn = $definitionResolver::getDefinedFqn($node); - // Only index definitions with an FQN (no variables) - if ($fqn === null) { - continue; - } - $this->definitionNodes[$fqn] = $node; - $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); - } + foreach ($this->stmts->getDescendantNodesAndTokens() as $node) { + if ($node instanceof Tolerant\Node) { + $fqn = $definitionResolver::getDefinedFqn($node); + // Only index definitions with an FQN (no variables) + if ($fqn === null) { + continue; + } + $this->definitionNodes[$fqn] = $node; + $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + } + if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); + + $this->diagnostics[] = new Diagnostic( + $_error->message, + new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->start->character) + ) + ); + } + } foreach ($this->stmts->getDescendantNodes() as $node) { $parent = $node->parent; @@ -90,7 +103,7 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso // Namespaced constant access and function calls also need to register a reference // to the global version because PHP falls back to global at runtime // http://php.net/manual/en/language.namespaces.fallback.php - if ($definitionResolver::isConstantFetch($node) || + if (TolerantDefinitionResolver::isConstantFetch($node) || ($parent instanceof Tolerant\Node\Expression\CallExpression && !( $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression @@ -102,23 +115,10 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso } } } - - $this->diagnostics = []; - foreach (Tolerant\DiagnosticsProvider::getDiagnostics($this->stmts) as $_error) { - $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); - - $this->diagnostics[] = new Diagnostic( - $_error->message, - new Range( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->start->character) - ) - ); - } } public function getDiagnostics() { - return $this->diagnostics; + return $this->diagnostics ?? []; } private function addReference(string $fqn, Tolerant\Node $node) From d62bdeac82ab66fb0cddc606dd4d2f4e025606d7 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 29 Mar 2017 10:45:38 -0700 Subject: [PATCH 034/149] revert earlier change to fix tests --- src/TolerantDefinitionResolver.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index fbf30aa7..b3d16b3e 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -327,10 +327,10 @@ public function resolveReferenceNodeToFqn($node) { }*/ else if ( - $node instanceof Tolerant\Node\Expression\CallExpression && - (($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression || - ($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression - )) { + ($node instanceof Tolerant\Node\Expression\CallExpression && + ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) || ( + ($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) + ) { if ($access->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition if right-hand side is expression return null; From 7d68e3acc3609aa05b38cfc221f8c4dffd167d07 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 29 Mar 2017 10:48:53 -0700 Subject: [PATCH 035/149] Only traverse tree 1x for definitions + references --- src/TolerantTreeAnalyzer.php | 101 +++++++++++++++++------------------ 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 39dd7eaa..8abc5ceb 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -49,12 +49,57 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso if ($node instanceof Tolerant\Node) { $fqn = $definitionResolver::getDefinedFqn($node); // Only index definitions with an FQN (no variables) - if ($fqn === null) { - continue; + if ($fqn !== null) { + $this->definitionNodes[$fqn] = $node; + $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); } - $this->definitionNodes[$fqn] = $node; - $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + + $parent = $node->parent; + if ( + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + && !( + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->memberName instanceof Tolerant\Token + )) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()) + ) { + continue; + } + $fqn = $definitionResolver->resolveReferenceNodeToFqn($node); + if ($fqn !== null) { + $this->addReference($fqn, $node); + + if ( + $node instanceof Tolerant\Node\QualifiedName + && $node->isQualifiedName() + && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } + } + + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if (TolerantDefinitionResolver::isConstantFetch($node) || + ($parent instanceof Tolerant\Node\Expression\CallExpression + && !( + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); + } + } + } } + if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); @@ -67,54 +112,6 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso ); } } - - foreach ($this->stmts->getDescendantNodes() as $node) { - $parent = $node->parent; - if ( - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - && !( - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->memberName instanceof Tolerant\Token - )) - || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()) - ) { - continue; - } - $fqn = $definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn === null) { - continue; - } - $this->addReference($fqn, $node); - - if ( - $node instanceof Tolerant\Node\QualifiedName - && $node->isQualifiedName() - && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() - ) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); - } - } - - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if (TolerantDefinitionResolver::isConstantFetch($node) || - ($parent instanceof Tolerant\Node\Expression\CallExpression - && !( - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - ))) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); - } - } - } } public function getDiagnostics() { From fa52aef28a9bca9c22d7ffba18ad141d1fbba590 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 12:29:58 -0700 Subject: [PATCH 036/149] revert isClass -> canBeInstantiated - ensures consistency w/ old parser --- src/TolerantDefinitionResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index b3d16b3e..e42a6296 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -177,7 +177,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition // this determines whether the suggestion will show after "new" // TODO name - $def->isClass = $node instanceof Tolerant\Node\Statement\ClassDeclaration; + $def->canBeInstantiated = $node instanceof Tolerant\Node\Statement\ClassDeclaration; $def->isGlobal = ( $node instanceof Tolerant\Node\Statement\InterfaceDeclaration From 651e6be08ad3009c95db1c09fdaa8c3b9d4f6f67 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 12:30:46 -0700 Subject: [PATCH 037/149] add definition comparison to validation tests --- tests/Validation/ValidationTest.php | 46 ++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index b3f829e0..dd4e4da3 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -6,6 +6,7 @@ use Exception; use LanguageServer\Index\Index; +use LanguageServer\ParserKind; use LanguageServer\ParserResourceFactory; use LanguageServer\PhpDocument; use phpDocumentor\Reflection\DocBlockFactory; @@ -16,6 +17,7 @@ use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use Sabre\Event\Loop; +use Microsoft\PhpParser as Tolerant; class ValidationTest extends TestCase { @@ -29,7 +31,7 @@ public function frameworkErrorProvider() { $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos((string)$file, ".php") !== false) { + if (strpos((string)$file, ".php") !== false && strpos((string)$file, "drupal") === false) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } @@ -76,4 +78,46 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { } // echo json_encode($parser->getErrors($sourceFile)); } + + /** + * @dataProvider frameworkErrorProvider + */ + public function testDefinitionErrors($testCaseFile, $frameworkName) { + $fileContents = file_get_contents($testCaseFile); + echo "$testCaseFile\n"; + + $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; + $maxRecursion = []; + $definitions = []; + + foreach ($parserKinds as $kind) { + global $parserKind; + $parserKind = $kind; + + $index = new Index; + $docBlockFactory = DocBlockFactory::createInstance(); + + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $parser = ParserResourceFactory::getParser(); + + try { + $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Exception $e) { + continue; + } + + $fqns = []; + foreach ($document->getDefinitions() as $defn) { + $fqns[] = $defn->fqn; + } + + if (isset($definitions[$testCaseFile])) { + var_dump($definitions[$testCaseFile]); + $this->assertEquals($definitions[$testCaseFile], $fqns); + } + + $definitions[$testCaseFile] = $fqns; + $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; + } + } } \ No newline at end of file From 21cee776248d36628beac7fec2f3a6204339fa2b Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 12:42:49 -0700 Subject: [PATCH 038/149] include traits and interfaces when retrieving fqn --- src/TolerantDefinitionResolver.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index e42a6296..0b538e2b 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -1095,7 +1095,7 @@ public static function getDefinedFqn($node) // } else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name - $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class); if (!isset($class->name)) { // Ignore anonymous classes return null; @@ -1116,7 +1116,9 @@ public static function getDefinedFqn($node) else if ( $node instanceof Tolerant\Node\Expression\Variable && ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && - ($classDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class)) !== null) + ($classDeclaration = + $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class) + ) !== null) { if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name From b02c164c2b153b21ea439e85af395138608a8e83 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 13:13:47 -0700 Subject: [PATCH 039/149] fix property / constant ancestor check --- src/TolerantDefinitionResolver.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 0b538e2b..2577bd34 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -1095,7 +1095,11 @@ public static function getDefinedFqn($node) // } else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name - $class = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class); + $class = $node->getFirstAncestor( + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ); if (!isset($class->name)) { // Ignore anonymous classes return null; @@ -1117,7 +1121,11 @@ public static function getDefinedFqn($node) $node instanceof Tolerant\Node\Expression\Variable && ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && ($classDeclaration = - $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class) + $node->getFirstAncestor( + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ) ) !== null) { if ($propertyDeclaration->isStatic()) { @@ -1143,7 +1151,11 @@ public static function getDefinedFqn($node) } if ($constDeclaration instanceof Tolerant\Node\ClassConstDeclaration) { // Class constant: use ClassName::CONSTANT_NAME as name - $classDeclaration = $constDeclaration->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + $classDeclaration = $constDeclaration->getFirstAncestor( + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ); if (!isset($classDeclaration->name)) { return null; } From 3d5d46d4e7f7d55dea2016cada4509e4061bebbb Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 14:18:19 -0700 Subject: [PATCH 040/149] don't use generator during iteration --- src/TolerantTreeAnalyzer.php | 159 ++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 66 deletions(-) diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 8abc5ceb..e1046fd5 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -25,7 +25,9 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface { /** @var Tolerant\Node */ private $stmts; - private $diagnostics; + private $diagnostics; + + private $content; /** * TolerantTreeAnalyzer constructor. @@ -45,73 +47,98 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso // TODO - docblock errors - foreach ($this->stmts->getDescendantNodesAndTokens() as $node) { - if ($node instanceof Tolerant\Node) { - $fqn = $definitionResolver::getDefinedFqn($node); - // Only index definitions with an FQN (no variables) - if ($fqn !== null) { - $this->definitionNodes[$fqn] = $node; - $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + $this->collectDefinitionsAndReferences($this->stmts); + } + + public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { + foreach ($stmts::CHILD_NAMES as $name) { + $node = $stmts->$name; + + if ($node === null) { + continue; + } + + if (\is_array($node)) { + foreach ($node as $child) { + if ($child instanceof Tolerant\Node) { + $this->update($child); + } + } + continue; + } + + if ($node instanceof Tolerant\Node) { + $this->update($node); + } + + if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); + + $this->diagnostics[] = new Diagnostic( + $_error->message, + new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->start->character) + ) + ); + } + } + } + + public function update($node) { + $fqn = ($this->definitionResolver)::getDefinedFqn($node); + // Only index definitions with an FQN (no variables) + if ($fqn !== null) { + $this->definitionNodes[$fqn] = $node; + $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + } + + $parent = $node->parent; + if (!( + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + && !( + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->memberName instanceof Tolerant\Token + )) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) + ) { + + $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); + if ($fqn !== null) { + $this->addReference($fqn, $node); + + if ( + $node instanceof Tolerant\Node\QualifiedName + && $node->isQualifiedName() + && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } } - $parent = $node->parent; - if ( - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - && !( - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->memberName instanceof Tolerant\Token - )) - || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()) - ) { - continue; - } - $fqn = $definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn !== null) { - $this->addReference($fqn, $node); - - if ( - $node instanceof Tolerant\Node\QualifiedName - && $node->isQualifiedName() - && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() - ) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); - } - } - - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if (TolerantDefinitionResolver::isConstantFetch($node) || - ($parent instanceof Tolerant\Node\Expression\CallExpression - && !( - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - ))) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); - } - } - } - } - - if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $content); - - $this->diagnostics[] = new Diagnostic( - $_error->message, - new Range( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->start->character) - ) - ); - } - } + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if (TolerantDefinitionResolver::isConstantFetch($node) || + ($parent instanceof Tolerant\Node\Expression\CallExpression + && !( + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); + } + } + } + } + + $this->collectDefinitionsAndReferences($node); } public function getDiagnostics() { From 864a7a862169ad59c46b3cb500eab112d7f1e4f0 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 14:19:55 -0700 Subject: [PATCH 041/149] test multipe frameworks in perf test script --- Performance.php | 90 ++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Performance.php b/Performance.php index 1416c95d..7b8e6b36 100644 --- a/Performance.php +++ b/Performance.php @@ -18,65 +18,65 @@ use Sabre\Event\Loop; $totalSize = 0; -$testProviderArray = array(); -$iterator = new RecursiveDirectoryIterator(__DIR__ . "/validation/frameworks/WordPress"); +$frameworks = ["drupal", "wordpress", "php-language-server", "tolerant-php-parser", "math-php", "symfony", "CodeIgniter", "cakephp"]; -foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos((string)$file, ".php") !== false) { - $totalSize += $file->getSize(); - $testProviderArray[] = $file->getPathname(); - } -} - -if (count($testProviderArray) === 0) { - throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); -} +foreach($frameworks as $framework) { + $iterator = new RecursiveDirectoryIterator(__DIR__ . "/validation/frameworks/$framework"); + $testProviderArray = array(); -$start = microtime(true); + foreach (new RecursiveIteratorIterator($iterator) as $file) { + if (strpos((string)$file, ".php") !== false) { + $totalSize += $file->getSize(); + $testProviderArray[] = $file->getPathname(); + } + } -$documents = []; -foreach ($testProviderArray as $idx=>$testCaseFile) { - if ($idx > 100) { - break; + if (count($testProviderArray) === 0) { + throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); } - echo "$idx=>$testCaseFile\n"; - $fileContents = file_get_contents($testCaseFile); - - $docBlockFactory = DocBlockFactory::createInstance(); - $index = new Index; + $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; + foreach ($parserKinds as $kind) { + $start = microtime(true); + + foreach ($testProviderArray as $idx => $testCaseFile) { + // if ($idx < 20) { + // continue; + // } + if (filesize($testCaseFile) > 10000) { + continue; + } + if ($idx % 1000 === 0) { + echo "$idx\n"; + } - $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; +// echo "$idx=>$testCaseFile\n"; - $maxRecursion = []; - foreach ($parserKinds as $kind) { - global $parserKind; - $parserKind = $kind; + $fileContents = file_get_contents($testCaseFile); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); + $index = new Index; + $maxRecursion = []; + $definitions = []; + global $parserKind; + $parserKind = $kind; + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $parser = ParserResourceFactory::getParser(); - try { - $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - if ($document->getStmts() === null) { - echo "AHHHHHHHHHH\n"; + try { + $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Exception $e) { + continue; } - if (isset($maxRecursion[$testCaseFile]) && $maxRecursion[$testCaseFile] !== ($max = $definitionResolver::$maxRecursion)) { - $documents[] = "$testCaseFile\n => OLD: $maxRecursion[$testCaseFile], NEW: $max"; - } - $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; -// $definitionResolver->printLogs(); - } catch (\Exception $e) { -// echo "AAAHH\n"; - continue; } + + echo "------------------------------\n"; + + echo "Time [$framework, $kind]: " . (microtime(true) - $start) . PHP_EOL; + } } -echo "------------------------------\n"; -var_dump($documents); - -echo "Time: " . (microtime(true) - $start) . PHP_EOL; From 59965448f0030c4b6f567dc44b23bd2aa4816ed1 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 14:20:45 -0700 Subject: [PATCH 042/149] Update definition validation tests --- tests/Validation/ValidationTest.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index dd4e4da3..aa87401e 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -31,7 +31,7 @@ public function frameworkErrorProvider() { $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos((string)$file, ".php") !== false && strpos((string)$file, "drupal") === false) { + if (strpos(\strrev((string)$file), \strrev(".php")) === 0) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } @@ -89,6 +89,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; $maxRecursion = []; $definitions = []; + $types = []; foreach ($parserKinds as $kind) { global $parserKind; @@ -106,17 +107,25 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { continue; } + if ($document->getStmts() === null) { + $this->markTestSkipped("null AST"); + } + $fqns = []; + $currentTypes = []; foreach ($document->getDefinitions() as $defn) { $fqns[] = $defn->fqn; + $currentTypes[$defn->fqn] = $defn->type; } if (isset($definitions[$testCaseFile])) { var_dump($definitions[$testCaseFile]); $this->assertEquals($definitions[$testCaseFile], $fqns); +// $this->assertEquals($types[$testCaseFile], $currentTypes); } $definitions[$testCaseFile] = $fqns; + $types[$testCaseFile] = $currentTypes; $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; } } From 5bd827fa4d398546bf21350cfdb56034450b64a7 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 19:39:25 -0700 Subject: [PATCH 043/149] include validation tests in separate test group --- tests/Validation/ValidationTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index aa87401e..62afea51 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -45,6 +45,7 @@ public function frameworkErrorProvider() { } /** + * @group validation * @dataProvider frameworkErrorProvider */ public function testFramworkErrors($testCaseFile, $frameworkName) { @@ -80,6 +81,7 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { } /** + * @group validation * @dataProvider frameworkErrorProvider */ public function testDefinitionErrors($testCaseFile, $frameworkName) { From 219c018ab2756d8d16678806e33b092f35f0566a Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 21:58:08 -0700 Subject: [PATCH 044/149] Disclude anonymous class members from definitions --- src/TolerantDefinitionResolver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 2577bd34..820d5b2b 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -1096,6 +1096,7 @@ public static function getDefinedFqn($node) else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name $class = $node->getFirstAncestor( + Tolerant\Node\Expression\ObjectCreationExpression::class, Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class @@ -1122,11 +1123,12 @@ public static function getDefinedFqn($node) ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && ($classDeclaration = $node->getFirstAncestor( + Tolerant\Node\Statement\ObjectCreationExpression::class, Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class ) - ) !== null) + ) !== null && !($classDeclaration instanceof Tolerant\Node\Statement\ObjectCreationExpression)) { if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name From e6ba591e9503fa4d35390936d45bd4ee543de9d1 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Mon, 10 Apr 2017 21:58:33 -0700 Subject: [PATCH 045/149] Catch all errors in perf test --- Performance.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Performance.php b/Performance.php index 7b8e6b36..c1103000 100644 --- a/Performance.php +++ b/Performance.php @@ -68,7 +68,7 @@ try { $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (\Exception $e) { + } catch (\Throwable $e) { continue; } } From 981b74a6dbc12c3d4d868d61bd03510ba5c0dc7b Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 11 Apr 2017 12:52:24 -0700 Subject: [PATCH 046/149] don't get docblock comment for namespace definition nodes --- src/TolerantDefinitionResolver.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 820d5b2b..9a3b5c14 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -132,12 +132,13 @@ public function getDocumentationFromNode($node) } } // for everything else, get the doc block summary corresponding to the current node. - else { + elseif (!($node instanceof Tolerant\Node\Statement\NamespaceDefinition)) { $docBlock = $this->getDocBlock($node); if ($docBlock !== null) { return $docBlock->getSummary(); } } + return null; } function getDocBlock(Tolerant\Node $node) { @@ -145,12 +146,12 @@ function getDocBlock(Tolerant\Node $node) { $namespaceDefinition = $node->getNamespaceDefinition(); $context = null; if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { - $name = (string)$namespaceDefinition->name->getNamespacedName(); list($namespaceImportTable,,) = $namespaceDefinition->name->getImportTablesForCurrentScope($namespaceDefinition); foreach ($namespaceImportTable as $alias=>$name) { $namespaceImportTable[$alias] = (string)$name; } - $context = new Types\Context($name, $namespaceImportTable); + $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); + $context = new Types\Context($namespaceName, $namespaceImportTable); } $docCommentText = $node->getDocCommentText(); @@ -190,6 +191,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition || $node instanceof Tolerant\Node\Statement\FunctionDeclaration || $node instanceof Tolerant\Node\Statement\ConstDeclaration + || $node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration // || $node instanceof Tolerant\Node\ClassConstDeclaration ); @@ -201,16 +203,16 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition ); $def->fqn = $fqn; if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { + $def->extends = []; // TODO - don't instantiate array if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { - $def->extends = []; $def->extends[] = (string)$node->classBaseClause->baseClass->getResolvedName(); } // TODO what about class interfaces } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { + $def->extends = []; if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { - $def->extends = []; foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { - $def->extends[] = $n->getText() ?? $n->getText($node->getFileContents()); + $def->extends[] = (string)$n->getResolvedName(); } } } From 57ebd58b6c8f53b7f942aebe9b85551184853abb Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 11 Apr 2017 12:54:20 -0700 Subject: [PATCH 047/149] Update validation tests to verify more definition properties, references --- src/Index/Index.php | 2 +- tests/Validation/ValidationTest.php | 55 ++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/Index/Index.php b/src/Index/Index.php index 5c24813e..78a09ad5 100644 --- a/src/Index/Index.php +++ b/src/Index/Index.php @@ -26,7 +26,7 @@ class Index implements ReadableIndex, \Serializable * * @var string[][] */ - private $references = []; + public $references = []; /** * @var bool diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 62afea51..0db17b51 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -28,6 +28,9 @@ public function frameworkErrorProvider() { $testProviderArray = array(); foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); + if ($frameworkName !== "wordpress") { + continue; + } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { @@ -80,6 +83,15 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { // echo json_encode($parser->getErrors($sourceFile)); } + private $index = []; + + private function getIndex($kind) { + if (!isset($this->index[$kind])) { + $this->index[$kind] = new Index(); + } + return $this->index[$kind]; + } + /** * @group validation * @dataProvider frameworkErrorProvider @@ -91,13 +103,19 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; $maxRecursion = []; $definitions = []; + $instantiated = []; $types = []; + $symbolInfo = []; + $extend = []; + $isGlobal = []; + $documentation = []; + $isStatic = []; foreach ($parserKinds as $kind) { global $parserKind; $parserKind = $kind; - $index = new Index; + $index = $this->getIndex($kind); $docBlockFactory = DocBlockFactory::createInstance(); $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); @@ -115,19 +133,48 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $fqns = []; $currentTypes = []; + $canBeInstantiated = []; + $symbols = []; + $extends = []; + $global = []; + $docs = []; + $static = []; foreach ($document->getDefinitions() as $defn) { $fqns[] = $defn->fqn; $currentTypes[$defn->fqn] = $defn->type; + $canBeInstantiated[$defn->fqn] = $defn->canBeInstantiated; + + $defn->symbolInformation->location = null; + $symbols[$defn->fqn] = $defn->symbolInformation; + + $extends[$defn->fqn] = $defn->extends; + $global[$defn->fqn] = $defn->isGlobal; + $docs[$defn->fqn] = $defn->documentation; + $static[$defn->fqn] = $defn->isStatic; } if (isset($definitions[$testCaseFile])) { - var_dump($definitions[$testCaseFile]); - $this->assertEquals($definitions[$testCaseFile], $fqns); -// $this->assertEquals($types[$testCaseFile], $currentTypes); + $this->assertEquals($definitions[$testCaseFile], $fqns, 'defn->fqn does not match'); +// $this->assertEquals($types[$testCaseFile], $currentTypes, "defn->type does not match"); + $this->assertEquals($instantiated[$testCaseFile], $canBeInstantiated, "defn->canBeInstantiated does not match"); + $this->assertEquals($extend[$testCaseFile], $extends, 'defn->extends does not match'); + $this->assertEquals($isGlobal[$testCaseFile], $global, 'defn->isGlobal does not match'); + $this->assertEquals($documentation[$testCaseFile], $docs, 'defn->documentation does not match'); + $this->assertEquals($isStatic[$testCaseFile], $static, 'defn->isStatic does not match'); + + $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); + $this->assertEquals($this->getIndex($parserKinds[0])->references, $this->getIndex($parserKinds[1])->references); } $definitions[$testCaseFile] = $fqns; $types[$testCaseFile] = $currentTypes; + $instantiated[$testCaseFile] = $canBeInstantiated; + $symbolInfo[$testCaseFile] = $symbols; + $extend[$testCaseFile] = $extends; + $isGlobal[$testCaseFile] = $global; + $documentation[$testCaseFile] = $docs; + $isStatic[$testCaseFile] = $static; + $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; } } From 39fe9dc7bcb3ebbecaddd9da13331f610e6f6b63 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Tue, 11 Apr 2017 16:24:35 -0700 Subject: [PATCH 048/149] fix issue where vars not being resolved to corresponding parameter definitions, update logging and validation tests --- src/DefinitionResolver.php | 6 ++++-- src/LoggedDefinitionResolverTrait.php | 15 +++++++++------ src/TolerantDefinitionResolver.php | 7 ++++--- tests/Validation/ValidationTest.php | 7 +++++++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index fde79dbf..e3dc20d1 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -342,7 +342,7 @@ private static function getContainingClassFqn(Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - private function resolveVariableToNode(Node\Expr $var) + public function resolveVariableToNode($var) { $n = $var; // When a use is passed, start outside the closure to not return immediatly @@ -401,6 +401,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\This; } // Find variable definition + $defNode = $this->resolveVariableToNode($expr); if ($defNode instanceof Node\Expr) { return $this->resolveExpressionNodeToType($defNode); @@ -748,7 +749,8 @@ public function getTypeFromNode($node) // Resolve a string like "bool" to a type object return $this->typeResolver->resolve($node->returnType); } - return new Types\Object_(new Fqsen('\\' . (string)$node->returnType)); + return new Types\Mixed; +// return new Types\Object_(new Fqsen('\\' . (string)$node->returnType)); } // Unknown return type return new Types\Mixed; diff --git a/src/LoggedDefinitionResolverTrait.php b/src/LoggedDefinitionResolverTrait.php index 7208048f..164076d4 100644 --- a/src/LoggedDefinitionResolverTrait.php +++ b/src/LoggedDefinitionResolverTrait.php @@ -44,7 +44,7 @@ public function logMethod($methodName, $param1, $param2 = -1) { if ($param2 !== -1) { if (self::$logger === true) { $callStr .= $this->getString($param1) . ", " . $this->getString($param2) . ")\n"; - echo $callStr; + echo str_repeat("\t", self::$recursion) . $callStr; } $start = microtime(true); for ($i = 0; $i < self::$repeat; $i++) { @@ -57,7 +57,7 @@ public function logMethod($methodName, $param1, $param2 = -1) { } else { if (self::$logger === true) { $callStr .= $this->getString($param1) . ")\n"; - echo $callStr; + echo str_repeat("\t", self::$recursion) . $callStr; } $start = microtime(true); for ($i = 0; $i < self::$repeat; $i++) { @@ -82,14 +82,17 @@ public function logMethod($methodName, $param1, $param2 = -1) { } else { $resultText = $result ?? "NULL"; } - echo "> RESULT[$callStr]: " . $resultText . "\n"; + echo str_repeat("\t", self::$recursion + 1) . "> RESULT[$callStr]: " . $resultText . "\n"; } return $result; } private function getString($param) { if ($param instanceof Tolerant\Node) { - return "[" . $param->getNodeKindName() . "] " . $param->getText(); + return "[" . $param->getNodeKindName() . "] " . \strtok($param->getText(), "\n"); + } elseif ($param instanceof Node) { + $pretty = isset($param->name) ? (string) $param->name : "UNKNOWN"; + return "[" . $param->getType() . "] " . \strtok($pretty, "\n"); } return (string)$param; } @@ -143,7 +146,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition public function resolveReferenceNodeToDefinition($node) { // var_dump(array_keys(self::$instance->index->getDefinitions())); - self::$logger = true; + self::$logger = false; return $this->logMethod('resolveReferenceNodeToDefinition', $node); } @@ -164,7 +167,7 @@ public function resolveReferenceNodeToFqn($node) { * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - public function resolveVariableToNode(Tolerant\Node $var) + public function resolveVariableToNode($var) { return $this->logMethod('resolveVariableToNode', $var); } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 9a3b5c14..dde12d58 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -339,6 +339,7 @@ public function resolveReferenceNodeToFqn($node) { } // Get the type of the left-hand expression $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); + if ($varType instanceof Types\Compound) { // For compound types, use the first FQN we find // (popular use case is ClassName|null) @@ -501,7 +502,7 @@ private static function getContainingClassFqn(Tolerant\Node $node) * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - public function resolveVariableToNode(Tolerant\Node $var) + public function resolveVariableToNode($var) { $n = $var; // When a use is passed, start outside the closure to not return immediately @@ -998,7 +999,7 @@ public function getTypeFromNode($node) // for variables / assignments, get the documented type the assignment resolves to. if ($node instanceof Tolerant\Node\Expression\Variable) { - $node = $node->getFirstAncestor(Tolerant\Node\Expression\AssignmentExpression::class) ?? $node; + $node = $node->parent; } if ( ($declarationNode = $node->getFirstAncestor( @@ -1047,7 +1048,7 @@ public function getTypeFromNode($node) private function getDocBlockTagForParameter($docBlock, $variableName) { $tags = $docBlock->getTagsByName('param'); foreach ($tags as $tag) { - if ($tag->getVariableName() === $variableName) { + if ($tag->getVariableName() === \ltrim($variableName, "$")) { return $tag; } } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 0db17b51..3f63942e 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -112,6 +112,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $isStatic = []; foreach ($parserKinds as $kind) { + echo ("=====================================\n"); global $parserKind; $parserKind = $kind; @@ -163,6 +164,12 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $this->assertEquals($isStatic[$testCaseFile], $static, 'defn->isStatic does not match'); $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); + + unset($this->getIndex($parserKinds[0])->references['false']); + unset($this->getIndex($parserKinds[0])->references['true']); + unset($this->getIndex($parserKinds[0])->references['null']); + unset($this->getIndex($parserKinds[1])->references['__FILE__']); + $this->assertEquals($this->getIndex($parserKinds[0])->references, $this->getIndex($parserKinds[1])->references); } From 0b0cad2dc0048288f6ed0ec4a2ac6fcb1018070f Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 12 Apr 2017 12:51:15 -0700 Subject: [PATCH 049/149] update validation test --- tests/Validation/ValidationTest.php | 45 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 3f63942e..5277247b 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -28,9 +28,9 @@ public function frameworkErrorProvider() { $testProviderArray = array(); foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); - if ($frameworkName !== "wordpress") { - continue; - } +// if ($frameworkName !== "wordpress") { +// continue; +// } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { @@ -85,11 +85,11 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { private $index = []; - private function getIndex($kind) { - if (!isset($this->index[$kind])) { - $this->index[$kind] = new Index(); + private function getIndex($kind, $frameworkName) { + if (!isset($this->index[$kind][$frameworkName])) { + $this->index[$kind][$frameworkName] = new Index(); } - return $this->index[$kind]; + return $this->index[$kind][$frameworkName]; } /** @@ -101,6 +101,8 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { echo "$testCaseFile\n"; $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; + $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; + $maxRecursion = []; $definitions = []; $instantiated = []; @@ -116,7 +118,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { global $parserKind; $parserKind = $kind; - $index = $this->getIndex($kind); + $index = $this->getIndex($kind, $frameworkName); $docBlockFactory = DocBlockFactory::createInstance(); $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); @@ -165,12 +167,25 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); - unset($this->getIndex($parserKinds[0])->references['false']); - unset($this->getIndex($parserKinds[0])->references['true']); - unset($this->getIndex($parserKinds[0])->references['null']); - unset($this->getIndex($parserKinds[1])->references['__FILE__']); - - $this->assertEquals($this->getIndex($parserKinds[0])->references, $this->getIndex($parserKinds[1])->references); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['false']); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['true']); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['null']); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['FALSE']); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['TRUE']); + unset($this->getIndex($parserKinds[0], $frameworkName)->references['NULL']); + +// unset($this->getIndex($parserKinds[1])->references['__LINE__']); +// unset($this->getIndex($parserKinds[1])->references['__FILE__']); +// unset($this->getIndex($parserKinds[1])->references['Exception']); +// unset($this->getIndex($parserKinds[1])->references['__METHOD__']); +// unset($this->getIndex($parserKinds[1])->references['__FUNCTION__']); +// unset($this->getIndex($parserKinds[1])->references['Requests_Exception']); + + try { + $this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); + } catch (\Throwable $e) { + $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); + } } $definitions[$testCaseFile] = $fqns; @@ -182,7 +197,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $documentation[$testCaseFile] = $docs; $isStatic[$testCaseFile] = $static; - $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; +// $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; } } } \ No newline at end of file From 35ce3af324ec4c94f33af3722a0946a3d6530044 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 12 Apr 2017 12:51:24 -0700 Subject: [PATCH 050/149] fix issue where call expression references weren't being properly indexed --- src/TolerantDefinitionResolver.php | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index dde12d58..b2a4a4e3 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -306,32 +306,11 @@ public function resolveReferenceNodeToFqn($node) { // does this work for function calls? return $name; } - /*elseif ($node instanceof Tolerant\Node\Expression\CallExpression || ($node = $node->getFirstAncestor(Tolerant\Node\Expression\CallExpression::class)) !== null) { - if ($node->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { - $qualifier = $node->callableExpression->scopeResolutionQualifier; - if ($qualifier instanceof Tolerant\Token) { - // resolve this/self/parent - } elseif ($qualifier instanceof Tolerant\Node\QualifiedName) { - $name = $qualifier->getResolvedName() ?? $qualifier->getNamespacedName(); - $name .= "::"; - $memberName = $node->callableExpression->memberName; - if ($memberName instanceof Tolerant\Token) { - $name .= $memberName->getText($node->getFileContents()); - } elseif ($memberName instanceof Tolerant\Node\Expression\Variable) { - $name .= $memberName->getText(); - } else { - return null; - } - $name .= "()"; - return $name; - } - } - }*/ else if ( ($node instanceof Tolerant\Node\Expression\CallExpression && - ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) || ( - ($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) + ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) + || (($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) ) { if ($access->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition if right-hand side is expression @@ -373,7 +352,8 @@ public function resolveReferenceNodeToFqn($node) { // var_dump($classFqn); } $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); - if ($node instanceof Tolerant\Node\Expression\CallExpression) { + if ($node instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression) { + // TODO - this is redundant $memberSuffix .= '()'; } // Find the right class that implements the member From d6d97121348b6f6e5a3b4d4a89ddd770304d5b8c Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 12 Apr 2017 16:53:03 -0700 Subject: [PATCH 051/149] clarify logic around scoped and member access expressions --- src/TolerantDefinitionResolver.php | 46 +++++++----------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index b2a4a4e3..295c5f76 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -308,9 +308,7 @@ public function resolveReferenceNodeToFqn($node) { } else if ( - ($node instanceof Tolerant\Node\Expression\CallExpression && - ($access = $node->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) - || (($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) + (($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) ) { if ($access->memberName instanceof Tolerant\Node\Expression) { // Cannot get definition if right-hand side is expression @@ -352,7 +350,7 @@ public function resolveReferenceNodeToFqn($node) { // var_dump($classFqn); } $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); - if ($node instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression) { + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { // TODO - this is redundant $memberSuffix .= '()'; } @@ -577,8 +575,10 @@ public function resolveExpressionNodeToType($expr): Type } } if ($expr instanceof Tolerant\Node\Expression\CallExpression && - !($expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression)) { + !( + $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) + ) { // Find the function definition if ($expr->callableExpression instanceof Tolerant\Node\Expression) { @@ -594,29 +594,6 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } } - - /* - $isScopedPropertyAccess = $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression; - $prefix = $isScopedPropertyAccess ? - $expr->callableExpression->scopeResolutionQualifier : $expr->callableExpression->dereferencableExpression; - - if ($prefix instanceof Tolerant\Node\QualifiedName) { - $name = $prefix->getNamespacedName() ?? $prefix->getText(); - } elseif ($prefix instanceof Tolerant\Token) { - // TODO DOES THIS EVER HAPPEN? - $name = $prefix->getText($expr->getText()); - } - - if (isset($name)) { - $memberNameText = $expr->callableExpression->memberName instanceof Node - ? $expr->callableExpression->memberName->getText() : $expr->callableExpression->memberName->getText($expr->getFileContents()); - $fqn = $name . ($isScopedPropertyAccess ? "::" : "->") . $memberNameText . "()"; - - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; - } - }*/ } if (strtolower((string)$expr->getText()) === 'true' || strtolower((string)$expr->getText()) === 'false') { return new Types\Boolean; @@ -630,9 +607,7 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } } - if (($expr instanceof Tolerant\Node\Expression\CallExpression && - ($access = $expr->callableExpression) instanceof Tolerant\Node\Expression\MemberAccessExpression) - || ($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { + if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { if ($access->memberName instanceof Tolerant\Node\Expression) { return new Types\Mixed; } @@ -658,7 +633,7 @@ public function resolveExpressionNodeToType($expr): Type // var_dump($classFqn); } $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); - if ($expr instanceof Tolerant\Node\Expression\CallExpression) { + if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } // var_dump($fqn); @@ -671,8 +646,7 @@ public function resolveExpressionNodeToType($expr): Type } } if ( - $expr instanceof Tolerant\Node\Expression\CallExpression && ($scopedAccess = $expr->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - || ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); // var_dump($classType); @@ -684,7 +658,7 @@ public function resolveExpressionNodeToType($expr): Type // $fqn .= '$'; // } $fqn .= $scopedAccess->memberName->getText() ?? $scopedAccess->memberName->getText($expr->getFileContents()); // TODO is there a cleaner way to do this? - if ($expr instanceof Tolerant\Node\Expression\CallExpression) { + if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } // var_dump($fqn); From ed2a591fa0664975d3772580db019235638d1b59 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 12 Apr 2017 16:54:38 -0700 Subject: [PATCH 052/149] Add stats from last perf run --- stats.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 stats.md diff --git a/stats.md b/stats.md new file mode 100644 index 00000000..cbf8bc53 --- /dev/null +++ b/stats.md @@ -0,0 +1,49 @@ +## Performance Stats + +#### drupal (-27%) +``` +old parser: 42.2 +new parser: 30.8 +``` + +#### wordpress (-33%) +``` +old parser: 3.6 +new parser: 2.4 +``` + +#### php-language-server (-17%) +``` +old parser: 13.3 +new parser: 11.0 +``` + +#### tolerant-php-parser (+59%) +``` +old parser: 3.7 +new parser: 5.9 +``` + +#### math-php (-35%) +``` +old parser: 1.7 +new parser: 1.1 +``` + +#### symfony (-23%) +``` +old parser: 18.2 +new parser: 14.1 +``` + +#### CodeIgniter (-23%) +``` +old parser: 1.8 +new parser: 1.1 +``` + +#### cakephp (-24%) +``` +old parser: 5.1 +new parser: 3.9 +``` \ No newline at end of file From 8d11ec7a9c412d67a1bb1eb6ff9a4fb5adf4dace Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 09:11:01 -0700 Subject: [PATCH 053/149] Update validation test comparison exceptions --- tests/Validation/ValidationTest.php | 30 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 5277247b..8a6c7c64 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -28,13 +28,15 @@ public function frameworkErrorProvider() { $testProviderArray = array(); foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); -// if ($frameworkName !== "wordpress") { -// continue; -// } + if ($frameworkName !== "broken") { + continue; + } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos(\strrev((string)$file), \strrev(".php")) === 0) { + if (strpos(\strrev((string)$file), \strrev(".php")) === 0 +// && strpos((string)$file, "ConsoleIoTest.php")!== false + ) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } @@ -167,12 +169,16 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['false']); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['true']); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['null']); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['FALSE']); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['TRUE']); - unset($this->getIndex($parserKinds[0], $frameworkName)->references['NULL']); + + $skipped = ['false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', 'parent', 'PARENT', 'self', 'static']; + $skipped = []; + foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { + foreach ($skipped as $s) { + if (strpos($key, $s) !== false) { + unset($this->getIndex($parserKinds[0], $frameworkName)->references[$key]); + } + } + } // unset($this->getIndex($parserKinds[1])->references['__LINE__']); // unset($this->getIndex($parserKinds[1])->references['__FILE__']); @@ -183,8 +189,10 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { try { $this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); + var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references)); } catch (\Throwable $e) { - $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); + $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, + "references do not match"); } } From 05bccec84d3b4f53a0114bd027445ba4d63cb7c7 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 09:12:30 -0700 Subject: [PATCH 054/149] Ensure duplicate ScopedPropertyAccess expressions don't appear --- src/TolerantTreeAnalyzer.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index e1046fd5..3b11df5a 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -95,7 +95,10 @@ public function update($node) { $parent = $node->parent; if (!( - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ( + // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression) && !( $node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->memberName instanceof Tolerant\Token @@ -127,7 +130,9 @@ public function update($node) { if (TolerantDefinitionResolver::isConstantFetch($node) || ($parent instanceof Tolerant\Node\Expression\CallExpression && !( - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + $parent->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression ))) { $parts = explode('\\', $fqn); if (count($parts) > 1) { From 26152b1de62fdcadd71fca53a9e175011c467545 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 09:13:03 -0700 Subject: [PATCH 055/149] Temporary change to expose index to validation tests --- src/Server/TextDocument.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 632c2e34..56af13f1 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -65,7 +65,7 @@ class TextDocument /** * @var ReadableIndex */ - protected $index; + public $index; /** * @var \stdClass|null From 52d70a283b57f4fbcbe614b609b29ed0b89f1f85 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 09:13:28 -0700 Subject: [PATCH 056/149] Update test case locations --- tests/Server/ServerTestCase.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 2d725e55..583b40af 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -152,9 +152,9 @@ public function setUp() 0 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) ], 'TestNamespace\\TestClass::testMethod()' => [ - 0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); - 1 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 32))), // $obj->testProperty->testMethod(); - 2 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 25))) // $child->testMethod(); + 0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 16))), // $obj->testMethod(); + 1 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 30))), // $obj->testProperty->testMethod(); + 2 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 23))) // $child->testMethod(); ], 'TestNamespace\\test_function()' => [ 0 => new Location($referencesUri, new Range(new Position(10, 0), new Position(10, 13))), @@ -202,9 +202,9 @@ public function setUp() 0 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 27))) ], 'TestClass::testMethod()' => [ - 0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 18))), // $obj->testMethod(); - 1 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 32))), // $obj->testProperty->testMethod(); - 2 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 25))) // $child->testMethod(); + 0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 16))), // $obj->testMethod(); + 1 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 30))), // $obj->testProperty->testMethod(); + 2 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 23))) // $child->testMethod(); ], 'test_function()' => [ 0 => new Location($globalReferencesUri, new Range(new Position(10, 0), new Position(10, 13))), From 596d7f0bef46eca99706ebf5e93b6146f1aa8996 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 09:14:58 -0700 Subject: [PATCH 057/149] Add isolated validation test cases --- .../anonymousClassMembersShouldNotBeSymbols.php | 11 +++++++++++ .../broken/docBlocksOnNamespaceDefinition.php | 6 ++++++ validation/frameworks/broken/memberAccess.php | 10 ++++++++++ .../frameworks/broken/multipleNamespaces.php | 17 +++++++++++++++++ validation/frameworks/broken/objectCreation.php | 9 +++++++++ validation/frameworks/broken/parent1.php | 15 +++++++++++++++ validation/frameworks/broken/parent2.php | 15 +++++++++++++++ validation/frameworks/broken/parent3.php | 15 +++++++++++++++ .../frameworks/broken/scopedPropertyAccess.php | 9 +++++++++ validation/frameworks/broken/self1.php | 15 +++++++++++++++ validation/frameworks/broken/self2.php | 15 +++++++++++++++ validation/frameworks/broken/self3.php | 15 +++++++++++++++ validation/frameworks/broken/static1.php | 15 +++++++++++++++ validation/frameworks/broken/static2.php | 15 +++++++++++++++ validation/frameworks/broken/static3.php | 15 +++++++++++++++ validation/frameworks/broken/stringVariable.php | 9 +++++++++ 16 files changed, 206 insertions(+) create mode 100644 validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php create mode 100644 validation/frameworks/broken/docBlocksOnNamespaceDefinition.php create mode 100644 validation/frameworks/broken/memberAccess.php create mode 100644 validation/frameworks/broken/multipleNamespaces.php create mode 100644 validation/frameworks/broken/objectCreation.php create mode 100644 validation/frameworks/broken/parent1.php create mode 100644 validation/frameworks/broken/parent2.php create mode 100644 validation/frameworks/broken/parent3.php create mode 100644 validation/frameworks/broken/scopedPropertyAccess.php create mode 100644 validation/frameworks/broken/self1.php create mode 100644 validation/frameworks/broken/self2.php create mode 100644 validation/frameworks/broken/self3.php create mode 100644 validation/frameworks/broken/static1.php create mode 100644 validation/frameworks/broken/static2.php create mode 100644 validation/frameworks/broken/static3.php create mode 100644 validation/frameworks/broken/stringVariable.php diff --git a/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php b/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php new file mode 100644 index 00000000..260a8cc6 --- /dev/null +++ b/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php @@ -0,0 +1,11 @@ +a(); + } +} diff --git a/validation/frameworks/broken/multipleNamespaces.php b/validation/frameworks/broken/multipleNamespaces.php new file mode 100644 index 00000000..07436352 --- /dev/null +++ b/validation/frameworks/broken/multipleNamespaces.php @@ -0,0 +1,17 @@ +b(); + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/objectCreation.php b/validation/frameworks/broken/objectCreation.php new file mode 100644 index 00000000..01437d34 --- /dev/null +++ b/validation/frameworks/broken/objectCreation.php @@ -0,0 +1,9 @@ +inline_diff_renderer; + } +} diff --git a/validation/frameworks/broken/parent1.php b/validation/frameworks/broken/parent1.php new file mode 100644 index 00000000..6708e7b0 --- /dev/null +++ b/validation/frameworks/broken/parent1.php @@ -0,0 +1,15 @@ +b(); + } +} diff --git a/validation/frameworks/broken/scopedPropertyAccess.php b/validation/frameworks/broken/scopedPropertyAccess.php new file mode 100644 index 00000000..ef83a47f --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess.php @@ -0,0 +1,9 @@ +b(); + } +} diff --git a/validation/frameworks/broken/static1.php b/validation/frameworks/broken/static1.php new file mode 100644 index 00000000..f512e00a --- /dev/null +++ b/validation/frameworks/broken/static1.php @@ -0,0 +1,15 @@ +b(); + } +} diff --git a/validation/frameworks/broken/stringVariable.php b/validation/frameworks/broken/stringVariable.php new file mode 100644 index 00000000..a3685c9a --- /dev/null +++ b/validation/frameworks/broken/stringVariable.php @@ -0,0 +1,9 @@ +hi"; + } +} \ No newline at end of file From 2ab7fc037afb42056088fe8a57d2d62c86d1d2f1 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 13 Apr 2017 11:32:37 -0700 Subject: [PATCH 058/149] add more validation test cases --- tests/Validation/ValidationTest.php | 2 +- validation/frameworks/broken/constants.php | 13 +++++++++++++ validation/frameworks/broken/constants2.php | 13 +++++++++++++ validation/frameworks/broken/constants3.php | 11 +++++++++++ .../broken/constantsInFunctionParamDefault.php | 5 +++++ .../broken/{memberAccess.php => memberAccess1.php} | 0 validation/frameworks/broken/memberAccess2.php | 10 ++++++++++ validation/frameworks/broken/memberAccess3.php | 13 +++++++++++++ validation/frameworks/broken/memberAccess4.php | 10 ++++++++++ validation/frameworks/broken/namespaces2.php | 5 +++++ validation/frameworks/broken/namespaces3.php | 3 +++ validation/frameworks/broken/namespaces4.php | 2 ++ validation/frameworks/broken/objectCreation2.php | 12 ++++++++++++ .../frameworks/broken/scopedPropertyAccess2.php | 6 ++++++ validation/frameworks/broken/self4.php | 13 +++++++++++++ validation/frameworks/broken/self5.php | 12 ++++++++++++ validation/frameworks/broken/static4.php | 9 +++++++++ 17 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 validation/frameworks/broken/constants.php create mode 100644 validation/frameworks/broken/constants2.php create mode 100644 validation/frameworks/broken/constants3.php create mode 100644 validation/frameworks/broken/constantsInFunctionParamDefault.php rename validation/frameworks/broken/{memberAccess.php => memberAccess1.php} (100%) create mode 100644 validation/frameworks/broken/memberAccess2.php create mode 100644 validation/frameworks/broken/memberAccess3.php create mode 100644 validation/frameworks/broken/memberAccess4.php create mode 100644 validation/frameworks/broken/namespaces2.php create mode 100644 validation/frameworks/broken/namespaces3.php create mode 100644 validation/frameworks/broken/namespaces4.php create mode 100644 validation/frameworks/broken/objectCreation2.php create mode 100644 validation/frameworks/broken/scopedPropertyAccess2.php create mode 100644 validation/frameworks/broken/self4.php create mode 100644 validation/frameworks/broken/self5.php create mode 100644 validation/frameworks/broken/static4.php diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 8a6c7c64..be5159fa 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -170,7 +170,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); - $skipped = ['false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', 'parent', 'PARENT', 'self', 'static']; +// $skipped = ['false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', 'parent', 'PARENT', 'self', 'static']; $skipped = []; foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { foreach ($skipped as $s) { diff --git a/validation/frameworks/broken/constants.php b/validation/frameworks/broken/constants.php new file mode 100644 index 00000000..23423cf7 --- /dev/null +++ b/validation/frameworks/broken/constants.php @@ -0,0 +1,13 @@ + BYE + ]; + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants2.php b/validation/frameworks/broken/constants2.php new file mode 100644 index 00000000..fda345ea --- /dev/null +++ b/validation/frameworks/broken/constants2.php @@ -0,0 +1,13 @@ + "hi" + ]; + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants3.php b/validation/frameworks/broken/constants3.php new file mode 100644 index 00000000..7ee1dde0 --- /dev/null +++ b/validation/frameworks/broken/constants3.php @@ -0,0 +1,11 @@ +a(); + } +} diff --git a/validation/frameworks/broken/memberAccess3.php b/validation/frameworks/broken/memberAccess3.php new file mode 100644 index 00000000..b2078d7d --- /dev/null +++ b/validation/frameworks/broken/memberAccess3.php @@ -0,0 +1,13 @@ +prefixesPsr0 = ComposerStaticInitIncludePath::$prefixesPsr0; + + }, null, ClassLoader::class); + } +} diff --git a/validation/frameworks/broken/memberAccess4.php b/validation/frameworks/broken/memberAccess4.php new file mode 100644 index 00000000..dd1b2fb7 --- /dev/null +++ b/validation/frameworks/broken/memberAccess4.php @@ -0,0 +1,10 @@ +toString()); + } +} diff --git a/validation/frameworks/broken/namespaces2.php b/validation/frameworks/broken/namespaces2.php new file mode 100644 index 00000000..a49478d5 --- /dev/null +++ b/validation/frameworks/broken/namespaces2.php @@ -0,0 +1,5 @@ +hi(); + } +} diff --git a/validation/frameworks/broken/scopedPropertyAccess2.php b/validation/frameworks/broken/scopedPropertyAccess2.php new file mode 100644 index 00000000..61a7131a --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess2.php @@ -0,0 +1,6 @@ +addTestFile(__DIR__ . DS . 'Database' . DS . 'ConnectionTest.php'); + + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self5.php b/validation/frameworks/broken/self5.php new file mode 100644 index 00000000..0fcd08fe --- /dev/null +++ b/validation/frameworks/broken/self5.php @@ -0,0 +1,12 @@ +assertTrue("HI"); + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/static4.php b/validation/frameworks/broken/static4.php new file mode 100644 index 00000000..bada62f0 --- /dev/null +++ b/validation/frameworks/broken/static4.php @@ -0,0 +1,9 @@ + Date: Thu, 13 Apr 2017 11:51:10 -0700 Subject: [PATCH 059/149] Fix class inheritance issue, fix parenthesized expression type resolution --- src/TolerantDefinitionResolver.php | 73 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 295c5f76..967ca143 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -393,8 +393,8 @@ public function resolveReferenceNodeToFqn($node) { $name = (string)($node->getNamespacedName()); } else if ( - ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + || ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || ($node->parent instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->parent->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) ) { // if ($scoped->memberName instanceof Tolerant\Node\Expression) { @@ -410,7 +410,7 @@ public function resolveReferenceNodeToFqn($node) { } if ($className === 'parent') { // parent is resolved to the parent class - if (!isset($node->extends)) { + if (!isset($classNode->extends)) { return null; } $className = (string)$classNode->extends->getResolvedName(); @@ -561,6 +561,11 @@ public function resolveExpressionNodeToType($expr): Type // How do we handle this more generally? return new Types\Mixed; } + + if ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { + $expr = $expr->expression; + } + if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { if ($expr instanceof Tolerant\Node\Expression\Variable && $expr->getName() === 'this') { return new Types\This; @@ -607,44 +612,44 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } } - if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { - if ($access->memberName instanceof Tolerant\Node\Expression) { - return new Types\Mixed; - } - $var = $access->dereferencableExpression; + if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { + if ($access->memberName instanceof Tolerant\Node\Expression) { + return new Types\Mixed; + } + $var = $access->dereferencableExpression; // var_dump("HERE!!!"); - // Resolve object - $objType = $this->resolveExpressionNodeToType($var); + // Resolve object + $objType = $this->resolveExpressionNodeToType($var); // var_dump($objType); - if (!($objType instanceof Types\Compound)) { - $objType = new Types\Compound([$objType]); - } - for ($i = 0; $t = $objType->get($i); $i++) { - if ($t instanceof Types\This) { - $classFqn = self::getContainingClassFqn($expr); - if ($classFqn === null) { - return new Types\Mixed; - } - } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { - return new Types\Mixed; - } else { - $classFqn = substr((string)$t->getFqsen(), 1); + if (!($objType instanceof Types\Compound)) { + $objType = new Types\Compound([$objType]); + } + for ($i = 0; $t = $objType->get($i); $i++) { + if ($t instanceof Types\This) { + $classFqn = self::getContainingClassFqn($expr); + if ($classFqn === null) { + return new Types\Mixed; + } + } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { + return new Types\Mixed; + } else { + $classFqn = substr((string)$t->getFqsen(), 1); // var_dump($classFqn); - } - $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { - $fqn .= '()'; - } + } + $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); + if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { + $fqn .= '()'; + } // var_dump($fqn); // var_dump($fqn); - $def = $this->index->getDefinition($fqn); + $def = $this->index->getDefinition($fqn); // var_dump($def); - if ($def !== null) { - return $def->type; - } - } - } + if ($def !== null) { + return $def->type; + } + } + } if ( ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { From 4382821b8c342ef8fbca4ec83bf03075188a09bb Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sun, 16 Apr 2017 15:09:05 -0700 Subject: [PATCH 060/149] Update logger to better handle errors --- src/LoggedDefinitionResolverTrait.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/LoggedDefinitionResolverTrait.php b/src/LoggedDefinitionResolverTrait.php index 164076d4..5ea5e9e4 100644 --- a/src/LoggedDefinitionResolverTrait.php +++ b/src/LoggedDefinitionResolverTrait.php @@ -15,7 +15,7 @@ trait LoggedDefinitionResolverTrait { - private static $logger = false; + private static $logger = true; private static $stackLevel = 0; @@ -27,7 +27,7 @@ trait LoggedDefinitionResolverTrait public function __construct(ReadableIndex $index) { parent::__construct($index); - self::$logger = false; + self::$logger = true; self::$maxRecursion = 0; } @@ -80,7 +80,11 @@ public function logMethod($methodName, $param1, $param2 = -1) { } elseif ($result instanceof DocBlock) { $resultText = $result->getDescription(); } else { - $resultText = $result ?? "NULL"; + try { + $resultText = (string) $result; + } catch (\Throwable $e) { + $resultText = "UNKNOWN"; + } } echo str_repeat("\t", self::$recursion + 1) . "> RESULT[$callStr]: " . $resultText . "\n"; } From 54f385f9ec50a688cc02ea101bdbba22db940597 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Sun, 16 Apr 2017 15:11:14 -0700 Subject: [PATCH 061/149] Fix misc. issues, add more test cases, update validation test --- src/ParserResourceFactory.php | 3 +- src/TolerantDefinitionResolver.php | 32 +++++-- src/TolerantTreeAnalyzer.php | 2 +- tests/Validation/ValidationTest.php | 90 ++++++++++++------- .../frameworks/broken/caseStatement1.php | 7 ++ validation/frameworks/broken/constants4.php | 11 +++ validation/frameworks/broken/exceptions1.php | 8 ++ validation/frameworks/broken/functionCall.php | 53 +++++++++++ validation/frameworks/broken/ifStatement1.php | 6 ++ .../broken/magicConstantsShouldBeGlobal.php | 5 ++ validation/frameworks/broken/namespaces5.php | 3 + validation/frameworks/broken/param1.php | 6 ++ 12 files changed, 184 insertions(+), 42 deletions(-) create mode 100644 validation/frameworks/broken/caseStatement1.php create mode 100644 validation/frameworks/broken/constants4.php create mode 100644 validation/frameworks/broken/exceptions1.php create mode 100644 validation/frameworks/broken/functionCall.php create mode 100644 validation/frameworks/broken/ifStatement1.php create mode 100644 validation/frameworks/broken/magicConstantsShouldBeGlobal.php create mode 100644 validation/frameworks/broken/namespaces5.php create mode 100644 validation/frameworks/broken/param1.php diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index d66dc843..bd957d09 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,7 +6,8 @@ use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; + const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; + private static function getParserKind () { global $parserKind; return isset($parserKind) ? $parserKind : self::PARSER_KIND; diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 967ca143..36207d67 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -280,12 +280,14 @@ public function resolveReferenceNodeToFqn($node) { $name = $node->getResolvedName(); if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { - $name = (string)($name ?? $node->getText()); + $name = (string)($name ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { $prefix = $useClause->parent->parent->namespaceName; - $prefix = $prefix === null ? "" : $prefix->getText(); - - $name = $prefix . "\\" . $name; + if ($prefix === null) { + return null; + } + $prefixName = Tolerant\ResolvedName::buildName($prefix->nameParts, $useClause->getFileContents()); + $name = (string)$prefixName . "\\" . $name; if ($useClause->functionOrConst === null) { $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); @@ -449,12 +451,25 @@ public static function isConstantFetch(Tolerant\Node $node) : bool { return ( $node instanceof Tolerant\Node\QualifiedName && - ($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression || $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList) && + ( +// $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || + $node->parent instanceof Tolerant\Node\Expression || + $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList || + $node->parent instanceof Tolerant\Node\ArrayElement || + ($node->parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || + $node->parent instanceof Tolerant\Node\StatementNode || + $node->parent instanceof Tolerant\Node\CaseStatementNode + ) && !( - $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || + $node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || - $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || - ($node->parent instanceof Tolerant\Node\Expression\BinaryExpression && $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword) + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || + ( + $node->parent instanceof Tolerant\Node\Expression\BinaryExpression && + $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword + ) )); } @@ -859,6 +874,7 @@ public function resolveClassNameToType($class): Type return new Types\Object_; } $className = (string)$class->getResolvedName(); + var_dump($className); if ($className === 'static') { return new Types\Static_; } diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 3b11df5a..103eb8d3 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -112,7 +112,7 @@ public function update($node) { if ( $node instanceof Tolerant\Node\QualifiedName - && $node->isQualifiedName() + && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() ) ) { diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index be5159fa..3e4a32c1 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -29,13 +29,13 @@ public function frameworkErrorProvider() { foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); if ($frameworkName !== "broken") { - continue; +// continue; } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { if (strpos(\strrev((string)$file), \strrev(".php")) === 0 -// && strpos((string)$file, "ConsoleIoTest.php")!== false +// && strpos((string)$file, "taxonomy.php")!== false ) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; @@ -106,14 +106,15 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; $maxRecursion = []; - $definitions = []; - $instantiated = []; - $types = []; - $symbolInfo = []; - $extend = []; - $isGlobal = []; - $documentation = []; - $isStatic = []; + + $definitions = null; + $instantiated = null; + $types = null; + $symbolInfo = null; + $extend = null; + $isGlobal = null; + $documentation = null; + $isStatic = null; foreach ($parserKinds as $kind) { echo ("=====================================\n"); @@ -128,8 +129,12 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { try { $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (\Exception $e) { - continue; + } catch (Exception $e) { + if ($kind === $parserKinds[0]) { + $this->markTestIncomplete("baseline parser failed: " . $e->getTraceAsString()); + } + throw $e; + } if ($document->getStmts() === null) { @@ -157,21 +162,26 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $docs[$defn->fqn] = $defn->documentation; $static[$defn->fqn] = $defn->isStatic; } + if ($definitions !== null) { - if (isset($definitions[$testCaseFile])) { - $this->assertEquals($definitions[$testCaseFile], $fqns, 'defn->fqn does not match'); -// $this->assertEquals($types[$testCaseFile], $currentTypes, "defn->type does not match"); - $this->assertEquals($instantiated[$testCaseFile], $canBeInstantiated, "defn->canBeInstantiated does not match"); - $this->assertEquals($extend[$testCaseFile], $extends, 'defn->extends does not match'); - $this->assertEquals($isGlobal[$testCaseFile], $global, 'defn->isGlobal does not match'); - $this->assertEquals($documentation[$testCaseFile], $docs, 'defn->documentation does not match'); - $this->assertEquals($isStatic[$testCaseFile], $static, 'defn->isStatic does not match'); + $this->assertEquals($definitions, $fqns, 'defn->fqn does not match'); +// $this->assertEquals($types, $currentTypes, "defn->type does not match"); + $this->assertEquals($instantiated, $canBeInstantiated, "defn->canBeInstantiated does not match"); + $this->assertEquals($extend, $extends, 'defn->extends does not match'); + $this->assertEquals($isGlobal, $global, 'defn->isGlobal does not match'); + $this->assertEquals($documentation, $docs, 'defn->documentation does not match'); + $this->assertEquals($isStatic, $static, 'defn->isStatic does not match'); - $this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); + $this->assertEquals($symbolInfo, $symbols, "defn->symbolInformation does not match"); -// $skipped = ['false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', 'parent', 'PARENT', 'self', 'static']; $skipped = []; + $skipped = [ + 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', + '__', // magic constants are treated as normal constants + 'Exception', // catch exception types missing from old definition resolver + 'Trait' // use Trait references are missing from old definition resolve + ]; foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { foreach ($skipped as $s) { if (strpos($key, $s) !== false) { @@ -179,6 +189,13 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { } } } + foreach ($this->getIndex($parserKinds[1], $frameworkName)->references as $key=>$value) { + foreach ($skipped as $s) { + if (strpos($key, $s) !== false) { + unset($this->getIndex($parserKinds[1], $frameworkName)->references[$key]); + } + } + } // unset($this->getIndex($parserKinds[1])->references['__LINE__']); // unset($this->getIndex($parserKinds[1])->references['__FILE__']); @@ -188,22 +205,31 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { // unset($this->getIndex($parserKinds[1])->references['Requests_Exception']); try { + +// $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, +// "references do not match"); + $this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); - var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references)); - } catch (\Throwable $e) { +// var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references)); + } + catch (\Throwable $e) { $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, "references do not match"); } + finally { + unset($this->index[$parserKinds[0]][$frameworkName]); + unset($this->index[$parserKinds[1]][$frameworkName]); + } } - $definitions[$testCaseFile] = $fqns; - $types[$testCaseFile] = $currentTypes; - $instantiated[$testCaseFile] = $canBeInstantiated; - $symbolInfo[$testCaseFile] = $symbols; - $extend[$testCaseFile] = $extends; - $isGlobal[$testCaseFile] = $global; - $documentation[$testCaseFile] = $docs; - $isStatic[$testCaseFile] = $static; + $definitions = $fqns; + $types = $currentTypes; + $instantiated = $canBeInstantiated; + $symbolInfo = $symbols; + $extend = $extends; + $isGlobal = $global; + $documentation = $docs; + $isStatic = $static; // $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; } diff --git a/validation/frameworks/broken/caseStatement1.php b/validation/frameworks/broken/caseStatement1.php new file mode 100644 index 00000000..69851aa0 --- /dev/null +++ b/validation/frameworks/broken/caseStatement1.php @@ -0,0 +1,7 @@ + Date: Sun, 16 Apr 2017 16:32:38 -0700 Subject: [PATCH 062/149] Fix namespace name, use variable issues --- src/DefinitionResolver.php | 3 --- src/Server/TextDocument.php | 1 - src/TolerantDefinitionResolver.php | 15 +++++++++------ validation/frameworks/broken/namespaces6.php | 2 ++ 4 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 validation/frameworks/broken/namespaces6.php diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index e3dc20d1..3d3a360e 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -777,9 +777,6 @@ public function getTypeFromNode($node) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { - if ((string)$type === "\\TestNamespace\\TestClass") { - var_dump($type); - } return $type; } // Resolve the expression diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 56af13f1..b4793175 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -220,7 +220,6 @@ public function references( if ($descendantNode instanceof Tolerant\Node\Expression\Variable && $descendantNode->getName() === $node->getName() ) { - var_dump($descendantNode->getName()); $locations[] = Location::fromNode($descendantNode); } } diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 36207d67..c0c474be 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -501,7 +501,7 @@ public function resolveVariableToNode($var) // When a use is passed, start outside the closure to not return immediately // Use variable vs variable parsing? if ($var instanceof Tolerant\Node\UseVariableName) { - $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class); + $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class)->parent; $name = $var->getName(); } else if ($var instanceof Tolerant\Node\Expression\Variable || $var instanceof Tolerant\Node\Parameter) { $name = $var->getName(); @@ -521,8 +521,11 @@ public function resolveVariableToNode($var) } } // If it is a closure, also check use statements - if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && $n->anonymousFunctionUseClause !== null && $n->anonymousFunctionUseClause->useVariableNameList !== null) { - foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use) { + if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && + $n->anonymousFunctionUseClause !== null && + $n->anonymousFunctionUseClause->useVariableNameList !== null) { + foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use + ) { if ($use->getName() === $name) { return $use; } @@ -587,7 +590,7 @@ public function resolveExpressionNodeToType($expr): Type } // Find variable definition $defNode = $this->resolveVariableToNode($expr); - if ($defNode instanceof Tolerant\Node\Expression) { + if ($defNode instanceof Tolerant\Node\Expression || $defNode instanceof Tolerant\Node\UseVariableName) { return $this->resolveExpressionNodeToType($defNode); } if ($defNode instanceof Tolerant\Node\Parameter) { @@ -874,7 +877,7 @@ public function resolveClassNameToType($class): Type return new Types\Object_; } $className = (string)$class->getResolvedName(); - var_dump($className); + if ($className === 'static') { return new Types\Static_; } @@ -1056,7 +1059,7 @@ public static function getDefinedFqn($node) // INPUT OUTPUT: // namespace A\B; A\B else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { - return (string) $node->name; + return (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); } // INPUT OUTPUT: // namespace A\B; diff --git a/validation/frameworks/broken/namespaces6.php b/validation/frameworks/broken/namespaces6.php new file mode 100644 index 00000000..198691d1 --- /dev/null +++ b/validation/frameworks/broken/namespaces6.php @@ -0,0 +1,2 @@ + Date: Tue, 18 Apr 2017 22:48:26 -0700 Subject: [PATCH 063/149] refactor definition resolver, fix misc. issues --- src/LoggedDefinitionResolverTrait.php | 10 +- src/Protocol/TolerantSymbolInformation.php | 10 +- src/TolerantDefinitionResolver.php | 671 ++++++++---------- src/TolerantParserHelpers.php | 103 +++ src/TolerantTreeAnalyzer.php | 2 +- .../frameworks/broken/classDefinition1.php | 11 + .../frameworks/broken/classProperty1.php | 19 + validation/frameworks/broken/constants5.php | 8 + .../frameworks/broken/memberAccess5.php | 11 + validation/frameworks/broken/memberCall1.php | 16 + validation/frameworks/broken/nameToken.php | 7 + validation/frameworks/broken/namespaces7.php | 4 + validation/frameworks/broken/namespaces8.php | 6 + .../broken/scopedPropertyAccess3.php | 8 + .../broken/scopedPropertyAccess5.php | 13 + 15 files changed, 512 insertions(+), 387 deletions(-) create mode 100644 src/TolerantParserHelpers.php create mode 100644 validation/frameworks/broken/classDefinition1.php create mode 100644 validation/frameworks/broken/classProperty1.php create mode 100644 validation/frameworks/broken/constants5.php create mode 100644 validation/frameworks/broken/memberAccess5.php create mode 100644 validation/frameworks/broken/memberCall1.php create mode 100644 validation/frameworks/broken/nameToken.php create mode 100644 validation/frameworks/broken/namespaces7.php create mode 100644 validation/frameworks/broken/namespaces8.php create mode 100644 validation/frameworks/broken/scopedPropertyAccess3.php create mode 100644 validation/frameworks/broken/scopedPropertyAccess5.php diff --git a/src/LoggedDefinitionResolverTrait.php b/src/LoggedDefinitionResolverTrait.php index 5ea5e9e4..f5b5d305 100644 --- a/src/LoggedDefinitionResolverTrait.php +++ b/src/LoggedDefinitionResolverTrait.php @@ -12,6 +12,7 @@ use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; use Microsoft\PhpParser as Tolerant; +use PhpParser\PrettyPrinterAbstract; trait LoggedDefinitionResolverTrait { @@ -79,9 +80,14 @@ public function logMethod($methodName, $param1, $param2 = -1) { $resultText = $result->fqn; } elseif ($result instanceof DocBlock) { $resultText = $result->getDescription(); - } else { + } + else { try { - $resultText = (string) $result; + if ($result instanceof Node) { + $resultText = (new PrettyPrinter())->prettyPrint([$result]); + } else { + $resultText = (string) $result; + } } catch (\Throwable $e) { $resultText = "UNKNOWN"; } diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php index 168d9065..769f1af2 100644 --- a/src/Protocol/TolerantSymbolInformation.php +++ b/src/Protocol/TolerantSymbolInformation.php @@ -53,9 +53,7 @@ public static function fromNode($node, string $fqn = null) return null; } - if ($node instanceof Node\Name) { - $symbol->name = (string)$node; - } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { $symbol->name = $node->leftOperand->getName(); } elseif ($node->leftOperand instanceof Tolerant\Token) { @@ -65,7 +63,11 @@ public static function fromNode($node, string $fqn = null) } else if ($node instanceof Tolerant\Node\UseVariableName) { $symbol->name = $node->getName(); } else if (isset($node->name)) { - $symbol->name = trim((string)$node->name->getText($node->getFileContents()), "$"); + if ($node->name instanceof Tolerant\Node\QualifiedName) { + $symbol->name = (string)Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + } else { + $symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$"); + } } else if (isset($node->variableName)) { $symbol->name = $node->variableName->getText($node); } else { diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index c0c474be..357afa83 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -5,7 +5,6 @@ use LanguageServer\Protocol\TolerantSymbolInformation; use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use phpDocumentor\Reflection\{ DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver }; @@ -16,21 +15,22 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface { /** + * The current project index (for retrieving existing definitions) + * * @var \LanguageServer\Index\ReadableIndex */ protected $index; /** + * Resolves strings to a type object. + * * @var \phpDocumentor\Reflection\TypeResolver */ private $typeResolver; /** - * @var \PhpParser\PrettyPrinterAbstract - */ - private $prettyPrinter; - - /** + * Parses Doc Block comments given the DocBlock text and import tables at a position. + * * @var DocBlockFactory */ private $docBlockFactory; @@ -42,61 +42,42 @@ public function __construct(ReadableIndex $index) { $this->index = $index; $this->typeResolver = new TypeResolver; - $this->prettyPrinter = new PrettyPrinter; $this->docBlockFactory = DocBlockFactory::createInstance(); } /** - * Builds the declaration line for a given node. - * + * Builds the declaration line for a given node. Declarations with multiple lines are trimmed. * * @param Tolerant\Node $node * @return string */ public function getDeclarationLineFromNode($node): string { - // TODO Tolerant\Node\Statement\FunctionStaticDeclaration::class - - // we should have a better way of determining whether something is a property or constant - // If part of a declaration list -> get the parent declaration + // If node is part of a declaration list, build a declaration line that discludes other elements in the list + // - [PropertyDeclaration] // public $a, [$b = 3], $c; => public $b = 3; + // - [ConstDeclaration | ClassConstDeclaration] // "const A = 3, [B = 4];" => "const B = 4;" if ( - // PropertyDeclaration // public $a, $b, $c; - $node instanceof Tolerant\Node\Expression\Variable && - ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null + ($declaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) && ($elements = $declaration->propertyElements) || + ($declaration = TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node)) && ($elements = $declaration->constElements) ) { - $defLine = $propertyDeclaration->getText(); - $defLineStart = $propertyDeclaration->getStart(); + $defLine = $declaration->getText(); + $defLineStart = $declaration->getStart(); $defLine = \substr_replace( $defLine, $node->getFullText(), - $propertyDeclaration->propertyElements->getFullStart() - $defLineStart, - $propertyDeclaration->propertyElements->getFullWidth() + $elements->getFullStart() - $defLineStart, + $elements->getFullWidth() ); - } elseif ( - // ClassConstDeclaration or ConstDeclaration // const A = 1, B = 2; - $node instanceof Tolerant\Node\ConstElement && - ($constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class)) - ) { - $defLine = $constDeclaration->getText(); - $defLineStart = $constDeclaration->getStart(); - - $defLine = \substr_replace( - $defLine, - $node->getFullText(), - $constDeclaration->constElements->getFullStart() - $defLineStart, - $constDeclaration->constElements->getFullWidth() - ); - } - - // Get the current node - else { + } else { $defLine = $node->getText(); } - $defLine = \strtok($defLine, "\n"); - $defLine = \strtok($defLine, "\r"); + // Trim string to only include first line + $defLine = \rtrim(\strtok($defLine, "\n"), "\r"); + // TODO - pretty print rather than getting text + return $defLine; } @@ -108,54 +89,60 @@ public function getDeclarationLineFromNode($node): string */ public function getDocumentationFromNode($node) { + // Any NamespaceDefinition comments likely apply to the file, not the declaration itself. + if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { + return null; + } + // For properties and constants, set the node to the declaration node, rather than the individual property. // This is because they get defined as part of a list. - $constOrPropertyDeclaration = $node->getFirstAncestor( - Tolerant\Node\PropertyDeclaration::class, - Tolerant\Node\Statement\ConstDeclaration::class, - Tolerant\Node\ClassConstDeclaration::class - ); + $constOrPropertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node); if ($constOrPropertyDeclaration !== null) { $node = $constOrPropertyDeclaration; } - // For parameters, parse the documentation to get the parameter tag. + // For parameters, parse the function-like declaration to get documentation for a parameter if ($node instanceof Tolerant\Node\Parameter) { - $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); - $variableName = substr($node->variableName->getText($node->getFileContents()), 1); - $docBlock = $this->getDocBlock($functionLikeDeclaration); + $variableName = $node->getName(); - if ($docBlock !== null) { - $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); - return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; + $functionLikeDeclaration = TolerantParserHelpers::getFunctionLikeDeclarationFromParameter($node); + $docBlock = $this->getDocBlock($functionLikeDeclaration); - } + $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); + return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; } - // for everything else, get the doc block summary corresponding to the current node. - elseif (!($node instanceof Tolerant\Node\Statement\NamespaceDefinition)) { - $docBlock = $this->getDocBlock($node); - if ($docBlock !== null) { - return $docBlock->getSummary(); - } + + // For everything else, get the doc block summary corresponding to the current node. + $docBlock = $this->getDocBlock($node); + if ($docBlock !== null) { + return $docBlock->getSummary(); } return null; } - function getDocBlock(Tolerant\Node $node) { - // TODO make more efficient - $namespaceDefinition = $node->getNamespaceDefinition(); - $context = null; - if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { - list($namespaceImportTable,,) = $namespaceDefinition->name->getImportTablesForCurrentScope($namespaceDefinition); + /** + * Gets Doc Block with resolved names for a Node + * + * @param Tolerant\Node $node + * @return DocBlock | null + */ + private function getDocBlock(Tolerant\Node $node) + { + // TODO make more efficient (caching, ensure import table is in right format to begin with) + $docCommentText = $node->getDocCommentText(); + if ($docCommentText !== null) { + list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); foreach ($namespaceImportTable as $alias=>$name) { $namespaceImportTable[$alias] = (string)$name; } - $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); + $namespaceDefinition = $node->getNamespaceDefinition(); + if ($namespaceDefinition !== null) { + $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); + } else { + $namespaceName = 'global'; + } $context = new Types\Context($namespaceName, $namespaceImportTable); - } - $docCommentText = $node->getDocCommentText(); - if ($docCommentText !== null) { try { return $this->docBlockFactory->create($docCommentText, $context); } catch (\InvalidArgumentException $e) { @@ -175,52 +162,54 @@ function getDocBlock(Tolerant\Node $node) { public function createDefinitionFromNode($node, string $fqn = null): Definition { $def = new Definition; + $def->fqn = $fqn; - // this determines whether the suggestion will show after "new" - // TODO name + // Determines whether the suggestion will show after "new" $def->canBeInstantiated = $node instanceof Tolerant\Node\Statement\ClassDeclaration; + // Interfaces, classes, traits, namespaces, functions, and global const elements $def->isGlobal = ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration - || $node instanceof Tolerant\Node\Statement\ClassDeclaration - || $node instanceof Tolerant\Node\Statement\TraitDeclaration + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration || - // TODO namespaces? - || $node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null + ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null) || - || $node instanceof Tolerant\Node\Statement\FunctionDeclaration + $node instanceof Tolerant\Node\Statement\FunctionDeclaration || - || $node instanceof Tolerant\Node\Statement\ConstDeclaration - || $node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration - // || $node instanceof Tolerant\Node\ClassConstDeclaration + ($node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration) ); + // Static methods and static property declarations $def->isStatic = ( - ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) - || ($node instanceof Tolerant\Node\Expression\Variable && - ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && - $propertyDeclaration->isStatic()) + ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) || + + (($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null + && $propertyDeclaration->isStatic()) ); - $def->fqn = $fqn; - if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { - $def->extends = []; // TODO - don't instantiate array - if ($node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { - $def->extends[] = (string)$node->classBaseClause->baseClass->getResolvedName(); - } - // TODO what about class interfaces - } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { + + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration && + // TODO - this should be bette rrpreented in the parser API + $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) + { + $def->extends = [(string)$node->classBaseClause->baseClass->getResolvedName()]; + // TODO - why is this represented as an array? + // TODO interface implementations. + } elseif ( + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && + // TODO - this hould be better represented in the parser API + $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null + ) { $def->extends = []; - if ($node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null) { - foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { - $def->extends[] = (string)$n->getResolvedName(); - } + foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { + $def->extends[] = (string)$n->getResolvedName(); } } $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); if ($def->symbolInformation !== null) { - $def->type = $this->getTypeFromNode($node); //TODO + $def->type = $this->getTypeFromNode($node); $def->declarationLine = $this->getDeclarationLineFromNode($node); $def->documentation = $this->getDocumentationFromNode($node); } @@ -237,13 +226,16 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition public function resolveReferenceNodeToDefinition($node) { $parent = $node->parent; - // Variables are not indexed globally, as they stay in the file scope anyway - if ($node instanceof Tolerant\Node\Expression\Variable && !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) { - // Resolve $this + // Variables are not indexed globally, as they stay in the file scope anyway. + // Ignore variable nodes that are part of ScopedPropertyAccessExpression, + // as the scoped property access expression node is handled separately. + if ($node instanceof Tolerant\Node\Expression\Variable && + !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) + { + // Resolve $this to the containing class definition. if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); } - // TODO running through thid for class constants or properties // Resolve the variable to a definition node (assignment, param or closure use) $defNode = $this->resolveVariableToNode($node); @@ -260,7 +252,7 @@ public function resolveReferenceNodeToDefinition($node) } // 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 - $globalFallback = $this->isConstantFetch($node) || $node->parent instanceof Tolerant\Node\Expression\CallExpression; + $globalFallback = TolerantParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -272,207 +264,174 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) { - $parent = $node->parent; -// TODO all name tokens should be a part of a node + public function resolveReferenceNodeToFqn($node) { + // TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { - // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = $node->getResolvedName(); - - if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { - $name = (string)($name ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); - if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { - $prefix = $useClause->parent->parent->namespaceName; - if ($prefix === null) { - return null; - } - $prefixName = Tolerant\ResolvedName::buildName($prefix->nameParts, $useClause->getFileContents()); - $name = (string)$prefixName . "\\" . $name; + return $this->resolveQualifiedNameNodeToFqn($node); + } + + else if ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { + return $this->resolveMemberAccessExpressionNodeToFqn($node); + } + else if (TolerantParserHelpers::isConstantFetch($node)) { + return (string)($node->getNamespacedName()); + } + else if ( + // A\B::C - constant access expression + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + && !($node->memberName instanceof Tolerant\Node\Expression\Variable) + ) { + return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); + } else if ( + // A\B::$c - static property access expression + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ) { + return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node->parent); + } + + return null; + } - if ($useClause->functionOrConst === null) { - $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); + private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { + $parent = $node->parent; + // Add use clause references + if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause + || $useClause instanceof Tolerant\Node\NamespaceUseClause + ) { + $contents = $node->getFileContents(); + if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { + $prefix = $useClause->parent->parent->namespaceName; + if ($prefix === null) { + return null; + } + $name = Tolerant\ResolvedName::buildName($prefix->nameParts, $contents); + $name->addNameParts($node->nameParts, $contents); + $name = (string)$name; + + if ($useClause->functionOrConst === null) { + $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); + if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $name .= '()'; } } - - if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + return $name; + } else { + $name = (string) Tolerant\ResolvedName::buildName($node->nameParts, $contents); + if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { $name .= '()'; } } - else { - $name = (string)($name ?? (string)$node->getNamespacedName()); - } - if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { - $name .= '()'; - } -// does this work for function calls? return $name; } - else if ( - (($access = $node) instanceof Tolerant\Node\Expression\MemberAccessExpression) - ) { - if ($access->memberName instanceof Tolerant\Node\Expression) { - // Cannot get definition if right-hand side is expression - return null; - } - // Get the type of the left-hand expression - $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); - - if ($varType instanceof Types\Compound) { - // For compound types, use the first FQN we find - // (popular use case is ClassName|null) - for ($i = 0; $t = $varType->get($i); $i++) { - if ( - $t instanceof Types\This - || $t instanceof Types\Object_ - || $t instanceof Types\Static_ - || $t instanceof Types\Self_ - ) { - $varType = $t; - break; - } - } - } - if ( - $varType instanceof Types\This - || $varType instanceof Types\Static_ - || $varType instanceof Types\Self_ - ) { - // $this/static/self is resolved to the containing class - $classFqn = self::getContainingClassFqn($node); - } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { - // Left-hand expression could not be resolved to a class - return null; - } else { - $classFqn = substr((string)$varType->getFqsen(), 1); + // For extends, implements, type hints and classes of classes of static calls use the name directly + $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); - // TODO -// $classFqn = $node->getNamespaceDefinition()->name->getNamespacedName() . (string)$varType->getFqsen(); -// var_dump($classFqn); - } - $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($node->getFileContents())); - if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { - // TODO - this is redundant - $memberSuffix .= '()'; - } - // Find the right class that implements the member - $implementorFqns = [$classFqn]; + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { + $name .= '()'; + } + return $name; + } - while ($implementorFqn = array_shift($implementorFqns)) { -// var_dump($implementorFqn . $memberSuffix); - // If the member FQN exists, return it - if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { + private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression\MemberAccessExpression $access) { + if ($access->memberName instanceof Tolerant\Node\Expression) { + // Cannot get definition if right-hand side is expression + return null; + } + // Get the type of the left-hand expression + $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); - return $implementorFqn . $memberSuffix; - } - // Get Definition of implementor class - $implementorDef = $this->index->getDefinition($implementorFqn); - // If it doesn't exist, return the initial guess - if ($implementorDef === null) { + if ($varType instanceof Types\Compound) { + // For compound types, use the first FQN we find + // (popular use case is ClassName|null) + for ($i = 0; $t = $varType->get($i); $i++) { + if ( + $t instanceof Types\This + || $t instanceof Types\Object_ + || $t instanceof Types\Static_ + || $t instanceof Types\Self_ + ) { + $varType = $t; break; } - // Repeat for parent class - if ($implementorDef->extends) { - foreach ($implementorDef->extends as $extends) { - $implementorFqns[] = $extends; - } - } } + } + if ( + $varType instanceof Types\This + || $varType instanceof Types\Static_ + || $varType instanceof Types\Self_ + ) { + // $this/static/self is resolved to the containing class + $classFqn = self::getContainingClassFqn($access); + } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { + // Left-hand expression could not be resolved to a class + return null; + } else { + $classFqn = substr((string)$varType->getFqsen(), 1); + } + $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($access->getFileContents())); + if ($access->parent instanceof Tolerant\Node\Expression\CallExpression) { + $memberSuffix .= '()'; + } + + // Find the right class that implements the member + $implementorFqns = [$classFqn]; -// var_dump("SUFFIX"); -// var_dump($classFqn); -// var_dump($memberSuffix); - return $classFqn . $memberSuffix; + while ($implementorFqn = array_shift($implementorFqns)) { + // If the member FQN exists, return it + if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { + + return $implementorFqn . $memberSuffix; + } + // Get Definition of implementor class + $implementorDef = $this->index->getDefinition($implementorFqn); + // If it doesn't exist, return the initial guess + if ($implementorDef === null) { + break; + } + // Repeat for parent class + if ($implementorDef->extends) { + foreach ($implementorDef->extends as $extends) { + $implementorFqns[] = $extends; + } + } } - else if ($parent instanceof Tolerant\Node\Expression\CallExpression && $node instanceof Tolerant\Node\QualifiedName) { - if ($parent->name instanceof Node\Expr) { + + return $classFqn . $memberSuffix; + } + + private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { + $className = $scoped->scopeResolutionQualifier->getText(); + if ($className === 'self' || $className === 'static' || $className === 'parent') { + // self and static are resolved to the containing class + $classNode = $scoped->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if ($classNode === null) { return null; } - $name = (string)($parent->getNamespacedName()); - } - else if ($this->isConstantFetch($node)) { - $name = (string)($node->getNamespacedName()); - } - else if ( - ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - || ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - || ($node->parent instanceof Tolerant\Node\Expression\CallExpression && ($scoped = $node->parent->callableExpression) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) - ) { -// if ($scoped->memberName instanceof Tolerant\Node\Expression) { - // Cannot get definition of dynamic names -// return null; -// } - $className = $scoped->scopeResolutionQualifier->getText(); - if ($className === 'self' || $className === 'static' || $className === 'parent') { - // self and static are resolved to the containing class - $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($classNode === null) { + if ($className === 'parent') { + // parent is resolved to the parent class + if (!isset($classNode->extends)) { return null; } - if ($className === 'parent') { - // parent is resolved to the parent class - if (!isset($classNode->extends)) { - return null; - } - $className = (string)$classNode->extends->getResolvedName(); - } else { - $className = (string)$classNode->getNamespacedName(); - } - } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { - $className = $scoped->scopeResolutionQualifier->getResolvedName(); - } - if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { - $name = (string)$className . '::$' . $scoped->memberName->getName(); + $className = (string)$classNode->extends->getResolvedName(); } else { - $name = (string)$className . '::' . $scoped->memberName->getText($node->getFileContents()); - } - - if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { - $name .= '()'; + $className = (string)$classNode->getNamespacedName(); } - return $name; - } - else { - return null; + } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + $className = $scoped->scopeResolutionQualifier->getResolvedName(); } - if (!isset($name)) { - return null; + if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { + $name = (string)$className . '::$' . $scoped->memberName->getName(); + } else { + $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); } - if ( - $node instanceof Tolerant\Node\Expression\CallExpression - ) { + if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; } return $name; } - public static function isConstantFetch(Tolerant\Node $node) : bool { - return - ( - $node instanceof Tolerant\Node\QualifiedName && - ( -// $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || - $node->parent instanceof Tolerant\Node\Expression || - $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList || - $node->parent instanceof Tolerant\Node\ArrayElement || - ($node->parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || - $node->parent instanceof Tolerant\Node\StatementNode || - $node->parent instanceof Tolerant\Node\CaseStatementNode - ) && - !( - $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || - $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || - ( - $node->parent instanceof Tolerant\Node\Expression\BinaryExpression && - $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword - ) - )); - } - /** * 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 @@ -511,7 +470,7 @@ public function resolveVariableToNode($var) // Traverse the AST up do { // If a function is met, check the parameters and use statements - if (self::isFunctionLike($n)) { + if (TolerantParserHelpers::isFunctionLike($n)) { if ($n->parameters !== null) { foreach ($n->parameters->getElements() as $param) { @@ -550,26 +509,11 @@ public function resolveVariableToNode($var) return null; } - function getFunctionLikeDeclarationFromParameter(Tolerant\Node $node) { - return $node->getFirstAncestor( - Tolerant\Node\Statement\FunctionDeclaration::class, - Tolerant\Node\MethodDeclaration::class, - Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class - ); - } - - public static function isFunctionLike(Tolerant\Node $node) { - return - $node instanceof Tolerant\Node\Statement\FunctionDeclaration || - $node instanceof Tolerant\Node\MethodDeclaration || - $node instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression; - } - /** * Given an expression node, resolves that expression recursively to a type. * If the type could not be resolved, returns Types\Mixed. * - * @param \PhpParser\Node\Expr $expr + * @param Tolerant\Node\Expression $expr * @return \phpDocumentor\Reflection\Type */ public function resolveExpressionNodeToType($expr): Type @@ -580,7 +524,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } - if ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { + while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { $expr = $expr->expression; } @@ -622,7 +566,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Boolean; } - if ($this->isConstantFetch($expr)) { + if (TolerantParserHelpers::isConstantFetch($expr)) { // Resolve constant $fqn = (string)$expr->getNamespacedName(); $def = $this->index->getDefinition($fqn, true); @@ -636,10 +580,8 @@ public function resolveExpressionNodeToType($expr): Type } $var = $access->dereferencableExpression; -// var_dump("HERE!!!"); // Resolve object $objType = $this->resolveExpressionNodeToType($var); -// var_dump($objType); if (!($objType instanceof Types\Compound)) { $objType = new Types\Compound([$objType]); } @@ -653,16 +595,12 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } else { $classFqn = substr((string)$t->getFqsen(), 1); -// var_dump($classFqn); } $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } -// var_dump($fqn); -// var_dump($fqn); $def = $this->index->getDefinition($fqn); -// var_dump($def); if ($def !== null) { return $def->type; } @@ -672,19 +610,16 @@ public function resolveExpressionNodeToType($expr): Type ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); -// var_dump($classType); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { return new Types\Mixed; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; -// if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && $expr->memberName instanceof Tolerant\Node\Expression\Variable) { -// $fqn .= '$'; -// } + $fqn .= $scopedAccess->memberName->getText() ?? $scopedAccess->memberName->getText($expr->getFileContents()); // TODO is there a cleaner way to do this? if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } -// var_dump($fqn); + $def = $this->index->getDefinition($fqn); if ($def === null) { return new Types\Mixed; @@ -722,7 +657,7 @@ public function resolveExpressionNodeToType($expr): Type ]); } if ( - $this->isBooleanExpression($expr) + TolerantParserHelpers::isBooleanExpression($expr) || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) || ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) @@ -819,9 +754,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Array_($valueType, $keyType); } if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { -// var_dump("SUBSCRIPT"); $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); -// var_dump($varType); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; } @@ -834,31 +767,6 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } - private function isBooleanExpression($expression) : bool { - if (!($expression instanceof Tolerant\Node\Expression\BinaryExpression)) { - return false; - } - switch ($expression->operator->kind) { - case Tolerant\TokenKind::InstanceOfKeyword: - case Tolerant\TokenKind::GreaterThanToken: - case Tolerant\TokenKind::GreaterThanEqualsToken: - case Tolerant\TokenKind::LessThanToken: - case Tolerant\TokenKind::LessThanEqualsToken: - case Tolerant\TokenKind::AndKeyword: - case Tolerant\TokenKind::AmpersandAmpersandToken: - case Tolerant\TokenKind::LessThanEqualsGreaterThanToken: - case Tolerant\TokenKind::OrKeyword: - case Tolerant\TokenKind::BarBarToken: - case Tolerant\TokenKind::XorKeyword: - case Tolerant\TokenKind::ExclamationEqualsEqualsToken: - case Tolerant\TokenKind::ExclamationEqualsToken: - case Tolerant\TokenKind::CaretToken: - case Tolerant\TokenKind::EqualsEqualsEqualsToken: - case Tolerant\TokenKind::EqualsToken: - return true; - } - return false; - } /** * Takes any class name node (from a static method call, or new node) and returns a Type object @@ -921,15 +829,13 @@ public function getTypeFromNode($node) if ($node instanceof Tolerant\Node\Parameter) { // Parameters // Get the doc block for the the function call - $functionLikeDeclaration = $this->getFunctionLikeDeclarationFromParameter($node); + $functionLikeDeclaration = TolerantParserHelpers::getFunctionLikeDeclarationFromParameter($node); $variableName = $node->variableName->getText($node->getFileContents()); $docBlock = $this->getDocBlock($functionLikeDeclaration); - if ($docBlock !== null) { - $parameterDocBlockTag = $this->getDocBlockTagForParameter($docBlock, $variableName); - if ($parameterDocBlockTag !== null && $parameterDocBlockTag->getType() !== null) { - return $parameterDocBlockTag->getType(); - } + $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); + if ($parameterDocBlockTag !== null && $parameterDocBlockTag->getType() !== null) { + return $parameterDocBlockTag->getType(); } if ($node->typeDeclaration !== null) { @@ -952,7 +858,7 @@ public function getTypeFromNode($node) return $type ?? new Types\Mixed; } // for functions and methods, get the return type [first from doc block, then from return type] - if ($this->isFunctionLike($node)) { + if (TolerantParserHelpers::isFunctionLike($node)) { // Functions/methods $docBlock = $this->getDocBlock($node); if ( @@ -976,14 +882,14 @@ public function getTypeFromNode($node) } // for variables / assignments, get the documented type the assignment resolves to. - if ($node instanceof Tolerant\Node\Expression\Variable) { + if ($node->parent instanceof Tolerant\Node\Expression\AssignmentExpression) { $node = $node->parent; } if ( - ($declarationNode = $node->getFirstAncestor( - Tolerant\Node\PropertyDeclaration::class, - Tolerant\Node\Statement\ConstDeclaration::class, - Tolerant\Node\ClassConstDeclaration::class)) !== null || + ($declarationNode = + TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? + TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node) + ) !== null || $node instanceof Tolerant\Node\Expression\AssignmentExpression) { $declarationNode = $declarationNode ?? $node; @@ -995,8 +901,6 @@ public function getTypeFromNode($node) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { -// var_dump("BOOYAH"); -// var_dump($type); return $type; } // Resolve the expression @@ -1018,20 +922,6 @@ public function getTypeFromNode($node) return null; } - /** - * @param DocBlock $docBlock - * @param $variableName - * @return DocBlock\Tags\Param | null - */ - private function getDocBlockTagForParameter($docBlock, $variableName) { - $tags = $docBlock->getTagsByName('param'); - foreach ($tags as $tag) { - if ($tag->getVariableName() === \ltrim($variableName, "$")) { - return $tag; - } - } - } - /** * 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 @@ -1059,14 +949,16 @@ public static function getDefinedFqn($node) // INPUT OUTPUT: // namespace A\B; A\B else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { - return (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + $name = (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + return \count($name) > 0 ? $name : null; } // INPUT OUTPUT: // namespace A\B; // function a(); A\B\a(); else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name - return (string)$node->getNamespacedName() . '()'; + $name = (string)$node->getNamespacedName(); + return \count($name) > 0 ? $name . '()' : null; } // INPUT OUTPUT // namespace A\B; @@ -1100,24 +992,24 @@ public static function getDefinedFqn($node) // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // } else if ( - $node instanceof Tolerant\Node\Expression\Variable && - ($propertyDeclaration = $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class)) !== null && + ($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null && ($classDeclaration = $node->getFirstAncestor( - Tolerant\Node\Statement\ObjectCreationExpression::class, + Tolerant\Node\Expression\ObjectCreationExpression::class, Tolerant\Node\Statement\ClassDeclaration::class, Tolerant\Node\Statement\InterfaceDeclaration::class, Tolerant\Node\Statement\TraitDeclaration::class ) - ) !== null && !($classDeclaration instanceof Tolerant\Node\Statement\ObjectCreationExpression)) + ) !== null && isset($classDeclaration->name)) { + $name = $node->getName(); if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name - return (string)$classDeclaration->getNamespacedName() . '::$' . (string)$node->getName(); - } elseif (($name = $node->getName()) !== null) { - // Instance Property: use ClassName->propertyName as name - return (string)$classDeclaration->getNamespacedName() . '->' . $name; + return (string)$classDeclaration->getNamespacedName() . '::$' . $name; } + + // Instance Property: use ClassName->propertyName as name + return (string)$classDeclaration->getNamespacedName() . '->' . $name; } // INPUT OUTPUT @@ -1126,23 +1018,42 @@ public static function getDefinedFqn($node) // class C { // const $a, $b = 4 A\B\C::$a(), A\B\C::$b // } - else if ($node instanceof Tolerant\Node\ConstElement) { - $constDeclaration = $node->getFirstAncestor(Tolerant\Node\Statement\ConstDeclaration::class, Tolerant\Node\ClassConstDeclaration::class); + else if (($constDeclaration = TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name return (string)$node->getNamespacedName(); } - if ($constDeclaration instanceof Tolerant\Node\ClassConstDeclaration) { - // Class constant: use ClassName::CONSTANT_NAME as name - $classDeclaration = $constDeclaration->getFirstAncestor( - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class - ); - if (!isset($classDeclaration->name)) { - return null; - } - return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); + + // Class constant: use ClassName::CONSTANT_NAME as name + $classDeclaration = $constDeclaration->getFirstAncestor( + Tolerant\Node\Expression\ObjectCreationExpression::class, + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ); + + if (!isset($classDeclaration->name)) { + return null; + } + return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); + } + + return null; + } + + /** + * @param DocBlock | null $docBlock + * @param $variableName + * @return DocBlock\Tags\Param | null + */ + private function tryGetDocBlockTagForParameter($docBlock, $variableName) { + if ($docBlock === null) { + return null; + } + $tags = $docBlock->getTagsByName('param'); + foreach ($tags as $tag) { + if ($tag->getVariableName() === \ltrim($variableName, "$")) { + return $tag; } } } diff --git a/src/TolerantParserHelpers.php b/src/TolerantParserHelpers.php new file mode 100644 index 00000000..8990f11d --- /dev/null +++ b/src/TolerantParserHelpers.php @@ -0,0 +1,103 @@ +parent instanceof Tolerant\Node\Statement\ExpressionStatement || + $node->parent instanceof Tolerant\Node\Expression || + $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList || + $node->parent instanceof Tolerant\Node\ArrayElement || + ($node->parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || + $node->parent instanceof Tolerant\Node\StatementNode || + $node->parent instanceof Tolerant\Node\CaseStatementNode + ) && + !( + $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || + ( + $node->parent instanceof Tolerant\Node\Expression\BinaryExpression && + $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword + ) + )); + } + + public static function getFunctionLikeDeclarationFromParameter(Tolerant\Node\Parameter $node) { + return $node->parent->parent; + } + + public static function isFunctionLike(Tolerant\Node $node) { + return + $node instanceof Tolerant\Node\Statement\FunctionDeclaration || + $node instanceof Tolerant\Node\MethodDeclaration || + $node instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression; + } + + public static function isBooleanExpression($expression) : bool { + if (!($expression instanceof Tolerant\Node\Expression\BinaryExpression)) { + return false; + } + switch ($expression->operator->kind) { + case Tolerant\TokenKind::InstanceOfKeyword: + case Tolerant\TokenKind::GreaterThanToken: + case Tolerant\TokenKind::GreaterThanEqualsToken: + case Tolerant\TokenKind::LessThanToken: + case Tolerant\TokenKind::LessThanEqualsToken: + case Tolerant\TokenKind::AndKeyword: + case Tolerant\TokenKind::AmpersandAmpersandToken: + case Tolerant\TokenKind::LessThanEqualsGreaterThanToken: + case Tolerant\TokenKind::OrKeyword: + case Tolerant\TokenKind::BarBarToken: + case Tolerant\TokenKind::XorKeyword: + case Tolerant\TokenKind::ExclamationEqualsEqualsToken: + case Tolerant\TokenKind::ExclamationEqualsToken: + case Tolerant\TokenKind::CaretToken: + case Tolerant\TokenKind::EqualsEqualsEqualsToken: + case Tolerant\TokenKind::EqualsToken: + return true; + } + return false; + } + + + /** + * Tries to get the parent property declaration given a Node + * @param Tolerant\Node $node + * @return Tolerant\Node\PropertyDeclaration | null $node + */ + public static function tryGetPropertyDeclaration(Tolerant\Node $node) { + if ($node instanceof Tolerant\Node\Expression\Variable && + (($propertyDeclaration = $node->parent->parent) instanceof Tolerant\Node\PropertyDeclaration || + ($propertyDeclaration = $propertyDeclaration->parent) instanceof Tolerant\Node\PropertyDeclaration) + ) { + return $propertyDeclaration; + } + return null; + } + + /** + * Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node + * @param Tolerant\Node $node + * @return Tolerant\Node\Statement\ConstDeclaration | Tolerant\Node\ClassConstDeclaration | null $node + */ + public static function tryGetConstOrClassConstDeclaration(Tolerant\Node $node) { + if ( + $node instanceof Tolerant\Node\ConstElement && ( + ($constDeclaration = $node->parent->parent) instanceof Tolerant\Node\ClassConstDeclaration || + $constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration ) + ) { + return $constDeclaration; + } + return null; + } +} \ No newline at end of file diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 103eb8d3..476ff2af 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -127,7 +127,7 @@ public function update($node) { // Namespaced constant access and function calls also need to register a reference // to the global version because PHP falls back to global at runtime // http://php.net/manual/en/language.namespaces.fallback.php - if (TolerantDefinitionResolver::isConstantFetch($node) || + if (TolerantParserHelpers::isConstantFetch($node) || ($parent instanceof Tolerant\Node\Expression\CallExpression && !( $parent->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || diff --git a/validation/frameworks/broken/classDefinition1.php b/validation/frameworks/broken/classDefinition1.php new file mode 100644 index 00000000..428b733b --- /dev/null +++ b/validation/frameworks/broken/classDefinition1.php @@ -0,0 +1,11 @@ +a; + +class A { + public $a = 3; +} \ No newline at end of file diff --git a/validation/frameworks/broken/classProperty1.php b/validation/frameworks/broken/classProperty1.php new file mode 100644 index 00000000..000e788c --- /dev/null +++ b/validation/frameworks/broken/classProperty1.php @@ -0,0 +1,19 @@ +args) { }; + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberCall1.php b/validation/frameworks/broken/memberCall1.php new file mode 100644 index 00000000..4f7ebeda --- /dev/null +++ b/validation/frameworks/broken/memberCall1.php @@ -0,0 +1,16 @@ +getAccount(); + } + + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/nameToken.php b/validation/frameworks/broken/nameToken.php new file mode 100644 index 00000000..770aef23 --- /dev/null +++ b/validation/frameworks/broken/nameToken.php @@ -0,0 +1,7 @@ +testProperty; \ No newline at end of file From bfbad095eeddbf493540a844c3b5eaae5a9cdb84 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Wed, 19 Apr 2017 17:52:37 -0700 Subject: [PATCH 064/149] Fix and start cleaning up type resolution issues --- src/TolerantDefinitionResolver.php | 80 ++- tests/Validation/ValidationTest.php | 15 +- .../frameworks/broken/ArrayNodeDefinition.php | 549 ++++++++++++++++++ .../frameworks/broken/WithReturnTypehints.php | 18 + .../frameworks/broken/forLoopReference1.php | 8 + validation/frameworks/broken/functionUse.php | 7 + validation/frameworks/broken/functionUse2.php | 4 + validation/frameworks/broken/magicConsts.php | 7 + validation/frameworks/broken/namespaces9.php | 6 + .../frameworks/broken/objectCreation3.php | 9 + .../broken/parameterTypeResolution1.php | 12 + .../frameworks/broken/propertyName1.php | 12 + .../frameworks/broken/propertyName2.php | 10 + .../frameworks/broken/staticInArray.php | 5 + 14 files changed, 712 insertions(+), 30 deletions(-) create mode 100644 validation/frameworks/broken/ArrayNodeDefinition.php create mode 100644 validation/frameworks/broken/WithReturnTypehints.php create mode 100644 validation/frameworks/broken/forLoopReference1.php create mode 100644 validation/frameworks/broken/functionUse.php create mode 100644 validation/frameworks/broken/functionUse2.php create mode 100644 validation/frameworks/broken/magicConsts.php create mode 100644 validation/frameworks/broken/namespaces9.php create mode 100644 validation/frameworks/broken/objectCreation3.php create mode 100644 validation/frameworks/broken/parameterTypeResolution1.php create mode 100644 validation/frameworks/broken/propertyName1.php create mode 100644 validation/frameworks/broken/propertyName2.php create mode 100644 validation/frameworks/broken/staticInArray.php diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 357afa83..58aac554 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -136,7 +136,7 @@ private function getDocBlock(Tolerant\Node $node) $namespaceImportTable[$alias] = (string)$name; } $namespaceDefinition = $node->getNamespaceDefinition(); - if ($namespaceDefinition !== null) { + if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); } else { $namespaceName = 'global'; @@ -518,7 +518,7 @@ public function resolveVariableToNode($var) */ public function resolveExpressionNodeToType($expr): Type { - if (!($expr instanceof Tolerant\Node)) { + if ($expr == null || $expr instanceof Tolerant\MissingToken || $expr instanceof Tolerant\SkippedToken) { // TODO some members are null or Missing/SkippedToken // How do we handle this more generally? return new Types\Mixed; @@ -529,18 +529,19 @@ public function resolveExpressionNodeToType($expr): Type } if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { - if ($expr instanceof Tolerant\Node\Expression\Variable && $expr->getName() === 'this') { + if ($expr->getName() === 'this') { return new Types\This; } - // Find variable definition + // Find variable definition (parameter or assignment expression) $defNode = $this->resolveVariableToNode($expr); - if ($defNode instanceof Tolerant\Node\Expression || $defNode instanceof Tolerant\Node\UseVariableName) { + if ($defNode instanceof Tolerant\Node\Expression\AssignmentExpression || $defNode instanceof Tolerant\Node\UseVariableName) { return $this->resolveExpressionNodeToType($defNode); } if ($defNode instanceof Tolerant\Node\Parameter) { return $this->getTypeFromNode($defNode); } } + if ($expr instanceof Tolerant\Node\Expression\CallExpression && !( $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || @@ -562,7 +563,9 @@ public function resolveExpressionNodeToType($expr): Type } } } - if (strtolower((string)$expr->getText()) === 'true' || strtolower((string)$expr->getText()) === 'false') { + + $lowerText = strtolower($expr->getText()); + if ($lowerText === 'true' || $lowerText === 'false') { return new Types\Boolean; } @@ -574,7 +577,8 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } } - if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { + + if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { if ($access->memberName instanceof Tolerant\Node\Expression) { return new Types\Mixed; } @@ -606,6 +610,7 @@ public function resolveExpressionNodeToType($expr): Type } } } + if ( ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { @@ -626,15 +631,19 @@ public function resolveExpressionNodeToType($expr): Type } return $def->type; } + if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { return $this->resolveClassNameToType($expr->classTypeDesignator); } + if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { return $this->resolveExpressionNodeToType($expr->expression); } + if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { return $this->resolveExpressionNodeToType($expr->rightOperand); } + if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { // ?: if ($expr->ifExpression === null) { @@ -649,6 +658,7 @@ public function resolveExpressionNodeToType($expr): Type $this->resolveExpressionNodeToType($expr->elseExpression) ]); } + if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { // ?? operator return new Types\Compound([ @@ -656,6 +666,7 @@ public function resolveExpressionNodeToType($expr): Type $this->resolveExpressionNodeToType($expr->rightOperand) ]); } + if ( TolerantParserHelpers::isBooleanExpression($expr) @@ -666,6 +677,7 @@ public function resolveExpressionNodeToType($expr): Type ) { return new Types\Boolean; } + if ( ($expr instanceof Tolerant\Node\Expression\BinaryExpression && ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || @@ -683,8 +695,10 @@ public function resolveExpressionNodeToType($expr): Type // || $expr instanceof Node\Expr\Scalar\MagicConst\Namespace_ // || $expr instanceof Node\Expr\Scalar\MagicConst\Trait_ ) { + var_dump("string literal"); return new Types\String_; } + if ( $expr instanceof Tolerant\Node\Expression\BinaryExpression && ($operator = $expr->operator->kind) @@ -706,6 +720,7 @@ public function resolveExpressionNodeToType($expr): Type } return new Types\Float_; } + if ( // TODO better naming ($expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::IntegerLiteralToken) || @@ -719,6 +734,7 @@ public function resolveExpressionNodeToType($expr): Type ) { return new Types\Integer; } + if ( $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || @@ -726,6 +742,7 @@ public function resolveExpressionNodeToType($expr): Type ) { return new Types\Float_; } + if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; @@ -753,6 +770,7 @@ public function resolveExpressionNodeToType($expr): Type } return new Types\Array_($valueType, $keyType); } + if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { @@ -760,10 +778,12 @@ public function resolveExpressionNodeToType($expr): Type } return $varType->getValueType(); } + if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { // TODO: resolve path to PhpDocument and find return statement return new Types\Mixed; } + return new Types\Mixed; } @@ -785,14 +805,15 @@ public function resolveClassNameToType($class): Type return new Types\Object_; } $className = (string)$class->getResolvedName(); + $lowerClassName = strtolower($className); - if ($className === 'static') { + if ($lowerClassName === 'static') { return new Types\Static_; } - if ($className === 'self' || $className === 'parent') { + if ($lowerClassName === 'self' || $lowerClassName === 'parent') { $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($className === 'parent') { - if ($classNode === null || $classNode->classBaseClause === null || $classNode->classBaseClause->baseClass === null) { + if ($lowerClassName === 'parent') { + if ($classNode === null || $classNode->classBaseClause === null) { return new Types\Object_; } // parent is resolved to the parent class @@ -825,19 +846,25 @@ public function resolveClassNameToType($class): Type */ public function getTypeFromNode($node) { - // For parameters, get the type of the parameter [first from doc block, then from param type] + // For parameters, get the type of the parameter [first from doc block, then from combo of param type and default if ($node instanceof Tolerant\Node\Parameter) { // Parameters // Get the doc block for the the function call + // /** + // * @param MyClass $myParam + // */ + // function foo($a) $functionLikeDeclaration = TolerantParserHelpers::getFunctionLikeDeclarationFromParameter($node); - $variableName = $node->variableName->getText($node->getFileContents()); + $variableName = $node->getName(); $docBlock = $this->getDocBlock($functionLikeDeclaration); $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); - if ($parameterDocBlockTag !== null && $parameterDocBlockTag->getType() !== null) { - return $parameterDocBlockTag->getType(); + if ($parameterDocBlockTag !== null && ($type = $parameterDocBlockTag->getType())) { + // Doc block comments supercede all other forms of type inference + return $type; } + // function foo(MyClass $a) if ($node->typeDeclaration !== null) { // Use PHP7 return type hint if ($node->typeDeclaration instanceof Tolerant\Token) { @@ -847,13 +874,14 @@ public function getTypeFromNode($node) $type = new Types\Object_(new Fqsen('\\' . (string)$node->typeDeclaration->getResolvedName())); } } + // function foo($a = 3) if ($node->default !== null) { $defaultType = $this->resolveExpressionNodeToType($node->default); if (isset($type) && !is_a($type, get_class($defaultType))) { - $type = new Types\Compound([$type, $defaultType]); - } else { - $type = $defaultType; + // TODO - verify it is worth creating a compound type + return new Types\Compound([$type, $defaultType]); } + $type = $defaultType; } return $type ?? new Types\Mixed; } @@ -869,7 +897,7 @@ public function getTypeFromNode($node) // Use @return tag return $returnTags[0]->getType(); } - if ($node->returnType !== null) { + if ($node->returnType !== null && !($node->returnType instanceof Tolerant\MissingToken)) { // Use PHP7 return type hint if ($node->returnType instanceof Tolerant\Token) { // Resolve a string like "bool" to a type object @@ -882,15 +910,12 @@ public function getTypeFromNode($node) } // for variables / assignments, get the documented type the assignment resolves to. - if ($node->parent instanceof Tolerant\Node\Expression\AssignmentExpression) { - $node = $node->parent; - } if ( ($declarationNode = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node) ) !== null || - $node instanceof Tolerant\Node\Expression\AssignmentExpression) + ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) { $declarationNode = $declarationNode ?? $node; @@ -903,22 +928,25 @@ public function getTypeFromNode($node) ) { return $type; } + // Resolve the expression if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { // TODO should have default - if (isset($node->rightOperand)) { - return $this->resolveExpressionNodeToType($node->rightOperand); + if (isset($node->parent->rightOperand)) { + return $this->resolveExpressionNodeToType($node->parent->rightOperand); } } else if ($node instanceof Tolerant\Node\ConstElement) { return $this->resolveExpressionNodeToType($node->assignment); } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { - return $this->resolveExpressionNodeToType($node); + return $this->resolveExpressionNodeToType($node->rightOperand); } // TODO: read @property tags of class // TODO: Try to infer the type from default value / constant value // Unknown return new Types\Mixed; } + + // The node does not have a type return null; } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 3e4a32c1..f3b08afb 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -35,7 +35,7 @@ public function frameworkErrorProvider() { foreach (new RecursiveIteratorIterator($iterator) as $file) { if (strpos(\strrev((string)$file), \strrev(".php")) === 0 -// && strpos((string)$file, "taxonomy.php")!== false +// && strpos((string)$file, "memberAccess3.php")!== false ) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; @@ -151,13 +151,18 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $static = []; foreach ($document->getDefinitions() as $defn) { $fqns[] = $defn->fqn; + + if ($defn->type instanceof \phpDocumentor\Reflection\Types\Null_) { + $defn->type = new \phpDocumentor\Reflection\Types\Mixed; + } $currentTypes[$defn->fqn] = $defn->type; + $canBeInstantiated[$defn->fqn] = $defn->canBeInstantiated; $defn->symbolInformation->location = null; $symbols[$defn->fqn] = $defn->symbolInformation; - $extends[$defn->fqn] = $defn->extends; + $extends[$defn->fqn] = $defn->extends ?? []; $global[$defn->fqn] = $defn->isGlobal; $docs[$defn->fqn] = $defn->documentation; $static[$defn->fqn] = $defn->isStatic; @@ -165,7 +170,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { if ($definitions !== null) { $this->assertEquals($definitions, $fqns, 'defn->fqn does not match'); -// $this->assertEquals($types, $currentTypes, "defn->type does not match"); + $this->assertEquals($types, $currentTypes, "defn->type does not match"); $this->assertEquals($instantiated, $canBeInstantiated, "defn->canBeInstantiated does not match"); $this->assertEquals($extend, $extends, 'defn->extends does not match'); $this->assertEquals($isGlobal, $global, 'defn->isGlobal does not match'); @@ -180,7 +185,9 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', '__', // magic constants are treated as normal constants 'Exception', // catch exception types missing from old definition resolver - 'Trait' // use Trait references are missing from old definition resolve + 'Trait', // use Trait references are missing from old definition resolve + '->tableAlias', '->realField', '->field', '->first_name', '->last_name', '->quoteMatch', '->idCol', '->timeCol', '->dataCol', + 'pathToUri', 'uriToPath' // group function use declarations are broken in old definition resolver ]; foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { foreach ($skipped as $s) { diff --git a/validation/frameworks/broken/ArrayNodeDefinition.php b/validation/frameworks/broken/ArrayNodeDefinition.php new file mode 100644 index 00000000..4ad218bb --- /dev/null +++ b/validation/frameworks/broken/ArrayNodeDefinition.php @@ -0,0 +1,549 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\ArrayNode; +use Symfony\Component\Config\Definition\PrototypedArrayNode; +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; + +/** + * This class provides a fluent interface for defining an array node. + * + * @author Johannes M. Schmitt + */ +class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface +{ + protected $performDeepMerging = true; + protected $ignoreExtraKeys = false; + protected $removeExtraKeys = true; + protected $children = array(); + protected $prototype; + protected $atLeastOne = false; + protected $allowNewKeys = true; + protected $key; + protected $removeKeyItem; + protected $addDefaults = false; + protected $addDefaultChildren = false; + protected $nodeBuilder; + protected $normalizeKeys = true; + + /** + * {@inheritdoc} + */ + public function __construct($name, NodeParentInterface $parent = null) + { + parent::__construct($name, $parent); + + $this->nullEquivalent = array(); + $this->trueEquivalent = array(); + } + + /** + * Sets a custom children builder. + * + * @param NodeBuilder $builder A custom NodeBuilder + */ + public function setBuilder(NodeBuilder $builder) + { + $this->nodeBuilder = $builder; + } + + /** + * Returns a builder to add children nodes. + * + * @return NodeBuilder + */ + public function children() + { + return $this->getNodeBuilder(); + } + + /** + * Sets a prototype for child nodes. + * + * @param string $type the type of node + * + * @return NodeDefinition + */ + public function prototype($type) + { + return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); + } + + /** + * @return VariableNodeDefinition + */ + public function variablePrototype() + { + return $this->prototype('variable'); + } + + /** + * @return ScalarNodeDefinition + */ + public function scalarPrototype() + { + return $this->prototype('scalar'); + } + + /** + * @return BooleanNodeDefinition + */ + public function booleanPrototype() + { + return $this->prototype('boolean'); + } + + /** + * @return IntegerNodeDefinition + */ + public function integerPrototype() + { + return $this->prototype('integer'); + } + + /** + * @return FloatNodeDefinition + */ + public function floatPrototype() + { + return $this->prototype('float'); + } + + /** + * @return ArrayNodeDefinition + */ + public function arrayPrototype() + { + return $this->prototype('array'); + } + + /** + * @return EnumNodeDefinition + */ + public function enumPrototype() + { + return $this->prototype('enum'); + } + + /** + * Adds the default value if the node is not set in the configuration. + * + * This method is applicable to concrete nodes only (not to prototype nodes). + * If this function has been called and the node is not set during the finalization + * phase, it's default value will be derived from its children default values. + * + * @return ArrayNodeDefinition + */ + public function addDefaultsIfNotSet() + { + $this->addDefaults = true; + + return $this; + } + + /** + * Adds children with a default value when none are defined. + * + * @param int|string|array|null $children The number of children|The child name|The children names to be added + * + * This method is applicable to prototype nodes only. + * + * @return ArrayNodeDefinition + */ + public function addDefaultChildrenIfNoneSet($children = null) + { + $this->addDefaultChildren = $children; + + return $this; + } + + /** + * Requires the node to have at least one element. + * + * This method is applicable to prototype nodes only. + * + * @return ArrayNodeDefinition + */ + public function requiresAtLeastOneElement() + { + $this->atLeastOne = true; + + return $this; + } + + /** + * Disallows adding news keys in a subsequent configuration. + * + * If used all keys have to be defined in the same configuration file. + * + * @return ArrayNodeDefinition + */ + public function disallowNewKeysInSubsequentConfigs() + { + $this->allowNewKeys = false; + + return $this; + } + + /** + * Sets a normalization rule for XML configurations. + * + * @param string $singular The key to remap + * @param string $plural The plural of the key for irregular plurals + * + * @return ArrayNodeDefinition + */ + public function fixXmlConfig($singular, $plural = null) + { + $this->normalization()->remap($singular, $plural); + + return $this; + } + + /** + * Sets the attribute which value is to be used as key. + * + * This is useful when you have an indexed array that should be an + * associative array. You can select an item from within the array + * to be the key of the particular item. For example, if "id" is the + * "key", then: + * + * array( + * array('id' => 'my_name', 'foo' => 'bar'), + * ); + * + * becomes + * + * array( + * 'my_name' => array('foo' => 'bar'), + * ); + * + * If you'd like "'id' => 'my_name'" to still be present in the resulting + * array, then you can set the second argument of this method to false. + * + * This method is applicable to prototype nodes only. + * + * @param string $name The name of the key + * @param bool $removeKeyItem Whether or not the key item should be removed + * + * @return ArrayNodeDefinition + */ + public function useAttributeAsKey($name, $removeKeyItem = true) + { + $this->key = $name; + $this->removeKeyItem = $removeKeyItem; + + return $this; + } + + /** + * Sets whether the node can be unset. + * + * @param bool $allow + * + * @return ArrayNodeDefinition + */ + public function canBeUnset($allow = true) + { + $this->merge()->allowUnset($allow); + + return $this; + } + + /** + * Adds an "enabled" boolean to enable the current section. + * + * By default, the section is disabled. If any configuration is specified then + * the node will be automatically enabled: + * + * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden + * enableableArrayNode: ~ # The config is enabled & use the default values + * enableableArrayNode: true # The config is enabled & use the default values + * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden + * enableableArrayNode: {enabled: false, ...} # The config is disabled + * enableableArrayNode: false # The config is disabled + * + * @return ArrayNodeDefinition + */ + public function canBeEnabled() + { + $this + ->addDefaultsIfNotSet() + ->treatFalseLike(array('enabled' => false)) + ->treatTrueLike(array('enabled' => true)) + ->treatNullLike(array('enabled' => true)) + ->beforeNormalization() + ->ifArray() + ->then(function ($v) { + $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; + + return $v; + }) + ->end() + ->children() + ->booleanNode('enabled') + ->defaultFalse() + ; + + return $this; + } + + /** + * Adds an "enabled" boolean to enable the current section. + * + * By default, the section is enabled. + * + * @return ArrayNodeDefinition + */ + public function canBeDisabled() + { + $this + ->addDefaultsIfNotSet() + ->treatFalseLike(array('enabled' => false)) + ->treatTrueLike(array('enabled' => true)) + ->treatNullLike(array('enabled' => true)) + ->children() + ->booleanNode('enabled') + ->defaultTrue() + ; + + return $this; + } + + /** + * Disables the deep merging of the node. + * + * @return ArrayNodeDefinition + */ + public function performNoDeepMerging() + { + $this->performDeepMerging = false; + + return $this; + } + + /** + * Allows extra config keys to be specified under an array without + * throwing an exception. + * + * Those config values are simply ignored and removed from the + * resulting array. This should be used only in special cases where + * you want to send an entire configuration array through a special + * tree that processes only part of the array. + * + * @param bool $remove Whether to remove the extra keys + * + * @return ArrayNodeDefinition + */ + public function ignoreExtraKeys($remove = true) + { + $this->ignoreExtraKeys = true; + $this->removeExtraKeys = $remove; + + return $this; + } + + /** + * Sets key normalization. + * + * @param bool $bool Whether to enable key normalization + * + * @return ArrayNodeDefinition + */ + public function normalizeKeys($bool) + { + $this->normalizeKeys = (bool) $bool; + + return $this; + } + + /** + * Appends a node definition. + * + * $node = new ArrayNodeDefinition() + * ->children() + * ->scalarNode('foo')->end() + * ->scalarNode('baz')->end() + * ->end() + * ->append($this->getBarNodeDefinition()) + * ; + * + * @param NodeDefinition $node A NodeDefinition instance + * + * @return ArrayNodeDefinition This node + */ + public function append(NodeDefinition $node) + { + $this->children[$node->name] = $node->setParent($this); + + return $this; + } + + /** + * Returns a node builder to be used to add children and prototype. + * + * @return NodeBuilder The node builder + */ + protected function getNodeBuilder() + { + if (null === $this->nodeBuilder) { + $this->nodeBuilder = new NodeBuilder(); + } + + return $this->nodeBuilder->setParent($this); + } + + /** + * {@inheritdoc} + */ + protected function createNode() + { + if (null === $this->prototype) { + $node = new ArrayNode($this->name, $this->parent); + + $this->validateConcreteNode($node); + + $node->setAddIfNotSet($this->addDefaults); + + foreach ($this->children as $child) { + $child->parent = $node; + $node->addChild($child->getNode()); + } + } else { + $node = new PrototypedArrayNode($this->name, $this->parent); + + $this->validatePrototypeNode($node); + + if (null !== $this->key) { + $node->setKeyAttribute($this->key, $this->removeKeyItem); + } + + if (true === $this->atLeastOne) { + $node->setMinNumberOfElements(1); + } + + if ($this->default) { + $node->setDefaultValue($this->defaultValue); + } + + if (false !== $this->addDefaultChildren) { + $node->setAddChildrenIfNoneSet($this->addDefaultChildren); + if ($this->prototype instanceof static && null === $this->prototype->prototype) { + $this->prototype->addDefaultsIfNotSet(); + } + } + + $this->prototype->parent = $node; + $node->setPrototype($this->prototype->getNode()); + } + + $node->setAllowNewKeys($this->allowNewKeys); + $node->addEquivalentValue(null, $this->nullEquivalent); + $node->addEquivalentValue(true, $this->trueEquivalent); + $node->addEquivalentValue(false, $this->falseEquivalent); + $node->setPerformDeepMerging($this->performDeepMerging); + $node->setRequired($this->required); + $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); + $node->setNormalizeKeys($this->normalizeKeys); + + if (null !== $this->normalization) { + $node->setNormalizationClosures($this->normalization->before); + $node->setXmlRemappings($this->normalization->remappings); + } + + if (null !== $this->merge) { + $node->setAllowOverwrite($this->merge->allowOverwrite); + $node->setAllowFalse($this->merge->allowFalse); + } + + if (null !== $this->validation) { + $node->setFinalValidationClosures($this->validation->rules); + } + + return $node; + } + + /** + * Validate the configuration of a concrete node. + * + * @param ArrayNode $node The related node + * + * @throws InvalidDefinitionException + */ + protected function validateConcreteNode(ArrayNode $node) + { + $path = $node->getPath(); + + if (null !== $this->key) { + throw new InvalidDefinitionException( + sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path) + ); + } + + if (true === $this->atLeastOne) { + throw new InvalidDefinitionException( + sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) + ); + } + + if ($this->default) { + throw new InvalidDefinitionException( + sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path) + ); + } + + if (false !== $this->addDefaultChildren) { + throw new InvalidDefinitionException( + sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path) + ); + } + } + + /** + * Validate the configuration of a prototype node. + * + * @param PrototypedArrayNode $node The related node + * + * @throws InvalidDefinitionException + */ + protected function validatePrototypeNode(PrototypedArrayNode $node) + { + $path = $node->getPath(); + + if ($this->addDefaults) { + throw new InvalidDefinitionException( + sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path) + ); + } + + if (false !== $this->addDefaultChildren) { + if ($this->default) { + throw new InvalidDefinitionException( + sprintf('A default value and default children might not be used together at path "%s"', $path) + ); + } + + if (null !== $this->key && (null === $this->addDefaultChildren || is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { + throw new InvalidDefinitionException( + sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path) + ); + } + + if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { + throw new InvalidDefinitionException( + sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path) + ); + } + } + } +} diff --git a/validation/frameworks/broken/WithReturnTypehints.php b/validation/frameworks/broken/WithReturnTypehints.php new file mode 100644 index 00000000..045051fd --- /dev/null +++ b/validation/frameworks/broken/WithReturnTypehints.php @@ -0,0 +1,18 @@ +getParent()) { + } + } +} diff --git a/validation/frameworks/broken/functionUse.php b/validation/frameworks/broken/functionUse.php new file mode 100644 index 00000000..ff3fe9e7 --- /dev/null +++ b/validation/frameworks/broken/functionUse.php @@ -0,0 +1,7 @@ +b(); +}; \ No newline at end of file diff --git a/validation/frameworks/broken/functionUse2.php b/validation/frameworks/broken/functionUse2.php new file mode 100644 index 00000000..593e6ac9 --- /dev/null +++ b/validation/frameworks/broken/functionUse2.php @@ -0,0 +1,4 @@ + true + ); +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces9.php b/validation/frameworks/broken/namespaces9.php new file mode 100644 index 00000000..5ca557a1 --- /dev/null +++ b/validation/frameworks/broken/namespaces9.php @@ -0,0 +1,6 @@ +textDocument = new class($this->args) + { + }; + } +} diff --git a/validation/frameworks/broken/parameterTypeResolution1.php b/validation/frameworks/broken/parameterTypeResolution1.php new file mode 100644 index 00000000..09ead6f5 --- /dev/null +++ b/validation/frameworks/broken/parameterTypeResolution1.php @@ -0,0 +1,12 @@ +getAccount(); + } + } +} diff --git a/validation/frameworks/broken/propertyName1.php b/validation/frameworks/broken/propertyName1.php new file mode 100644 index 00000000..c53cf545 --- /dev/null +++ b/validation/frameworks/broken/propertyName1.php @@ -0,0 +1,12 @@ + Date: Thu, 20 Apr 2017 00:20:47 -0700 Subject: [PATCH 065/149] Update + clarify type resolution logic --- src/TolerantDefinitionResolver.php | 172 ++++++++++++++++++++-------- src/TolerantTreeAnalyzer.php | 90 +++++++-------- tests/Validation/ValidationTest.php | 5 +- 3 files changed, 172 insertions(+), 95 deletions(-) diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 58aac554..f9fc3414 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -402,7 +402,18 @@ private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression } private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { - $className = $scoped->scopeResolutionQualifier->getText(); + if ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\Expression\Variable) { + $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); + if ($varType === null) { + return null; + } + $className = substr((string)$varType->getFqsen(), 1); + } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + $className = (string)$scoped->scopeResolutionQualifier->getResolvedName(); + } else { + return null; + } + if ($className === 'self' || $className === 'static' || $className === 'parent') { // self and static are resolved to the containing class $classNode = $scoped->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); @@ -422,7 +433,11 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex $className = $scoped->scopeResolutionQualifier->getResolvedName(); } if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { - $name = (string)$className . '::$' . $scoped->memberName->getName(); + $memberName = $scoped->memberName->getName(); + if (empty($memberName)) { + return null; + } + $name = (string)$className . '::$' . $memberName; } else { $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); } @@ -524,10 +539,15 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } + // PARENTHESIZED EXPRESSION + // Retrieve inner expression from parenthesized expression while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { $expr = $expr->expression; } + // VARIABLE + // $this -> Type\this + // $myVariable -> type of corresponding assignment expression if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { if ($expr->getName() === 'this') { return new Types\This; @@ -542,11 +562,13 @@ public function resolveExpressionNodeToType($expr): Type } } + // FUNCTION CALL + // Function calls are resolved to type corresponding to their FQN if ($expr instanceof Tolerant\Node\Expression\CallExpression && !( $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) - ) { + ) { // Find the function definition if ($expr->callableExpression instanceof Tolerant\Node\Expression) { @@ -564,13 +586,22 @@ public function resolveExpressionNodeToType($expr): Type } } - $lowerText = strtolower($expr->getText()); - if ($lowerText === 'true' || $lowerText === 'false') { - return new Types\Boolean; + // TRUE / FALSE / NULL + // Resolve true and false reserved words to Types\Boolean + if ($expr instanceof Tolerant\Node\ReservedWord) { + $token = $expr->children->kind; + if ($token === Tolerant\TokenKind::TrueReservedWord || $token === Tolerant\TokenKind::FalseReservedWord) { + return new Types\Boolean; + } + + if ($token === Tolerant\TokenKind::NullReservedWord) { + return new Types\Null_; + } } + // CONSTANT FETCH + // Resolve constants by retrieving corresponding definition type from FQN if (TolerantParserHelpers::isConstantFetch($expr)) { - // Resolve constant $fqn = (string)$expr->getNamespacedName(); $def = $this->index->getDefinition($fqn, true); if ($def !== null) { @@ -578,11 +609,12 @@ public function resolveExpressionNodeToType($expr): Type } } - if (($access = $expr) instanceof Tolerant\Node\Expression\MemberAccessExpression) { - if ($access->memberName instanceof Tolerant\Node\Expression) { + // MEMBER ACCESS EXPRESSION + if ($expr instanceof Tolerant\Node\Expression\MemberAccessExpression) { + if ($expr->memberName instanceof Tolerant\Node\Expression) { return new Types\Mixed; } - $var = $access->dereferencableExpression; + $var = $expr->dereferencableExpression; // Resolve object $objType = $this->resolveExpressionNodeToType($var); @@ -600,7 +632,7 @@ public function resolveExpressionNodeToType($expr): Type } else { $classFqn = substr((string)$t->getFqsen(), 1); } - $fqn = $classFqn . '->' . $access->memberName->getText($expr->getFileContents()); + $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } @@ -609,18 +641,18 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } } - } + } - if ( - ($scopedAccess = $expr) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - ) { - $classType = $this->resolveClassNameToType($scopedAccess->scopeResolutionQualifier); - if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null /*|| $expr->name instanceof Tolerant\Node\Expression*/) { + // SCOPED PROPERTY ACCESS EXPRESSION + if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { + $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); + if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { return new Types\Mixed; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; - $fqn .= $scopedAccess->memberName->getText() ?? $scopedAccess->memberName->getText($expr->getFileContents()); // 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()); if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } @@ -632,23 +664,33 @@ public function resolveExpressionNodeToType($expr): Type return $def->type; } + // OBJECT CREATION EXPRESSION + // new A() => resolves to the type of the class type designator (A) + // TODO: new $this->a => resolves to the string represented by "a" if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { return $this->resolveClassNameToType($expr->classTypeDesignator); } + // CLONE EXPRESSION + // clone($a) => resolves to the type of $a if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { return $this->resolveExpressionNodeToType($expr->expression); } + // ASSIGNMENT EXPRESSION + // $a = $myExpression => resolves to the type of the right-hand operand if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { return $this->resolveExpressionNodeToType($expr->rightOperand); } + // TERNARY EXPRESSION + // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression + // $condition ?: $elseExpression => resolves to type of $condition or $elseExpression if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { // ?: if ($expr->ifExpression === null) { return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->condition), // why? + $this->resolveExpressionNodeToType($expr->condition), // TODO: why? $this->resolveExpressionNodeToType($expr->elseExpression) ]); } @@ -659,6 +701,8 @@ public function resolveExpressionNodeToType($expr): Type ]); } + // NULL COALLESCE + // $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { // ?? operator return new Types\Compound([ @@ -667,6 +711,12 @@ public function resolveExpressionNodeToType($expr): Type ]); } + // BOOLEAN EXPRESSIONS: resolve to Types\Boolean + // (bool) $expression + // !$expression + // empty($var) + // isset($var) + // >, >=, <, <=, &&, ||, AND, OR, XOR, ==, ===, !=, !== if ( TolerantParserHelpers::isBooleanExpression($expr) @@ -678,27 +728,27 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Boolean; } + // STRING EXPRESSIONS: resolve to Types\String + // [concatenation] .=, . + // [literals] "hello", \b"hello", \B"hello", 'hello', \b'hello', HEREDOC, NOWDOC + // [cast] (string) "hello" + // + // TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__) if ( ($expr instanceof Tolerant\Node\Expression\BinaryExpression && ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || $expr instanceof Tolerant\Node\StringLiteral || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) - - // TODO -// || $expr instanceof Node\Expr\Scalar\String_ -// || $expr instanceof Node\Expr\Scalar\Encapsed -// || $expr instanceof Node\Expr\Scalar\EncapsedStringPart -// || $expr instanceof Node\Expr\Scalar\MagicConst\Class_ -// || $expr instanceof Node\Expr\Scalar\MagicConst\Dir -// || $expr instanceof Node\Expr\Scalar\MagicConst\Function_ -// || $expr instanceof Node\Expr\Scalar\MagicConst\Method -// || $expr instanceof Node\Expr\Scalar\MagicConst\Namespace_ -// || $expr instanceof Node\Expr\Scalar\MagicConst\Trait_ ) { - var_dump("string literal"); return new Types\String_; } + // BINARY EXPRESSIONS: + // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float + // [operator] +, -, *, ** + // [assignment] *=, **=, -=, += + // Resolve to Types\Float + // [assignment] /= if ( $expr instanceof Tolerant\Node\Expression\BinaryExpression && ($operator = $expr->operator->kind) @@ -706,23 +756,34 @@ public function resolveExpressionNodeToType($expr): Type $operator === Tolerant\TokenKind::AsteriskAsteriskToken || $operator === Tolerant\TokenKind::AsteriskToken || $operator === Tolerant\TokenKind::MinusToken || + + // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression) $operator === Tolerant\TokenKind::AsteriskEqualsToken|| $operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || $operator === Tolerant\TokenKind::MinusEqualsToken || - $operator === Tolerant\TokenKind::PlusEqualsToken // TODO - this should be a type of assigment expression + $operator === Tolerant\TokenKind::PlusEqualsToken ) ) { if ( - $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer_ - && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer_ + $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer + && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer ) { return new Types\Integer; } return new Types\Float_; + } else if ( + $expr instanceof Tolerant\Node\Expression\BinaryExpression && + $expr->operator->kind === Tolerant\TokenKind::SlashEqualsToken + ) { + return new Types\Float_; } + // INTEGER EXPRESSIONS: resolve to Types\Integer + // [literal] 1 + // [operator] <=>, &, ^, | + // TODO: Magic constants (__LINE__) if ( - // TODO better naming + // 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 Tolerant\Node\Expression\BinaryExpression && ( ($operator = $expr->operator->kind) @@ -735,14 +796,22 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Integer; } + // FLOAT EXPRESSIONS: resolve to Types\Float + // [literal] 1.5 + // [operator] / + // [cast] (double) if ( - $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken - || - ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) + $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || + ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) || + ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::SlashToken) ) { return new Types\Float_; } + // ARRAY CREATION EXPRESSION: + // Resolve to Types\Array (Types\Compound of value and key types) + // [a, b, c] + // [1=>"hello", "hi"=>1, 4=>[]]s if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; @@ -771,6 +840,9 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Array_($valueType, $keyType); } + // SUBSCRIPT EXPRESSION + // $myArray[3] + // $myArray{"hello"} if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { @@ -779,6 +851,8 @@ public function resolveExpressionNodeToType($expr): Type return $varType->getValueType(); } + // SCRIPT INCLUSION EXPRESSION + // include, require, include_once, require_once if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { // TODO: resolve path to PhpDocument and find return statement return new Types\Mixed; @@ -805,14 +879,13 @@ public function resolveClassNameToType($class): Type return new Types\Object_; } $className = (string)$class->getResolvedName(); - $lowerClassName = strtolower($className); - if ($lowerClassName === 'static') { + if ($className === 'static') { return new Types\Static_; } - if ($lowerClassName === 'self' || $lowerClassName === 'parent') { + if ($className === 'self' || $className === 'parent') { $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($lowerClassName === 'parent') { + if ($className === 'parent') { if ($classNode === null || $classNode->classBaseClause === null) { return new Types\Object_; } @@ -846,7 +919,10 @@ public function resolveClassNameToType($class): Type */ public function getTypeFromNode($node) { - // For parameters, get the type of the parameter [first from doc block, then from combo of param type and default + // PARAMETERS + // Get the type of the parameter: + // 1. Doc block + // 2. Parameter type and default if ($node instanceof Tolerant\Node\Parameter) { // Parameters // Get the doc block for the the function call @@ -885,7 +961,12 @@ public function getTypeFromNode($node) } return $type ?? new Types\Mixed; } - // for functions and methods, get the return type [first from doc block, then from return type] + + // FUNCTIONS AND METHODS + // Get the return type + // 1. doc block + // 2. return type hint + // 3. TODO: infer from return statements if (TolerantParserHelpers::isFunctionLike($node)) { // Functions/methods $docBlock = $this->getDocBlock($node); @@ -909,7 +990,8 @@ public function getTypeFromNode($node) return new Types\Mixed; } - // for variables / assignments, get the documented type the assignment resolves to. + // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS + // Get the documented type the assignment resolves to. if ( ($declarationNode = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 476ff2af..933b793b 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -91,58 +91,56 @@ public function update($node) { if ($fqn !== null) { $this->definitionNodes[$fqn] = $node; $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); - } - - $parent = $node->parent; - if (!( - ( - // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression) - && !( - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->memberName instanceof Tolerant\Token - )) - || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) - ) { - - $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn !== null) { - $this->addReference($fqn, $node); - - if ( - $node instanceof Tolerant\Node\QualifiedName - && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) - && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() - ) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); + } else { + $parent = $node->parent; + if (!( + ( + // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression) + && !( + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->memberName instanceof Tolerant\Token + )) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) + ) { + + $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); + if ($fqn !== null) { + $this->addReference($fqn, $node); + + if ( + $node instanceof Tolerant\Node\QualifiedName + && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) + && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } } - } - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if (TolerantParserHelpers::isConstantFetch($node) || - ($parent instanceof Tolerant\Node\Expression\CallExpression - && !( - $parent->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression - ))) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if (TolerantParserHelpers::isConstantFetch($node) || + ($parent instanceof Tolerant\Node\Expression\CallExpression + && !( + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); + } } } } } - $this->collectDefinitionsAndReferences($node); } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index f3b08afb..3375f6cb 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -35,7 +35,7 @@ public function frameworkErrorProvider() { foreach (new RecursiveIteratorIterator($iterator) as $file) { if (strpos(\strrev((string)$file), \strrev(".php")) === 0 -// && strpos((string)$file, "memberAccess3.php")!== false +// && strpos((string)$file, "ContainerFactory.php")!== false ) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; @@ -152,9 +152,6 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { foreach ($document->getDefinitions() as $defn) { $fqns[] = $defn->fqn; - if ($defn->type instanceof \phpDocumentor\Reflection\Types\Null_) { - $defn->type = new \phpDocumentor\Reflection\Types\Mixed; - } $currentTypes[$defn->fqn] = $defn->type; $canBeInstantiated[$defn->fqn] = $defn->canBeInstantiated; From 223a2eac6c52f0b660978927bbec2eb31593d572 Mon Sep 17 00:00:00 2001 From: Sara Itani Date: Thu, 20 Apr 2017 00:58:26 -0700 Subject: [PATCH 066/149] fix return type resolution issue --- src/TolerantParserHelpers.php | 27 +++++++++++---------- validation/frameworks/broken/returnType.php | 13 ++++++++++ 2 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 validation/frameworks/broken/returnType.php diff --git a/src/TolerantParserHelpers.php b/src/TolerantParserHelpers.php index 8990f11d..33902028 100644 --- a/src/TolerantParserHelpers.php +++ b/src/TolerantParserHelpers.php @@ -7,27 +7,28 @@ class TolerantParserHelpers { public static function isConstantFetch(Tolerant\Node $node) : bool { + $parent = $node->parent; return ( $node instanceof Tolerant\Node\QualifiedName && ( // $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || - $node->parent instanceof Tolerant\Node\Expression || - $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList || - $node->parent instanceof Tolerant\Node\ArrayElement || - ($node->parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || - $node->parent instanceof Tolerant\Node\StatementNode || - $node->parent instanceof Tolerant\Node\CaseStatementNode + $parent instanceof Tolerant\Node\Expression || + $parent instanceof Tolerant\Node\DelimitedList\ExpressionList || + $parent instanceof Tolerant\Node\ArrayElement || + ($parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || + $parent instanceof Tolerant\Node\StatementNode || + $parent instanceof Tolerant\Node\CaseStatementNode ) && !( - $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || - $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || + $parent instanceof Tolerant\Node\Expression\MemberAccessExpression || + $parent instanceof Tolerant\Node\Expression\CallExpression || + $parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || + $parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + self::isFunctionLike($parent) || ( - $node->parent instanceof Tolerant\Node\Expression\BinaryExpression && - $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword + $parent instanceof Tolerant\Node\Expression\BinaryExpression && + $parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword ) )); } diff --git a/validation/frameworks/broken/returnType.php b/validation/frameworks/broken/returnType.php new file mode 100644 index 00000000..5aad9403 --- /dev/null +++ b/validation/frameworks/broken/returnType.php @@ -0,0 +1,13 @@ + Date: Thu, 20 Apr 2017 01:33:45 -0700 Subject: [PATCH 067/149] fix trait use and scoped call expressions --- src/TolerantDefinitionResolver.php | 9 ++++++++- validation/frameworks/broken/scopedPropertyAccess4.php | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 validation/frameworks/broken/scopedPropertyAccess4.php diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index f9fc3414..6f1e1cae 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -294,6 +294,10 @@ public function resolveReferenceNodeToFqn($node) { private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { $parent = $node->parent; + + if ($parent instanceof Tolerant\Node\TraitSelectOrAliasClause) { + return null; + } // Add use clause references if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause || $useClause instanceof Tolerant\Node\NamespaceUseClause @@ -327,7 +331,7 @@ private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node // For extends, implements, type hints and classes of classes of static calls use the name directly $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); - + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; } @@ -433,6 +437,9 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex $className = $scoped->scopeResolutionQualifier->getResolvedName(); } if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { + if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { + return null; + } $memberName = $scoped->memberName->getName(); if (empty($memberName)) { return null; diff --git a/validation/frameworks/broken/scopedPropertyAccess4.php b/validation/frameworks/broken/scopedPropertyAccess4.php new file mode 100644 index 00000000..c3d76335 --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess4.php @@ -0,0 +1,3 @@ + Date: Tue, 25 Apr 2017 17:09:52 -0700 Subject: [PATCH 068/149] first pass at completion provider (work in progress) --- src/CompletionProvider.php | 347 ++++++++++++++++------------- src/PhpDocument.php | 2 +- src/TolerantDefinitionResolver.php | 5 + 3 files changed, 195 insertions(+), 159 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 5ce8bec8..58531e28 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -13,6 +13,7 @@ CompletionItem, CompletionItemKind }; +use Microsoft\PhpParser as Tolerant; class CompletionProvider { @@ -123,44 +124,71 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi { // This can be made much more performant if the tree follows specific invariants. $node = $doc->getNodeAtPosition($pos); + - if ($node instanceof Node\Expr\Error) { - $node = $node->getAttribute('parentNode'); + if($node !== null && ($offset = $pos->toOffset($node->getFileContents())) > $node->getEndPosition() && + $node->parent->getLastChild() instanceof Tolerant\MissingToken) { + $node = $node->parent; } $list = new CompletionList; $list->isIncomplete = true; - // A non-free node means we do NOT suggest global symbols - if ( - $node instanceof Node\Expr\MethodCall - || $node instanceof Node\Expr\PropertyFetch - || $node instanceof Node\Expr\StaticCall - || $node instanceof Node\Expr\StaticPropertyFetch - || $node instanceof Node\Expr\ClassConstFetch + if ($node instanceof Tolerant\Node\Expression\Variable && + $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression && + $node->name instanceof Tolerant\MissingToken ) { - // If the name is an Error node, just filter by the class - if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { - // For instances, resolve the variable type - $prefixes = FqnUtilities::getFqnsFromType( - $this->definitionResolver->resolveExpressionNodeToType($node->var) + $node = $node->parent; + } + + if ($node === null || $node instanceof Tolerant\Node\Statement\InlineHtml || $pos == new Position(0, 0)) { + $item = new CompletionItem('textEdit = new TextEdit( + new Range($pos, $pos), + stripStringOverlap($doc->getRange(new Range(new Position(0, 0), $pos)), 'items[] = $item; + } + // VARIABLES + elseif ( + $node instanceof Tolerant\Node\Expression\Variable && + !( + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && + $node->parent->memberName === $node) + ) { + // Find variables, parameters and use statements in the scope + // If there was only a $ typed, $node will be instanceof Node\Error + $namePrefix = $node->getName() ?? ''; + foreach ($this->suggestVariablesAtNode($node, $namePrefix) as $var) { + $item = new CompletionItem; + $item->kind = CompletionItemKind::VARIABLE; + $item->label = '$' . $var->getName(); + $item->documentation = $this->definitionResolver->getDocumentationFromNode($var); + $item->detail = (string)$this->definitionResolver->getTypeFromNode($var); + $item->textEdit = new TextEdit( + new Range($pos, $pos), + stripStringOverlap($doc->getRange(new Range(new Position(0, 0), $pos)), $item->label) ); - } else { - // Static member reference - $prefixes = [$node->class instanceof Node\Name ? (string)$node->class : '']; + $list->items[] = $item; } + } + + // MEMBER ACCESS EXPRESSIONS + // $a->c# + // $a-># + elseif ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { + $prefixes = FqnUtilities::getFqnsFromType( + $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) + ); $prefixes = $this->expandParentFqns($prefixes); - // If we are just filtering by the class, add the appropiate operator to the prefix - // to filter the type of symbol + foreach ($prefixes as &$prefix) { - if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { - $prefix .= '->'; - } else if ($node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\ClassConstFetch) { - $prefix .= '::'; - } else if ($node instanceof Node\Expr\StaticPropertyFetch) { - $prefix .= '::$'; + $prefix .= '->'; + if ($node->memberName !== null && $node->memberName instanceof Tolerant\Token) { + $prefix .= $node->memberName->getText($node->getFileContents()); } } + unset($prefix); foreach ($this->index->getDefinitions() as $fqn => $def) { @@ -170,125 +198,126 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } - } else if ( - // A ConstFetch means any static reference, like a class, interface, etc. or keyword - ($node instanceof Node\Name && $node->getAttribute('parentNode') instanceof Node\Expr\ConstFetch) - || $node instanceof Node\Expr\New_ + } + + // SCOPED PROPERTY ACCESS EXPRESSIONS + // A\B\C::$a# + // A\B\C::# + // A\B\C::$# + // A\B\C::foo# + // TODO: $a::# + elseif ( + ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ) { - $prefix = ''; - $prefixLen = 0; - if ($node instanceof Node\Name) { - $isFullyQualified = $node->isFullyQualified(); - $prefix = (string)$node; - $prefixLen = strlen($prefix); - $namespacedPrefix = (string)$node->getAttribute('namespacedName'); - $namespacedPrefixLen = strlen($prefix); + $prefixes = FqnUtilities::getFqnsFromType( + $classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier) + ); + + $prefixes = $this->expandParentFqns($prefixes); + + foreach ($prefixes as &$prefix) { + $prefix .= '::'; } - // Find closest namespace - $namespace = getClosestNode($node, Node\Stmt\Namespace_::class); - /** Map from alias to Definition */ - $aliasedDefs = []; - if ($namespace) { - foreach ($namespace->stmts as $stmt) { - if ($stmt instanceof Node\Stmt\Use_ || $stmt instanceof Node\Stmt\GroupUse) { - foreach ($stmt->uses as $use) { - // Get the definition for the used namespace, class-like, function or constant - // And save it under the alias - $fqn = (string)Node\Name::concat($stmt->prefix ?? null, $use->name); - if ($def = $this->index->getDefinition($fqn)) { - $aliasedDefs[$use->alias] = $def; - } + + unset($prefix); + + $memberName = $scoped->memberName->getText($scoped->getFileContents()); + + foreach ($this->index->getDefinitions() as $fqn => $def) { + foreach ($prefixes as $prefix) { + if (substr(strtolower($fqn), 0, strlen($prefix)) === strtolower($prefix) && !$def->isGlobal) { + if (empty($memberName) || strpos(substr(strtolower($fqn), 0), strtolower($memberName)) !== false) { + $list->items[] = CompletionItem::fromDefinition($def); } - } else { - // Use statements are always the first statements in a namespace - break; } } } - // If there is a prefix that does not start with a slash, suggest `use`d symbols - if ($prefix && !$isFullyQualified) { - // Suggest symbols that have been `use`d - // Search the aliases for the typed-in name - foreach ($aliasedDefs as $alias => $def) { - if (substr($alias, 0, $prefixLen) === $prefix) { - $list->items[] = CompletionItem::fromDefinition($def); - } - } + } elseif (TolerantParserHelpers::isConstantFetch($node) || + ($creation = $node->parent) instanceof Tolerant\Node\Expression\ObjectCreationExpression || + (($creation = $node) instanceof Tolerant\Node\Expression\ObjectCreationExpression)) { + + $class = isset($creation) ? $creation->classTypeDesignator : $node; + + $prefix = $class instanceof Tolerant\Node\QualifiedName + ? (string)Tolerant\ResolvedName::buildName($class->nameParts, $class->getFileContents()) + : $class->getText($node->getFileContents()); + + $namespaceDefinition = $node->getNamespaceDefinition(); + + list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); + foreach ($namespaceImportTable as $alias=>$name) { + $namespaceImportTable[$alias] = (string)$name; } - // Additionally, suggest global symbols that either - // - start with the current namespace + prefix, if the Name node is not fully qualified - // - start with just the prefix, if the Name node is fully qualified + foreach ($this->index->getDefinitions() as $fqn => $def) { if ( - $def->isGlobal // exclude methods, properties etc. - && ( - !$prefix - || ( - ((!$namespace || $isFullyQualified) && substr($fqn, 0, $prefixLen) === $prefix) - || ( - $namespace - && !$isFullyQualified - && substr($fqn, 0, $namespacedPrefixLen) === $namespacedPrefix - ) - ) - ) - // Only suggest classes for `new` - && (!($node instanceof Node\Expr\New_) || $def->canBeInstantiated) + ($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && (empty($prefix) || strpos($fqn, $prefix) !== false) + ) { - $item = CompletionItem::fromDefinition($def); - // Find the shortest name to reference the symbol - if ($namespace && ($alias = array_search($def, $aliasedDefs, true)) !== false) { - // $alias is the name under which this definition is aliased in the current namespace - $item->insertText = $alias; - } else if ($namespace && !($prefix && $isFullyQualified)) { - // Insert the global FQN with trailing backslash - $item->insertText = '\\' . $fqn; - } else { - // Insert the FQN without trailing backlash - $item->insertText = $fqn; + if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { + $namespacePrefix = (string)Tolerant\ResolvedName::buildName($namespaceDefinition->name->nameParts, $node->getFileContents()); + + $isAliased = false; + + $isNotFullyQualified = !($class instanceof Tolerant\Node\QualifiedName) || !$class->isFullyQualifiedName(); + if ($isNotFullyQualified) { + foreach ($namespaceImportTable as $alias => $name) { + if (strpos($fqn, $name) === 0) { + $fqn = $alias; + $isAliased = true; + break; + } + } + } + + + if (!$isNotFullyQualified && ((strpos($fqn, $prefix) === 0) || strpos($fqn, $namespacePrefix . "\\" . $prefix) === 0)) { + $fqn = $fqn; + } + elseif (!$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { + if (empty($prefix)) { + $fqn = '\\' . $fqn; + } elseif (strpos($fqn, $namespacePrefix . "\\" . $prefix) === 0) { + $fqn = substr($fqn, strlen($namespacePrefix) + 1); + } else { + continue; + } + } elseif (!$isAliased) { + continue; + } + } elseif (strpos($fqn, $prefix) === 0 && $class->isFullyQualifiedName()) { + $fqn = '\\' . $fqn; } + + $item = CompletionItem::fromDefinition($def); + + $item->insertText = $fqn; $list->items[] = $item; } } - // Suggest keywords - if ($node instanceof Node\Name && $node->getAttribute('parentNode') instanceof Node\Expr\ConstFetch) { + + if (!isset($creation)) { foreach (self::KEYWORDS as $keyword) { - if (substr($keyword, 0, $prefixLen) === $prefix) { + if (strpos($keyword, $prefix) === 0) { $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); $item->insertText = $keyword . ' '; $list->items[] = $item; } } } - } else if ( - $node instanceof Node\Expr\Variable - || ($node && $node->getAttribute('parentNode') instanceof Node\Expr\Variable) - ) { - // Find variables, parameters and use statements in the scope - // If there was only a $ typed, $node will be instanceof Node\Error - $namePrefix = $node instanceof Node\Expr\Variable && is_string($node->name) ? $node->name : ''; - foreach ($this->suggestVariablesAtNode($node, $namePrefix) as $var) { - $item = new CompletionItem; - $item->kind = CompletionItemKind::VARIABLE; - $item->label = '$' . ($var instanceof Node\Expr\ClosureUse ? $var->var : $var->name); - $item->documentation = $this->definitionResolver->getDocumentationFromNode($var); - $item->detail = (string)$this->definitionResolver->getTypeFromNode($var); - $item->textEdit = new TextEdit( - new Range($pos, $pos), - stripStringOverlap($doc->getRange(new Range(new Position(0, 0), $pos)), $item->label) - ); - $list->items[] = $item; + } elseif (TolerantParserHelpers::isConstantFetch($node)) { + $prefix = (string) ($node->getResolvedName() ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); + foreach (self::KEYWORDS as $keyword) { + if (strpos($keyword, $prefix) === 0) { + $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); + $item->insertText = $keyword . ' '; + $list->items[] = $item; + } } - } else if ($node instanceof Node\Stmt\InlineHTML || $pos == new Position(0, 0)) { - $item = new CompletionItem('textEdit = new TextEdit( - new Range($pos, $pos), - stripStringOverlap($doc->getRange(new Range(new Position(0, 0), $pos)), 'items[] = $item; } - return $list; + return $list; } /** @@ -303,7 +332,7 @@ private function expandParentFqns(array $fqns): array foreach ($fqns as $fqn) { $def = $this->index->getDefinition($fqn); if ($def) { - foreach ($this->expandParentFqns($def->extends) as $parent) { + foreach ($this->expandParentFqns($def->extends ?? []) as $parent) { $expanded[] = $parent; } } @@ -320,7 +349,7 @@ private function expandParentFqns(array $fqns): array * @param string $namePrefix Prefix to filter * @return array */ - private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): array + private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix = ''): array { $vars = []; @@ -336,30 +365,33 @@ private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): ar // Walk the AST upwards until a scope boundary is met $level = $node; - while ($level && !($level instanceof Node\FunctionLike)) { + while ($level && !TolerantParserHelpers::isFunctionLike($level)) { // Walk siblings before the node $sibling = $level; - while ($sibling = $sibling->getAttribute('previousSibling')) { + while ($sibling = $sibling->getPreviousSibling()) { // Collect all variables inside the sibling node foreach ($this->findVariableDefinitionsInNode($sibling, $namePrefix) as $var) { - $vars[$var->name] = $var; + $vars[$var->getName()] = $var; } } - $level = $level->getAttribute('parentNode'); + $level = $level->parent; } // If the traversal ended because a function was met, // also add its parameters and closure uses to the result list - if ($level instanceof Node\FunctionLike) { - foreach ($level->params as $param) { - if (!isset($vars[$param->name]) && substr($param->name, 0, strlen($namePrefix)) === $namePrefix) { - $vars[$param->name] = $param; + if ($level && TolerantParserHelpers::isFunctionLike($level) && $level->parameters !== null) { + foreach ($level->parameters->getValues() as $param) { + $paramName = $param->getName(); + if (empty($namePrefix) || strpos($paramName, $namePrefix) !== false) { + $vars[$paramName] = $param; } } - if ($level instanceof Node\Expr\Closure) { - foreach ($level->uses as $use) { - if (!isset($vars[$use->var]) && substr($use->var, 0, strlen($namePrefix)) === $namePrefix) { - $vars[$use->var] = $use; + + if ($level instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && $level->anonymousFunctionUseClause !== null) { + foreach ($level->anonymousFunctionUseClause->useVariableNameList->getValues() as $use) { + $useName = $use->getName(); + if (empty($namePrefix) || strpos($useName, $namePrefix) !== false) { + $vars[$useName] = $use; } } } @@ -375,36 +407,35 @@ private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): ar * @param string $namePrefix Prefix to filter * @return Node\Expr\Variable[] */ - private function findVariableDefinitionsInNode(Node $node, string $namePrefix = ''): array + private function findVariableDefinitionsInNode(Tolerant\Node $node, string $namePrefix = ''): array { $vars = []; // If the child node is a variable assignment, save it - $parent = $node->getAttribute('parentNode'); - if ( - $node instanceof Node\Expr\Variable - && ($parent instanceof Node\Expr\Assign || $parent instanceof Node\Expr\AssignOp) - && is_string($node->name) // Variable variables are of no use - && substr($node->name, 0, strlen($namePrefix)) === $namePrefix - ) { - $vars[] = $node; - } - // Iterate over subnodes - foreach ($node->getSubNodeNames() as $attr) { - if (!isset($node->$attr)) { - continue; - } - $children = is_array($node->$attr) ? $node->$attr : [$node->$attr]; - foreach ($children as $child) { - // Dont try to traverse scalars - // Dont traverse functions, the contained variables are in a different scope - if (!($child instanceof Node) || $child instanceof Node\FunctionLike) { - continue; - } - foreach ($this->findVariableDefinitionsInNode($child, $namePrefix) as $var) { - $vars[] = $var; + + $isAssignmentToVariable = function ($node) use ($namePrefix) { + return $node instanceof Tolerant\Node\Expression\AssignmentExpression + && $node->leftOperand instanceof Tolerant\Node\Expression\Variable + && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); + }; + $isNotFunctionLike = function($node) { + return !( + TolerantParserHelpers::isFunctionLike($node) || + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration + ); + }; + + if ($isAssignmentToVariable($node)) { + $vars[] = $node->leftOperand; + } else { + foreach ($node->getDescendantNodes($isNotFunctionLike) as $descendantNode) { + if ($isAssignmentToVariable($descendantNode)) { + $vars[] = $descendantNode->leftOperand; } } } + return $vars; } } diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 4ccedf3b..399d2b55 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -240,7 +240,7 @@ public function getStmts() * Returns the node at a specified position * * @param Position $position - * @return Node|null + * @return Tolerant\Node|null */ public function getNodeAtPosition(Position $position) { diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 6f1e1cae..0459a431 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -520,6 +520,7 @@ public function resolveVariableToNode($var) $n = $n->expression; } if ( + // TODO - clean this up ($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) && $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name ) { @@ -865,6 +866,10 @@ public function resolveExpressionNodeToType($expr): Type return new Types\Mixed; } + if ($expr instanceof Tolerant\Node\QualifiedName) { + return $this->resolveClassNameToType($expr); + } + return new Types\Mixed; } From 3e22956be9edf90e1990b8af89df4da3ca421cf7 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 26 Apr 2017 11:26:00 -0700 Subject: [PATCH 069/149] Fix tolerant-php-parser branch ref --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4856aa53..f03a557f 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "dev-lang-server" + "Microsoft/tolerant-php-parser": "lang-server" }, "minimum-stability": "dev", "repositories": [ From 7940ea48899c80d832400b3db208fac911fe2cc6 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 26 Apr 2017 11:31:58 -0700 Subject: [PATCH 070/149] Revert "Fix tolerant-php-parser branch ref" (I blame @mousetraps) This reverts commit 3e22956be9edf90e1990b8af89df4da3ca421cf7. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f03a557f..4856aa53 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "lang-server" + "Microsoft/tolerant-php-parser": "dev-lang-server" }, "minimum-stability": "dev", "repositories": [ From 8af671e917cbee8c6c400b60fdeace5af7d5202c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 11:49:39 -0700 Subject: [PATCH 071/149] Add validation test submodules --- .gitmodules | 15 +++++++++++++++ phpunit.xml.dist | 3 +++ validation/frameworks/cakephp | 1 + validation/frameworks/codeigniter | 1 + validation/frameworks/math-php | 1 + validation/frameworks/phpunit | 1 + validation/frameworks/symfony | 1 + 7 files changed, 23 insertions(+) create mode 160000 validation/frameworks/cakephp create mode 160000 validation/frameworks/codeigniter create mode 160000 validation/frameworks/math-php create mode 160000 validation/frameworks/phpunit create mode 160000 validation/frameworks/symfony diff --git a/.gitmodules b/.gitmodules index 81bcac19..06d05cb1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,18 @@ [submodule "validation/frameworks/tolerant-php-parser"] path = validation/frameworks/tolerant-php-parser url = https://github.com/microsoft/tolerant-php-parser +[submodule "validation/frameworks/symfony"] + path = validation/frameworks/symfony + url = https://github.com/symfony/symfony +[submodule "validation/frameworks/math-php"] + path = validation/frameworks/math-php + url = https://github.com/markrogoyski/math-php +[submodule "validation/frameworks/codeigniter"] + path = validation/frameworks/codeigniter + url = https://github.com/bcit-ci/codeigniter +[submodule "validation/frameworks/cakephp"] + path = validation/frameworks/cakephp + url = https://github.com/cakephp/cakephp +[submodule "validation/frameworks/phpunit"] + path = validation/frameworks/phpunit + url = https://github.com/sebastianbergmann/phpunit diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4e3f6be1..759cd2f5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,4 +11,7 @@ ./src + + + diff --git a/validation/frameworks/cakephp b/validation/frameworks/cakephp new file mode 160000 index 00000000..0450ecc0 --- /dev/null +++ b/validation/frameworks/cakephp @@ -0,0 +1 @@ +Subproject commit 0450ecc030ae37ca0a3f8c0e4e56ce9ceec8402d diff --git a/validation/frameworks/codeigniter b/validation/frameworks/codeigniter new file mode 160000 index 00000000..c06bc67d --- /dev/null +++ b/validation/frameworks/codeigniter @@ -0,0 +1 @@ +Subproject commit c06bc67d6c4059b3d1050221d5b1624ac4e2f1f8 diff --git a/validation/frameworks/math-php b/validation/frameworks/math-php new file mode 160000 index 00000000..601baa62 --- /dev/null +++ b/validation/frameworks/math-php @@ -0,0 +1 @@ +Subproject commit 601baa6267cc4a357c8032d9407a0206975aa26e diff --git a/validation/frameworks/phpunit b/validation/frameworks/phpunit new file mode 160000 index 00000000..bb74d4ea --- /dev/null +++ b/validation/frameworks/phpunit @@ -0,0 +1 @@ +Subproject commit bb74d4eac541cf63f3454ca5fa31c4a20391032b diff --git a/validation/frameworks/symfony b/validation/frameworks/symfony new file mode 160000 index 00000000..9d9f628d --- /dev/null +++ b/validation/frameworks/symfony @@ -0,0 +1 @@ +Subproject commit 9d9f628d926aaf34e020ddccb4454ff7c4ce5ceb From f201ecd177318cd5e54ab74ad7f005ffcf3bfef1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 16:50:42 -0700 Subject: [PATCH 072/149] Rewrite ValidationTest --- tests/Validation/ValidationTest.php | 256 +++++++++++++--------------- 1 file changed, 120 insertions(+), 136 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 3375f6cb..10ab1207 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -5,10 +5,12 @@ namespace LanguageServer\Tests; use Exception; +use LanguageServer\Definition; use LanguageServer\Index\Index; use LanguageServer\ParserKind; use LanguageServer\ParserResourceFactory; use LanguageServer\PhpDocument; +use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlockFactory; use PHPUnit\Framework\TestCase; use LanguageServer\ClientHandler; @@ -22,7 +24,6 @@ class ValidationTest extends TestCase { public function frameworkErrorProvider() { - $totalSize = 0; $frameworks = glob(__DIR__ . "/../../validation/frameworks/*", GLOB_ONLYDIR); $testProviderArray = array(); @@ -31,12 +32,11 @@ public function frameworkErrorProvider() { if ($frameworkName !== "broken") { // continue; } + $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos(\strrev((string)$file), \strrev(".php")) === 0 -// && strpos((string)$file, "ContainerFactory.php")!== false - ) { + if (strpos(\strrev((string)$file), \strrev(".php")) === 0) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } @@ -52,10 +52,12 @@ public function frameworkErrorProvider() { /** * @group validation * @dataProvider frameworkErrorProvider + * @param $testCaseFile + * @param $frameworkName */ - public function testFramworkErrors($testCaseFile, $frameworkName) { + public function testFrameworkErrors($testCaseFile, $frameworkName) { $fileContents = file_get_contents($testCaseFile); - + $parser = ParserResourceFactory::getParser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; @@ -82,160 +84,142 @@ public function testFramworkErrors($testCaseFile, $frameworkName) { if (file_exists($outFile)) { unlink($outFile); } - // echo json_encode($parser->getErrors($sourceFile)); - } - - private $index = []; - - private function getIndex($kind, $frameworkName) { - if (!isset($this->index[$kind][$frameworkName])) { - $this->index[$kind][$frameworkName] = new Index(); - } - return $this->index[$kind][$frameworkName]; } /** * @group validation * @dataProvider frameworkErrorProvider + * @param $testCaseFile + * @param $frameworkName */ public function testDefinitionErrors($testCaseFile, $frameworkName) { + echo PHP_EOL . realpath($testCaseFile) . PHP_EOL; + $fileContents = file_get_contents($testCaseFile); - echo "$testCaseFile\n"; - - $parserKinds = [ParserKind::DIAGNOSTIC_PHP_PARSER, ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER]; - $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; - - $maxRecursion = []; - - $definitions = null; - $instantiated = null; - $types = null; - $symbolInfo = null; - $extend = null; - $isGlobal = null; - $documentation = null; - $isStatic = null; - - foreach ($parserKinds as $kind) { - echo ("=====================================\n"); - global $parserKind; - $parserKind = $kind; - - $index = $this->getIndex($kind, $frameworkName); - $docBlockFactory = DocBlockFactory::createInstance(); - - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - $parser = ParserResourceFactory::getParser(); - - try { - $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (Exception $e) { - if ($kind === $parserKinds[0]) { - $this->markTestIncomplete("baseline parser failed: " . $e->getTraceAsString()); - } - throw $e; + [$expectedDefinitions, $expectedReferences] = $this->getExpectedDefinitionsAndReferences($testCaseFile, $frameworkName, $fileContents); + [$actualDefinitions, $actualReferences] = $this->getActualDefinitionsAndReferences($testCaseFile, $fileContents); - } + $this->filterSkippedReferences($expectedReferences); + $this->filterSkippedReferences($actualReferences); - if ($document->getStmts() === null) { - $this->markTestSkipped("null AST"); + $expectedValues = $this->getValuesFromDefinitionsAndReferences($expectedDefinitions, $expectedReferences); + $actualValues = $this->getValuesFromDefinitionsAndReferences($actualDefinitions, $actualReferences); + + foreach ($expectedValues as $name => $expectedValue) { + $actualValue = $actualValues[$name]; + + if ($name === 'references') { + try { + $this->assertArraySubset($expectedValue, $actualValue, false, 'references don\'t match.'); + } catch (\Throwable $e) { + $this->assertEquals($expectedValue, $actualValue, 'references don\'t match.'); + } + continue; } - $fqns = []; - $currentTypes = []; - $canBeInstantiated = []; - $symbols = []; - $extends = []; - $global = []; - $docs = []; - $static = []; - foreach ($document->getDefinitions() as $defn) { - $fqns[] = $defn->fqn; + $this->assertEquals($expectedValue, $actualValue, "$name did not match."); + } + } - $currentTypes[$defn->fqn] = $defn->type; + /** + * @param $filename + * @param $fileContents + * @return array + */ + private function getExpectedDefinitionsAndReferences($filename, $frameworkName, $fileContents) { +// $outputFile = $filename . '.expected'; +// if (file_exists($outputFile)) { +// return json_decode(file_get_contents($outputFile)); +// } - $canBeInstantiated[$defn->fqn] = $defn->canBeInstantiated; + global $parserKind; + $parserKind = ParserKind::PHP_PARSER; - $defn->symbolInformation->location = null; - $symbols[$defn->fqn] = $defn->symbolInformation; + $index = new Index(); + $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - $extends[$defn->fqn] = $defn->extends ?? []; - $global[$defn->fqn] = $defn->isGlobal; - $docs[$defn->fqn] = $defn->documentation; - $static[$defn->fqn] = $defn->isStatic; - } - if ($definitions !== null) { - - $this->assertEquals($definitions, $fqns, 'defn->fqn does not match'); - $this->assertEquals($types, $currentTypes, "defn->type does not match"); - $this->assertEquals($instantiated, $canBeInstantiated, "defn->canBeInstantiated does not match"); - $this->assertEquals($extend, $extends, 'defn->extends does not match'); - $this->assertEquals($isGlobal, $global, 'defn->isGlobal does not match'); - $this->assertEquals($documentation, $docs, 'defn->documentation does not match'); - $this->assertEquals($isStatic, $static, 'defn->isStatic does not match'); - - $this->assertEquals($symbolInfo, $symbols, "defn->symbolInformation does not match"); - - - $skipped = []; - $skipped = [ - 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', - '__', // magic constants are treated as normal constants - 'Exception', // catch exception types missing from old definition resolver - 'Trait', // use Trait references are missing from old definition resolve - '->tableAlias', '->realField', '->field', '->first_name', '->last_name', '->quoteMatch', '->idCol', '->timeCol', '->dataCol', - 'pathToUri', 'uriToPath' // group function use declarations are broken in old definition resolver - ]; - foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { - foreach ($skipped as $s) { - if (strpos($key, $s) !== false) { - unset($this->getIndex($parserKinds[0], $frameworkName)->references[$key]); - } - } - } - foreach ($this->getIndex($parserKinds[1], $frameworkName)->references as $key=>$value) { - foreach ($skipped as $s) { - if (strpos($key, $s) !== false) { - unset($this->getIndex($parserKinds[1], $frameworkName)->references[$key]); - } - } - } + try { + $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Throwable $e) { + $this->markTestSkipped('Baseline parser failed: '. $e->getTraceAsString()); + } -// unset($this->getIndex($parserKinds[1])->references['__LINE__']); -// unset($this->getIndex($parserKinds[1])->references['__FILE__']); -// unset($this->getIndex($parserKinds[1])->references['Exception']); -// unset($this->getIndex($parserKinds[1])->references['__METHOD__']); -// unset($this->getIndex($parserKinds[1])->references['__FUNCTION__']); -// unset($this->getIndex($parserKinds[1])->references['Requests_Exception']); + if ($document->getStmts() === null) { + $this->markTestSkipped('Baseline parser failed: null AST'); + } - try { + $defsAndRefs = [$document->getDefinitions(), $index->references]; +// if ($frameworkName === 'broken') { +// file_put_contents($outputFile, json_encode($defsAndRefs, JSON_PRETTY_PRINT)); +// } +// } -// $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, -// "references do not match"); + return $defsAndRefs; + } - $this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); -// var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references)); - } - catch (\Throwable $e) { - $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, - "references do not match"); - } - finally { - unset($this->index[$parserKinds[0]][$frameworkName]); - unset($this->index[$parserKinds[1]][$frameworkName]); + private function getActualDefinitionsAndReferences($filename, $fileContents) { + global $parserKind; + $parserKind = ParserKind::TOLERANT_PHP_PARSER; + + $index = new Index(); + $parser = ParserResourceFactory::getParser(); + $docBlockFactory = DocBlockFactory::createInstance(); + $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + + $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + + return [$document->getDefinitions(), $index->references]; + } + + /** + * @param $expectedDefinitions + * @param $expectedReferences + * @return array|\array[] + * @internal param $propertyNames + */ + private function getValuesFromDefinitionsAndReferences($expectedDefinitions, $expectedReferences): array + { + // TODO - use reflection to read these properties + $propertyNames = ['extends', 'isGlobal', 'isStatic', 'canBeInstantiated', 'symbolInformation', 'type', 'documentation']; + + $expectedValues = []; + foreach ($expectedDefinitions as $expectedDefinition) { + $fqn = $expectedDefinition->fqn; + $expectedValues['$def->fqn'][] = $fqn; + + foreach ($propertyNames as $propertyName) { + if ($propertyName === 'symbolInformation') { + unset($expectedDefinition->$propertyName->location->range); + } elseif ($propertyName === 'extends') { + $expectedDefinition->$propertyName = $expectedDefinition->$propertyName ?? []; } + $expectedValues['$def->' . $propertyName][$fqn] = $expectedDefinition->$propertyName; } + } - $definitions = $fqns; - $types = $currentTypes; - $instantiated = $canBeInstantiated; - $symbolInfo = $symbols; - $extend = $extends; - $isGlobal = $global; - $documentation = $docs; - $isStatic = $static; + $expectedValues['references'] = $expectedReferences; + return $expectedValues; + } -// $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; + private function filterSkippedReferences(&$references) + { + $skipped = [ + 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', + '__', // magic constants are treated as normal constants + 'Exception', 'Error', // catch exception types missing from old definition resolver + 'Trait', // use Trait references are missing from old definition resolve + '->tableAlias', '->realField', '->field', '->first_name', '->last_name', '->quoteMatch', '->idCol', '->timeCol', '->dataCol', + 'pathToUri', 'uriToPath' // group function use declarations are broken in old definition resolver + ]; + + foreach ($references as $key=>$value) { + foreach ($skipped as $s) { + if (strpos($key, $s) !== false) { + unset($references[$key]); + } + } } } } \ No newline at end of file From 4d476714ffd7e081a1fa1c595a2649362e69ba74 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 16:52:30 -0700 Subject: [PATCH 073/149] Fix ValidationTest to read serialized results --- tests/Validation/ValidationTest.php | 146 +++++++++++----------------- 1 file changed, 57 insertions(+), 89 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 10ab1207..85cf54ba 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -30,7 +30,7 @@ public function frameworkErrorProvider() { foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); if ($frameworkName !== "broken") { -// continue; + continue; } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); @@ -49,43 +49,6 @@ public function frameworkErrorProvider() { return $testProviderArray; } - /** - * @group validation - * @dataProvider frameworkErrorProvider - * @param $testCaseFile - * @param $frameworkName - */ - public function testFrameworkErrors($testCaseFile, $frameworkName) { - $fileContents = file_get_contents($testCaseFile); - - $parser = ParserResourceFactory::getParser(); - $docBlockFactory = DocBlockFactory::createInstance(); - $index = new Index; - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - - $directory = __DIR__ . "/output/$frameworkName/"; - $outFile = $directory . basename($testCaseFile); - - try { - $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (\Exception $e) { - if (!file_exists($dir = __DIR__ . "/output")) { - mkdir($dir); - } - if (!file_exists($directory)) { - mkdir($directory); - } - file_put_contents($outFile, $fileContents); - $this->fail((string)$e); - } - - $this->assertNotNull($document->getStmts()); - - if (file_exists($outFile)) { - unlink($outFile); - } - } - /** * @group validation * @dataProvider frameworkErrorProvider @@ -93,48 +56,36 @@ public function testFrameworkErrors($testCaseFile, $frameworkName) { * @param $frameworkName */ public function testDefinitionErrors($testCaseFile, $frameworkName) { - echo PHP_EOL . realpath($testCaseFile) . PHP_EOL; + echo "Test file: " . realpath($testCaseFile) . PHP_EOL; $fileContents = file_get_contents($testCaseFile); - [$expectedDefinitions, $expectedReferences] = $this->getExpectedDefinitionsAndReferences($testCaseFile, $frameworkName, $fileContents); - [$actualDefinitions, $actualReferences] = $this->getActualDefinitionsAndReferences($testCaseFile, $fileContents); - - $this->filterSkippedReferences($expectedReferences); - $this->filterSkippedReferences($actualReferences); - - $expectedValues = $this->getValuesFromDefinitionsAndReferences($expectedDefinitions, $expectedReferences); - $actualValues = $this->getValuesFromDefinitionsAndReferences($actualDefinitions, $actualReferences); + $expectedValues = $this->getExpectedTestValues($testCaseFile, $frameworkName, $fileContents); + $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); - foreach ($expectedValues as $name => $expectedValue) { - $actualValue = $actualValues[$name]; + $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); - if ($name === 'references') { - try { - $this->assertArraySubset($expectedValue, $actualValue, false, 'references don\'t match.'); - } catch (\Throwable $e) { - $this->assertEquals($expectedValue, $actualValue, 'references don\'t match.'); - } - continue; - } - - $this->assertEquals($expectedValue, $actualValue, "$name did not match."); + try { + $this->assertArraySubset((array)$expectedValues['references'], (array)$actualValues['references'], false, 'references don\'t match.'); + } catch (\Throwable $e) { + $this->assertEquals((array)$expectedValues['references'], (array)$actualValues['references'], 'references don\'t match.'); } } /** * @param $filename + * @param $frameworkName * @param $fileContents - * @return array + * @return array */ - private function getExpectedDefinitionsAndReferences($filename, $frameworkName, $fileContents) { -// $outputFile = $filename . '.expected'; -// if (file_exists($outputFile)) { -// return json_decode(file_get_contents($outputFile)); -// } - + private function getExpectedTestValues($filename, $frameworkName, $fileContents) { global $parserKind; $parserKind = ParserKind::PHP_PARSER; + $outputFile = $filename . '.expected.json'; + if (file_exists($outputFile)) { + return (array)json_decode(file_get_contents($outputFile)); + } + $index = new Index(); $parser = ParserResourceFactory::getParser(); $docBlockFactory = DocBlockFactory::createInstance(); @@ -150,16 +101,23 @@ private function getExpectedDefinitionsAndReferences($filename, $frameworkName, $this->markTestSkipped('Baseline parser failed: null AST'); } - $defsAndRefs = [$document->getDefinitions(), $index->references]; -// if ($frameworkName === 'broken') { -// file_put_contents($outputFile, json_encode($defsAndRefs, JSON_PRETTY_PRINT)); -// } -// } + $expectedRefs = $index->references; + $this->filterSkippedReferences($expectedRefs); + $expectedDefs = $this->getTestValuesFromDefs($document->getDefinitions()); - return $defsAndRefs; + $refsAndDefs = array( + 'references' => json_decode(json_encode($expectedRefs)), + 'definitions' => json_decode(json_encode($expectedDefs)) + ); + + if ($frameworkName === 'broken') { + file_put_contents($outputFile, json_encode($refsAndDefs, JSON_PRETTY_PRINT)); + } + + return $refsAndDefs; } - private function getActualDefinitionsAndReferences($filename, $fileContents) { + private function getActualTestValues($filename, $fileContents): array { global $parserKind; $parserKind = ParserKind::TOLERANT_PHP_PARSER; @@ -170,40 +128,50 @@ private function getActualDefinitionsAndReferences($filename, $fileContents) { $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - return [$document->getDefinitions(), $index->references]; + $actualRefs = $index->references; + $this->filterSkippedReferences($actualRefs); + $actualDefs = $this->getTestValuesFromDefs($document->getDefinitions()); + + // TODO - probably a more PHP-typical way to do this. Need to compare the objects parsed from json files + // to the real results. json_decode returns stdClass Objects, not arrays. + return array( + 'references' => json_decode(json_encode($actualRefs)), + 'definitions' => json_decode(json_encode($actualDefs)) + ); } /** - * @param $expectedDefinitions - * @param $expectedReferences + * @param $definitions Definition[] * @return array|\array[] - * @internal param $propertyNames */ - private function getValuesFromDefinitionsAndReferences($expectedDefinitions, $expectedReferences): array + private function getTestValuesFromDefs($definitions): array { // TODO - use reflection to read these properties $propertyNames = ['extends', 'isGlobal', 'isStatic', 'canBeInstantiated', 'symbolInformation', 'type', 'documentation']; - $expectedValues = []; - foreach ($expectedDefinitions as $expectedDefinition) { - $fqn = $expectedDefinition->fqn; - $expectedValues['$def->fqn'][] = $fqn; + $defsForAssert = []; + foreach ($definitions as $definition) { + $fqn = $definition->fqn; foreach ($propertyNames as $propertyName) { if ($propertyName === 'symbolInformation') { - unset($expectedDefinition->$propertyName->location->range); + // Range is very often different - don't check it, for now + unset($definition->$propertyName->location->range); } elseif ($propertyName === 'extends') { - $expectedDefinition->$propertyName = $expectedDefinition->$propertyName ?? []; + $definition->$propertyName = $definition->$propertyName ?? []; + } elseif ($propertyName === 'type') { + // Class info is not captured by json_encode. It's important for 'type'. + $defsForAssert[$fqn][$propertyName . '__class'] = get_class($definition->$propertyName); } - $expectedValues['$def->' . $propertyName][$fqn] = $expectedDefinition->$propertyName; + + $defsForAssert[$fqn][$propertyName] = $definition->$propertyName; } } - $expectedValues['references'] = $expectedReferences; - return $expectedValues; + return $defsForAssert; } - private function filterSkippedReferences(&$references) + private function filterSkippedReferences(&$references): void { $skipped = [ 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', @@ -217,7 +185,7 @@ private function filterSkippedReferences(&$references) foreach ($references as $key=>$value) { foreach ($skipped as $s) { if (strpos($key, $s) !== false) { - unset($references[$key]); + unset($references->$key); } } } From 587822b55897502628158bb58acf711ad28ee987 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 21:14:04 -0700 Subject: [PATCH 074/149] $references are now an array, not an object - fix removing skipped refs --- tests/Validation/ValidationTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 85cf54ba..a7d98b87 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -185,7 +185,7 @@ private function filterSkippedReferences(&$references): void foreach ($references as $key=>$value) { foreach ($skipped as $s) { if (strpos($key, $s) !== false) { - unset($references->$key); + unset($references[$key]); } } } From ede5edc40de65b8059b39de05d6d8e0b36ec232d Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 21:14:48 -0700 Subject: [PATCH 075/149] Add .expected.json files and skipped.json --- tests/Validation/ValidationTest.php | 3 +- tests/Validation/skipped.json | 6 + .../frameworks/broken/ArrayNodeDefinition.php | 549 ------------------ .../WithReturnTypehints.php.expected.json | 102 ++++ ...embersShouldNotBeSymbols.php.expected.json | 22 + .../broken/arrayValueShouldBeBoolean.php | 4 + ...rrayValueShouldBeBoolean.php.expected.json | 39 ++ .../broken/caseStatement1.php.expected.json | 29 + .../broken/classDefinition1.php.expected.json | 63 ++ .../broken/classProperty1.php.expected.json | 80 +++ .../broken/constants.php.expected.json | 63 ++ .../broken/constants2.php.expected.json | 63 ++ .../broken/constants3.php.expected.json | 63 ++ .../broken/constants4.php.expected.json | 63 ++ .../broken/constants5.php.expected.json | 63 ++ ...tsInFunctionParamDefault.php.expected.json | 43 ++ ...cksOnNamespaceDefinition.php.expected.json | 22 + .../broken/exceptions1.php.expected.json | 22 + .../frameworks/broken/forLoopReference1.php | 10 +- .../forLoopReference1.php.expected.json | 60 ++ validation/frameworks/broken/functionCall.php | 53 -- .../broken/functionUse.php.expected.json | 11 + .../broken/functionUse2.php.expected.json | 11 + .../broken/ifStatement1.php.expected.json | 29 + ...cConstantsShouldBeGlobal.php.expected.json | 22 + .../broken/magicConsts.php.expected.json | 39 ++ .../broken/memberAccess1.php.expected.json | 63 ++ .../broken/memberAccess2.php.expected.json | 63 ++ .../broken/memberAccess3.php.expected.json | 78 +++ .../broken/memberAccess4.php.expected.json | 69 +++ .../broken/memberAccess5.php.expected.json | 56 ++ .../broken/memberCall1.php.expected.json | 66 +++ .../multipleNamespaces.php.expected.json | 116 ++++ .../broken/multiplePreceedingComments.php | 15 + ...ltiplePreceedingComments.php.expected.json | 39 ++ .../broken/nameToken.php.expected.json | 43 ++ .../broken/namespaces2.php.expected.json | 35 ++ .../broken/namespaces3.php.expected.json | 14 + .../broken/namespaces4.php.expected.json | 11 + .../broken/namespaces5.php.expected.json | 44 ++ .../broken/namespaces6.php.expected.json | 22 + .../broken/namespaces7.php.expected.json | 4 + .../broken/namespaces8.php.expected.json | 26 + .../broken/namespaces9.php.expected.json | 4 + .../broken/objectCreation.php.expected.json | 60 ++ .../broken/objectCreation2.php.expected.json | 80 +++ .../broken/objectCreation3.php.expected.json | 43 ++ .../broken/param1.php.expected.json | 43 ++ .../broken/parameterTypeResolution1.php | 4 +- ...parameterTypeResolution1.php.expected.json | 66 +++ .../broken/parent1.php.expected.json | 99 ++++ .../broken/parent2.php.expected.json | 102 ++++ .../broken/parent3.php.expected.json | 108 ++++ .../broken/propertyName1.php.expected.json | 39 ++ .../broken/propertyName2.php.expected.json | 39 ++ .../broken/returnType.php.expected.json | 46 ++ .../scopedPropertyAccess.php.expected.json | 63 ++ .../scopedPropertyAccess2.php.expected.json | 26 + .../scopedPropertyAccess3.php.expected.json | 46 ++ .../scopedPropertyAccess4.php.expected.json | 8 + .../scopedPropertyAccess5.php.expected.json | 52 ++ validation/frameworks/broken/self1.php | 1 + .../frameworks/broken/self1.php.expected.json | 102 ++++ .../frameworks/broken/self2.php.expected.json | 102 ++++ .../frameworks/broken/self3.php.expected.json | 108 ++++ .../frameworks/broken/self4.php.expected.json | 69 +++ .../frameworks/broken/self5.php.expected.json | 60 ++ .../broken/static1.php.expected.json | 102 ++++ .../broken/static2.php.expected.json | 102 ++++ .../broken/static3.php.expected.json | 102 ++++ .../broken/static4.php.expected.json | 65 +++ .../broken/staticInArray.php.expected.json | 4 + .../broken/stringVariable.php.expected.json | 60 ++ .../testQualifiedNameOutsideOfNamespace.php | 5 + ...edNameOutsideOfNamespace.php.expected.json | 29 + .../broken/verifyFqsenOnClassProperty.php | 9 + ...rifyFqsenOnClassProperty.php.expected.json | 63 ++ 77 files changed, 3601 insertions(+), 608 deletions(-) create mode 100644 tests/Validation/skipped.json delete mode 100644 validation/frameworks/broken/ArrayNodeDefinition.php create mode 100644 validation/frameworks/broken/WithReturnTypehints.php.expected.json create mode 100644 validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json create mode 100644 validation/frameworks/broken/arrayValueShouldBeBoolean.php create mode 100644 validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json create mode 100644 validation/frameworks/broken/caseStatement1.php.expected.json create mode 100644 validation/frameworks/broken/classDefinition1.php.expected.json create mode 100644 validation/frameworks/broken/classProperty1.php.expected.json create mode 100644 validation/frameworks/broken/constants.php.expected.json create mode 100644 validation/frameworks/broken/constants2.php.expected.json create mode 100644 validation/frameworks/broken/constants3.php.expected.json create mode 100644 validation/frameworks/broken/constants4.php.expected.json create mode 100644 validation/frameworks/broken/constants5.php.expected.json create mode 100644 validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json create mode 100644 validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json create mode 100644 validation/frameworks/broken/exceptions1.php.expected.json create mode 100644 validation/frameworks/broken/forLoopReference1.php.expected.json delete mode 100644 validation/frameworks/broken/functionCall.php create mode 100644 validation/frameworks/broken/functionUse.php.expected.json create mode 100644 validation/frameworks/broken/functionUse2.php.expected.json create mode 100644 validation/frameworks/broken/ifStatement1.php.expected.json create mode 100644 validation/frameworks/broken/magicConstantsShouldBeGlobal.php.expected.json create mode 100644 validation/frameworks/broken/magicConsts.php.expected.json create mode 100644 validation/frameworks/broken/memberAccess1.php.expected.json create mode 100644 validation/frameworks/broken/memberAccess2.php.expected.json create mode 100644 validation/frameworks/broken/memberAccess3.php.expected.json create mode 100644 validation/frameworks/broken/memberAccess4.php.expected.json create mode 100644 validation/frameworks/broken/memberAccess5.php.expected.json create mode 100644 validation/frameworks/broken/memberCall1.php.expected.json create mode 100644 validation/frameworks/broken/multipleNamespaces.php.expected.json create mode 100644 validation/frameworks/broken/multiplePreceedingComments.php create mode 100644 validation/frameworks/broken/multiplePreceedingComments.php.expected.json create mode 100644 validation/frameworks/broken/nameToken.php.expected.json create mode 100644 validation/frameworks/broken/namespaces2.php.expected.json create mode 100644 validation/frameworks/broken/namespaces3.php.expected.json create mode 100644 validation/frameworks/broken/namespaces4.php.expected.json create mode 100644 validation/frameworks/broken/namespaces5.php.expected.json create mode 100644 validation/frameworks/broken/namespaces6.php.expected.json create mode 100644 validation/frameworks/broken/namespaces7.php.expected.json create mode 100644 validation/frameworks/broken/namespaces8.php.expected.json create mode 100644 validation/frameworks/broken/namespaces9.php.expected.json create mode 100644 validation/frameworks/broken/objectCreation.php.expected.json create mode 100644 validation/frameworks/broken/objectCreation2.php.expected.json create mode 100644 validation/frameworks/broken/objectCreation3.php.expected.json create mode 100644 validation/frameworks/broken/param1.php.expected.json create mode 100644 validation/frameworks/broken/parameterTypeResolution1.php.expected.json create mode 100644 validation/frameworks/broken/parent1.php.expected.json create mode 100644 validation/frameworks/broken/parent2.php.expected.json create mode 100644 validation/frameworks/broken/parent3.php.expected.json create mode 100644 validation/frameworks/broken/propertyName1.php.expected.json create mode 100644 validation/frameworks/broken/propertyName2.php.expected.json create mode 100644 validation/frameworks/broken/returnType.php.expected.json create mode 100644 validation/frameworks/broken/scopedPropertyAccess.php.expected.json create mode 100644 validation/frameworks/broken/scopedPropertyAccess2.php.expected.json create mode 100644 validation/frameworks/broken/scopedPropertyAccess3.php.expected.json create mode 100644 validation/frameworks/broken/scopedPropertyAccess4.php.expected.json create mode 100644 validation/frameworks/broken/scopedPropertyAccess5.php.expected.json create mode 100644 validation/frameworks/broken/self1.php.expected.json create mode 100644 validation/frameworks/broken/self2.php.expected.json create mode 100644 validation/frameworks/broken/self3.php.expected.json create mode 100644 validation/frameworks/broken/self4.php.expected.json create mode 100644 validation/frameworks/broken/self5.php.expected.json create mode 100644 validation/frameworks/broken/static1.php.expected.json create mode 100644 validation/frameworks/broken/static2.php.expected.json create mode 100644 validation/frameworks/broken/static3.php.expected.json create mode 100644 validation/frameworks/broken/static4.php.expected.json create mode 100644 validation/frameworks/broken/staticInArray.php.expected.json create mode 100644 validation/frameworks/broken/stringVariable.php.expected.json create mode 100644 validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php create mode 100644 validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json create mode 100644 validation/frameworks/broken/verifyFqsenOnClassProperty.php create mode 100644 validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index a7d98b87..9f292d61 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -34,9 +34,10 @@ public function frameworkErrorProvider() { } $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); + $skipped = json_decode(file_get_contents(__DIR__ . '/skipped.json')); foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos(\strrev((string)$file), \strrev(".php")) === 0) { + if (strpos(\strrev((string)$file), \strrev(".php")) === 0 && !\in_array(basename((string)$file), $skipped)) { if ($file->getSize() < 100000) { $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; } diff --git a/tests/Validation/skipped.json b/tests/Validation/skipped.json new file mode 100644 index 00000000..901c77a7 --- /dev/null +++ b/tests/Validation/skipped.json @@ -0,0 +1,6 @@ +[ + "forLoopReference1.php", + "namespaces3.php", + "parameterTypeResolution1.php", + "parent2.php" +] \ No newline at end of file diff --git a/validation/frameworks/broken/ArrayNodeDefinition.php b/validation/frameworks/broken/ArrayNodeDefinition.php deleted file mode 100644 index 4ad218bb..00000000 --- a/validation/frameworks/broken/ArrayNodeDefinition.php +++ /dev/null @@ -1,549 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\PrototypedArrayNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; - -/** - * This class provides a fluent interface for defining an array node. - * - * @author Johannes M. Schmitt - */ -class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface -{ - protected $performDeepMerging = true; - protected $ignoreExtraKeys = false; - protected $removeExtraKeys = true; - protected $children = array(); - protected $prototype; - protected $atLeastOne = false; - protected $allowNewKeys = true; - protected $key; - protected $removeKeyItem; - protected $addDefaults = false; - protected $addDefaultChildren = false; - protected $nodeBuilder; - protected $normalizeKeys = true; - - /** - * {@inheritdoc} - */ - public function __construct($name, NodeParentInterface $parent = null) - { - parent::__construct($name, $parent); - - $this->nullEquivalent = array(); - $this->trueEquivalent = array(); - } - - /** - * Sets a custom children builder. - * - * @param NodeBuilder $builder A custom NodeBuilder - */ - public function setBuilder(NodeBuilder $builder) - { - $this->nodeBuilder = $builder; - } - - /** - * Returns a builder to add children nodes. - * - * @return NodeBuilder - */ - public function children() - { - return $this->getNodeBuilder(); - } - - /** - * Sets a prototype for child nodes. - * - * @param string $type the type of node - * - * @return NodeDefinition - */ - public function prototype($type) - { - return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); - } - - /** - * @return VariableNodeDefinition - */ - public function variablePrototype() - { - return $this->prototype('variable'); - } - - /** - * @return ScalarNodeDefinition - */ - public function scalarPrototype() - { - return $this->prototype('scalar'); - } - - /** - * @return BooleanNodeDefinition - */ - public function booleanPrototype() - { - return $this->prototype('boolean'); - } - - /** - * @return IntegerNodeDefinition - */ - public function integerPrototype() - { - return $this->prototype('integer'); - } - - /** - * @return FloatNodeDefinition - */ - public function floatPrototype() - { - return $this->prototype('float'); - } - - /** - * @return ArrayNodeDefinition - */ - public function arrayPrototype() - { - return $this->prototype('array'); - } - - /** - * @return EnumNodeDefinition - */ - public function enumPrototype() - { - return $this->prototype('enum'); - } - - /** - * Adds the default value if the node is not set in the configuration. - * - * This method is applicable to concrete nodes only (not to prototype nodes). - * If this function has been called and the node is not set during the finalization - * phase, it's default value will be derived from its children default values. - * - * @return ArrayNodeDefinition - */ - public function addDefaultsIfNotSet() - { - $this->addDefaults = true; - - return $this; - } - - /** - * Adds children with a default value when none are defined. - * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - * - * This method is applicable to prototype nodes only. - * - * @return ArrayNodeDefinition - */ - public function addDefaultChildrenIfNoneSet($children = null) - { - $this->addDefaultChildren = $children; - - return $this; - } - - /** - * Requires the node to have at least one element. - * - * This method is applicable to prototype nodes only. - * - * @return ArrayNodeDefinition - */ - public function requiresAtLeastOneElement() - { - $this->atLeastOne = true; - - return $this; - } - - /** - * Disallows adding news keys in a subsequent configuration. - * - * If used all keys have to be defined in the same configuration file. - * - * @return ArrayNodeDefinition - */ - public function disallowNewKeysInSubsequentConfigs() - { - $this->allowNewKeys = false; - - return $this; - } - - /** - * Sets a normalization rule for XML configurations. - * - * @param string $singular The key to remap - * @param string $plural The plural of the key for irregular plurals - * - * @return ArrayNodeDefinition - */ - public function fixXmlConfig($singular, $plural = null) - { - $this->normalization()->remap($singular, $plural); - - return $this; - } - - /** - * Sets the attribute which value is to be used as key. - * - * This is useful when you have an indexed array that should be an - * associative array. You can select an item from within the array - * to be the key of the particular item. For example, if "id" is the - * "key", then: - * - * array( - * array('id' => 'my_name', 'foo' => 'bar'), - * ); - * - * becomes - * - * array( - * 'my_name' => array('foo' => 'bar'), - * ); - * - * If you'd like "'id' => 'my_name'" to still be present in the resulting - * array, then you can set the second argument of this method to false. - * - * This method is applicable to prototype nodes only. - * - * @param string $name The name of the key - * @param bool $removeKeyItem Whether or not the key item should be removed - * - * @return ArrayNodeDefinition - */ - public function useAttributeAsKey($name, $removeKeyItem = true) - { - $this->key = $name; - $this->removeKeyItem = $removeKeyItem; - - return $this; - } - - /** - * Sets whether the node can be unset. - * - * @param bool $allow - * - * @return ArrayNodeDefinition - */ - public function canBeUnset($allow = true) - { - $this->merge()->allowUnset($allow); - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is disabled. If any configuration is specified then - * the node will be automatically enabled: - * - * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden - * enableableArrayNode: ~ # The config is enabled & use the default values - * enableableArrayNode: true # The config is enabled & use the default values - * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden - * enableableArrayNode: {enabled: false, ...} # The config is disabled - * enableableArrayNode: false # The config is disabled - * - * @return ArrayNodeDefinition - */ - public function canBeEnabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(array('enabled' => false)) - ->treatTrueLike(array('enabled' => true)) - ->treatNullLike(array('enabled' => true)) - ->beforeNormalization() - ->ifArray() - ->then(function ($v) { - $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; - - return $v; - }) - ->end() - ->children() - ->booleanNode('enabled') - ->defaultFalse() - ; - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is enabled. - * - * @return ArrayNodeDefinition - */ - public function canBeDisabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(array('enabled' => false)) - ->treatTrueLike(array('enabled' => true)) - ->treatNullLike(array('enabled' => true)) - ->children() - ->booleanNode('enabled') - ->defaultTrue() - ; - - return $this; - } - - /** - * Disables the deep merging of the node. - * - * @return ArrayNodeDefinition - */ - public function performNoDeepMerging() - { - $this->performDeepMerging = false; - - return $this; - } - - /** - * Allows extra config keys to be specified under an array without - * throwing an exception. - * - * Those config values are simply ignored and removed from the - * resulting array. This should be used only in special cases where - * you want to send an entire configuration array through a special - * tree that processes only part of the array. - * - * @param bool $remove Whether to remove the extra keys - * - * @return ArrayNodeDefinition - */ - public function ignoreExtraKeys($remove = true) - { - $this->ignoreExtraKeys = true; - $this->removeExtraKeys = $remove; - - return $this; - } - - /** - * Sets key normalization. - * - * @param bool $bool Whether to enable key normalization - * - * @return ArrayNodeDefinition - */ - public function normalizeKeys($bool) - { - $this->normalizeKeys = (bool) $bool; - - return $this; - } - - /** - * Appends a node definition. - * - * $node = new ArrayNodeDefinition() - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->end() - * ->append($this->getBarNodeDefinition()) - * ; - * - * @param NodeDefinition $node A NodeDefinition instance - * - * @return ArrayNodeDefinition This node - */ - public function append(NodeDefinition $node) - { - $this->children[$node->name] = $node->setParent($this); - - return $this; - } - - /** - * Returns a node builder to be used to add children and prototype. - * - * @return NodeBuilder The node builder - */ - protected function getNodeBuilder() - { - if (null === $this->nodeBuilder) { - $this->nodeBuilder = new NodeBuilder(); - } - - return $this->nodeBuilder->setParent($this); - } - - /** - * {@inheritdoc} - */ - protected function createNode() - { - if (null === $this->prototype) { - $node = new ArrayNode($this->name, $this->parent); - - $this->validateConcreteNode($node); - - $node->setAddIfNotSet($this->addDefaults); - - foreach ($this->children as $child) { - $child->parent = $node; - $node->addChild($child->getNode()); - } - } else { - $node = new PrototypedArrayNode($this->name, $this->parent); - - $this->validatePrototypeNode($node); - - if (null !== $this->key) { - $node->setKeyAttribute($this->key, $this->removeKeyItem); - } - - if (true === $this->atLeastOne) { - $node->setMinNumberOfElements(1); - } - - if ($this->default) { - $node->setDefaultValue($this->defaultValue); - } - - if (false !== $this->addDefaultChildren) { - $node->setAddChildrenIfNoneSet($this->addDefaultChildren); - if ($this->prototype instanceof static && null === $this->prototype->prototype) { - $this->prototype->addDefaultsIfNotSet(); - } - } - - $this->prototype->parent = $node; - $node->setPrototype($this->prototype->getNode()); - } - - $node->setAllowNewKeys($this->allowNewKeys); - $node->addEquivalentValue(null, $this->nullEquivalent); - $node->addEquivalentValue(true, $this->trueEquivalent); - $node->addEquivalentValue(false, $this->falseEquivalent); - $node->setPerformDeepMerging($this->performDeepMerging); - $node->setRequired($this->required); - $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); - $node->setNormalizeKeys($this->normalizeKeys); - - if (null !== $this->normalization) { - $node->setNormalizationClosures($this->normalization->before); - $node->setXmlRemappings($this->normalization->remappings); - } - - if (null !== $this->merge) { - $node->setAllowOverwrite($this->merge->allowOverwrite); - $node->setAllowFalse($this->merge->allowFalse); - } - - if (null !== $this->validation) { - $node->setFinalValidationClosures($this->validation->rules); - } - - return $node; - } - - /** - * Validate the configuration of a concrete node. - * - * @param ArrayNode $node The related node - * - * @throws InvalidDefinitionException - */ - protected function validateConcreteNode(ArrayNode $node) - { - $path = $node->getPath(); - - if (null !== $this->key) { - throw new InvalidDefinitionException( - sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path) - ); - } - - if (true === $this->atLeastOne) { - throw new InvalidDefinitionException( - sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) - ); - } - - if ($this->default) { - throw new InvalidDefinitionException( - sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path) - ); - } - - if (false !== $this->addDefaultChildren) { - throw new InvalidDefinitionException( - sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path) - ); - } - } - - /** - * Validate the configuration of a prototype node. - * - * @param PrototypedArrayNode $node The related node - * - * @throws InvalidDefinitionException - */ - protected function validatePrototypeNode(PrototypedArrayNode $node) - { - $path = $node->getPath(); - - if ($this->addDefaults) { - throw new InvalidDefinitionException( - sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path) - ); - } - - if (false !== $this->addDefaultChildren) { - if ($this->default) { - throw new InvalidDefinitionException( - sprintf('A default value and default children might not be used together at path "%s"', $path) - ); - } - - if (null !== $this->key && (null === $this->addDefaultChildren || is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { - throw new InvalidDefinitionException( - sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path) - ); - } - - if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { - throw new InvalidDefinitionException( - sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path) - ); - } - } - } -} diff --git a/validation/frameworks/broken/WithReturnTypehints.php.expected.json b/validation/frameworks/broken/WithReturnTypehints.php.expected.json new file mode 100644 index 00000000..f9c2430f --- /dev/null +++ b/validation/frameworks/broken/WithReturnTypehints.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "Fixtures\\Prophecy\\EmptyClass": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + ], + "self": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + ], + "parent": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + ] + }, + "definitions": { + "Fixtures\\Prophecy": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "Fixtures\\Prophecy", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + }, + "containerName": "Fixtures" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "Fixtures\\Prophecy\\WithReturnTypehints": { + "extends": [ + "Fixtures\\Prophecy\\EmptyClass" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "WithReturnTypehints", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + }, + "containerName": "Fixtures\\Prophecy" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "Fixtures\\Prophecy\\WithReturnTypehints->getSelf()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getSelf", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + }, + "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "Fixtures\\Prophecy\\WithReturnTypehints->getName()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getName", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + }, + "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\String_", + "type": {}, + "documentation": null + }, + "Fixtures\\Prophecy\\WithReturnTypehints->getParent()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getParent", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + }, + "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json new file mode 100644 index 00000000..dc579f95 --- /dev/null +++ b/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -0,0 +1,22 @@ +{ + "references": [], + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/anonymousClassMembersShouldNotBeSymbols.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/arrayValueShouldBeBoolean.php b/validation/frameworks/broken/arrayValueShouldBeBoolean.php new file mode 100644 index 00000000..bd5ff493 --- /dev/null +++ b/validation/frameworks/broken/arrayValueShouldBeBoolean.php @@ -0,0 +1,4 @@ + TRUE]; +} \ No newline at end of file diff --git a/validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json b/validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json new file mode 100644 index 00000000..9faade7e --- /dev/null +++ b/validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json @@ -0,0 +1,39 @@ +{ + "references": [], + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/arrayValueShouldBeBoolean.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A->foo": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "foo", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/arrayValueShouldBeBoolean.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Array_", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/caseStatement1.php.expected.json b/validation/frameworks/broken/caseStatement1.php.expected.json new file mode 100644 index 00000000..e8400af6 --- /dev/null +++ b/validation/frameworks/broken/caseStatement1.php.expected.json @@ -0,0 +1,29 @@ +{ + "references": { + "MyNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + ], + "A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/classDefinition1.php.expected.json b/validation/frameworks/broken/classDefinition1.php.expected.json new file mode 100644 index 00000000..c505348f --- /dev/null +++ b/validation/frameworks/broken/classDefinition1.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "TestNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + ], + "TestNamespace\\A->a": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + ] + }, + "definitions": { + "TestNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "TestNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + }, + "containerName": "TestNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestNamespace\\A->a": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + }, + "containerName": "TestNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Integer", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/classProperty1.php.expected.json b/validation/frameworks/broken/classProperty1.php.expected.json new file mode 100644 index 00000000..cce5b151 --- /dev/null +++ b/validation/frameworks/broken/classProperty1.php.expected.json @@ -0,0 +1,80 @@ +{ + "references": { + "SomeNamespace\\Goo": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + ], + "SomeNamespace": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + ] + }, + "definitions": { + "TestNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "TestNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestNamespace\\TestClass": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "TestClass", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + }, + "containerName": "TestNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestNamespace\\TestClass->testProperty": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "testProperty", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + }, + "containerName": "TestNamespace\\TestClass" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "TestNamespace\\TestClass->testMethod()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "testMethod", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + }, + "containerName": "TestNamespace\\TestClass" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants.php.expected.json b/validation/frameworks/broken/constants.php.expected.json new file mode 100644 index 00000000..be3094d3 --- /dev/null +++ b/validation/frameworks/broken/constants.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\BYE": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + ], + "BYE": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::suite()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "suite", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants2.php.expected.json b/validation/frameworks/broken/constants2.php.expected.json new file mode 100644 index 00000000..1e35fd35 --- /dev/null +++ b/validation/frameworks/broken/constants2.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\BYE": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + ], + "BYE": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::suite()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "suite", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants3.php.expected.json b/validation/frameworks/broken/constants3.php.expected.json new file mode 100644 index 00000000..cba6091f --- /dev/null +++ b/validation/frameworks/broken/constants3.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\T_NEW": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + ], + "T_NEW": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::suite()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "suite", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants4.php.expected.json b/validation/frameworks/broken/constants4.php.expected.json new file mode 100644 index 00000000..7585f03a --- /dev/null +++ b/validation/frameworks/broken/constants4.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\HI": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + ], + "HI": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->suite()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "suite", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constants5.php.expected.json b/validation/frameworks/broken/constants5.php.expected.json new file mode 100644 index 00000000..189b1cbb --- /dev/null +++ b/validation/frameworks/broken/constants5.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\PHP_INT_MAX": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + ], + "PHP_INT_MAX": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\Mbstring": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "Mbstring", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\Mbstring::MB_CASE_FOLD": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MB_CASE_FOLD", + "kind": 14, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + }, + "containerName": "MyNamespace\\Mbstring" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json b/validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json new file mode 100644 index 00000000..15be3501 --- /dev/null +++ b/validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json @@ -0,0 +1,43 @@ +{ + "references": { + "MY_CONSTANT": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + ] + }, + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "A", + "kind": 11, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json b/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json new file mode 100644 index 00000000..e4660b70 --- /dev/null +++ b/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json @@ -0,0 +1,22 @@ +{ + "references": [], + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/docBlocksOnNamespaceDefinition.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/exceptions1.php.expected.json b/validation/frameworks/broken/exceptions1.php.expected.json new file mode 100644 index 00000000..1cf37fc5 --- /dev/null +++ b/validation/frameworks/broken/exceptions1.php.expected.json @@ -0,0 +1,22 @@ +{ + "references": [], + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/exceptions1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/forLoopReference1.php b/validation/frameworks/broken/forLoopReference1.php index a51d1ad0..438323f1 100644 --- a/validation/frameworks/broken/forLoopReference1.php +++ b/validation/frameworks/broken/forLoopReference1.php @@ -1,8 +1,12 @@ getParent()) { +class ForLoopReference1 { + public function getThat() { + for ($that = $this; null !== $that; $that = $that->foo()) { } } + + public function foo() { + return $this; + } } diff --git a/validation/frameworks/broken/forLoopReference1.php.expected.json b/validation/frameworks/broken/forLoopReference1.php.expected.json new file mode 100644 index 00000000..66da6eb7 --- /dev/null +++ b/validation/frameworks/broken/forLoopReference1.php.expected.json @@ -0,0 +1,60 @@ +{ + "references": { + "ForLoopReference1->foo()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + ] + }, + "definitions": { + "ForLoopReference1": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "ForLoopReference1", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "ForLoopReference1->getThat()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getThat", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + }, + "containerName": "ForLoopReference1" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "ForLoopReference1->foo()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "foo", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + }, + "containerName": "ForLoopReference1" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/functionCall.php b/validation/frameworks/broken/functionCall.php deleted file mode 100644 index 121e84b4..00000000 --- a/validation/frameworks/broken/functionCall.php +++ /dev/null @@ -1,53 +0,0 @@ -b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse.php" + ] + }, + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/functionUse2.php.expected.json b/validation/frameworks/broken/functionUse2.php.expected.json new file mode 100644 index 00000000..dfb66d55 --- /dev/null +++ b/validation/frameworks/broken/functionUse2.php.expected.json @@ -0,0 +1,11 @@ +{ + "references": { + "LanguageServer": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" + ], + "LanguageServer\\timeout": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" + ] + }, + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/ifStatement1.php.expected.json b/validation/frameworks/broken/ifStatement1.php.expected.json new file mode 100644 index 00000000..4e4a23fc --- /dev/null +++ b/validation/frameworks/broken/ifStatement1.php.expected.json @@ -0,0 +1,29 @@ +{ + "references": { + "MyNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + ], + "A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/magicConstantsShouldBeGlobal.php.expected.json b/validation/frameworks/broken/magicConstantsShouldBeGlobal.php.expected.json new file mode 100644 index 00000000..363fc5fe --- /dev/null +++ b/validation/frameworks/broken/magicConstantsShouldBeGlobal.php.expected.json @@ -0,0 +1,22 @@ +{ + "references": [], + "definitions": { + "B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "B", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/magicConstantsShouldBeGlobal.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/magicConsts.php.expected.json b/validation/frameworks/broken/magicConsts.php.expected.json new file mode 100644 index 00000000..222b0b6a --- /dev/null +++ b/validation/frameworks/broken/magicConsts.php.expected.json @@ -0,0 +1,39 @@ +{ + "references": [], + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/magicConsts.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A::$deprecationsTriggered": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "deprecationsTriggered", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/magicConsts.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Array_", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberAccess1.php.expected.json b/validation/frameworks/broken/memberAccess1.php.expected.json new file mode 100644 index 00000000..59b2fa20 --- /dev/null +++ b/validation/frameworks/broken/memberAccess1.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\a": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + ], + "MyNamespace\\a->a()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::a()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberAccess2.php.expected.json b/validation/frameworks/broken/memberAccess2.php.expected.json new file mode 100644 index 00000000..c3b93350 --- /dev/null +++ b/validation/frameworks/broken/memberAccess2.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\a": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + ], + "MyNamespace\\a->a()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::a()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberAccess3.php.expected.json b/validation/frameworks/broken/memberAccess3.php.expected.json new file mode 100644 index 00000000..9026d384 --- /dev/null +++ b/validation/frameworks/broken/memberAccess3.php.expected.json @@ -0,0 +1,78 @@ +{ + "references": { + "MyNamespace\\ClassLoader": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "Closure::bind()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "Closure": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "MyNamespace\\ClassLoader->prefixesPsr0": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "MyNamespace\\ComposerStaticInitIncludePath": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ], + "MyNamespace\\ClassLoader::class": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::getInitializer()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getInitializer", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberAccess4.php.expected.json b/validation/frameworks/broken/memberAccess4.php.expected.json new file mode 100644 index 00000000..e2352a71 --- /dev/null +++ b/validation/frameworks/broken/memberAccess4.php.expected.json @@ -0,0 +1,69 @@ +{ + "references": { + "MyNamespace\\Request::create()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + ], + "MyNamespace\\Request": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + ], + "MyNamespace\\Url->toString()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + ], + "MyNamespace\\Url": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->testRequest()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "testRequest", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberAccess5.php.expected.json b/validation/frameworks/broken/memberAccess5.php.expected.json new file mode 100644 index 00000000..ec0f7223 --- /dev/null +++ b/validation/frameworks/broken/memberAccess5.php.expected.json @@ -0,0 +1,56 @@ +{ + "references": [], + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\ParseErrorsTest": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "ParseErrorsTest", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\ParseErrorsTest->setUp()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "setUp", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + }, + "containerName": "MyNamespace\\ParseErrorsTest" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/memberCall1.php.expected.json b/validation/frameworks/broken/memberCall1.php.expected.json new file mode 100644 index 00000000..b640d83c --- /dev/null +++ b/validation/frameworks/broken/memberCall1.php.expected.json @@ -0,0 +1,66 @@ +{ + "references": { + "MyNamespace\\AccountInterface": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + ], + "MyNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + ], + "MyNamespace\\AccountInterface->getAccount()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\ParseErrorsTest": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "ParseErrorsTest", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\ParseErrorsTest->setAccount()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "setAccount", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + }, + "containerName": "MyNamespace\\ParseErrorsTest" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/multipleNamespaces.php.expected.json b/validation/frameworks/broken/multipleNamespaces.php.expected.json new file mode 100644 index 00000000..95b36453 --- /dev/null +++ b/validation/frameworks/broken/multipleNamespaces.php.expected.json @@ -0,0 +1,116 @@ +{ + "references": { + "MyNamespace2\\MyNamespace1\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + ], + "MyNamespace2\\A->b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + ] + }, + "definitions": { + "MyNamespace1": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace1", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace1\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "MyNamespace1" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace1\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "MyNamespace1\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace2": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace2", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace2\\A": { + "extends": [ + "MyNamespace2\\MyNamespace1\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "MyNamespace2" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace2\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + }, + "containerName": "MyNamespace2\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/multiplePreceedingComments.php b/validation/frameworks/broken/multiplePreceedingComments.php new file mode 100644 index 00000000..14903856 --- /dev/null +++ b/validation/frameworks/broken/multiplePreceedingComments.php @@ -0,0 +1,15 @@ +fn()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "fn", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multiplePreceedingComments.php" + }, + "containerName": "Foo" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/nameToken.php.expected.json b/validation/frameworks/broken/nameToken.php.expected.json new file mode 100644 index 00000000..12bb667f --- /dev/null +++ b/validation/frameworks/broken/nameToken.php.expected.json @@ -0,0 +1,43 @@ +{ + "references": { + "static": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" + ] + }, + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces2.php.expected.json b/validation/frameworks/broken/namespaces2.php.expected.json new file mode 100644 index 00000000..a3099501 --- /dev/null +++ b/validation/frameworks/broken/namespaces2.php.expected.json @@ -0,0 +1,35 @@ +{ + "references": { + "NS1\\C": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + ], + "NS1": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + ], + "NS1\\I": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + ], + "NS1\\T": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + ] + }, + "definitions": { + "MyNamespace1": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace1", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces3.php.expected.json b/validation/frameworks/broken/namespaces3.php.expected.json new file mode 100644 index 00000000..d347fa2a --- /dev/null +++ b/validation/frameworks/broken/namespaces3.php.expected.json @@ -0,0 +1,14 @@ +{ + "references": { + "a\\b": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + ], + "b": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + ], + "c": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + ] + }, + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces4.php.expected.json b/validation/frameworks/broken/namespaces4.php.expected.json new file mode 100644 index 00000000..32f01cbc --- /dev/null +++ b/validation/frameworks/broken/namespaces4.php.expected.json @@ -0,0 +1,11 @@ +{ + "references": { + "a\\b": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces4.php" + ], + "a": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces4.php" + ] + }, + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces5.php.expected.json b/validation/frameworks/broken/namespaces5.php.expected.json new file mode 100644 index 00000000..95e8f513 --- /dev/null +++ b/validation/frameworks/broken/namespaces5.php.expected.json @@ -0,0 +1,44 @@ +{ + "references": { + "LanguageServer\\Protocol": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer\\Protocol\\TextDocumentIdentifier": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer\\Protocol\\Position": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer\\Protocol\\ReferenceContext": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer\\Protocol\\Location": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ], + "LanguageServer\\Protocol\\Range": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + ] + }, + "definitions": { + "B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "B", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces6.php.expected.json b/validation/frameworks/broken/namespaces6.php.expected.json new file mode 100644 index 00000000..ff214a78 --- /dev/null +++ b/validation/frameworks/broken/namespaces6.php.expected.json @@ -0,0 +1,22 @@ +{ + "references": [], + "definitions": { + "A\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "A\\B", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces6.php" + }, + "containerName": "A" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces7.php.expected.json b/validation/frameworks/broken/namespaces7.php.expected.json new file mode 100644 index 00000000..fe7e4fc2 --- /dev/null +++ b/validation/frameworks/broken/namespaces7.php.expected.json @@ -0,0 +1,4 @@ +{ + "references": [], + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces8.php.expected.json b/validation/frameworks/broken/namespaces8.php.expected.json new file mode 100644 index 00000000..3538793c --- /dev/null +++ b/validation/frameworks/broken/namespaces8.php.expected.json @@ -0,0 +1,26 @@ +{ + "references": { + "LanguageServer": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces8.php" + ] + }, + "definitions": { + "LanguageServer\\Tests\\Utils": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "LanguageServer\\Tests\\Utils", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces8.php" + }, + "containerName": "LanguageServer\\Tests" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/namespaces9.php.expected.json b/validation/frameworks/broken/namespaces9.php.expected.json new file mode 100644 index 00000000..fe7e4fc2 --- /dev/null +++ b/validation/frameworks/broken/namespaces9.php.expected.json @@ -0,0 +1,4 @@ +{ + "references": [], + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/objectCreation.php.expected.json b/validation/frameworks/broken/objectCreation.php.expected.json new file mode 100644 index 00000000..a23931a2 --- /dev/null +++ b/validation/frameworks/broken/objectCreation.php.expected.json @@ -0,0 +1,60 @@ +{ + "references": { + "MyNamespace\\A->inline_diff_renderer": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/objectCreation2.php.expected.json b/validation/frameworks/broken/objectCreation2.php.expected.json new file mode 100644 index 00000000..c2226fb1 --- /dev/null +++ b/validation/frameworks/broken/objectCreation2.php.expected.json @@ -0,0 +1,80 @@ +{ + "references": { + "MyNamespace\\B->hi()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + ], + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/objectCreation3.php.expected.json b/validation/frameworks/broken/objectCreation3.php.expected.json new file mode 100644 index 00000000..9c2d7530 --- /dev/null +++ b/validation/frameworks/broken/objectCreation3.php.expected.json @@ -0,0 +1,43 @@ +{ + "references": { + "A->args": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + ] + }, + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/param1.php.expected.json b/validation/frameworks/broken/param1.php.expected.json new file mode 100644 index 00000000..0d4fb71f --- /dev/null +++ b/validation/frameworks/broken/param1.php.expected.json @@ -0,0 +1,43 @@ +{ + "references": { + "MyNamespace\\Hi": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\init()": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "init", + "kind": 12, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/parameterTypeResolution1.php b/validation/frameworks/broken/parameterTypeResolution1.php index 09ead6f5..d69bc7ef 100644 --- a/validation/frameworks/broken/parameterTypeResolution1.php +++ b/validation/frameworks/broken/parameterTypeResolution1.php @@ -1,7 +1,7 @@ getAccount()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + ] + }, + "definitions": { + "ParamType": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "ParamType", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "ParamType->setAccount()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "setAccount", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + }, + "containerName": "ParamType" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "ParamType->getAccount()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "getAccount", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + }, + "containerName": "ParamType" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/parent1.php.expected.json b/validation/frameworks/broken/parent1.php.expected.json new file mode 100644 index 00000000..0bd3113f --- /dev/null +++ b/validation/frameworks/broken/parent1.php.expected.json @@ -0,0 +1,99 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + ], + "parent": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/parent2.php.expected.json b/validation/frameworks/broken/parent2.php.expected.json new file mode 100644 index 00000000..bedd4d53 --- /dev/null +++ b/validation/frameworks/broken/parent2.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + ], + "PARENT::b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + ], + "PARENT": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/parent3.php.expected.json b/validation/frameworks/broken/parent3.php.expected.json new file mode 100644 index 00000000..b051fb9e --- /dev/null +++ b/validation/frameworks/broken/parent3.php.expected.json @@ -0,0 +1,108 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + ], + "MyNamespace\\parent": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + ], + "parent": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + ], + "MyNamespace\\b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + ], + "b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/propertyName1.php.expected.json b/validation/frameworks/broken/propertyName1.php.expected.json new file mode 100644 index 00000000..24b16fe2 --- /dev/null +++ b/validation/frameworks/broken/propertyName1.php.expected.json @@ -0,0 +1,39 @@ +{ + "references": [], + "definitions": { + "MyClass": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "MyClass", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyClass->mainPropertyName": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "mainPropertyName", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName1.php" + }, + "containerName": "MyClass" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\String_", + "type": {}, + "documentation": "The name of the main property, or NULL if there is none." + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/propertyName2.php.expected.json b/validation/frameworks/broken/propertyName2.php.expected.json new file mode 100644 index 00000000..59db6fce --- /dev/null +++ b/validation/frameworks/broken/propertyName2.php.expected.json @@ -0,0 +1,39 @@ +{ + "references": [], + "definitions": { + "MyClass": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "MyClass", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyClass->mainPropertyName": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "mainPropertyName", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName2.php" + }, + "containerName": "MyClass" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\String_", + "type": {}, + "documentation": "The name of the main property, or NULL if there is none." + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/returnType.php.expected.json b/validation/frameworks/broken/returnType.php.expected.json new file mode 100644 index 00000000..45831dc6 --- /dev/null +++ b/validation/frameworks/broken/returnType.php.expected.json @@ -0,0 +1,46 @@ +{ + "references": { + "TestNamespace\\TestClass": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + ], + "TestNamespace\\TestClass2": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + ] + }, + "definitions": { + "TestNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "TestNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestNamespace\\whatever()": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "whatever", + "kind": 12, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + }, + "containerName": "TestNamespace" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", + "type": {}, + "documentation": "Aute duis elit reprehenderit tempor cillum proident anim laborum eu laboris reprehenderit ea incididunt." + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/scopedPropertyAccess.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess.php.expected.json new file mode 100644 index 00000000..f30d2359 --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "MyNamespace\\A::a()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + ], + "MyNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::a()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/scopedPropertyAccess2.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess2.php.expected.json new file mode 100644 index 00000000..93d41ae4 --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess2.php.expected.json @@ -0,0 +1,26 @@ +{ + "references": { + "MyNamespace\\A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json new file mode 100644 index 00000000..70170985 --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json @@ -0,0 +1,46 @@ +{ + "references": { + "A::$a": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + ], + "A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + ] + }, + "definitions": { + "A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "A::$a": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + }, + "containerName": "A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\String_", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/scopedPropertyAccess4.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess4.php.expected.json new file mode 100644 index 00000000..015a08cc --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess4.php.expected.json @@ -0,0 +1,8 @@ +{ + "references": { + "A": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess4.php" + ] + }, + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json new file mode 100644 index 00000000..a556e1a0 --- /dev/null +++ b/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json @@ -0,0 +1,52 @@ +{ + "references": { + "TestInterface": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + ], + "TestClass::$testProperty": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + ], + "TestClass": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + ], + "TestClass::$staticTestProperty": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + ] + }, + "definitions": { + "TestClass": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "TestClass", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "TestClass::$testProperty": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "testProperty", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + }, + "containerName": "TestClass" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Array_", + "type": {}, + "documentation": "Lorem excepteur officia sit anim velit veniam enim." + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self1.php b/validation/frameworks/broken/self1.php index b3036d2a..e2863816 100644 --- a/validation/frameworks/broken/self1.php +++ b/validation/frameworks/broken/self1.php @@ -10,6 +10,7 @@ function b() { class A extends B { function a () { + // TODO - should 'self' be included in references? $a = self::b(); } } diff --git a/validation/frameworks/broken/self1.php.expected.json b/validation/frameworks/broken/self1.php.expected.json new file mode 100644 index 00000000..d1953fb8 --- /dev/null +++ b/validation/frameworks/broken/self1.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + ], + "MyNamespace\\A::b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + ], + "self": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self2.php.expected.json b/validation/frameworks/broken/self2.php.expected.json new file mode 100644 index 00000000..71204d88 --- /dev/null +++ b/validation/frameworks/broken/self2.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + ], + "SELF::b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + ], + "SELF": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self3.php.expected.json b/validation/frameworks/broken/self3.php.expected.json new file mode 100644 index 00000000..0bf7e6c6 --- /dev/null +++ b/validation/frameworks/broken/self3.php.expected.json @@ -0,0 +1,108 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + ], + "MyNamespace\\self": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + ], + "self": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + ], + "MyNamespace\\b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + ], + "b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self4.php.expected.json b/validation/frameworks/broken/self4.php.expected.json new file mode 100644 index 00000000..e9665baa --- /dev/null +++ b/validation/frameworks/broken/self4.php.expected.json @@ -0,0 +1,69 @@ +{ + "references": { + "self": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + ], + "MyNamespace\\A->addTestFile()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + ], + "MyNamespace\\DS": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + ], + "DS": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A::suite()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "suite", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/self5.php.expected.json b/validation/frameworks/broken/self5.php.expected.json new file mode 100644 index 00000000..5758d939 --- /dev/null +++ b/validation/frameworks/broken/self5.php.expected.json @@ -0,0 +1,60 @@ +{ + "references": { + "MyNamespace\\A->assertTrue()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->typesProvider()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "typesProvider", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/static1.php.expected.json b/validation/frameworks/broken/static1.php.expected.json new file mode 100644 index 00000000..66591b2b --- /dev/null +++ b/validation/frameworks/broken/static1.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + ], + "MyNamespace\\A::b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + ], + "static": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/static2.php.expected.json b/validation/frameworks/broken/static2.php.expected.json new file mode 100644 index 00000000..dec1323e --- /dev/null +++ b/validation/frameworks/broken/static2.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + ], + "STATIC::b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + ], + "STATIC": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/static3.php.expected.json b/validation/frameworks/broken/static3.php.expected.json new file mode 100644 index 00000000..3a821727 --- /dev/null +++ b/validation/frameworks/broken/static3.php.expected.json @@ -0,0 +1,102 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + ], + "MyNamespace\\b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + ], + "b()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\B->b()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "b", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + }, + "containerName": "MyNamespace\\B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/static4.php.expected.json b/validation/frameworks/broken/static4.php.expected.json new file mode 100644 index 00000000..cab56e32 --- /dev/null +++ b/validation/frameworks/broken/static4.php.expected.json @@ -0,0 +1,65 @@ +{ + "references": { + "MyNamespace\\B": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + ], + "static": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + ] + }, + "definitions": { + "MyNamespace": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "MyNamespace", + "kind": 3, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A": { + "extends": [ + "MyNamespace\\B" + ], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "A", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + }, + "containerName": "MyNamespace" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "MyNamespace\\A->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + }, + "containerName": "MyNamespace\\A" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/staticInArray.php.expected.json b/validation/frameworks/broken/staticInArray.php.expected.json new file mode 100644 index 00000000..fe7e4fc2 --- /dev/null +++ b/validation/frameworks/broken/staticInArray.php.expected.json @@ -0,0 +1,4 @@ +{ + "references": [], + "definitions": [] +} \ No newline at end of file diff --git a/validation/frameworks/broken/stringVariable.php.expected.json b/validation/frameworks/broken/stringVariable.php.expected.json new file mode 100644 index 00000000..ce538698 --- /dev/null +++ b/validation/frameworks/broken/stringVariable.php.expected.json @@ -0,0 +1,60 @@ +{ + "references": { + "B->hi": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + ] + }, + "definitions": { + "B": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "B", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "B->hi": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "hi", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + }, + "containerName": "B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Integer", + "type": {}, + "documentation": null + }, + "B->a()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "a", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + }, + "containerName": "B" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php b/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php new file mode 100644 index 00000000..61fe57e2 --- /dev/null +++ b/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php @@ -0,0 +1,5 @@ +bar = 'hello'; + } +} diff --git a/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json new file mode 100644 index 00000000..73a81e9f --- /dev/null +++ b/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json @@ -0,0 +1,63 @@ +{ + "references": { + "CURLAUTH_BASIC": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + ], + "Foo->bar": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + ] + }, + "definitions": { + "Foo": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "Foo", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "Foo->bar": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "bar", + "kind": 7, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + }, + "containerName": "Foo" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "Foo->foo()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "foo", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + }, + "containerName": "Foo" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file From ce548deb9d4e24b21bdc23171f2f4da347df6ed6 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 21:32:01 -0700 Subject: [PATCH 076/149] Update baselines - failing tests are verified as expected --- tests/Validation/ValidationTest.php | 19 +++++++++++-------- .../WithReturnTypehints.php.expected.json | 4 ++-- .../broken/constants5.php.expected.json | 5 +---- .../broken/functionUse2.php.expected.json | 2 +- .../broken/memberAccess3.php.expected.json | 4 ++-- .../multipleNamespaces.php.expected.json | 6 ++++++ ...ltiplePreceedingComments.php.expected.json | 4 ++-- .../broken/nameToken.php.expected.json | 6 +----- .../broken/parent3.php.expected.json | 8 +------- .../scopedPropertyAccess3.php.expected.json | 4 ++-- .../scopedPropertyAccess5.php.expected.json | 4 ++-- .../frameworks/broken/self2.php.expected.json | 4 ++-- .../frameworks/broken/self3.php.expected.json | 8 +------- .../broken/static2.php.expected.json | 4 ++-- .../broken/stringVariable.php.expected.json | 6 +----- ...edNameOutsideOfNamespace.php.expected.json | 3 --- ...rifyFqsenOnClassProperty.php.expected.json | 2 +- 17 files changed, 38 insertions(+), 55 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 9f292d61..5a31eecf 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -61,7 +61,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $fileContents = file_get_contents($testCaseFile); $expectedValues = $this->getExpectedTestValues($testCaseFile, $frameworkName, $fileContents); - $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); + $actualValues = $this->getActualTestValues($testCaseFile, $frameworkName, $fileContents); $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); @@ -111,14 +111,10 @@ private function getExpectedTestValues($filename, $frameworkName, $fileContents) 'definitions' => json_decode(json_encode($expectedDefs)) ); - if ($frameworkName === 'broken') { - file_put_contents($outputFile, json_encode($refsAndDefs, JSON_PRETTY_PRINT)); - } - return $refsAndDefs; } - private function getActualTestValues($filename, $fileContents): array { + private function getActualTestValues($filename, $frameworkName, $fileContents): array { global $parserKind; $parserKind = ParserKind::TOLERANT_PHP_PARSER; @@ -133,12 +129,19 @@ private function getActualTestValues($filename, $fileContents): array { $this->filterSkippedReferences($actualRefs); $actualDefs = $this->getTestValuesFromDefs($document->getDefinitions()); - // TODO - probably a more PHP-typical way to do this. Need to compare the objects parsed from json files + // TODO - there's probably a more PHP-typical way to do this. Need to compare the objects parsed from json files // to the real results. json_decode returns stdClass Objects, not arrays. - return array( + $refsAndDefs = array( 'references' => json_decode(json_encode($actualRefs)), 'definitions' => json_decode(json_encode($actualDefs)) ); + + $outputFile = $filename . '.expected.json'; + if ($frameworkName === 'broken') { + file_put_contents($outputFile, json_encode($refsAndDefs, JSON_PRETTY_PRINT)); + } + + return $refsAndDefs; } /** diff --git a/validation/frameworks/broken/WithReturnTypehints.php.expected.json b/validation/frameworks/broken/WithReturnTypehints.php.expected.json index f9c2430f..0a3eb097 100644 --- a/validation/frameworks/broken/WithReturnTypehints.php.expected.json +++ b/validation/frameworks/broken/WithReturnTypehints.php.expected.json @@ -60,7 +60,7 @@ }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, - "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, "documentation": null }, @@ -94,7 +94,7 @@ }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, - "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, "documentation": null } diff --git a/validation/frameworks/broken/constants5.php.expected.json b/validation/frameworks/broken/constants5.php.expected.json index 189b1cbb..3d5da35f 100644 --- a/validation/frameworks/broken/constants5.php.expected.json +++ b/validation/frameworks/broken/constants5.php.expected.json @@ -2,9 +2,6 @@ "references": { "MyNamespace\\PHP_INT_MAX": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" - ], - "PHP_INT_MAX": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" ] }, "definitions": { @@ -55,7 +52,7 @@ }, "containerName": "MyNamespace\\Mbstring" }, - "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, "documentation": null } diff --git a/validation/frameworks/broken/functionUse2.php.expected.json b/validation/frameworks/broken/functionUse2.php.expected.json index dfb66d55..fa047e6d 100644 --- a/validation/frameworks/broken/functionUse2.php.expected.json +++ b/validation/frameworks/broken/functionUse2.php.expected.json @@ -3,7 +3,7 @@ "LanguageServer": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" ], - "LanguageServer\\timeout": [ + "LanguageServer\\timeout()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" ] }, diff --git a/validation/frameworks/broken/memberAccess3.php.expected.json b/validation/frameworks/broken/memberAccess3.php.expected.json index 9026d384..c9e83101 100644 --- a/validation/frameworks/broken/memberAccess3.php.expected.json +++ b/validation/frameworks/broken/memberAccess3.php.expected.json @@ -12,10 +12,10 @@ "MyNamespace\\ClassLoader->prefixesPsr0": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" ], - "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ + "MyNamespace\\ComposerStaticInitIncludePath": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" ], - "MyNamespace\\ComposerStaticInitIncludePath": [ + "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" ], "MyNamespace\\ClassLoader::class": [ diff --git a/validation/frameworks/broken/multipleNamespaces.php.expected.json b/validation/frameworks/broken/multipleNamespaces.php.expected.json index 95b36453..274dd5bf 100644 --- a/validation/frameworks/broken/multipleNamespaces.php.expected.json +++ b/validation/frameworks/broken/multipleNamespaces.php.expected.json @@ -3,6 +3,12 @@ "MyNamespace2\\MyNamespace1\\B": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" ], + "MyNamespace2\\MyNamespace1": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + ], + "MyNamespace2": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + ], "MyNamespace2\\A->b()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" ] diff --git a/validation/frameworks/broken/multiplePreceedingComments.php.expected.json b/validation/frameworks/broken/multiplePreceedingComments.php.expected.json index 3feefc45..415b052b 100644 --- a/validation/frameworks/broken/multiplePreceedingComments.php.expected.json +++ b/validation/frameworks/broken/multiplePreceedingComments.php.expected.json @@ -31,9 +31,9 @@ }, "containerName": "Foo" }, - "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, - "documentation": null + "documentation": "Foo" } } } \ No newline at end of file diff --git a/validation/frameworks/broken/nameToken.php.expected.json b/validation/frameworks/broken/nameToken.php.expected.json index 12bb667f..5513701d 100644 --- a/validation/frameworks/broken/nameToken.php.expected.json +++ b/validation/frameworks/broken/nameToken.php.expected.json @@ -1,9 +1,5 @@ { - "references": { - "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" - ] - }, + "references": [], "definitions": { "A": { "extends": [], diff --git a/validation/frameworks/broken/parent3.php.expected.json b/validation/frameworks/broken/parent3.php.expected.json index b051fb9e..1acf7ab6 100644 --- a/validation/frameworks/broken/parent3.php.expected.json +++ b/validation/frameworks/broken/parent3.php.expected.json @@ -3,17 +3,11 @@ "MyNamespace\\B": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" ], - "MyNamespace\\parent": [ + "MyNamespace\\B->b()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" ], "parent": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" - ], - "MyNamespace\\b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" - ], - "b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" ] }, "definitions": { diff --git a/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json index 70170985..d64eb892 100644 --- a/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json +++ b/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json @@ -1,9 +1,9 @@ { "references": { - "A::$a": [ + "A": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" ], - "A": [ + "A::$a": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" ] }, diff --git a/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json b/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json index a556e1a0..84d52c3b 100644 --- a/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json +++ b/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json @@ -3,10 +3,10 @@ "TestInterface": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" ], - "TestClass::$testProperty": [ + "TestClass": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" ], - "TestClass": [ + "TestClass::$testProperty": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" ], "TestClass::$staticTestProperty": [ diff --git a/validation/frameworks/broken/self2.php.expected.json b/validation/frameworks/broken/self2.php.expected.json index 71204d88..03b72d68 100644 --- a/validation/frameworks/broken/self2.php.expected.json +++ b/validation/frameworks/broken/self2.php.expected.json @@ -3,10 +3,10 @@ "MyNamespace\\B": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" ], - "SELF::b()": [ + "MyNamespace\\A::b()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" ], - "SELF": [ + "self": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" ] }, diff --git a/validation/frameworks/broken/self3.php.expected.json b/validation/frameworks/broken/self3.php.expected.json index 0bf7e6c6..e2ea5f2a 100644 --- a/validation/frameworks/broken/self3.php.expected.json +++ b/validation/frameworks/broken/self3.php.expected.json @@ -3,17 +3,11 @@ "MyNamespace\\B": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" ], - "MyNamespace\\self": [ + "MyNamespace\\A->b()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" ], "self": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" - ], - "MyNamespace\\b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" - ], - "b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" ] }, "definitions": { diff --git a/validation/frameworks/broken/static2.php.expected.json b/validation/frameworks/broken/static2.php.expected.json index dec1323e..363a5865 100644 --- a/validation/frameworks/broken/static2.php.expected.json +++ b/validation/frameworks/broken/static2.php.expected.json @@ -3,10 +3,10 @@ "MyNamespace\\B": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" ], - "STATIC::b()": [ + "MyNamespace\\A::b()": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" ], - "STATIC": [ + "static": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" ] }, diff --git a/validation/frameworks/broken/stringVariable.php.expected.json b/validation/frameworks/broken/stringVariable.php.expected.json index ce538698..79119343 100644 --- a/validation/frameworks/broken/stringVariable.php.expected.json +++ b/validation/frameworks/broken/stringVariable.php.expected.json @@ -1,9 +1,5 @@ { - "references": { - "B->hi": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" - ] - }, + "references": [], "definitions": { "B": { "extends": [], diff --git a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json b/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json index 302e5113..331b893d 100644 --- a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -1,8 +1,5 @@ { "references": { - "SomeNamespace\\NameOutsideOfNamespace": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/testQualifiedNameOutsideOfNamespace.php" - ], "NameOutsideOfNamespace": [ "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/testQualifiedNameOutsideOfNamespace.php" ] diff --git a/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json index 73a81e9f..b54f1562 100644 --- a/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json +++ b/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json @@ -38,7 +38,7 @@ }, "containerName": "Foo" }, - "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, "documentation": null }, From dc673373df84a875000b2070837525cc0ff19596 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 22:22:22 -0700 Subject: [PATCH 077/149] Rewrite .expected file on test failure and rename "broken" -> "_cases" --- tests/Validation/ValidationTest.php | 30 ++++++---- .../WithReturnTypehints.php | 0 .../WithReturnTypehints.php.expected.json | 16 +++--- ...nonymousClassMembersShouldNotBeSymbols.php | 0 ...embersShouldNotBeSymbols.php.expected.json | 2 +- .../arrayValueShouldBeBoolean.php | 0 ...rrayValueShouldBeBoolean.php.expected.json | 4 +- .../{broken => _cases}/caseStatement1.php | 0 .../caseStatement1.php.expected.json | 6 +- .../{broken => _cases}/classDefinition1.php | 0 .../classDefinition1.php.expected.json | 10 ++-- .../{broken => _cases}/classProperty1.php | 0 .../classProperty1.php.expected.json | 12 ++-- .../{broken => _cases}/constants.php | 0 .../constants.php.expected.json | 10 ++-- .../{broken => _cases}/constants2.php | 0 .../constants2.php.expected.json | 10 ++-- .../{broken => _cases}/constants3.php | 0 .../constants3.php.expected.json | 10 ++-- .../{broken => _cases}/constants4.php | 0 .../constants4.php.expected.json | 10 ++-- .../{broken => _cases}/constants5.php | 0 .../constants5.php.expected.json | 8 +-- .../constantsInFunctionParamDefault.php | 0 ...tsInFunctionParamDefault.php.expected.json | 6 +- .../docBlocksOnNamespaceDefinition.php | 0 ...cksOnNamespaceDefinition.php.expected.json | 2 +- .../{broken => _cases}/exceptions1.php | 0 .../exceptions1.php.expected.json | 2 +- .../{broken => _cases}/forLoopReference1.php | 0 .../forLoopReference1.php.expected.json | 0 .../{broken => _cases}/functionUse.php | 0 .../functionUse.php.expected.json | 4 +- .../{broken => _cases}/functionUse2.php | 0 .../functionUse2.php.expected.json | 4 +- .../{broken => _cases}/ifStatement1.php | 0 .../ifStatement1.php.expected.json | 6 +- .../frameworks/_cases/interfaceProperty.php | 5 ++ .../interfaceProperty.php.expected.json | 22 ++++++++ .../magicConstantsShouldBeGlobal.php | 0 ...cConstantsShouldBeGlobal.php.expected.json | 2 +- .../{broken => _cases}/magicConsts.php | 0 .../magicConsts.php.expected.json | 4 +- .../{broken => _cases}/memberAccess1.php | 0 .../memberAccess1.php.expected.json | 10 ++-- .../{broken => _cases}/memberAccess2.php | 0 .../memberAccess2.php.expected.json | 10 ++-- .../{broken => _cases}/memberAccess3.php | 0 .../memberAccess3.php.expected.json | 20 +++---- .../{broken => _cases}/memberAccess4.php | 0 .../memberAccess4.php.expected.json | 14 ++--- .../{broken => _cases}/memberAccess5.php | 0 .../memberAccess5.php.expected.json | 6 +- .../{broken => _cases}/memberCall1.php | 0 .../memberCall1.php.expected.json | 12 ++-- .../{broken => _cases}/multipleNamespaces.php | 0 .../multipleNamespaces.php.expected.json | 20 +++---- .../multiplePreceedingComments.php | 0 ...ltiplePreceedingComments.php.expected.json | 4 +- .../{broken => _cases}/nameToken.php | 0 .../nameToken.php.expected.json | 4 +- .../{broken => _cases}/namespaces2.php | 0 .../namespaces2.php.expected.json | 10 ++-- .../{broken => _cases}/namespaces3.php | 0 .../namespaces3.php.expected.json | 0 .../{broken => _cases}/namespaces4.php | 0 .../namespaces4.php.expected.json | 4 +- .../{broken => _cases}/namespaces5.php | 0 .../namespaces5.php.expected.json | 16 +++--- .../{broken => _cases}/namespaces6.php | 0 .../namespaces6.php.expected.json | 2 +- .../{broken => _cases}/namespaces7.php | 0 .../namespaces7.php.expected.json | 0 .../{broken => _cases}/namespaces8.php | 0 .../namespaces8.php.expected.json | 4 +- .../{broken => _cases}/namespaces9.php | 0 .../namespaces9.php.expected.json | 0 validation/frameworks/_cases/newStatic.php | 12 ++++ .../_cases/newStatic.php.expected.json | 56 +++++++++++++++++++ .../{broken => _cases}/objectCreation.php | 0 .../objectCreation.php.expected.json | 8 +-- .../{broken => _cases}/objectCreation2.php | 0 .../objectCreation2.php.expected.json | 12 ++-- .../{broken => _cases}/objectCreation3.php | 0 .../objectCreation3.php.expected.json | 6 +- .../frameworks/{broken => _cases}/param1.php | 0 .../param1.php.expected.json | 6 +- .../parameterTypeResolution1.php | 0 ...parameterTypeResolution1.php.expected.json | 0 .../frameworks/{broken => _cases}/parent1.php | 0 .../parent1.php.expected.json | 14 ++--- .../frameworks/{broken => _cases}/parent2.php | 0 .../parent2.php.expected.json | 0 .../frameworks/{broken => _cases}/parent3.php | 0 .../parent3.php.expected.json | 16 +++--- .../{broken => _cases}/propertyName1.php | 0 .../propertyName1.php.expected.json | 4 +- .../{broken => _cases}/propertyName2.php | 0 .../propertyName2.php.expected.json | 4 +- .../{broken => _cases}/returnType.php | 0 .../returnType.php.expected.json | 8 +-- .../scopedPropertyAccess.php | 0 .../scopedPropertyAccess.php.expected.json | 10 ++-- .../scopedPropertyAccess2.php | 0 .../scopedPropertyAccess2.php.expected.json | 4 +- .../scopedPropertyAccess3.php | 0 .../scopedPropertyAccess3.php.expected.json | 8 +-- .../scopedPropertyAccess4.php | 0 .../scopedPropertyAccess4.php.expected.json | 2 +- .../scopedPropertyAccess5.php | 0 .../scopedPropertyAccess5.php.expected.json | 12 ++-- .../frameworks/{broken => _cases}/self1.php | 0 .../self1.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/self2.php | 0 .../self2.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/self3.php | 0 .../self3.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/self4.php | 0 .../self4.php.expected.json | 14 ++--- .../frameworks/{broken => _cases}/self5.php | 0 .../self5.php.expected.json | 8 +-- .../frameworks/{broken => _cases}/static1.php | 0 .../static1.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/static2.php | 0 .../static2.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/static3.php | 0 .../static3.php.expected.json | 16 +++--- .../frameworks/{broken => _cases}/static4.php | 0 .../static4.php.expected.json | 10 ++-- .../{broken => _cases}/staticInArray.php | 0 .../staticInArray.php.expected.json | 0 .../{broken => _cases}/stringVariable.php | 0 .../stringVariable.php.expected.json | 6 +- .../testQualifiedNameOutsideOfNamespace.php | 0 ...edNameOutsideOfNamespace.php.expected.json | 4 +- .../verifyFqsenOnClassProperty.php | 0 ...rifyFqsenOnClassProperty.php.expected.json | 10 ++-- 137 files changed, 377 insertions(+), 274 deletions(-) rename validation/frameworks/{broken => _cases}/WithReturnTypehints.php (100%) rename validation/frameworks/{broken => _cases}/WithReturnTypehints.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/anonymousClassMembersShouldNotBeSymbols.php (100%) rename validation/frameworks/{broken => _cases}/anonymousClassMembersShouldNotBeSymbols.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/arrayValueShouldBeBoolean.php (100%) rename validation/frameworks/{broken => _cases}/arrayValueShouldBeBoolean.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/caseStatement1.php (100%) rename validation/frameworks/{broken => _cases}/caseStatement1.php.expected.json (79%) rename validation/frameworks/{broken => _cases}/classDefinition1.php (100%) rename validation/frameworks/{broken => _cases}/classDefinition1.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/classProperty1.php (100%) rename validation/frameworks/{broken => _cases}/classProperty1.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/constants.php (100%) rename validation/frameworks/{broken => _cases}/constants.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/constants2.php (100%) rename validation/frameworks/{broken => _cases}/constants2.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/constants3.php (100%) rename validation/frameworks/{broken => _cases}/constants3.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/constants4.php (100%) rename validation/frameworks/{broken => _cases}/constants4.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/constants5.php (100%) rename validation/frameworks/{broken => _cases}/constants5.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/constantsInFunctionParamDefault.php (100%) rename validation/frameworks/{broken => _cases}/constantsInFunctionParamDefault.php.expected.json (82%) rename validation/frameworks/{broken => _cases}/docBlocksOnNamespaceDefinition.php (100%) rename validation/frameworks/{broken => _cases}/docBlocksOnNamespaceDefinition.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/exceptions1.php (100%) rename validation/frameworks/{broken => _cases}/exceptions1.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/forLoopReference1.php (100%) rename validation/frameworks/{broken => _cases}/forLoopReference1.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/functionUse.php (100%) rename validation/frameworks/{broken => _cases}/functionUse.php.expected.json (65%) rename validation/frameworks/{broken => _cases}/functionUse2.php (100%) rename validation/frameworks/{broken => _cases}/functionUse2.php.expected.json (68%) rename validation/frameworks/{broken => _cases}/ifStatement1.php (100%) rename validation/frameworks/{broken => _cases}/ifStatement1.php.expected.json (79%) create mode 100644 validation/frameworks/_cases/interfaceProperty.php create mode 100644 validation/frameworks/_cases/interfaceProperty.php.expected.json rename validation/frameworks/{broken => _cases}/magicConstantsShouldBeGlobal.php (100%) rename validation/frameworks/{broken => _cases}/magicConstantsShouldBeGlobal.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/magicConsts.php (100%) rename validation/frameworks/{broken => _cases}/magicConsts.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/memberAccess1.php (100%) rename validation/frameworks/{broken => _cases}/memberAccess1.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/memberAccess2.php (100%) rename validation/frameworks/{broken => _cases}/memberAccess2.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/memberAccess3.php (100%) rename validation/frameworks/{broken => _cases}/memberAccess3.php.expected.json (78%) rename validation/frameworks/{broken => _cases}/memberAccess4.php (100%) rename validation/frameworks/{broken => _cases}/memberAccess4.php.expected.json (81%) rename validation/frameworks/{broken => _cases}/memberAccess5.php (100%) rename validation/frameworks/{broken => _cases}/memberAccess5.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/memberCall1.php (100%) rename validation/frameworks/{broken => _cases}/memberCall1.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/multipleNamespaces.php (100%) rename validation/frameworks/{broken => _cases}/multipleNamespaces.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/multiplePreceedingComments.php (100%) rename validation/frameworks/{broken => _cases}/multiplePreceedingComments.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/nameToken.php (100%) rename validation/frameworks/{broken => _cases}/nameToken.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/namespaces2.php (100%) rename validation/frameworks/{broken => _cases}/namespaces2.php.expected.json (74%) rename validation/frameworks/{broken => _cases}/namespaces3.php (100%) rename validation/frameworks/{broken => _cases}/namespaces3.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/namespaces4.php (100%) rename validation/frameworks/{broken => _cases}/namespaces4.php.expected.json (65%) rename validation/frameworks/{broken => _cases}/namespaces5.php (100%) rename validation/frameworks/{broken => _cases}/namespaces5.php.expected.json (73%) rename validation/frameworks/{broken => _cases}/namespaces6.php (100%) rename validation/frameworks/{broken => _cases}/namespaces6.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/namespaces7.php (100%) rename validation/frameworks/{broken => _cases}/namespaces7.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/namespaces8.php (100%) rename validation/frameworks/{broken => _cases}/namespaces8.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/namespaces9.php (100%) rename validation/frameworks/{broken => _cases}/namespaces9.php.expected.json (100%) create mode 100644 validation/frameworks/_cases/newStatic.php create mode 100644 validation/frameworks/_cases/newStatic.php.expected.json rename validation/frameworks/{broken => _cases}/objectCreation.php (100%) rename validation/frameworks/{broken => _cases}/objectCreation.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/objectCreation2.php (100%) rename validation/frameworks/{broken => _cases}/objectCreation2.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/objectCreation3.php (100%) rename validation/frameworks/{broken => _cases}/objectCreation3.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/param1.php (100%) rename validation/frameworks/{broken => _cases}/param1.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/parameterTypeResolution1.php (100%) rename validation/frameworks/{broken => _cases}/parameterTypeResolution1.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/parent1.php (100%) rename validation/frameworks/{broken => _cases}/parent1.php.expected.json (85%) rename validation/frameworks/{broken => _cases}/parent2.php (100%) rename validation/frameworks/{broken => _cases}/parent2.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/parent3.php (100%) rename validation/frameworks/{broken => _cases}/parent3.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/propertyName1.php (100%) rename validation/frameworks/{broken => _cases}/propertyName1.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/propertyName2.php (100%) rename validation/frameworks/{broken => _cases}/propertyName2.php.expected.json (87%) rename validation/frameworks/{broken => _cases}/returnType.php (100%) rename validation/frameworks/{broken => _cases}/returnType.php.expected.json (83%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess.php (100%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess.php.expected.json (82%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess2.php (100%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess2.php.expected.json (82%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess3.php (100%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess3.php.expected.json (81%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess4.php (100%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess4.php.expected.json (70%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess5.php (100%) rename validation/frameworks/{broken => _cases}/scopedPropertyAccess5.php.expected.json (79%) rename validation/frameworks/{broken => _cases}/self1.php (100%) rename validation/frameworks/{broken => _cases}/self1.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/self2.php (100%) rename validation/frameworks/{broken => _cases}/self2.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/self3.php (100%) rename validation/frameworks/{broken => _cases}/self3.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/self4.php (100%) rename validation/frameworks/{broken => _cases}/self4.php.expected.json (81%) rename validation/frameworks/{broken => _cases}/self5.php (100%) rename validation/frameworks/{broken => _cases}/self5.php.expected.json (86%) rename validation/frameworks/{broken => _cases}/static1.php (100%) rename validation/frameworks/{broken => _cases}/static1.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/static2.php (100%) rename validation/frameworks/{broken => _cases}/static2.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/static3.php (100%) rename validation/frameworks/{broken => _cases}/static3.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/static4.php (100%) rename validation/frameworks/{broken => _cases}/static4.php.expected.json (84%) rename validation/frameworks/{broken => _cases}/staticInArray.php (100%) rename validation/frameworks/{broken => _cases}/staticInArray.php.expected.json (100%) rename validation/frameworks/{broken => _cases}/stringVariable.php (100%) rename validation/frameworks/{broken => _cases}/stringVariable.php.expected.json (86%) rename validation/frameworks/{broken => _cases}/testQualifiedNameOutsideOfNamespace.php (100%) rename validation/frameworks/{broken => _cases}/testQualifiedNameOutsideOfNamespace.php.expected.json (81%) rename validation/frameworks/{broken => _cases}/verifyFqsenOnClassProperty.php (100%) rename validation/frameworks/{broken => _cases}/verifyFqsenOnClassProperty.php.expected.json (82%) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 5a31eecf..1b476951 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -29,7 +29,7 @@ public function frameworkErrorProvider() { $testProviderArray = array(); foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); - if ($frameworkName !== "broken") { + if ($frameworkName !== '_cases') { continue; } @@ -63,12 +63,21 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $expectedValues = $this->getExpectedTestValues($testCaseFile, $frameworkName, $fileContents); $actualValues = $this->getActualTestValues($testCaseFile, $frameworkName, $fileContents); - $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); - try { - $this->assertArraySubset((array)$expectedValues['references'], (array)$actualValues['references'], false, 'references don\'t match.'); + $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); + + try { + $this->assertArraySubset((array)$expectedValues['references'], (array)$actualValues['references'], false, 'references don\'t match.'); + } catch (\Throwable $e) { + $this->assertEquals((array)$expectedValues['references'], (array)$actualValues['references'], 'references don\'t match.'); + } } catch (\Throwable $e) { - $this->assertEquals((array)$expectedValues['references'], (array)$actualValues['references'], 'references don\'t match.'); + $outputFile = getExpectedValuesFile($testCaseFile); + if ($frameworkName === '_cases') { + file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT)); + } + + throw $e; } } @@ -82,7 +91,7 @@ private function getExpectedTestValues($filename, $frameworkName, $fileContents) global $parserKind; $parserKind = ParserKind::PHP_PARSER; - $outputFile = $filename . '.expected.json'; + $outputFile = getExpectedValuesFile($filename); if (file_exists($outputFile)) { return (array)json_decode(file_get_contents($outputFile)); } @@ -136,11 +145,6 @@ private function getActualTestValues($filename, $frameworkName, $fileContents): 'definitions' => json_decode(json_encode($actualDefs)) ); - $outputFile = $filename . '.expected.json'; - if ($frameworkName === 'broken') { - file_put_contents($outputFile, json_encode($refsAndDefs, JSON_PRETTY_PRINT)); - } - return $refsAndDefs; } @@ -194,4 +198,8 @@ private function filterSkippedReferences(&$references): void } } } +} + +function getExpectedValuesFile($testCaseFile): string { + return $testCaseFile . '.expected.json'; } \ No newline at end of file diff --git a/validation/frameworks/broken/WithReturnTypehints.php b/validation/frameworks/_cases/WithReturnTypehints.php similarity index 100% rename from validation/frameworks/broken/WithReturnTypehints.php rename to validation/frameworks/_cases/WithReturnTypehints.php diff --git a/validation/frameworks/broken/WithReturnTypehints.php.expected.json b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json similarity index 84% rename from validation/frameworks/broken/WithReturnTypehints.php.expected.json rename to validation/frameworks/_cases/WithReturnTypehints.php.expected.json index 0a3eb097..e1da9a4c 100644 --- a/validation/frameworks/broken/WithReturnTypehints.php.expected.json +++ b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json @@ -1,13 +1,13 @@ { "references": { "Fixtures\\Prophecy\\EmptyClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "Fixtures\\Prophecy", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" }, "containerName": "Fixtures" }, @@ -39,7 +39,7 @@ "name": "WithReturnTypehints", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy" }, @@ -56,7 +56,7 @@ "name": "getSelf", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -73,7 +73,7 @@ "name": "getName", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -90,7 +90,7 @@ "name": "getParent", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/WithReturnTypehints.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, diff --git a/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php similarity index 100% rename from validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php rename to validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php diff --git a/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json similarity index 84% rename from validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json rename to validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index dc579f95..88ed9309 100644 --- a/validation/frameworks/broken/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/anonymousClassMembersShouldNotBeSymbols.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/anonymousClassMembersShouldNotBeSymbols.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/arrayValueShouldBeBoolean.php b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php similarity index 100% rename from validation/frameworks/broken/arrayValueShouldBeBoolean.php rename to validation/frameworks/_cases/arrayValueShouldBeBoolean.php diff --git a/validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json similarity index 85% rename from validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json rename to validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json index 9faade7e..a6168d76 100644 --- a/validation/frameworks/broken/arrayValueShouldBeBoolean.php.expected.json +++ b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/arrayValueShouldBeBoolean.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/arrayValueShouldBeBoolean.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "foo", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/arrayValueShouldBeBoolean.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/arrayValueShouldBeBoolean.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/caseStatement1.php b/validation/frameworks/_cases/caseStatement1.php similarity index 100% rename from validation/frameworks/broken/caseStatement1.php rename to validation/frameworks/_cases/caseStatement1.php diff --git a/validation/frameworks/broken/caseStatement1.php.expected.json b/validation/frameworks/_cases/caseStatement1.php.expected.json similarity index 79% rename from validation/frameworks/broken/caseStatement1.php.expected.json rename to validation/frameworks/_cases/caseStatement1.php.expected.json index e8400af6..07fd68d4 100644 --- a/validation/frameworks/broken/caseStatement1.php.expected.json +++ b/validation/frameworks/_cases/caseStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" ], "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/caseStatement1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/classDefinition1.php b/validation/frameworks/_cases/classDefinition1.php similarity index 100% rename from validation/frameworks/broken/classDefinition1.php rename to validation/frameworks/_cases/classDefinition1.php diff --git a/validation/frameworks/broken/classDefinition1.php.expected.json b/validation/frameworks/_cases/classDefinition1.php.expected.json similarity index 83% rename from validation/frameworks/broken/classDefinition1.php.expected.json rename to validation/frameworks/_cases/classDefinition1.php.expected.json index c505348f..a0c0672d 100644 --- a/validation/frameworks/broken/classDefinition1.php.expected.json +++ b/validation/frameworks/_cases/classDefinition1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" ], "TestNamespace\\A->a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" }, "containerName": "TestNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classDefinition1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" }, "containerName": "TestNamespace\\A" }, diff --git a/validation/frameworks/broken/classProperty1.php b/validation/frameworks/_cases/classProperty1.php similarity index 100% rename from validation/frameworks/broken/classProperty1.php rename to validation/frameworks/_cases/classProperty1.php diff --git a/validation/frameworks/broken/classProperty1.php.expected.json b/validation/frameworks/_cases/classProperty1.php.expected.json similarity index 84% rename from validation/frameworks/broken/classProperty1.php.expected.json rename to validation/frameworks/_cases/classProperty1.php.expected.json index cce5b151..2088a930 100644 --- a/validation/frameworks/broken/classProperty1.php.expected.json +++ b/validation/frameworks/_cases/classProperty1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "SomeNamespace\\Goo": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" ], "SomeNamespace": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" }, "containerName": "TestNamespace" }, @@ -51,7 +51,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, @@ -68,7 +68,7 @@ "name": "testMethod", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/classProperty1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, diff --git a/validation/frameworks/broken/constants.php b/validation/frameworks/_cases/constants.php similarity index 100% rename from validation/frameworks/broken/constants.php rename to validation/frameworks/_cases/constants.php diff --git a/validation/frameworks/broken/constants.php.expected.json b/validation/frameworks/_cases/constants.php.expected.json similarity index 83% rename from validation/frameworks/broken/constants.php.expected.json rename to validation/frameworks/_cases/constants.php.expected.json index be3094d3..9106488e 100644 --- a/validation/frameworks/broken/constants.php.expected.json +++ b/validation/frameworks/_cases/constants.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" ], "BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/constants2.php b/validation/frameworks/_cases/constants2.php similarity index 100% rename from validation/frameworks/broken/constants2.php rename to validation/frameworks/_cases/constants2.php diff --git a/validation/frameworks/broken/constants2.php.expected.json b/validation/frameworks/_cases/constants2.php.expected.json similarity index 83% rename from validation/frameworks/broken/constants2.php.expected.json rename to validation/frameworks/_cases/constants2.php.expected.json index 1e35fd35..476a21c7 100644 --- a/validation/frameworks/broken/constants2.php.expected.json +++ b/validation/frameworks/_cases/constants2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" ], "BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/constants3.php b/validation/frameworks/_cases/constants3.php similarity index 100% rename from validation/frameworks/broken/constants3.php rename to validation/frameworks/_cases/constants3.php diff --git a/validation/frameworks/broken/constants3.php.expected.json b/validation/frameworks/_cases/constants3.php.expected.json similarity index 83% rename from validation/frameworks/broken/constants3.php.expected.json rename to validation/frameworks/_cases/constants3.php.expected.json index cba6091f..1f647e77 100644 --- a/validation/frameworks/broken/constants3.php.expected.json +++ b/validation/frameworks/_cases/constants3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\T_NEW": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" ], "T_NEW": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/constants4.php b/validation/frameworks/_cases/constants4.php similarity index 100% rename from validation/frameworks/broken/constants4.php rename to validation/frameworks/_cases/constants4.php diff --git a/validation/frameworks/broken/constants4.php.expected.json b/validation/frameworks/_cases/constants4.php.expected.json similarity index 83% rename from validation/frameworks/broken/constants4.php.expected.json rename to validation/frameworks/_cases/constants4.php.expected.json index 7585f03a..cb39ca11 100644 --- a/validation/frameworks/broken/constants4.php.expected.json +++ b/validation/frameworks/_cases/constants4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\HI": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" ], "HI": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/constants5.php b/validation/frameworks/_cases/constants5.php similarity index 100% rename from validation/frameworks/broken/constants5.php rename to validation/frameworks/_cases/constants5.php diff --git a/validation/frameworks/broken/constants5.php.expected.json b/validation/frameworks/_cases/constants5.php.expected.json similarity index 85% rename from validation/frameworks/broken/constants5.php.expected.json rename to validation/frameworks/_cases/constants5.php.expected.json index 3d5da35f..4eba3ad5 100644 --- a/validation/frameworks/broken/constants5.php.expected.json +++ b/validation/frameworks/_cases/constants5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\PHP_INT_MAX": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "Mbstring", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "MB_CASE_FOLD", "kind": 14, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constants5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" }, "containerName": "MyNamespace\\Mbstring" }, diff --git a/validation/frameworks/broken/constantsInFunctionParamDefault.php b/validation/frameworks/_cases/constantsInFunctionParamDefault.php similarity index 100% rename from validation/frameworks/broken/constantsInFunctionParamDefault.php rename to validation/frameworks/_cases/constantsInFunctionParamDefault.php diff --git a/validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json similarity index 82% rename from validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json rename to validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json index 15be3501..6bbd112c 100644 --- a/validation/frameworks/broken/constantsInFunctionParamDefault.php.expected.json +++ b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MY_CONSTANT": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 11, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/constantsInFunctionParamDefault.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php similarity index 100% rename from validation/frameworks/broken/docBlocksOnNamespaceDefinition.php rename to validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php diff --git a/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json similarity index 85% rename from validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json rename to validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json index e4660b70..8db10d33 100644 --- a/validation/frameworks/broken/docBlocksOnNamespaceDefinition.php.expected.json +++ b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/docBlocksOnNamespaceDefinition.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/docBlocksOnNamespaceDefinition.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/exceptions1.php b/validation/frameworks/_cases/exceptions1.php similarity index 100% rename from validation/frameworks/broken/exceptions1.php rename to validation/frameworks/_cases/exceptions1.php diff --git a/validation/frameworks/broken/exceptions1.php.expected.json b/validation/frameworks/_cases/exceptions1.php.expected.json similarity index 87% rename from validation/frameworks/broken/exceptions1.php.expected.json rename to validation/frameworks/_cases/exceptions1.php.expected.json index 1cf37fc5..783cb223 100644 --- a/validation/frameworks/broken/exceptions1.php.expected.json +++ b/validation/frameworks/_cases/exceptions1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/exceptions1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/exceptions1.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/forLoopReference1.php b/validation/frameworks/_cases/forLoopReference1.php similarity index 100% rename from validation/frameworks/broken/forLoopReference1.php rename to validation/frameworks/_cases/forLoopReference1.php diff --git a/validation/frameworks/broken/forLoopReference1.php.expected.json b/validation/frameworks/_cases/forLoopReference1.php.expected.json similarity index 100% rename from validation/frameworks/broken/forLoopReference1.php.expected.json rename to validation/frameworks/_cases/forLoopReference1.php.expected.json diff --git a/validation/frameworks/broken/functionUse.php b/validation/frameworks/_cases/functionUse.php similarity index 100% rename from validation/frameworks/broken/functionUse.php rename to validation/frameworks/_cases/functionUse.php diff --git a/validation/frameworks/broken/functionUse.php.expected.json b/validation/frameworks/_cases/functionUse.php.expected.json similarity index 65% rename from validation/frameworks/broken/functionUse.php.expected.json rename to validation/frameworks/_cases/functionUse.php.expected.json index 29c132e5..4d321386 100644 --- a/validation/frameworks/broken/functionUse.php.expected.json +++ b/validation/frameworks/_cases/functionUse.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse.php" ], "A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse.php" ] }, "definitions": [] diff --git a/validation/frameworks/broken/functionUse2.php b/validation/frameworks/_cases/functionUse2.php similarity index 100% rename from validation/frameworks/broken/functionUse2.php rename to validation/frameworks/_cases/functionUse2.php diff --git a/validation/frameworks/broken/functionUse2.php.expected.json b/validation/frameworks/_cases/functionUse2.php.expected.json similarity index 68% rename from validation/frameworks/broken/functionUse2.php.expected.json rename to validation/frameworks/_cases/functionUse2.php.expected.json index fa047e6d..127b34d9 100644 --- a/validation/frameworks/broken/functionUse2.php.expected.json +++ b/validation/frameworks/_cases/functionUse2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse2.php" ], "LanguageServer\\timeout()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/functionUse2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse2.php" ] }, "definitions": [] diff --git a/validation/frameworks/broken/ifStatement1.php b/validation/frameworks/_cases/ifStatement1.php similarity index 100% rename from validation/frameworks/broken/ifStatement1.php rename to validation/frameworks/_cases/ifStatement1.php diff --git a/validation/frameworks/broken/ifStatement1.php.expected.json b/validation/frameworks/_cases/ifStatement1.php.expected.json similarity index 79% rename from validation/frameworks/broken/ifStatement1.php.expected.json rename to validation/frameworks/_cases/ifStatement1.php.expected.json index 4e4a23fc..20ded823 100644 --- a/validation/frameworks/broken/ifStatement1.php.expected.json +++ b/validation/frameworks/_cases/ifStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" ], "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/ifStatement1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/interfaceProperty.php b/validation/frameworks/_cases/interfaceProperty.php new file mode 100644 index 00000000..96b5cc54 --- /dev/null +++ b/validation/frameworks/_cases/interfaceProperty.php @@ -0,0 +1,5 @@ +a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/memberAccess2.php b/validation/frameworks/_cases/memberAccess2.php similarity index 100% rename from validation/frameworks/broken/memberAccess2.php rename to validation/frameworks/_cases/memberAccess2.php diff --git a/validation/frameworks/broken/memberAccess2.php.expected.json b/validation/frameworks/_cases/memberAccess2.php.expected.json similarity index 83% rename from validation/frameworks/broken/memberAccess2.php.expected.json rename to validation/frameworks/_cases/memberAccess2.php.expected.json index c3b93350..bc5f135c 100644 --- a/validation/frameworks/broken/memberAccess2.php.expected.json +++ b/validation/frameworks/_cases/memberAccess2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" ], "MyNamespace\\a->a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/memberAccess3.php b/validation/frameworks/_cases/memberAccess3.php similarity index 100% rename from validation/frameworks/broken/memberAccess3.php rename to validation/frameworks/_cases/memberAccess3.php diff --git a/validation/frameworks/broken/memberAccess3.php.expected.json b/validation/frameworks/_cases/memberAccess3.php.expected.json similarity index 78% rename from validation/frameworks/broken/memberAccess3.php.expected.json rename to validation/frameworks/_cases/memberAccess3.php.expected.json index c9e83101..6af62238 100644 --- a/validation/frameworks/broken/memberAccess3.php.expected.json +++ b/validation/frameworks/_cases/memberAccess3.php.expected.json @@ -1,25 +1,25 @@ { "references": { "MyNamespace\\ClassLoader": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "Closure::bind()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "Closure": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "MyNamespace\\ClassLoader->prefixesPsr0": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ], "MyNamespace\\ClassLoader::class": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" }, "containerName": "" }, @@ -49,7 +49,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" }, "containerName": "MyNamespace" }, @@ -66,7 +66,7 @@ "name": "getInitializer", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/memberAccess4.php b/validation/frameworks/_cases/memberAccess4.php similarity index 100% rename from validation/frameworks/broken/memberAccess4.php rename to validation/frameworks/_cases/memberAccess4.php diff --git a/validation/frameworks/broken/memberAccess4.php.expected.json b/validation/frameworks/_cases/memberAccess4.php.expected.json similarity index 81% rename from validation/frameworks/broken/memberAccess4.php.expected.json rename to validation/frameworks/_cases/memberAccess4.php.expected.json index e2352a71..31b7d6b6 100644 --- a/validation/frameworks/broken/memberAccess4.php.expected.json +++ b/validation/frameworks/_cases/memberAccess4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace\\Request::create()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" ], "MyNamespace\\Request": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" ], "MyNamespace\\Url->toString()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" ], "MyNamespace\\Url": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" }, "containerName": "MyNamespace" }, @@ -57,7 +57,7 @@ "name": "testRequest", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/memberAccess5.php b/validation/frameworks/_cases/memberAccess5.php similarity index 100% rename from validation/frameworks/broken/memberAccess5.php rename to validation/frameworks/_cases/memberAccess5.php diff --git a/validation/frameworks/broken/memberAccess5.php.expected.json b/validation/frameworks/_cases/memberAccess5.php.expected.json similarity index 87% rename from validation/frameworks/broken/memberAccess5.php.expected.json rename to validation/frameworks/_cases/memberAccess5.php.expected.json index ec0f7223..f58a6fc5 100644 --- a/validation/frameworks/broken/memberAccess5.php.expected.json +++ b/validation/frameworks/_cases/memberAccess5.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" }, "containerName": "MyNamespace" }, @@ -44,7 +44,7 @@ "name": "setUp", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberAccess5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/broken/memberCall1.php b/validation/frameworks/_cases/memberCall1.php similarity index 100% rename from validation/frameworks/broken/memberCall1.php rename to validation/frameworks/_cases/memberCall1.php diff --git a/validation/frameworks/broken/memberCall1.php.expected.json b/validation/frameworks/_cases/memberCall1.php.expected.json similarity index 83% rename from validation/frameworks/broken/memberCall1.php.expected.json rename to validation/frameworks/_cases/memberCall1.php.expected.json index b640d83c..6ce04a74 100644 --- a/validation/frameworks/broken/memberCall1.php.expected.json +++ b/validation/frameworks/_cases/memberCall1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\AccountInterface": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" ], "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" ], "MyNamespace\\AccountInterface->getAccount()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "setAccount", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/memberCall1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/broken/multipleNamespaces.php b/validation/frameworks/_cases/multipleNamespaces.php similarity index 100% rename from validation/frameworks/broken/multipleNamespaces.php rename to validation/frameworks/_cases/multipleNamespaces.php diff --git a/validation/frameworks/broken/multipleNamespaces.php.expected.json b/validation/frameworks/_cases/multipleNamespaces.php.expected.json similarity index 83% rename from validation/frameworks/broken/multipleNamespaces.php.expected.json rename to validation/frameworks/_cases/multipleNamespaces.php.expected.json index 274dd5bf..9cecc763 100644 --- a/validation/frameworks/broken/multipleNamespaces.php.expected.json +++ b/validation/frameworks/_cases/multipleNamespaces.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace2\\MyNamespace1\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" ], "MyNamespace2\\MyNamespace1": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" ], "MyNamespace2": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" ], "MyNamespace2\\A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "MyNamespace1" }, @@ -57,7 +57,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "MyNamespace1\\B" }, @@ -74,7 +74,7 @@ "name": "MyNamespace2", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "" }, @@ -93,7 +93,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "MyNamespace2" }, @@ -110,7 +110,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multipleNamespaces.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" }, "containerName": "MyNamespace2\\A" }, diff --git a/validation/frameworks/broken/multiplePreceedingComments.php b/validation/frameworks/_cases/multiplePreceedingComments.php similarity index 100% rename from validation/frameworks/broken/multiplePreceedingComments.php rename to validation/frameworks/_cases/multiplePreceedingComments.php diff --git a/validation/frameworks/broken/multiplePreceedingComments.php.expected.json b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json similarity index 85% rename from validation/frameworks/broken/multiplePreceedingComments.php.expected.json rename to validation/frameworks/_cases/multiplePreceedingComments.php.expected.json index 415b052b..05fb01f7 100644 --- a/validation/frameworks/broken/multiplePreceedingComments.php.expected.json +++ b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json @@ -10,7 +10,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multiplePreceedingComments.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multiplePreceedingComments.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "fn", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/multiplePreceedingComments.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multiplePreceedingComments.php" }, "containerName": "Foo" }, diff --git a/validation/frameworks/broken/nameToken.php b/validation/frameworks/_cases/nameToken.php similarity index 100% rename from validation/frameworks/broken/nameToken.php rename to validation/frameworks/_cases/nameToken.php diff --git a/validation/frameworks/broken/nameToken.php.expected.json b/validation/frameworks/_cases/nameToken.php.expected.json similarity index 87% rename from validation/frameworks/broken/nameToken.php.expected.json rename to validation/frameworks/_cases/nameToken.php.expected.json index 5513701d..404ad7e3 100644 --- a/validation/frameworks/broken/nameToken.php.expected.json +++ b/validation/frameworks/_cases/nameToken.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/nameToken.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/nameToken.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/nameToken.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/namespaces2.php b/validation/frameworks/_cases/namespaces2.php similarity index 100% rename from validation/frameworks/broken/namespaces2.php rename to validation/frameworks/_cases/namespaces2.php diff --git a/validation/frameworks/broken/namespaces2.php.expected.json b/validation/frameworks/_cases/namespaces2.php.expected.json similarity index 74% rename from validation/frameworks/broken/namespaces2.php.expected.json rename to validation/frameworks/_cases/namespaces2.php.expected.json index a3099501..0140af53 100644 --- a/validation/frameworks/broken/namespaces2.php.expected.json +++ b/validation/frameworks/_cases/namespaces2.php.expected.json @@ -1,16 +1,16 @@ { "references": { "NS1\\C": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" ], "NS1": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" ], "NS1\\I": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" ], "NS1\\T": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/namespaces3.php b/validation/frameworks/_cases/namespaces3.php similarity index 100% rename from validation/frameworks/broken/namespaces3.php rename to validation/frameworks/_cases/namespaces3.php diff --git a/validation/frameworks/broken/namespaces3.php.expected.json b/validation/frameworks/_cases/namespaces3.php.expected.json similarity index 100% rename from validation/frameworks/broken/namespaces3.php.expected.json rename to validation/frameworks/_cases/namespaces3.php.expected.json diff --git a/validation/frameworks/broken/namespaces4.php b/validation/frameworks/_cases/namespaces4.php similarity index 100% rename from validation/frameworks/broken/namespaces4.php rename to validation/frameworks/_cases/namespaces4.php diff --git a/validation/frameworks/broken/namespaces4.php.expected.json b/validation/frameworks/_cases/namespaces4.php.expected.json similarity index 65% rename from validation/frameworks/broken/namespaces4.php.expected.json rename to validation/frameworks/_cases/namespaces4.php.expected.json index 32f01cbc..374c22e2 100644 --- a/validation/frameworks/broken/namespaces4.php.expected.json +++ b/validation/frameworks/_cases/namespaces4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "a\\b": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces4.php" ], "a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces4.php" ] }, "definitions": [] diff --git a/validation/frameworks/broken/namespaces5.php b/validation/frameworks/_cases/namespaces5.php similarity index 100% rename from validation/frameworks/broken/namespaces5.php rename to validation/frameworks/_cases/namespaces5.php diff --git a/validation/frameworks/broken/namespaces5.php.expected.json b/validation/frameworks/_cases/namespaces5.php.expected.json similarity index 73% rename from validation/frameworks/broken/namespaces5.php.expected.json rename to validation/frameworks/_cases/namespaces5.php.expected.json index 95e8f513..346b5281 100644 --- a/validation/frameworks/broken/namespaces5.php.expected.json +++ b/validation/frameworks/_cases/namespaces5.php.expected.json @@ -1,25 +1,25 @@ { "references": { "LanguageServer\\Protocol": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer\\Protocol\\TextDocumentIdentifier": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer\\Protocol\\Position": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer\\Protocol\\ReferenceContext": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer\\Protocol\\Location": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ], "LanguageServer\\Protocol\\Range": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "B", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/namespaces6.php b/validation/frameworks/_cases/namespaces6.php similarity index 100% rename from validation/frameworks/broken/namespaces6.php rename to validation/frameworks/_cases/namespaces6.php diff --git a/validation/frameworks/broken/namespaces6.php.expected.json b/validation/frameworks/_cases/namespaces6.php.expected.json similarity index 87% rename from validation/frameworks/broken/namespaces6.php.expected.json rename to validation/frameworks/_cases/namespaces6.php.expected.json index ff214a78..25e100c2 100644 --- a/validation/frameworks/broken/namespaces6.php.expected.json +++ b/validation/frameworks/_cases/namespaces6.php.expected.json @@ -10,7 +10,7 @@ "name": "A\\B", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces6.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces6.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/namespaces7.php b/validation/frameworks/_cases/namespaces7.php similarity index 100% rename from validation/frameworks/broken/namespaces7.php rename to validation/frameworks/_cases/namespaces7.php diff --git a/validation/frameworks/broken/namespaces7.php.expected.json b/validation/frameworks/_cases/namespaces7.php.expected.json similarity index 100% rename from validation/frameworks/broken/namespaces7.php.expected.json rename to validation/frameworks/_cases/namespaces7.php.expected.json diff --git a/validation/frameworks/broken/namespaces8.php b/validation/frameworks/_cases/namespaces8.php similarity index 100% rename from validation/frameworks/broken/namespaces8.php rename to validation/frameworks/_cases/namespaces8.php diff --git a/validation/frameworks/broken/namespaces8.php.expected.json b/validation/frameworks/_cases/namespaces8.php.expected.json similarity index 83% rename from validation/frameworks/broken/namespaces8.php.expected.json rename to validation/frameworks/_cases/namespaces8.php.expected.json index 3538793c..bccea586 100644 --- a/validation/frameworks/broken/namespaces8.php.expected.json +++ b/validation/frameworks/_cases/namespaces8.php.expected.json @@ -1,7 +1,7 @@ { "references": { "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces8.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces8.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "LanguageServer\\Tests\\Utils", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces8.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces8.php" }, "containerName": "LanguageServer\\Tests" }, diff --git a/validation/frameworks/broken/namespaces9.php b/validation/frameworks/_cases/namespaces9.php similarity index 100% rename from validation/frameworks/broken/namespaces9.php rename to validation/frameworks/_cases/namespaces9.php diff --git a/validation/frameworks/broken/namespaces9.php.expected.json b/validation/frameworks/_cases/namespaces9.php.expected.json similarity index 100% rename from validation/frameworks/broken/namespaces9.php.expected.json rename to validation/frameworks/_cases/namespaces9.php.expected.json diff --git a/validation/frameworks/_cases/newStatic.php b/validation/frameworks/_cases/newStatic.php new file mode 100644 index 00000000..aa6a7af2 --- /dev/null +++ b/validation/frameworks/_cases/newStatic.php @@ -0,0 +1,12 @@ +foo(); + } + + private function foo() { + } +} \ No newline at end of file diff --git a/validation/frameworks/_cases/newStatic.php.expected.json b/validation/frameworks/_cases/newStatic.php.expected.json new file mode 100644 index 00000000..19a09b62 --- /dev/null +++ b/validation/frameworks/_cases/newStatic.php.expected.json @@ -0,0 +1,56 @@ +{ + "references": [], + "definitions": { + "NewStatic": { + "extends": [], + "isGlobal": true, + "isStatic": false, + "canBeInstantiated": true, + "symbolInformation": { + "name": "NewStatic", + "kind": 5, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/newStatic.php" + }, + "containerName": "" + }, + "type__class": "LanguageServer\\Tests\\ValidationTest", + "type": null, + "documentation": null + }, + "NewStatic::main()": { + "extends": [], + "isGlobal": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "main", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/newStatic.php" + }, + "containerName": "NewStatic" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + }, + "NewStatic->foo()": { + "extends": [], + "isGlobal": false, + "isStatic": false, + "canBeInstantiated": false, + "symbolInformation": { + "name": "foo", + "kind": 6, + "location": { + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/newStatic.php" + }, + "containerName": "NewStatic" + }, + "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", + "type": {}, + "documentation": null + } + } +} \ No newline at end of file diff --git a/validation/frameworks/broken/objectCreation.php b/validation/frameworks/_cases/objectCreation.php similarity index 100% rename from validation/frameworks/broken/objectCreation.php rename to validation/frameworks/_cases/objectCreation.php diff --git a/validation/frameworks/broken/objectCreation.php.expected.json b/validation/frameworks/_cases/objectCreation.php.expected.json similarity index 85% rename from validation/frameworks/broken/objectCreation.php.expected.json rename to validation/frameworks/_cases/objectCreation.php.expected.json index a23931a2..b941c2e2 100644 --- a/validation/frameworks/broken/objectCreation.php.expected.json +++ b/validation/frameworks/_cases/objectCreation.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->inline_diff_renderer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/objectCreation2.php b/validation/frameworks/_cases/objectCreation2.php similarity index 100% rename from validation/frameworks/broken/objectCreation2.php rename to validation/frameworks/_cases/objectCreation2.php diff --git a/validation/frameworks/broken/objectCreation2.php.expected.json b/validation/frameworks/_cases/objectCreation2.php.expected.json similarity index 84% rename from validation/frameworks/broken/objectCreation2.php.expected.json rename to validation/frameworks/_cases/objectCreation2.php.expected.json index c2226fb1..6f187e16 100644 --- a/validation/frameworks/broken/objectCreation2.php.expected.json +++ b/validation/frameworks/_cases/objectCreation2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B->hi()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" ], "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -68,7 +68,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/objectCreation3.php b/validation/frameworks/_cases/objectCreation3.php similarity index 100% rename from validation/frameworks/broken/objectCreation3.php rename to validation/frameworks/_cases/objectCreation3.php diff --git a/validation/frameworks/broken/objectCreation3.php.expected.json b/validation/frameworks/_cases/objectCreation3.php.expected.json similarity index 83% rename from validation/frameworks/broken/objectCreation3.php.expected.json rename to validation/frameworks/_cases/objectCreation3.php.expected.json index 9c2d7530..662e8aa8 100644 --- a/validation/frameworks/broken/objectCreation3.php.expected.json +++ b/validation/frameworks/_cases/objectCreation3.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A->args": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/objectCreation3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/param1.php b/validation/frameworks/_cases/param1.php similarity index 100% rename from validation/frameworks/broken/param1.php rename to validation/frameworks/_cases/param1.php diff --git a/validation/frameworks/broken/param1.php.expected.json b/validation/frameworks/_cases/param1.php.expected.json similarity index 85% rename from validation/frameworks/broken/param1.php.expected.json rename to validation/frameworks/_cases/param1.php.expected.json index 0d4fb71f..a976b705 100644 --- a/validation/frameworks/broken/param1.php.expected.json +++ b/validation/frameworks/_cases/param1.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\Hi": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "init", "kind": 12, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/param1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" }, "containerName": "MyNamespace" }, diff --git a/validation/frameworks/broken/parameterTypeResolution1.php b/validation/frameworks/_cases/parameterTypeResolution1.php similarity index 100% rename from validation/frameworks/broken/parameterTypeResolution1.php rename to validation/frameworks/_cases/parameterTypeResolution1.php diff --git a/validation/frameworks/broken/parameterTypeResolution1.php.expected.json b/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json similarity index 100% rename from validation/frameworks/broken/parameterTypeResolution1.php.expected.json rename to validation/frameworks/_cases/parameterTypeResolution1.php.expected.json diff --git a/validation/frameworks/broken/parent1.php b/validation/frameworks/_cases/parent1.php similarity index 100% rename from validation/frameworks/broken/parent1.php rename to validation/frameworks/_cases/parent1.php diff --git a/validation/frameworks/broken/parent1.php.expected.json b/validation/frameworks/_cases/parent1.php.expected.json similarity index 85% rename from validation/frameworks/broken/parent1.php.expected.json rename to validation/frameworks/_cases/parent1.php.expected.json index 0bd3113f..64400b1a 100644 --- a/validation/frameworks/broken/parent1.php.expected.json +++ b/validation/frameworks/_cases/parent1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" }, "containerName": "MyNamespace\\B" }, @@ -70,7 +70,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/parent2.php b/validation/frameworks/_cases/parent2.php similarity index 100% rename from validation/frameworks/broken/parent2.php rename to validation/frameworks/_cases/parent2.php diff --git a/validation/frameworks/broken/parent2.php.expected.json b/validation/frameworks/_cases/parent2.php.expected.json similarity index 100% rename from validation/frameworks/broken/parent2.php.expected.json rename to validation/frameworks/_cases/parent2.php.expected.json diff --git a/validation/frameworks/broken/parent3.php b/validation/frameworks/_cases/parent3.php similarity index 100% rename from validation/frameworks/broken/parent3.php rename to validation/frameworks/_cases/parent3.php diff --git a/validation/frameworks/broken/parent3.php.expected.json b/validation/frameworks/_cases/parent3.php.expected.json similarity index 84% rename from validation/frameworks/broken/parent3.php.expected.json rename to validation/frameworks/_cases/parent3.php.expected.json index 1acf7ab6..f844c06e 100644 --- a/validation/frameworks/broken/parent3.php.expected.json +++ b/validation/frameworks/_cases/parent3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" ], "MyNamespace\\B->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/propertyName1.php b/validation/frameworks/_cases/propertyName1.php similarity index 100% rename from validation/frameworks/broken/propertyName1.php rename to validation/frameworks/_cases/propertyName1.php diff --git a/validation/frameworks/broken/propertyName1.php.expected.json b/validation/frameworks/_cases/propertyName1.php.expected.json similarity index 87% rename from validation/frameworks/broken/propertyName1.php.expected.json rename to validation/frameworks/_cases/propertyName1.php.expected.json index 24b16fe2..1f46f135 100644 --- a/validation/frameworks/broken/propertyName1.php.expected.json +++ b/validation/frameworks/_cases/propertyName1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName1.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName1.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/broken/propertyName2.php b/validation/frameworks/_cases/propertyName2.php similarity index 100% rename from validation/frameworks/broken/propertyName2.php rename to validation/frameworks/_cases/propertyName2.php diff --git a/validation/frameworks/broken/propertyName2.php.expected.json b/validation/frameworks/_cases/propertyName2.php.expected.json similarity index 87% rename from validation/frameworks/broken/propertyName2.php.expected.json rename to validation/frameworks/_cases/propertyName2.php.expected.json index 59db6fce..ab81b736 100644 --- a/validation/frameworks/broken/propertyName2.php.expected.json +++ b/validation/frameworks/_cases/propertyName2.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName2.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/propertyName2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName2.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/broken/returnType.php b/validation/frameworks/_cases/returnType.php similarity index 100% rename from validation/frameworks/broken/returnType.php rename to validation/frameworks/_cases/returnType.php diff --git a/validation/frameworks/broken/returnType.php.expected.json b/validation/frameworks/_cases/returnType.php.expected.json similarity index 83% rename from validation/frameworks/broken/returnType.php.expected.json rename to validation/frameworks/_cases/returnType.php.expected.json index 45831dc6..479b915b 100644 --- a/validation/frameworks/broken/returnType.php.expected.json +++ b/validation/frameworks/_cases/returnType.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\TestClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" ], "TestNamespace\\TestClass2": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "whatever", "kind": 12, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/returnType.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" }, "containerName": "TestNamespace" }, diff --git a/validation/frameworks/broken/scopedPropertyAccess.php b/validation/frameworks/_cases/scopedPropertyAccess.php similarity index 100% rename from validation/frameworks/broken/scopedPropertyAccess.php rename to validation/frameworks/_cases/scopedPropertyAccess.php diff --git a/validation/frameworks/broken/scopedPropertyAccess.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json similarity index 82% rename from validation/frameworks/broken/scopedPropertyAccess.php.expected.json rename to validation/frameworks/_cases/scopedPropertyAccess.php.expected.json index f30d2359..6a4770c1 100644 --- a/validation/frameworks/broken/scopedPropertyAccess.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A::a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" ], "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/scopedPropertyAccess2.php b/validation/frameworks/_cases/scopedPropertyAccess2.php similarity index 100% rename from validation/frameworks/broken/scopedPropertyAccess2.php rename to validation/frameworks/_cases/scopedPropertyAccess2.php diff --git a/validation/frameworks/broken/scopedPropertyAccess2.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json similarity index 82% rename from validation/frameworks/broken/scopedPropertyAccess2.php.expected.json rename to validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json index 93d41ae4..5e2faa2e 100644 --- a/validation/frameworks/broken/scopedPropertyAccess2.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess2.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess2.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/scopedPropertyAccess3.php b/validation/frameworks/_cases/scopedPropertyAccess3.php similarity index 100% rename from validation/frameworks/broken/scopedPropertyAccess3.php rename to validation/frameworks/_cases/scopedPropertyAccess3.php diff --git a/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json similarity index 81% rename from validation/frameworks/broken/scopedPropertyAccess3.php.expected.json rename to validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json index d64eb892..169587b8 100644 --- a/validation/frameworks/broken/scopedPropertyAccess3.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" ], "A::$a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "a", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/broken/scopedPropertyAccess4.php b/validation/frameworks/_cases/scopedPropertyAccess4.php similarity index 100% rename from validation/frameworks/broken/scopedPropertyAccess4.php rename to validation/frameworks/_cases/scopedPropertyAccess4.php diff --git a/validation/frameworks/broken/scopedPropertyAccess4.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json similarity index 70% rename from validation/frameworks/broken/scopedPropertyAccess4.php.expected.json rename to validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json index 015a08cc..e8cb3e42 100644 --- a/validation/frameworks/broken/scopedPropertyAccess4.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess4.php" ] }, "definitions": [] diff --git a/validation/frameworks/broken/scopedPropertyAccess5.php b/validation/frameworks/_cases/scopedPropertyAccess5.php similarity index 100% rename from validation/frameworks/broken/scopedPropertyAccess5.php rename to validation/frameworks/_cases/scopedPropertyAccess5.php diff --git a/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json similarity index 79% rename from validation/frameworks/broken/scopedPropertyAccess5.php.expected.json rename to validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json index 84d52c3b..0f72e44e 100644 --- a/validation/frameworks/broken/scopedPropertyAccess5.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json @@ -1,16 +1,16 @@ { "references": { "TestInterface": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" ], "TestClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" ], "TestClass::$testProperty": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" ], "TestClass::$staticTestProperty": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/scopedPropertyAccess5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" }, "containerName": "TestClass" }, diff --git a/validation/frameworks/broken/self1.php b/validation/frameworks/_cases/self1.php similarity index 100% rename from validation/frameworks/broken/self1.php rename to validation/frameworks/_cases/self1.php diff --git a/validation/frameworks/broken/self1.php.expected.json b/validation/frameworks/_cases/self1.php.expected.json similarity index 84% rename from validation/frameworks/broken/self1.php.expected.json rename to validation/frameworks/_cases/self1.php.expected.json index d1953fb8..571d579b 100644 --- a/validation/frameworks/broken/self1.php.expected.json +++ b/validation/frameworks/_cases/self1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/self2.php b/validation/frameworks/_cases/self2.php similarity index 100% rename from validation/frameworks/broken/self2.php rename to validation/frameworks/_cases/self2.php diff --git a/validation/frameworks/broken/self2.php.expected.json b/validation/frameworks/_cases/self2.php.expected.json similarity index 84% rename from validation/frameworks/broken/self2.php.expected.json rename to validation/frameworks/_cases/self2.php.expected.json index 03b72d68..3780e2f2 100644 --- a/validation/frameworks/broken/self2.php.expected.json +++ b/validation/frameworks/_cases/self2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/self3.php b/validation/frameworks/_cases/self3.php similarity index 100% rename from validation/frameworks/broken/self3.php rename to validation/frameworks/_cases/self3.php diff --git a/validation/frameworks/broken/self3.php.expected.json b/validation/frameworks/_cases/self3.php.expected.json similarity index 84% rename from validation/frameworks/broken/self3.php.expected.json rename to validation/frameworks/_cases/self3.php.expected.json index e2ea5f2a..99425908 100644 --- a/validation/frameworks/broken/self3.php.expected.json +++ b/validation/frameworks/_cases/self3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" ], "MyNamespace\\A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/self4.php b/validation/frameworks/_cases/self4.php similarity index 100% rename from validation/frameworks/broken/self4.php rename to validation/frameworks/_cases/self4.php diff --git a/validation/frameworks/broken/self4.php.expected.json b/validation/frameworks/_cases/self4.php.expected.json similarity index 81% rename from validation/frameworks/broken/self4.php.expected.json rename to validation/frameworks/_cases/self4.php.expected.json index e9665baa..d99b3440 100644 --- a/validation/frameworks/broken/self4.php.expected.json +++ b/validation/frameworks/_cases/self4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" ], "MyNamespace\\A->addTestFile()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" ], "MyNamespace\\DS": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" ], "DS": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" }, "containerName": "MyNamespace" }, @@ -57,7 +57,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/self5.php b/validation/frameworks/_cases/self5.php similarity index 100% rename from validation/frameworks/broken/self5.php rename to validation/frameworks/_cases/self5.php diff --git a/validation/frameworks/broken/self5.php.expected.json b/validation/frameworks/_cases/self5.php.expected.json similarity index 86% rename from validation/frameworks/broken/self5.php.expected.json rename to validation/frameworks/_cases/self5.php.expected.json index 5758d939..bd151dc4 100644 --- a/validation/frameworks/broken/self5.php.expected.json +++ b/validation/frameworks/_cases/self5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->assertTrue()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "typesProvider", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/self5.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/static1.php b/validation/frameworks/_cases/static1.php similarity index 100% rename from validation/frameworks/broken/static1.php rename to validation/frameworks/_cases/static1.php diff --git a/validation/frameworks/broken/static1.php.expected.json b/validation/frameworks/_cases/static1.php.expected.json similarity index 84% rename from validation/frameworks/broken/static1.php.expected.json rename to validation/frameworks/_cases/static1.php.expected.json index 66591b2b..8c30d6b0 100644 --- a/validation/frameworks/broken/static1.php.expected.json +++ b/validation/frameworks/_cases/static1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static1.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/static2.php b/validation/frameworks/_cases/static2.php similarity index 100% rename from validation/frameworks/broken/static2.php rename to validation/frameworks/_cases/static2.php diff --git a/validation/frameworks/broken/static2.php.expected.json b/validation/frameworks/_cases/static2.php.expected.json similarity index 84% rename from validation/frameworks/broken/static2.php.expected.json rename to validation/frameworks/_cases/static2.php.expected.json index 363a5865..e1e5ed5f 100644 --- a/validation/frameworks/broken/static2.php.expected.json +++ b/validation/frameworks/_cases/static2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static2.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/static3.php b/validation/frameworks/_cases/static3.php similarity index 100% rename from validation/frameworks/broken/static3.php rename to validation/frameworks/_cases/static3.php diff --git a/validation/frameworks/broken/static3.php.expected.json b/validation/frameworks/_cases/static3.php.expected.json similarity index 84% rename from validation/frameworks/broken/static3.php.expected.json rename to validation/frameworks/_cases/static3.php.expected.json index 3a821727..2ecdc991 100644 --- a/validation/frameworks/broken/static3.php.expected.json +++ b/validation/frameworks/_cases/static3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" ], "MyNamespace\\b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" ], "b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static3.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/static4.php b/validation/frameworks/_cases/static4.php similarity index 100% rename from validation/frameworks/broken/static4.php rename to validation/frameworks/_cases/static4.php diff --git a/validation/frameworks/broken/static4.php.expected.json b/validation/frameworks/_cases/static4.php.expected.json similarity index 84% rename from validation/frameworks/broken/static4.php.expected.json rename to validation/frameworks/_cases/static4.php.expected.json index cab56e32..186cbe58 100644 --- a/validation/frameworks/broken/static4.php.expected.json +++ b/validation/frameworks/_cases/static4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" }, "containerName": "MyNamespace" }, @@ -53,7 +53,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/static4.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/broken/staticInArray.php b/validation/frameworks/_cases/staticInArray.php similarity index 100% rename from validation/frameworks/broken/staticInArray.php rename to validation/frameworks/_cases/staticInArray.php diff --git a/validation/frameworks/broken/staticInArray.php.expected.json b/validation/frameworks/_cases/staticInArray.php.expected.json similarity index 100% rename from validation/frameworks/broken/staticInArray.php.expected.json rename to validation/frameworks/_cases/staticInArray.php.expected.json diff --git a/validation/frameworks/broken/stringVariable.php b/validation/frameworks/_cases/stringVariable.php similarity index 100% rename from validation/frameworks/broken/stringVariable.php rename to validation/frameworks/_cases/stringVariable.php diff --git a/validation/frameworks/broken/stringVariable.php.expected.json b/validation/frameworks/_cases/stringVariable.php.expected.json similarity index 86% rename from validation/frameworks/broken/stringVariable.php.expected.json rename to validation/frameworks/_cases/stringVariable.php.expected.json index 79119343..129ac637 100644 --- a/validation/frameworks/broken/stringVariable.php.expected.json +++ b/validation/frameworks/_cases/stringVariable.php.expected.json @@ -10,7 +10,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "hi", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" }, "containerName": "B" }, @@ -44,7 +44,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/stringVariable.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" }, "containerName": "B" }, diff --git a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php similarity index 100% rename from validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php rename to validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php diff --git a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json similarity index 81% rename from validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json rename to validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json index 331b893d..c5c303e3 100644 --- a/validation/frameworks/broken/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -1,7 +1,7 @@ { "references": { "NameOutsideOfNamespace": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/testQualifiedNameOutsideOfNamespace.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/testQualifiedNameOutsideOfNamespace.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "SomeNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/testQualifiedNameOutsideOfNamespace.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/testQualifiedNameOutsideOfNamespace.php" }, "containerName": "" }, diff --git a/validation/frameworks/broken/verifyFqsenOnClassProperty.php b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php similarity index 100% rename from validation/frameworks/broken/verifyFqsenOnClassProperty.php rename to validation/frameworks/_cases/verifyFqsenOnClassProperty.php diff --git a/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json similarity index 82% rename from validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json rename to validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json index b54f1562..338a1939 100644 --- a/validation/frameworks/broken/verifyFqsenOnClassProperty.php.expected.json +++ b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json @@ -1,10 +1,10 @@ { "references": { "CURLAUTH_BASIC": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" ], "Foo->bar": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "bar", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, @@ -51,7 +51,7 @@ "name": "foo", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/verifyFqsenOnClassProperty.php" + "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, From bb94aeac7edbc72cb3ac7c333c6d5eb7d6fadaf9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 May 2017 22:40:01 -0700 Subject: [PATCH 078/149] Add newStatic.php to skipped.json --- tests/Validation/skipped.json | 3 ++- validation/frameworks/_cases/newStatic.php.expected.json | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/Validation/skipped.json b/tests/Validation/skipped.json index 901c77a7..5e223ef5 100644 --- a/tests/Validation/skipped.json +++ b/tests/Validation/skipped.json @@ -2,5 +2,6 @@ "forLoopReference1.php", "namespaces3.php", "parameterTypeResolution1.php", - "parent2.php" + "parent2.php", + "newStatic.php" ] \ No newline at end of file diff --git a/validation/frameworks/_cases/newStatic.php.expected.json b/validation/frameworks/_cases/newStatic.php.expected.json index 19a09b62..cafe1141 100644 --- a/validation/frameworks/_cases/newStatic.php.expected.json +++ b/validation/frameworks/_cases/newStatic.php.expected.json @@ -1,5 +1,12 @@ { - "references": [], + "references": { + "static": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/newStatic.php" + ], + "NewStatic->foo()": [ + "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/newStatic.php" + ] + }, "definitions": { "NewStatic": { "extends": [], From 30da705a88eb6e5bd2f9f79a27d3f0a5808ce653 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 2 May 2017 10:52:37 -0700 Subject: [PATCH 079/149] Fix codesniffer reference --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4856aa53..8a1d04cb 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "phpdocumentor/reflection-docblock": "^3.0", "sabre/event": "^5.0", "felixfbecker/advanced-json-rpc": "^2.0", - "squizlabs/php_codesniffer" : "^3.0", + "squizlabs/php_codesniffer" : "3.0.0RC3", "netresearch/jsonmapper": "^1.0", "webmozart/path-util": "^2.3", "webmozart/glob": "^4.1", From 31441f4b7ed96d5c648a55eaa75cf69244e82883 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 2 May 2017 11:04:44 -0700 Subject: [PATCH 080/149] Remove ParserResourceFactory and DefinitionResolverInterface (leave original DefinitionResolver for now, for more testing) --- Performance.php | 14 +-- src/CompletionProvider.php | 8 +- src/ComposerScripts.php | 4 +- src/DefinitionResolver.php | 2 +- src/DefinitionResolverInterface.php | 86 ------------------- src/LanguageServer.php | 11 +-- src/NodeVisitor/DefinitionCollector.php | 5 +- src/NodeVisitor/ReferencesCollector.php | 11 +-- src/ParserResourceFactory.php | 45 ---------- src/PhpDocument.php | 33 ++++--- src/PhpDocumentLoader.php | 11 +-- src/Server/TextDocument.php | 37 +++----- src/TolerantDefinitionResolver.php | 54 ++++++------ tests/NodeVisitor/DefinitionCollectorTest.php | 8 +- tests/PhpDocumentLoaderTest.php | 18 ++-- tests/PhpDocumentTest.php | 23 ++--- tests/Server/ServerTestCase.php | 9 +- tests/Server/TextDocument/CompletionTest.php | 7 +- .../Definition/GlobalFallbackTest.php | 7 +- tests/Server/TextDocument/DidChangeTest.php | 9 +- tests/Server/TextDocument/DidCloseTest.php | 7 +- tests/Server/TextDocument/FormattingTest.php | 5 +- tests/Server/TextDocument/ParseErrorsTest.php | 6 +- .../References/GlobalFallbackTest.php | 15 ++-- tests/Validation/ValidationTest.php | 63 +++----------- 25 files changed, 143 insertions(+), 355 deletions(-) delete mode 100644 src/DefinitionResolverInterface.php delete mode 100644 src/ParserResourceFactory.php diff --git a/Performance.php b/Performance.php index c1103000..8ed002fb 100644 --- a/Performance.php +++ b/Performance.php @@ -6,16 +6,12 @@ use Exception; use LanguageServer\Index\Index; use LanguageServer\ParserKind; -use LanguageServer\ParserResourceFactory; use LanguageServer\PhpDocument; +use LanguageServer\TolerantDefinitionResolver; +use Microsoft\PhpParser as Tolerant; use phpDocumentor\Reflection\DocBlockFactory; -use PHPUnit\Framework\TestCase; -use LanguageServer\ClientHandler; -use LanguageServer\Protocol\Message; -use AdvancedJsonRpc; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; -use Sabre\Event\Loop; $totalSize = 0; @@ -60,11 +56,9 @@ $index = new Index; $maxRecursion = []; $definitions = []; - global $parserKind; - $parserKind = $kind; - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - $parser = ParserResourceFactory::getParser(); + $definitionResolver = new TolerantDefinitionResolver($index); + $parser = new Tolerant\Parser(); try { $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 58531e28..d19c6bf5 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -89,7 +89,7 @@ class CompletionProvider ]; /** - * @var DefinitionResolverInterface + * @var TolerantDefinitionResolver */ private $definitionResolver; @@ -104,10 +104,10 @@ class CompletionProvider private $index; /** - * @param DefinitionResolverInterface $definitionResolver + * @param TolerantDefinitionResolver $definitionResolver * @param ReadableIndex $index */ - public function __construct(DefinitionResolverInterface $definitionResolver, ReadableIndex $index) + public function __construct(TolerantDefinitionResolver $definitionResolver, ReadableIndex $index) { $this->definitionResolver = $definitionResolver; $this->index = $index; @@ -124,7 +124,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi { // This can be made much more performant if the tree follows specific invariants. $node = $doc->getNodeAtPosition($pos); - + if($node !== null && ($offset = $pos->toOffset($node->getFileContents())) > $node->getEndPosition() && $node->parent->getLastChild() instanceof Tolerant\MissingToken) { diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index 6109fb21..086a0101 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -30,8 +30,8 @@ public static function parseStubs() $finder = new FileSystemFilesFinder; $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); - $parser = ParserResourceFactory::getParser(); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $parser = Tolerant\Parser(); + $definitionResolver = new TolerantDefinitionResolver($index); $stubsLocation = null; foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 3d3a360e..3bc7b0c5 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -9,7 +9,7 @@ use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; -class DefinitionResolver implements DefinitionResolverInterface +class DefinitionResolver { /** * @var \LanguageServer\Index\ReadableIndex diff --git a/src/DefinitionResolverInterface.php b/src/DefinitionResolverInterface.php deleted file mode 100644 index 767f4e0e..00000000 --- a/src/DefinitionResolverInterface.php +++ /dev/null @@ -1,86 +0,0 @@ -globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex); // The DefinitionResolver should look in stubs, the project source and dependencies - $this->definitionResolver = ParserResourceFactory::getDefinitionResolver($this->globalIndex); + $this->definitionResolver = new TolerantDefinitionResolver($this->globalIndex); $this->documentLoader = new PhpDocumentLoader( $this->contentRetriever, diff --git a/src/NodeVisitor/DefinitionCollector.php b/src/NodeVisitor/DefinitionCollector.php index 7579ce9a..37eeebe0 100644 --- a/src/NodeVisitor/DefinitionCollector.php +++ b/src/NodeVisitor/DefinitionCollector.php @@ -5,9 +5,8 @@ use PhpParser\{NodeVisitorAbstract, Node}; use LanguageServer\{ - Definition, DefinitionResolver, DefinitionResolverInterface, FqnUtilities + Definition, FqnUtilities, TolerantDefinitionResolver }; -use LanguageServer\Protocol\SymbolInformation; /** * Collects definitions of classes, interfaces, traits, methods, properties and constants @@ -31,7 +30,7 @@ class DefinitionCollector extends NodeVisitorAbstract private $definitionResolver; - public function __construct(DefinitionResolverInterface $definitionResolver) + public function __construct(TolerantDefinitionResolver $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/NodeVisitor/ReferencesCollector.php b/src/NodeVisitor/ReferencesCollector.php index d586b5b3..a64e6330 100644 --- a/src/NodeVisitor/ReferencesCollector.php +++ b/src/NodeVisitor/ReferencesCollector.php @@ -4,8 +4,9 @@ namespace LanguageServer\NodeVisitor; use LanguageServer\DefinitionResolverInterface; -use PhpParser\{NodeVisitorAbstract, Node}; -use LanguageServer\DefinitionResolver; +use PhpParser\{ + Node, NodeVisitorAbstract +}; /** * Collects references to classes, interfaces, traits, methods, properties and constants @@ -21,14 +22,14 @@ class ReferencesCollector extends NodeVisitorAbstract public $nodes = []; /** - * @var DefinitionResolverInterface + * @var TolerantDefinitionResolver */ private $definitionResolver; /** - * @param DefinitionResolverInterface $definitionResolver The DefinitionResolver to resolve reference nodes to definitions + * @param TolerantDefinitionResolver $definitionResolver The definition resolver to resolve reference nodes to definitions */ - public function __construct(DefinitionResolverInterface $definitionResolver) + public function __construct(TolerantDefinitionResolver $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php deleted file mode 100644 index bd957d09..00000000 --- a/src/ParserResourceFactory.php +++ /dev/null @@ -1,45 +0,0 @@ -uri = $uri; $this->index = $index; @@ -161,7 +158,7 @@ public function updateContent(string $content) $this->definitions = null; $this->definitionNodes = null; - $treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); + $treeAnalyzer = new TolerantTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); $this->diagnostics = $treeAnalyzer->getDiagnostics(); @@ -170,7 +167,7 @@ public function updateContent(string $content) $this->definitionNodes = $treeAnalyzer->getDefinitionNodes(); $this->referenceNodes = $treeAnalyzer->getReferenceNodes(); - + foreach ($this->definitions as $fqn => $definition) { $this->index->setDefinition($fqn, $definition); } @@ -179,7 +176,7 @@ public function updateContent(string $content) foreach ($this->referenceNodes as $fqn => $nodes) { $this->index->addReferenceUri($fqn, $this->uri); } - + $this->stmts = $treeAnalyzer->getStmts(); } diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index 88ed5253..8f949430 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -48,24 +48,25 @@ class PhpDocumentLoader private $docBlockFactory; /** - * @var DefinitionResolverInterface + * @var TolerantDefinitionResolver */ private $definitionResolver; /** * @param ContentRetriever $contentRetriever - * @param ProjectIndex $project - * @param DefinitionResolverInterface $definitionResolver + * @param ProjectIndex $projectIndex + * @param TolerantDefinitionResolver $definitionResolver + * @internal param ProjectIndex $project */ public function __construct( ContentRetriever $contentRetriever, ProjectIndex $projectIndex, - DefinitionResolverInterface $definitionResolver + TolerantDefinitionResolver $definitionResolver ) { $this->contentRetriever = $contentRetriever; $this->projectIndex = $projectIndex; $this->definitionResolver = $definitionResolver; - $this->parser = ParserResourceFactory::getParser(); + $this->parser = new Tolerant\Parser(); $this->docBlockFactory = DocBlockFactory::createInstance(); } diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index b4793175..36799507 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -3,37 +3,20 @@ namespace LanguageServer\Server; -use Microsoft\PhpParser as Tolerant; -use phpDocumentor\Reflection\DocBlock\Tags\Param; -use PhpParser\{Node, NodeTraverser}; use LanguageServer\{ - DefinitionResolverInterface, FqnUtilities, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider, TolerantDefinitionResolver, TolerantTreeAnalyzer + CompletionProvider, FqnUtilities, LanguageClient, PhpDocument, PhpDocumentLoader, TolerantDefinitionResolver }; -use LanguageServer\NodeVisitor\VariableReferencesCollector; +use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\{ - SymbolLocationInformation, - SymbolDescriptor, - TextDocumentItem, - TextDocumentIdentifier, - VersionedTextDocumentIdentifier, - Position, - Range, - FormattingOptions, - TextEdit, - Location, - SymbolInformation, - ReferenceContext, - Hover, - MarkedString, - SymbolKind, - CompletionItem, - CompletionItemKind + FormattingOptions, Hover, Location, MarkedString, Position, Range, ReferenceContext, SymbolDescriptor, SymbolLocationInformation, TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier }; -use LanguageServer\Index\ReadableIndex; +use Microsoft\PhpParser as Tolerant; use Sabre\Event\Promise; use Sabre\Uri; +use function LanguageServer\{ + isVendored, waitForEvent +}; use function Sabre\Event\coroutine; -use function LanguageServer\{waitForEvent, isVendored}; /** * Provides method handlers for all textDocument/* methods @@ -53,7 +36,7 @@ class TextDocument protected $project; /** - * @var DefinitionResolverInterface + * @var TolerantDefinitionResolver */ protected $definitionResolver; @@ -79,7 +62,7 @@ class TextDocument /** * @param PhpDocumentLoader $documentLoader - * @param DefinitionResolverInterface $definitionResolver + * @param TolerantDefinitionResolver $definitionResolver * @param LanguageClient $client * @param ReadableIndex $index * @param \stdClass $composerJson @@ -87,7 +70,7 @@ class TextDocument */ public function __construct( PhpDocumentLoader $documentLoader, - DefinitionResolverInterface $definitionResolver, + TolerantDefinitionResolver $definitionResolver, LanguageClient $client, ReadableIndex $index, \stdClass $composerJson = null, diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 0459a431..38d2ce7b 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -3,16 +3,15 @@ namespace LanguageServer; +use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\TolerantSymbolInformation; -use PhpParser\Node; +use Microsoft\PhpParser as Tolerant; use phpDocumentor\Reflection\{ - DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver + DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types }; -use LanguageServer\Protocol\SymbolInformation; -use LanguageServer\Index\ReadableIndex; -use Microsoft\PhpParser as Tolerant; +use PhpParser\Node; -class TolerantDefinitionResolver implements DefinitionResolverInterface +class TolerantDefinitionResolver { /** * The current project index (for retrieving existing definitions) @@ -77,7 +76,7 @@ public function getDeclarationLineFromNode($node): string $defLine = \rtrim(\strtok($defLine, "\n"), "\r"); // TODO - pretty print rather than getting text - + return $defLine; } @@ -93,7 +92,7 @@ public function getDocumentationFromNode($node) if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { return null; } - + // For properties and constants, set the node to the declaration node, rather than the individual property. // This is because they get defined as part of a list. $constOrPropertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node); @@ -196,8 +195,8 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition // TODO - why is this represented as an array? // TODO interface implementations. } elseif ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && - // TODO - this hould be better represented in the parser API + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && + // TODO - this should be better represented in the parser API $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null ) { $def->extends = []; @@ -229,7 +228,7 @@ public function resolveReferenceNodeToDefinition($node) // Variables are not indexed globally, as they stay in the file scope anyway. // Ignore variable nodes that are part of ScopedPropertyAccessExpression, // as the scoped property access expression node is handled separately. - if ($node instanceof Tolerant\Node\Expression\Variable && + if ($node instanceof Tolerant\Node\Expression\Variable && !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) { // Resolve $this to the containing class definition. @@ -252,6 +251,7 @@ public function resolveReferenceNodeToDefinition($node) } // 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 + // TODO - verify that this is not a method $globalFallback = TolerantParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); @@ -264,7 +264,7 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) { + public function resolveReferenceNodeToFqn($node) { // TODO all name tokens should be a part of a node if ($node instanceof Tolerant\Node\QualifiedName) { return $this->resolveQualifiedNameNodeToFqn($node); @@ -278,7 +278,7 @@ public function resolveReferenceNodeToFqn($node) { } else if ( // A\B::C - constant access expression - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression && !($node->memberName instanceof Tolerant\Node\Expression\Variable) ) { return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); @@ -299,10 +299,10 @@ private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node return null; } // Add use clause references - if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause + if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause || $useClause instanceof Tolerant\Node\NamespaceUseClause ) { - $contents = $node->getFileContents(); + $contents = $node->getFileContents(); if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { $prefix = $useClause->parent->parent->namespaceName; if ($prefix === null) { @@ -331,7 +331,7 @@ private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node // For extends, implements, type hints and classes of classes of static calls use the name directly $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); - + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; } @@ -555,7 +555,7 @@ public function resolveExpressionNodeToType($expr): Type // VARIABLE // $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->getName() === 'this') { return new Types\This; @@ -577,7 +577,7 @@ public function resolveExpressionNodeToType($expr): Type $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) ) { - + // Find the function definition if ($expr->callableExpression instanceof Tolerant\Node\Expression) { // Cannot get type for dynamic function call @@ -664,7 +664,7 @@ public function resolveExpressionNodeToType($expr): Type if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } - + $def = $this->index->getDefinition($fqn); if ($def === null) { return new Types\Mixed; @@ -686,14 +686,14 @@ public function resolveExpressionNodeToType($expr): Type } // 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) { return $this->resolveExpressionNodeToType($expr->rightOperand); } // TERNARY EXPRESSION // $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->ifExpression === null) { @@ -751,7 +751,7 @@ public function resolveExpressionNodeToType($expr): Type return new Types\String_; } - // BINARY EXPRESSIONS: + // BINARY EXPRESSIONS: // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float // [operator] +, -, *, ** // [assignment] *=, **=, -=, += @@ -1005,8 +1005,8 @@ public function getTypeFromNode($node) // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS // Get the documented type the assignment resolves to. if ( - ($declarationNode = - TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? + ($declarationNode = + TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node) ) !== null || ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) @@ -1085,8 +1085,8 @@ public static function getDefinedFqn($node) // INPUT OUTPUT // namespace A\B; // class C { - // function a () {} A\B\C::a() - // static function b() {} A\B\C->b() + // function a () {} A\B\C->a() + // static function b() {} A\B\C::b() // } else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name @@ -1111,7 +1111,7 @@ public static function getDefinedFqn($node) // namespace A\B; // class C { // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b - // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b + // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name // } else if ( ($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null && diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index d53f43bb..5d6e7e84 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -7,7 +7,7 @@ use PhpParser\{Node}; use phpDocumentor\Reflection\DocBlockFactory; use LanguageServer\{ - ParserResourceFactory + TolerantDefinitionResolver, TolerantTreeAnalyzer }; use LanguageServer\Index\{Index}; use function LanguageServer\pathToUri; @@ -67,14 +67,14 @@ public function testDoesNotCollectReferences() private function collectDefinitions($path):array { $uri = pathToUri($path); - $parser = ParserResourceFactory::getParser(); + $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $definitionResolver = new TolerantDefinitionResolver($index); $content = file_get_contents($path); - $treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); + $treeAnalyzer = new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); return $treeAnalyzer->getDefinitionNodes(); } } diff --git a/tests/PhpDocumentLoaderTest.php b/tests/PhpDocumentLoaderTest.php index 8ae56d84..18e8373d 100644 --- a/tests/PhpDocumentLoaderTest.php +++ b/tests/PhpDocumentLoaderTest.php @@ -3,22 +3,14 @@ namespace LanguageServer\Tests\Server; -use PHPUnit\Framework\TestCase; -use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver + PhpDocument, PhpDocumentLoader, Project, TolerantDefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; -use LanguageServer\Protocol\{ - TextDocumentItem, - TextDocumentIdentifier, - SymbolKind, - DiagnosticSeverity, - FormattingOptions, - ClientCapabilities +use LanguageServer\Index\{ + DependenciesIndex, Index, ProjectIndex }; -use AdvancedJsonRpc\{Request as RequestBody, Response as ResponseBody}; +use PHPUnit\Framework\TestCase; use function LanguageServer\pathToUri; class PhpDocumentLoaderTest extends TestCase @@ -34,7 +26,7 @@ public function setUp() $this->loader = new PhpDocumentLoader( new FileSystemContentRetriever, $projectIndex, - ParserResourceFactory::getDefinitionResolver($projectIndex) + new TolerantDefinitionResolver($projectIndex) ); } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 0dc9a6de..19081afe 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -3,28 +3,29 @@ namespace LanguageServer\Tests\Server; -use PHPUnit\Framework\TestCase; -use phpDocumentor\Reflection\DocBlockFactory; -use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, LanguageClient, PhpDocument, DefinitionResolver, Parser + PhpDocument, TolerantDefinitionResolver +}; +use LanguageServer\Index\{ + Index +}; +use LanguageServer\Protocol\{ + Position }; -use LanguageServer\NodeVisitor\NodeAtPositionFinder; -use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Protocol\{SymbolKind, Position, ClientCapabilities}; -use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; +use Microsoft\PhpParser as Tolerant; +use phpDocumentor\Reflection\DocBlockFactory; use PhpParser\Node; +use PHPUnit\Framework\TestCase; use function LanguageServer\isVendored; -use Microsoft\PhpParser as Tolerant; class PhpDocumentTest extends TestCase { public function createDocument(string $uri, string $content) { - $parser = ParserResourceFactory::getParser(); + $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $definitionResolver = new TolerantDefinitionResolver($index); return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); } diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 583b40af..a93e4c10 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -6,13 +6,12 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver }; -use LanguageServer\Index\{ProjectIndex, StubsIndex, GlobalIndex, DependenciesIndex, Index}; +use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Protocol\{Position, Location, Range, ClientCapabilities}; +use LanguageServer\Protocol\{Position, Location, Range}; use function LanguageServer\pathToUri; -use Sabre\Event\Promise; abstract class ServerTestCase extends TestCase { @@ -52,7 +51,7 @@ public function setUp() $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); + $definitionResolver = new TolerantDefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index a48ab952..600755dd 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -6,16 +6,15 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver + Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver }; -use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex, GlobalIndex, StubsIndex}; +use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Protocol\{ TextDocumentIdentifier, TextEdit, Range, Position, - ClientCapabilities, CompletionList, CompletionItem, CompletionItemKind @@ -38,7 +37,7 @@ public function setUp() { $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); + $definitionResolver = new TolerantDefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait(); diff --git a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php index b0510f66..aa9d7b97 100644 --- a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php @@ -6,12 +6,11 @@ use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; use LanguageServer\{ - ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Protocol\{TextDocumentIdentifier, Position, Range, Location, ClientCapabilities}; -use Sabre\Event\Promise; +use LanguageServer\Protocol\{TextDocumentIdentifier, Position, Range, Location}; class GlobalFallbackTest extends ServerTestCase { @@ -20,7 +19,7 @@ public function setUp() $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); + $definitionResolver = new TolerantDefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/DidChangeTest.php b/tests/Server/TextDocument/DidChangeTest.php index 3e66e940..d46067b2 100644 --- a/tests/Server/TextDocument/DidChangeTest.php +++ b/tests/Server/TextDocument/DidChangeTest.php @@ -6,18 +6,15 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver + Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Protocol\{ - TextDocumentIdentifier, - TextDocumentItem, VersionedTextDocumentIdentifier, TextDocumentContentChangeEvent, Range, - Position, - ClientCapabilities + Position }; class DidChangeTest extends TestCase @@ -26,7 +23,7 @@ public function test() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); + $definitionResolver = new TolerantDefinitionResolver($projectIndex); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $phpDocument = $loader->open('whatever', "open('whatever', "textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); } diff --git a/tests/Server/TextDocument/References/GlobalFallbackTest.php b/tests/Server/TextDocument/References/GlobalFallbackTest.php index 1fc9daa1..684be182 100644 --- a/tests/Server/TextDocument/References/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/References/GlobalFallbackTest.php @@ -3,14 +3,17 @@ namespace LanguageServer\Tests\Server\TextDocument\References; -use PHPUnit\Framework\TestCase; -use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver + LanguageClient, PhpDocumentLoader, Server, TolerantDefinitionResolver }; -use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; -use LanguageServer\Protocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range, ClientCapabilities}; +use LanguageServer\Index\{ + DependenciesIndex, Index, ProjectIndex +}; +use LanguageServer\Protocol\{ + Location, Position, Range, ReferenceContext, TextDocumentIdentifier +}; +use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; class GlobalFallbackTest extends ServerTestCase @@ -19,7 +22,7 @@ public function setUp() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); + $definitionResolver = new TolerantDefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 1b476951..d830f190 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -8,8 +8,8 @@ use LanguageServer\Definition; use LanguageServer\Index\Index; use LanguageServer\ParserKind; -use LanguageServer\ParserResourceFactory; use LanguageServer\PhpDocument; +use LanguageServer\TolerantDefinitionResolver; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlockFactory; use PHPUnit\Framework\TestCase; @@ -60,8 +60,14 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { echo "Test file: " . realpath($testCaseFile) . PHP_EOL; $fileContents = file_get_contents($testCaseFile); - $expectedValues = $this->getExpectedTestValues($testCaseFile, $frameworkName, $fileContents); - $actualValues = $this->getActualTestValues($testCaseFile, $frameworkName, $fileContents); + $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); + + $outputFile = getExpectedValuesFile($testCaseFile); + if (!file_exists($outputFile)) { + file_put_contents(json_encode($actualValues, JSON_PRETTY_PRINT)); + } + + $expectedValues = (array)json_decode(file_get_contents($outputFile)); try { $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); @@ -81,56 +87,11 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { } } - /** - * @param $filename - * @param $frameworkName - * @param $fileContents - * @return array - */ - private function getExpectedTestValues($filename, $frameworkName, $fileContents) { - global $parserKind; - $parserKind = ParserKind::PHP_PARSER; - - $outputFile = getExpectedValuesFile($filename); - if (file_exists($outputFile)) { - return (array)json_decode(file_get_contents($outputFile)); - } - - $index = new Index(); - $parser = ParserResourceFactory::getParser(); - $docBlockFactory = DocBlockFactory::createInstance(); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); - - try { - $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (\Throwable $e) { - $this->markTestSkipped('Baseline parser failed: '. $e->getTraceAsString()); - } - - if ($document->getStmts() === null) { - $this->markTestSkipped('Baseline parser failed: null AST'); - } - - $expectedRefs = $index->references; - $this->filterSkippedReferences($expectedRefs); - $expectedDefs = $this->getTestValuesFromDefs($document->getDefinitions()); - - $refsAndDefs = array( - 'references' => json_decode(json_encode($expectedRefs)), - 'definitions' => json_decode(json_encode($expectedDefs)) - ); - - return $refsAndDefs; - } - - private function getActualTestValues($filename, $frameworkName, $fileContents): array { - global $parserKind; - $parserKind = ParserKind::TOLERANT_PHP_PARSER; - + private function getActualTestValues($filename, $fileContents): array { $index = new Index(); - $parser = ParserResourceFactory::getParser(); + $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); - $definitionResolver = ParserResourceFactory::getDefinitionResolver($index); + $definitionResolver = new TolerantDefinitionResolver($index); $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); From 57f9e1f20e6f7d9bc989bfd621f66e1f5d29c65e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 2 May 2017 11:08:02 -0700 Subject: [PATCH 081/149] Fix completions test (insertText is optional) --- tests/Server/TextDocument/CompletionTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index 600755dd..20743de4 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -210,7 +210,10 @@ public function testUsedClass() 'TestClass', CompletionItemKind::CLASS_, 'TestNamespace', - 'Pariatur ut laborum tempor voluptate consequat ea deserunt.' + 'Pariatur ut laborum tempor voluptate consequat ea deserunt.', + null, + null, + 'TestClass' ) ], true), $items); } From de08134173026f2bd01cdd51cb360af9ade30e93 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 12 May 2017 09:47:24 -0700 Subject: [PATCH 082/149] Point at master branch of tolerant-php-parser --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8a1d04cb..30a00ce0 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "dev-lang-server" + "Microsoft/tolerant-php-parser": "dev-master" }, "minimum-stability": "dev", "repositories": [ From addc8624043aef9ee802ebbe09d852ed94d1fb64 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 14 May 2017 14:17:43 -0700 Subject: [PATCH 083/149] Add Diagnostic source and severity --- src/TolerantTreeAnalyzer.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php index 933b793b..1b5bd0dc 100644 --- a/src/TolerantTreeAnalyzer.php +++ b/src/TolerantTreeAnalyzer.php @@ -79,7 +79,10 @@ public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { new Range( new Position($range->start->line, $range->start->character), new Position($range->end->line, $range->start->character) - ) + ), + null, + DiagnosticSeverity::ERROR, + 'php' ); } } @@ -96,7 +99,7 @@ public function update($node) { if (!( ( // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node instanceof Tolerant\Node\Expression\MemberAccessExpression) && !( $node->parent instanceof Tolerant\Node\Expression\CallExpression || @@ -143,7 +146,7 @@ public function update($node) { } $this->collectDefinitionsAndReferences($node); } - + public function getDiagnostics() { return $this->diagnostics ?? []; } From 1bb710f8526f1375d4b8867f5e90bda22e01c5fa Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 15 May 2017 15:30:29 -0700 Subject: [PATCH 084/149] Fix absolute paths and escaped slashes in validation expected output --- tests/Validation/ValidationTest.php | 37 ++++++++++++++++--- .../WithReturnTypehints.php.expected.json | 16 ++++---- ...embersShouldNotBeSymbols.php.expected.json | 2 +- ...rrayValueShouldBeBoolean.php.expected.json | 4 +- .../_cases/caseStatement1.php.expected.json | 6 +-- .../_cases/classDefinition1.php.expected.json | 10 ++--- .../_cases/classProperty1.php.expected.json | 12 +++--- .../_cases/constants.php.expected.json | 10 ++--- .../_cases/constants2.php.expected.json | 10 ++--- .../_cases/constants3.php.expected.json | 10 ++--- .../_cases/constants4.php.expected.json | 10 ++--- .../_cases/constants5.php.expected.json | 8 ++-- ...tsInFunctionParamDefault.php.expected.json | 6 +-- ...cksOnNamespaceDefinition.php.expected.json | 2 +- .../_cases/exceptions1.php.expected.json | 2 +- .../_cases/functionUse.php.expected.json | 4 +- .../_cases/functionUse2.php.expected.json | 4 +- .../_cases/ifStatement1.php.expected.json | 6 +-- .../interfaceProperty.php.expected.json | 2 +- ...cConstantsShouldBeGlobal.php.expected.json | 2 +- .../_cases/magicConsts.php.expected.json | 4 +- .../_cases/memberAccess1.php.expected.json | 10 ++--- .../_cases/memberAccess2.php.expected.json | 10 ++--- .../_cases/memberAccess3.php.expected.json | 20 +++++----- .../_cases/memberAccess4.php.expected.json | 14 +++---- .../_cases/memberAccess5.php.expected.json | 6 +-- .../_cases/memberCall1.php.expected.json | 12 +++--- .../multipleNamespaces.php.expected.json | 20 +++++----- ...ltiplePreceedingComments.php.expected.json | 4 +- .../_cases/nameToken.php.expected.json | 4 +- .../_cases/namespaces2.php.expected.json | 10 ++--- .../_cases/namespaces4.php.expected.json | 4 +- .../_cases/namespaces5.php.expected.json | 16 ++++---- .../_cases/namespaces6.php.expected.json | 2 +- .../_cases/namespaces8.php.expected.json | 4 +- .../_cases/objectCreation.php.expected.json | 8 ++-- .../_cases/objectCreation2.php.expected.json | 12 +++--- .../_cases/objectCreation3.php.expected.json | 6 +-- .../_cases/param1.php.expected.json | 6 +-- .../_cases/parent1.php.expected.json | 14 +++---- .../_cases/parent3.php.expected.json | 16 ++++---- .../_cases/propertyName1.php.expected.json | 4 +- .../_cases/propertyName2.php.expected.json | 4 +- .../_cases/returnType.php.expected.json | 8 ++-- .../scopedPropertyAccess.php.expected.json | 10 ++--- .../scopedPropertyAccess2.php.expected.json | 4 +- .../scopedPropertyAccess3.php.expected.json | 8 ++-- .../scopedPropertyAccess4.php.expected.json | 2 +- .../scopedPropertyAccess5.php.expected.json | 12 +++--- .../frameworks/_cases/self1.php.expected.json | 16 ++++---- .../frameworks/_cases/self2.php.expected.json | 16 ++++---- .../frameworks/_cases/self3.php.expected.json | 16 ++++---- .../frameworks/_cases/self4.php.expected.json | 14 +++---- .../frameworks/_cases/self5.php.expected.json | 8 ++-- .../_cases/static1.php.expected.json | 16 ++++---- .../_cases/static2.php.expected.json | 16 ++++---- .../_cases/static3.php.expected.json | 16 ++++---- .../_cases/static4.php.expected.json | 10 ++--- .../_cases/stringVariable.php.expected.json | 6 +-- ...edNameOutsideOfNamespace.php.expected.json | 4 +- ...rifyFqsenOnClassProperty.php.expected.json | 10 ++--- 61 files changed, 295 insertions(+), 270 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index d830f190..a7d3ec11 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -21,10 +21,13 @@ use Sabre\Event\Loop; use Microsoft\PhpParser as Tolerant; +$frameworksDir = realpath(__DIR__ . '/../../validation/frameworks'); + class ValidationTest extends TestCase { public function frameworkErrorProvider() { - $frameworks = glob(__DIR__ . "/../../validation/frameworks/*", GLOB_ONLYDIR); + global $frameworksDir; + $frameworks = glob($frameworksDir . '/*', GLOB_ONLYDIR); $testProviderArray = array(); foreach ($frameworks as $frameworkDir) { @@ -33,7 +36,7 @@ public function frameworkErrorProvider() { continue; } - $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); + $iterator = new RecursiveDirectoryIterator($frameworkDir); $skipped = json_decode(file_get_contents(__DIR__ . '/skipped.json')); foreach (new RecursiveIteratorIterator($iterator) as $file) { @@ -44,9 +47,11 @@ public function frameworkErrorProvider() { } } } + if (count($testProviderArray) === 0) { throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); } + return $testProviderArray; } @@ -64,7 +69,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $outputFile = getExpectedValuesFile($testCaseFile); if (!file_exists($outputFile)) { - file_put_contents(json_encode($actualValues, JSON_PRETTY_PRINT)); + file_put_contents(json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); } $expectedValues = (array)json_decode(file_get_contents($outputFile)); @@ -80,7 +85,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { } catch (\Throwable $e) { $outputFile = getExpectedValuesFile($testCaseFile); if ($frameworkName === '_cases') { - file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT)); + file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); } throw $e; @@ -88,6 +93,8 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { } private function getActualTestValues($filename, $fileContents): array { + global $frameworksDir; + $index = new Index(); $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); @@ -106,6 +113,24 @@ private function getActualTestValues($filename, $fileContents): array { 'definitions' => json_decode(json_encode($actualDefs)) ); + // Turn references into relative paths + foreach ($refsAndDefs['references'] as $key => $list) { + $fixedPathRefs = array_map(function($ref) { + global $frameworksDir; + return str_replace($frameworksDir, '.', $ref); + }, $list); + + $refsAndDefs['references']->$key = $fixedPathRefs; + } + + // Turn def locations into relative paths + foreach ($refsAndDefs['definitions'] as $key => $def) { + if ($def !== null && $def->symbolInformation !== null && + $def->symbolInformation->location !== null && $def->symbolInformation->location->uri !== null) { + $def->symbolInformation->location->uri = str_replace($frameworksDir, '.', $def->symbolInformation->location->uri); + } + } + return $refsAndDefs; } @@ -151,7 +176,7 @@ private function filterSkippedReferences(&$references): void 'pathToUri', 'uriToPath' // group function use declarations are broken in old definition resolver ]; - foreach ($references as $key=>$value) { + foreach ($references as $key => $value) { foreach ($skipped as $s) { if (strpos($key, $s) !== false) { unset($references[$key]); @@ -163,4 +188,4 @@ private function filterSkippedReferences(&$references): void function getExpectedValuesFile($testCaseFile): string { return $testCaseFile . '.expected.json'; -} \ No newline at end of file +} diff --git a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json index e1da9a4c..17a5213b 100644 --- a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json +++ b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json @@ -1,13 +1,13 @@ { "references": { "Fixtures\\Prophecy\\EmptyClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "./_cases/WithReturnTypehints.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "./_cases/WithReturnTypehints.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "./_cases/WithReturnTypehints.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "Fixtures\\Prophecy", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "uri": "./_cases/WithReturnTypehints.php" }, "containerName": "Fixtures" }, @@ -39,7 +39,7 @@ "name": "WithReturnTypehints", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "uri": "./_cases/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy" }, @@ -56,7 +56,7 @@ "name": "getSelf", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "uri": "./_cases/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -73,7 +73,7 @@ "name": "getName", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "uri": "./_cases/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -90,7 +90,7 @@ "name": "getParent", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/WithReturnTypehints.php" + "uri": "./_cases/WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, diff --git a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index 88ed9309..719e3884 100644 --- a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/anonymousClassMembersShouldNotBeSymbols.php" + "uri": "./_cases/anonymousClassMembersShouldNotBeSymbols.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json index a6168d76..78acadd3 100644 --- a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json +++ b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/arrayValueShouldBeBoolean.php" + "uri": "./_cases/arrayValueShouldBeBoolean.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "foo", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/arrayValueShouldBeBoolean.php" + "uri": "./_cases/arrayValueShouldBeBoolean.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/caseStatement1.php.expected.json b/validation/frameworks/_cases/caseStatement1.php.expected.json index 07fd68d4..545de327 100644 --- a/validation/frameworks/_cases/caseStatement1.php.expected.json +++ b/validation/frameworks/_cases/caseStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" + "./_cases/caseStatement1.php" ], "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" + "./_cases/caseStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/caseStatement1.php" + "uri": "./_cases/caseStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/classDefinition1.php.expected.json b/validation/frameworks/_cases/classDefinition1.php.expected.json index a0c0672d..52dd9f62 100644 --- a/validation/frameworks/_cases/classDefinition1.php.expected.json +++ b/validation/frameworks/_cases/classDefinition1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" + "./_cases/classDefinition1.php" ], "TestNamespace\\A->a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" + "./_cases/classDefinition1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" + "uri": "./_cases/classDefinition1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" + "uri": "./_cases/classDefinition1.php" }, "containerName": "TestNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classDefinition1.php" + "uri": "./_cases/classDefinition1.php" }, "containerName": "TestNamespace\\A" }, diff --git a/validation/frameworks/_cases/classProperty1.php.expected.json b/validation/frameworks/_cases/classProperty1.php.expected.json index 2088a930..5affe9d9 100644 --- a/validation/frameworks/_cases/classProperty1.php.expected.json +++ b/validation/frameworks/_cases/classProperty1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "SomeNamespace\\Goo": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "./_cases/classProperty1.php" ], "SomeNamespace": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "./_cases/classProperty1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "uri": "./_cases/classProperty1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "uri": "./_cases/classProperty1.php" }, "containerName": "TestNamespace" }, @@ -51,7 +51,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "uri": "./_cases/classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, @@ -68,7 +68,7 @@ "name": "testMethod", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/classProperty1.php" + "uri": "./_cases/classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, diff --git a/validation/frameworks/_cases/constants.php.expected.json b/validation/frameworks/_cases/constants.php.expected.json index 9106488e..0c95336e 100644 --- a/validation/frameworks/_cases/constants.php.expected.json +++ b/validation/frameworks/_cases/constants.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" + "./_cases/constants.php" ], "BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" + "./_cases/constants.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" + "uri": "./_cases/constants.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" + "uri": "./_cases/constants.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants.php" + "uri": "./_cases/constants.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants2.php.expected.json b/validation/frameworks/_cases/constants2.php.expected.json index 476a21c7..ee44131f 100644 --- a/validation/frameworks/_cases/constants2.php.expected.json +++ b/validation/frameworks/_cases/constants2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" + "./_cases/constants2.php" ], "BYE": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" + "./_cases/constants2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" + "uri": "./_cases/constants2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" + "uri": "./_cases/constants2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants2.php" + "uri": "./_cases/constants2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants3.php.expected.json b/validation/frameworks/_cases/constants3.php.expected.json index 1f647e77..35b13da9 100644 --- a/validation/frameworks/_cases/constants3.php.expected.json +++ b/validation/frameworks/_cases/constants3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\T_NEW": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" + "./_cases/constants3.php" ], "T_NEW": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" + "./_cases/constants3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" + "uri": "./_cases/constants3.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" + "uri": "./_cases/constants3.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants3.php" + "uri": "./_cases/constants3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants4.php.expected.json b/validation/frameworks/_cases/constants4.php.expected.json index cb39ca11..8f0752ad 100644 --- a/validation/frameworks/_cases/constants4.php.expected.json +++ b/validation/frameworks/_cases/constants4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\HI": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" + "./_cases/constants4.php" ], "HI": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" + "./_cases/constants4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" + "uri": "./_cases/constants4.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" + "uri": "./_cases/constants4.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants4.php" + "uri": "./_cases/constants4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants5.php.expected.json b/validation/frameworks/_cases/constants5.php.expected.json index 4eba3ad5..0a3b68cf 100644 --- a/validation/frameworks/_cases/constants5.php.expected.json +++ b/validation/frameworks/_cases/constants5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\PHP_INT_MAX": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" + "./_cases/constants5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" + "uri": "./_cases/constants5.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "Mbstring", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" + "uri": "./_cases/constants5.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "MB_CASE_FOLD", "kind": 14, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constants5.php" + "uri": "./_cases/constants5.php" }, "containerName": "MyNamespace\\Mbstring" }, diff --git a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json index 6bbd112c..8ba8a2f2 100644 --- a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json +++ b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MY_CONSTANT": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" + "./_cases/constantsInFunctionParamDefault.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 11, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" + "uri": "./_cases/constantsInFunctionParamDefault.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/constantsInFunctionParamDefault.php" + "uri": "./_cases/constantsInFunctionParamDefault.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json index 8db10d33..50afd5e1 100644 --- a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json +++ b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/docBlocksOnNamespaceDefinition.php" + "uri": "./_cases/docBlocksOnNamespaceDefinition.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/exceptions1.php.expected.json b/validation/frameworks/_cases/exceptions1.php.expected.json index 783cb223..debebd20 100644 --- a/validation/frameworks/_cases/exceptions1.php.expected.json +++ b/validation/frameworks/_cases/exceptions1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/exceptions1.php" + "uri": "./_cases/exceptions1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/functionUse.php.expected.json b/validation/frameworks/_cases/functionUse.php.expected.json index 4d321386..5ecb0b82 100644 --- a/validation/frameworks/_cases/functionUse.php.expected.json +++ b/validation/frameworks/_cases/functionUse.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse.php" + "./_cases/functionUse.php" ], "A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse.php" + "./_cases/functionUse.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/functionUse2.php.expected.json b/validation/frameworks/_cases/functionUse2.php.expected.json index 127b34d9..b58c001a 100644 --- a/validation/frameworks/_cases/functionUse2.php.expected.json +++ b/validation/frameworks/_cases/functionUse2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse2.php" + "./_cases/functionUse2.php" ], "LanguageServer\\timeout()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/functionUse2.php" + "./_cases/functionUse2.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/ifStatement1.php.expected.json b/validation/frameworks/_cases/ifStatement1.php.expected.json index 20ded823..26d91dc9 100644 --- a/validation/frameworks/_cases/ifStatement1.php.expected.json +++ b/validation/frameworks/_cases/ifStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" + "./_cases/ifStatement1.php" ], "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" + "./_cases/ifStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/ifStatement1.php" + "uri": "./_cases/ifStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/interfaceProperty.php.expected.json b/validation/frameworks/_cases/interfaceProperty.php.expected.json index 45032638..a4787cef 100644 --- a/validation/frameworks/_cases/interfaceProperty.php.expected.json +++ b/validation/frameworks/_cases/interfaceProperty.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 11, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/interfaceProperty.php" + "uri": "./_cases/interfaceProperty.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json index 7b247477..9e5002b1 100644 --- a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json +++ b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json @@ -10,7 +10,7 @@ "name": "B", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/magicConstantsShouldBeGlobal.php" + "uri": "./_cases/magicConstantsShouldBeGlobal.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/magicConsts.php.expected.json b/validation/frameworks/_cases/magicConsts.php.expected.json index 2565a900..ce249ba3 100644 --- a/validation/frameworks/_cases/magicConsts.php.expected.json +++ b/validation/frameworks/_cases/magicConsts.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/magicConsts.php" + "uri": "./_cases/magicConsts.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "deprecationsTriggered", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/magicConsts.php" + "uri": "./_cases/magicConsts.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/memberAccess1.php.expected.json b/validation/frameworks/_cases/memberAccess1.php.expected.json index 2ecd9fb9..3e4d354b 100644 --- a/validation/frameworks/_cases/memberAccess1.php.expected.json +++ b/validation/frameworks/_cases/memberAccess1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" + "./_cases/memberAccess1.php" ], "MyNamespace\\a->a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" + "./_cases/memberAccess1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" + "uri": "./_cases/memberAccess1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" + "uri": "./_cases/memberAccess1.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess1.php" + "uri": "./_cases/memberAccess1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess2.php.expected.json b/validation/frameworks/_cases/memberAccess2.php.expected.json index bc5f135c..69a1e6a0 100644 --- a/validation/frameworks/_cases/memberAccess2.php.expected.json +++ b/validation/frameworks/_cases/memberAccess2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" + "./_cases/memberAccess2.php" ], "MyNamespace\\a->a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" + "./_cases/memberAccess2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" + "uri": "./_cases/memberAccess2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" + "uri": "./_cases/memberAccess2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess2.php" + "uri": "./_cases/memberAccess2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess3.php.expected.json b/validation/frameworks/_cases/memberAccess3.php.expected.json index 6af62238..6486a9c1 100644 --- a/validation/frameworks/_cases/memberAccess3.php.expected.json +++ b/validation/frameworks/_cases/memberAccess3.php.expected.json @@ -1,25 +1,25 @@ { "references": { "MyNamespace\\ClassLoader": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "Closure::bind()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "Closure": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "MyNamespace\\ClassLoader->prefixesPsr0": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ], "MyNamespace\\ClassLoader::class": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "./_cases/memberAccess3.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "uri": "./_cases/memberAccess3.php" }, "containerName": "" }, @@ -49,7 +49,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "uri": "./_cases/memberAccess3.php" }, "containerName": "MyNamespace" }, @@ -66,7 +66,7 @@ "name": "getInitializer", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess3.php" + "uri": "./_cases/memberAccess3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess4.php.expected.json b/validation/frameworks/_cases/memberAccess4.php.expected.json index 31b7d6b6..78887b3d 100644 --- a/validation/frameworks/_cases/memberAccess4.php.expected.json +++ b/validation/frameworks/_cases/memberAccess4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace\\Request::create()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "./_cases/memberAccess4.php" ], "MyNamespace\\Request": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "./_cases/memberAccess4.php" ], "MyNamespace\\Url->toString()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "./_cases/memberAccess4.php" ], "MyNamespace\\Url": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "./_cases/memberAccess4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "uri": "./_cases/memberAccess4.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "uri": "./_cases/memberAccess4.php" }, "containerName": "MyNamespace" }, @@ -57,7 +57,7 @@ "name": "testRequest", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess4.php" + "uri": "./_cases/memberAccess4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess5.php.expected.json b/validation/frameworks/_cases/memberAccess5.php.expected.json index f58a6fc5..40ee9232 100644 --- a/validation/frameworks/_cases/memberAccess5.php.expected.json +++ b/validation/frameworks/_cases/memberAccess5.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" + "uri": "./_cases/memberAccess5.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" + "uri": "./_cases/memberAccess5.php" }, "containerName": "MyNamespace" }, @@ -44,7 +44,7 @@ "name": "setUp", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberAccess5.php" + "uri": "./_cases/memberAccess5.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/_cases/memberCall1.php.expected.json b/validation/frameworks/_cases/memberCall1.php.expected.json index 6ce04a74..fd91dc4b 100644 --- a/validation/frameworks/_cases/memberCall1.php.expected.json +++ b/validation/frameworks/_cases/memberCall1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\AccountInterface": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "./_cases/memberCall1.php" ], "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "./_cases/memberCall1.php" ], "MyNamespace\\AccountInterface->getAccount()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "./_cases/memberCall1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "uri": "./_cases/memberCall1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "uri": "./_cases/memberCall1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "setAccount", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/memberCall1.php" + "uri": "./_cases/memberCall1.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/_cases/multipleNamespaces.php.expected.json b/validation/frameworks/_cases/multipleNamespaces.php.expected.json index 9cecc763..fdfee7d8 100644 --- a/validation/frameworks/_cases/multipleNamespaces.php.expected.json +++ b/validation/frameworks/_cases/multipleNamespaces.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace2\\MyNamespace1\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "./_cases/multipleNamespaces.php" ], "MyNamespace2\\MyNamespace1": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "./_cases/multipleNamespaces.php" ], "MyNamespace2": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "./_cases/multipleNamespaces.php" ], "MyNamespace2\\A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "./_cases/multipleNamespaces.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "MyNamespace1" }, @@ -57,7 +57,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "MyNamespace1\\B" }, @@ -74,7 +74,7 @@ "name": "MyNamespace2", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "" }, @@ -93,7 +93,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "MyNamespace2" }, @@ -110,7 +110,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multipleNamespaces.php" + "uri": "./_cases/multipleNamespaces.php" }, "containerName": "MyNamespace2\\A" }, diff --git a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json index 05fb01f7..81331edc 100644 --- a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json +++ b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json @@ -10,7 +10,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multiplePreceedingComments.php" + "uri": "./_cases/multiplePreceedingComments.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "fn", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/multiplePreceedingComments.php" + "uri": "./_cases/multiplePreceedingComments.php" }, "containerName": "Foo" }, diff --git a/validation/frameworks/_cases/nameToken.php.expected.json b/validation/frameworks/_cases/nameToken.php.expected.json index 404ad7e3..256da008 100644 --- a/validation/frameworks/_cases/nameToken.php.expected.json +++ b/validation/frameworks/_cases/nameToken.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/nameToken.php" + "uri": "./_cases/nameToken.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/nameToken.php" + "uri": "./_cases/nameToken.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/namespaces2.php.expected.json b/validation/frameworks/_cases/namespaces2.php.expected.json index 0140af53..a57f8727 100644 --- a/validation/frameworks/_cases/namespaces2.php.expected.json +++ b/validation/frameworks/_cases/namespaces2.php.expected.json @@ -1,16 +1,16 @@ { "references": { "NS1\\C": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" + "./_cases/namespaces2.php" ], "NS1": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" + "./_cases/namespaces2.php" ], "NS1\\I": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" + "./_cases/namespaces2.php" ], "NS1\\T": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" + "./_cases/namespaces2.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces2.php" + "uri": "./_cases/namespaces2.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/namespaces4.php.expected.json b/validation/frameworks/_cases/namespaces4.php.expected.json index 374c22e2..6d3d4ca9 100644 --- a/validation/frameworks/_cases/namespaces4.php.expected.json +++ b/validation/frameworks/_cases/namespaces4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "a\\b": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces4.php" + "./_cases/namespaces4.php" ], "a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces4.php" + "./_cases/namespaces4.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/namespaces5.php.expected.json b/validation/frameworks/_cases/namespaces5.php.expected.json index 346b5281..4a9b18d7 100644 --- a/validation/frameworks/_cases/namespaces5.php.expected.json +++ b/validation/frameworks/_cases/namespaces5.php.expected.json @@ -1,25 +1,25 @@ { "references": { "LanguageServer\\Protocol": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer\\Protocol\\TextDocumentIdentifier": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer\\Protocol\\Position": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer\\Protocol\\ReferenceContext": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer\\Protocol\\Location": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ], "LanguageServer\\Protocol\\Range": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "./_cases/namespaces5.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "B", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces5.php" + "uri": "./_cases/namespaces5.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/namespaces6.php.expected.json b/validation/frameworks/_cases/namespaces6.php.expected.json index 25e100c2..4c3e2850 100644 --- a/validation/frameworks/_cases/namespaces6.php.expected.json +++ b/validation/frameworks/_cases/namespaces6.php.expected.json @@ -10,7 +10,7 @@ "name": "A\\B", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces6.php" + "uri": "./_cases/namespaces6.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/namespaces8.php.expected.json b/validation/frameworks/_cases/namespaces8.php.expected.json index bccea586..02e5a6e1 100644 --- a/validation/frameworks/_cases/namespaces8.php.expected.json +++ b/validation/frameworks/_cases/namespaces8.php.expected.json @@ -1,7 +1,7 @@ { "references": { "LanguageServer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces8.php" + "./_cases/namespaces8.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "LanguageServer\\Tests\\Utils", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/namespaces8.php" + "uri": "./_cases/namespaces8.php" }, "containerName": "LanguageServer\\Tests" }, diff --git a/validation/frameworks/_cases/objectCreation.php.expected.json b/validation/frameworks/_cases/objectCreation.php.expected.json index b941c2e2..db211bf2 100644 --- a/validation/frameworks/_cases/objectCreation.php.expected.json +++ b/validation/frameworks/_cases/objectCreation.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->inline_diff_renderer": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" + "./_cases/objectCreation.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" + "uri": "./_cases/objectCreation.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" + "uri": "./_cases/objectCreation.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation.php" + "uri": "./_cases/objectCreation.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/objectCreation2.php.expected.json b/validation/frameworks/_cases/objectCreation2.php.expected.json index 6f187e16..f18ab104 100644 --- a/validation/frameworks/_cases/objectCreation2.php.expected.json +++ b/validation/frameworks/_cases/objectCreation2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B->hi()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "./_cases/objectCreation2.php" ], "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "./_cases/objectCreation2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "uri": "./_cases/objectCreation2.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "uri": "./_cases/objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "uri": "./_cases/objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -68,7 +68,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation2.php" + "uri": "./_cases/objectCreation2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/objectCreation3.php.expected.json b/validation/frameworks/_cases/objectCreation3.php.expected.json index 662e8aa8..198ef872 100644 --- a/validation/frameworks/_cases/objectCreation3.php.expected.json +++ b/validation/frameworks/_cases/objectCreation3.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A->args": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" + "./_cases/objectCreation3.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" + "uri": "./_cases/objectCreation3.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/objectCreation3.php" + "uri": "./_cases/objectCreation3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/param1.php.expected.json b/validation/frameworks/_cases/param1.php.expected.json index a976b705..9cf8a0ba 100644 --- a/validation/frameworks/_cases/param1.php.expected.json +++ b/validation/frameworks/_cases/param1.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\Hi": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" + "./_cases/param1.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" + "uri": "./_cases/param1.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "init", "kind": 12, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/param1.php" + "uri": "./_cases/param1.php" }, "containerName": "MyNamespace" }, diff --git a/validation/frameworks/_cases/parent1.php.expected.json b/validation/frameworks/_cases/parent1.php.expected.json index 64400b1a..1ca0490d 100644 --- a/validation/frameworks/_cases/parent1.php.expected.json +++ b/validation/frameworks/_cases/parent1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "./_cases/parent1.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "./_cases/parent1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "uri": "./_cases/parent1.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "uri": "./_cases/parent1.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "uri": "./_cases/parent1.php" }, "containerName": "MyNamespace\\B" }, @@ -70,7 +70,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "uri": "./_cases/parent1.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent1.php" + "uri": "./_cases/parent1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/parent3.php.expected.json b/validation/frameworks/_cases/parent3.php.expected.json index f844c06e..63dab420 100644 --- a/validation/frameworks/_cases/parent3.php.expected.json +++ b/validation/frameworks/_cases/parent3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "./_cases/parent3.php" ], "MyNamespace\\B->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "./_cases/parent3.php" ], "parent": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "./_cases/parent3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "uri": "./_cases/parent3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "uri": "./_cases/parent3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "uri": "./_cases/parent3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "uri": "./_cases/parent3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/parent3.php" + "uri": "./_cases/parent3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/propertyName1.php.expected.json b/validation/frameworks/_cases/propertyName1.php.expected.json index 1f46f135..d858143e 100644 --- a/validation/frameworks/_cases/propertyName1.php.expected.json +++ b/validation/frameworks/_cases/propertyName1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName1.php" + "uri": "./_cases/propertyName1.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName1.php" + "uri": "./_cases/propertyName1.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/_cases/propertyName2.php.expected.json b/validation/frameworks/_cases/propertyName2.php.expected.json index ab81b736..916b0145 100644 --- a/validation/frameworks/_cases/propertyName2.php.expected.json +++ b/validation/frameworks/_cases/propertyName2.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName2.php" + "uri": "./_cases/propertyName2.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/propertyName2.php" + "uri": "./_cases/propertyName2.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/_cases/returnType.php.expected.json b/validation/frameworks/_cases/returnType.php.expected.json index 479b915b..a8be8099 100644 --- a/validation/frameworks/_cases/returnType.php.expected.json +++ b/validation/frameworks/_cases/returnType.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\TestClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" + "./_cases/returnType.php" ], "TestNamespace\\TestClass2": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" + "./_cases/returnType.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" + "uri": "./_cases/returnType.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "whatever", "kind": 12, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/returnType.php" + "uri": "./_cases/returnType.php" }, "containerName": "TestNamespace" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json index 6a4770c1..0212fdfd 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A::a()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" + "./_cases/scopedPropertyAccess.php" ], "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" + "./_cases/scopedPropertyAccess.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" + "uri": "./_cases/scopedPropertyAccess.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" + "uri": "./_cases/scopedPropertyAccess.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess.php" + "uri": "./_cases/scopedPropertyAccess.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json index 5e2faa2e..375b992b 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess2.php" + "./_cases/scopedPropertyAccess2.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess2.php" + "uri": "./_cases/scopedPropertyAccess2.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json index 169587b8..be2c0c3b 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" + "./_cases/scopedPropertyAccess3.php" ], "A::$a": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" + "./_cases/scopedPropertyAccess3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" + "uri": "./_cases/scopedPropertyAccess3.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "a", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess3.php" + "uri": "./_cases/scopedPropertyAccess3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json index e8cb3e42..bcf1489c 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess4.php" + "./_cases/scopedPropertyAccess4.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json index 0f72e44e..79e7374e 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json @@ -1,16 +1,16 @@ { "references": { "TestInterface": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "./_cases/scopedPropertyAccess5.php" ], "TestClass": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "./_cases/scopedPropertyAccess5.php" ], "TestClass::$testProperty": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "./_cases/scopedPropertyAccess5.php" ], "TestClass::$staticTestProperty": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "./_cases/scopedPropertyAccess5.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "uri": "./_cases/scopedPropertyAccess5.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/scopedPropertyAccess5.php" + "uri": "./_cases/scopedPropertyAccess5.php" }, "containerName": "TestClass" }, diff --git a/validation/frameworks/_cases/self1.php.expected.json b/validation/frameworks/_cases/self1.php.expected.json index 571d579b..a6a0a492 100644 --- a/validation/frameworks/_cases/self1.php.expected.json +++ b/validation/frameworks/_cases/self1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "./_cases/self1.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "./_cases/self1.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "./_cases/self1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "uri": "./_cases/self1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "uri": "./_cases/self1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "uri": "./_cases/self1.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "uri": "./_cases/self1.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self1.php" + "uri": "./_cases/self1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self2.php.expected.json b/validation/frameworks/_cases/self2.php.expected.json index 3780e2f2..4820363b 100644 --- a/validation/frameworks/_cases/self2.php.expected.json +++ b/validation/frameworks/_cases/self2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "./_cases/self2.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "./_cases/self2.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "./_cases/self2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "uri": "./_cases/self2.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "uri": "./_cases/self2.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "uri": "./_cases/self2.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "uri": "./_cases/self2.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self2.php" + "uri": "./_cases/self2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self3.php.expected.json b/validation/frameworks/_cases/self3.php.expected.json index 99425908..9a5f633f 100644 --- a/validation/frameworks/_cases/self3.php.expected.json +++ b/validation/frameworks/_cases/self3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "./_cases/self3.php" ], "MyNamespace\\A->b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "./_cases/self3.php" ], "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "./_cases/self3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "uri": "./_cases/self3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "uri": "./_cases/self3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "uri": "./_cases/self3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "uri": "./_cases/self3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self3.php" + "uri": "./_cases/self3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self4.php.expected.json b/validation/frameworks/_cases/self4.php.expected.json index d99b3440..b45c143a 100644 --- a/validation/frameworks/_cases/self4.php.expected.json +++ b/validation/frameworks/_cases/self4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "self": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "./_cases/self4.php" ], "MyNamespace\\A->addTestFile()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "./_cases/self4.php" ], "MyNamespace\\DS": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "./_cases/self4.php" ], "DS": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "./_cases/self4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "uri": "./_cases/self4.php" }, "containerName": "" }, @@ -40,7 +40,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "uri": "./_cases/self4.php" }, "containerName": "MyNamespace" }, @@ -57,7 +57,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self4.php" + "uri": "./_cases/self4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self5.php.expected.json b/validation/frameworks/_cases/self5.php.expected.json index bd151dc4..a03daff1 100644 --- a/validation/frameworks/_cases/self5.php.expected.json +++ b/validation/frameworks/_cases/self5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->assertTrue()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" + "./_cases/self5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" + "uri": "./_cases/self5.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" + "uri": "./_cases/self5.php" }, "containerName": "MyNamespace" }, @@ -48,7 +48,7 @@ "name": "typesProvider", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/self5.php" + "uri": "./_cases/self5.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static1.php.expected.json b/validation/frameworks/_cases/static1.php.expected.json index 8c30d6b0..315a05e4 100644 --- a/validation/frameworks/_cases/static1.php.expected.json +++ b/validation/frameworks/_cases/static1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "./_cases/static1.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "./_cases/static1.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "./_cases/static1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "uri": "./_cases/static1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "uri": "./_cases/static1.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "uri": "./_cases/static1.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "uri": "./_cases/static1.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static1.php" + "uri": "./_cases/static1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static2.php.expected.json b/validation/frameworks/_cases/static2.php.expected.json index e1e5ed5f..9dd92498 100644 --- a/validation/frameworks/_cases/static2.php.expected.json +++ b/validation/frameworks/_cases/static2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "./_cases/static2.php" ], "MyNamespace\\A::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "./_cases/static2.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "./_cases/static2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "uri": "./_cases/static2.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "uri": "./_cases/static2.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "uri": "./_cases/static2.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "uri": "./_cases/static2.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static2.php" + "uri": "./_cases/static2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static3.php.expected.json b/validation/frameworks/_cases/static3.php.expected.json index 2ecdc991..88f1db8c 100644 --- a/validation/frameworks/_cases/static3.php.expected.json +++ b/validation/frameworks/_cases/static3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "./_cases/static3.php" ], "MyNamespace\\b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "./_cases/static3.php" ], "b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "./_cases/static3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "uri": "./_cases/static3.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "uri": "./_cases/static3.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "uri": "./_cases/static3.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "uri": "./_cases/static3.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static3.php" + "uri": "./_cases/static3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static4.php.expected.json b/validation/frameworks/_cases/static4.php.expected.json index 186cbe58..6cca3db6 100644 --- a/validation/frameworks/_cases/static4.php.expected.json +++ b/validation/frameworks/_cases/static4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" + "./_cases/static4.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" + "./_cases/static4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" + "uri": "./_cases/static4.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" + "uri": "./_cases/static4.php" }, "containerName": "MyNamespace" }, @@ -53,7 +53,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/static4.php" + "uri": "./_cases/static4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/stringVariable.php.expected.json b/validation/frameworks/_cases/stringVariable.php.expected.json index 129ac637..c5b43bf0 100644 --- a/validation/frameworks/_cases/stringVariable.php.expected.json +++ b/validation/frameworks/_cases/stringVariable.php.expected.json @@ -10,7 +10,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" + "uri": "./_cases/stringVariable.php" }, "containerName": "" }, @@ -27,7 +27,7 @@ "name": "hi", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" + "uri": "./_cases/stringVariable.php" }, "containerName": "B" }, @@ -44,7 +44,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/stringVariable.php" + "uri": "./_cases/stringVariable.php" }, "containerName": "B" }, diff --git a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json index c5c303e3..2a65fa60 100644 --- a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -1,7 +1,7 @@ { "references": { "NameOutsideOfNamespace": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/testQualifiedNameOutsideOfNamespace.php" + "./_cases/testQualifiedNameOutsideOfNamespace.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "SomeNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/testQualifiedNameOutsideOfNamespace.php" + "uri": "./_cases/testQualifiedNameOutsideOfNamespace.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json index 338a1939..af4062b3 100644 --- a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json +++ b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json @@ -1,10 +1,10 @@ { "references": { "CURLAUTH_BASIC": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" + "./_cases/verifyFqsenOnClassProperty.php" ], "Foo->bar": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" + "./_cases/verifyFqsenOnClassProperty.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" + "uri": "./_cases/verifyFqsenOnClassProperty.php" }, "containerName": "" }, @@ -34,7 +34,7 @@ "name": "bar", "kind": 7, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" + "uri": "./_cases/verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, @@ -51,7 +51,7 @@ "name": "foo", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/_cases\/verifyFqsenOnClassProperty.php" + "uri": "./_cases/verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, From 22ddb81f285e32566bfe62240f629c9acb2793e0 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 15 May 2017 15:32:08 -0700 Subject: [PATCH 085/149] Also fix disabled validation test output files --- .../_cases/forLoopReference1.php.expected.json | 8 ++++---- .../_cases/namespaces3.php.expected.json | 6 +++--- .../parameterTypeResolution1.php.expected.json | 12 ++++++------ .../frameworks/_cases/parent2.php.expected.json | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/validation/frameworks/_cases/forLoopReference1.php.expected.json b/validation/frameworks/_cases/forLoopReference1.php.expected.json index 66da6eb7..e861248e 100644 --- a/validation/frameworks/_cases/forLoopReference1.php.expected.json +++ b/validation/frameworks/_cases/forLoopReference1.php.expected.json @@ -1,7 +1,7 @@ { "references": { "ForLoopReference1->foo()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + "./_cases/forLoopReference1.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "ForLoopReference1", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + "uri": "./_cases/forLoopReference1.php" }, "containerName": "" }, @@ -31,7 +31,7 @@ "name": "getThat", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + "uri": "./_cases/forLoopReference1.php" }, "containerName": "ForLoopReference1" }, @@ -48,7 +48,7 @@ "name": "foo", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/forLoopReference1.php" + "uri": "./_cases/forLoopReference1.php" }, "containerName": "ForLoopReference1" }, diff --git a/validation/frameworks/_cases/namespaces3.php.expected.json b/validation/frameworks/_cases/namespaces3.php.expected.json index d347fa2a..14fff5c7 100644 --- a/validation/frameworks/_cases/namespaces3.php.expected.json +++ b/validation/frameworks/_cases/namespaces3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "a\\b": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + "./_cases/namespaces3.php" ], "b": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + "./_cases/namespaces3.php" ], "c": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/namespaces3.php" + "./_cases/namespaces3.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json b/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json index 53858ddf..2910eaf7 100644 --- a/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json +++ b/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "ParamType": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "./_cases/parameterTypeResolution1.php" ], "static": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "./_cases/parameterTypeResolution1.php" ], "ParamType->getAccount()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "./_cases/parameterTypeResolution1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "ParamType", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "uri": "./_cases/parameterTypeResolution1.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "setAccount", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "uri": "./_cases/parameterTypeResolution1.php" }, "containerName": "ParamType" }, @@ -54,7 +54,7 @@ "name": "getAccount", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parameterTypeResolution1.php" + "uri": "./_cases/parameterTypeResolution1.php" }, "containerName": "ParamType" }, diff --git a/validation/frameworks/_cases/parent2.php.expected.json b/validation/frameworks/_cases/parent2.php.expected.json index bedd4d53..dcaf9d4a 100644 --- a/validation/frameworks/_cases/parent2.php.expected.json +++ b/validation/frameworks/_cases/parent2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "./_cases/parent2.php" ], "PARENT::b()": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "./_cases/parent2.php" ], "PARENT": [ - "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "./_cases/parent2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "uri": "./_cases/parent2.php" }, "containerName": "" }, @@ -37,7 +37,7 @@ "name": "B", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "uri": "./_cases/parent2.php" }, "containerName": "MyNamespace" }, @@ -54,7 +54,7 @@ "name": "b", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "uri": "./_cases/parent2.php" }, "containerName": "MyNamespace\\B" }, @@ -73,7 +73,7 @@ "name": "A", "kind": 5, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "uri": "./_cases/parent2.php" }, "containerName": "MyNamespace" }, @@ -90,7 +90,7 @@ "name": "a", "kind": 6, "location": { - "uri": "\/Users\/roblou\/code\/php-language-server\/tests\/Validation\/..\/..\/validation\/frameworks\/broken\/parent2.php" + "uri": "./_cases/parent2.php" }, "containerName": "MyNamespace\\A" }, From 403e0c57436ccf74cb4ca9b3b1b85589775f9598 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 15 May 2017 15:32:29 -0700 Subject: [PATCH 086/149] Remove diagnostics log disable hack --- src/LoggedDefinitionResolverTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LoggedDefinitionResolverTrait.php b/src/LoggedDefinitionResolverTrait.php index f5b5d305..3c37d370 100644 --- a/src/LoggedDefinitionResolverTrait.php +++ b/src/LoggedDefinitionResolverTrait.php @@ -156,7 +156,6 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition public function resolveReferenceNodeToDefinition($node) { // var_dump(array_keys(self::$instance->index->getDefinitions())); - self::$logger = false; return $this->logMethod('resolveReferenceNodeToDefinition', $node); } From e46d0ded1105f1179819b4c8f193cf590a53e65e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 15 May 2017 16:47:42 -0700 Subject: [PATCH 087/149] Fix 'type_class' set to wrong value --- tests/Validation/ValidationTest.php | 6 +++--- .../frameworks/_cases/WithReturnTypehints.php.expected.json | 2 -- ...nonymousClassMembersShouldNotBeSymbols.php.expected.json | 1 - .../_cases/arrayValueShouldBeBoolean.php.expected.json | 1 - .../frameworks/_cases/caseStatement1.php.expected.json | 1 - .../frameworks/_cases/classDefinition1.php.expected.json | 2 -- .../frameworks/_cases/classProperty1.php.expected.json | 2 -- validation/frameworks/_cases/constants.php.expected.json | 2 -- validation/frameworks/_cases/constants2.php.expected.json | 2 -- validation/frameworks/_cases/constants3.php.expected.json | 2 -- validation/frameworks/_cases/constants4.php.expected.json | 2 -- validation/frameworks/_cases/constants5.php.expected.json | 2 -- .../constantsInFunctionParamDefault.php.expected.json | 1 - .../_cases/docBlocksOnNamespaceDefinition.php.expected.json | 1 - validation/frameworks/_cases/exceptions1.php.expected.json | 1 - validation/frameworks/_cases/ifStatement1.php.expected.json | 1 - .../frameworks/_cases/interfaceProperty.php.expected.json | 1 - .../_cases/magicConstantsShouldBeGlobal.php.expected.json | 1 - validation/frameworks/_cases/magicConsts.php.expected.json | 1 - .../frameworks/_cases/memberAccess1.php.expected.json | 2 -- .../frameworks/_cases/memberAccess2.php.expected.json | 2 -- .../frameworks/_cases/memberAccess3.php.expected.json | 2 -- .../frameworks/_cases/memberAccess4.php.expected.json | 2 -- .../frameworks/_cases/memberAccess5.php.expected.json | 2 -- validation/frameworks/_cases/memberCall1.php.expected.json | 2 -- .../frameworks/_cases/multipleNamespaces.php.expected.json | 4 ---- .../_cases/multiplePreceedingComments.php.expected.json | 1 - validation/frameworks/_cases/nameToken.php.expected.json | 1 - validation/frameworks/_cases/namespaces2.php.expected.json | 1 - validation/frameworks/_cases/namespaces5.php.expected.json | 1 - validation/frameworks/_cases/namespaces6.php.expected.json | 1 - validation/frameworks/_cases/namespaces8.php.expected.json | 1 - .../frameworks/_cases/objectCreation.php.expected.json | 2 -- .../frameworks/_cases/objectCreation2.php.expected.json | 3 --- .../frameworks/_cases/objectCreation3.php.expected.json | 1 - validation/frameworks/_cases/param1.php.expected.json | 1 - validation/frameworks/_cases/parent1.php.expected.json | 3 --- validation/frameworks/_cases/parent3.php.expected.json | 3 --- .../frameworks/_cases/propertyName1.php.expected.json | 1 - .../frameworks/_cases/propertyName2.php.expected.json | 1 - validation/frameworks/_cases/returnType.php.expected.json | 1 - .../_cases/scopedPropertyAccess.php.expected.json | 2 -- .../_cases/scopedPropertyAccess2.php.expected.json | 1 - .../_cases/scopedPropertyAccess3.php.expected.json | 1 - .../_cases/scopedPropertyAccess5.php.expected.json | 1 - validation/frameworks/_cases/self1.php.expected.json | 3 --- validation/frameworks/_cases/self2.php.expected.json | 3 --- validation/frameworks/_cases/self3.php.expected.json | 3 --- validation/frameworks/_cases/self4.php.expected.json | 2 -- validation/frameworks/_cases/self5.php.expected.json | 2 -- validation/frameworks/_cases/static1.php.expected.json | 3 --- validation/frameworks/_cases/static2.php.expected.json | 3 --- validation/frameworks/_cases/static3.php.expected.json | 3 --- validation/frameworks/_cases/static4.php.expected.json | 2 -- .../frameworks/_cases/stringVariable.php.expected.json | 1 - .../testQualifiedNameOutsideOfNamespace.php.expected.json | 1 - .../_cases/verifyFqsenOnClassProperty.php.expected.json | 1 - 57 files changed, 3 insertions(+), 99 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index a7d3ec11..c3253c94 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -69,7 +69,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { $outputFile = getExpectedValuesFile($testCaseFile); if (!file_exists($outputFile)) { - file_put_contents(json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); + file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); } $expectedValues = (array)json_decode(file_get_contents($outputFile)); @@ -153,9 +153,9 @@ private function getTestValuesFromDefs($definitions): array unset($definition->$propertyName->location->range); } elseif ($propertyName === 'extends') { $definition->$propertyName = $definition->$propertyName ?? []; - } elseif ($propertyName === 'type') { + } elseif ($propertyName === 'type' && $definition->type !== null) { // Class info is not captured by json_encode. It's important for 'type'. - $defsForAssert[$fqn][$propertyName . '__class'] = get_class($definition->$propertyName); + $defsForAssert[$fqn]['type__class'] = get_class($definition->type); } $defsForAssert[$fqn][$propertyName] = $definition->$propertyName; diff --git a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json index 17a5213b..dd00cd53 100644 --- a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json +++ b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "Fixtures" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -43,7 +42,6 @@ }, "containerName": "Fixtures\\Prophecy" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index 719e3884..b0a09822 100644 --- a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json index 78acadd3..c461f3e7 100644 --- a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json +++ b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/caseStatement1.php.expected.json b/validation/frameworks/_cases/caseStatement1.php.expected.json index 545de327..c3021392 100644 --- a/validation/frameworks/_cases/caseStatement1.php.expected.json +++ b/validation/frameworks/_cases/caseStatement1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/classDefinition1.php.expected.json b/validation/frameworks/_cases/classDefinition1.php.expected.json index 52dd9f62..efd937af 100644 --- a/validation/frameworks/_cases/classDefinition1.php.expected.json +++ b/validation/frameworks/_cases/classDefinition1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "TestNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/classProperty1.php.expected.json b/validation/frameworks/_cases/classProperty1.php.expected.json index 5affe9d9..56c87822 100644 --- a/validation/frameworks/_cases/classProperty1.php.expected.json +++ b/validation/frameworks/_cases/classProperty1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "TestNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constants.php.expected.json b/validation/frameworks/_cases/constants.php.expected.json index 0c95336e..228f838c 100644 --- a/validation/frameworks/_cases/constants.php.expected.json +++ b/validation/frameworks/_cases/constants.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constants2.php.expected.json b/validation/frameworks/_cases/constants2.php.expected.json index ee44131f..04040068 100644 --- a/validation/frameworks/_cases/constants2.php.expected.json +++ b/validation/frameworks/_cases/constants2.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constants3.php.expected.json b/validation/frameworks/_cases/constants3.php.expected.json index 35b13da9..0ddad8ce 100644 --- a/validation/frameworks/_cases/constants3.php.expected.json +++ b/validation/frameworks/_cases/constants3.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constants4.php.expected.json b/validation/frameworks/_cases/constants4.php.expected.json index 8f0752ad..a1fe6634 100644 --- a/validation/frameworks/_cases/constants4.php.expected.json +++ b/validation/frameworks/_cases/constants4.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constants5.php.expected.json b/validation/frameworks/_cases/constants5.php.expected.json index 0a3b68cf..c7ebff95 100644 --- a/validation/frameworks/_cases/constants5.php.expected.json +++ b/validation/frameworks/_cases/constants5.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -35,7 +34,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json index 8ba8a2f2..89613e98 100644 --- a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json +++ b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json index 50afd5e1..1e72d0dd 100644 --- a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json +++ b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/exceptions1.php.expected.json b/validation/frameworks/_cases/exceptions1.php.expected.json index debebd20..12047798 100644 --- a/validation/frameworks/_cases/exceptions1.php.expected.json +++ b/validation/frameworks/_cases/exceptions1.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/ifStatement1.php.expected.json b/validation/frameworks/_cases/ifStatement1.php.expected.json index 26d91dc9..1341d08b 100644 --- a/validation/frameworks/_cases/ifStatement1.php.expected.json +++ b/validation/frameworks/_cases/ifStatement1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/interfaceProperty.php.expected.json b/validation/frameworks/_cases/interfaceProperty.php.expected.json index a4787cef..56dbc279 100644 --- a/validation/frameworks/_cases/interfaceProperty.php.expected.json +++ b/validation/frameworks/_cases/interfaceProperty.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json index 9e5002b1..95737a9c 100644 --- a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json +++ b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/magicConsts.php.expected.json b/validation/frameworks/_cases/magicConsts.php.expected.json index ce249ba3..ddbe0967 100644 --- a/validation/frameworks/_cases/magicConsts.php.expected.json +++ b/validation/frameworks/_cases/magicConsts.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberAccess1.php.expected.json b/validation/frameworks/_cases/memberAccess1.php.expected.json index 3e4d354b..66601b86 100644 --- a/validation/frameworks/_cases/memberAccess1.php.expected.json +++ b/validation/frameworks/_cases/memberAccess1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberAccess2.php.expected.json b/validation/frameworks/_cases/memberAccess2.php.expected.json index 69a1e6a0..ad94aa69 100644 --- a/validation/frameworks/_cases/memberAccess2.php.expected.json +++ b/validation/frameworks/_cases/memberAccess2.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberAccess3.php.expected.json b/validation/frameworks/_cases/memberAccess3.php.expected.json index 6486a9c1..68e4ae33 100644 --- a/validation/frameworks/_cases/memberAccess3.php.expected.json +++ b/validation/frameworks/_cases/memberAccess3.php.expected.json @@ -36,7 +36,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -53,7 +52,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberAccess4.php.expected.json b/validation/frameworks/_cases/memberAccess4.php.expected.json index 78887b3d..c6b939ea 100644 --- a/validation/frameworks/_cases/memberAccess4.php.expected.json +++ b/validation/frameworks/_cases/memberAccess4.php.expected.json @@ -27,7 +27,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -44,7 +43,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberAccess5.php.expected.json b/validation/frameworks/_cases/memberAccess5.php.expected.json index 40ee9232..60392c40 100644 --- a/validation/frameworks/_cases/memberAccess5.php.expected.json +++ b/validation/frameworks/_cases/memberAccess5.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -31,7 +30,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/memberCall1.php.expected.json b/validation/frameworks/_cases/memberCall1.php.expected.json index fd91dc4b..b2f8a880 100644 --- a/validation/frameworks/_cases/memberCall1.php.expected.json +++ b/validation/frameworks/_cases/memberCall1.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/multipleNamespaces.php.expected.json b/validation/frameworks/_cases/multipleNamespaces.php.expected.json index fdfee7d8..5e630c00 100644 --- a/validation/frameworks/_cases/multipleNamespaces.php.expected.json +++ b/validation/frameworks/_cases/multipleNamespaces.php.expected.json @@ -27,7 +27,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -44,7 +43,6 @@ }, "containerName": "MyNamespace1" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -78,7 +76,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -97,7 +94,6 @@ }, "containerName": "MyNamespace2" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json index 81331edc..686aa455 100644 --- a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json +++ b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/nameToken.php.expected.json b/validation/frameworks/_cases/nameToken.php.expected.json index 256da008..836cf207 100644 --- a/validation/frameworks/_cases/nameToken.php.expected.json +++ b/validation/frameworks/_cases/nameToken.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/namespaces2.php.expected.json b/validation/frameworks/_cases/namespaces2.php.expected.json index a57f8727..b3f73eb0 100644 --- a/validation/frameworks/_cases/namespaces2.php.expected.json +++ b/validation/frameworks/_cases/namespaces2.php.expected.json @@ -27,7 +27,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/namespaces5.php.expected.json b/validation/frameworks/_cases/namespaces5.php.expected.json index 4a9b18d7..ef19aef0 100644 --- a/validation/frameworks/_cases/namespaces5.php.expected.json +++ b/validation/frameworks/_cases/namespaces5.php.expected.json @@ -36,7 +36,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/namespaces6.php.expected.json b/validation/frameworks/_cases/namespaces6.php.expected.json index 4c3e2850..0acbf4a7 100644 --- a/validation/frameworks/_cases/namespaces6.php.expected.json +++ b/validation/frameworks/_cases/namespaces6.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "A" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/namespaces8.php.expected.json b/validation/frameworks/_cases/namespaces8.php.expected.json index 02e5a6e1..ec654b61 100644 --- a/validation/frameworks/_cases/namespaces8.php.expected.json +++ b/validation/frameworks/_cases/namespaces8.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "LanguageServer\\Tests" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/objectCreation.php.expected.json b/validation/frameworks/_cases/objectCreation.php.expected.json index db211bf2..070a8f76 100644 --- a/validation/frameworks/_cases/objectCreation.php.expected.json +++ b/validation/frameworks/_cases/objectCreation.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -35,7 +34,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/objectCreation2.php.expected.json b/validation/frameworks/_cases/objectCreation2.php.expected.json index f18ab104..e887559b 100644 --- a/validation/frameworks/_cases/objectCreation2.php.expected.json +++ b/validation/frameworks/_cases/objectCreation2.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -55,7 +53,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/objectCreation3.php.expected.json b/validation/frameworks/_cases/objectCreation3.php.expected.json index 198ef872..745f5d4f 100644 --- a/validation/frameworks/_cases/objectCreation3.php.expected.json +++ b/validation/frameworks/_cases/objectCreation3.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/param1.php.expected.json b/validation/frameworks/_cases/param1.php.expected.json index 9cf8a0ba..c086acc1 100644 --- a/validation/frameworks/_cases/param1.php.expected.json +++ b/validation/frameworks/_cases/param1.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/parent1.php.expected.json b/validation/frameworks/_cases/parent1.php.expected.json index 1ca0490d..2503280b 100644 --- a/validation/frameworks/_cases/parent1.php.expected.json +++ b/validation/frameworks/_cases/parent1.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -74,7 +72,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/parent3.php.expected.json b/validation/frameworks/_cases/parent3.php.expected.json index 63dab420..37e227f9 100644 --- a/validation/frameworks/_cases/parent3.php.expected.json +++ b/validation/frameworks/_cases/parent3.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/propertyName1.php.expected.json b/validation/frameworks/_cases/propertyName1.php.expected.json index d858143e..56d754c7 100644 --- a/validation/frameworks/_cases/propertyName1.php.expected.json +++ b/validation/frameworks/_cases/propertyName1.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/propertyName2.php.expected.json b/validation/frameworks/_cases/propertyName2.php.expected.json index 916b0145..7adeceed 100644 --- a/validation/frameworks/_cases/propertyName2.php.expected.json +++ b/validation/frameworks/_cases/propertyName2.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/returnType.php.expected.json b/validation/frameworks/_cases/returnType.php.expected.json index a8be8099..aa495886 100644 --- a/validation/frameworks/_cases/returnType.php.expected.json +++ b/validation/frameworks/_cases/returnType.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json index 0212fdfd..6968698a 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -38,7 +37,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json index 375b992b..11b62678 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json index be2c0c3b..fe417b37 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json index 79e7374e..b88e83ec 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json @@ -27,7 +27,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/self1.php.expected.json b/validation/frameworks/_cases/self1.php.expected.json index a6a0a492..d6c1ccda 100644 --- a/validation/frameworks/_cases/self1.php.expected.json +++ b/validation/frameworks/_cases/self1.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/self2.php.expected.json b/validation/frameworks/_cases/self2.php.expected.json index 4820363b..4416af5b 100644 --- a/validation/frameworks/_cases/self2.php.expected.json +++ b/validation/frameworks/_cases/self2.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/self3.php.expected.json b/validation/frameworks/_cases/self3.php.expected.json index 9a5f633f..a75d4cdc 100644 --- a/validation/frameworks/_cases/self3.php.expected.json +++ b/validation/frameworks/_cases/self3.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/self4.php.expected.json b/validation/frameworks/_cases/self4.php.expected.json index b45c143a..fe688f33 100644 --- a/validation/frameworks/_cases/self4.php.expected.json +++ b/validation/frameworks/_cases/self4.php.expected.json @@ -27,7 +27,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -44,7 +43,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/self5.php.expected.json b/validation/frameworks/_cases/self5.php.expected.json index a03daff1..914cf1b7 100644 --- a/validation/frameworks/_cases/self5.php.expected.json +++ b/validation/frameworks/_cases/self5.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -35,7 +34,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/static1.php.expected.json b/validation/frameworks/_cases/static1.php.expected.json index 315a05e4..3a7ddcc7 100644 --- a/validation/frameworks/_cases/static1.php.expected.json +++ b/validation/frameworks/_cases/static1.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/static2.php.expected.json b/validation/frameworks/_cases/static2.php.expected.json index 9dd92498..73dbf9bf 100644 --- a/validation/frameworks/_cases/static2.php.expected.json +++ b/validation/frameworks/_cases/static2.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/static3.php.expected.json b/validation/frameworks/_cases/static3.php.expected.json index 88f1db8c..265a93b8 100644 --- a/validation/frameworks/_cases/static3.php.expected.json +++ b/validation/frameworks/_cases/static3.php.expected.json @@ -24,7 +24,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -41,7 +40,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -77,7 +75,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/static4.php.expected.json b/validation/frameworks/_cases/static4.php.expected.json index 6cca3db6..d0b6aa96 100644 --- a/validation/frameworks/_cases/static4.php.expected.json +++ b/validation/frameworks/_cases/static4.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, @@ -40,7 +39,6 @@ }, "containerName": "MyNamespace" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/stringVariable.php.expected.json b/validation/frameworks/_cases/stringVariable.php.expected.json index c5b43bf0..6afd5c23 100644 --- a/validation/frameworks/_cases/stringVariable.php.expected.json +++ b/validation/frameworks/_cases/stringVariable.php.expected.json @@ -14,7 +14,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, diff --git a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json index 2a65fa60..96cc2b83 100644 --- a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -18,7 +18,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null } diff --git a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json index af4062b3..42ef6d71 100644 --- a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json +++ b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json @@ -21,7 +21,6 @@ }, "containerName": "" }, - "type__class": "LanguageServer\\Tests\\ValidationTest", "type": null, "documentation": null }, From 90b40ef44980bb11837df7b8101e183d981df70e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 17 May 2017 14:57:54 -0700 Subject: [PATCH 088/149] Fix composer references --- composer.json | 2 +- src/ComposerScripts.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 30a00ce0..fa6924cd 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "repositories": [ { "type": "git", - "url": "https://github.com/mousetraps/tolerant-php-parser.git" + "url": "https://github.com/Microsoft/tolerant-php-parser.git" } ], "prefer-stable": true, diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index 086a0101..c8c7a166 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -30,7 +30,7 @@ public static function parseStubs() $finder = new FileSystemFilesFinder; $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); - $parser = Tolerant\Parser(); + $parser = new Tolerant\Parser(); $definitionResolver = new TolerantDefinitionResolver($index); $stubsLocation = null; From 253f9b50a4266e2dfc5f2cb41dfbfb7b444a1a5d Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 17 May 2017 23:41:35 -0700 Subject: [PATCH 089/149] Fix completions on -> next to an unrelated token --- src/CompletionProvider.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index d19c6bf5..c9354a38 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -184,8 +184,9 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi foreach ($prefixes as &$prefix) { $prefix .= '->'; - if ($node->memberName !== null && $node->memberName instanceof Tolerant\Token) { - $prefix .= $node->memberName->getText($node->getFileContents()); + if ($node->memberName !== null && $node->memberName instanceof Tolerant\Token && $offset > $node->memberName->start) { + $memberNameText = $node->memberName->getText($node->getFileContents()); + $prefix .= substr($memberNameText, 0, $offset - $node->memberName->start); } } From 91f13795d6c9567436204a928658fc7b4cd93c86 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 18 May 2017 11:03:13 -0700 Subject: [PATCH 090/149] Don't try to filter completions by member name, vscode does it --- src/CompletionProvider.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index c9354a38..a5de029a 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -125,9 +125,10 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi // This can be made much more performant if the tree follows specific invariants. $node = $doc->getNodeAtPosition($pos); - - if($node !== null && ($offset = $pos->toOffset($node->getFileContents())) > $node->getEndPosition() && - $node->parent->getLastChild() instanceof Tolerant\MissingToken) { + $offset = $node === null ? -1 : $pos->toOffset($node->getFileContents()); + if ($node !== null && $offset > $node->getEndPosition() && + $node->parent->getLastChild() instanceof Tolerant\MissingToken + ) { $node = $node->parent; } @@ -184,10 +185,6 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi foreach ($prefixes as &$prefix) { $prefix .= '->'; - if ($node->memberName !== null && $node->memberName instanceof Tolerant\Token && $offset > $node->memberName->start) { - $memberNameText = $node->memberName->getText($node->getFileContents()); - $prefix .= substr($memberNameText, 0, $offset - $node->memberName->start); - } } unset($prefix); @@ -223,14 +220,10 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi unset($prefix); - $memberName = $scoped->memberName->getText($scoped->getFileContents()); - foreach ($this->index->getDefinitions() as $fqn => $def) { foreach ($prefixes as $prefix) { if (substr(strtolower($fqn), 0, strlen($prefix)) === strtolower($prefix) && !$def->isGlobal) { - if (empty($memberName) || strpos(substr(strtolower($fqn), 0), strtolower($memberName)) !== false) { - $list->items[] = CompletionItem::fromDefinition($def); - } + $list->items[] = CompletionItem::fromDefinition($def); } } } From 1fa29ccae59ad2879a19fbdc1f6c7145f09c91a5 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 18 May 2017 11:17:09 -0700 Subject: [PATCH 091/149] Fix exception thrown when getting completions on Definitions with a null type- this is expected --- src/FqnUtilities.php | 4 ++-- src/TolerantDefinitionResolver.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index f4b53754..40cb4871 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -29,10 +29,10 @@ public static function getDefinedFqn($node) /** * Returns all possible FQNs in a type * - * @param Type $type + * @param Type|null $type * @return string[] */ - public static function getFqnsFromType(Type $type): array + public static function getFqnsFromType($type): array { $fqns = []; if ($type instanceof Types\Object_) { diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php index 38d2ce7b..810eb9fe 100644 --- a/src/TolerantDefinitionResolver.php +++ b/src/TolerantDefinitionResolver.php @@ -537,9 +537,9 @@ public function resolveVariableToNode($var) * If the type could not be resolved, returns Types\Mixed. * * @param Tolerant\Node\Expression $expr - * @return \phpDocumentor\Reflection\Type + * @return \phpDocumentor\Reflection\Type|null */ - public function resolveExpressionNodeToType($expr): Type + public function resolveExpressionNodeToType($expr) { if ($expr == null || $expr instanceof Tolerant\MissingToken || $expr instanceof Tolerant\SkippedToken) { // TODO some members are null or Missing/SkippedToken From 67081c4abeff23a23525d635c6ca20991e11d996 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 18 May 2017 14:26:34 -0700 Subject: [PATCH 092/149] Clean up completions, fix exceptions thrown from running strpos on empty strings --- src/CompletionProvider.php | 33 ++++++++++++++------------------- src/utils.php | 4 ++++ tests/Utils/UtilsTest.php | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 tests/Utils/UtilsTest.php diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index a5de029a..cd78e615 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -13,6 +13,7 @@ CompletionItem, CompletionItemKind }; +use function LanguageServer\{strStartsWith}; use Microsoft\PhpParser as Tolerant; class CompletionProvider @@ -245,10 +246,8 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } foreach ($this->index->getDefinitions() as $fqn => $def) { - if ( - ($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && (empty($prefix) || strpos($fqn, $prefix) !== false) - - ) { + $fqnStartsWithPrefix = strStartsWith($fqn, $prefix); + if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && strStartsWith($fqn, $prefix)) { if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { $namespacePrefix = (string)Tolerant\ResolvedName::buildName($namespaceDefinition->name->nameParts, $node->getFileContents()); @@ -257,7 +256,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $isNotFullyQualified = !($class instanceof Tolerant\Node\QualifiedName) || !$class->isFullyQualifiedName(); if ($isNotFullyQualified) { foreach ($namespaceImportTable as $alias => $name) { - if (strpos($fqn, $name) === 0) { + if (strStartsWith($fqn, $name)) { $fqn = $alias; $isAliased = true; break; @@ -266,13 +265,13 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } - if (!$isNotFullyQualified && ((strpos($fqn, $prefix) === 0) || strpos($fqn, $namespacePrefix . "\\" . $prefix) === 0)) { - $fqn = $fqn; + if (!$isNotFullyQualified && ($fqnStartsWithPrefix || strStartsWith($fqn, $namespacePrefix . "\\" . $prefix))) { + // $fqn = $fqn; } elseif (!$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { if (empty($prefix)) { $fqn = '\\' . $fqn; - } elseif (strpos($fqn, $namespacePrefix . "\\" . $prefix) === 0) { + } elseif (strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)) { $fqn = substr($fqn, strlen($namespacePrefix) + 1); } else { continue; @@ -280,7 +279,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } elseif (!$isAliased) { continue; } - } elseif (strpos($fqn, $prefix) === 0 && $class->isFullyQualifiedName()) { + } elseif ($fqnStartsWithPrefix && $class->isFullyQualifiedName()) { $fqn = '\\' . $fqn; } @@ -293,21 +292,17 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi if (!isset($creation)) { foreach (self::KEYWORDS as $keyword) { - if (strpos($keyword, $prefix) === 0) { - $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); - $item->insertText = $keyword . ' '; - $list->items[] = $item; - } + $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); + $item->insertText = $keyword . ' '; + $list->items[] = $item; } } } elseif (TolerantParserHelpers::isConstantFetch($node)) { $prefix = (string) ($node->getResolvedName() ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); foreach (self::KEYWORDS as $keyword) { - if (strpos($keyword, $prefix) === 0) { - $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); - $item->insertText = $keyword . ' '; - $list->items[] = $item; - } + $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); + $item->insertText = $keyword . ' '; + $list->items[] = $item; } } diff --git a/src/utils.php b/src/utils.php index c0c5bf73..8c854d3c 100644 --- a/src/utils.php +++ b/src/utils.php @@ -189,3 +189,7 @@ function getVendorDir(\stdClass $composerJson = null): string { return $composerJson->config->{'vendor-dir'} ?? 'vendor'; } + +function strStartsWith(string $haystack, string $prefix): bool { + return empty($prefix) || strpos($haystack, $prefix) === 0; +} diff --git a/tests/Utils/UtilsTest.php b/tests/Utils/UtilsTest.php new file mode 100644 index 00000000..d225ff26 --- /dev/null +++ b/tests/Utils/UtilsTest.php @@ -0,0 +1,34 @@ +assertEquals(strStartsWith($haystack, $prefix), $expectedResult); + } +} From b5412621d6be5f39e59b54ddb2c712e46bceca40 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 18 May 2017 18:58:01 -0700 Subject: [PATCH 093/149] Fix completion tests to handle receiving all items --- src/CompletionProvider.php | 5 ++- tests/Server/TextDocument/CompletionTest.php | 40 ++++++++++++-------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index cd78e615..4c42ff49 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -247,7 +247,8 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi foreach ($this->index->getDefinitions() as $fqn => $def) { $fqnStartsWithPrefix = strStartsWith($fqn, $prefix); - if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && strStartsWith($fqn, $prefix)) { + $fqnContainsPrefix = empty($prefix) || strpos($fqn, $prefix) !== false; + if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && $fqnContainsPrefix) { if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { $namespacePrefix = (string)Tolerant\ResolvedName::buildName($namespaceDefinition->name->nameParts, $node->getFileContents()); @@ -306,7 +307,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } - return $list; + return $list; } /** diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index 20743de4..e8b417d0 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -53,7 +53,7 @@ public function testPropertyAndMethodWithPrefix() new TextDocumentIdentifier($completionUri), new Position(3, 7) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'testProperty', CompletionItemKind::PROPERTY, @@ -77,7 +77,7 @@ public function testPropertyAndMethodWithoutPrefix() new TextDocumentIdentifier($completionUri), new Position(3, 6) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'testProperty', CompletionItemKind::PROPERTY, @@ -101,7 +101,7 @@ public function testVariable() new TextDocumentIdentifier($completionUri), new Position(8, 5) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( '$var', CompletionItemKind::VARIABLE, @@ -133,7 +133,7 @@ public function testVariableWithPrefix() new TextDocumentIdentifier($completionUri), new Position(8, 6) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( '$param', CompletionItemKind::VARIABLE, @@ -155,7 +155,7 @@ public function testNewInNamespace() new TextDocumentIdentifier($completionUri), new Position(6, 10) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ // Global TestClass definition (inserted as \TestClass) new CompletionItem( 'TestClass', @@ -205,7 +205,7 @@ public function testUsedClass() new TextDocumentIdentifier($completionUri), new Position(6, 5) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'TestClass', CompletionItemKind::CLASS_, @@ -226,7 +226,7 @@ public function testStaticPropertyWithPrefix() new TextDocumentIdentifier($completionUri), new Position(2, 14) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'staticTestProperty', CompletionItemKind::PROPERTY, @@ -247,7 +247,7 @@ public function testStaticWithoutPrefix() new TextDocumentIdentifier($completionUri), new Position(2, 11) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'TEST_CLASS_CONST', CompletionItemKind::VARIABLE, @@ -280,7 +280,7 @@ public function testStaticMethodWithPrefix() new TextDocumentIdentifier($completionUri), new Position(2, 13) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'TEST_CLASS_CONST', CompletionItemKind::VARIABLE, @@ -313,7 +313,7 @@ public function testClassConstWithPrefix() new TextDocumentIdentifier($completionUri), new Position(2, 13) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'TEST_CLASS_CONST', CompletionItemKind::VARIABLE, @@ -346,7 +346,7 @@ public function testFullyQualifiedClass() new TextDocumentIdentifier($completionUri), new Position(6, 6) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'TestClass', CompletionItemKind::CLASS_, @@ -367,7 +367,7 @@ public function testKeywords() new TextDocumentIdentifier($completionUri), new Position(2, 1) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem('class', CompletionItemKind::KEYWORD, null, null, null, null, 'class '), new CompletionItem('clone', CompletionItemKind::KEYWORD, null, null, null, null, 'clone ') ], true), $items); @@ -381,7 +381,7 @@ public function testHtmlWithoutPrefix() new TextDocumentIdentifier($completionUri), new Position(0, 0) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( 'SomeNamespace', CompletionItemKind::MODULE, @@ -446,7 +446,7 @@ public function testBarePhp() new TextDocumentIdentifier($completionUri), new Position(4, 8) )->wait(); - $this->assertEquals(new CompletionList([ + $this->assertCompletionsListSubset(new CompletionList([ new CompletionItem( '$abc2', CompletionItemKind::VARIABLE, @@ -469,4 +469,12 @@ public function testBarePhp() ) ], true), $items); } + + private function assertCompletionsListSubset(CompletionList $subsetList, CompletionList $list) { + foreach ($subsetList->items as $expectedItem) { + $this->assertContains($expectedItem, $list->items, null, null, false); + } + + $this->assertEquals($subsetList->isIncomplete, $list->isIncomplete); + } } From f2e6e3aa66acbd542e810120a58f79d8d1d57e3e Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 10:46:13 -0700 Subject: [PATCH 094/149] Remove tmp test logging --- tests/Server/TextDocument/Definition/GlobalTest.php | 1 - tests/Validation/ValidationTest.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/Server/TextDocument/Definition/GlobalTest.php b/tests/Server/TextDocument/Definition/GlobalTest.php index e800ec14..0988e2ae 100644 --- a/tests/Server/TextDocument/Definition/GlobalTest.php +++ b/tests/Server/TextDocument/Definition/GlobalTest.php @@ -26,7 +26,6 @@ public function testDefinitionEmptyResult() new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), new Position(1, 0) )->wait(); - var_dump($result); $this->assertEquals([], $result); } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index c3253c94..a66e82e5 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -62,8 +62,6 @@ public function frameworkErrorProvider() { * @param $frameworkName */ public function testDefinitionErrors($testCaseFile, $frameworkName) { - echo "Test file: " . realpath($testCaseFile) . PHP_EOL; - $fileContents = file_get_contents($testCaseFile); $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); From fc3e8ef3496bcc7cb32c9ac0b459d5381e3435a8 Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 10:55:22 -0700 Subject: [PATCH 095/149] Fix ParseErrorTests --- tests/Server/TextDocument/ParseErrorsTest.php | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/tests/Server/TextDocument/ParseErrorsTest.php b/tests/Server/TextDocument/ParseErrorsTest.php index f3a3d3bf..68948ef9 100644 --- a/tests/Server/TextDocument/ParseErrorsTest.php +++ b/tests/Server/TextDocument/ParseErrorsTest.php @@ -64,42 +64,91 @@ public function testParseErrorsArePublishedAsDiagnostics() 'range' => [ 'start' => [ 'line' => 2, - 'character' => 10 + 'character' => 9 ], 'end' => [ 'line' => 2, - 'character' => 15 + 'character' => 9 ] ], 'severity' => DiagnosticSeverity::ERROR, 'code' => null, 'source' => 'php', - 'message' => "Syntax error, unexpected T_CLASS, expecting T_STRING" - ]] - ], json_decode(json_encode($this->args), true)); - } - - public function testParseErrorsWithOnlyStartLine() - { - $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php'); - $this->assertEquals([ - 'whatever', - [[ + 'message' => "'Name' expected." + ], + [ + 'range' => [ + 'start' => [ + 'line' => 2, + 'character' => 9 + ], + 'end' => [ + 'line' => 2, + 'character' => 9 + ] + ], + 'severity' => DiagnosticSeverity::ERROR, + 'code' => null, + 'source' => 'php', + 'message' => "'{' expected." + ], + [ + 'range' => [ + 'start' => [ + 'line' => 2, + 'character' => 9 + ], + 'end' => [ + 'line' => 2, + 'character' => 9 + ] + ], + 'severity' => DiagnosticSeverity::ERROR, + 'code' => null, + 'source' => 'php', + 'message' => "'}' expected." + ], + [ 'range' => [ 'start' => [ - 'line' => 4, - 'character' => 0 + 'line' => 2, + 'character' => 15 ], 'end' => [ - 'line' => 4, - 'character' => 0 + 'line' => 2, + 'character' => 15 ] ], 'severity' => DiagnosticSeverity::ERROR, 'code' => null, 'source' => 'php', - 'message' => "Namespace declaration statement has to be the very first statement in the script" + 'message' => "'Name' expected." ]] ], json_decode(json_encode($this->args), true)); } + + // This diagnostic not yet implemented in tolerant-php-parser + // public function testParseErrorsWithOnlyStartLine() + // { + // $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php'); + // $this->assertEquals([ + // 'whatever', + // [[ + // 'range' => [ + // 'start' => [ + // 'line' => 4, + // 'character' => 0 + // ], + // 'end' => [ + // 'line' => 4, + // 'character' => 0 + // ] + // ], + // 'severity' => DiagnosticSeverity::ERROR, + // 'code' => null, + // 'source' => 'php', + // 'message' => "Namespace declaration statement has to be the very first statement in the script" + // ]] + // ], json_decode(json_encode($this->args), true)); + // } } From a9be548cb1e62c8022c21a20773884c9dacaeeaa Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 11:16:29 -0700 Subject: [PATCH 096/149] Remove LoggedDefinitionResolver --- src/LoggedDefinitionResolver.php | 9 - src/LoggedDefinitionResolverTrait.php | 249 ----------------------- src/LoggedTolerantDefinitionResolver.php | 9 - 3 files changed, 267 deletions(-) delete mode 100644 src/LoggedDefinitionResolver.php delete mode 100644 src/LoggedDefinitionResolverTrait.php delete mode 100644 src/LoggedTolerantDefinitionResolver.php diff --git a/src/LoggedDefinitionResolver.php b/src/LoggedDefinitionResolver.php deleted file mode 100644 index e0a42389..00000000 --- a/src/LoggedDefinitionResolver.php +++ /dev/null @@ -1,9 +0,0 @@ -getString($param1) . ", " . $this->getString($param2) . ")\n"; - echo str_repeat("\t", self::$recursion) . $callStr; - } - $start = microtime(true); - for ($i = 0; $i < self::$repeat; $i++) { - - $result = parent::$methodName($param1, $param2); - } - - $end = microtime(true) - $start; - - } else { - if (self::$logger === true) { - $callStr .= $this->getString($param1) . ")\n"; - echo str_repeat("\t", self::$recursion) . $callStr; - } - $start = microtime(true); - for ($i = 0; $i < self::$repeat; $i++) { - $result = parent::$methodName($param1); - } - $end = microtime(true) - $start; - } - self::$recursion--; - if (self::$recursion === 1) { - if (!isset(self::$times[$methodName])) { - self::$times[$methodName] = $end; - } else { - self::$times[$methodName] += $end; - } - } - - if (self::$logger === true) { - if ($result instanceof Definition) { - $resultText = $result->fqn; - } elseif ($result instanceof DocBlock) { - $resultText = $result->getDescription(); - } - else { - try { - if ($result instanceof Node) { - $resultText = (new PrettyPrinter())->prettyPrint([$result]); - } else { - $resultText = (string) $result; - } - } catch (\Throwable $e) { - $resultText = "UNKNOWN"; - } - } - echo str_repeat("\t", self::$recursion + 1) . "> RESULT[$callStr]: " . $resultText . "\n"; - } - return $result; - } - - private function getString($param) { - if ($param instanceof Tolerant\Node) { - return "[" . $param->getNodeKindName() . "] " . \strtok($param->getText(), "\n"); - } elseif ($param instanceof Node) { - $pretty = isset($param->name) ? (string) $param->name : "UNKNOWN"; - return "[" . $param->getType() . "] " . \strtok($pretty, "\n"); - } - return (string)$param; - } - - /** - * Builds the declaration line for a given node. - * - * - * @param Tolerant\Node $node - * @return string - */ - public function getDeclarationLineFromNode($node): string - { - return $this->logMethod('getDeclarationLineFromNode', $node); - } - - /** - * Gets the documentation string for a node, if it has one - * - * @param Tolerant\Node $node - * @return string|null - */ - public function getDocumentationFromNode($node) - { - return $this->logMethod('getDocumentationFromNode', $node); - } - - function getDocBlock(Tolerant\Node $node) { - return $this->logMethod('getDocBlock', $node); - - } - - /** - * Create a Definition for a definition node - * - * @param Tolerant\Node $node - * @param string $fqn - * @return Definition - */ - public function createDefinitionFromNode($node, string $fqn = null): Definition - { - return $this->logMethod('createDefinitionFromNode', $node, $fqn); - } - - /** - * Given any node, returns the Definition object of the symbol that is referenced - * - * @param Tolerant\Node $node Any reference node - * @return Definition|null - */ - public function resolveReferenceNodeToDefinition($node) - { -// var_dump(array_keys(self::$instance->index->getDefinitions())); - return $this->logMethod('resolveReferenceNodeToDefinition', $node); - } - - /** - * Given any node, returns the FQN of the symbol that is referenced - * Returns null if the FQN could not be resolved or the reference node references a variable - * - * @param Tolerant\Node $node - * @return string|null - */ - public function resolveReferenceNodeToFqn($node) { - return $this->logMethod('resolveReferenceNodeToFqn', $node); - } - - /** - * Returns the assignment or parameter node where a variable was defined - * - * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access - * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null - */ - public function resolveVariableToNode($var) - { - return $this->logMethod('resolveVariableToNode', $var); - } - - /** - * Given an expression node, resolves that expression recursively to a type. - * If the type could not be resolved, returns Types\Mixed. - * - * @param \PhpParser\Node\Expr $expr - * @return \phpDocumentor\Reflection\Type - */ - public function resolveExpressionNodeToType($expr): Type - { - return $this->logMethod('resolveExpressionNodeToType', $expr); - } - - /** - * 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 - * - * @param Tolerant\Node || Tolerant\Token $class - * @return Type - */ - public function resolveClassNameToType($class): Type - { - return $this->logMethod('resolveClassNameToType', $class); - } - - /** - * Returns the type a reference to this symbol will resolve to. - * For properties and constants, this is the type of the property/constant. - * For functions and methods, this is the return type. - * For parameters, this is the type of the parameter. - * For classes and interfaces, this is the class type (object). - * For variables / assignments, this is the documented type or type the assignment resolves to. - * Can also be a compound type. - * If it is unknown, will be Types\Mixed. - * Returns null if the node does not have a type. - * - * @param Tolerant\Node $node - * @return \phpDocumentor\Reflection\Type|null - */ - public function getTypeFromNode($node) - { - return $this->logMethod('getTypeFromNode', $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 - * - * @param Tolerant\Node $node - * @return string|null - */ - public static function getDefinedFqn($node) - { - $result = parent::getDefinedFqn($node); - if (self::$logger === true) { - echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; - var_dump($result); - } - return $result; - } - - public function printLogs() { - var_dump(self::$times); - var_dump(self::$maxRecursion); - } -} diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php deleted file mode 100644 index 9466ce06..00000000 --- a/src/LoggedTolerantDefinitionResolver.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Fri, 19 May 2017 13:39:16 -0700 Subject: [PATCH 097/149] Remove original DefinitionResolver, remove "Tolerant" on file names --- Performance.php | 4 +- src/CompletionProvider.php | 16 +- src/ComposerScripts.php | 2 +- src/DefinitionResolver.php | 1219 +++++++++++------ src/FqnUtilities.php | 2 +- src/LanguageServer.php | 4 +- src/NodeVisitor/DefinitionCollector.php | 4 +- src/NodeVisitor/ReferencesCollector.php | 6 +- ...antParserHelpers.php => ParserHelpers.php} | 4 +- src/PhpDocument.php | 8 +- src/PhpDocumentLoader.php | 6 +- src/Protocol/SymbolInformation.php | 59 +- src/Protocol/TolerantSymbolInformation.php | 85 -- src/Server/TextDocument.php | 8 +- src/TolerantDefinitionResolver.php | 1182 ---------------- src/TolerantTreeAnalyzer.php | 186 --- src/TreeAnalyzer.php | 163 ++- src/TreeAnalyzerInterface.php | 34 - tests/NodeVisitor/DefinitionCollectorTest.php | 6 +- tests/PhpDocumentLoaderTest.php | 4 +- tests/PhpDocumentTest.php | 4 +- tests/Server/ServerTestCase.php | 4 +- tests/Server/TextDocument/CompletionTest.php | 4 +- .../Definition/GlobalFallbackTest.php | 4 +- tests/Server/TextDocument/DidChangeTest.php | 4 +- tests/Server/TextDocument/DidCloseTest.php | 4 +- tests/Server/TextDocument/FormattingTest.php | 4 +- tests/Server/TextDocument/ParseErrorsTest.php | 4 +- .../References/GlobalFallbackTest.php | 4 +- tests/Validation/ValidationTest.php | 4 +- 30 files changed, 975 insertions(+), 2067 deletions(-) rename src/{TolerantParserHelpers.php => ParserHelpers.php} (99%) delete mode 100644 src/Protocol/TolerantSymbolInformation.php delete mode 100644 src/TolerantDefinitionResolver.php delete mode 100644 src/TolerantTreeAnalyzer.php delete mode 100644 src/TreeAnalyzerInterface.php diff --git a/Performance.php b/Performance.php index 8ed002fb..3a04bc7b 100644 --- a/Performance.php +++ b/Performance.php @@ -7,7 +7,7 @@ use LanguageServer\Index\Index; use LanguageServer\ParserKind; use LanguageServer\PhpDocument; -use LanguageServer\TolerantDefinitionResolver; +use LanguageServer\DefinitionResolver; use Microsoft\PhpParser as Tolerant; use phpDocumentor\Reflection\DocBlockFactory; use RecursiveDirectoryIterator; @@ -57,7 +57,7 @@ $maxRecursion = []; $definitions = []; - $definitionResolver = new TolerantDefinitionResolver($index); + $definitionResolver = new DefinitionResolver($index); $parser = new Tolerant\Parser(); try { diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 4c42ff49..bdb52f97 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -90,7 +90,7 @@ class CompletionProvider ]; /** - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ private $definitionResolver; @@ -105,10 +105,10 @@ class CompletionProvider private $index; /** - * @param TolerantDefinitionResolver $definitionResolver + * @param DefinitionResolver $definitionResolver * @param ReadableIndex $index */ - public function __construct(TolerantDefinitionResolver $definitionResolver, ReadableIndex $index) + public function __construct(DefinitionResolver $definitionResolver, ReadableIndex $index) { $this->definitionResolver = $definitionResolver; $this->index = $index; @@ -228,7 +228,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } - } elseif (TolerantParserHelpers::isConstantFetch($node) || + } elseif (ParserHelpers::isConstantFetch($node) || ($creation = $node->parent) instanceof Tolerant\Node\Expression\ObjectCreationExpression || (($creation = $node) instanceof Tolerant\Node\Expression\ObjectCreationExpression)) { @@ -298,7 +298,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $list->items[] = $item; } } - } elseif (TolerantParserHelpers::isConstantFetch($node)) { + } elseif (ParserHelpers::isConstantFetch($node)) { $prefix = (string) ($node->getResolvedName() ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents())); foreach (self::KEYWORDS as $keyword) { $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); @@ -355,7 +355,7 @@ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix // Walk the AST upwards until a scope boundary is met $level = $node; - while ($level && !TolerantParserHelpers::isFunctionLike($level)) { + while ($level && !ParserHelpers::isFunctionLike($level)) { // Walk siblings before the node $sibling = $level; while ($sibling = $sibling->getPreviousSibling()) { @@ -369,7 +369,7 @@ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix // If the traversal ended because a function was met, // also add its parameters and closure uses to the result list - if ($level && TolerantParserHelpers::isFunctionLike($level) && $level->parameters !== null) { + if ($level && ParserHelpers::isFunctionLike($level) && $level->parameters !== null) { foreach ($level->parameters->getValues() as $param) { $paramName = $param->getName(); if (empty($namePrefix) || strpos($paramName, $namePrefix) !== false) { @@ -409,7 +409,7 @@ private function findVariableDefinitionsInNode(Tolerant\Node $node, string $name }; $isNotFunctionLike = function($node) { return !( - TolerantParserHelpers::isFunctionLike($node) || + ParserHelpers::isFunctionLike($node) || $node instanceof Tolerant\Node\Statement\ClassDeclaration || $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || $node instanceof Tolerant\Node\Statement\TraitDeclaration diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index c8c7a166..11f04332 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -31,7 +31,7 @@ public static function parseStubs() $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); $parser = new Tolerant\Parser(); - $definitionResolver = new TolerantDefinitionResolver($index); + $definitionResolver = new DefinitionResolver($index); $stubsLocation = null; foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 3bc7b0c5..4843df07 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -3,28 +3,36 @@ namespace LanguageServer; -use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard as PrettyPrinter; -use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; -use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Index\ReadableIndex; +use LanguageServer\Protocol\SymbolInformation; +use Microsoft\PhpParser as Tolerant; +use phpDocumentor\Reflection\{ + DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types +}; +use PhpParser\Node; class DefinitionResolver { /** + * The current project index (for retrieving existing definitions) + * * @var \LanguageServer\Index\ReadableIndex */ - private $index; + protected $index; /** + * Resolves strings to a type object. + * * @var \phpDocumentor\Reflection\TypeResolver */ private $typeResolver; /** - * @var \PhpParser\PrettyPrinterAbstract + * Parses Doc Block comments given the DocBlock text and import tables at a position. + * + * @var DocBlockFactory */ - private $prettyPrinter; + private $docBlockFactory; /** * @param ReadableIndex $index @@ -33,125 +41,203 @@ public function __construct(ReadableIndex $index) { $this->index = $index; $this->typeResolver = new TypeResolver; - $this->prettyPrinter = new PrettyPrinter; + $this->docBlockFactory = DocBlockFactory::createInstance(); } /** - * Builds the declaration line for a given node + * Builds the declaration line for a given node. Declarations with multiple lines are trimmed. * - * @param Node $node + * @param Tolerant\Node $node * @return string */ public function getDeclarationLineFromNode($node): string { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - // Properties and constants can have multiple declarations - // Use the parent node (that includes the modifiers), but only render the requested declaration - $child = $node; - /** @var Node */ - $node = $node->getAttribute('parentNode'); - $defLine = clone $node; - $defLine->props = [$child]; + // If node is part of a declaration list, build a declaration line that discludes other elements in the list + // - [PropertyDeclaration] // public $a, [$b = 3], $c; => public $b = 3; + // - [ConstDeclaration | ClassConstDeclaration] // "const A = 3, [B = 4];" => "const B = 4;" + if ( + ($declaration = ParserHelpers::tryGetPropertyDeclaration($node)) && ($elements = $declaration->propertyElements) || + ($declaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) && ($elements = $declaration->constElements) + ) { + $defLine = $declaration->getText(); + $defLineStart = $declaration->getStart(); + + $defLine = \substr_replace( + $defLine, + $node->getFullText(), + $elements->getFullStart() - $defLineStart, + $elements->getFullWidth() + ); } else { - $defLine = clone $node; + $defLine = $node->getText(); } - // Don't include the docblock in the declaration string - $defLine->setAttribute('comments', []); - if (isset($defLine->stmts)) { - $defLine->stmts = []; - } - $defText = $this->prettyPrinter->prettyPrint([$defLine]); - return strstr($defText, "\n", true) ?: $defText; + + // Trim string to only include first line + $defLine = \rtrim(\strtok($defLine, "\n"), "\r"); + + // TODO - pretty print rather than getting text + + return $defLine; } /** * Gets the documentation string for a node, if it has one * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public function getDocumentationFromNode($node) { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - $node = $node->getAttribute('parentNode'); - } - if ($node instanceof Node\Param) { - $fn = $node->getAttribute('parentNode'); - $docBlock = $fn->getAttribute('docBlock'); - if ($docBlock !== null) { - $tags = $docBlock->getTagsByName('param'); - foreach ($tags as $tag) { - if ($tag->getVariableName() === $node->name) { - return $tag->getDescription()->render(); - } - } + // Any NamespaceDefinition comments likely apply to the file, not the declaration itself. + if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { + return null; + } + + // For properties and constants, set the node to the declaration node, rather than the individual property. + // This is because they get defined as part of a list. + $constOrPropertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node) ?? ParserHelpers::tryGetConstOrClassConstDeclaration($node); + if ($constOrPropertyDeclaration !== null) { + $node = $constOrPropertyDeclaration; + } + + // For parameters, parse the function-like declaration to get documentation for a parameter + if ($node instanceof Tolerant\Node\Parameter) { + $variableName = $node->getName(); + + $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); + $docBlock = $this->getDocBlock($functionLikeDeclaration); + + $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); + return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; + } + + // For everything else, get the doc block summary corresponding to the current node. + $docBlock = $this->getDocBlock($node); + if ($docBlock !== null) { + return $docBlock->getSummary(); + } + return null; + } + + /** + * Gets Doc Block with resolved names for a Node + * + * @param Tolerant\Node $node + * @return DocBlock | null + */ + private function getDocBlock(Tolerant\Node $node) + { + // TODO make more efficient (caching, ensure import table is in right format to begin with) + $docCommentText = $node->getDocCommentText(); + if ($docCommentText !== null) { + list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); + foreach ($namespaceImportTable as $alias=>$name) { + $namespaceImportTable[$alias] = (string)$name; } - } else { - $docBlock = $node->getAttribute('docBlock'); - if ($docBlock !== null) { - return $docBlock->getSummary(); + $namespaceDefinition = $node->getNamespaceDefinition(); + if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { + $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); + } else { + $namespaceName = 'global'; + } + $context = new Types\Context($namespaceName, $namespaceImportTable); + + try { + return $this->docBlockFactory->create($docCommentText, $context); + } catch (\InvalidArgumentException $e) { + return null; } } + return null; } /** * Create a Definition for a definition node * - * @param Node $node + * @param Tolerant\Node $node * @param string $fqn * @return Definition */ public function createDefinitionFromNode($node, string $fqn = null): Definition { - $parent = $node->getAttribute('parentNode'); $def = new Definition; - $def->canBeInstantiated = $node instanceof Node\Stmt\Class_; + $def->fqn = $fqn; + + // Determines whether the suggestion will show after "new" + $def->canBeInstantiated = $node instanceof Tolerant\Node\Statement\ClassDeclaration; + + // Interfaces, classes, traits, namespaces, functions, and global const elements $def->isGlobal = ( - $node instanceof Node\Stmt\ClassLike - || ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) - || $node instanceof Node\Stmt\Function_ - || $parent instanceof Node\Stmt\Const_ + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration || + + ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null) || + + $node instanceof Tolerant\Node\Statement\FunctionDeclaration || + + ($node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration) ); + + // Static methods and static property declarations $def->isStatic = ( - ($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) - || ($node instanceof Node\Stmt\PropertyProperty && $parent->isStatic()) + ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) || + + (($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null + && $propertyDeclaration->isStatic()) ); - $def->fqn = $fqn; - if ($node instanceof Node\Stmt\Class_) { - $def->extends = []; - if ($node->extends) { - $def->extends[] = (string)$node->extends; - } - } else if ($node instanceof Node\Stmt\Interface_) { + + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration && + // TODO - this should be bette rrpreented in the parser API + $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) + { + $def->extends = [(string)$node->classBaseClause->baseClass->getResolvedName()]; + // TODO - why is this represented as an array? + // TODO interface implementations. + } elseif ( + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && + // TODO - this should be better represented in the parser API + $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null + ) { $def->extends = []; - foreach ($node->extends as $n) { - $def->extends[] = (string)$n; + foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { + $def->extends[] = (string)$n->getResolvedName(); } } + $def->symbolInformation = SymbolInformation::fromNode($node, $fqn); - $def->type = $this->getTypeFromNode($node); - $def->declarationLine = $this->getDeclarationLineFromNode($node); - $def->documentation = $this->getDocumentationFromNode($node); -// var_dump($def); + + if ($def->symbolInformation !== null) { + $def->type = $this->getTypeFromNode($node); + $def->declarationLine = $this->getDeclarationLineFromNode($node); + $def->documentation = $this->getDocumentationFromNode($node); + } + return $def; } /** * Given any node, returns the Definition object of the symbol that is referenced * - * @param Node $node Any reference node + * @param Tolerant\Node $node Any reference node * @return Definition|null */ public function resolveReferenceNodeToDefinition($node) { - // Variables are not indexed globally, as they stay in the file scope anyway - if ($node instanceof Node\Expr\Variable) { - // Resolve $this - if ($node->name === 'this' && $fqn = $this->getContainingClassFqn($node)) { + $parent = $node->parent; + // Variables are not indexed globally, as they stay in the file scope anyway. + // Ignore variable nodes that are part of ScopedPropertyAccessExpression, + // as the scoped property access expression node is handled separately. + if ($node instanceof Tolerant\Node\Expression\Variable && + !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) + { + // Resolve $this to the containing class definition. + if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); } + // Resolve the variable to a definition node (assignment, param or closure use) - $defNode = self::resolveVariableToNode($node); + $defNode = $this->resolveVariableToNode($node); if ($defNode === null) { return null; } @@ -165,8 +251,8 @@ public function resolveReferenceNodeToDefinition($node) } // 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 - $parent = $node->getAttribute('parentNode'); - $globalFallback = $parent instanceof Node\Expr\ConstFetch || $parent instanceof Node\Expr\FuncCall; + // TODO - verify that this is not a method + $globalFallback = ParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -178,143 +264,191 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) - { - $parent = $node->getAttribute('parentNode'); + public function resolveReferenceNodeToFqn($node) { + // TODO all name tokens should be a part of a node + if ($node instanceof Tolerant\Node\QualifiedName) { + return $this->resolveQualifiedNameNodeToFqn($node); + } - if ( - $node instanceof Node\Name && ( - $parent instanceof Node\Stmt\ClassLike - || $parent instanceof Node\Param - || $parent instanceof Node\FunctionLike - || $parent instanceof Node\Stmt\GroupUse - || $parent instanceof Node\Expr\New_ - || $parent instanceof Node\Expr\StaticCall - || $parent instanceof Node\Expr\ClassConstFetch - || $parent instanceof Node\Expr\StaticPropertyFetch - || $parent instanceof Node\Expr\Instanceof_ - ) + else if ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { + return $this->resolveMemberAccessExpressionNodeToFqn($node); + } + else if (ParserHelpers::isConstantFetch($node)) { + return (string)($node->getNamespacedName()); + } + else if ( + // A\B::C - constant access expression + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + && !($node->memberName instanceof Tolerant\Node\Expression\Variable) ) { - // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = (string)$node; - // Only the name node should be considered a reference, not the UseUse node itself - } else if ($parent instanceof Node\Stmt\UseUse) { - $name = (string)$parent->name; - $grandParent = $parent->getAttribute('parentNode'); - if ($grandParent instanceof Node\Stmt\GroupUse) { - $name = $grandParent->prefix . '\\' . $name; - } else if ($grandParent instanceof Node\Stmt\Use_ && $grandParent->type === Node\Stmt\Use_::TYPE_FUNCTION) { - $name .= '()'; - } - } else if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { - if ($node->name instanceof Node\Expr) { - // Cannot get definition if right-hand side is expression - return null; - } - // Get the type of the left-hand expression - $varType = $this->resolveExpressionNodeToType($node->var); - if ($varType instanceof Types\Compound) { - // For compound types, use the first FQN we find - // (popular use case is ClassName|null) - for ($i = 0; $t = $varType->get($i); $i++) { - if ( - $t instanceof Types\This - || $t instanceof Types\Object_ - || $t instanceof Types\Static_ - || $t instanceof Types\Self_ - ) { - $varType = $t; - break; + return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); + } else if ( + // A\B::$c - static property access expression + $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ) { + return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node->parent); + } + + return null; + } + + private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { + $parent = $node->parent; + + if ($parent instanceof Tolerant\Node\TraitSelectOrAliasClause) { + return null; + } + // Add use clause references + if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause + || $useClause instanceof Tolerant\Node\NamespaceUseClause + ) { + $contents = $node->getFileContents(); + if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { + $prefix = $useClause->parent->parent->namespaceName; + if ($prefix === null) { + return null; + } + $name = Tolerant\ResolvedName::buildName($prefix->nameParts, $contents); + $name->addNameParts($node->nameParts, $contents); + $name = (string)$name; + + if ($useClause->functionOrConst === null) { + $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); + if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $name .= '()'; } } - } - if ( - $varType instanceof Types\This - || $varType instanceof Types\Static_ - || $varType instanceof Types\Self_ - ) { - // $this/static/self is resolved to the containing class - $classFqn = self::getContainingClassFqn($node); - } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { - // Left-hand expression could not be resolved to a class - return null; + return $name; } else { - $classFqn = substr((string)$varType->getFqsen(), 1); - } - $memberSuffix = '->' . (string)$node->name; - if ($node instanceof Node\Expr\MethodCall) { - $memberSuffix .= '()'; - } - // Find the right class that implements the member - $implementorFqns = [$classFqn]; - while ($implementorFqn = array_shift($implementorFqns)) { - // If the member FQN exists, return it - if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { - return $implementorFqn . $memberSuffix; + $name = (string) Tolerant\ResolvedName::buildName($node->nameParts, $contents); + if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $name .= '()'; } - // Get Definition of implementor class - $implementorDef = $this->index->getDefinition($implementorFqn); - // If it doesn't exist, return the initial guess - if ($implementorDef === null) { + } + + return $name; + } + + // For extends, implements, type hints and classes of classes of static calls use the name directly + $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); + + if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { + $name .= '()'; + } + return $name; + } + + private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression\MemberAccessExpression $access) { + if ($access->memberName instanceof Tolerant\Node\Expression) { + // Cannot get definition if right-hand side is expression + return null; + } + // Get the type of the left-hand expression + $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); + + if ($varType instanceof Types\Compound) { + // For compound types, use the first FQN we find + // (popular use case is ClassName|null) + for ($i = 0; $t = $varType->get($i); $i++) { + if ( + $t instanceof Types\This + || $t instanceof Types\Object_ + || $t instanceof Types\Static_ + || $t instanceof Types\Self_ + ) { + $varType = $t; break; } - // Repeat for parent class - if ($implementorDef->extends) { - foreach ($implementorDef->extends as $extends) { - $implementorFqns[] = $extends; - } + } + } + if ( + $varType instanceof Types\This + || $varType instanceof Types\Static_ + || $varType instanceof Types\Self_ + ) { + // $this/static/self is resolved to the containing class + $classFqn = self::getContainingClassFqn($access); + } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { + // Left-hand expression could not be resolved to a class + return null; + } else { + $classFqn = substr((string)$varType->getFqsen(), 1); + } + $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($access->getFileContents())); + if ($access->parent instanceof Tolerant\Node\Expression\CallExpression) { + $memberSuffix .= '()'; + } + + // Find the right class that implements the member + $implementorFqns = [$classFqn]; + + while ($implementorFqn = array_shift($implementorFqns)) { + // If the member FQN exists, return it + if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { + + return $implementorFqn . $memberSuffix; + } + // Get Definition of implementor class + $implementorDef = $this->index->getDefinition($implementorFqn); + // If it doesn't exist, return the initial guess + if ($implementorDef === null) { + break; + } + // Repeat for parent class + if ($implementorDef->extends) { + foreach ($implementorDef->extends as $extends) { + $implementorFqns[] = $extends; } } - return $classFqn . $memberSuffix; - } else if ($parent instanceof Node\Expr\FuncCall && $node instanceof Node\Name) { - if ($parent->name instanceof Node\Expr) { + } + + return $classFqn . $memberSuffix; + } + + private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { + if ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\Expression\Variable) { + $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); + if ($varType === null) { return null; } - $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); - } else if ($parent instanceof Node\Expr\ConstFetch && $node instanceof Node\Name) { - $name = (string)($node->getAttribute('namespacedName') ?? $parent->name); - } else if ( - $node instanceof Node\Expr\ClassConstFetch - || $node instanceof Node\Expr\StaticPropertyFetch - || $node instanceof Node\Expr\StaticCall - ) { - if ($node->class instanceof Node\Expr || $node->name instanceof Node\Expr) { - // Cannot get definition of dynamic names + $className = substr((string)$varType->getFqsen(), 1); + } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + $className = (string)$scoped->scopeResolutionQualifier->getResolvedName(); + } else { + return null; + } + + if ($className === 'self' || $className === 'static' || $className === 'parent') { + // self and static are resolved to the containing class + $classNode = $scoped->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if ($classNode === null) { return null; } - $className = (string)$node->class; - if ($className === 'self' || $className === 'static' || $className === 'parent') { - // self and static are resolved to the containing class - $classNode = getClosestNode($node, Node\Stmt\Class_::class); - if ($classNode === null) { + if ($className === 'parent') { + // parent is resolved to the parent class + if (!isset($classNode->extends)) { return null; } - if ($className === 'parent') { - // parent is resolved to the parent class - if (!isset($n->extends)) { - return null; - } - $className = (string)$classNode->extends; - } else { - $className = (string)$classNode->namespacedName; - } - } - if ($node instanceof Node\Expr\StaticPropertyFetch) { - $name = (string)$className . '::$' . $node->name; + $className = (string)$classNode->extends->getResolvedName(); } else { - $name = (string)$className . '::' . $node->name; + $className = (string)$classNode->getNamespacedName(); } - } else { - return null; + } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + $className = $scoped->scopeResolutionQualifier->getResolvedName(); } - if (!isset($name)) { - return null; + if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { + if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { + return null; + } + $memberName = $scoped->memberName->getName(); + if (empty($memberName)) { + return null; + } + $name = (string)$className . '::$' . $memberName; + } else { + $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); } - if ( - $node instanceof Node\Expr\MethodCall - || $node instanceof Node\Expr\StaticCall - || $parent instanceof Node\Expr\FuncCall - ) { + if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { $name .= '()'; } return $name; @@ -324,16 +458,16 @@ public function resolveReferenceNodeToFqn($node) * 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 * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ - private static function getContainingClassFqn(Node $node) + private static function getContainingClassFqn(Tolerant\Node $node) { - $classNode = getClosestNode($node, Node\Stmt\Class_::class); - if ($classNode === null || $classNode->isAnonymous()) { + $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + if ($classNode === null) { return null; } - return (string)$classNode->namespacedName; + return (string)$classNode->getNamespacedName(); } /** @@ -345,28 +479,35 @@ private static function getContainingClassFqn(Node $node) public function resolveVariableToNode($var) { $n = $var; - // When a use is passed, start outside the closure to not return immediatly - if ($var instanceof Node\Expr\ClosureUse) { - $n = $var->getAttribute('parentNode')->getAttribute('parentNode'); - $name = $var->var; - } else if ($var instanceof Node\Expr\Variable || $var instanceof Node\Param) { - $name = $var->name; + // When a use is passed, start outside the closure to not return immediately + // Use variable vs variable parsing? + if ($var instanceof Tolerant\Node\UseVariableName) { + $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class)->parent; + $name = $var->getName(); + } else if ($var instanceof Tolerant\Node\Expression\Variable || $var instanceof Tolerant\Node\Parameter) { + $name = $var->getName(); } else { throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); } // Traverse the AST up do { // If a function is met, check the parameters and use statements - if ($n instanceof Node\FunctionLike) { - foreach ($n->getParams() as $param) { - if ($param->name === $name) { - return $param; + if (ParserHelpers::isFunctionLike($n)) { + if ($n->parameters !== null) { + + foreach ($n->parameters->getElements() as $param) { + if ($param->getName() === $name) { + return $param; + } } } // If it is a closure, also check use statements - if ($n instanceof Node\Expr\Closure) { - foreach ($n->uses as $use) { - if ($use->var === $name) { + if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && + $n->anonymousFunctionUseClause !== null && + $n->anonymousFunctionUseClause->useVariableNameList !== null) { + foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use + ) { + if ($use->getName() === $name) { return $use; } } @@ -374,15 +515,19 @@ public function resolveVariableToNode($var) break; } // Check each previous sibling node for a variable assignment to that variable - while ($n->getAttribute('previousSibling') && $n = $n->getAttribute('previousSibling')) { + while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { + if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { + $n = $n->expression; + } if ( - ($n instanceof Node\Expr\Assign || $n instanceof Node\Expr\AssignOp) - && $n->var instanceof Node\Expr\Variable && $n->var->name === $name + // TODO - clean this up + ($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) + && $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name ) { return $n; } } - } while (isset($n) && $n = $n->getAttribute('parentNode')); + } while (isset($n) && $n = $n->parent); // Return null if nothing was found return null; } @@ -391,224 +536,298 @@ public function resolveVariableToNode($var) * Given an expression node, resolves that expression recursively to a type. * If the type could not be resolved, returns Types\Mixed. * - * @param \PhpParser\Node\Expr $expr - * @return \phpDocumentor\Reflection\Type + * @param Tolerant\Node\Expression $expr + * @return \phpDocumentor\Reflection\Type|null */ - public function resolveExpressionNodeToType($expr): Type + public function resolveExpressionNodeToType($expr) { - if ($expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\ClosureUse) { - if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { + if ($expr == null || $expr instanceof Tolerant\MissingToken || $expr instanceof Tolerant\SkippedToken) { + // TODO some members are null or Missing/SkippedToken + // How do we handle this more generally? + return new Types\Mixed; + } + + // PARENTHESIZED EXPRESSION + // Retrieve inner expression from parenthesized expression + while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { + $expr = $expr->expression; + } + + // VARIABLE + // $this -> Type\this + // $myVariable -> type of corresponding assignment expression + if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { + if ($expr->getName() === 'this') { return new Types\This; } - // Find variable definition - + // Find variable definition (parameter or assignment expression) $defNode = $this->resolveVariableToNode($expr); - if ($defNode instanceof Node\Expr) { + if ($defNode instanceof Tolerant\Node\Expression\AssignmentExpression || $defNode instanceof Tolerant\Node\UseVariableName) { return $this->resolveExpressionNodeToType($defNode); } - if ($defNode instanceof Node\Param) { + if ($defNode instanceof Tolerant\Node\Parameter) { return $this->getTypeFromNode($defNode); } } - if ($expr instanceof Node\Expr\FuncCall) { + + // FUNCTION CALL + // Function calls are resolved to type corresponding to their FQN + if ($expr instanceof Tolerant\Node\Expression\CallExpression && + !( + $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) + ) { + // Find the function definition - if ($expr->name instanceof Node\Expr) { + if ($expr->callableExpression instanceof Tolerant\Node\Expression) { // Cannot get type for dynamic function call return new Types\Mixed; } - $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; + + if ($expr->callableExpression instanceof Tolerant\Node\QualifiedName) { + $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName(); + $fqn .= '()'; + $def = $this->index->getDefinition($fqn, true); + if ($def !== null) { + return $def->type; + } } } - if ($expr instanceof Node\Expr\ConstFetch) { - if (strtolower((string)$expr->name) === 'true' || strtolower((string)$expr->name) === 'false') { + + // TRUE / FALSE / NULL + // Resolve true and false reserved words to Types\Boolean + if ($expr instanceof Tolerant\Node\ReservedWord) { + $token = $expr->children->kind; + if ($token === Tolerant\TokenKind::TrueReservedWord || $token === Tolerant\TokenKind::FalseReservedWord) { return new Types\Boolean; } - if (strtolower((string)$expr->name) === 'null') { + + if ($token === Tolerant\TokenKind::NullReservedWord) { return new Types\Null_; } - // Resolve constant - $fqn = (string)($expr->getAttribute('namespacedName') ?? $expr->name); + } + + // CONSTANT FETCH + // Resolve constants by retrieving corresponding definition type from FQN + if (ParserHelpers::isConstantFetch($expr)) { + $fqn = (string)$expr->getNamespacedName(); $def = $this->index->getDefinition($fqn, true); if ($def !== null) { return $def->type; } } - if ($expr instanceof Node\Expr\MethodCall || $expr instanceof Node\Expr\PropertyFetch) { - if ($expr->name instanceof Node\Expr) { - return new Types\Mixed; - } - // Resolve object - $objType = $this->resolveExpressionNodeToType($expr->var); - // var_dump((string)$expr->var->name); -// var_dump($objType); - if (!($objType instanceof Types\Compound)) { - $objType = new Types\Compound([$objType]); - } - for ($i = 0; $t = $objType->get($i); $i++) { - if ($t instanceof Types\This) { - $classFqn = self::getContainingClassFqn($expr); - if ($classFqn === null) { - return new Types\Mixed; - } - } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { - return new Types\Mixed; - } else { - $classFqn = substr((string)$t->getFqsen(), 1); - // var_dump($classFqn); - } - $fqn = $classFqn . '->' . $expr->name; - if ($expr instanceof Node\Expr\MethodCall) { - $fqn .= '()'; - } - $def = $this->index->getDefinition($fqn); - if ($def !== null) { - return $def->type; - } - } + + // MEMBER ACCESS EXPRESSION + if ($expr instanceof Tolerant\Node\Expression\MemberAccessExpression) { + if ($expr->memberName instanceof Tolerant\Node\Expression) { + return new Types\Mixed; + } + $var = $expr->dereferencableExpression; + + // Resolve object + $objType = $this->resolveExpressionNodeToType($var); + if (!($objType instanceof Types\Compound)) { + $objType = new Types\Compound([$objType]); + } + for ($i = 0; $t = $objType->get($i); $i++) { + if ($t instanceof Types\This) { + $classFqn = self::getContainingClassFqn($expr); + if ($classFqn === null) { + return new Types\Mixed; + } + } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { + return new Types\Mixed; + } else { + $classFqn = substr((string)$t->getFqsen(), 1); + } + $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); + if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { + $fqn .= '()'; + } + $def = $this->index->getDefinition($fqn); + if ($def !== null) { + return $def->type; + } + } } - if ( - $expr instanceof Node\Expr\StaticCall - || $expr instanceof Node\Expr\StaticPropertyFetch - || $expr instanceof Node\Expr\ClassConstFetch - ) { - $classType = self::resolveClassNameToType($expr->class); - if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null || $expr->name instanceof Node\Expr) { + + // SCOPED PROPERTY ACCESS EXPRESSION + if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { + $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); + if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { return new Types\Mixed; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; - if ($expr instanceof Node\Expr\StaticPropertyFetch) { - $fqn .= '$'; - } - $fqn .= $expr->name; - if ($expr instanceof Node\Expr\StaticCall) { + + // TODO is there a cleaner way to do this? + $fqn .= $expr->memberName->getText() ?? $expr->memberName->getText($expr->getFileContents()); + if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { $fqn .= '()'; } + $def = $this->index->getDefinition($fqn); if ($def === null) { return new Types\Mixed; } return $def->type; } - if ($expr instanceof Node\Expr\New_) { - return self::resolveClassNameToType($expr->class); + + // OBJECT CREATION EXPRESSION + // new A() => resolves to the type of the class type designator (A) + // TODO: new $this->a => resolves to the string represented by "a" + if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { + return $this->resolveClassNameToType($expr->classTypeDesignator); } - if ($expr instanceof Node\Expr\Clone_ || $expr instanceof Node\Expr\Assign) { - return $this->resolveExpressionNodeToType($expr->expr); + + // CLONE EXPRESSION + // clone($a) => resolves to the type of $a + if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { + return $this->resolveExpressionNodeToType($expr->expression); } - if ($expr instanceof Node\Expr\Ternary) { + + // ASSIGNMENT EXPRESSION + // $a = $myExpression => resolves to the type of the right-hand operand + if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { + return $this->resolveExpressionNodeToType($expr->rightOperand); + } + + // TERNARY EXPRESSION + // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression + // $condition ?: $elseExpression => resolves to type of $condition or $elseExpression + if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { // ?: - if ($expr->if === null) { + if ($expr->ifExpression === null) { return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->cond), - $this->resolveExpressionNodeToType($expr->else) + $this->resolveExpressionNodeToType($expr->condition), // TODO: why? + $this->resolveExpressionNodeToType($expr->elseExpression) ]); } // Ternary is a compound of the two possible values return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->if), - $this->resolveExpressionNodeToType($expr->else) + $this->resolveExpressionNodeToType($expr->ifExpression), + $this->resolveExpressionNodeToType($expr->elseExpression) ]); } - if ($expr instanceof Node\Expr\BinaryOp\Coalesce) { + + // NULL COALLESCE + // $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand + if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { // ?? operator return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->left), - $this->resolveExpressionNodeToType($expr->right) + $this->resolveExpressionNodeToType($expr->leftOperand), + $this->resolveExpressionNodeToType($expr->rightOperand) ]); } + + // BOOLEAN EXPRESSIONS: resolve to Types\Boolean + // (bool) $expression + // !$expression + // empty($var) + // isset($var) + // >, >=, <, <=, &&, ||, AND, OR, XOR, ==, ===, !=, !== if ( - $expr instanceof Node\Expr\Instanceof_ - || $expr instanceof Node\Expr\Cast\Bool_ - || $expr instanceof Node\Expr\BooleanNot - || $expr instanceof Node\Expr\Empty_ - || $expr instanceof Node\Expr\Isset_ - || $expr instanceof Node\Expr\BinaryOp\Greater - || $expr instanceof Node\Expr\BinaryOp\GreaterOrEqual - || $expr instanceof Node\Expr\BinaryOp\Smaller - || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual - || $expr instanceof Node\Expr\BinaryOp\BooleanAnd - || $expr instanceof Node\Expr\BinaryOp\BooleanOr - || $expr instanceof Node\Expr\BinaryOp\LogicalAnd - || $expr instanceof Node\Expr\BinaryOp\LogicalOr - || $expr instanceof Node\Expr\BinaryOp\LogicalXor - || $expr instanceof Node\Expr\BinaryOp\NotEqual - || $expr instanceof Node\Expr\BinaryOp\NotIdentical + ParserHelpers::isBooleanExpression($expr) + + || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) + || ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) + || $expr instanceof Tolerant\Node\Expression\EmptyIntrinsicExpression + || $expr instanceof Tolerant\Node\Expression\IssetIntrinsicExpression ) { return new Types\Boolean; } + + // STRING EXPRESSIONS: resolve to Types\String + // [concatenation] .=, . + // [literals] "hello", \b"hello", \B"hello", 'hello', \b'hello', HEREDOC, NOWDOC + // [cast] (string) "hello" + // + // TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__) if ( - $expr instanceof Node\Expr\Cast\String_ - || $expr instanceof Node\Expr\BinaryOp\Concat - || $expr instanceof Node\Expr\AssignOp\Concat - || $expr instanceof Node\Scalar\String_ - || $expr instanceof Node\Scalar\Encapsed - || $expr instanceof Node\Scalar\EncapsedStringPart - || $expr instanceof Node\Scalar\MagicConst\Class_ - || $expr instanceof Node\Scalar\MagicConst\Dir - || $expr instanceof Node\Scalar\MagicConst\Function_ - || $expr instanceof Node\Scalar\MagicConst\Method - || $expr instanceof Node\Scalar\MagicConst\Namespace_ - || $expr instanceof Node\Scalar\MagicConst\Trait_ + ($expr instanceof Tolerant\Node\Expression\BinaryExpression && + ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || + $expr instanceof Tolerant\Node\StringLiteral || + ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) ) { return new Types\String_; } + + // BINARY EXPRESSIONS: + // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float + // [operator] +, -, *, ** + // [assignment] *=, **=, -=, += + // Resolve to Types\Float + // [assignment] /= if ( - $expr instanceof Node\Expr\BinaryOp\Minus - || $expr instanceof Node\Expr\BinaryOp\Plus - || $expr instanceof Node\Expr\BinaryOp\Pow - || $expr instanceof Node\Expr\BinaryOp\Mul + $expr instanceof Tolerant\Node\Expression\BinaryExpression && + ($operator = $expr->operator->kind) + && ($operator === Tolerant\TokenKind::PlusToken || + $operator === Tolerant\TokenKind::AsteriskAsteriskToken || + $operator === Tolerant\TokenKind::AsteriskToken || + $operator === Tolerant\TokenKind::MinusToken || + + // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression) + $operator === Tolerant\TokenKind::AsteriskEqualsToken|| + $operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || + $operator === Tolerant\TokenKind::MinusEqualsToken || + $operator === Tolerant\TokenKind::PlusEqualsToken + ) ) { if ( - $this->resolveExpressionNodeToType($expr->left) instanceof Types\Integer - && $this->resolveExpressionNodeToType($expr->right) instanceof Types\Integer + $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer + && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer ) { return new Types\Integer; } return new Types\Float_; - } - - if ( - $expr instanceof Node\Expr\AssignOp\Minus - || $expr instanceof Node\Expr\AssignOp\Plus - || $expr instanceof Node\Expr\AssignOp\Pow - || $expr instanceof Node\Expr\AssignOp\Mul + } else if ( + $expr instanceof Tolerant\Node\Expression\BinaryExpression && + $expr->operator->kind === Tolerant\TokenKind::SlashEqualsToken ) { - if ( - $this->resolveExpressionNodeToType($expr->var) instanceof Types\Integer - && $this->resolveExpressionNodeToType($expr->expr) instanceof Types\Integer - ) { - return new Types\Integer; - } return new Types\Float_; } + // INTEGER EXPRESSIONS: resolve to Types\Integer + // [literal] 1 + // [operator] <=>, &, ^, | + // TODO: Magic constants (__LINE__) if ( - $expr instanceof Node\Scalar\LNumber - || $expr instanceof Node\Expr\Cast\Int_ - || $expr instanceof Node\Scalar\MagicConst\Line - || $expr instanceof Node\Expr\BinaryOp\Spaceship - || $expr instanceof Node\Expr\BinaryOp\BitwiseAnd - || $expr instanceof Node\Expr\BinaryOp\BitwiseOr - || $expr instanceof Node\Expr\BinaryOp\BitwiseXor + // 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 Tolerant\Node\Expression\BinaryExpression && ( + ($operator = $expr->operator->kind) + && ($operator === Tolerant\TokenKind::LessThanEqualsGreaterThanToken || + $operator === Tolerant\TokenKind::AmpersandToken || + $operator === Tolerant\TokenKind::CaretToken || + $operator === Tolerant\TokenKind::BarToken) + ) ) { return new Types\Integer; } + + // FLOAT EXPRESSIONS: resolve to Types\Float + // [literal] 1.5 + // [operator] / + // [cast] (double) if ( - $expr instanceof Node\Expr\BinaryOp\Div - || $expr instanceof Node\Scalar\DNumber - || $expr instanceof Node\Expr\Cast\Double + $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || + ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) || + ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::SlashToken) ) { return new Types\Float_; } - if ($expr instanceof Node\Expr\Array_) { + + // ARRAY CREATION EXPRESSION: + // Resolve to Types\Array (Types\Compound of value and key types) + // [a, b, c] + // [1=>"hello", "hi"=>1, 4=>[]]s + if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; - foreach ($expr->items as $item) { - $valueTypes[] = $this->resolveExpressionNodeToType($item->value); - $keyTypes[] = $item->key ? $this->resolveExpressionNodeToType($item->key) : new Types\Integer; + if ($expr->arrayElements !== null) { + foreach ($expr->arrayElements->getElements() as $item) { + $valueTypes[] = $this->resolveExpressionNodeToType($item->elementValue); + $keyTypes[] = $item->elementKey ? $this->resolveExpressionNodeToType($item->elementKey) : new Types\Integer; + } } $valueTypes = array_unique($keyTypes); $keyTypes = array_unique($keyTypes); @@ -628,54 +847,68 @@ public function resolveExpressionNodeToType($expr): Type } return new Types\Array_($valueType, $keyType); } - if ($expr instanceof Node\Expr\ArrayDimFetch) { - $varType = $this->resolveExpressionNodeToType($expr->var); + + // SUBSCRIPT EXPRESSION + // $myArray[3] + // $myArray{"hello"} + if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { + $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; } return $varType->getValueType(); } - if ($expr instanceof Node\Expr\Include_) { + + // SCRIPT INCLUSION EXPRESSION + // include, require, include_once, require_once + if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { // TODO: resolve path to PhpDocument and find return statement return new Types\Mixed; } + + if ($expr instanceof Tolerant\Node\QualifiedName) { + return $this->resolveClassNameToType($expr); + } + return new Types\Mixed; } + /** * 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 * - * @param Node $class + * @param Tolerant\Node || Tolerant\Token $class * @return Type */ - private function resolveClassNameToType(Node $class): Type + public function resolveClassNameToType($class): Type { - if ($class instanceof Node\Expr) { + if ($class instanceof Tolerant\Node\Expression) { return new Types\Mixed; } - if ($class instanceof Node\Stmt\Class_) { + if ($class instanceof Tolerant\Token && $class->kind === Tolerant\TokenKind::ClassKeyword) { // Anonymous class return new Types\Object_; } - $className = (string)$class; + $className = (string)$class->getResolvedName(); + if ($className === 'static') { return new Types\Static_; } if ($className === 'self' || $className === 'parent') { - $classNode = getClosestNode($class, Node\Stmt\Class_::class); + $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); if ($className === 'parent') { - if ($classNode === null || $classNode->extends === null) { + if ($classNode === null || $classNode->classBaseClause === null) { return new Types\Object_; } // parent is resolved to the parent class - $classFqn = (string)$classNode->extends; + $classFqn = (string)$classNode->classBaseClause->baseClass->getResolvedName(); } else { if ($classNode === null) { return new Types\Self_; } // self is resolved to the containing class - $classFqn = (string)$classNode->namespacedName; + $classFqn = (string)$classNode->getNamespacedName(); } return new Types\Object_(new Fqsen('\\' . $classFqn)); } @@ -693,48 +926,62 @@ private function resolveClassNameToType(Node $class): Type * If it is unknown, will be Types\Mixed. * Returns null if the node does not have a type. * - * @param Node $node + * @param Tolerant\Node $node * @return \phpDocumentor\Reflection\Type|null */ public function getTypeFromNode($node) { - if ($node instanceof Node\Param) { + // PARAMETERS + // Get the type of the parameter: + // 1. Doc block + // 2. Parameter type and default + if ($node instanceof Tolerant\Node\Parameter) { // Parameters - $docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock'); - if ($docBlock !== null) { - // Use @param tag - foreach ($docBlock->getTagsByName('param') as $paramTag) { - if ($paramTag->getVariableName() === $node->name) { - if ($paramTag->getType() === null) { - break; - } - return $paramTag->getType(); - } - } + // Get the doc block for the the function call + // /** + // * @param MyClass $myParam + // */ + // function foo($a) + $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); + $variableName = $node->getName(); + $docBlock = $this->getDocBlock($functionLikeDeclaration); + + $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); + if ($parameterDocBlockTag !== null && ($type = $parameterDocBlockTag->getType())) { + // Doc block comments supercede all other forms of type inference + return $type; } - $type = null; - if ($node->type !== null) { + + // function foo(MyClass $a) + if ($node->typeDeclaration !== null) { // Use PHP7 return type hint - if (is_string($node->type)) { + if ($node->typeDeclaration instanceof Tolerant\Token) { // Resolve a string like "bool" to a type object - $type = $this->typeResolver->resolve($node->type); + $type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents())); } else { - $type = new Types\Object_(new Fqsen('\\' . (string)$node->type)); + $type = new Types\Object_(new Fqsen('\\' . (string)$node->typeDeclaration->getResolvedName())); } } + // function foo($a = 3) if ($node->default !== null) { $defaultType = $this->resolveExpressionNodeToType($node->default); if (isset($type) && !is_a($type, get_class($defaultType))) { - $type = new Types\Compound([$type, $defaultType]); - } else { - $type = $defaultType; + // TODO - verify it is worth creating a compound type + return new Types\Compound([$type, $defaultType]); } + $type = $defaultType; } return $type ?? new Types\Mixed; } - if ($node instanceof Node\FunctionLike) { + + // FUNCTIONS AND METHODS + // Get the return type + // 1. doc block + // 2. return type hint + // 3. TODO: infer from return statements + if (ParserHelpers::isFunctionLike($node)) { // Functions/methods - $docBlock = $node->getAttribute('docBlock'); + $docBlock = $this->getDocBlock($node); if ( $docBlock !== null && !empty($returnTags = $docBlock->getTagsByName('return')) @@ -743,57 +990,57 @@ public function getTypeFromNode($node) // Use @return tag return $returnTags[0]->getType(); } - if ($node->returnType !== null) { + if ($node->returnType !== null && !($node->returnType instanceof Tolerant\MissingToken)) { // Use PHP7 return type hint - if (is_string($node->returnType)) { + if ($node->returnType instanceof Tolerant\Token) { // Resolve a string like "bool" to a type object - return $this->typeResolver->resolve($node->returnType); + return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); } - return new Types\Mixed; -// return new Types\Object_(new Fqsen('\\' . (string)$node->returnType)); + return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); } // Unknown return type return new Types\Mixed; } - if ($node instanceof Node\Expr\Variable) { - $node = $node->getAttribute('parentNode'); - } + + // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS + // Get the documented type the assignment resolves to. if ( - $node instanceof Node\Stmt\PropertyProperty - || $node instanceof Node\Const_ - || $node instanceof Node\Expr\Assign - || $node instanceof Node\Expr\AssignOp - ) { - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - $docBlockHolder = $node->getAttribute('parentNode'); - } else { - $docBlockHolder = $node; - } + ($declarationNode = + ParserHelpers::tryGetPropertyDeclaration($node) ?? + ParserHelpers::tryGetConstOrClassConstDeclaration($node) + ) !== null || + ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) + { + $declarationNode = $declarationNode ?? $node; + // Property, constant or variable // Use @var tag if ( - isset($docBlockHolder) - && ($docBlock = $docBlockHolder->getAttribute('docBlock')) + ($docBlock = $this->getDocBlock($declarationNode)) && !empty($varTags = $docBlock->getTagsByName('var')) && ($type = $varTags[0]->getType()) ) { return $type; } + // Resolve the expression - if ($node instanceof Node\Stmt\PropertyProperty) { - if ($node->default) { - return $this->resolveExpressionNodeToType($node->default); + if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { + // TODO should have default + if (isset($node->parent->rightOperand)) { + return $this->resolveExpressionNodeToType($node->parent->rightOperand); } - } else if ($node instanceof Node\Const_) { - return $this->resolveExpressionNodeToType($node->value); - } else { - return $this->resolveExpressionNodeToType($node); + } else if ($node instanceof Tolerant\Node\ConstElement) { + return $this->resolveExpressionNodeToType($node->assignment); + } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + return $this->resolveExpressionNodeToType($node->rightOperand); } // TODO: read @property tags of class // TODO: Try to infer the type from default value / constant value // Unknown return new Types\Mixed; } + + // The node does not have a type return null; } @@ -801,60 +1048,134 @@ public function getTypeFromNode($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 * - * @param Node $node + * @param Tolerant\Node $node * @return string|null */ public static function getDefinedFqn($node) { - $parent = $node->getAttribute('parentNode'); + $parent = $node->parent; // Anonymous classes don't count as a definition - if ($node instanceof Node\Stmt\ClassLike && isset($node->name)) { - // Class, interface or trait declaration - return (string)$node->namespacedName; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { - return (string)$node; - } else if ($node instanceof Node\Stmt\Function_) { + // INPUT OUTPUT: + // namespace A\B; + // class C { } A\B\C + // interface C { } A\B\C + // trait C { } A\B\C + if ( + $node instanceof Tolerant\Node\Statement\ClassDeclaration || + $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || + $node instanceof Tolerant\Node\Statement\TraitDeclaration + ) { + return (string) $node->getNamespacedName(); + } + + // INPUT OUTPUT: + // namespace A\B; A\B + else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { + $name = (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + return \count($name) > 0 ? $name : null; + } + // INPUT OUTPUT: + // namespace A\B; + // function a(); A\B\a(); + else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name - return (string)$node->namespacedName . '()'; - } else if ($node instanceof Node\Stmt\ClassMethod) { + $name = (string)$node->getNamespacedName(); + return \count($name) > 0 ? $name . '()' : null; + } + // INPUT OUTPUT + // namespace A\B; + // class C { + // function a () {} A\B\C->a() + // static function b() {} A\B\C::b() + // } + else if ($node instanceof Tolerant\Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name - $class = $node->getAttribute('parentNode'); + $class = $node->getFirstAncestor( + Tolerant\Node\Expression\ObjectCreationExpression::class, + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ); if (!isset($class->name)) { // Ignore anonymous classes return null; } if ($node->isStatic()) { - return (string)$class->namespacedName . '::' . (string)$node->name . '()'; + return (string)$class->getNamespacedName() . '::' . $node->getName() . '()'; } else { - return (string)$class->namespacedName . '->' . (string)$node->name . '()'; + return (string)$class->getNamespacedName() . '->' . $node->getName() . '()'; } - } else if ($node instanceof Node\Stmt\PropertyProperty) { - $property = $node->getAttribute('parentNode'); - $class = $property->getAttribute('parentNode'); - if (!isset($class->name)) { - // Ignore anonymous classes - return null; - } - if ($property->isStatic()) { + } + + // INPUT OUTPUT + // namespace A\B; + // class C { + // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b + // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name + // } + else if ( + ($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && + ($classDeclaration = + $node->getFirstAncestor( + Tolerant\Node\Expression\ObjectCreationExpression::class, + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ) + ) !== null && isset($classDeclaration->name)) + { + $name = $node->getName(); + if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name - return (string)$class->namespacedName . '::$' . (string)$node->name; - } else { - // Instance Property: use ClassName->propertyName as name - return (string)$class->namespacedName . '->' . (string)$node->name; + return (string)$classDeclaration->getNamespacedName() . '::$' . $name; } - } else if ($node instanceof Node\Const_) { - $parent = $node->getAttribute('parentNode'); - if ($parent instanceof Node\Stmt\Const_) { + + // Instance Property: use ClassName->propertyName as name + return (string)$classDeclaration->getNamespacedName() . '->' . $name; + } + + // INPUT OUTPUT + // namespace A\B; + // const FOO = 5; A\B\FOO + // class C { + // const $a, $b = 4 A\B\C::$a(), A\B\C::$b + // } + else if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { + if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name - return (string)$node->namespacedName; + return (string)$node->getNamespacedName(); } - if ($parent instanceof Node\Stmt\ClassConst) { - // Class constant: use ClassName::CONSTANT_NAME as name - $class = $parent->getAttribute('parentNode'); - if (!isset($class->name) || $class->name instanceof Node\Expr) { - return null; - } - return (string)$class->namespacedName . '::' . $node->name; + + // Class constant: use ClassName::CONSTANT_NAME as name + $classDeclaration = $constDeclaration->getFirstAncestor( + Tolerant\Node\Expression\ObjectCreationExpression::class, + Tolerant\Node\Statement\ClassDeclaration::class, + Tolerant\Node\Statement\InterfaceDeclaration::class, + Tolerant\Node\Statement\TraitDeclaration::class + ); + + if (!isset($classDeclaration->name)) { + return null; + } + return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); + } + + return null; + } + + /** + * @param DocBlock | null $docBlock + * @param $variableName + * @return DocBlock\Tags\Param | null + */ + private function tryGetDocBlockTagForParameter($docBlock, $variableName) { + if ($docBlock === null) { + return null; + } + $tags = $docBlock->getTagsByName('param'); + foreach ($tags as $tag) { + if ($tag->getVariableName() === \ltrim($variableName, "$")) { + return $tag; } } } diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index 40cb4871..3e24819e 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -20,7 +20,7 @@ public static function getDefinedFqn($node) if ($node instanceof Node) { return DefinitionResolver::getDefinedFqn($node); } elseif ($node instanceof Tolerant\Node) { - return TolerantDefinitionResolver::getDefinedFqn($node); + return DefinitionResolver::getDefinedFqn($node); } throw new \TypeError("Unspported Node class"); diff --git a/src/LanguageServer.php b/src/LanguageServer.php index 091651ac..31348f9c 100644 --- a/src/LanguageServer.php +++ b/src/LanguageServer.php @@ -101,7 +101,7 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher protected $projectIndex; /** - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ protected $definitionResolver; @@ -187,7 +187,7 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath = $this->globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex); // The DefinitionResolver should look in stubs, the project source and dependencies - $this->definitionResolver = new TolerantDefinitionResolver($this->globalIndex); + $this->definitionResolver = new DefinitionResolver($this->globalIndex); $this->documentLoader = new PhpDocumentLoader( $this->contentRetriever, diff --git a/src/NodeVisitor/DefinitionCollector.php b/src/NodeVisitor/DefinitionCollector.php index 37eeebe0..ead2d884 100644 --- a/src/NodeVisitor/DefinitionCollector.php +++ b/src/NodeVisitor/DefinitionCollector.php @@ -5,7 +5,7 @@ use PhpParser\{NodeVisitorAbstract, Node}; use LanguageServer\{ - Definition, FqnUtilities, TolerantDefinitionResolver + Definition, FqnUtilities, DefinitionResolver }; /** @@ -30,7 +30,7 @@ class DefinitionCollector extends NodeVisitorAbstract private $definitionResolver; - public function __construct(TolerantDefinitionResolver $definitionResolver) + public function __construct(DefinitionResolver $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/NodeVisitor/ReferencesCollector.php b/src/NodeVisitor/ReferencesCollector.php index a64e6330..cc20ffdd 100644 --- a/src/NodeVisitor/ReferencesCollector.php +++ b/src/NodeVisitor/ReferencesCollector.php @@ -22,14 +22,14 @@ class ReferencesCollector extends NodeVisitorAbstract public $nodes = []; /** - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ private $definitionResolver; /** - * @param TolerantDefinitionResolver $definitionResolver The definition resolver to resolve reference nodes to definitions + * @param DefinitionResolver $definitionResolver The definition resolver to resolve reference nodes to definitions */ - public function __construct(TolerantDefinitionResolver $definitionResolver) + public function __construct(DefinitionResolver $definitionResolver) { $this->definitionResolver = $definitionResolver; } diff --git a/src/TolerantParserHelpers.php b/src/ParserHelpers.php similarity index 99% rename from src/TolerantParserHelpers.php rename to src/ParserHelpers.php index 33902028..bd9c6e1a 100644 --- a/src/TolerantParserHelpers.php +++ b/src/ParserHelpers.php @@ -5,7 +5,7 @@ use Microsoft\PhpParser as Tolerant; -class TolerantParserHelpers { +class ParserHelpers { public static function isConstantFetch(Tolerant\Node $node) : bool { $parent = $node->parent; return @@ -70,7 +70,7 @@ public static function isBooleanExpression($expression) : bool { return false; } - + /** * Tries to get the parent property declaration given a Node * @param Tolerant\Node $node diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 69b6a9b7..878cfe99 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -35,7 +35,7 @@ class PhpDocument /** * The DefinitionResolver instance to resolve reference nodes to definitions * - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ private $definitionResolver; @@ -99,7 +99,7 @@ class PhpDocument * @param Index $index The Index to register definitions and references to * @param Parser $parser The PHPParser instance * @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks - * @param TolerantDefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace + * @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace */ public function __construct( string $uri, @@ -107,7 +107,7 @@ public function __construct( Index $index, $parser, DocBlockFactory $docBlockFactory, - TolerantDefinitionResolver $definitionResolver + DefinitionResolver $definitionResolver ) { $this->uri = $uri; $this->index = $index; @@ -158,7 +158,7 @@ public function updateContent(string $content) $this->definitions = null; $this->definitionNodes = null; - $treeAnalyzer = new TolerantTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); + $treeAnalyzer = new TreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); $this->diagnostics = $treeAnalyzer->getDiagnostics(); diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index 8f949430..0c5bbcac 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -48,20 +48,20 @@ class PhpDocumentLoader private $docBlockFactory; /** - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ private $definitionResolver; /** * @param ContentRetriever $contentRetriever * @param ProjectIndex $projectIndex - * @param TolerantDefinitionResolver $definitionResolver + * @param DefinitionResolver $definitionResolver * @internal param ProjectIndex $project */ public function __construct( ContentRetriever $contentRetriever, ProjectIndex $projectIndex, - TolerantDefinitionResolver $definitionResolver + DefinitionResolver $definitionResolver ) { $this->contentRetriever = $contentRetriever; $this->projectIndex = $projectIndex; diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index a608ebd4..7e6f4896 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -3,6 +3,7 @@ namespace LanguageServer\Protocol; use PhpParser\Node; +use Microsoft\PhpParser as Tolerant; use Exception; /** @@ -42,53 +43,65 @@ class SymbolInformation /** * Converts a Node to a SymbolInformation * - * @param Node $node + * @param Tolerant\Node $node * @param string $fqn If given, $containerName will be extracted from it - * @return self|null + * @return SymbolInformation|null */ public static function fromNode($node, string $fqn = null) { - $parent = $node->getAttribute('parentNode'); $symbol = new self; - if ($node instanceof Node\Stmt\Class_) { + if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Trait_) { + } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Node\Stmt\Interface_) { + } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { $symbol->kind = SymbolKind::INTERFACE; - } else if ($node instanceof Node\Name && $parent instanceof Node\Stmt\Namespace_) { + } else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { $symbol->kind = SymbolKind::NAMESPACE; - } else if ($node instanceof Node\Stmt\Function_) { + } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { $symbol->kind = SymbolKind::FUNCTION; - } else if ($node instanceof Node\Stmt\ClassMethod) { + } else if ($node instanceof Tolerant\Node\MethodDeclaration) { $symbol->kind = SymbolKind::METHOD; - } else if ($node instanceof Node\Stmt\PropertyProperty) { + } else if ($node instanceof Tolerant\Node\Expression\Variable && $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class) !== null) { $symbol->kind = SymbolKind::PROPERTY; - } else if ($node instanceof Node\Const_) { + } else if ($node instanceof Tolerant\Node\ConstElement) { $symbol->kind = SymbolKind::CONSTANT; - } else if ( + } + + else if ( ( - ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) - && $node->var instanceof Node\Expr\Variable + ($node instanceof Tolerant\Node\Expression\AssignmentExpression) + && $node->leftOperand instanceof Tolerant\Node\Expression\Variable ) - || $node instanceof Node\Expr\ClosureUse - || $node instanceof Node\Param + || $node instanceof Tolerant\Node\UseVariableName + || $node instanceof Tolerant\Node\Parameter ) { $symbol->kind = SymbolKind::VARIABLE; } else { return null; } - if ($node instanceof Node\Name) { - $symbol->name = (string)$node; - } else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { - $symbol->name = $node->var->name; - } else if ($node instanceof Node\Expr\ClosureUse) { - $symbol->name = $node->var; + + if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { + $symbol->name = $node->leftOperand->getName(); + } elseif ($node->leftOperand instanceof Tolerant\Token) { + $symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$"); + } + + } else if ($node instanceof Tolerant\Node\UseVariableName) { + $symbol->name = $node->getName(); } else if (isset($node->name)) { - $symbol->name = (string)$node->name; + if ($node->name instanceof Tolerant\Node\QualifiedName) { + $symbol->name = (string)Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + } else { + $symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$"); + } + } else if (isset($node->variableName)) { + $symbol->name = $node->variableName->getText($node); } else { return null; } + $symbol->location = Location::fromNode($node); if ($fqn !== null) { $parts = preg_split('/(::|->|\\\\)/', $fqn); diff --git a/src/Protocol/TolerantSymbolInformation.php b/src/Protocol/TolerantSymbolInformation.php deleted file mode 100644 index 769f1af2..00000000 --- a/src/Protocol/TolerantSymbolInformation.php +++ /dev/null @@ -1,85 +0,0 @@ -kind = SymbolKind::CLASS_; - } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { - $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Tolerant\Node\Statement\InterfaceDeclaration) { - $symbol->kind = SymbolKind::INTERFACE; - } else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { - $symbol->kind = SymbolKind::NAMESPACE; - } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { - $symbol->kind = SymbolKind::FUNCTION; - } else if ($node instanceof Tolerant\Node\MethodDeclaration) { - $symbol->kind = SymbolKind::METHOD; - } else if ($node instanceof Tolerant\Node\Expression\Variable && $node->getFirstAncestor(Tolerant\Node\PropertyDeclaration::class) !== null) { - $symbol->kind = SymbolKind::PROPERTY; - } else if ($node instanceof Tolerant\Node\ConstElement) { - $symbol->kind = SymbolKind::CONSTANT; - } - - else if ( - ( - ($node instanceof Tolerant\Node\Expression\AssignmentExpression) - && $node->leftOperand instanceof Tolerant\Node\Expression\Variable - ) - || $node instanceof Tolerant\Node\UseVariableName - || $node instanceof Tolerant\Node\Parameter - ) { - $symbol->kind = SymbolKind::VARIABLE; - } else { - return null; - } - - if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { - if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { - $symbol->name = $node->leftOperand->getName(); - } elseif ($node->leftOperand instanceof Tolerant\Token) { - $symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$"); - } - - } else if ($node instanceof Tolerant\Node\UseVariableName) { - $symbol->name = $node->getName(); - } else if (isset($node->name)) { - if ($node->name instanceof Tolerant\Node\QualifiedName) { - $symbol->name = (string)Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); - } else { - $symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$"); - } - } else if (isset($node->variableName)) { - $symbol->name = $node->variableName->getText($node); - } else { - return null; - } - - $symbol->location = Location::fromNode($node); - if ($fqn !== null) { - $parts = preg_split('/(::|->|\\\\)/', $fqn); - array_pop($parts); - $symbol->containerName = implode('\\', $parts); - } - return $symbol; - } -} diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 36799507..7a2b062c 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -4,7 +4,7 @@ namespace LanguageServer\Server; use LanguageServer\{ - CompletionProvider, FqnUtilities, LanguageClient, PhpDocument, PhpDocumentLoader, TolerantDefinitionResolver + CompletionProvider, FqnUtilities, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\{ @@ -36,7 +36,7 @@ class TextDocument protected $project; /** - * @var TolerantDefinitionResolver + * @var DefinitionResolver */ protected $definitionResolver; @@ -62,7 +62,7 @@ class TextDocument /** * @param PhpDocumentLoader $documentLoader - * @param TolerantDefinitionResolver $definitionResolver + * @param DefinitionResolver $definitionResolver * @param LanguageClient $client * @param ReadableIndex $index * @param \stdClass $composerJson @@ -70,7 +70,7 @@ class TextDocument */ public function __construct( PhpDocumentLoader $documentLoader, - TolerantDefinitionResolver $definitionResolver, + DefinitionResolver $definitionResolver, LanguageClient $client, ReadableIndex $index, \stdClass $composerJson = null, diff --git a/src/TolerantDefinitionResolver.php b/src/TolerantDefinitionResolver.php deleted file mode 100644 index 810eb9fe..00000000 --- a/src/TolerantDefinitionResolver.php +++ /dev/null @@ -1,1182 +0,0 @@ -index = $index; - $this->typeResolver = new TypeResolver; - $this->docBlockFactory = DocBlockFactory::createInstance(); - } - - /** - * Builds the declaration line for a given node. Declarations with multiple lines are trimmed. - * - * @param Tolerant\Node $node - * @return string - */ - public function getDeclarationLineFromNode($node): string - { - // If node is part of a declaration list, build a declaration line that discludes other elements in the list - // - [PropertyDeclaration] // public $a, [$b = 3], $c; => public $b = 3; - // - [ConstDeclaration | ClassConstDeclaration] // "const A = 3, [B = 4];" => "const B = 4;" - if ( - ($declaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) && ($elements = $declaration->propertyElements) || - ($declaration = TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node)) && ($elements = $declaration->constElements) - ) { - $defLine = $declaration->getText(); - $defLineStart = $declaration->getStart(); - - $defLine = \substr_replace( - $defLine, - $node->getFullText(), - $elements->getFullStart() - $defLineStart, - $elements->getFullWidth() - ); - } else { - $defLine = $node->getText(); - } - - // Trim string to only include first line - $defLine = \rtrim(\strtok($defLine, "\n"), "\r"); - - // TODO - pretty print rather than getting text - - return $defLine; - } - - /** - * Gets the documentation string for a node, if it has one - * - * @param Tolerant\Node $node - * @return string|null - */ - public function getDocumentationFromNode($node) - { - // Any NamespaceDefinition comments likely apply to the file, not the declaration itself. - if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { - return null; - } - - // For properties and constants, set the node to the declaration node, rather than the individual property. - // This is because they get defined as part of a list. - $constOrPropertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node); - if ($constOrPropertyDeclaration !== null) { - $node = $constOrPropertyDeclaration; - } - - // For parameters, parse the function-like declaration to get documentation for a parameter - if ($node instanceof Tolerant\Node\Parameter) { - $variableName = $node->getName(); - - $functionLikeDeclaration = TolerantParserHelpers::getFunctionLikeDeclarationFromParameter($node); - $docBlock = $this->getDocBlock($functionLikeDeclaration); - - $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); - return $parameterDocBlockTag !== null ? $parameterDocBlockTag->getDescription()->render() : null; - } - - // For everything else, get the doc block summary corresponding to the current node. - $docBlock = $this->getDocBlock($node); - if ($docBlock !== null) { - return $docBlock->getSummary(); - } - return null; - } - - /** - * Gets Doc Block with resolved names for a Node - * - * @param Tolerant\Node $node - * @return DocBlock | null - */ - private function getDocBlock(Tolerant\Node $node) - { - // TODO make more efficient (caching, ensure import table is in right format to begin with) - $docCommentText = $node->getDocCommentText(); - if ($docCommentText !== null) { - list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); - foreach ($namespaceImportTable as $alias=>$name) { - $namespaceImportTable[$alias] = (string)$name; - } - $namespaceDefinition = $node->getNamespaceDefinition(); - if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { - $namespaceName = (string)$namespaceDefinition->name->getNamespacedName(); - } else { - $namespaceName = 'global'; - } - $context = new Types\Context($namespaceName, $namespaceImportTable); - - try { - return $this->docBlockFactory->create($docCommentText, $context); - } catch (\InvalidArgumentException $e) { - return null; - } - } - return null; - } - - /** - * Create a Definition for a definition node - * - * @param Tolerant\Node $node - * @param string $fqn - * @return Definition - */ - public function createDefinitionFromNode($node, string $fqn = null): Definition - { - $def = new Definition; - $def->fqn = $fqn; - - // Determines whether the suggestion will show after "new" - $def->canBeInstantiated = $node instanceof Tolerant\Node\Statement\ClassDeclaration; - - // Interfaces, classes, traits, namespaces, functions, and global const elements - $def->isGlobal = ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || - $node instanceof Tolerant\Node\Statement\ClassDeclaration || - $node instanceof Tolerant\Node\Statement\TraitDeclaration || - - ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name !== null) || - - $node instanceof Tolerant\Node\Statement\FunctionDeclaration || - - ($node instanceof Tolerant\Node\ConstElement && $node->parent->parent instanceof Tolerant\Node\Statement\ConstDeclaration) - ); - - // Static methods and static property declarations - $def->isStatic = ( - ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) || - - (($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null - && $propertyDeclaration->isStatic()) - ); - - if ($node instanceof Tolerant\Node\Statement\ClassDeclaration && - // TODO - this should be bette rrpreented in the parser API - $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) - { - $def->extends = [(string)$node->classBaseClause->baseClass->getResolvedName()]; - // TODO - why is this represented as an array? - // TODO interface implementations. - } elseif ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && - // TODO - this should be better represented in the parser API - $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null - ) { - $def->extends = []; - foreach ($node->interfaceBaseClause->interfaceNameList->getValues() as $n) { - $def->extends[] = (string)$n->getResolvedName(); - } - } - - $def->symbolInformation = TolerantSymbolInformation::fromNode($node, $fqn); - - if ($def->symbolInformation !== null) { - $def->type = $this->getTypeFromNode($node); - $def->declarationLine = $this->getDeclarationLineFromNode($node); - $def->documentation = $this->getDocumentationFromNode($node); - } - - return $def; - } - - /** - * Given any node, returns the Definition object of the symbol that is referenced - * - * @param Tolerant\Node $node Any reference node - * @return Definition|null - */ - public function resolveReferenceNodeToDefinition($node) - { - $parent = $node->parent; - // Variables are not indexed globally, as they stay in the file scope anyway. - // Ignore variable nodes that are part of ScopedPropertyAccessExpression, - // as the scoped property access expression node is handled separately. - if ($node instanceof Tolerant\Node\Expression\Variable && - !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) - { - // Resolve $this to the containing class definition. - if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { - return $this->index->getDefinition($fqn, false); - } - - // Resolve the variable to a definition node (assignment, param or closure use) - $defNode = $this->resolveVariableToNode($node); - if ($defNode === null) { - return null; - } - return $this->createDefinitionFromNode($defNode); - } - // Other references are references to a global symbol that have an FQN - // Find out the FQN - $fqn = $this->resolveReferenceNodeToFqn($node); - if ($fqn === null) { - return null; - } - // 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 - // TODO - verify that this is not a method - $globalFallback = TolerantParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; - // Return the Definition object from the index index - return $this->index->getDefinition($fqn, $globalFallback); - } - - /** - * Given any node, returns the FQN of the symbol that is referenced - * Returns null if the FQN could not be resolved or the reference node references a variable - * - * @param Node $node - * @return string|null - */ - public function resolveReferenceNodeToFqn($node) { - // TODO all name tokens should be a part of a node - if ($node instanceof Tolerant\Node\QualifiedName) { - return $this->resolveQualifiedNameNodeToFqn($node); - } - - else if ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { - return $this->resolveMemberAccessExpressionNodeToFqn($node); - } - else if (TolerantParserHelpers::isConstantFetch($node)) { - return (string)($node->getNamespacedName()); - } - else if ( - // A\B::C - constant access expression - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - && !($node->memberName instanceof Tolerant\Node\Expression\Variable) - ) { - return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); - } else if ( - // A\B::$c - static property access expression - $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - ) { - return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node->parent); - } - - return null; - } - - private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { - $parent = $node->parent; - - if ($parent instanceof Tolerant\Node\TraitSelectOrAliasClause) { - return null; - } - // Add use clause references - if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause - || $useClause instanceof Tolerant\Node\NamespaceUseClause - ) { - $contents = $node->getFileContents(); - if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { - $prefix = $useClause->parent->parent->namespaceName; - if ($prefix === null) { - return null; - } - $name = Tolerant\ResolvedName::buildName($prefix->nameParts, $contents); - $name->addNameParts($node->nameParts, $contents); - $name = (string)$name; - - if ($useClause->functionOrConst === null) { - $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); - if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { - $name .= '()'; - } - } - return $name; - } else { - $name = (string) Tolerant\ResolvedName::buildName($node->nameParts, $contents); - if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { - $name .= '()'; - } - } - - return $name; - } - - // For extends, implements, type hints and classes of classes of static calls use the name directly - $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); - - if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { - $name .= '()'; - } - return $name; - } - - private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression\MemberAccessExpression $access) { - if ($access->memberName instanceof Tolerant\Node\Expression) { - // Cannot get definition if right-hand side is expression - return null; - } - // Get the type of the left-hand expression - $varType = $this->resolveExpressionNodeToType($access->dereferencableExpression); - - if ($varType instanceof Types\Compound) { - // For compound types, use the first FQN we find - // (popular use case is ClassName|null) - for ($i = 0; $t = $varType->get($i); $i++) { - if ( - $t instanceof Types\This - || $t instanceof Types\Object_ - || $t instanceof Types\Static_ - || $t instanceof Types\Self_ - ) { - $varType = $t; - break; - } - } - } - if ( - $varType instanceof Types\This - || $varType instanceof Types\Static_ - || $varType instanceof Types\Self_ - ) { - // $this/static/self is resolved to the containing class - $classFqn = self::getContainingClassFqn($access); - } else if (!($varType instanceof Types\Object_) || $varType->getFqsen() === null) { - // Left-hand expression could not be resolved to a class - return null; - } else { - $classFqn = substr((string)$varType->getFqsen(), 1); - } - $memberSuffix = '->' . (string)($access->memberName->getText() ?? $access->memberName->getText($access->getFileContents())); - if ($access->parent instanceof Tolerant\Node\Expression\CallExpression) { - $memberSuffix .= '()'; - } - - // Find the right class that implements the member - $implementorFqns = [$classFqn]; - - while ($implementorFqn = array_shift($implementorFqns)) { - // If the member FQN exists, return it - if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { - - return $implementorFqn . $memberSuffix; - } - // Get Definition of implementor class - $implementorDef = $this->index->getDefinition($implementorFqn); - // If it doesn't exist, return the initial guess - if ($implementorDef === null) { - break; - } - // Repeat for parent class - if ($implementorDef->extends) { - foreach ($implementorDef->extends as $extends) { - $implementorFqns[] = $extends; - } - } - } - - return $classFqn . $memberSuffix; - } - - private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { - if ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\Expression\Variable) { - $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); - if ($varType === null) { - return null; - } - $className = substr((string)$varType->getFqsen(), 1); - } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { - $className = (string)$scoped->scopeResolutionQualifier->getResolvedName(); - } else { - return null; - } - - if ($className === 'self' || $className === 'static' || $className === 'parent') { - // self and static are resolved to the containing class - $classNode = $scoped->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($classNode === null) { - return null; - } - if ($className === 'parent') { - // parent is resolved to the parent class - if (!isset($classNode->extends)) { - return null; - } - $className = (string)$classNode->extends->getResolvedName(); - } else { - $className = (string)$classNode->getNamespacedName(); - } - } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { - $className = $scoped->scopeResolutionQualifier->getResolvedName(); - } - if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { - if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { - return null; - } - $memberName = $scoped->memberName->getName(); - if (empty($memberName)) { - return null; - } - $name = (string)$className . '::$' . $memberName; - } else { - $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); - } - if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { - $name .= '()'; - } - return $name; - } - - /** - * 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 - * - * @param Tolerant\Node $node - * @return string|null - */ - private static function getContainingClassFqn(Tolerant\Node $node) - { - $classNode = $node->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($classNode === null) { - return null; - } - return (string)$classNode->getNamespacedName(); - } - - /** - * Returns the assignment or parameter node where a variable was defined - * - * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access - * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null - */ - public function resolveVariableToNode($var) - { - $n = $var; - // When a use is passed, start outside the closure to not return immediately - // Use variable vs variable parsing? - if ($var instanceof Tolerant\Node\UseVariableName) { - $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class)->parent; - $name = $var->getName(); - } else if ($var instanceof Tolerant\Node\Expression\Variable || $var instanceof Tolerant\Node\Parameter) { - $name = $var->getName(); - } else { - throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); - } - // Traverse the AST up - do { - // If a function is met, check the parameters and use statements - if (TolerantParserHelpers::isFunctionLike($n)) { - if ($n->parameters !== null) { - - foreach ($n->parameters->getElements() as $param) { - if ($param->getName() === $name) { - return $param; - } - } - } - // If it is a closure, also check use statements - if ($n instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression && - $n->anonymousFunctionUseClause !== null && - $n->anonymousFunctionUseClause->useVariableNameList !== null) { - foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use - ) { - if ($use->getName() === $name) { - return $use; - } - } - } - break; - } - // Check each previous sibling node for a variable assignment to that variable - while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { - if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { - $n = $n->expression; - } - if ( - // TODO - clean this up - ($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) - && $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name - ) { - return $n; - } - } - } while (isset($n) && $n = $n->parent); - // Return null if nothing was found - return null; - } - - /** - * Given an expression node, resolves that expression recursively to a type. - * If the type could not be resolved, returns Types\Mixed. - * - * @param Tolerant\Node\Expression $expr - * @return \phpDocumentor\Reflection\Type|null - */ - public function resolveExpressionNodeToType($expr) - { - if ($expr == null || $expr instanceof Tolerant\MissingToken || $expr instanceof Tolerant\SkippedToken) { - // TODO some members are null or Missing/SkippedToken - // How do we handle this more generally? - return new Types\Mixed; - } - - // PARENTHESIZED EXPRESSION - // Retrieve inner expression from parenthesized expression - while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { - $expr = $expr->expression; - } - - // VARIABLE - // $this -> Type\this - // $myVariable -> type of corresponding assignment expression - if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { - if ($expr->getName() === 'this') { - return new Types\This; - } - // Find variable definition (parameter or assignment expression) - $defNode = $this->resolveVariableToNode($expr); - if ($defNode instanceof Tolerant\Node\Expression\AssignmentExpression || $defNode instanceof Tolerant\Node\UseVariableName) { - return $this->resolveExpressionNodeToType($defNode); - } - if ($defNode instanceof Tolerant\Node\Parameter) { - return $this->getTypeFromNode($defNode); - } - } - - // FUNCTION CALL - // Function calls are resolved to type corresponding to their FQN - if ($expr instanceof Tolerant\Node\Expression\CallExpression && - !( - $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) - ) { - - // Find the function definition - if ($expr->callableExpression instanceof Tolerant\Node\Expression) { - // Cannot get type for dynamic function call - return new Types\Mixed; - } - - if ($expr->callableExpression instanceof Tolerant\Node\QualifiedName) { - $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName(); - $fqn .= '()'; - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; - } - } - } - - // TRUE / FALSE / NULL - // Resolve true and false reserved words to Types\Boolean - if ($expr instanceof Tolerant\Node\ReservedWord) { - $token = $expr->children->kind; - if ($token === Tolerant\TokenKind::TrueReservedWord || $token === Tolerant\TokenKind::FalseReservedWord) { - return new Types\Boolean; - } - - if ($token === Tolerant\TokenKind::NullReservedWord) { - return new Types\Null_; - } - } - - // CONSTANT FETCH - // Resolve constants by retrieving corresponding definition type from FQN - if (TolerantParserHelpers::isConstantFetch($expr)) { - $fqn = (string)$expr->getNamespacedName(); - $def = $this->index->getDefinition($fqn, true); - if ($def !== null) { - return $def->type; - } - } - - // MEMBER ACCESS EXPRESSION - if ($expr instanceof Tolerant\Node\Expression\MemberAccessExpression) { - if ($expr->memberName instanceof Tolerant\Node\Expression) { - return new Types\Mixed; - } - $var = $expr->dereferencableExpression; - - // Resolve object - $objType = $this->resolveExpressionNodeToType($var); - if (!($objType instanceof Types\Compound)) { - $objType = new Types\Compound([$objType]); - } - for ($i = 0; $t = $objType->get($i); $i++) { - if ($t instanceof Types\This) { - $classFqn = self::getContainingClassFqn($expr); - if ($classFqn === null) { - return new Types\Mixed; - } - } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { - return new Types\Mixed; - } else { - $classFqn = substr((string)$t->getFqsen(), 1); - } - $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { - $fqn .= '()'; - } - $def = $this->index->getDefinition($fqn); - if ($def !== null) { - return $def->type; - } - } - } - - // SCOPED PROPERTY ACCESS EXPRESSION - if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { - $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); - if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { - return new Types\Mixed; - } - $fqn = substr((string)$classType->getFqsen(), 1) . '::'; - - // TODO is there a cleaner way to do this? - $fqn .= $expr->memberName->getText() ?? $expr->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { - $fqn .= '()'; - } - - $def = $this->index->getDefinition($fqn); - if ($def === null) { - return new Types\Mixed; - } - return $def->type; - } - - // OBJECT CREATION EXPRESSION - // new A() => resolves to the type of the class type designator (A) - // TODO: new $this->a => resolves to the string represented by "a" - if ($expr instanceof Tolerant\Node\Expression\ObjectCreationExpression) { - return $this->resolveClassNameToType($expr->classTypeDesignator); - } - - // CLONE EXPRESSION - // clone($a) => resolves to the type of $a - if ($expr instanceof Tolerant\Node\Expression\CloneExpression) { - return $this->resolveExpressionNodeToType($expr->expression); - } - - // ASSIGNMENT EXPRESSION - // $a = $myExpression => resolves to the type of the right-hand operand - if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { - return $this->resolveExpressionNodeToType($expr->rightOperand); - } - - // TERNARY EXPRESSION - // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression - // $condition ?: $elseExpression => resolves to type of $condition or $elseExpression - if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { - // ?: - if ($expr->ifExpression === null) { - return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->condition), // TODO: why? - $this->resolveExpressionNodeToType($expr->elseExpression) - ]); - } - // Ternary is a compound of the two possible values - return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->ifExpression), - $this->resolveExpressionNodeToType($expr->elseExpression) - ]); - } - - // NULL COALLESCE - // $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand - if ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::QuestionQuestionToken) { - // ?? operator - return new Types\Compound([ - $this->resolveExpressionNodeToType($expr->leftOperand), - $this->resolveExpressionNodeToType($expr->rightOperand) - ]); - } - - // BOOLEAN EXPRESSIONS: resolve to Types\Boolean - // (bool) $expression - // !$expression - // empty($var) - // isset($var) - // >, >=, <, <=, &&, ||, AND, OR, XOR, ==, ===, !=, !== - if ( - TolerantParserHelpers::isBooleanExpression($expr) - - || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) - || ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) - || $expr instanceof Tolerant\Node\Expression\EmptyIntrinsicExpression - || $expr instanceof Tolerant\Node\Expression\IssetIntrinsicExpression - ) { - return new Types\Boolean; - } - - // STRING EXPRESSIONS: resolve to Types\String - // [concatenation] .=, . - // [literals] "hello", \b"hello", \B"hello", 'hello', \b'hello', HEREDOC, NOWDOC - // [cast] (string) "hello" - // - // TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__) - if ( - ($expr instanceof Tolerant\Node\Expression\BinaryExpression && - ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || - $expr instanceof Tolerant\Node\StringLiteral || - ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) - ) { - return new Types\String_; - } - - // BINARY EXPRESSIONS: - // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float - // [operator] +, -, *, ** - // [assignment] *=, **=, -=, += - // Resolve to Types\Float - // [assignment] /= - if ( - $expr instanceof Tolerant\Node\Expression\BinaryExpression && - ($operator = $expr->operator->kind) - && ($operator === Tolerant\TokenKind::PlusToken || - $operator === Tolerant\TokenKind::AsteriskAsteriskToken || - $operator === Tolerant\TokenKind::AsteriskToken || - $operator === Tolerant\TokenKind::MinusToken || - - // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression) - $operator === Tolerant\TokenKind::AsteriskEqualsToken|| - $operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || - $operator === Tolerant\TokenKind::MinusEqualsToken || - $operator === Tolerant\TokenKind::PlusEqualsToken - ) - ) { - if ( - $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer - && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer - ) { - return new Types\Integer; - } - return new Types\Float_; - } else if ( - $expr instanceof Tolerant\Node\Expression\BinaryExpression && - $expr->operator->kind === Tolerant\TokenKind::SlashEqualsToken - ) { - return new Types\Float_; - } - - // INTEGER EXPRESSIONS: resolve to Types\Integer - // [literal] 1 - // [operator] <=>, &, ^, | - // TODO: Magic constants (__LINE__) - if ( - // 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 Tolerant\Node\Expression\BinaryExpression && ( - ($operator = $expr->operator->kind) - && ($operator === Tolerant\TokenKind::LessThanEqualsGreaterThanToken || - $operator === Tolerant\TokenKind::AmpersandToken || - $operator === Tolerant\TokenKind::CaretToken || - $operator === Tolerant\TokenKind::BarToken) - ) - ) { - return new Types\Integer; - } - - // FLOAT EXPRESSIONS: resolve to Types\Float - // [literal] 1.5 - // [operator] / - // [cast] (double) - if ( - $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || - ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) || - ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::SlashToken) - ) { - return new Types\Float_; - } - - // ARRAY CREATION EXPRESSION: - // Resolve to Types\Array (Types\Compound of value and key types) - // [a, b, c] - // [1=>"hello", "hi"=>1, 4=>[]]s - if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { - $valueTypes = []; - $keyTypes = []; - if ($expr->arrayElements !== null) { - foreach ($expr->arrayElements->getElements() as $item) { - $valueTypes[] = $this->resolveExpressionNodeToType($item->elementValue); - $keyTypes[] = $item->elementKey ? $this->resolveExpressionNodeToType($item->elementKey) : new Types\Integer; - } - } - $valueTypes = array_unique($keyTypes); - $keyTypes = array_unique($keyTypes); - if (empty($valueTypes)) { - $valueType = null; - } else if (count($valueTypes) === 1) { - $valueType = $valueTypes[0]; - } else { - $valueType = new Types\Compound($valueTypes); - } - if (empty($keyTypes)) { - $keyType = null; - } else if (count($keyTypes) === 1) { - $keyType = $keyTypes[0]; - } else { - $keyType = new Types\Compound($keyTypes); - } - return new Types\Array_($valueType, $keyType); - } - - // SUBSCRIPT EXPRESSION - // $myArray[3] - // $myArray{"hello"} - if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { - $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); - if (!($varType instanceof Types\Array_)) { - return new Types\Mixed; - } - return $varType->getValueType(); - } - - // SCRIPT INCLUSION EXPRESSION - // include, require, include_once, require_once - if ($expr instanceof Tolerant\Node\Expression\ScriptInclusionExpression) { - // TODO: resolve path to PhpDocument and find return statement - return new Types\Mixed; - } - - if ($expr instanceof Tolerant\Node\QualifiedName) { - return $this->resolveClassNameToType($expr); - } - - return new Types\Mixed; - } - - - /** - * 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 - * - * @param Tolerant\Node || Tolerant\Token $class - * @return Type - */ - public function resolveClassNameToType($class): Type - { - if ($class instanceof Tolerant\Node\Expression) { - return new Types\Mixed; - } - if ($class instanceof Tolerant\Token && $class->kind === Tolerant\TokenKind::ClassKeyword) { - // Anonymous class - return new Types\Object_; - } - $className = (string)$class->getResolvedName(); - - if ($className === 'static') { - return new Types\Static_; - } - if ($className === 'self' || $className === 'parent') { - $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); - if ($className === 'parent') { - if ($classNode === null || $classNode->classBaseClause === null) { - return new Types\Object_; - } - // parent is resolved to the parent class - $classFqn = (string)$classNode->classBaseClause->baseClass->getResolvedName(); - } else { - if ($classNode === null) { - return new Types\Self_; - } - // self is resolved to the containing class - $classFqn = (string)$classNode->getNamespacedName(); - } - return new Types\Object_(new Fqsen('\\' . $classFqn)); - } - return new Types\Object_(new Fqsen('\\' . $className)); - } - - /** - * Returns the type a reference to this symbol will resolve to. - * For properties and constants, this is the type of the property/constant. - * For functions and methods, this is the return type. - * For parameters, this is the type of the parameter. - * For classes and interfaces, this is the class type (object). - * For variables / assignments, this is the documented type or type the assignment resolves to. - * Can also be a compound type. - * If it is unknown, will be Types\Mixed. - * Returns null if the node does not have a type. - * - * @param Tolerant\Node $node - * @return \phpDocumentor\Reflection\Type|null - */ - public function getTypeFromNode($node) - { - // PARAMETERS - // Get the type of the parameter: - // 1. Doc block - // 2. Parameter type and default - if ($node instanceof Tolerant\Node\Parameter) { - // Parameters - // Get the doc block for the the function call - // /** - // * @param MyClass $myParam - // */ - // function foo($a) - $functionLikeDeclaration = TolerantParserHelpers::getFunctionLikeDeclarationFromParameter($node); - $variableName = $node->getName(); - $docBlock = $this->getDocBlock($functionLikeDeclaration); - - $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); - if ($parameterDocBlockTag !== null && ($type = $parameterDocBlockTag->getType())) { - // Doc block comments supercede all other forms of type inference - return $type; - } - - // function foo(MyClass $a) - if ($node->typeDeclaration !== null) { - // Use PHP7 return type hint - if ($node->typeDeclaration instanceof Tolerant\Token) { - // Resolve a string like "bool" to a type object - $type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents())); - } else { - $type = new Types\Object_(new Fqsen('\\' . (string)$node->typeDeclaration->getResolvedName())); - } - } - // function foo($a = 3) - if ($node->default !== null) { - $defaultType = $this->resolveExpressionNodeToType($node->default); - if (isset($type) && !is_a($type, get_class($defaultType))) { - // TODO - verify it is worth creating a compound type - return new Types\Compound([$type, $defaultType]); - } - $type = $defaultType; - } - return $type ?? new Types\Mixed; - } - - // FUNCTIONS AND METHODS - // Get the return type - // 1. doc block - // 2. return type hint - // 3. TODO: infer from return statements - if (TolerantParserHelpers::isFunctionLike($node)) { - // Functions/methods - $docBlock = $this->getDocBlock($node); - if ( - $docBlock !== null - && !empty($returnTags = $docBlock->getTagsByName('return')) - && $returnTags[0]->getType() !== null - ) { - // Use @return tag - return $returnTags[0]->getType(); - } - if ($node->returnType !== null && !($node->returnType instanceof Tolerant\MissingToken)) { - // Use PHP7 return type hint - if ($node->returnType instanceof Tolerant\Token) { - // Resolve a string like "bool" to a type object - return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); - } - return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); - } - // Unknown return type - return new Types\Mixed; - } - - // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS - // Get the documented type the assignment resolves to. - if ( - ($declarationNode = - TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? - TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node) - ) !== null || - ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) - { - $declarationNode = $declarationNode ?? $node; - - // Property, constant or variable - // Use @var tag - if ( - ($docBlock = $this->getDocBlock($declarationNode)) - && !empty($varTags = $docBlock->getTagsByName('var')) - && ($type = $varTags[0]->getType()) - ) { - return $type; - } - - // Resolve the expression - if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { - // TODO should have default - if (isset($node->parent->rightOperand)) { - return $this->resolveExpressionNodeToType($node->parent->rightOperand); - } - } else if ($node instanceof Tolerant\Node\ConstElement) { - return $this->resolveExpressionNodeToType($node->assignment); - } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { - return $this->resolveExpressionNodeToType($node->rightOperand); - } - // TODO: read @property tags of class - // TODO: Try to infer the type from default value / constant value - // Unknown - return new Types\Mixed; - } - - // The node does not have a type - return null; - } - - /** - * Returns the fully qualified name (FQN) that is defined by a node - * Returns null if the node does not declare any symbol that can be referenced by an FQN - * - * @param Tolerant\Node $node - * @return string|null - */ - public static function getDefinedFqn($node) - { - $parent = $node->parent; - // Anonymous classes don't count as a definition - // INPUT OUTPUT: - // namespace A\B; - // class C { } A\B\C - // interface C { } A\B\C - // trait C { } A\B\C - if ( - $node instanceof Tolerant\Node\Statement\ClassDeclaration || - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || - $node instanceof Tolerant\Node\Statement\TraitDeclaration - ) { - return (string) $node->getNamespacedName(); - } - - // INPUT OUTPUT: - // namespace A\B; A\B - else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { - $name = (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); - return \count($name) > 0 ? $name : null; - } - // INPUT OUTPUT: - // namespace A\B; - // function a(); A\B\a(); - else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { - // Function: use functionName() as the name - $name = (string)$node->getNamespacedName(); - return \count($name) > 0 ? $name . '()' : null; - } - // INPUT OUTPUT - // namespace A\B; - // class C { - // function a () {} A\B\C->a() - // static function b() {} A\B\C::b() - // } - else if ($node instanceof Tolerant\Node\MethodDeclaration) { - // Class method: use ClassName->methodName() as name - $class = $node->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class - ); - if (!isset($class->name)) { - // Ignore anonymous classes - return null; - } - if ($node->isStatic()) { - return (string)$class->getNamespacedName() . '::' . $node->getName() . '()'; - } else { - return (string)$class->getNamespacedName() . '->' . $node->getName() . '()'; - } - } - - // INPUT OUTPUT - // namespace A\B; - // class C { - // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b - // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name - // } - else if ( - ($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null && - ($classDeclaration = - $node->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class - ) - ) !== null && isset($classDeclaration->name)) - { - $name = $node->getName(); - if ($propertyDeclaration->isStatic()) { - // Static Property: use ClassName::$propertyName as name - return (string)$classDeclaration->getNamespacedName() . '::$' . $name; - } - - // Instance Property: use ClassName->propertyName as name - return (string)$classDeclaration->getNamespacedName() . '->' . $name; - } - - // INPUT OUTPUT - // namespace A\B; - // const FOO = 5; A\B\FOO - // class C { - // const $a, $b = 4 A\B\C::$a(), A\B\C::$b - // } - else if (($constDeclaration = TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { - if ($constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration) { - // Basic constant: use CONSTANT_NAME as name - return (string)$node->getNamespacedName(); - } - - // Class constant: use ClassName::CONSTANT_NAME as name - $classDeclaration = $constDeclaration->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class - ); - - if (!isset($classDeclaration->name)) { - return null; - } - return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); - } - - return null; - } - - /** - * @param DocBlock | null $docBlock - * @param $variableName - * @return DocBlock\Tags\Param | null - */ - private function tryGetDocBlockTagForParameter($docBlock, $variableName) { - if ($docBlock === null) { - return null; - } - $tags = $docBlock->getTagsByName('param'); - foreach ($tags as $tag) { - if ($tag->getVariableName() === \ltrim($variableName, "$")) { - return $tag; - } - } - } -} diff --git a/src/TolerantTreeAnalyzer.php b/src/TolerantTreeAnalyzer.php deleted file mode 100644 index 1b5bd0dc..00000000 --- a/src/TolerantTreeAnalyzer.php +++ /dev/null @@ -1,186 +0,0 @@ -uri = $uri; - $this->parser = $parser; - $this->docBlockFactory = $docBlockFactory; - $this->definitionResolver = $definitionResolver; - $this->content = $content; - $this->stmts = $this->parser->parseSourceFile($content, $uri); - - // TODO - docblock errors - - $this->collectDefinitionsAndReferences($this->stmts); - } - - public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { - foreach ($stmts::CHILD_NAMES as $name) { - $node = $stmts->$name; - - if ($node === null) { - continue; - } - - if (\is_array($node)) { - foreach ($node as $child) { - if ($child instanceof Tolerant\Node) { - $this->update($child); - } - } - continue; - } - - if ($node instanceof Tolerant\Node) { - $this->update($node); - } - - if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); - - $this->diagnostics[] = new Diagnostic( - $_error->message, - new Range( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->start->character) - ), - null, - DiagnosticSeverity::ERROR, - 'php' - ); - } - } - } - - public function update($node) { - $fqn = ($this->definitionResolver)::getDefinedFqn($node); - // Only index definitions with an FQN (no variables) - if ($fqn !== null) { - $this->definitionNodes[$fqn] = $node; - $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); - } else { - $parent = $node->parent; - if (!( - ( - // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression) - && !( - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->memberName instanceof Tolerant\Token - )) - || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) - ) { - - $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn !== null) { - $this->addReference($fqn, $node); - - if ( - $node instanceof Tolerant\Node\QualifiedName - && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) - && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() - ) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); - } - } - - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if (TolerantParserHelpers::isConstantFetch($node) || - ($parent instanceof Tolerant\Node\Expression\CallExpression - && !( - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression - ))) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); - } - } - } - } - } - $this->collectDefinitionsAndReferences($node); - } - - public function getDiagnostics() { - return $this->diagnostics ?? []; - } - - private function addReference(string $fqn, Tolerant\Node $node) - { - if (!isset($this->referenceNodes[$fqn])) { - $this->referenceNodes[$fqn] = []; - } - $this->referenceNodes[$fqn][] = $node; - } - - public function getDefinitions() { - return $this->definitions ?? []; - } - - public function getDefinitionNodes() { - return $this->definitionNodes ?? []; - } - - public function getReferenceNodes() { - return $this->referenceNodes ?? []; - } - - public function getStmts() { - return $this->stmts; - } - /** - * Returns the URI of the document - * - * @return string - */ - public function getUri(): string - { - return $this->uri; - } -} diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index ddb78aba..82e5870d 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -19,83 +19,144 @@ use Sabre\Uri; use Microsoft\PhpParser as Tolerant; -class TreeAnalyzer implements TreeAnalyzerInterface { +class TreeAnalyzer { private $parser; + /** @var Tolerant\Node */ private $stmts; - private $errorHandler; - private $diagnostics; + private $content; + + /** + * TreeAnalyzer constructor. + * @param Tolerant\Parser $parser + * @param $content + * @param $docBlockFactory + * @param DefinitionResolver $definitionResolver + * @param $uri + */ public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; $this->content = $content; - $errorHandler = new ErrorHandler\Collecting; - $stmts = $this->parser->parse($content, $errorHandler); - - $this->diagnostics = []; - foreach ($errorHandler->getErrors() as $error) { - $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::ERROR, 'php'); - } + $this->stmts = $this->parser->parseSourceFile($content, $uri); - // $stmts can be null in case of a fatal parsing error <- Interesting. When do fatal parsing errors occur? - if ($stmts) { - $traverser = new NodeTraverser; + // TODO - docblock errors - // Resolve aliased names to FQNs - $traverser->addVisitor(new NameResolver($errorHandler)); - - // Add parentNode, previousSibling, nextSibling attributes - $traverser->addVisitor(new ReferencesAdder($this)); - - // Add column attributes to nodes - $traverser->addVisitor(new ColumnCalculator($content)); - - // Parse docblocks and add docBlock attributes to nodes - $docBlockParser = new DocBlockParser($this->docBlockFactory); - $traverser->addVisitor($docBlockParser); + $this->collectDefinitionsAndReferences($this->stmts); + } - $traverser->traverse($stmts); + public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { + foreach ($stmts::CHILD_NAMES as $name) { + $node = $stmts->$name; - // Report errors from parsing docblocks - foreach ($docBlockParser->errors as $error) { - $this->diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::WARNING, 'php'); + if ($node === null) { + continue; } - $traverser = new NodeTraverser; - - // Collect all definitions - $definitionCollector = new DefinitionCollector($this->definitionResolver); - $traverser->addVisitor($definitionCollector); - - // Collect all references - $referencesCollector = new ReferencesCollector($this->definitionResolver); - $traverser->addVisitor($referencesCollector); - - $traverser->traverse($stmts); + if (\is_array($node)) { + foreach ($node as $child) { + if ($child instanceof Tolerant\Node) { + $this->update($child); + } + } + continue; + } - // Register this document on the project for all the symbols defined in it - $this->definitions = $definitionCollector->definitions; - $this->definitionNodes = $definitionCollector->nodes; - foreach ($definitionCollector->definitions as $fqn => $definition) { - // $this->index->setDefinition($fqn, $definition); + if ($node instanceof Tolerant\Node) { + $this->update($node); } - // Register this document on the project for references - $this->referenceNodes = $referencesCollector->nodes; - foreach ($referencesCollector->nodes as $fqn => $nodes) { - // $this->index->addReferenceUri($fqn, $this->uri); + + if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); + + $this->diagnostics[] = new Diagnostic( + $_error->message, + new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->start->character) + ), + null, + DiagnosticSeverity::ERROR, + 'php' + ); } + } + } - $this->stmts = $stmts; + public function update($node) { + $fqn = ($this->definitionResolver)::getDefinedFqn($node); + // Only index definitions with an FQN (no variables) + if ($fqn !== null) { + $this->definitionNodes[$fqn] = $node; + $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); + } else { + $parent = $node->parent; + if (!( + ( + // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression) + && !( + $node->parent instanceof Tolerant\Node\Expression\CallExpression || + $node->memberName instanceof Tolerant\Token + )) + || ($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) + ) { + + $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); + if ($fqn !== null) { + $this->addReference($fqn, $node); + + if ( + $node instanceof Tolerant\Node\QualifiedName + && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) + && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } + } + + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if (ParserHelpers::isConstantFetch($node) || + ($parent instanceof Tolerant\Node\Expression\CallExpression + && !( + $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Tolerant\Node\Expression\MemberAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); + } + } + } + } } + $this->collectDefinitionsAndReferences($node); } public function getDiagnostics() { - return $this->diagnostics; + return $this->diagnostics ?? []; + } + + private function addReference(string $fqn, Tolerant\Node $node) + { + if (!isset($this->referenceNodes[$fqn])) { + $this->referenceNodes[$fqn] = []; + } + $this->referenceNodes[$fqn][] = $node; } public function getDefinitions() { diff --git a/src/TreeAnalyzerInterface.php b/src/TreeAnalyzerInterface.php deleted file mode 100644 index a534a728..00000000 --- a/src/TreeAnalyzerInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -getDefinitionNodes(); } } diff --git a/tests/PhpDocumentLoaderTest.php b/tests/PhpDocumentLoaderTest.php index 18e8373d..348f23fd 100644 --- a/tests/PhpDocumentLoaderTest.php +++ b/tests/PhpDocumentLoaderTest.php @@ -4,7 +4,7 @@ namespace LanguageServer\Tests\Server; use LanguageServer\{ - PhpDocument, PhpDocumentLoader, Project, TolerantDefinitionResolver + PhpDocument, PhpDocumentLoader, Project, DefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{ @@ -26,7 +26,7 @@ public function setUp() $this->loader = new PhpDocumentLoader( new FileSystemContentRetriever, $projectIndex, - new TolerantDefinitionResolver($projectIndex) + new DefinitionResolver($projectIndex) ); } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 19081afe..ca36d796 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -4,7 +4,7 @@ namespace LanguageServer\Tests\Server; use LanguageServer\{ - PhpDocument, TolerantDefinitionResolver + PhpDocument, DefinitionResolver }; use LanguageServer\Index\{ Index @@ -25,7 +25,7 @@ public function createDocument(string $uri, string $content) $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; - $definitionResolver = new TolerantDefinitionResolver($index); + $definitionResolver = new DefinitionResolver($index); return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); } diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index a93e4c10..bbef3eae 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver + Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -51,7 +51,7 @@ public function setUp() $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = new TolerantDefinitionResolver($projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index e8b417d0..20569534 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver + Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -37,7 +37,7 @@ public function setUp() { $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); - $definitionResolver = new TolerantDefinitionResolver($projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait(); diff --git a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php index aa9d7b97..4e45f9e6 100644 --- a/tests/Server/TextDocument/Definition/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/Definition/GlobalFallbackTest.php @@ -6,7 +6,7 @@ use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; use LanguageServer\{ - Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver + Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\ContentRetriever\FileSystemContentRetriever; @@ -19,7 +19,7 @@ public function setUp() $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = new TolerantDefinitionResolver($projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); $contentRetriever = new FileSystemContentRetriever; $loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Server/TextDocument/DidChangeTest.php b/tests/Server/TextDocument/DidChangeTest.php index d46067b2..4d26ed8e 100644 --- a/tests/Server/TextDocument/DidChangeTest.php +++ b/tests/Server/TextDocument/DidChangeTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Tests\MockProtocolStream; use LanguageServer\{ - Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver + Server, LanguageClient, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; @@ -23,7 +23,7 @@ public function test() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); - $definitionResolver = new TolerantDefinitionResolver($projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $phpDocument = $loader->open('whatever', "open('whatever', "textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); } diff --git a/tests/Server/TextDocument/References/GlobalFallbackTest.php b/tests/Server/TextDocument/References/GlobalFallbackTest.php index 684be182..abfefce9 100644 --- a/tests/Server/TextDocument/References/GlobalFallbackTest.php +++ b/tests/Server/TextDocument/References/GlobalFallbackTest.php @@ -4,7 +4,7 @@ namespace LanguageServer\Tests\Server\TextDocument\References; use LanguageServer\{ - LanguageClient, PhpDocumentLoader, Server, TolerantDefinitionResolver + LanguageClient, PhpDocumentLoader, Server, DefinitionResolver }; use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\Index\{ @@ -22,7 +22,7 @@ public function setUp() { $projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex->setComplete(); - $definitionResolver = new TolerantDefinitionResolver($projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index a66e82e5..06e97edd 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -9,7 +9,7 @@ use LanguageServer\Index\Index; use LanguageServer\ParserKind; use LanguageServer\PhpDocument; -use LanguageServer\TolerantDefinitionResolver; +use LanguageServer\DefinitionResolver; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlockFactory; use PHPUnit\Framework\TestCase; @@ -96,7 +96,7 @@ private function getActualTestValues($filename, $fileContents): array { $index = new Index(); $parser = new Tolerant\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); - $definitionResolver = new TolerantDefinitionResolver($index); + $definitionResolver = new DefinitionResolver($index); $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); From cf9590b9b71d7139b83f0e41af863088f20eec60 Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 13:45:23 -0700 Subject: [PATCH 098/149] Remove "use PhpParser\Node" --- src/CompletionProvider.php | 1 - src/Definition.php | 1 - src/DefinitionResolver.php | 1 - src/FqnUtilities.php | 1 - src/Protocol/Location.php | 1 - src/Protocol/SymbolInformation.php | 1 - src/utils.php | 1 - tests/PhpDocumentTest.php | 1 - 8 files changed, 8 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index bdb52f97..e355ea2c 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -3,7 +3,6 @@ namespace LanguageServer; -use PhpParser\Node; use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\{ TextEdit, diff --git a/src/Definition.php b/src/Definition.php index d4b59cb1..e302f719 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -3,7 +3,6 @@ namespace LanguageServer; -use PhpParser\Node; use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver}; use LanguageServer\Protocol\SymbolInformation; use Exception; diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 4843df07..e4b00213 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -9,7 +9,6 @@ use phpDocumentor\Reflection\{ DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types }; -use PhpParser\Node; class DefinitionResolver { diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index 3e24819e..74e809b2 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -3,7 +3,6 @@ namespace LanguageServer; use phpDocumentor\Reflection\{Type, Types}; -use PhpParser\Node; use Microsoft\PhpParser as Tolerant; class FqnUtilities diff --git a/src/Protocol/Location.php b/src/Protocol/Location.php index 6cafecdd..b838102c 100644 --- a/src/Protocol/Location.php +++ b/src/Protocol/Location.php @@ -2,7 +2,6 @@ namespace LanguageServer\Protocol; -use PhpParser\Node; use Microsoft\PhpParser as Tolerant; /** diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index 7e6f4896..bca4f8a6 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -2,7 +2,6 @@ namespace LanguageServer\Protocol; -use PhpParser\Node; use Microsoft\PhpParser as Tolerant; use Exception; diff --git a/src/utils.php b/src/utils.php index 8c854d3c..4018455a 100644 --- a/src/utils.php +++ b/src/utils.php @@ -5,7 +5,6 @@ use Throwable; use InvalidArgumentException; -use PhpParser\Node; use Sabre\Event\{Loop, Promise, EmitterInterface}; use Sabre\Uri; diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index ca36d796..eedc32b0 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -14,7 +14,6 @@ }; use Microsoft\PhpParser as Tolerant; use phpDocumentor\Reflection\DocBlockFactory; -use PhpParser\Node; use PHPUnit\Framework\TestCase; use function LanguageServer\isVendored; From 71d71a896c5b202d5092499ef93b0e081cdcb6ff Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 14:17:21 -0700 Subject: [PATCH 099/149] Remove obsolete NodeVisitors --- src/NodeVisitor/ColumnCalculator.php | 41 -------- src/NodeVisitor/DefinitionCollector.php | 48 ---------- src/NodeVisitor/DocBlockParser.php | 96 ------------------- src/NodeVisitor/NodeAtPositionFinder.php | 45 --------- src/NodeVisitor/ReferencesAdder.php | 54 ----------- src/NodeVisitor/ReferencesCollector.php | 77 --------------- .../VariableReferencesCollector.php | 50 ---------- src/PhpDocument.php | 38 +++----- src/TreeAnalyzer.php | 8 -- 9 files changed, 12 insertions(+), 445 deletions(-) delete mode 100644 src/NodeVisitor/ColumnCalculator.php delete mode 100644 src/NodeVisitor/DefinitionCollector.php delete mode 100644 src/NodeVisitor/DocBlockParser.php delete mode 100644 src/NodeVisitor/NodeAtPositionFinder.php delete mode 100644 src/NodeVisitor/ReferencesAdder.php delete mode 100644 src/NodeVisitor/ReferencesCollector.php delete mode 100644 src/NodeVisitor/VariableReferencesCollector.php diff --git a/src/NodeVisitor/ColumnCalculator.php b/src/NodeVisitor/ColumnCalculator.php deleted file mode 100644 index 6f6b3bfb..00000000 --- a/src/NodeVisitor/ColumnCalculator.php +++ /dev/null @@ -1,41 +0,0 @@ -code = $code; - $this->codeLength = strlen($code); - } - - public function enterNode(Node $node) - { - $startFilePos = $node->getAttribute('startFilePos'); - $endFilePos = $node->getAttribute('endFilePos'); - - if ($startFilePos > $this->codeLength || $endFilePos > $this->codeLength) { - throw new \RuntimeException('Invalid position information'); - } - - $startLinePos = strrpos($this->code, "\n", $startFilePos - $this->codeLength); - if ($startLinePos === false) { - $startLinePos = -1; - } - - $endLinePos = strrpos($this->code, "\n", $endFilePos - $this->codeLength); - if ($endLinePos === false) { - $endLinePos = -1; - } - - $node->setAttribute('startColumn', $startFilePos - $startLinePos); - $node->setAttribute('endColumn', $endFilePos - $endLinePos); - } -} diff --git a/src/NodeVisitor/DefinitionCollector.php b/src/NodeVisitor/DefinitionCollector.php deleted file mode 100644 index ead2d884..00000000 --- a/src/NodeVisitor/DefinitionCollector.php +++ /dev/null @@ -1,48 +0,0 @@ -definitionResolver = $definitionResolver; - } - - public function enterNode(Node $node) - { - $fqn = FqnUtilities::getDefinedFqn($node); - // Only index definitions with an FQN (no variables) - if ($fqn === null) { - return; - } - $this->nodes[$fqn] = $node; - $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); - } -} diff --git a/src/NodeVisitor/DocBlockParser.php b/src/NodeVisitor/DocBlockParser.php deleted file mode 100644 index 78f928e3..00000000 --- a/src/NodeVisitor/DocBlockParser.php +++ /dev/null @@ -1,96 +0,0 @@ -docBlockFactory = $docBlockFactory; - } - - public function beforeTraverse(array $nodes) - { - $this->namespace = ''; - $this->prefix = ''; - $this->aliases = []; - } - - public function enterNode(Node $node) - { - if ($node instanceof Node\Stmt\Namespace_) { - $this->namespace = (string)$node->name; - } else if ($node instanceof Node\Stmt\GroupUse) { - $this->prefix = (string)$node->prefix . '\\'; - } else if ($node instanceof Node\Stmt\UseUse) { - $this->aliases[$node->alias] = $this->prefix . (string)$node->name; - } - $docComment = $node->getDocComment(); - if ($docComment === null) { - return; - } - $context = new Context($this->namespace, $this->aliases); - try { - $docBlock = $this->docBlockFactory->create($docComment->getText(), $context); - $node->setAttribute('docBlock', $docBlock); - } catch (Exception $e) { - $this->errors[] = new PhpParser\Error($e->getMessage(), [ - 'startFilePos' => $docComment->getFilePos(), - 'endFilePos' => $docComment->getFilePos() + strlen($docComment->getText()), - 'startLine' => $docComment->getLine(), - 'endLine' => $docComment->getLine() + preg_match_all('/[\\n\\r]/', $docComment->getText()) + 1 - ]); - } - } - - public function leaveNode(Node $node) - { - if ($node instanceof Node\Stmt\Namespace_) { - $this->namespace = ''; - $this->aliases = []; - } else if ($node instanceof Node\Stmt\GroupUse) { - $this->prefix = ''; - } - } -} diff --git a/src/NodeVisitor/NodeAtPositionFinder.php b/src/NodeVisitor/NodeAtPositionFinder.php deleted file mode 100644 index cb178014..00000000 --- a/src/NodeVisitor/NodeAtPositionFinder.php +++ /dev/null @@ -1,45 +0,0 @@ -position = $position; - } - - public function leaveNode(Node $node) - { - if ($this->node === null) { - $range = Range::fromNode($node); - if ($range->includes($this->position)) { - $this->node = $node; - return NodeTraverser::STOP_TRAVERSAL; - } - } - } -} diff --git a/src/NodeVisitor/ReferencesAdder.php b/src/NodeVisitor/ReferencesAdder.php deleted file mode 100644 index 9c6ac0f8..00000000 --- a/src/NodeVisitor/ReferencesAdder.php +++ /dev/null @@ -1,54 +0,0 @@ -document = $document; - } - - public function enterNode(Node $node) - { - $node->setAttribute('ownerDocument', $this->document); - if (!empty($this->stack)) { - $node->setAttribute('parentNode', end($this->stack)); - } - if (isset($this->previous) && $this->previous->getAttribute('parentNode') === $node->getAttribute('parentNode')) { - $node->setAttribute('previousSibling', $this->previous); - $this->previous->setAttribute('nextSibling', $node); - } - $this->stack[] = $node; - } - - public function leaveNode(Node $node) - { - $this->previous = $node; - array_pop($this->stack); - } -} diff --git a/src/NodeVisitor/ReferencesCollector.php b/src/NodeVisitor/ReferencesCollector.php deleted file mode 100644 index cc20ffdd..00000000 --- a/src/NodeVisitor/ReferencesCollector.php +++ /dev/null @@ -1,77 +0,0 @@ -definitionResolver = $definitionResolver; - } - - public function enterNode(Node $node) - { - // Check if the node references any global symbol - $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn) { - $parent = $node->getAttribute('parentNode'); - $grandParent = $parent ? $parent->getAttribute('parentNode') : null; - $this->addReference($fqn, $node); - if ( - $node instanceof Node\Name - && $node->isQualified() - && !($parent instanceof Node\Stmt\Namespace_ && $parent->name === $node) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); - } - } - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if ($parent instanceof Node\Expr\ConstFetch || $parent instanceof Node\Expr\FuncCall) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); - } - } - } - } - - private function addReference(string $fqn, Node $node) - { - if (!isset($this->nodes[$fqn])) { - $this->nodes[$fqn] = []; - } - $this->nodes[$fqn][] = $node; - } -} diff --git a/src/NodeVisitor/VariableReferencesCollector.php b/src/NodeVisitor/VariableReferencesCollector.php deleted file mode 100644 index bb44bdc8..00000000 --- a/src/NodeVisitor/VariableReferencesCollector.php +++ /dev/null @@ -1,50 +0,0 @@ -name = $name; - } - - public function enterNode(Node $node) - { - if ($node instanceof Node\Expr\Variable && $node->name === $this->name) { - $this->nodes[] = $node; - } else if ($node instanceof Node\FunctionLike) { - // If we meet a function node, dont traverse its statements, they are in another scope - // except it is a closure that has imported the variable through use - if ($node instanceof Node\Expr\Closure) { - foreach ($node->uses as $use) { - if ($use->var === $this->name) { - return; - } - } - } - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - } -} diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 878cfe99..b755dead 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -4,17 +4,11 @@ namespace LanguageServer; use LanguageServer\Index\Index; -use LanguageServer\NodeVisitor\{ - NodeAtPositionFinder -}; use LanguageServer\Protocol\{ Diagnostic, Position, Range }; use Microsoft\PhpParser as Tolerant; use phpDocumentor\Reflection\DocBlockFactory; -use PhpParser\{ - Node, NodeTraverser -}; class PhpDocument { @@ -61,7 +55,7 @@ class PhpDocument /** * The AST of the document * - * @var Node[] | Tolerant\Node + * @var Tolerant\Node */ private $stmts; @@ -75,14 +69,14 @@ class PhpDocument /** * Map from fully qualified name (FQN) to Node * - * @var Node[] + * @var Tolerant\Node */ private $definitionNodes; /** * Map from fully qualified name (FQN) to array of nodes that reference the symbol * - * @var Node[][] + * @var Tolerant\Node[][] */ private $referenceNodes; @@ -121,7 +115,7 @@ public function __construct( * Get all references of a fully qualified name * * @param string $fqn The fully qualified name of the symbol - * @return Node[] + * @return Tolerant\Node[] */ public function getReferenceNodesByFqn(string $fqn) { @@ -226,7 +220,7 @@ public function getUri(): string /** * Returns the AST of the document * - * @return Node[] | Tolerant\Node | null + * @return Tolerant\Node | null */ public function getStmts() { @@ -245,20 +239,12 @@ public function getNodeAtPosition(Position $position) return null; } - if (\is_array($this->stmts)) { - $traverser = new NodeTraverser; - $finder = new NodeAtPositionFinder($position); - $traverser->addVisitor($finder); - $traverser->traverse($this->stmts); - return $finder->node; - } else { - $offset = $position->toOffset($this->stmts->getFileContents()); - $node = $this->stmts->getDescendantNodeAtPosition($offset); - if ($node !== null && $node->getStart() > $offset) { - return null; - } - return $node; + $offset = $position->toOffset($this->stmts->getFileContents()); + $node = $this->stmts->getDescendantNodeAtPosition($offset); + if ($node !== null && $node->getStart() > $offset) { + return null; } + return $node; } /** @@ -281,7 +267,7 @@ public function getRange(Range $range) * Returns the definition node for a fully qualified name * * @param string $fqn - * @return Node|null + * @return Tolerant\Node|null */ public function getDefinitionNodeByFqn(string $fqn) { @@ -291,7 +277,7 @@ public function getDefinitionNodeByFqn(string $fqn) /** * Returns a map from fully qualified name (FQN) to Nodes defined in this document * - * @return Node[] + * @return Tolerant\Node[] */ public function getDefinitionNodes() { diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 82e5870d..f5cfbaf6 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -4,14 +4,6 @@ namespace LanguageServer; use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, TextEdit}; -use LanguageServer\NodeVisitor\{ - NodeAtPositionFinder, - ReferencesAdder, - DocBlockParser, - DefinitionCollector, - ColumnCalculator, - ReferencesCollector -}; use LanguageServer\Index\Index; use PhpParser\{Error, ErrorHandler, Node, NodeTraverser, Parser}; use PhpParser\NodeVisitor\NameResolver; From 442fc7ea0257e6b2c811a8ad8b576cf724ddaa94 Mon Sep 17 00:00:00 2001 From: roblou Date: Fri, 19 May 2017 14:26:30 -0700 Subject: [PATCH 100/149] Remove remaining 'use PhpParser\' statements and some dead code --- src/Parser.php | 25 ------------- src/PhpDocument.php | 4 +-- src/Protocol/Diagnostic.php | 22 ------------ src/Protocol/Range.php | 36 ++++--------------- src/TreeAnalyzer.php | 2 -- tests/NodeVisitor/DefinitionCollectorTest.php | 4 +-- 6 files changed, 9 insertions(+), 84 deletions(-) delete mode 100644 src/Parser.php diff --git a/src/Parser.php b/src/Parser.php deleted file mode 100644 index d6d6d133..00000000 --- a/src/Parser.php +++ /dev/null @@ -1,25 +0,0 @@ - [ - 'comments', - 'startLine', - 'endLine', - 'startFilePos', - 'endFilePos' - ] - ]); - parent::__construct($lexer); - } -} diff --git a/src/PhpDocument.php b/src/PhpDocument.php index b755dead..77c9aac7 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -15,7 +15,7 @@ class PhpDocument /** * The PHPParser instance * - * @var Parser + * @var Tolerant\Parser */ private $parser; @@ -91,7 +91,7 @@ class PhpDocument * @param string $uri The URI of the document * @param string $content The content of the document * @param Index $index The Index to register definitions and references to - * @param Parser $parser The PHPParser instance + * @param Tolerant\Parser $parser The PhpParser instance * @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks * @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace */ diff --git a/src/Protocol/Diagnostic.php b/src/Protocol/Diagnostic.php index 44a24c12..7bf98953 100644 --- a/src/Protocol/Diagnostic.php +++ b/src/Protocol/Diagnostic.php @@ -2,8 +2,6 @@ namespace LanguageServer\Protocol; -use PhpParser\Error; - /** * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects are only valid in the scope of a * resource. @@ -47,26 +45,6 @@ class Diagnostic */ public $message; - /** - * Creates a diagnostic from a PhpParser Error - * - * @param Error $error Message and code will be used - * @param string $content The file content to calculate the column info - * @param int $severity DiagnosticSeverity - * @param string $source A human-readable string describing the source of this diagnostic - * @return self - */ - public static function fromError(Error $error, string $content, int $severity = null, string $source = null): self - { - return new self( - $error->getRawMessage(), // Do not include "on line ..." in the error message - Range::fromError($error, $content), - $error->getCode(), - $severity, - $source - ); - } - /** * @param string $message The diagnostic's message * @param Range $range The range at which the message applies diff --git a/src/Protocol/Range.php b/src/Protocol/Range.php index 908dd679..de2011b9 100644 --- a/src/Protocol/Range.php +++ b/src/Protocol/Range.php @@ -2,7 +2,6 @@ namespace LanguageServer\Protocol; -use PhpParser\{Error, Node}; use Microsoft\PhpParser as Tolerant; /** @@ -27,40 +26,17 @@ class Range /** * Returns the range the node spans * - * @param Node | Tolerant\Node $node + * @param Tolerant\Node $node * @return self */ public static function fromNode($node) { - if ($node instanceof Node) { - return new self( - new Position($node->getAttribute('startLine') - 1, $node->getAttribute('startColumn') - 1), - new Position($node->getAttribute('endLine') - 1, $node->getAttribute('endColumn')) - ); - } else { - $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); + $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); - return new self( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->end->character) - ); - } - } - - /** - * Returns the range where an error occured - * - * @param \PhpParser\Error $error - * @param string $content - * @return self - */ - public static function fromError(Error $error, string $content) - { - $startLine = max($error->getStartLine() - 1, 0); - $endLine = max($error->getEndLine() - 1, $startLine); - $startColumn = $error->hasColumnInfo() ? $error->getStartColumn($content) - 1 : 0; - $endColumn = $error->hasColumnInfo() ? $error->getEndColumn($content) : 0; - return new self(new Position($startLine, $startColumn), new Position($endLine, $endColumn)); + return new self( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + ); } public function __construct(Position $start = null, Position $end = null) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index f5cfbaf6..e4cd7885 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -5,8 +5,6 @@ use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, TextEdit}; use LanguageServer\Index\Index; -use PhpParser\{Error, ErrorHandler, Node, NodeTraverser, Parser}; -use PhpParser\NodeVisitor\NameResolver; use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Uri; use Microsoft\PhpParser as Tolerant; diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index 0b507817..8e8b9e14 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -4,7 +4,6 @@ namespace LanguageServer\Tests\Server\TextDocument; use PHPUnit\Framework\TestCase; -use PhpParser\{Node}; use phpDocumentor\Reflection\DocBlockFactory; use LanguageServer\{ DefinitionResolver, TreeAnalyzer @@ -62,9 +61,8 @@ public function testDoesNotCollectReferences() /** * @param $path - * @return Node */ - private function collectDefinitions($path):array + private function collectDefinitions($path): array { $uri = pathToUri($path); $parser = new Tolerant\Parser(); From b4e77f2e9c47311b57d6e800235f3ee03f285398 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 19 May 2017 14:40:38 -0700 Subject: [PATCH 101/149] Remove more PhpParser\Node references --- src/CompletionProvider.php | 7 +++---- src/DefinitionResolver.php | 4 ++-- src/FqnUtilities.php | 18 ------------------ src/Protocol/Location.php | 16 ++++++---------- src/Server/TextDocument.php | 6 +++--- src/utils.php | 17 ----------------- tests/PhpDocumentTest.php | 6 +----- 7 files changed, 15 insertions(+), 59 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index e355ea2c..2b084962 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -158,7 +158,6 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $node->parent->memberName === $node) ) { // Find variables, parameters and use statements in the scope - // If there was only a $ typed, $node will be instanceof Node\Error $namePrefix = $node->getName() ?? ''; foreach ($this->suggestVariablesAtNode($node, $namePrefix) as $var) { $item = new CompletionItem; @@ -334,9 +333,9 @@ private function expandParentFqns(array $fqns): array * and at each level walk all previous siblings and their children to search for definitions * of that variable * - * @param Node $node + * @param Tolerant\Node $node * @param string $namePrefix Prefix to filter - * @return array + * @return array */ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix = ''): array { @@ -394,7 +393,7 @@ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix * * @param Node $node * @param string $namePrefix Prefix to filter - * @return Node\Expr\Variable[] + * @return Tolerant\Node\Expression\Variable[] */ private function findVariableDefinitionsInNode(Tolerant\Node $node, string $namePrefix = ''): array { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index e4b00213..8cec289a 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -472,8 +472,8 @@ private static function getContainingClassFqn(Tolerant\Node $node) /** * Returns the assignment or parameter node where a variable was defined * - * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access - * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null + * @param Tolerant\Node\Expression\Variable | Tolerant\Node\Expression\ClosureUse $var The variable access + * @return Tolerant\Node\Expression\Assign | Tolerant\Node\Expression\AssignOp|Node\Param | Tolerant\Node\Expression\ClosureUse|null */ public function resolveVariableToNode($var) { diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index 74e809b2..a569d9b8 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -7,24 +7,6 @@ class FqnUtilities { - /** - * Returns the fully qualified name (FQN) that is defined by a node - * Returns null if the node does not declare any symbol that can be referenced by an FQN - * - * @param Node | Tolerant\Node $node - * @return string|null - */ - public static function getDefinedFqn($node) - { - if ($node instanceof Node) { - return DefinitionResolver::getDefinedFqn($node); - } elseif ($node instanceof Tolerant\Node) { - return DefinitionResolver::getDefinedFqn($node); - } - - throw new \TypeError("Unspported Node class"); - } - /** * Returns all possible FQNs in a type * diff --git a/src/Protocol/Location.php b/src/Protocol/Location.php index b838102c..0de3c384 100644 --- a/src/Protocol/Location.php +++ b/src/Protocol/Location.php @@ -22,20 +22,16 @@ class Location /** * Returns the location of the node * - * @param Node | Tolerant\Node $node + * @param Tolerant\Node $node * @return self */ public static function fromNode($node) { - if ($node instanceof Node) { - return new self($node->getAttribute('ownerDocument')->getUri(), Range::fromNode($node)); - } else { - $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); - return new self($node->getUri(), new Range( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->end->character) - )); - } + $range = Tolerant\PositionUtilities::getRangeFromPosition($node->getStart(), $node->getWidth(), $node->getFileContents()); + return new self($node->getUri(), new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + )); } public function __construct(string $uri = null, Range $range = null) diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 7a2b062c..97a17811 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -208,7 +208,7 @@ public function references( } } else { // Definition with a global FQN - $fqn = FqnUtilities::getDefinedFqn($node); + $fqn = DefinitionResolver::getDefinedFqn($node); // var_dump($fqn); // Wait until indexing finished if (!$this->index->isComplete()) { @@ -255,7 +255,7 @@ public function definition(TextDocumentIdentifier $textDocument, Position $posit return []; } // Handle definition nodes - $fqn = FqnUtilities::getDefinedFqn($node); + $fqn = DefinitionResolver::getDefinedFqn($node); while (true) { if ($fqn) { $def = $this->index->getDefinition($fqn); @@ -296,7 +296,7 @@ public function hover(TextDocumentIdentifier $textDocument, Position $position): if ($node === null) { return new Hover([]); } - $definedFqn = FqnUtilities::getDefinedFqn($node); + $definedFqn = DefinitionResolver::getDefinedFqn($node); while (true) { if ($definedFqn) { // Support hover for definitions diff --git a/src/utils.php b/src/utils.php index 4018455a..ec69a5bb 100644 --- a/src/utils.php +++ b/src/utils.php @@ -93,23 +93,6 @@ function waitForEvent(EmitterInterface $emitter, string $event): Promise return $p; } -/** - * Returns the closest node of a specific type - * - * @param Node $node - * @param string $type The node class name - * @return Node|null $type - */ -function getClosestNode(Node $node, string $type) -{ - $n = $node; - while ($n = $n->getAttribute('parentNode')) { - if ($n instanceof $type) { - return $n; - } - } -} - /** * Returns the part of $b that is not overlapped by $a * Example: diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index eedc32b0..926cb9d2 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -44,11 +44,7 @@ public function testGetNodeAtPosition() } private function assertQualifiedName($node) { - if ($node instanceof Node) { - $this->assertInstanceOf(Node\Name\FullyQualified::class, $node); - } else { - $this->assertInstanceOf(Tolerant\Node\QualifiedName::class, $node); - } + $this->assertInstanceOf(Tolerant\Node\QualifiedName::class, $node); } public function testIsVendored() From 6e1f638b368b4a7d342b7086bc0ae0f420246a18 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 19 May 2017 14:41:17 -0700 Subject: [PATCH 102/149] Remove nikic/php-parser reference --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index fa6924cd..c896216f 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,6 @@ }, "require": { "php": ">=7.0", - "nikic/php-parser": "^3.0.4", "phpdocumentor/reflection-docblock": "^3.0", "sabre/event": "^5.0", "felixfbecker/advanced-json-rpc": "^2.0", From 97937eaadb280cf6f4dd0119da664b7b7c583782 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 22 May 2017 15:44:24 -0700 Subject: [PATCH 103/149] Fix unsupported hover test --- tests/Server/TextDocument/HoverTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Server/TextDocument/HoverTest.php b/tests/Server/TextDocument/HoverTest.php index 4aaf87ae..163e13bb 100644 --- a/tests/Server/TextDocument/HoverTest.php +++ b/tests/Server/TextDocument/HoverTest.php @@ -165,8 +165,9 @@ public function testHoverForGlobalConstant() new TextDocumentIdentifier($reference->uri), $reference->range->end )->wait(); + // TODO - should pretty print with fqns, like \define, \false. Not yet supported by tolerant-php-parser $this->assertEquals(new Hover([ - new MarkedString('php', "range), $result); } From f51af8bc0d89e90363494c7e366e3a2debf50833 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 23 May 2017 18:27:11 -0700 Subject: [PATCH 104/149] Minor cleanup --- fixtures/global_symbols.php | 2 +- src/Protocol/SymbolInformation.php | 1 - src/Server/TextDocument.php | 3 +-- tests/Server/TextDocument/References/NamespacedTest.php | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/fixtures/global_symbols.php b/fixtures/global_symbols.php index 098d1878..ac93b685 100644 --- a/fixtures/global_symbols.php +++ b/fixtures/global_symbols.php @@ -55,7 +55,7 @@ public static function staticTestMethod() * @param TestClass $testParameter Lorem sunt velit incididunt mollit * @return TestClass */ - public function testMethod($testParameter) : TestInterface + public function testMethod($testParameter): TestInterface { $this->testProperty = $testParameter; } diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index 5d1f3613..ec8730c1 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -54,7 +54,6 @@ public static function fromNode($node, string $fqn = null) } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; } - // TODO 'define' else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { // constants with define() like // define('TEST_DEFINE_CONSTANT', false); diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 97a17811..6dadf2fc 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -209,7 +209,7 @@ public function references( } else { // Definition with a global FQN $fqn = DefinitionResolver::getDefinedFqn($node); - // var_dump($fqn); + // Wait until indexing finished if (!$this->index->isComplete()) { yield waitForEvent($this->index, 'complete'); @@ -228,7 +228,6 @@ public function references( $refs = $document->getReferenceNodesByFqn($fqn); if ($refs !== null) { foreach ($refs as $ref) { - // var_dump($ref->getNodeKindName()); $locations[] = Location::fromNode($ref); } } diff --git a/tests/Server/TextDocument/References/NamespacedTest.php b/tests/Server/TextDocument/References/NamespacedTest.php index 32b8c4bc..1ee1ab4d 100644 --- a/tests/Server/TextDocument/References/NamespacedTest.php +++ b/tests/Server/TextDocument/References/NamespacedTest.php @@ -28,7 +28,6 @@ public function testReferencesForNamespaces() new TextDocumentIdentifier($definition->uri), $definition->range->end )->wait(); - // var_dump($result); $this->assertEquals(parent::getReferenceLocations('TestNamespace'), $result); } } From 836cdb77c071e4b12004330a5ff8a6afc0f70c34 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 24 May 2017 11:25:01 -0700 Subject: [PATCH 105/149] Fix HoverTest after previous fixture change --- tests/Server/TextDocument/HoverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Server/TextDocument/HoverTest.php b/tests/Server/TextDocument/HoverTest.php index 163e13bb..5010360f 100644 --- a/tests/Server/TextDocument/HoverTest.php +++ b/tests/Server/TextDocument/HoverTest.php @@ -61,7 +61,7 @@ public function testHoverForMethod() $reference->range->end )->wait(); $this->assertEquals(new Hover([ - new MarkedString('php', "range), $result); } From 3dfe50572719c9fc37f228b6c0aa8cc3579c85ed Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 24 May 2017 11:26:53 -0700 Subject: [PATCH 106/149] Remove "Tolerant" alias - Now unnecessary - Makes type annotations more readable --- Performance.php | 4 +- src/CompletionProvider.php | 59 ++-- src/ComposerScripts.php | 4 +- src/DefinitionResolver.php | 303 +++++++++--------- src/FqnUtilities.php | 2 +- src/ParserHelpers.php | 111 +++---- src/PhpDocument.php | 23 +- src/PhpDocumentLoader.php | 6 +- src/Protocol/Location.php | 7 +- src/Protocol/Range.php | 7 +- src/Protocol/SymbolInformation.php | 41 +-- src/Server/TextDocument.php | 17 +- src/TreeAnalyzer.php | 43 +-- tests/DefinitionResolverTest.php | 10 +- tests/NodeVisitor/DefinitionCollectorTest.php | 37 +-- tests/PhpDocumentTest.php | 7 +- tests/Validation/ValidationTest.php | 4 +- 17 files changed, 348 insertions(+), 337 deletions(-) diff --git a/Performance.php b/Performance.php index 3a04bc7b..312b726f 100644 --- a/Performance.php +++ b/Performance.php @@ -8,7 +8,7 @@ use LanguageServer\ParserKind; use LanguageServer\PhpDocument; use LanguageServer\DefinitionResolver; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; use phpDocumentor\Reflection\DocBlockFactory; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -58,7 +58,7 @@ $definitions = []; $definitionResolver = new DefinitionResolver($index); - $parser = new Tolerant\Parser(); + $parser = new PhpParser\Parser(); try { $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2b084962..fef59c22 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -13,7 +13,8 @@ CompletionItemKind }; use function LanguageServer\{strStartsWith}; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; class CompletionProvider { @@ -127,7 +128,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $offset = $node === null ? -1 : $pos->toOffset($node->getFileContents()); if ($node !== null && $offset > $node->getEndPosition() && - $node->parent->getLastChild() instanceof Tolerant\MissingToken + $node->parent->getLastChild() instanceof PhpParser\MissingToken ) { $node = $node->parent; } @@ -135,14 +136,14 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $list = new CompletionList; $list->isIncomplete = true; - if ($node instanceof Tolerant\Node\Expression\Variable && - $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression && - $node->name instanceof Tolerant\MissingToken + if ($node instanceof Node\Expression\Variable && + $node->parent instanceof Node\Expression\ObjectCreationExpression && + $node->name instanceof PhpParser\MissingToken ) { $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('textEdit = new TextEdit( new Range($pos, $pos), @@ -152,9 +153,9 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } // VARIABLES 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) ) { // Find variables, parameters and use statements in the scope @@ -176,7 +177,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi // MEMBER ACCESS EXPRESSIONS // $a->c# // $a-># - elseif ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { + elseif ($node instanceof Node\Expression\MemberAccessExpression) { $prefixes = FqnUtilities::getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) ); @@ -204,8 +205,8 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi // A\B\C::foo# // TODO: $a::# elseif ( - ($scoped = $node->parent) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($scoped = $node) instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression + ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression || + ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression ) { $prefixes = FqnUtilities::getFqnsFromType( $classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier) @@ -227,13 +228,13 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } elseif (ParserHelpers::isConstantFetch($node) || - ($creation = $node->parent) instanceof Tolerant\Node\Expression\ObjectCreationExpression || - (($creation = $node) instanceof Tolerant\Node\Expression\ObjectCreationExpression)) { + ($creation = $node->parent) instanceof Node\Expression\ObjectCreationExpression || + (($creation = $node) instanceof Node\Expression\ObjectCreationExpression)) { $class = isset($creation) ? $creation->classTypeDesignator : $node; - $prefix = $class instanceof Tolerant\Node\QualifiedName - ? (string)Tolerant\ResolvedName::buildName($class->nameParts, $class->getFileContents()) + $prefix = $class instanceof Node\QualifiedName + ? (string)PhpParser\ResolvedName::buildName($class->nameParts, $class->getFileContents()) : $class->getText($node->getFileContents()); $namespaceDefinition = $node->getNamespaceDefinition(); @@ -248,11 +249,11 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $fqnContainsPrefix = empty($prefix) || strpos($fqn, $prefix) !== false; if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && $fqnContainsPrefix) { 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; - $isNotFullyQualified = !($class instanceof Tolerant\Node\QualifiedName) || !$class->isFullyQualifiedName(); + $isNotFullyQualified = !($class instanceof Node\QualifiedName) || !$class->isFullyQualifiedName(); if ($isNotFullyQualified) { foreach ($namespaceImportTable as $alias => $name) { if (strStartsWith($fqn, $name)) { @@ -297,7 +298,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } 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) { $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); $item->insertText = $keyword . ' '; @@ -333,11 +334,11 @@ private function expandParentFqns(array $fqns): array * and at each level walk all previous siblings and their children to search for definitions * of that variable * - * @param Tolerant\Node $node + * @param Node $node * @param string $namePrefix Prefix to filter - * @return array + * @return array */ - private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix = ''): array + private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): array { $vars = []; @@ -375,7 +376,7 @@ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix } } - 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) { $useName = $use->getName(); if (empty($namePrefix) || strpos($useName, $namePrefix) !== false) { @@ -393,24 +394,24 @@ private function suggestVariablesAtNode(Tolerant\Node $node, string $namePrefix * * @param Node $node * @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 = []; // If the child node is a variable assignment, save it $isAssignmentToVariable = function ($node) use ($namePrefix) { - return $node instanceof Tolerant\Node\Expression\AssignmentExpression - && $node->leftOperand instanceof Tolerant\Node\Expression\Variable + return $node instanceof Node\Expression\AssignmentExpression + && $node->leftOperand instanceof Node\Expression\Variable && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); }; $isNotFunctionLike = function($node) { return !( ParserHelpers::isFunctionLike($node) || - $node instanceof Tolerant\Node\Statement\ClassDeclaration || - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || - $node instanceof Tolerant\Node\Statement\TraitDeclaration + $node instanceof Node\Statement\ClassDeclaration || + $node instanceof Node\Statement\InterfaceDeclaration || + $node instanceof Node\Statement\TraitDeclaration ); }; diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index 11f04332..487c39d5 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -10,7 +10,7 @@ use Webmozart\PathUtil\Path; use Sabre\Uri; 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) { if (file_exists($file)) { @@ -30,7 +30,7 @@ public static function parseStubs() $finder = new FileSystemFilesFinder; $contentRetriever = new FileSystemContentRetriever; $docBlockFactory = DocBlockFactory::createInstance(); - $parser = new Tolerant\Parser(); + $parser = new PhpParser\Parser(); $definitionResolver = new DefinitionResolver($index); $stubsLocation = null; diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 9452507b..abce69e9 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -5,7 +5,8 @@ use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\SymbolInformation; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; use phpDocumentor\Reflection\{ DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types }; @@ -46,7 +47,7 @@ public function __construct(ReadableIndex $index) /** * Builds the declaration line for a given node. Declarations with multiple lines are trimmed. * - * @param Tolerant\Node $node + * @param Node $node * @return string */ public function getDeclarationLineFromNode($node): string @@ -82,13 +83,13 @@ public function getDeclarationLineFromNode($node): string /** * Gets the documentation string for a node, if it has one * - * @param Tolerant\Node $node + * @param Node $node * @return string|null */ public function getDocumentationFromNode($node) { // 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; } @@ -100,7 +101,7 @@ public function getDocumentationFromNode($node) } // 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(); $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); @@ -129,10 +130,10 @@ public function getDocumentationFromNode($node) /** * Gets Doc Block with resolved names for a Node * - * @param Tolerant\Node $node + * @param Node $node * @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) $docCommentText = $node->getDocCommentText(); @@ -161,7 +162,7 @@ private function getDocBlock(Tolerant\Node $node) /** * Create a Definition for a definition node * - * @param Tolerant\Node $node + * @param Node $node * @param string $fqn * @return Definition */ @@ -171,30 +172,30 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition $def->fqn = $fqn; // 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 $def->isGlobal = ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || - $node instanceof Tolerant\Node\Statement\ClassDeclaration || - $node instanceof Tolerant\Node\Statement\TraitDeclaration || + $node instanceof Node\Statement\InterfaceDeclaration || + $node instanceof Node\Statement\ClassDeclaration || + $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 $def->isStatic = ( - ($node instanceof Tolerant\Node\MethodDeclaration && $node->isStatic()) || + ($node instanceof Node\MethodDeclaration && $node->isStatic()) || (($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && $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 $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { @@ -202,7 +203,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition // TODO - why is this represented as an array? // TODO interface implementations. } elseif ( - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration && + $node instanceof Node\Statement\InterfaceDeclaration && // TODO - this should be better represented in the parser API $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null ) { @@ -226,7 +227,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition /** * 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 */ public function resolveReferenceNodeToDefinition($node) @@ -235,8 +236,8 @@ public function resolveReferenceNodeToDefinition($node) // Variables are not indexed globally, as they stay in the file scope anyway. // Ignore variable nodes that are part of ScopedPropertyAccessExpression, // as the scoped property access expression node is handled separately. - if ($node instanceof Tolerant\Node\Expression\Variable && - !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) + if ($node instanceof Node\Expression\Variable && + !($parent instanceof Node\Expression\ScopedPropertyAccessExpression)) { // Resolve $this to the containing class definition. if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { @@ -259,7 +260,7 @@ public function resolveReferenceNodeToDefinition($node) // 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 // 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 $this->index->getDefinition($fqn, $globalFallback); } @@ -273,11 +274,11 @@ public function resolveReferenceNodeToDefinition($node) */ public function resolveReferenceNodeToFqn($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); } - else if ($node instanceof Tolerant\Node\Expression\MemberAccessExpression) { + else if ($node instanceof Node\Expression\MemberAccessExpression) { return $this->resolveMemberAccessExpressionNodeToFqn($node); } else if (ParserHelpers::isConstantFetch($node)) { @@ -285,13 +286,13 @@ public function resolveReferenceNodeToFqn($node) { } else if ( // A\B::C - constant access expression - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression - && !($node->memberName instanceof Tolerant\Node\Expression\Variable) + $node instanceof Node\Expression\ScopedPropertyAccessExpression + && !($node->memberName instanceof Node\Expression\Variable) ) { return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); } else if ( // 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); } @@ -299,36 +300,36 @@ public function resolveReferenceNodeToFqn($node) { return null; } - private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node) { + private function resolveQualifiedNameNodeToFqn(Node\QualifiedName $node) { $parent = $node->parent; - if ($parent instanceof Tolerant\Node\TraitSelectOrAliasClause) { + if ($parent instanceof Node\TraitSelectOrAliasClause) { return null; } // Add use clause references - if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause - || $useClause instanceof Tolerant\Node\NamespaceUseClause + if (($useClause = $parent) instanceof Node\NamespaceUseGroupClause + || $useClause instanceof Node\NamespaceUseClause ) { $contents = $node->getFileContents(); - if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { + if ($useClause instanceof Node\NamespaceUseGroupClause) { $prefix = $useClause->parent->parent->namespaceName; if ($prefix === null) { return null; } - $name = Tolerant\ResolvedName::buildName($prefix->nameParts, $contents); + $name = PhpParser\ResolvedName::buildName($prefix->nameParts, $contents); $name->addNameParts($node->nameParts, $contents); $name = (string)$name; if ($useClause->functionOrConst === null) { - $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); - if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $useClause = $node->getFirstAncestor(Node\Statement\NamespaceUseDeclaration::class); + if ($useClause->functionOrConst !== null && $useClause->functionOrConst->kind === PhpParser\TokenKind::FunctionKeyword) { $name .= '()'; } } return $name; } else { - $name = (string) Tolerant\ResolvedName::buildName($node->nameParts, $contents); - if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === Tolerant\TokenKind::FunctionKeyword) { + $name = (string) PhpParser\ResolvedName::buildName($node->nameParts, $contents); + if ($useClause->groupClauses === null && $useClause->parent->parent->functionOrConst !== null && $useClause->parent->parent->functionOrConst->kind === PhpParser\TokenKind::FunctionKeyword) { $name .= '()'; } } @@ -339,14 +340,14 @@ private function resolveQualifiedNameNodeToFqn(Tolerant\Node\QualifiedName $node // For extends, implements, type hints and classes of classes of static calls use the name directly $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); - if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { + if ($node->parent instanceof Node\Expression\CallExpression) { $name .= '()'; } return $name; } - private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression\MemberAccessExpression $access) { - if ($access->memberName instanceof Tolerant\Node\Expression) { + private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAccessExpression $access) { + if ($access->memberName instanceof Node\Expression) { // Cannot get definition if right-hand side is expression return null; } @@ -382,7 +383,7 @@ private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression $classFqn = substr((string)$varType->getFqsen(), 1); } $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 .= '()'; } @@ -412,14 +413,14 @@ private function resolveMemberAccessExpressionNodeToFqn(Tolerant\Node\Expression return $classFqn . $memberSuffix; } - private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Expression\ScopedPropertyAccessExpression $scoped) { - if ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\Expression\Variable) { + private function resolveScopedPropertyAccessExpressionNodeToFqn(Node\Expression\ScopedPropertyAccessExpression $scoped) { + if ($scoped->scopeResolutionQualifier instanceof Node\Expression\Variable) { $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); if ($varType === null) { return null; } $className = substr((string)$varType->getFqsen(), 1); - } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + } elseif ($scoped->scopeResolutionQualifier instanceof Node\QualifiedName) { $className = (string)$scoped->scopeResolutionQualifier->getResolvedName(); } else { return null; @@ -427,7 +428,7 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex if ($className === 'self' || $className === 'static' || $className === 'parent') { // 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) { return null; } @@ -440,11 +441,11 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex } else { $className = (string)$classNode->getNamespacedName(); } - } elseif ($scoped->scopeResolutionQualifier instanceof Tolerant\Node\QualifiedName) { + } elseif ($scoped->scopeResolutionQualifier instanceof Node\QualifiedName) { $className = $scoped->scopeResolutionQualifier->getResolvedName(); } - if ($scoped->memberName instanceof Tolerant\Node\Expression\Variable) { - if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { + if ($scoped->memberName instanceof Node\Expression\Variable) { + if ($scoped->parent instanceof Node\Expression\CallExpression) { return null; } $memberName = $scoped->memberName->getName(); @@ -455,7 +456,7 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex } else { $name = (string)$className . '::' . $scoped->memberName->getText($scoped->getFileContents()); } - if ($scoped->parent instanceof Tolerant\Node\Expression\CallExpression) { + if ($scoped->parent instanceof Node\Expression\CallExpression) { $name .= '()'; } return $name; @@ -465,12 +466,12 @@ private function resolveScopedPropertyAccessExpressionNodeToFqn(Tolerant\Node\Ex * 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 * - * @param Tolerant\Node $node + * @param Node $node * @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) { return null; } @@ -480,18 +481,18 @@ private static function getContainingClassFqn(Tolerant\Node $node) /** * Returns the assignment or parameter node where a variable was defined * - * @param Tolerant\Node\Expression\Variable | Tolerant\Node\Expression\ClosureUse $var The variable access - * @return Tolerant\Node\Expression\Assign | Tolerant\Node\Expression\AssignOp|Node\Param | Tolerant\Node\Expression\ClosureUse|null + * @param Node\Expression\Variable | Node\Expression\ClosureUse $var The variable access + * @return Node\Expression\Assign | Node\Expression\AssignOp|Node\Param | Node\Expression\ClosureUse|null */ public function resolveVariableToNode($var) { $n = $var; // When a use is passed, start outside the closure to not return immediately // Use variable vs variable parsing? - if ($var instanceof Tolerant\Node\UseVariableName) { - $n = $var->getFirstAncestor(Tolerant\Node\Expression\AnonymousFunctionCreationExpression::class)->parent; + if ($var instanceof Node\UseVariableName) { + $n = $var->getFirstAncestor(Node\Expression\AnonymousFunctionCreationExpression::class)->parent; $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(); } else { throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); @@ -509,7 +510,7 @@ public function resolveVariableToNode($var) } } // 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->useVariableNameList !== null) { foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use @@ -523,13 +524,13 @@ public function resolveVariableToNode($var) } // Check each previous sibling node for a variable assignment to that variable while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { - if ($n instanceof Tolerant\Node\Statement\ExpressionStatement) { + if ($n instanceof Node\Statement\ExpressionStatement) { $n = $n->expression; } if ( // TODO - clean this up - ($n instanceof Tolerant\Node\Expression\AssignmentExpression && $n->operator->kind === Tolerant\TokenKind::EqualsToken) - && $n->leftOperand instanceof Tolerant\Node\Expression\Variable && $n->leftOperand->getName() === $name + ($n instanceof Node\Expression\AssignmentExpression && $n->operator->kind === PhpParser\TokenKind::EqualsToken) + && $n->leftOperand instanceof Node\Expression\Variable && $n->leftOperand->getName() === $name ) { return $n; } @@ -543,12 +544,12 @@ public function resolveVariableToNode($var) * Given an expression node, resolves that expression recursively to a type. * If the type could not be resolved, returns Types\Mixed. * - * @param Tolerant\Node\Expression $expr + * @param Node\Expression $expr * @return \phpDocumentor\Reflection\Type|null */ 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 // How do we handle this more generally? return new Types\Mixed; @@ -556,42 +557,42 @@ public function resolveExpressionNodeToType($expr) // PARENTHESIZED EXPRESSION // Retrieve inner expression from parenthesized expression - while ($expr instanceof Tolerant\Node\Expression\ParenthesizedExpression) { + while ($expr instanceof Node\Expression\ParenthesizedExpression) { $expr = $expr->expression; } // VARIABLE // $this -> Type\this // $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') { return new Types\This; } // Find variable definition (parameter or assignment expression) $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); } - if ($defNode instanceof Tolerant\Node\Parameter) { + if ($defNode instanceof Node\Parameter) { return $this->getTypeFromNode($defNode); } } // FUNCTION CALL // 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 Tolerant\Node\Expression\MemberAccessExpression) + $expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression || + $expr->callableExpression instanceof Node\Expression\MemberAccessExpression) ) { // Find the function definition - if ($expr->callableExpression instanceof Tolerant\Node\Expression) { + if ($expr->callableExpression instanceof Node\Expression) { // Cannot get type for dynamic function call 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 .= '()'; $def = $this->index->getDefinition($fqn, true); @@ -603,13 +604,13 @@ public function resolveExpressionNodeToType($expr) // TRUE / FALSE / NULL // Resolve true and false reserved words to Types\Boolean - if ($expr instanceof Tolerant\Node\ReservedWord) { + if ($expr instanceof Node\ReservedWord) { $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; } - if ($token === Tolerant\TokenKind::NullReservedWord) { + if ($token === PhpParser\TokenKind::NullReservedWord) { return new Types\Null_; } } @@ -625,8 +626,8 @@ public function resolveExpressionNodeToType($expr) } // MEMBER ACCESS EXPRESSION - if ($expr instanceof Tolerant\Node\Expression\MemberAccessExpression) { - if ($expr->memberName instanceof Tolerant\Node\Expression) { + if ($expr instanceof Node\Expression\MemberAccessExpression) { + if ($expr->memberName instanceof Node\Expression) { return new Types\Mixed; } $var = $expr->dereferencableExpression; @@ -648,7 +649,7 @@ public function resolveExpressionNodeToType($expr) $classFqn = substr((string)$t->getFqsen(), 1); } $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { + if ($expr->parent instanceof Node\Expression\CallExpression) { $fqn .= '()'; } $def = $this->index->getDefinition($fqn); @@ -659,7 +660,7 @@ public function resolveExpressionNodeToType($expr) } // SCOPED PROPERTY ACCESS EXPRESSION - if ($expr instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression) { + if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) { $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { return new Types\Mixed; @@ -668,7 +669,7 @@ public function resolveExpressionNodeToType($expr) // TODO is there a cleaner way to do this? $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 .= '()'; } @@ -682,26 +683,26 @@ public function resolveExpressionNodeToType($expr) // OBJECT CREATION EXPRESSION // new A() => resolves to the type of the class type designator (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); } // CLONE EXPRESSION // 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); } // ASSIGNMENT EXPRESSION // $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); } // TERNARY EXPRESSION // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition 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) { return new Types\Compound([ @@ -718,7 +719,7 @@ public function resolveExpressionNodeToType($expr) // NULL COALLESCE // $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 return new Types\Compound([ $this->resolveExpressionNodeToType($expr->leftOperand), @@ -735,10 +736,10 @@ public function resolveExpressionNodeToType($expr) if ( ParserHelpers::isBooleanExpression($expr) - || ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::BoolCastToken) - || ($expr instanceof Tolerant\Node\Expression\UnaryOpExpression && $expr->operator->kind === Tolerant\TokenKind::ExclamationToken) - || $expr instanceof Tolerant\Node\Expression\EmptyIntrinsicExpression - || $expr instanceof Tolerant\Node\Expression\IssetIntrinsicExpression + || ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::BoolCastToken) + || ($expr instanceof Node\Expression\UnaryOpExpression && $expr->operator->kind === PhpParser\TokenKind::ExclamationToken) + || $expr instanceof Node\Expression\EmptyIntrinsicExpression + || $expr instanceof Node\Expression\IssetIntrinsicExpression ) { return new Types\Boolean; } @@ -750,10 +751,10 @@ public function resolveExpressionNodeToType($expr) // // TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__) if ( - ($expr instanceof Tolerant\Node\Expression\BinaryExpression && - ($expr->operator->kind === Tolerant\TokenKind::DotToken || $expr->operator->kind === Tolerant\TokenKind::DotEqualsToken)) || - $expr instanceof Tolerant\Node\StringLiteral || - ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::StringCastToken) + ($expr instanceof Node\Expression\BinaryExpression && + ($expr->operator->kind === PhpParser\TokenKind::DotToken || $expr->operator->kind === PhpParser\TokenKind::DotEqualsToken)) || + $expr instanceof Node\StringLiteral || + ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::StringCastToken) ) { return new Types\String_; } @@ -765,18 +766,18 @@ public function resolveExpressionNodeToType($expr) // Resolve to Types\Float // [assignment] /= if ( - $expr instanceof Tolerant\Node\Expression\BinaryExpression && + $expr instanceof Node\Expression\BinaryExpression && ($operator = $expr->operator->kind) - && ($operator === Tolerant\TokenKind::PlusToken || - $operator === Tolerant\TokenKind::AsteriskAsteriskToken || - $operator === Tolerant\TokenKind::AsteriskToken || - $operator === Tolerant\TokenKind::MinusToken || + && ($operator === PhpParser\TokenKind::PlusToken || + $operator === PhpParser\TokenKind::AsteriskAsteriskToken || + $operator === PhpParser\TokenKind::AsteriskToken || + $operator === PhpParser\TokenKind::MinusToken || // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression) - $operator === Tolerant\TokenKind::AsteriskEqualsToken|| - $operator === Tolerant\TokenKind::AsteriskAsteriskEqualsToken || - $operator === Tolerant\TokenKind::MinusEqualsToken || - $operator === Tolerant\TokenKind::PlusEqualsToken + $operator === PhpParser\TokenKind::AsteriskEqualsToken|| + $operator === PhpParser\TokenKind::AsteriskAsteriskEqualsToken || + $operator === PhpParser\TokenKind::MinusEqualsToken || + $operator === PhpParser\TokenKind::PlusEqualsToken ) ) { if ( @@ -787,8 +788,8 @@ public function resolveExpressionNodeToType($expr) } return new Types\Float_; } else if ( - $expr instanceof Tolerant\Node\Expression\BinaryExpression && - $expr->operator->kind === Tolerant\TokenKind::SlashEqualsToken + $expr instanceof Node\Expression\BinaryExpression && + $expr->operator->kind === PhpParser\TokenKind::SlashEqualsToken ) { return new Types\Float_; } @@ -799,13 +800,13 @@ public function resolveExpressionNodeToType($expr) // TODO: Magic constants (__LINE__) if ( // 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 Tolerant\Node\Expression\BinaryExpression && ( + ($expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::IntegerLiteralToken) || + $expr instanceof Node\Expression\BinaryExpression && ( ($operator = $expr->operator->kind) - && ($operator === Tolerant\TokenKind::LessThanEqualsGreaterThanToken || - $operator === Tolerant\TokenKind::AmpersandToken || - $operator === Tolerant\TokenKind::CaretToken || - $operator === Tolerant\TokenKind::BarToken) + && ($operator === PhpParser\TokenKind::LessThanEqualsGreaterThanToken || + $operator === PhpParser\TokenKind::AmpersandToken || + $operator === PhpParser\TokenKind::CaretToken || + $operator === PhpParser\TokenKind::BarToken) ) ) { return new Types\Integer; @@ -816,9 +817,9 @@ public function resolveExpressionNodeToType($expr) // [operator] / // [cast] (double) if ( - $expr instanceof Tolerant\Node\NumericLiteral && $expr->children->kind === Tolerant\TokenKind::FloatingLiteralToken || - ($expr instanceof Tolerant\Node\Expression\CastExpression && $expr->castType->kind === Tolerant\TokenKind::DoubleCastToken) || - ($expr instanceof Tolerant\Node\Expression\BinaryExpression && $expr->operator->kind === Tolerant\TokenKind::SlashToken) + $expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::FloatingLiteralToken || + ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::DoubleCastToken) || + ($expr instanceof Node\Expression\BinaryExpression && $expr->operator->kind === PhpParser\TokenKind::SlashToken) ) { return new Types\Float_; } @@ -827,7 +828,7 @@ public function resolveExpressionNodeToType($expr) // Resolve to Types\Array (Types\Compound of value and key types) // [a, b, c] // [1=>"hello", "hi"=>1, 4=>[]]s - if ($expr instanceof Tolerant\Node\Expression\ArrayCreationExpression) { + if ($expr instanceof Node\Expression\ArrayCreationExpression) { $valueTypes = []; $keyTypes = []; if ($expr->arrayElements !== null) { @@ -858,7 +859,7 @@ public function resolveExpressionNodeToType($expr) // SUBSCRIPT EXPRESSION // $myArray[3] // $myArray{"hello"} - if ($expr instanceof Tolerant\Node\Expression\SubscriptExpression) { + if ($expr instanceof Node\Expression\SubscriptExpression) { $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { return new Types\Mixed; @@ -868,12 +869,12 @@ public function resolveExpressionNodeToType($expr) // SCRIPT INCLUSION EXPRESSION // 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 return new Types\Mixed; } - if ($expr instanceof Tolerant\Node\QualifiedName) { + if ($expr instanceof Node\QualifiedName) { return $this->resolveClassNameToType($expr); } @@ -885,15 +886,15 @@ public function resolveExpressionNodeToType($expr) * 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 * - * @param Tolerant\Node || Tolerant\Token $class + * @param Node || PhpParser\Token $class * @return Type */ public function resolveClassNameToType($class): Type { - if ($class instanceof Tolerant\Node\Expression) { + if ($class instanceof Node\Expression) { 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 return new Types\Object_; } @@ -903,7 +904,7 @@ public function resolveClassNameToType($class): Type return new Types\Static_; } if ($className === 'self' || $className === 'parent') { - $classNode = $class->getFirstAncestor(Tolerant\Node\Statement\ClassDeclaration::class); + $classNode = $class->getFirstAncestor(Node\Statement\ClassDeclaration::class); if ($className === 'parent') { if ($classNode === null || $classNode->classBaseClause === null) { return new Types\Object_; @@ -933,7 +934,7 @@ public function resolveClassNameToType($class): Type * If it is unknown, will be Types\Mixed. * Returns null if the node does not have a type. * - * @param Tolerant\Node $node + * @param Node $node * @return \phpDocumentor\Reflection\Type|null */ public function getTypeFromNode($node) @@ -948,7 +949,7 @@ public function getTypeFromNode($node) // Get the type of the parameter: // 1. Doc block // 2. Parameter type and default - if ($node instanceof Tolerant\Node\Parameter) { + if ($node instanceof Node\Parameter) { // Parameters // Get the doc block for the the function call // /** @@ -968,7 +969,7 @@ public function getTypeFromNode($node) // function foo(MyClass $a) if ($node->typeDeclaration !== null) { // 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 $type = $this->typeResolver->resolve($node->typeDeclaration->getText($node->getFileContents())); } else { @@ -1003,9 +1004,9 @@ public function getTypeFromNode($node) // Use @return tag 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 - if ($node->returnType instanceof Tolerant\Token) { + if ($node->returnType instanceof PhpParser\Token) { // Resolve a string like "bool" to a type object return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); } @@ -1022,7 +1023,7 @@ public function getTypeFromNode($node) ParserHelpers::tryGetPropertyDeclaration($node) ?? ParserHelpers::tryGetConstOrClassConstDeclaration($node) ) !== null || - ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) + ($node = $node->parent) instanceof Node\Expression\AssignmentExpression) { $declarationNode = $declarationNode ?? $node; @@ -1037,14 +1038,14 @@ public function getTypeFromNode($node) } // Resolve the expression - if ($declarationNode instanceof Tolerant\Node\PropertyDeclaration) { + if ($declarationNode instanceof Node\PropertyDeclaration) { // TODO should have default if (isset($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); - } else if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { + } else if ($node instanceof Node\Expression\AssignmentExpression) { return $this->resolveExpressionNodeToType($node->rightOperand); } // TODO: read @property tags of class @@ -1061,7 +1062,7 @@ public function getTypeFromNode($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 * - * @param Tolerant\Node $node + * @param Node $node * @return string|null */ public static function getDefinedFqn($node) @@ -1074,23 +1075,23 @@ public static function getDefinedFqn($node) // interface C { } A\B\C // trait C { } A\B\C if ( - $node instanceof Tolerant\Node\Statement\ClassDeclaration || - $node instanceof Tolerant\Node\Statement\InterfaceDeclaration || - $node instanceof Tolerant\Node\Statement\TraitDeclaration + $node instanceof Node\Statement\ClassDeclaration || + $node instanceof Node\Statement\InterfaceDeclaration || + $node instanceof Node\Statement\TraitDeclaration ) { return (string) $node->getNamespacedName(); } // INPUT OUTPUT: // namespace A\B; A\B - else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition && $node->name instanceof Tolerant\Node\QualifiedName) { - $name = (string) Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + else if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) { + $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); return \count($name) > 0 ? $name : null; } // INPUT OUTPUT: // namespace A\B; // 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 $name = (string)$node->getNamespacedName(); return \count($name) > 0 ? $name . '()' : null; @@ -1101,13 +1102,13 @@ public static function getDefinedFqn($node) // function a () {} A\B\C->a() // 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 = $node->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class + Node\Expression\ObjectCreationExpression::class, + Node\Statement\ClassDeclaration::class, + Node\Statement\InterfaceDeclaration::class, + Node\Statement\TraitDeclaration::class ); if (!isset($class->name)) { // Ignore anonymous classes @@ -1130,10 +1131,10 @@ public static function getDefinedFqn($node) ($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && ($classDeclaration = $node->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class + Node\Expression\ObjectCreationExpression::class, + Node\Statement\ClassDeclaration::class, + Node\Statement\InterfaceDeclaration::class, + Node\Statement\TraitDeclaration::class ) ) !== null && isset($classDeclaration->name)) { @@ -1154,17 +1155,17 @@ public static function getDefinedFqn($node) // const $a, $b = 4 A\B\C::$a(), A\B\C::$b // } 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 return (string)$node->getNamespacedName(); } // Class constant: use ClassName::CONSTANT_NAME as name $classDeclaration = $constDeclaration->getFirstAncestor( - Tolerant\Node\Expression\ObjectCreationExpression::class, - Tolerant\Node\Statement\ClassDeclaration::class, - Tolerant\Node\Statement\InterfaceDeclaration::class, - Tolerant\Node\Statement\TraitDeclaration::class + Node\Expression\ObjectCreationExpression::class, + Node\Statement\ClassDeclaration::class, + Node\Statement\InterfaceDeclaration::class, + Node\Statement\TraitDeclaration::class ); if (!isset($classDeclaration->name)) { diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index a569d9b8..c7d45a69 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -3,7 +3,7 @@ namespace LanguageServer; use phpDocumentor\Reflection\{Type, Types}; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; class FqnUtilities { diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index b7347690..d1916f28 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -3,68 +3,69 @@ namespace LanguageServer; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; class ParserHelpers { - public static function isConstantFetch(Tolerant\Node $node) : bool { + public static function isConstantFetch(Node $node) : bool { $parent = $node->parent; return ( - $node instanceof Tolerant\Node\QualifiedName && + $node instanceof Node\QualifiedName && ( -// $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || - $parent instanceof Tolerant\Node\Expression || - $parent instanceof Tolerant\Node\DelimitedList\ExpressionList || - $parent instanceof Tolerant\Node\ArrayElement || - ($parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) || - $parent instanceof Tolerant\Node\StatementNode || - $parent instanceof Tolerant\Node\CaseStatementNode +// $node->parent instanceof Node\Statement\ExpressionStatement || + $parent instanceof Node\Expression || + $parent instanceof Node\DelimitedList\ExpressionList || + $parent instanceof Node\ArrayElement || + ($parent instanceof Node\Parameter && $node->parent->default === $node) || + $parent instanceof Node\StatementNode || + $parent instanceof Node\CaseStatementNode ) && !( - $parent instanceof Tolerant\Node\Expression\MemberAccessExpression || - $parent instanceof Tolerant\Node\Expression\CallExpression || - $parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || - $parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || + $parent instanceof Node\Expression\MemberAccessExpression || + $parent instanceof Node\Expression\CallExpression || + $parent instanceof Node\Expression\ObjectCreationExpression || + $parent instanceof Node\Expression\ScopedPropertyAccessExpression || self::isFunctionLike($parent) || ( - $parent instanceof Tolerant\Node\Expression\BinaryExpression && - $parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword + $parent instanceof Node\Expression\BinaryExpression && + $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; } - public static function isFunctionLike(Tolerant\Node $node) { + public static function isFunctionLike(Node $node) { return - $node instanceof Tolerant\Node\Statement\FunctionDeclaration || - $node instanceof Tolerant\Node\MethodDeclaration || - $node instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression; + $node instanceof Node\Statement\FunctionDeclaration || + $node instanceof Node\MethodDeclaration || + $node instanceof Node\Expression\AnonymousFunctionCreationExpression; } public static function isBooleanExpression($expression) : bool { - if (!($expression instanceof Tolerant\Node\Expression\BinaryExpression)) { + if (!($expression instanceof Node\Expression\BinaryExpression)) { return false; } switch ($expression->operator->kind) { - case Tolerant\TokenKind::InstanceOfKeyword: - case Tolerant\TokenKind::GreaterThanToken: - case Tolerant\TokenKind::GreaterThanEqualsToken: - case Tolerant\TokenKind::LessThanToken: - case Tolerant\TokenKind::LessThanEqualsToken: - case Tolerant\TokenKind::AndKeyword: - case Tolerant\TokenKind::AmpersandAmpersandToken: - case Tolerant\TokenKind::LessThanEqualsGreaterThanToken: - case Tolerant\TokenKind::OrKeyword: - case Tolerant\TokenKind::BarBarToken: - case Tolerant\TokenKind::XorKeyword: - case Tolerant\TokenKind::ExclamationEqualsEqualsToken: - case Tolerant\TokenKind::ExclamationEqualsToken: - case Tolerant\TokenKind::CaretToken: - case Tolerant\TokenKind::EqualsEqualsEqualsToken: - case Tolerant\TokenKind::EqualsToken: + case PhpParser\TokenKind::InstanceOfKeyword: + case PhpParser\TokenKind::GreaterThanToken: + case PhpParser\TokenKind::GreaterThanEqualsToken: + case PhpParser\TokenKind::LessThanToken: + case PhpParser\TokenKind::LessThanEqualsToken: + case PhpParser\TokenKind::AndKeyword: + case PhpParser\TokenKind::AmpersandAmpersandToken: + case PhpParser\TokenKind::LessThanEqualsGreaterThanToken: + case PhpParser\TokenKind::OrKeyword: + case PhpParser\TokenKind::BarBarToken: + case PhpParser\TokenKind::XorKeyword: + case PhpParser\TokenKind::ExclamationEqualsEqualsToken: + case PhpParser\TokenKind::ExclamationEqualsToken: + case PhpParser\TokenKind::CaretToken: + case PhpParser\TokenKind::EqualsEqualsEqualsToken: + case PhpParser\TokenKind::EqualsToken: return true; } return false; @@ -73,13 +74,13 @@ public static function isBooleanExpression($expression) : bool { /** * Tries to get the parent property declaration given a Node - * @param Tolerant\Node $node - * @return Tolerant\Node\PropertyDeclaration | null $node + * @param Node $node + * @return Node\PropertyDeclaration | null $node */ - public static function tryGetPropertyDeclaration(Tolerant\Node $node) { - if ($node instanceof Tolerant\Node\Expression\Variable && - (($propertyDeclaration = $node->parent->parent) instanceof Tolerant\Node\PropertyDeclaration || - ($propertyDeclaration = $propertyDeclaration->parent) instanceof Tolerant\Node\PropertyDeclaration) + public static function tryGetPropertyDeclaration(Node $node) { + if ($node instanceof Node\Expression\Variable && + (($propertyDeclaration = $node->parent->parent) instanceof Node\PropertyDeclaration || + ($propertyDeclaration = $propertyDeclaration->parent) instanceof Node\PropertyDeclaration) ) { return $propertyDeclaration; } @@ -88,14 +89,14 @@ public static function tryGetPropertyDeclaration(Tolerant\Node $node) { /** * Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node - * @param Tolerant\Node $node - * @return Tolerant\Node\Statement\ConstDeclaration | Tolerant\Node\ClassConstDeclaration | null $node + * @param Node $node + * @return Node\Statement\ConstDeclaration | Node\ClassConstDeclaration | null $node */ - public static function tryGetConstOrClassConstDeclaration(Tolerant\Node $node) { + public static function tryGetConstOrClassConstDeclaration(Node $node) { if ( - $node instanceof Tolerant\Node\ConstElement && ( - ($constDeclaration = $node->parent->parent) instanceof Tolerant\Node\ClassConstDeclaration || - $constDeclaration instanceof Tolerant\Node\Statement\ConstDeclaration ) + $node instanceof Node\ConstElement && ( + ($constDeclaration = $node->parent->parent) instanceof Node\ClassConstDeclaration || + $constDeclaration instanceof Node\Statement\ConstDeclaration ) ) { return $constDeclaration; } @@ -105,15 +106,15 @@ public static function tryGetConstOrClassConstDeclaration(Tolerant\Node $node) { /** * Returns true if the node is a usage of `define`. * e.g. define('TEST_DEFINE_CONSTANT', false); - * @param Tolerant\Node $node + * @param Node $node * @return bool */ - public static function isConstDefineExpression(Tolerant\Node $node): bool { - return $node instanceof Tolerant\Node\Expression\CallExpression - && $node->callableExpression instanceof Tolerant\Node\QualifiedName + public static function isConstDefineExpression(Node $node): bool { + return $node instanceof Node\Expression\CallExpression + && $node->callableExpression instanceof Node\QualifiedName && strtolower($node->callableExpression->getText()) === 'define' && 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]); } } \ No newline at end of file diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 77c9aac7..f7b813e1 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -7,7 +7,8 @@ use LanguageServer\Protocol\{ Diagnostic, Position, Range }; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; use phpDocumentor\Reflection\DocBlockFactory; class PhpDocument @@ -15,7 +16,7 @@ class PhpDocument /** * The PHPParser instance * - * @var Tolerant\Parser + * @var PhpParser\Parser */ private $parser; @@ -55,7 +56,7 @@ class PhpDocument /** * The AST of the document * - * @var Tolerant\Node + * @var Node */ private $stmts; @@ -69,14 +70,14 @@ class PhpDocument /** * Map from fully qualified name (FQN) to Node * - * @var Tolerant\Node + * @var Node */ private $definitionNodes; /** * Map from fully qualified name (FQN) to array of nodes that reference the symbol * - * @var Tolerant\Node[][] + * @var Node[][] */ private $referenceNodes; @@ -91,7 +92,7 @@ class PhpDocument * @param string $uri The URI of the document * @param string $content The content of the document * @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 DefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace */ @@ -115,7 +116,7 @@ public function __construct( * Get all references of a fully qualified name * * @param string $fqn The fully qualified name of the symbol - * @return Tolerant\Node[] + * @return Node[] */ public function getReferenceNodesByFqn(string $fqn) { @@ -220,7 +221,7 @@ public function getUri(): string /** * Returns the AST of the document * - * @return Tolerant\Node | null + * @return Node | null */ public function getStmts() { @@ -231,7 +232,7 @@ public function getStmts() * Returns the node at a specified position * * @param Position $position - * @return Tolerant\Node|null + * @return Node|null */ public function getNodeAtPosition(Position $position) { @@ -267,7 +268,7 @@ public function getRange(Range $range) * Returns the definition node for a fully qualified name * * @param string $fqn - * @return Tolerant\Node|null + * @return Node|null */ public function getDefinitionNodeByFqn(string $fqn) { @@ -277,7 +278,7 @@ public function getDefinitionNodeByFqn(string $fqn) /** * Returns a map from fully qualified name (FQN) to Nodes defined in this document * - * @return Tolerant\Node[] + * @return Node[] */ public function getDefinitionNodes() { diff --git a/src/PhpDocumentLoader.php b/src/PhpDocumentLoader.php index 0c5bbcac..57a7e9c9 100644 --- a/src/PhpDocumentLoader.php +++ b/src/PhpDocumentLoader.php @@ -8,7 +8,7 @@ use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Event\Promise; use function Sabre\Event\coroutine; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; /** * Takes care of loading documents and managing "open" documents @@ -38,7 +38,7 @@ class PhpDocumentLoader private $parser; /** - * @var Tolerant\Parser + * @var PhpParser\Parser */ private $tolerantParser; @@ -66,7 +66,7 @@ public function __construct( $this->contentRetriever = $contentRetriever; $this->projectIndex = $projectIndex; $this->definitionResolver = $definitionResolver; - $this->parser = new Tolerant\Parser(); + $this->parser = new PhpParser\Parser(); $this->docBlockFactory = DocBlockFactory::createInstance(); } diff --git a/src/Protocol/Location.php b/src/Protocol/Location.php index 0de3c384..50fedfa9 100644 --- a/src/Protocol/Location.php +++ b/src/Protocol/Location.php @@ -2,7 +2,8 @@ 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. @@ -22,12 +23,12 @@ class Location /** * Returns the location of the node * - * @param Tolerant\Node $node + * @param Node $node * @return self */ 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( new Position($range->start->line, $range->start->character), new Position($range->end->line, $range->end->character) diff --git a/src/Protocol/Range.php b/src/Protocol/Range.php index de2011b9..482004a1 100644 --- a/src/Protocol/Range.php +++ b/src/Protocol/Range.php @@ -2,7 +2,8 @@ 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. @@ -26,12 +27,12 @@ class Range /** * Returns the range the node spans * - * @param Tolerant\Node $node + * @param Node $node * @return self */ 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( new Position($range->start->line, $range->start->character), diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index ec8730c1..895830ac 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -2,7 +2,8 @@ namespace LanguageServer\Protocol; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; use Exception; /** @@ -42,16 +43,16 @@ class 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 * @return SymbolInformation|null */ public static function fromNode($node, string $fqn = null) { $symbol = new self; - if ($node instanceof Tolerant\Node\Statement\ClassDeclaration) { + if ($node instanceof Node\Statement\ClassDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if ($node instanceof Tolerant\Node\Statement\TraitDeclaration) { + } else if ($node instanceof Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; } else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { @@ -59,49 +60,49 @@ public static function fromNode($node, string $fqn = null) // define('TEST_DEFINE_CONSTANT', false); $symbol->kind = SymbolKind::CONSTANT; $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; - } else if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { + } else if ($node instanceof Node\Statement\NamespaceDefinition) { $symbol->kind = SymbolKind::NAMESPACE; - } else if ($node instanceof Tolerant\Node\Statement\FunctionDeclaration) { + } else if ($node instanceof Node\Statement\FunctionDeclaration) { $symbol->kind = SymbolKind::FUNCTION; - } else if ($node instanceof Tolerant\Node\MethodDeclaration) { + } else if ($node instanceof Node\MethodDeclaration) { $nameText = $node->getName(); if ($nameText === '__construct' || $nameText === '__destruct') { $symbol->kind = SymbolKind::CONSTRUCTOR; } else { $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; - } else if ($node instanceof Tolerant\Node\ConstElement) { + } else if ($node instanceof Node\ConstElement) { $symbol->kind = SymbolKind::CONSTANT; } else if ( ( - ($node instanceof Tolerant\Node\Expression\AssignmentExpression) - && $node->leftOperand instanceof Tolerant\Node\Expression\Variable + ($node instanceof Node\Expression\AssignmentExpression) + && $node->leftOperand instanceof Node\Expression\Variable ) - || $node instanceof Tolerant\Node\UseVariableName - || $node instanceof Tolerant\Node\Parameter + || $node instanceof Node\UseVariableName + || $node instanceof Node\Parameter ) { $symbol->kind = SymbolKind::VARIABLE; } else { return null; } - if ($node instanceof Tolerant\Node\Expression\AssignmentExpression) { - if ($node->leftOperand instanceof Tolerant\Node\Expression\Variable) { + if ($node instanceof Node\Expression\AssignmentExpression) { + if ($node->leftOperand instanceof Node\Expression\Variable) { $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()), "$"); } - } else if ($node instanceof Tolerant\Node\UseVariableName) { + } else if ($node instanceof Node\UseVariableName) { $symbol->name = $node->getName(); } else if (isset($node->name)) { - if ($node->name instanceof Tolerant\Node\QualifiedName) { - $symbol->name = (string)Tolerant\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); + if ($node->name instanceof Node\QualifiedName) { + $symbol->name = (string)PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); } else { $symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$"); } diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 6dadf2fc..d00ebfa2 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -10,7 +10,8 @@ use LanguageServer\Protocol\{ 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\Uri; use function LanguageServer\{ @@ -183,24 +184,24 @@ public function references( // by traversing the AST if ( - ($node instanceof Tolerant\Node\Expression\Variable && !($node->getParent()->getParent() instanceof Tolerant\Node\PropertyDeclaration)) - || $node instanceof Tolerant\Node\Parameter - || $node instanceof Tolerant\Node\UseVariableName + ($node instanceof Node\Expression\Variable && !($node->getParent()->getParent() instanceof Node\PropertyDeclaration)) + || $node instanceof Node\Parameter + || $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; } // Find function/method/closure scope $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) { - $n = $node->getFirstAncestor(Tolerant\Node\Statement\ExpressionStatement::class)->getParent(); + $n = $node->getFirstAncestor(Node\Statement\ExpressionStatement::class)->getParent(); } foreach ($n->getDescendantNodes() as $descendantNode) { - if ($descendantNode instanceof Tolerant\Node\Expression\Variable && + if ($descendantNode instanceof Node\Expression\Variable && $descendantNode->getName() === $node->getName() ) { $locations[] = Location::fromNode($descendantNode); diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index e4cd7885..6f7cdc05 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -7,12 +7,13 @@ use LanguageServer\Index\Index; use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Uri; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; class TreeAnalyzer { private $parser; - /** @var Tolerant\Node */ + /** @var Node */ private $stmts; private $diagnostics; @@ -21,7 +22,7 @@ class TreeAnalyzer { /** * TreeAnalyzer constructor. - * @param Tolerant\Parser $parser + * @param PhpParser\Parser $parser * @param $content * @param $docBlockFactory * @param DefinitionResolver $definitionResolver @@ -40,7 +41,7 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso $this->collectDefinitionsAndReferences($this->stmts); } - public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { + public function collectDefinitionsAndReferences(Node $stmts) { foreach ($stmts::CHILD_NAMES as $name) { $node = $stmts->$name; @@ -50,19 +51,19 @@ public function collectDefinitionsAndReferences(Tolerant\Node $stmts) { if (\is_array($node)) { foreach ($node as $child) { - if ($child instanceof Tolerant\Node) { + if ($child instanceof Node) { $this->update($child); } } continue; } - if ($node instanceof Tolerant\Node) { + if ($node instanceof Node) { $this->update($node); } - if (($_error = Tolerant\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = Tolerant\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); + if (($_error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = PhpParser\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); $this->diagnostics[] = new Diagnostic( $_error->message, @@ -88,14 +89,14 @@ public function update($node) { $parent = $node->parent; if (!( ( - // $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - ($node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression) + // $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression || + ($node instanceof Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Node\Expression\MemberAccessExpression) && !( - $node->parent instanceof Tolerant\Node\Expression\CallExpression || - $node->memberName instanceof Tolerant\Token + $node->parent instanceof Node\Expression\CallExpression || + $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); @@ -103,9 +104,9 @@ public function update($node) { $this->addReference($fqn, $node); if ( - $node instanceof Tolerant\Node\QualifiedName - && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause) - && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + $node instanceof Node\QualifiedName + && ($node->isQualifiedName() || $node->parent instanceof Node\NamespaceUseClause) + && !($parent instanceof Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() ) ) { // Add references for each referenced namespace @@ -120,10 +121,10 @@ public function update($node) { // to the global version because PHP falls back to global at runtime // http://php.net/manual/en/language.namespaces.fallback.php if (ParserHelpers::isConstantFetch($node) || - ($parent instanceof Tolerant\Node\Expression\CallExpression + ($parent instanceof Node\Expression\CallExpression && !( - $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Tolerant\Node\Expression\MemberAccessExpression + $node instanceof Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Node\Expression\MemberAccessExpression ))) { $parts = explode('\\', $fqn); if (count($parts) > 1) { @@ -141,7 +142,7 @@ public function getDiagnostics() { return $this->diagnostics ?? []; } - private function addReference(string $fqn, Tolerant\Node $node) + private function addReference(string $fqn, Node $node) { if (!isset($this->referenceNodes[$fqn])) { $this->referenceNodes[$fqn] = []; diff --git a/tests/DefinitionResolverTest.php b/tests/DefinitionResolverTest.php index dc287cb4..e7d8b784 100644 --- a/tests/DefinitionResolverTest.php +++ b/tests/DefinitionResolverTest.php @@ -6,13 +6,13 @@ use PHPUnit\Framework\TestCase; use LanguageServer\Index\Index; use LanguageServer\DefinitionResolver; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; class DefinitionResolverTest extends TestCase { public function testCreateDefinitionFromNode() { - $parser = new Tolerant\Parser; + $parser = new PhpParser\Parser; $doc = new MockPhpDocument; $stmts = $parser->parseSourceFile("getUri()); @@ -25,7 +25,7 @@ public function testCreateDefinitionFromNode() public function testGetTypeFromNode() { - $parser = new Tolerant\Parser; + $parser = new PhpParser\Parser; $doc = new MockPhpDocument; $stmts = $parser->parseSourceFile("getUri()); @@ -39,7 +39,7 @@ public function testGetTypeFromNode() public function testGetDefinedFqnForIncompleteDefine() { // define('XXX') (only one argument) must not introduce a new symbol - $parser = new Tolerant\Parser; + $parser = new PhpParser\Parser; $doc = new MockPhpDocument; $stmts = $parser->parseSourceFile("getUri()); @@ -52,7 +52,7 @@ public function testGetDefinedFqnForIncompleteDefine() public function testGetDefinedFqnForDefine() { - $parser = new Tolerant\Parser; + $parser = new PhpParser\Parser; $doc = new MockPhpDocument; $stmts = $parser->parseSourceFile("getUri()); diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index fa47185e..604f30d1 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -10,7 +10,8 @@ }; use LanguageServer\Index\{Index}; use function LanguageServer\pathToUri; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; class DefinitionCollectorTest extends TestCase { @@ -37,21 +38,21 @@ public function testCollectsSymbols() 'TestNamespace\\Example->__destruct()' ], array_keys($defNodes)); - $this->assertInstanceOf(Tolerant\Node\ConstElement::class, $defNodes['TestNamespace\\TEST_CONST']); - $this->assertInstanceOf(Tolerant\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\\TEST_CONST']); + $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\TestClass']); + $this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']); // TODO - should we parse properties more strictly? - $this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']); - $this->assertInstanceOf(Tolerant\Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass->testProperty']); - $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']); - $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass->testMethod()']); - $this->assertInstanceOf(Tolerant\Node\Statement\TraitDeclaration::class, $defNodes['TestNamespace\\TestTrait']); - $this->assertInstanceOf(Tolerant\Node\Statement\InterfaceDeclaration::class, $defNodes['TestNamespace\\TestInterface']); - $this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\test_function()']); - $this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\ChildClass']); - $this->assertInstanceOf(Tolerant\Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\Example']); - $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__construct()']); - $this->assertInstanceOf(Tolerant\Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__destruct()']); + $this->assertInstanceOf(Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass::$staticTestProperty']); + $this->assertInstanceOf(Node\Expression\Variable::class, $defNodes['TestNamespace\\TestClass->testProperty']); + $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass::staticTestMethod()']); + $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\TestClass->testMethod()']); + $this->assertInstanceOf(Node\Statement\TraitDeclaration::class, $defNodes['TestNamespace\\TestTrait']); + $this->assertInstanceOf(Node\Statement\InterfaceDeclaration::class, $defNodes['TestNamespace\\TestInterface']); + $this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\test_function()']); + $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\ChildClass']); + $this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\Example']); + $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__construct()']); + $this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__destruct()']); } public function testDoesNotCollectReferences() @@ -60,8 +61,8 @@ public function testDoesNotCollectReferences() $defNodes = $this->collectDefinitions($path); $this->assertEquals(['TestNamespace', 'TestNamespace\\whatever()'], array_keys($defNodes)); - $this->assertInstanceOf(Tolerant\Node\Statement\NamespaceDefinition::class, $defNodes['TestNamespace']); - $this->assertInstanceOf(Tolerant\Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\whatever()']); + $this->assertInstanceOf(Node\Statement\NamespaceDefinition::class, $defNodes['TestNamespace']); + $this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\\whatever()']); } /** @@ -70,7 +71,7 @@ public function testDoesNotCollectReferences() private function collectDefinitions($path): array { $uri = pathToUri($path); - $parser = new Tolerant\Parser(); + $parser = new PhpParser\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 926cb9d2..167aea18 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -12,7 +12,8 @@ use LanguageServer\Protocol\{ Position }; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; +use Microsoft\PhpParser\Node; use phpDocumentor\Reflection\DocBlockFactory; use PHPUnit\Framework\TestCase; use function LanguageServer\isVendored; @@ -21,7 +22,7 @@ class PhpDocumentTest extends TestCase { public function createDocument(string $uri, string $content) { - $parser = new Tolerant\Parser(); + $parser = new PhpParser\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $index = new Index; $definitionResolver = new DefinitionResolver($index); @@ -44,7 +45,7 @@ public function testGetNodeAtPosition() } private function assertQualifiedName($node) { - $this->assertInstanceOf(Tolerant\Node\QualifiedName::class, $node); + $this->assertInstanceOf(Node\QualifiedName::class, $node); } public function testIsVendored() diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 06e97edd..3703083c 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -19,7 +19,7 @@ use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use Sabre\Event\Loop; -use Microsoft\PhpParser as Tolerant; +use Microsoft\PhpParser; $frameworksDir = realpath(__DIR__ . '/../../validation/frameworks'); @@ -94,7 +94,7 @@ private function getActualTestValues($filename, $fileContents): array { global $frameworksDir; $index = new Index(); - $parser = new Tolerant\Parser(); + $parser = new PhpParser\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); $definitionResolver = new DefinitionResolver($index); From 9c35aa6bd03bcd925e3246b52ced932c9797c277 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 24 May 2017 21:33:12 -0700 Subject: [PATCH 107/149] Remove stats.md - Perf result is saved in the PR, don't need a file here forever --- stats.md | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 stats.md diff --git a/stats.md b/stats.md deleted file mode 100644 index cbf8bc53..00000000 --- a/stats.md +++ /dev/null @@ -1,49 +0,0 @@ -## Performance Stats - -#### drupal (-27%) -``` -old parser: 42.2 -new parser: 30.8 -``` - -#### wordpress (-33%) -``` -old parser: 3.6 -new parser: 2.4 -``` - -#### php-language-server (-17%) -``` -old parser: 13.3 -new parser: 11.0 -``` - -#### tolerant-php-parser (+59%) -``` -old parser: 3.7 -new parser: 5.9 -``` - -#### math-php (-35%) -``` -old parser: 1.7 -new parser: 1.1 -``` - -#### symfony (-23%) -``` -old parser: 18.2 -new parser: 14.1 -``` - -#### CodeIgniter (-23%) -``` -old parser: 1.8 -new parser: 1.1 -``` - -#### cakephp (-24%) -``` -old parser: 5.1 -new parser: 3.9 -``` \ No newline at end of file From 22481480e36e1866755d1fb2e19045eea2e71a53 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 24 May 2017 21:37:00 -0700 Subject: [PATCH 108/149] Remove nullDocs logging - Tolerant parser doesn't produce null SourceFileNodes --- src/Indexer.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/Indexer.php b/src/Indexer.php index 28b7d1ed..9f8749da 100644 --- a/src/Indexer.php +++ b/src/Indexer.php @@ -193,19 +193,11 @@ public function index(): Promise $mem = (int)(memory_get_usage(true) / (1024 * 1024)); $this->client->window->logMessage( MessageType::INFO, - "All $count PHP files parsed in $duration seconds. $mem MiB allocated. " . \count($this->nullDocs) . " null docs" + "All $count PHP files parsed in $duration seconds. $mem MiB allocated." ); - foreach ($this->nullDocs as $nullDoc) { - $this->client->window->logMessage( - MessageType::INFO, - $nullDoc - ); - } }); } - private $nullDocs = []; - /** * @param array $files * @return Promise @@ -224,9 +216,6 @@ private function indexFiles(array $files): Promise $this->client->window->logMessage(MessageType::LOG, "Parsing $uri"); try { $document = yield $this->documentLoader->load($uri); - if ($document->getStmts() === null) { - $this->nullDocs[] = $document->getUri(); - } if (!isVendored($document, $this->composerJson)) { $this->client->textDocument->publishDiagnostics($uri, $document->getDiagnostics()); } From 05aa935908f3fb8030cc1b189c200924b3966bc7 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 24 May 2017 21:43:16 -0700 Subject: [PATCH 109/149] Bump phpunit memory limit --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6cd87876..38df71a1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,6 +12,6 @@ - + From 2568a42e1251846bd50146161502d6be940e9c73 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 25 May 2017 11:39:42 -0700 Subject: [PATCH 110/149] Fix autofixable formatting errors --- src/CompletionProvider.php | 37 +++--- src/DefinitionResolver.php | 115 +++++++++---------- src/FqnUtilities.php | 2 +- src/ParserHelpers.php | 26 +++-- src/ParserKind.php | 3 +- src/Protocol/SymbolInformation.php | 7 +- src/TreeAnalyzer.php | 28 +++-- src/utils.php | 3 +- tests/PhpDocumentTest.php | 3 +- tests/Server/TextDocument/CompletionTest.php | 3 +- tests/Utils/UtilsTest.php | 3 +- tests/Validation/ValidationTest.php | 14 ++- 12 files changed, 129 insertions(+), 115 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index fef59c22..f7181a6f 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -150,8 +150,9 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi stripStringOverlap($doc->getRange(new Range(new Position(0, 0), $pos)), 'items[] = $item; - } - // VARIABLES + } /* + + VARIABLES */ elseif ( $node instanceof Node\Expression\Variable && !( @@ -172,11 +173,11 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi ); $list->items[] = $item; } - } + } /* - // MEMBER ACCESS EXPRESSIONS - // $a->c# - // $a-># + MEMBER ACCESS EXPRESSIONS + $a->c# + $a-># */ elseif ($node instanceof Node\Expression\MemberAccessExpression) { $prefixes = FqnUtilities::getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) @@ -196,14 +197,14 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } - } - - // SCOPED PROPERTY ACCESS EXPRESSIONS - // A\B\C::$a# - // A\B\C::# - // A\B\C::$# - // A\B\C::foo# - // TODO: $a::# + } /* + + SCOPED PROPERTY ACCESS EXPRESSIONS + A\B\C::$a# + A\B\C::# + A\B\C::$# + A\B\C::foo# + TODO: $a::# */ elseif ( ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression || ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression @@ -230,7 +231,6 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } elseif (ParserHelpers::isConstantFetch($node) || ($creation = $node->parent) instanceof Node\Expression\ObjectCreationExpression || (($creation = $node) instanceof Node\Expression\ObjectCreationExpression)) { - $class = isset($creation) ? $creation->classTypeDesignator : $node; $prefix = $class instanceof Node\QualifiedName @@ -240,7 +240,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $namespaceDefinition = $node->getNamespaceDefinition(); list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); - foreach ($namespaceImportTable as $alias=>$name) { + foreach ($namespaceImportTable as $alias => $name) { $namespaceImportTable[$alias] = (string)$name; } @@ -267,8 +267,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi if (!$isNotFullyQualified && ($fqnStartsWithPrefix || strStartsWith($fqn, $namespacePrefix . "\\" . $prefix))) { // $fqn = $fqn; - } - elseif (!$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { + } elseif (!$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { if (empty($prefix)) { $fqn = '\\' . $fqn; } elseif (strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)) { @@ -406,7 +405,7 @@ private function findVariableDefinitionsInNode(Node $node, string $namePrefix = && $node->leftOperand instanceof Node\Expression\Variable && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); }; - $isNotFunctionLike = function($node) { + $isNotFunctionLike = function ($node) { return !( ParserHelpers::isFunctionLike($node) || $node instanceof Node\Statement\ClassDeclaration || diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index abce69e9..7df4aee0 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -139,7 +139,7 @@ private function getDocBlock(Node $node) $docCommentText = $node->getDocCommentText(); if ($docCommentText !== null) { list($namespaceImportTable,,) = $node->getImportTablesForCurrentScope(); - foreach ($namespaceImportTable as $alias=>$name) { + foreach ($namespaceImportTable as $alias => $name) { $namespaceImportTable[$alias] = (string)$name; } $namespaceDefinition = $node->getNamespaceDefinition(); @@ -197,8 +197,7 @@ public function createDefinitionFromNode($node, string $fqn = null): Definition if ($node instanceof Node\Statement\ClassDeclaration && // TODO - this should be bette rrpreented in the parser API - $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) - { + $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { $def->extends = [(string)$node->classBaseClause->baseClass->getResolvedName()]; // TODO - why is this represented as an array? // TODO interface implementations. @@ -237,8 +236,7 @@ public function resolveReferenceNodeToDefinition($node) // Ignore variable nodes that are part of ScopedPropertyAccessExpression, // as the scoped property access expression node is handled separately. if ($node instanceof Node\Expression\Variable && - !($parent instanceof Node\Expression\ScopedPropertyAccessExpression)) - { + !($parent instanceof Node\Expression\ScopedPropertyAccessExpression)) { // Resolve $this to the containing class definition. if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) { return $this->index->getDefinition($fqn, false); @@ -272,19 +270,16 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) { + public function resolveReferenceNodeToFqn($node) + { // TODO all name tokens should be a part of a node if ($node instanceof Node\QualifiedName) { return $this->resolveQualifiedNameNodeToFqn($node); - } - - else if ($node instanceof Node\Expression\MemberAccessExpression) { + } else if ($node instanceof Node\Expression\MemberAccessExpression) { return $this->resolveMemberAccessExpressionNodeToFqn($node); - } - else if (ParserHelpers::isConstantFetch($node)) { + } else if (ParserHelpers::isConstantFetch($node)) { return (string)($node->getNamespacedName()); - } - else if ( + } else if ( // A\B::C - constant access expression $node instanceof Node\Expression\ScopedPropertyAccessExpression && !($node->memberName instanceof Node\Expression\Variable) @@ -300,7 +295,8 @@ public function resolveReferenceNodeToFqn($node) { return null; } - private function resolveQualifiedNameNodeToFqn(Node\QualifiedName $node) { + private function resolveQualifiedNameNodeToFqn(Node\QualifiedName $node) + { $parent = $node->parent; if ($parent instanceof Node\TraitSelectOrAliasClause) { @@ -346,7 +342,8 @@ private function resolveQualifiedNameNodeToFqn(Node\QualifiedName $node) { return $name; } - private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAccessExpression $access) { + private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAccessExpression $access) + { if ($access->memberName instanceof Node\Expression) { // Cannot get definition if right-hand side is expression return null; @@ -393,7 +390,6 @@ private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAc while ($implementorFqn = array_shift($implementorFqns)) { // If the member FQN exists, return it if ($this->index->getDefinition($implementorFqn . $memberSuffix)) { - return $implementorFqn . $memberSuffix; } // Get Definition of implementor class @@ -413,7 +409,8 @@ private function resolveMemberAccessExpressionNodeToFqn(Node\Expression\MemberAc return $classFqn . $memberSuffix; } - private function resolveScopedPropertyAccessExpressionNodeToFqn(Node\Expression\ScopedPropertyAccessExpression $scoped) { + private function resolveScopedPropertyAccessExpressionNodeToFqn(Node\Expression\ScopedPropertyAccessExpression $scoped) + { if ($scoped->scopeResolutionQualifier instanceof Node\Expression\Variable) { $varType = $this->getTypeFromNode($scoped->scopeResolutionQualifier); if ($varType === null) { @@ -502,7 +499,6 @@ public function resolveVariableToNode($var) // If a function is met, check the parameters and use statements if (ParserHelpers::isFunctionLike($n)) { if ($n->parameters !== null) { - foreach ($n->parameters->getElements() as $param) { if ($param->getName() === $name) { return $param; @@ -513,8 +509,7 @@ public function resolveVariableToNode($var) if ($n instanceof Node\Expression\AnonymousFunctionCreationExpression && $n->anonymousFunctionUseClause !== null && $n->anonymousFunctionUseClause->useVariableNameList !== null) { - foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use - ) { + foreach ($n->anonymousFunctionUseClause->useVariableNameList->getElements() as $use) { if ($use->getName() === $name) { return $use; } @@ -585,7 +580,6 @@ public function resolveExpressionNodeToType($expr) $expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Node\Expression\MemberAccessExpression) ) { - // Find the function definition if ($expr->callableExpression instanceof Node\Expression) { // Cannot get type for dynamic function call @@ -627,36 +621,36 @@ public function resolveExpressionNodeToType($expr) // MEMBER ACCESS EXPRESSION if ($expr instanceof Node\Expression\MemberAccessExpression) { - if ($expr->memberName instanceof Node\Expression) { - return new Types\Mixed; - } - $var = $expr->dereferencableExpression; + if ($expr->memberName instanceof Node\Expression) { + return new Types\Mixed; + } + $var = $expr->dereferencableExpression; // Resolve object - $objType = $this->resolveExpressionNodeToType($var); - if (!($objType instanceof Types\Compound)) { - $objType = new Types\Compound([$objType]); - } - for ($i = 0; $t = $objType->get($i); $i++) { - if ($t instanceof Types\This) { - $classFqn = self::getContainingClassFqn($expr); - if ($classFqn === null) { - return new Types\Mixed; - } - } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { - return new Types\Mixed; - } else { - $classFqn = substr((string)$t->getFqsen(), 1); - } - $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Node\Expression\CallExpression) { - $fqn .= '()'; - } - $def = $this->index->getDefinition($fqn); - if ($def !== null) { - return $def->type; - } - } + $objType = $this->resolveExpressionNodeToType($var); + if (!($objType instanceof Types\Compound)) { + $objType = new Types\Compound([$objType]); + } + for ($i = 0; $t = $objType->get($i); $i++) { + if ($t instanceof Types\This) { + $classFqn = self::getContainingClassFqn($expr); + if ($classFqn === null) { + return new Types\Mixed; + } + } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { + return new Types\Mixed; + } else { + $classFqn = substr((string)$t->getFqsen(), 1); + } + $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); + if ($expr->parent instanceof Node\Expression\CallExpression) { + $fqn .= '()'; + } + $def = $this->index->getDefinition($fqn); + if ($def !== null) { + return $def->type; + } + } } // SCOPED PROPERTY ACCESS EXPRESSION @@ -1023,8 +1017,7 @@ public function getTypeFromNode($node) ParserHelpers::tryGetPropertyDeclaration($node) ?? ParserHelpers::tryGetConstOrClassConstDeclaration($node) ) !== null || - ($node = $node->parent) instanceof Node\Expression\AssignmentExpression) - { + ($node = $node->parent) instanceof Node\Expression\AssignmentExpression) { $declarationNode = $declarationNode ?? $node; // Property, constant or variable @@ -1084,25 +1077,27 @@ public static function getDefinedFqn($node) // INPUT OUTPUT: // namespace A\B; A\B - else if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) { + if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) { $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); return \count($name) > 0 ? $name : null; } + // INPUT OUTPUT: // namespace A\B; // function a(); A\B\a(); - else if ($node instanceof Node\Statement\FunctionDeclaration) { + if ($node instanceof Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name $name = (string)$node->getNamespacedName(); return \count($name) > 0 ? $name . '()' : null; } + // INPUT OUTPUT // namespace A\B; // class C { // function a () {} A\B\C->a() // static function b() {} A\B\C::b() // } - else if ($node instanceof Node\MethodDeclaration) { + if ($node instanceof Node\MethodDeclaration) { // Class method: use ClassName->methodName() as name $class = $node->getFirstAncestor( Node\Expression\ObjectCreationExpression::class, @@ -1127,7 +1122,7 @@ public static function getDefinedFqn($node) // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name // } - else if ( + if ( ($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && ($classDeclaration = $node->getFirstAncestor( @@ -1136,8 +1131,7 @@ public static function getDefinedFqn($node) Node\Statement\InterfaceDeclaration::class, Node\Statement\TraitDeclaration::class ) - ) !== null && isset($classDeclaration->name)) - { + ) !== null && isset($classDeclaration->name)) { $name = $node->getName(); if ($propertyDeclaration->isStatic()) { // Static Property: use ClassName::$propertyName as name @@ -1154,7 +1148,7 @@ public static function getDefinedFqn($node) // class C { // const $a, $b = 4 A\B\C::$a(), A\B\C::$b // } - else if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { + if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { if ($constDeclaration instanceof Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name return (string)$node->getNamespacedName(); @@ -1174,7 +1168,7 @@ public static function getDefinedFqn($node) return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); } - else if (ParserHelpers::isConstDefineExpression($node)) { + if (ParserHelpers::isConstDefineExpression($node)) { return $node->argumentExpressionList->children[0]->expression->getStringContentsText(); } @@ -1186,7 +1180,8 @@ public static function getDefinedFqn($node) * @param $variableName * @return DocBlock\Tags\Param | null */ - private function tryGetDocBlockTagForParameter($docBlock, $variableName) { + private function tryGetDocBlockTagForParameter($docBlock, $variableName) + { if ($docBlock === null) { return null; } diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index c7d45a69..f0ff53cc 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -31,4 +31,4 @@ public static function getFqnsFromType($type): array } return $fqns; } -} \ No newline at end of file +} diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index d1916f28..81195a66 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -6,8 +6,10 @@ use Microsoft\PhpParser; use Microsoft\PhpParser\Node; -class ParserHelpers { - public static function isConstantFetch(Node $node) : bool { +class ParserHelpers +{ + public static function isConstantFetch(Node $node) : bool + { $parent = $node->parent; return ( @@ -34,18 +36,21 @@ public static function isConstantFetch(Node $node) : bool { )); } - public static function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) { + public static function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) + { return $node->parent->parent; } - public static function isFunctionLike(Node $node) { + public static function isFunctionLike(Node $node) + { return $node instanceof Node\Statement\FunctionDeclaration || $node instanceof Node\MethodDeclaration || $node instanceof Node\Expression\AnonymousFunctionCreationExpression; } - public static function isBooleanExpression($expression) : bool { + public static function isBooleanExpression($expression) : bool + { if (!($expression instanceof Node\Expression\BinaryExpression)) { return false; } @@ -77,7 +82,8 @@ public static function isBooleanExpression($expression) : bool { * @param Node $node * @return Node\PropertyDeclaration | null $node */ - public static function tryGetPropertyDeclaration(Node $node) { + public static function tryGetPropertyDeclaration(Node $node) + { if ($node instanceof Node\Expression\Variable && (($propertyDeclaration = $node->parent->parent) instanceof Node\PropertyDeclaration || ($propertyDeclaration = $propertyDeclaration->parent) instanceof Node\PropertyDeclaration) @@ -92,7 +98,8 @@ public static function tryGetPropertyDeclaration(Node $node) { * @param Node $node * @return Node\Statement\ConstDeclaration | Node\ClassConstDeclaration | null $node */ - public static function tryGetConstOrClassConstDeclaration(Node $node) { + public static function tryGetConstOrClassConstDeclaration(Node $node) + { if ( $node instanceof Node\ConstElement && ( ($constDeclaration = $node->parent->parent) instanceof Node\ClassConstDeclaration || @@ -109,7 +116,8 @@ public static function tryGetConstOrClassConstDeclaration(Node $node) { * @param Node $node * @return bool */ - public static function isConstDefineExpression(Node $node): bool { + public static function isConstDefineExpression(Node $node): bool + { return $node instanceof Node\Expression\CallExpression && $node->callableExpression instanceof Node\QualifiedName && strtolower($node->callableExpression->getText()) === 'define' @@ -117,4 +125,4 @@ public static function isConstDefineExpression(Node $node): bool { && $node->argumentExpressionList->children[0]->expression instanceof Node\StringLiteral && isset($node->argumentExpressionList->children[2]); } -} \ No newline at end of file +} diff --git a/src/ParserKind.php b/src/ParserKind.php index a7944a4e..39d75590 100644 --- a/src/ParserKind.php +++ b/src/ParserKind.php @@ -2,11 +2,10 @@ namespace LanguageServer; - class ParserKind { const PHP_PARSER = 1; const TOLERANT_PHP_PARSER = 2; const DIAGNOSTIC_TOLERANT_PHP_PARSER = 3; const DIAGNOSTIC_PHP_PARSER = 4; -} \ No newline at end of file +} diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index 895830ac..e0283d57 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -54,8 +54,7 @@ public static function fromNode($node, string $fqn = null) $symbol->kind = SymbolKind::CLASS_; } else if ($node instanceof Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } - else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { + } else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { // constants with define() like // define('TEST_DEFINE_CONSTANT', false); $symbol->kind = SymbolKind::CONSTANT; @@ -77,9 +76,7 @@ public static function fromNode($node, string $fqn = null) $symbol->kind = SymbolKind::PROPERTY; } else if ($node instanceof Node\ConstElement) { $symbol->kind = SymbolKind::CONSTANT; - } - - else if ( + } else if ( ( ($node instanceof Node\Expression\AssignmentExpression) && $node->leftOperand instanceof Node\Expression\Variable diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 6f7cdc05..1caa421e 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -10,7 +10,8 @@ use Microsoft\PhpParser; use Microsoft\PhpParser\Node; -class TreeAnalyzer { +class TreeAnalyzer +{ private $parser; /** @var Node */ @@ -28,7 +29,8 @@ class TreeAnalyzer { * @param DefinitionResolver $definitionResolver * @param $uri */ - public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { + public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) + { $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; @@ -41,7 +43,8 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso $this->collectDefinitionsAndReferences($this->stmts); } - public function collectDefinitionsAndReferences(Node $stmts) { + public function collectDefinitionsAndReferences(Node $stmts) + { foreach ($stmts::CHILD_NAMES as $name) { $node = $stmts->$name; @@ -79,7 +82,8 @@ public function collectDefinitionsAndReferences(Node $stmts) { } } - public function update($node) { + public function update($node) + { $fqn = ($this->definitionResolver)::getDefinedFqn($node); // Only index definitions with an FQN (no variables) if ($fqn !== null) { @@ -98,7 +102,6 @@ public function update($node) { )) || ($parent instanceof Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) ) { - $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); if ($fqn !== null) { $this->addReference($fqn, $node); @@ -138,7 +141,8 @@ public function update($node) { $this->collectDefinitionsAndReferences($node); } - public function getDiagnostics() { + public function getDiagnostics() + { return $this->diagnostics ?? []; } @@ -150,19 +154,23 @@ private function addReference(string $fqn, Node $node) $this->referenceNodes[$fqn][] = $node; } - public function getDefinitions() { + public function getDefinitions() + { return $this->definitions ?? []; } - public function getDefinitionNodes() { + public function getDefinitionNodes() + { return $this->definitionNodes ?? []; } - public function getReferenceNodes() { + public function getReferenceNodes() + { return $this->referenceNodes ?? []; } - public function getStmts() { + public function getStmts() + { return $this->stmts; } /** diff --git a/src/utils.php b/src/utils.php index ec69a5bb..c8df0006 100644 --- a/src/utils.php +++ b/src/utils.php @@ -172,6 +172,7 @@ function getVendorDir(\stdClass $composerJson = null): string return $composerJson->config->{'vendor-dir'} ?? 'vendor'; } -function strStartsWith(string $haystack, string $prefix): bool { +function strStartsWith(string $haystack, string $prefix): bool +{ return empty($prefix) || strpos($haystack, $prefix) === 0; } diff --git a/tests/PhpDocumentTest.php b/tests/PhpDocumentTest.php index 167aea18..ae1b5cdb 100644 --- a/tests/PhpDocumentTest.php +++ b/tests/PhpDocumentTest.php @@ -44,7 +44,8 @@ public function testGetNodeAtPosition() $this->assertEquals('SomeClass', (string)$node); } - private function assertQualifiedName($node) { + private function assertQualifiedName($node) + { $this->assertInstanceOf(Node\QualifiedName::class, $node); } diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index 48e70b3f..03ba3d86 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -499,7 +499,8 @@ public function testBarePhp() ], true), $items); } - private function assertCompletionsListSubset(CompletionList $subsetList, CompletionList $list) { + private function assertCompletionsListSubset(CompletionList $subsetList, CompletionList $list) + { foreach ($subsetList->items as $expectedItem) { $this->assertContains($expectedItem, $list->items, null, null, false); } diff --git a/tests/Utils/UtilsTest.php b/tests/Utils/UtilsTest.php index d225ff26..d14ce59c 100644 --- a/tests/Utils/UtilsTest.php +++ b/tests/Utils/UtilsTest.php @@ -8,7 +8,8 @@ class UtilsTest extends TestCase { - public function testStrStartsWithDataProvider(): array { + public function testStrStartsWithDataProvider(): array + { return [ ['a', 'b', false], ['', 'a', false], diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 3703083c..eab70a3a 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -25,7 +25,8 @@ class ValidationTest extends TestCase { - public function frameworkErrorProvider() { + public function frameworkErrorProvider() + { global $frameworksDir; $frameworks = glob($frameworksDir . '/*', GLOB_ONLYDIR); @@ -61,7 +62,8 @@ public function frameworkErrorProvider() { * @param $testCaseFile * @param $frameworkName */ - public function testDefinitionErrors($testCaseFile, $frameworkName) { + public function testDefinitionErrors($testCaseFile, $frameworkName) + { $fileContents = file_get_contents($testCaseFile); $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); @@ -90,7 +92,8 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) { } } - private function getActualTestValues($filename, $fileContents): array { + private function getActualTestValues($filename, $fileContents): array + { global $frameworksDir; $index = new Index(); @@ -113,7 +116,7 @@ private function getActualTestValues($filename, $fileContents): array { // Turn references into relative paths foreach ($refsAndDefs['references'] as $key => $list) { - $fixedPathRefs = array_map(function($ref) { + $fixedPathRefs = array_map(function ($ref) { global $frameworksDir; return str_replace($frameworksDir, '.', $ref); }, $list); @@ -184,6 +187,7 @@ private function filterSkippedReferences(&$references): void } } -function getExpectedValuesFile($testCaseFile): string { +function getExpectedValuesFile($testCaseFile): string +{ return $testCaseFile . '.expected.json'; } From de44ce5cd42ed0c79723c2cd88808d530cfee100 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 31 May 2017 20:22:37 -0700 Subject: [PATCH 111/149] Fix error from completions after typing 'new' --- src/CompletionProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index f7181a6f..2b34d3f1 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -278,7 +278,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } elseif (!$isAliased) { continue; } - } elseif ($fqnStartsWithPrefix && $class->isFullyQualifiedName()) { + } elseif ($fqnStartsWithPrefix && $class instanceof Node\QualifiedName && $class->isFullyQualifiedName()) { $fqn = '\\' . $fqn; } From 077f0be6f0ad2dd3ced5b555c9e86fd9f72e45b8 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 1 Jun 2017 16:05:06 -0700 Subject: [PATCH 112/149] Remove 'void' return annotation --- tests/Validation/ValidationTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index eab70a3a..7957fc1b 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -166,7 +166,10 @@ private function getTestValuesFromDefs($definitions): array return $defsForAssert; } - private function filterSkippedReferences(&$references): void + /** + * @return void + */ + private function filterSkippedReferences(&$references) { $skipped = [ 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', From 260969b3bee9c63d13940066efc9365847965311 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 2 Jun 2017 15:43:15 -0700 Subject: [PATCH 113/149] Remove Performance.php comments --- Performance.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Performance.php b/Performance.php index 312b726f..30b2fa6c 100644 --- a/Performance.php +++ b/Performance.php @@ -38,9 +38,6 @@ $start = microtime(true); foreach ($testProviderArray as $idx => $testCaseFile) { - // if ($idx < 20) { - // continue; - // } if (filesize($testCaseFile) > 10000) { continue; } @@ -48,8 +45,6 @@ echo "$idx\n"; } -// echo "$idx=>$testCaseFile\n"; - $fileContents = file_get_contents($testCaseFile); $docBlockFactory = DocBlockFactory::createInstance(); From f144ca7c26f495a52a637a1b6ec7eeab04ebf210 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 2 Jun 2017 17:09:01 -0700 Subject: [PATCH 114/149] Refactor findVariableDefinitionsInNode to simplify and avoid closure use --- src/CompletionProvider.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2b34d3f1..8050a65e 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -400,25 +400,17 @@ private function findVariableDefinitionsInNode(Node $node, string $namePrefix = $vars = []; // If the child node is a variable assignment, save it - $isAssignmentToVariable = function ($node) use ($namePrefix) { - return $node instanceof Node\Expression\AssignmentExpression - && $node->leftOperand instanceof Node\Expression\Variable - && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); - }; - $isNotFunctionLike = function ($node) { - return !( - ParserHelpers::isFunctionLike($node) || - $node instanceof Node\Statement\ClassDeclaration || - $node instanceof Node\Statement\InterfaceDeclaration || - $node instanceof Node\Statement\TraitDeclaration - ); + $isAssignmentToVariable = function ($node) { + return $node instanceof Node\Expression\AssignmentExpression; }; - if ($isAssignmentToVariable($node)) { + if ($this->isAssignmentToVariableWithPrefix($node, $namePrefix)) { $vars[] = $node->leftOperand; } else { - foreach ($node->getDescendantNodes($isNotFunctionLike) as $descendantNode) { - if ($isAssignmentToVariable($descendantNode)) { + // Get all descendent variables, then filter to ones that start with $namePrefix. + // Avoiding closure usage in tight loop + foreach ($node->getDescendantNodes($isAssignmentToVariable) as $descendantNode) { + if ($this->isAssignmentToVariableWithPrefix($descendantNode, $namePrefix)) { $vars[] = $descendantNode->leftOperand; } } @@ -426,4 +418,11 @@ private function findVariableDefinitionsInNode(Node $node, string $namePrefix = return $vars; } + + private function isAssignmentToVariableWithPrefix($node, $namePrefix) + { + return $node instanceof Node\Expression\AssignmentExpression + && $node->leftOperand instanceof Node\Expression\Variable + && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); + } } From d56d1b7fe7707e7dc558bf7f2b630ef2c2fa8b82 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 2 Jun 2017 17:10:33 -0700 Subject: [PATCH 115/149] $index can be private again --- src/DefinitionResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 7df4aee0..f07521b2 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -18,7 +18,7 @@ class DefinitionResolver * * @var \LanguageServer\Index\ReadableIndex */ - protected $index; + private $index; /** * Resolves strings to a type object. From e0a7b2108ea97cafa91782d4ee76344775279268 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 14:25:27 -0700 Subject: [PATCH 116/149] Fix possible Node/MissingToken mismatch (error reported in Lumen project) --- src/DefinitionResolver.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index f07521b2..c242abf9 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -544,18 +544,18 @@ public function resolveVariableToNode($var) */ public function resolveExpressionNodeToType($expr) { - if ($expr == null || $expr instanceof PhpParser\MissingToken || $expr instanceof PhpParser\SkippedToken) { - // TODO some members are null or Missing/SkippedToken - // How do we handle this more generally? - return new Types\Mixed; - } - // PARENTHESIZED EXPRESSION // Retrieve inner expression from parenthesized expression while ($expr instanceof Node\Expression\ParenthesizedExpression) { $expr = $expr->expression; } + if ($expr == null || $expr instanceof PhpParser\MissingToken || $expr instanceof PhpParser\SkippedToken) { + // TODO some members are null or Missing/SkippedToken + // How do we handle this more generally? + return new Types\Mixed; + } + // VARIABLE // $this -> Type\this // $myVariable -> type of corresponding assignment expression From 65363b7390212f70fb837a6b407a7e1bc0eca108 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 14:39:44 -0700 Subject: [PATCH 117/149] Add comment on try/catch in DefinitionResolver --- src/DefinitionResolver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index c242abf9..77527f33 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -151,6 +151,8 @@ private function getDocBlock(Node $node) $context = new Types\Context($namespaceName, $namespaceImportTable); try { + // create() throws when it thinks the doc comment has invalid fields. + // For example, a @see tag that is followed by something that doesn't look like a valid fqsen will throw. return $this->docBlockFactory->create($docCommentText, $context); } catch (\InvalidArgumentException $e) { return null; From f16866ae4d18739c40d9575af8121e5a4904ec2e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 14:40:24 -0700 Subject: [PATCH 118/149] Restore type annotation --- src/DefinitionResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 77527f33..33c72c25 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -168,7 +168,7 @@ private function getDocBlock(Node $node) * @param string $fqn * @return Definition */ - public function createDefinitionFromNode($node, string $fqn = null): Definition + public function createDefinitionFromNode(Node $node, string $fqn = null): Definition { $def = new Definition; $def->fqn = $fqn; From f1c0cc5c0648271293d4b1d804dd5fdb85a9beac Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 14:41:42 -0700 Subject: [PATCH 119/149] Remove comments, question answered by Felix --- src/DefinitionResolver.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 33c72c25..8e871cd9 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -198,11 +198,9 @@ public function createDefinitionFromNode(Node $node, string $fqn = null): Defini ); if ($node instanceof Node\Statement\ClassDeclaration && - // TODO - this should be bette rrpreented in the parser API + // TODO - this should be better represented in the parser API $node->classBaseClause !== null && $node->classBaseClause->baseClass !== null) { $def->extends = [(string)$node->classBaseClause->baseClass->getResolvedName()]; - // TODO - why is this represented as an array? - // TODO interface implementations. } elseif ( $node instanceof Node\Statement\InterfaceDeclaration && // TODO - this should be better represented in the parser API From 3cb0c03c81a9aaf554f6e3f541a6ab161e4dbdaf Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 16:05:47 -0700 Subject: [PATCH 120/149] Restore more type annotations --- src/DefinitionResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 8e871cd9..8e989230 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -229,7 +229,7 @@ public function createDefinitionFromNode(Node $node, string $fqn = null): Defini * @param Node $node Any reference node * @return Definition|null */ - public function resolveReferenceNodeToDefinition($node) + public function resolveReferenceNodeToDefinition(Node $node) { $parent = $node->parent; // Variables are not indexed globally, as they stay in the file scope anyway. @@ -270,7 +270,7 @@ public function resolveReferenceNodeToDefinition($node) * @param Node $node * @return string|null */ - public function resolveReferenceNodeToFqn($node) + public function resolveReferenceNodeToFqn(Node $node) { // TODO all name tokens should be a part of a node if ($node instanceof Node\QualifiedName) { From 01e72430d0a45179e1be66583dccbc36944370c8 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 16:08:34 -0700 Subject: [PATCH 121/149] Fix indentation --- src/CompletionProvider.php | 2 +- src/DefinitionResolver.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 8050a65e..d1fd9508 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -158,7 +158,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi !( $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression && $node->parent->memberName === $node) - ) { + ) { // Find variables, parameters and use statements in the scope $namePrefix = $node->getName() ?? ''; foreach ($this->suggestVariablesAtNode($node, $namePrefix) as $var) { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 8e989230..9fc5b5b5 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -642,11 +642,11 @@ public function resolveExpressionNodeToType($expr) } else { $classFqn = substr((string)$t->getFqsen(), 1); } - $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); + $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); if ($expr->parent instanceof Node\Expression\CallExpression) { $fqn .= '()'; } - $def = $this->index->getDefinition($fqn); + $def = $this->index->getDefinition($fqn); if ($def !== null) { return $def->type; } From 825c67159e0964ce0d78e898b5625c35f330d49e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 16:45:51 -0700 Subject: [PATCH 122/149] Remove unnecessary group import --- src/LanguageServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LanguageServer.php b/src/LanguageServer.php index a368e55c..173abfe9 100644 --- a/src/LanguageServer.php +++ b/src/LanguageServer.php @@ -16,7 +16,7 @@ use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex}; use LanguageServer\Cache\{FileSystemCache, ClientCache}; use AdvancedJsonRpc; -use Sabre\Event\{Promise}; +use Sabre\Event\Promise; use function Sabre\Event\coroutine; use Throwable; use Webmozart\PathUtil\Path; From eef824488efe28e236a21d03ad7b08932c5dd8e9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 6 Jun 2017 16:46:08 -0700 Subject: [PATCH 123/149] Make Index->references private again --- src/Index/Index.php | 13 ++++++++++++- tests/Validation/ValidationTest.php | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Index/Index.php b/src/Index/Index.php index 7a13529d..9cb975e5 100644 --- a/src/Index/Index.php +++ b/src/Index/Index.php @@ -26,7 +26,7 @@ class Index implements ReadableIndex, \Serializable * * @var string[][] */ - public $references = []; + private $references = []; /** * @var bool @@ -150,6 +150,17 @@ public function getReferenceUris(string $fqn): array return $this->references[$fqn] ?? []; } + /** + * For test use. + * Returns all references, keyed by fqn. + * + * @return string[][] + */ + public function getReferences(): array + { + return $this->references; + } + /** * Adds a document URI as a referencee of a specific symbol * diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 7957fc1b..1145df06 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -103,7 +103,7 @@ private function getActualTestValues($filename, $fileContents): array $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - $actualRefs = $index->references; + $actualRefs = $index->getReferences(); $this->filterSkippedReferences($actualRefs); $actualDefs = $this->getTestValuesFromDefs($document->getDefinitions()); From aba798aaba0a217b6e8bbf8b74001c0354e32948 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 11:10:12 -0700 Subject: [PATCH 124/149] Cleanup --- src/ParserHelpers.php | 1 - src/ParserKind.php | 11 ----------- src/Protocol/Range.php | 2 +- src/Protocol/SymbolInformation.php | 12 ------------ src/Server/TextDocument.php | 2 +- src/TreeAnalyzer.php | 8 +++++--- 6 files changed, 7 insertions(+), 29 deletions(-) delete mode 100644 src/ParserKind.php diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index 81195a66..779c2839 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -15,7 +15,6 @@ public static function isConstantFetch(Node $node) : bool ( $node instanceof Node\QualifiedName && ( -// $node->parent instanceof Node\Statement\ExpressionStatement || $parent instanceof Node\Expression || $parent instanceof Node\DelimitedList\ExpressionList || $parent instanceof Node\ArrayElement || diff --git a/src/ParserKind.php b/src/ParserKind.php deleted file mode 100644 index 39d75590..00000000 --- a/src/ParserKind.php +++ /dev/null @@ -1,11 +0,0 @@ -getStart(), $node->getWidth(), $node->getFileContents()); diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index e0283d57..f3defbf4 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -107,18 +107,6 @@ public static function fromNode($node, string $fqn = null) $symbol->name = $node->variableName->getText($node); } else if (!isset($symbol->name)) { return null; - // if (!isset($symbol->name)) { - // if ($node instanceof Node\Name) { - // $symbol->name = (string)$node; - // } else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { - // $symbol->name = $node->var->name; - // } else if ($node instanceof Node\Expr\ClosureUse) { - // $symbol->name = $node->var; - // } else if (isset($node->name)) { - // $symbol->name = (string)$node->name; - // } else { - // return null; - // } } $symbol->location = Location::fromNode($node); diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index d00ebfa2..c07586cb 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -49,7 +49,7 @@ class TextDocument /** * @var ReadableIndex */ - public $index; + protected $index; /** * @var \stdClass|null diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 1caa421e..995f7c0c 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -17,8 +17,10 @@ class TreeAnalyzer /** @var Node */ private $stmts; + /** @var Diagnostic[] */ private $diagnostics; + /** @var string */ private $content; /** @@ -65,11 +67,11 @@ public function collectDefinitionsAndReferences(Node $stmts) $this->update($node); } - if (($_error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = PhpParser\PositionUtilities::getRangeFromPosition($_error->start, $_error->length, $this->content); + if (($error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = PhpParser\PositionUtilities::getRangeFromPosition($error->start, $error->length, $this->content); $this->diagnostics[] = new Diagnostic( - $_error->message, + $error->message, new Range( new Position($range->start->line, $range->start->character), new Position($range->end->line, $range->start->character) From d4cabc60cc4fbbf91336078f2835f44e647948bb Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 11:24:07 -0700 Subject: [PATCH 125/149] Annotate TreeAnalyzer->update --- src/TreeAnalyzer.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 995f7c0c..6a659d6b 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -84,7 +84,11 @@ public function collectDefinitionsAndReferences(Node $stmts) } } - public function update($node) + /** + * Collect definitions and references for the given node + * @param Node $node + */ + private function update(Node $node) { $fqn = ($this->definitionResolver)::getDefinedFqn($node); // Only index definitions with an FQN (no variables) From 70cf60e86824c3a389d4fa0b437b6b7bd98dd335 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 11:37:04 -0700 Subject: [PATCH 126/149] Add missing props to TreeAnalyzer, remove unused getUri --- src/TreeAnalyzer.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 6a659d6b..7921d011 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -23,6 +23,15 @@ class TreeAnalyzer /** @var string */ private $content; + /** @var Node[] */ + private $referenceNodes; + + /** @var Definition[] */ + private $definitions; + + /** @var Node[] */ + private $definitionNodes; + /** * TreeAnalyzer constructor. * @param PhpParser\Parser $parser @@ -33,7 +42,6 @@ class TreeAnalyzer */ public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) { - $this->uri = $uri; $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; $this->definitionResolver = $definitionResolver; @@ -179,13 +187,4 @@ public function getStmts() { return $this->stmts; } - /** - * Returns the URI of the document - * - * @return string - */ - public function getUri(): string - { - return $this->uri; - } } From 829d3075f787569e1471726c6cf0110fdefa0c6a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 11:37:45 -0700 Subject: [PATCH 127/149] Improve strStartsWith --- src/utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.php b/src/utils.php index c8df0006..04553ce8 100644 --- a/src/utils.php +++ b/src/utils.php @@ -174,5 +174,5 @@ function getVendorDir(\stdClass $composerJson = null): string function strStartsWith(string $haystack, string $prefix): bool { - return empty($prefix) || strpos($haystack, $prefix) === 0; + return substr($haystack, 0, strlen($prefix)) === $prefix; } From af5a5fe172aa9ed3f3f3d7a4bd1f000e7652a044 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 11:38:46 -0700 Subject: [PATCH 128/149] Mark test incomplete instead of commenting it out --- tests/Server/TextDocument/ParseErrorsTest.php | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/Server/TextDocument/ParseErrorsTest.php b/tests/Server/TextDocument/ParseErrorsTest.php index 8e377046..44285234 100644 --- a/tests/Server/TextDocument/ParseErrorsTest.php +++ b/tests/Server/TextDocument/ParseErrorsTest.php @@ -127,28 +127,28 @@ public function testParseErrorsArePublishedAsDiagnostics() ], json_decode(json_encode($this->args), true)); } - // This diagnostic not yet implemented in tolerant-php-parser - // public function testParseErrorsWithOnlyStartLine() - // { - // $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php'); - // $this->assertEquals([ - // 'whatever', - // [[ - // 'range' => [ - // 'start' => [ - // 'line' => 4, - // 'character' => 0 - // ], - // 'end' => [ - // 'line' => 4, - // 'character' => 0 - // ] - // ], - // 'severity' => DiagnosticSeverity::ERROR, - // 'code' => null, - // 'source' => 'php', - // 'message' => "Namespace declaration statement has to be the very first statement in the script" - // ]] - // ], json_decode(json_encode($this->args), true)); - // } + public function testParseErrorsWithOnlyStartLine() + { + $this->markTestIncomplete('This diagnostic not yet implemented in tolerant-php-parser'); + $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php'); + $this->assertEquals([ + 'whatever', + [[ + 'range' => [ + 'start' => [ + 'line' => 4, + 'character' => 0 + ], + 'end' => [ + 'line' => 4, + 'character' => 0 + ] + ], + 'severity' => DiagnosticSeverity::ERROR, + 'code' => null, + 'source' => 'php', + 'message' => "Namespace declaration statement has to be the very first statement in the script" + ]] + ], json_decode(json_encode($this->args), true)); + } } From b2a849d6d27bfd1b8ab228b452548115534c48fb Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 14:00:12 -0700 Subject: [PATCH 129/149] Cleanup ValidationTest some more --- tests/Validation/ValidationTest.php | 53 +++++++------------ .../{skipped.json => disabled.json} | 0 .../WithReturnTypehints.php.expected.json | 16 +++--- ...embersShouldNotBeSymbols.php.expected.json | 2 +- ...rrayValueShouldBeBoolean.php.expected.json | 4 +- .../_cases/caseStatement1.php.expected.json | 6 +-- .../_cases/classDefinition1.php.expected.json | 10 ++-- .../_cases/classProperty1.php.expected.json | 12 ++--- .../_cases/constants.php.expected.json | 10 ++-- .../_cases/constants2.php.expected.json | 10 ++-- .../_cases/constants3.php.expected.json | 10 ++-- .../_cases/constants4.php.expected.json | 10 ++-- .../_cases/constants5.php.expected.json | 8 +-- ...tsInFunctionParamDefault.php.expected.json | 6 +-- ...cksOnNamespaceDefinition.php.expected.json | 2 +- .../_cases/exceptions1.php.expected.json | 2 +- .../_cases/functionUse.php.expected.json | 4 +- .../_cases/functionUse2.php.expected.json | 4 +- .../_cases/ifStatement1.php.expected.json | 6 +-- .../interfaceProperty.php.expected.json | 2 +- ...cConstantsShouldBeGlobal.php.expected.json | 2 +- .../_cases/magicConsts.php.expected.json | 4 +- .../_cases/memberAccess1.php.expected.json | 10 ++-- .../_cases/memberAccess2.php.expected.json | 10 ++-- .../_cases/memberAccess3.php.expected.json | 20 +++---- .../_cases/memberAccess4.php.expected.json | 14 ++--- .../_cases/memberAccess5.php.expected.json | 6 +-- .../_cases/memberCall1.php.expected.json | 12 ++--- .../multipleNamespaces.php.expected.json | 20 +++---- ...ltiplePreceedingComments.php.expected.json | 4 +- .../_cases/nameToken.php.expected.json | 4 +- .../_cases/namespaces2.php.expected.json | 10 ++-- .../_cases/namespaces4.php.expected.json | 4 +- .../_cases/namespaces5.php.expected.json | 16 +++--- .../_cases/namespaces6.php.expected.json | 2 +- .../_cases/namespaces8.php.expected.json | 4 +- .../_cases/objectCreation.php.expected.json | 8 +-- .../_cases/objectCreation2.php.expected.json | 12 ++--- .../_cases/objectCreation3.php.expected.json | 6 +-- .../_cases/param1.php.expected.json | 6 +-- .../_cases/parent1.php.expected.json | 14 ++--- .../_cases/parent3.php.expected.json | 16 +++--- .../_cases/propertyName1.php.expected.json | 4 +- .../_cases/propertyName2.php.expected.json | 4 +- .../_cases/returnType.php.expected.json | 8 +-- .../scopedPropertyAccess.php.expected.json | 10 ++-- .../scopedPropertyAccess2.php.expected.json | 4 +- .../scopedPropertyAccess3.php.expected.json | 8 +-- .../scopedPropertyAccess4.php.expected.json | 2 +- .../scopedPropertyAccess5.php.expected.json | 12 ++--- .../frameworks/_cases/self1.php.expected.json | 16 +++--- .../frameworks/_cases/self2.php.expected.json | 16 +++--- .../frameworks/_cases/self3.php.expected.json | 16 +++--- .../frameworks/_cases/self4.php.expected.json | 14 ++--- .../frameworks/_cases/self5.php.expected.json | 8 +-- .../_cases/static1.php.expected.json | 16 +++--- .../_cases/static2.php.expected.json | 16 +++--- .../_cases/static3.php.expected.json | 16 +++--- .../_cases/static4.php.expected.json | 10 ++-- .../_cases/stringVariable.php.expected.json | 6 +-- ...edNameOutsideOfNamespace.php.expected.json | 4 +- ...rifyFqsenOnClassProperty.php.expected.json | 10 ++-- 62 files changed, 283 insertions(+), 298 deletions(-) rename tests/Validation/{skipped.json => disabled.json} (100%) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 1145df06..2bbb5651 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -21,48 +21,37 @@ use Sabre\Event\Loop; use Microsoft\PhpParser; -$frameworksDir = realpath(__DIR__ . '/../../validation/frameworks'); - class ValidationTest extends TestCase { - public function frameworkErrorProvider() + public function validationTestProvider() { - global $frameworksDir; - $frameworks = glob($frameworksDir . '/*', GLOB_ONLYDIR); - $testProviderArray = array(); - foreach ($frameworks as $frameworkDir) { - $frameworkName = basename($frameworkDir); - if ($frameworkName !== '_cases') { - continue; - } + $testCasesDir = realpath(__DIR__ . '/../../validation/frameworks/_cases'); - $iterator = new RecursiveDirectoryIterator($frameworkDir); - $skipped = json_decode(file_get_contents(__DIR__ . '/skipped.json')); + $iterator = new RecursiveDirectoryIterator($testCasesDir); + $disabled = json_decode(file_get_contents(__DIR__ . '/disabled.json')); - foreach (new RecursiveIteratorIterator($iterator) as $file) { - if (strpos(\strrev((string)$file), \strrev(".php")) === 0 && !\in_array(basename((string)$file), $skipped)) { - if ($file->getSize() < 100000) { - $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; - } + foreach (new RecursiveIteratorIterator($iterator) as $file) { + if (strpos(\strrev((string)$file), \strrev(".php")) === 0 && !\in_array(basename((string)$file), $disabled)) { + if ($file->getSize() < 100000) { + $testProviderArray[] = [$file->getPathname()]; } } } - if (count($testProviderArray) === 0) { - throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); - } - return $testProviderArray; } /** + * This test loads the test cases specified in .php files under cases/ and looks at the whole set of + * Definitions and References produced. It reads the expected results from associated .json files + * and compares to the actual result. If they don't match, the test fails and it writes the new baseline + * to the .json file. * @group validation - * @dataProvider frameworkErrorProvider + * @dataProvider validationTestProvider * @param $testCaseFile - * @param $frameworkName */ - public function testDefinitionErrors($testCaseFile, $frameworkName) + public function testDefinitionsAndReferences($testCaseFile) { $fileContents = file_get_contents($testCaseFile); $actualValues = $this->getActualTestValues($testCaseFile, $fileContents); @@ -84,9 +73,7 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) } } catch (\Throwable $e) { $outputFile = getExpectedValuesFile($testCaseFile); - if ($frameworkName === '_cases') { - file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); - } + file_put_contents($outputFile, json_encode($actualValues, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); throw $e; } @@ -94,8 +81,6 @@ public function testDefinitionErrors($testCaseFile, $frameworkName) private function getActualTestValues($filename, $fileContents): array { - global $frameworksDir; - $index = new Index(); $parser = new PhpParser\Parser(); $docBlockFactory = DocBlockFactory::createInstance(); @@ -115,10 +100,10 @@ private function getActualTestValues($filename, $fileContents): array ); // Turn references into relative paths + $testCasesDir = realpath(__DIR__ . '/../../validation/frameworks/_cases'); foreach ($refsAndDefs['references'] as $key => $list) { - $fixedPathRefs = array_map(function ($ref) { - global $frameworksDir; - return str_replace($frameworksDir, '.', $ref); + $fixedPathRefs = array_map(function ($ref) use ($testCasesDir) { + return str_replace($testCasesDir, '.', $ref); }, $list); $refsAndDefs['references']->$key = $fixedPathRefs; @@ -128,7 +113,7 @@ private function getActualTestValues($filename, $fileContents): array foreach ($refsAndDefs['definitions'] as $key => $def) { if ($def !== null && $def->symbolInformation !== null && $def->symbolInformation->location !== null && $def->symbolInformation->location->uri !== null) { - $def->symbolInformation->location->uri = str_replace($frameworksDir, '.', $def->symbolInformation->location->uri); + $def->symbolInformation->location->uri = str_replace($testCasesDir, '.', $def->symbolInformation->location->uri); } } diff --git a/tests/Validation/skipped.json b/tests/Validation/disabled.json similarity index 100% rename from tests/Validation/skipped.json rename to tests/Validation/disabled.json diff --git a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json index dd00cd53..43dc4b56 100644 --- a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json +++ b/validation/frameworks/_cases/WithReturnTypehints.php.expected.json @@ -1,13 +1,13 @@ { "references": { "Fixtures\\Prophecy\\EmptyClass": [ - "./_cases/WithReturnTypehints.php" + "./WithReturnTypehints.php" ], "self": [ - "./_cases/WithReturnTypehints.php" + "./WithReturnTypehints.php" ], "parent": [ - "./_cases/WithReturnTypehints.php" + "./WithReturnTypehints.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "Fixtures\\Prophecy", "kind": 3, "location": { - "uri": "./_cases/WithReturnTypehints.php" + "uri": "./WithReturnTypehints.php" }, "containerName": "Fixtures" }, @@ -38,7 +38,7 @@ "name": "WithReturnTypehints", "kind": 5, "location": { - "uri": "./_cases/WithReturnTypehints.php" + "uri": "./WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy" }, @@ -54,7 +54,7 @@ "name": "getSelf", "kind": 6, "location": { - "uri": "./_cases/WithReturnTypehints.php" + "uri": "./WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -71,7 +71,7 @@ "name": "getName", "kind": 6, "location": { - "uri": "./_cases/WithReturnTypehints.php" + "uri": "./WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, @@ -88,7 +88,7 @@ "name": "getParent", "kind": 6, "location": { - "uri": "./_cases/WithReturnTypehints.php" + "uri": "./WithReturnTypehints.php" }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, diff --git a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index b0a09822..727210b7 100644 --- a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/anonymousClassMembersShouldNotBeSymbols.php" + "uri": "./anonymousClassMembersShouldNotBeSymbols.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json index c461f3e7..4acb4ba7 100644 --- a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json +++ b/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/arrayValueShouldBeBoolean.php" + "uri": "./arrayValueShouldBeBoolean.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "foo", "kind": 7, "location": { - "uri": "./_cases/arrayValueShouldBeBoolean.php" + "uri": "./arrayValueShouldBeBoolean.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/caseStatement1.php.expected.json b/validation/frameworks/_cases/caseStatement1.php.expected.json index c3021392..8d8d968c 100644 --- a/validation/frameworks/_cases/caseStatement1.php.expected.json +++ b/validation/frameworks/_cases/caseStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "./_cases/caseStatement1.php" + "./caseStatement1.php" ], "A": [ - "./_cases/caseStatement1.php" + "./caseStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/caseStatement1.php" + "uri": "./caseStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/classDefinition1.php.expected.json b/validation/frameworks/_cases/classDefinition1.php.expected.json index efd937af..f135c15c 100644 --- a/validation/frameworks/_cases/classDefinition1.php.expected.json +++ b/validation/frameworks/_cases/classDefinition1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\A": [ - "./_cases/classDefinition1.php" + "./classDefinition1.php" ], "TestNamespace\\A->a": [ - "./_cases/classDefinition1.php" + "./classDefinition1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "./_cases/classDefinition1.php" + "uri": "./classDefinition1.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/classDefinition1.php" + "uri": "./classDefinition1.php" }, "containerName": "TestNamespace" }, @@ -49,7 +49,7 @@ "name": "a", "kind": 7, "location": { - "uri": "./_cases/classDefinition1.php" + "uri": "./classDefinition1.php" }, "containerName": "TestNamespace\\A" }, diff --git a/validation/frameworks/_cases/classProperty1.php.expected.json b/validation/frameworks/_cases/classProperty1.php.expected.json index 56c87822..4469987c 100644 --- a/validation/frameworks/_cases/classProperty1.php.expected.json +++ b/validation/frameworks/_cases/classProperty1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "SomeNamespace\\Goo": [ - "./_cases/classProperty1.php" + "./classProperty1.php" ], "SomeNamespace": [ - "./_cases/classProperty1.php" + "./classProperty1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "./_cases/classProperty1.php" + "uri": "./classProperty1.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "./_cases/classProperty1.php" + "uri": "./classProperty1.php" }, "containerName": "TestNamespace" }, @@ -49,7 +49,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "./_cases/classProperty1.php" + "uri": "./classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, @@ -66,7 +66,7 @@ "name": "testMethod", "kind": 6, "location": { - "uri": "./_cases/classProperty1.php" + "uri": "./classProperty1.php" }, "containerName": "TestNamespace\\TestClass" }, diff --git a/validation/frameworks/_cases/constants.php.expected.json b/validation/frameworks/_cases/constants.php.expected.json index 228f838c..b38fbb86 100644 --- a/validation/frameworks/_cases/constants.php.expected.json +++ b/validation/frameworks/_cases/constants.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "./_cases/constants.php" + "./constants.php" ], "BYE": [ - "./_cases/constants.php" + "./constants.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/constants.php" + "uri": "./constants.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/constants.php" + "uri": "./constants.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "./_cases/constants.php" + "uri": "./constants.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants2.php.expected.json b/validation/frameworks/_cases/constants2.php.expected.json index 04040068..978d0bfa 100644 --- a/validation/frameworks/_cases/constants2.php.expected.json +++ b/validation/frameworks/_cases/constants2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\BYE": [ - "./_cases/constants2.php" + "./constants2.php" ], "BYE": [ - "./_cases/constants2.php" + "./constants2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/constants2.php" + "uri": "./constants2.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/constants2.php" + "uri": "./constants2.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "./_cases/constants2.php" + "uri": "./constants2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants3.php.expected.json b/validation/frameworks/_cases/constants3.php.expected.json index 0ddad8ce..6f8b7007 100644 --- a/validation/frameworks/_cases/constants3.php.expected.json +++ b/validation/frameworks/_cases/constants3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\T_NEW": [ - "./_cases/constants3.php" + "./constants3.php" ], "T_NEW": [ - "./_cases/constants3.php" + "./constants3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/constants3.php" + "uri": "./constants3.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/constants3.php" + "uri": "./constants3.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "./_cases/constants3.php" + "uri": "./constants3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants4.php.expected.json b/validation/frameworks/_cases/constants4.php.expected.json index a1fe6634..0d962efe 100644 --- a/validation/frameworks/_cases/constants4.php.expected.json +++ b/validation/frameworks/_cases/constants4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\HI": [ - "./_cases/constants4.php" + "./constants4.php" ], "HI": [ - "./_cases/constants4.php" + "./constants4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/constants4.php" + "uri": "./constants4.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/constants4.php" + "uri": "./constants4.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "./_cases/constants4.php" + "uri": "./constants4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/constants5.php.expected.json b/validation/frameworks/_cases/constants5.php.expected.json index c7ebff95..d7a19835 100644 --- a/validation/frameworks/_cases/constants5.php.expected.json +++ b/validation/frameworks/_cases/constants5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\PHP_INT_MAX": [ - "./_cases/constants5.php" + "./constants5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/constants5.php" + "uri": "./constants5.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "Mbstring", "kind": 5, "location": { - "uri": "./_cases/constants5.php" + "uri": "./constants5.php" }, "containerName": "MyNamespace" }, @@ -46,7 +46,7 @@ "name": "MB_CASE_FOLD", "kind": 14, "location": { - "uri": "./_cases/constants5.php" + "uri": "./constants5.php" }, "containerName": "MyNamespace\\Mbstring" }, diff --git a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json index 89613e98..cb24cfda 100644 --- a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json +++ b/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MY_CONSTANT": [ - "./_cases/constantsInFunctionParamDefault.php" + "./constantsInFunctionParamDefault.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 11, "location": { - "uri": "./_cases/constantsInFunctionParamDefault.php" + "uri": "./constantsInFunctionParamDefault.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/constantsInFunctionParamDefault.php" + "uri": "./constantsInFunctionParamDefault.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json index 1e72d0dd..dbd85f69 100644 --- a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json +++ b/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/docBlocksOnNamespaceDefinition.php" + "uri": "./docBlocksOnNamespaceDefinition.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/exceptions1.php.expected.json b/validation/frameworks/_cases/exceptions1.php.expected.json index 12047798..42981946 100644 --- a/validation/frameworks/_cases/exceptions1.php.expected.json +++ b/validation/frameworks/_cases/exceptions1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/exceptions1.php" + "uri": "./exceptions1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/functionUse.php.expected.json b/validation/frameworks/_cases/functionUse.php.expected.json index 5ecb0b82..5c9af19a 100644 --- a/validation/frameworks/_cases/functionUse.php.expected.json +++ b/validation/frameworks/_cases/functionUse.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "./_cases/functionUse.php" + "./functionUse.php" ], "A->b()": [ - "./_cases/functionUse.php" + "./functionUse.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/functionUse2.php.expected.json b/validation/frameworks/_cases/functionUse2.php.expected.json index b58c001a..f3609bd0 100644 --- a/validation/frameworks/_cases/functionUse2.php.expected.json +++ b/validation/frameworks/_cases/functionUse2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "LanguageServer": [ - "./_cases/functionUse2.php" + "./functionUse2.php" ], "LanguageServer\\timeout()": [ - "./_cases/functionUse2.php" + "./functionUse2.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/ifStatement1.php.expected.json b/validation/frameworks/_cases/ifStatement1.php.expected.json index 1341d08b..d412ee16 100644 --- a/validation/frameworks/_cases/ifStatement1.php.expected.json +++ b/validation/frameworks/_cases/ifStatement1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A": [ - "./_cases/ifStatement1.php" + "./ifStatement1.php" ], "A": [ - "./_cases/ifStatement1.php" + "./ifStatement1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/ifStatement1.php" + "uri": "./ifStatement1.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/interfaceProperty.php.expected.json b/validation/frameworks/_cases/interfaceProperty.php.expected.json index 56dbc279..955456b1 100644 --- a/validation/frameworks/_cases/interfaceProperty.php.expected.json +++ b/validation/frameworks/_cases/interfaceProperty.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 11, "location": { - "uri": "./_cases/interfaceProperty.php" + "uri": "./interfaceProperty.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json index 95737a9c..f40036ed 100644 --- a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json +++ b/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json @@ -10,7 +10,7 @@ "name": "B", "kind": 3, "location": { - "uri": "./_cases/magicConstantsShouldBeGlobal.php" + "uri": "./magicConstantsShouldBeGlobal.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/magicConsts.php.expected.json b/validation/frameworks/_cases/magicConsts.php.expected.json index ddbe0967..e9b187fd 100644 --- a/validation/frameworks/_cases/magicConsts.php.expected.json +++ b/validation/frameworks/_cases/magicConsts.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/magicConsts.php" + "uri": "./magicConsts.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "deprecationsTriggered", "kind": 7, "location": { - "uri": "./_cases/magicConsts.php" + "uri": "./magicConsts.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/memberAccess1.php.expected.json b/validation/frameworks/_cases/memberAccess1.php.expected.json index 66601b86..a8d7ff3d 100644 --- a/validation/frameworks/_cases/memberAccess1.php.expected.json +++ b/validation/frameworks/_cases/memberAccess1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\a": [ - "./_cases/memberAccess1.php" + "./memberAccess1.php" ], "MyNamespace\\a->a()": [ - "./_cases/memberAccess1.php" + "./memberAccess1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberAccess1.php" + "uri": "./memberAccess1.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/memberAccess1.php" + "uri": "./memberAccess1.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/memberAccess1.php" + "uri": "./memberAccess1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess2.php.expected.json b/validation/frameworks/_cases/memberAccess2.php.expected.json index ad94aa69..dd2493bb 100644 --- a/validation/frameworks/_cases/memberAccess2.php.expected.json +++ b/validation/frameworks/_cases/memberAccess2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\a": [ - "./_cases/memberAccess2.php" + "./memberAccess2.php" ], "MyNamespace\\a->a()": [ - "./_cases/memberAccess2.php" + "./memberAccess2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberAccess2.php" + "uri": "./memberAccess2.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/memberAccess2.php" + "uri": "./memberAccess2.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/memberAccess2.php" + "uri": "./memberAccess2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess3.php.expected.json b/validation/frameworks/_cases/memberAccess3.php.expected.json index 68e4ae33..60db5b55 100644 --- a/validation/frameworks/_cases/memberAccess3.php.expected.json +++ b/validation/frameworks/_cases/memberAccess3.php.expected.json @@ -1,25 +1,25 @@ { "references": { "MyNamespace\\ClassLoader": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "Closure::bind()": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "Closure": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "MyNamespace\\ClassLoader->prefixesPsr0": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "MyNamespace\\ComposerStaticInitIncludePath::$prefixesPsr0": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ], "MyNamespace\\ClassLoader::class": [ - "./_cases/memberAccess3.php" + "./memberAccess3.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberAccess3.php" + "uri": "./memberAccess3.php" }, "containerName": "" }, @@ -48,7 +48,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/memberAccess3.php" + "uri": "./memberAccess3.php" }, "containerName": "MyNamespace" }, @@ -64,7 +64,7 @@ "name": "getInitializer", "kind": 6, "location": { - "uri": "./_cases/memberAccess3.php" + "uri": "./memberAccess3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess4.php.expected.json b/validation/frameworks/_cases/memberAccess4.php.expected.json index c6b939ea..78208ce8 100644 --- a/validation/frameworks/_cases/memberAccess4.php.expected.json +++ b/validation/frameworks/_cases/memberAccess4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace\\Request::create()": [ - "./_cases/memberAccess4.php" + "./memberAccess4.php" ], "MyNamespace\\Request": [ - "./_cases/memberAccess4.php" + "./memberAccess4.php" ], "MyNamespace\\Url->toString()": [ - "./_cases/memberAccess4.php" + "./memberAccess4.php" ], "MyNamespace\\Url": [ - "./_cases/memberAccess4.php" + "./memberAccess4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberAccess4.php" + "uri": "./memberAccess4.php" }, "containerName": "" }, @@ -39,7 +39,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/memberAccess4.php" + "uri": "./memberAccess4.php" }, "containerName": "MyNamespace" }, @@ -55,7 +55,7 @@ "name": "testRequest", "kind": 6, "location": { - "uri": "./_cases/memberAccess4.php" + "uri": "./memberAccess4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/memberAccess5.php.expected.json b/validation/frameworks/_cases/memberAccess5.php.expected.json index 60392c40..6e23151c 100644 --- a/validation/frameworks/_cases/memberAccess5.php.expected.json +++ b/validation/frameworks/_cases/memberAccess5.php.expected.json @@ -10,7 +10,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberAccess5.php" + "uri": "./memberAccess5.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "./_cases/memberAccess5.php" + "uri": "./memberAccess5.php" }, "containerName": "MyNamespace" }, @@ -42,7 +42,7 @@ "name": "setUp", "kind": 6, "location": { - "uri": "./_cases/memberAccess5.php" + "uri": "./memberAccess5.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/_cases/memberCall1.php.expected.json b/validation/frameworks/_cases/memberCall1.php.expected.json index b2f8a880..a94a8437 100644 --- a/validation/frameworks/_cases/memberCall1.php.expected.json +++ b/validation/frameworks/_cases/memberCall1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\AccountInterface": [ - "./_cases/memberCall1.php" + "./memberCall1.php" ], "MyNamespace\\A": [ - "./_cases/memberCall1.php" + "./memberCall1.php" ], "MyNamespace\\AccountInterface->getAccount()": [ - "./_cases/memberCall1.php" + "./memberCall1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/memberCall1.php" + "uri": "./memberCall1.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "ParseErrorsTest", "kind": 5, "location": { - "uri": "./_cases/memberCall1.php" + "uri": "./memberCall1.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "setAccount", "kind": 6, "location": { - "uri": "./_cases/memberCall1.php" + "uri": "./memberCall1.php" }, "containerName": "MyNamespace\\ParseErrorsTest" }, diff --git a/validation/frameworks/_cases/multipleNamespaces.php.expected.json b/validation/frameworks/_cases/multipleNamespaces.php.expected.json index 5e630c00..5bf8760b 100644 --- a/validation/frameworks/_cases/multipleNamespaces.php.expected.json +++ b/validation/frameworks/_cases/multipleNamespaces.php.expected.json @@ -1,16 +1,16 @@ { "references": { "MyNamespace2\\MyNamespace1\\B": [ - "./_cases/multipleNamespaces.php" + "./multipleNamespaces.php" ], "MyNamespace2\\MyNamespace1": [ - "./_cases/multipleNamespaces.php" + "./multipleNamespaces.php" ], "MyNamespace2": [ - "./_cases/multipleNamespaces.php" + "./multipleNamespaces.php" ], "MyNamespace2\\A->b()": [ - "./_cases/multipleNamespaces.php" + "./multipleNamespaces.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "" }, @@ -39,7 +39,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "MyNamespace1" }, @@ -55,7 +55,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "MyNamespace1\\B" }, @@ -72,7 +72,7 @@ "name": "MyNamespace2", "kind": 3, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "" }, @@ -90,7 +90,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "MyNamespace2" }, @@ -106,7 +106,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/multipleNamespaces.php" + "uri": "./multipleNamespaces.php" }, "containerName": "MyNamespace2\\A" }, diff --git a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json index 686aa455..fe34f9a2 100644 --- a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json +++ b/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json @@ -10,7 +10,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "./_cases/multiplePreceedingComments.php" + "uri": "./multiplePreceedingComments.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "fn", "kind": 6, "location": { - "uri": "./_cases/multiplePreceedingComments.php" + "uri": "./multiplePreceedingComments.php" }, "containerName": "Foo" }, diff --git a/validation/frameworks/_cases/nameToken.php.expected.json b/validation/frameworks/_cases/nameToken.php.expected.json index 836cf207..42b9a084 100644 --- a/validation/frameworks/_cases/nameToken.php.expected.json +++ b/validation/frameworks/_cases/nameToken.php.expected.json @@ -10,7 +10,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/nameToken.php" + "uri": "./nameToken.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/nameToken.php" + "uri": "./nameToken.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/namespaces2.php.expected.json b/validation/frameworks/_cases/namespaces2.php.expected.json index b3f73eb0..d4b40342 100644 --- a/validation/frameworks/_cases/namespaces2.php.expected.json +++ b/validation/frameworks/_cases/namespaces2.php.expected.json @@ -1,16 +1,16 @@ { "references": { "NS1\\C": [ - "./_cases/namespaces2.php" + "./namespaces2.php" ], "NS1": [ - "./_cases/namespaces2.php" + "./namespaces2.php" ], "NS1\\I": [ - "./_cases/namespaces2.php" + "./namespaces2.php" ], "NS1\\T": [ - "./_cases/namespaces2.php" + "./namespaces2.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace1", "kind": 3, "location": { - "uri": "./_cases/namespaces2.php" + "uri": "./namespaces2.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/namespaces4.php.expected.json b/validation/frameworks/_cases/namespaces4.php.expected.json index 6d3d4ca9..a15b0a91 100644 --- a/validation/frameworks/_cases/namespaces4.php.expected.json +++ b/validation/frameworks/_cases/namespaces4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "a\\b": [ - "./_cases/namespaces4.php" + "./namespaces4.php" ], "a": [ - "./_cases/namespaces4.php" + "./namespaces4.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/namespaces5.php.expected.json b/validation/frameworks/_cases/namespaces5.php.expected.json index ef19aef0..8c0b27db 100644 --- a/validation/frameworks/_cases/namespaces5.php.expected.json +++ b/validation/frameworks/_cases/namespaces5.php.expected.json @@ -1,25 +1,25 @@ { "references": { "LanguageServer\\Protocol": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer\\Protocol\\TextDocumentIdentifier": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer\\Protocol\\Position": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer\\Protocol\\ReferenceContext": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer\\Protocol\\Location": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ], "LanguageServer\\Protocol\\Range": [ - "./_cases/namespaces5.php" + "./namespaces5.php" ] }, "definitions": { @@ -32,7 +32,7 @@ "name": "B", "kind": 3, "location": { - "uri": "./_cases/namespaces5.php" + "uri": "./namespaces5.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/namespaces6.php.expected.json b/validation/frameworks/_cases/namespaces6.php.expected.json index 0acbf4a7..6a3fa818 100644 --- a/validation/frameworks/_cases/namespaces6.php.expected.json +++ b/validation/frameworks/_cases/namespaces6.php.expected.json @@ -10,7 +10,7 @@ "name": "A\\B", "kind": 3, "location": { - "uri": "./_cases/namespaces6.php" + "uri": "./namespaces6.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/namespaces8.php.expected.json b/validation/frameworks/_cases/namespaces8.php.expected.json index ec654b61..20dd6fca 100644 --- a/validation/frameworks/_cases/namespaces8.php.expected.json +++ b/validation/frameworks/_cases/namespaces8.php.expected.json @@ -1,7 +1,7 @@ { "references": { "LanguageServer": [ - "./_cases/namespaces8.php" + "./namespaces8.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "LanguageServer\\Tests\\Utils", "kind": 3, "location": { - "uri": "./_cases/namespaces8.php" + "uri": "./namespaces8.php" }, "containerName": "LanguageServer\\Tests" }, diff --git a/validation/frameworks/_cases/objectCreation.php.expected.json b/validation/frameworks/_cases/objectCreation.php.expected.json index 070a8f76..2a1cfa7a 100644 --- a/validation/frameworks/_cases/objectCreation.php.expected.json +++ b/validation/frameworks/_cases/objectCreation.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->inline_diff_renderer": [ - "./_cases/objectCreation.php" + "./objectCreation.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/objectCreation.php" + "uri": "./objectCreation.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/objectCreation.php" + "uri": "./objectCreation.php" }, "containerName": "MyNamespace" }, @@ -46,7 +46,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/objectCreation.php" + "uri": "./objectCreation.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/objectCreation2.php.expected.json b/validation/frameworks/_cases/objectCreation2.php.expected.json index e887559b..3968842f 100644 --- a/validation/frameworks/_cases/objectCreation2.php.expected.json +++ b/validation/frameworks/_cases/objectCreation2.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B->hi()": [ - "./_cases/objectCreation2.php" + "./objectCreation2.php" ], "MyNamespace\\B": [ - "./_cases/objectCreation2.php" + "./objectCreation2.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/objectCreation2.php" + "uri": "./objectCreation2.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/objectCreation2.php" + "uri": "./objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/objectCreation2.php" + "uri": "./objectCreation2.php" }, "containerName": "MyNamespace" }, @@ -65,7 +65,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/objectCreation2.php" + "uri": "./objectCreation2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/objectCreation3.php.expected.json b/validation/frameworks/_cases/objectCreation3.php.expected.json index 745f5d4f..a411754d 100644 --- a/validation/frameworks/_cases/objectCreation3.php.expected.json +++ b/validation/frameworks/_cases/objectCreation3.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A->args": [ - "./_cases/objectCreation3.php" + "./objectCreation3.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/objectCreation3.php" + "uri": "./objectCreation3.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/objectCreation3.php" + "uri": "./objectCreation3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/param1.php.expected.json b/validation/frameworks/_cases/param1.php.expected.json index c086acc1..c3f977e3 100644 --- a/validation/frameworks/_cases/param1.php.expected.json +++ b/validation/frameworks/_cases/param1.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\Hi": [ - "./_cases/param1.php" + "./param1.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/param1.php" + "uri": "./param1.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "init", "kind": 12, "location": { - "uri": "./_cases/param1.php" + "uri": "./param1.php" }, "containerName": "MyNamespace" }, diff --git a/validation/frameworks/_cases/parent1.php.expected.json b/validation/frameworks/_cases/parent1.php.expected.json index 2503280b..dfe8caa5 100644 --- a/validation/frameworks/_cases/parent1.php.expected.json +++ b/validation/frameworks/_cases/parent1.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "./_cases/parent1.php" + "./parent1.php" ], "parent": [ - "./_cases/parent1.php" + "./parent1.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/parent1.php" + "uri": "./parent1.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/parent1.php" + "uri": "./parent1.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/parent1.php" + "uri": "./parent1.php" }, "containerName": "MyNamespace\\B" }, @@ -68,7 +68,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/parent1.php" + "uri": "./parent1.php" }, "containerName": "MyNamespace" }, @@ -84,7 +84,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/parent1.php" + "uri": "./parent1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/parent3.php.expected.json b/validation/frameworks/_cases/parent3.php.expected.json index 37e227f9..9065e301 100644 --- a/validation/frameworks/_cases/parent3.php.expected.json +++ b/validation/frameworks/_cases/parent3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/parent3.php" + "./parent3.php" ], "MyNamespace\\B->b()": [ - "./_cases/parent3.php" + "./parent3.php" ], "parent": [ - "./_cases/parent3.php" + "./parent3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/parent3.php" + "uri": "./parent3.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/parent3.php" + "uri": "./parent3.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/parent3.php" + "uri": "./parent3.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/parent3.php" + "uri": "./parent3.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/parent3.php" + "uri": "./parent3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/propertyName1.php.expected.json b/validation/frameworks/_cases/propertyName1.php.expected.json index 56d754c7..a79f79ce 100644 --- a/validation/frameworks/_cases/propertyName1.php.expected.json +++ b/validation/frameworks/_cases/propertyName1.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "./_cases/propertyName1.php" + "uri": "./propertyName1.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "./_cases/propertyName1.php" + "uri": "./propertyName1.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/_cases/propertyName2.php.expected.json b/validation/frameworks/_cases/propertyName2.php.expected.json index 7adeceed..45c54a7c 100644 --- a/validation/frameworks/_cases/propertyName2.php.expected.json +++ b/validation/frameworks/_cases/propertyName2.php.expected.json @@ -10,7 +10,7 @@ "name": "MyClass", "kind": 5, "location": { - "uri": "./_cases/propertyName2.php" + "uri": "./propertyName2.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "mainPropertyName", "kind": 7, "location": { - "uri": "./_cases/propertyName2.php" + "uri": "./propertyName2.php" }, "containerName": "MyClass" }, diff --git a/validation/frameworks/_cases/returnType.php.expected.json b/validation/frameworks/_cases/returnType.php.expected.json index aa495886..e131837d 100644 --- a/validation/frameworks/_cases/returnType.php.expected.json +++ b/validation/frameworks/_cases/returnType.php.expected.json @@ -1,10 +1,10 @@ { "references": { "TestNamespace\\TestClass": [ - "./_cases/returnType.php" + "./returnType.php" ], "TestNamespace\\TestClass2": [ - "./_cases/returnType.php" + "./returnType.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "TestNamespace", "kind": 3, "location": { - "uri": "./_cases/returnType.php" + "uri": "./returnType.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "whatever", "kind": 12, "location": { - "uri": "./_cases/returnType.php" + "uri": "./returnType.php" }, "containerName": "TestNamespace" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json index 6968698a..9d3864bc 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\A::a()": [ - "./_cases/scopedPropertyAccess.php" + "./scopedPropertyAccess.php" ], "MyNamespace\\A": [ - "./_cases/scopedPropertyAccess.php" + "./scopedPropertyAccess.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/scopedPropertyAccess.php" + "uri": "./scopedPropertyAccess.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/scopedPropertyAccess.php" + "uri": "./scopedPropertyAccess.php" }, "containerName": "MyNamespace" }, @@ -49,7 +49,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/scopedPropertyAccess.php" + "uri": "./scopedPropertyAccess.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json index 11b62678..9b009519 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A": [ - "./_cases/scopedPropertyAccess2.php" + "./scopedPropertyAccess2.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/scopedPropertyAccess2.php" + "uri": "./scopedPropertyAccess2.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json index fe417b37..990f3819 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json @@ -1,10 +1,10 @@ { "references": { "A": [ - "./_cases/scopedPropertyAccess3.php" + "./scopedPropertyAccess3.php" ], "A::$a": [ - "./_cases/scopedPropertyAccess3.php" + "./scopedPropertyAccess3.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/scopedPropertyAccess3.php" + "uri": "./scopedPropertyAccess3.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "a", "kind": 7, "location": { - "uri": "./_cases/scopedPropertyAccess3.php" + "uri": "./scopedPropertyAccess3.php" }, "containerName": "A" }, diff --git a/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json index bcf1489c..d349d058 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json @@ -1,7 +1,7 @@ { "references": { "A": [ - "./_cases/scopedPropertyAccess4.php" + "./scopedPropertyAccess4.php" ] }, "definitions": [] diff --git a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json index b88e83ec..1f3f3df3 100644 --- a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json +++ b/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json @@ -1,16 +1,16 @@ { "references": { "TestInterface": [ - "./_cases/scopedPropertyAccess5.php" + "./scopedPropertyAccess5.php" ], "TestClass": [ - "./_cases/scopedPropertyAccess5.php" + "./scopedPropertyAccess5.php" ], "TestClass::$testProperty": [ - "./_cases/scopedPropertyAccess5.php" + "./scopedPropertyAccess5.php" ], "TestClass::$staticTestProperty": [ - "./_cases/scopedPropertyAccess5.php" + "./scopedPropertyAccess5.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "TestClass", "kind": 5, "location": { - "uri": "./_cases/scopedPropertyAccess5.php" + "uri": "./scopedPropertyAccess5.php" }, "containerName": "" }, @@ -39,7 +39,7 @@ "name": "testProperty", "kind": 7, "location": { - "uri": "./_cases/scopedPropertyAccess5.php" + "uri": "./scopedPropertyAccess5.php" }, "containerName": "TestClass" }, diff --git a/validation/frameworks/_cases/self1.php.expected.json b/validation/frameworks/_cases/self1.php.expected.json index d6c1ccda..6d569d35 100644 --- a/validation/frameworks/_cases/self1.php.expected.json +++ b/validation/frameworks/_cases/self1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/self1.php" + "./self1.php" ], "MyNamespace\\A::b()": [ - "./_cases/self1.php" + "./self1.php" ], "self": [ - "./_cases/self1.php" + "./self1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/self1.php" + "uri": "./self1.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/self1.php" + "uri": "./self1.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/self1.php" + "uri": "./self1.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/self1.php" + "uri": "./self1.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/self1.php" + "uri": "./self1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self2.php.expected.json b/validation/frameworks/_cases/self2.php.expected.json index 4416af5b..425e911f 100644 --- a/validation/frameworks/_cases/self2.php.expected.json +++ b/validation/frameworks/_cases/self2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/self2.php" + "./self2.php" ], "MyNamespace\\A::b()": [ - "./_cases/self2.php" + "./self2.php" ], "self": [ - "./_cases/self2.php" + "./self2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/self2.php" + "uri": "./self2.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/self2.php" + "uri": "./self2.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/self2.php" + "uri": "./self2.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/self2.php" + "uri": "./self2.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/self2.php" + "uri": "./self2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self3.php.expected.json b/validation/frameworks/_cases/self3.php.expected.json index a75d4cdc..764a424c 100644 --- a/validation/frameworks/_cases/self3.php.expected.json +++ b/validation/frameworks/_cases/self3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/self3.php" + "./self3.php" ], "MyNamespace\\A->b()": [ - "./_cases/self3.php" + "./self3.php" ], "self": [ - "./_cases/self3.php" + "./self3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/self3.php" + "uri": "./self3.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/self3.php" + "uri": "./self3.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/self3.php" + "uri": "./self3.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/self3.php" + "uri": "./self3.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/self3.php" + "uri": "./self3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self4.php.expected.json b/validation/frameworks/_cases/self4.php.expected.json index fe688f33..c055887e 100644 --- a/validation/frameworks/_cases/self4.php.expected.json +++ b/validation/frameworks/_cases/self4.php.expected.json @@ -1,16 +1,16 @@ { "references": { "self": [ - "./_cases/self4.php" + "./self4.php" ], "MyNamespace\\A->addTestFile()": [ - "./_cases/self4.php" + "./self4.php" ], "MyNamespace\\DS": [ - "./_cases/self4.php" + "./self4.php" ], "DS": [ - "./_cases/self4.php" + "./self4.php" ] }, "definitions": { @@ -23,7 +23,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/self4.php" + "uri": "./self4.php" }, "containerName": "" }, @@ -39,7 +39,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/self4.php" + "uri": "./self4.php" }, "containerName": "MyNamespace" }, @@ -55,7 +55,7 @@ "name": "suite", "kind": 6, "location": { - "uri": "./_cases/self4.php" + "uri": "./self4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/self5.php.expected.json b/validation/frameworks/_cases/self5.php.expected.json index 914cf1b7..5cf42dd5 100644 --- a/validation/frameworks/_cases/self5.php.expected.json +++ b/validation/frameworks/_cases/self5.php.expected.json @@ -1,7 +1,7 @@ { "references": { "MyNamespace\\A->assertTrue()": [ - "./_cases/self5.php" + "./self5.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/self5.php" + "uri": "./self5.php" }, "containerName": "" }, @@ -30,7 +30,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/self5.php" + "uri": "./self5.php" }, "containerName": "MyNamespace" }, @@ -46,7 +46,7 @@ "name": "typesProvider", "kind": 6, "location": { - "uri": "./_cases/self5.php" + "uri": "./self5.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static1.php.expected.json b/validation/frameworks/_cases/static1.php.expected.json index 3a7ddcc7..14a117a9 100644 --- a/validation/frameworks/_cases/static1.php.expected.json +++ b/validation/frameworks/_cases/static1.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/static1.php" + "./static1.php" ], "MyNamespace\\A::b()": [ - "./_cases/static1.php" + "./static1.php" ], "static": [ - "./_cases/static1.php" + "./static1.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/static1.php" + "uri": "./static1.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/static1.php" + "uri": "./static1.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/static1.php" + "uri": "./static1.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/static1.php" + "uri": "./static1.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/static1.php" + "uri": "./static1.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static2.php.expected.json b/validation/frameworks/_cases/static2.php.expected.json index 73dbf9bf..cc8d400e 100644 --- a/validation/frameworks/_cases/static2.php.expected.json +++ b/validation/frameworks/_cases/static2.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/static2.php" + "./static2.php" ], "MyNamespace\\A::b()": [ - "./_cases/static2.php" + "./static2.php" ], "static": [ - "./_cases/static2.php" + "./static2.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/static2.php" + "uri": "./static2.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/static2.php" + "uri": "./static2.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/static2.php" + "uri": "./static2.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/static2.php" + "uri": "./static2.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/static2.php" + "uri": "./static2.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static3.php.expected.json b/validation/frameworks/_cases/static3.php.expected.json index 265a93b8..c70f6a25 100644 --- a/validation/frameworks/_cases/static3.php.expected.json +++ b/validation/frameworks/_cases/static3.php.expected.json @@ -1,13 +1,13 @@ { "references": { "MyNamespace\\B": [ - "./_cases/static3.php" + "./static3.php" ], "MyNamespace\\b()": [ - "./_cases/static3.php" + "./static3.php" ], "b()": [ - "./_cases/static3.php" + "./static3.php" ] }, "definitions": { @@ -20,7 +20,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/static3.php" + "uri": "./static3.php" }, "containerName": "" }, @@ -36,7 +36,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/static3.php" + "uri": "./static3.php" }, "containerName": "MyNamespace" }, @@ -52,7 +52,7 @@ "name": "b", "kind": 6, "location": { - "uri": "./_cases/static3.php" + "uri": "./static3.php" }, "containerName": "MyNamespace\\B" }, @@ -71,7 +71,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/static3.php" + "uri": "./static3.php" }, "containerName": "MyNamespace" }, @@ -87,7 +87,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/static3.php" + "uri": "./static3.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/static4.php.expected.json b/validation/frameworks/_cases/static4.php.expected.json index d0b6aa96..6ca8f974 100644 --- a/validation/frameworks/_cases/static4.php.expected.json +++ b/validation/frameworks/_cases/static4.php.expected.json @@ -1,10 +1,10 @@ { "references": { "MyNamespace\\B": [ - "./_cases/static4.php" + "./static4.php" ], "static": [ - "./_cases/static4.php" + "./static4.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "MyNamespace", "kind": 3, "location": { - "uri": "./_cases/static4.php" + "uri": "./static4.php" }, "containerName": "" }, @@ -35,7 +35,7 @@ "name": "A", "kind": 5, "location": { - "uri": "./_cases/static4.php" + "uri": "./static4.php" }, "containerName": "MyNamespace" }, @@ -51,7 +51,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/static4.php" + "uri": "./static4.php" }, "containerName": "MyNamespace\\A" }, diff --git a/validation/frameworks/_cases/stringVariable.php.expected.json b/validation/frameworks/_cases/stringVariable.php.expected.json index 6afd5c23..569bdc95 100644 --- a/validation/frameworks/_cases/stringVariable.php.expected.json +++ b/validation/frameworks/_cases/stringVariable.php.expected.json @@ -10,7 +10,7 @@ "name": "B", "kind": 5, "location": { - "uri": "./_cases/stringVariable.php" + "uri": "./stringVariable.php" }, "containerName": "" }, @@ -26,7 +26,7 @@ "name": "hi", "kind": 7, "location": { - "uri": "./_cases/stringVariable.php" + "uri": "./stringVariable.php" }, "containerName": "B" }, @@ -43,7 +43,7 @@ "name": "a", "kind": 6, "location": { - "uri": "./_cases/stringVariable.php" + "uri": "./stringVariable.php" }, "containerName": "B" }, diff --git a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json index 96cc2b83..0c7a37ce 100644 --- a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -1,7 +1,7 @@ { "references": { "NameOutsideOfNamespace": [ - "./_cases/testQualifiedNameOutsideOfNamespace.php" + "./testQualifiedNameOutsideOfNamespace.php" ] }, "definitions": { @@ -14,7 +14,7 @@ "name": "SomeNamespace", "kind": 3, "location": { - "uri": "./_cases/testQualifiedNameOutsideOfNamespace.php" + "uri": "./testQualifiedNameOutsideOfNamespace.php" }, "containerName": "" }, diff --git a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json index 42ef6d71..1fefbf78 100644 --- a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json +++ b/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json @@ -1,10 +1,10 @@ { "references": { "CURLAUTH_BASIC": [ - "./_cases/verifyFqsenOnClassProperty.php" + "./verifyFqsenOnClassProperty.php" ], "Foo->bar": [ - "./_cases/verifyFqsenOnClassProperty.php" + "./verifyFqsenOnClassProperty.php" ] }, "definitions": { @@ -17,7 +17,7 @@ "name": "Foo", "kind": 5, "location": { - "uri": "./_cases/verifyFqsenOnClassProperty.php" + "uri": "./verifyFqsenOnClassProperty.php" }, "containerName": "" }, @@ -33,7 +33,7 @@ "name": "bar", "kind": 7, "location": { - "uri": "./_cases/verifyFqsenOnClassProperty.php" + "uri": "./verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, @@ -50,7 +50,7 @@ "name": "foo", "kind": 6, "location": { - "uri": "./_cases/verifyFqsenOnClassProperty.php" + "uri": "./verifyFqsenOnClassProperty.php" }, "containerName": "Foo" }, From 586b0d6baf09a4bb903f0962a4fbec979aff0dac Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 14:01:19 -0700 Subject: [PATCH 130/149] Move validation testcases out of frameworks folder --- tests/Validation/ValidationTest.php | 4 ++-- .../_cases => tests/Validation/cases}/WithReturnTypehints.php | 0 .../Validation/cases}/WithReturnTypehints.php.expected.json | 0 .../cases}/anonymousClassMembersShouldNotBeSymbols.php | 0 .../anonymousClassMembersShouldNotBeSymbols.php.expected.json | 0 .../Validation/cases}/arrayValueShouldBeBoolean.php | 0 .../cases}/arrayValueShouldBeBoolean.php.expected.json | 0 .../_cases => tests/Validation/cases}/caseStatement1.php | 0 .../Validation/cases}/caseStatement1.php.expected.json | 0 .../_cases => tests/Validation/cases}/classDefinition1.php | 0 .../Validation/cases}/classDefinition1.php.expected.json | 0 .../_cases => tests/Validation/cases}/classProperty1.php | 0 .../Validation/cases}/classProperty1.php.expected.json | 0 .../_cases => tests/Validation/cases}/constants.php | 0 .../Validation/cases}/constants.php.expected.json | 0 .../_cases => tests/Validation/cases}/constants2.php | 0 .../Validation/cases}/constants2.php.expected.json | 0 .../_cases => tests/Validation/cases}/constants3.php | 0 .../Validation/cases}/constants3.php.expected.json | 0 .../_cases => tests/Validation/cases}/constants4.php | 0 .../Validation/cases}/constants4.php.expected.json | 0 .../_cases => tests/Validation/cases}/constants5.php | 0 .../Validation/cases}/constants5.php.expected.json | 0 .../Validation/cases}/constantsInFunctionParamDefault.php | 0 .../cases}/constantsInFunctionParamDefault.php.expected.json | 0 .../Validation/cases}/docBlocksOnNamespaceDefinition.php | 0 .../cases}/docBlocksOnNamespaceDefinition.php.expected.json | 0 .../_cases => tests/Validation/cases}/exceptions1.php | 0 .../Validation/cases}/exceptions1.php.expected.json | 0 .../_cases => tests/Validation/cases}/forLoopReference1.php | 0 .../Validation/cases}/forLoopReference1.php.expected.json | 0 .../_cases => tests/Validation/cases}/functionUse.php | 0 .../Validation/cases}/functionUse.php.expected.json | 0 .../_cases => tests/Validation/cases}/functionUse2.php | 0 .../Validation/cases}/functionUse2.php.expected.json | 0 .../_cases => tests/Validation/cases}/ifStatement1.php | 0 .../Validation/cases}/ifStatement1.php.expected.json | 0 .../_cases => tests/Validation/cases}/interfaceProperty.php | 0 .../Validation/cases}/interfaceProperty.php.expected.json | 0 .../Validation/cases}/magicConstantsShouldBeGlobal.php | 0 .../cases}/magicConstantsShouldBeGlobal.php.expected.json | 0 .../_cases => tests/Validation/cases}/magicConsts.php | 0 .../Validation/cases}/magicConsts.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberAccess1.php | 0 .../Validation/cases}/memberAccess1.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberAccess2.php | 0 .../Validation/cases}/memberAccess2.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberAccess3.php | 0 .../Validation/cases}/memberAccess3.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberAccess4.php | 0 .../Validation/cases}/memberAccess4.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberAccess5.php | 0 .../Validation/cases}/memberAccess5.php.expected.json | 0 .../_cases => tests/Validation/cases}/memberCall1.php | 0 .../Validation/cases}/memberCall1.php.expected.json | 0 .../_cases => tests/Validation/cases}/multipleNamespaces.php | 0 .../Validation/cases}/multipleNamespaces.php.expected.json | 0 .../Validation/cases}/multiplePreceedingComments.php | 0 .../cases}/multiplePreceedingComments.php.expected.json | 0 .../_cases => tests/Validation/cases}/nameToken.php | 0 .../Validation/cases}/nameToken.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces2.php | 0 .../Validation/cases}/namespaces2.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces3.php | 0 .../Validation/cases}/namespaces3.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces4.php | 0 .../Validation/cases}/namespaces4.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces5.php | 0 .../Validation/cases}/namespaces5.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces6.php | 0 .../Validation/cases}/namespaces6.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces7.php | 0 .../Validation/cases}/namespaces7.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces8.php | 0 .../Validation/cases}/namespaces8.php.expected.json | 0 .../_cases => tests/Validation/cases}/namespaces9.php | 0 .../Validation/cases}/namespaces9.php.expected.json | 0 .../_cases => tests/Validation/cases}/newStatic.php | 0 .../Validation/cases}/newStatic.php.expected.json | 0 .../_cases => tests/Validation/cases}/objectCreation.php | 0 .../Validation/cases}/objectCreation.php.expected.json | 0 .../_cases => tests/Validation/cases}/objectCreation2.php | 0 .../Validation/cases}/objectCreation2.php.expected.json | 0 .../_cases => tests/Validation/cases}/objectCreation3.php | 0 .../Validation/cases}/objectCreation3.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/param1.php | 0 .../Validation/cases}/param1.php.expected.json | 0 .../Validation/cases}/parameterTypeResolution1.php | 0 .../cases}/parameterTypeResolution1.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/parent1.php | 0 .../Validation/cases}/parent1.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/parent2.php | 0 .../Validation/cases}/parent2.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/parent3.php | 0 .../Validation/cases}/parent3.php.expected.json | 0 .../_cases => tests/Validation/cases}/propertyName1.php | 0 .../Validation/cases}/propertyName1.php.expected.json | 0 .../_cases => tests/Validation/cases}/propertyName2.php | 0 .../Validation/cases}/propertyName2.php.expected.json | 0 .../_cases => tests/Validation/cases}/returnType.php | 0 .../Validation/cases}/returnType.php.expected.json | 0 .../Validation/cases}/scopedPropertyAccess.php | 0 .../Validation/cases}/scopedPropertyAccess.php.expected.json | 0 .../Validation/cases}/scopedPropertyAccess2.php | 0 .../Validation/cases}/scopedPropertyAccess2.php.expected.json | 0 .../Validation/cases}/scopedPropertyAccess3.php | 0 .../Validation/cases}/scopedPropertyAccess3.php.expected.json | 0 .../Validation/cases}/scopedPropertyAccess4.php | 0 .../Validation/cases}/scopedPropertyAccess4.php.expected.json | 0 .../Validation/cases}/scopedPropertyAccess5.php | 0 .../Validation/cases}/scopedPropertyAccess5.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/self1.php | 0 .../_cases => tests/Validation/cases}/self1.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/self2.php | 0 .../_cases => tests/Validation/cases}/self2.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/self3.php | 0 .../_cases => tests/Validation/cases}/self3.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/self4.php | 0 .../_cases => tests/Validation/cases}/self4.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/self5.php | 0 .../_cases => tests/Validation/cases}/self5.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/static1.php | 0 .../Validation/cases}/static1.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/static2.php | 0 .../Validation/cases}/static2.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/static3.php | 0 .../Validation/cases}/static3.php.expected.json | 0 .../frameworks/_cases => tests/Validation/cases}/static4.php | 0 .../Validation/cases}/static4.php.expected.json | 0 .../_cases => tests/Validation/cases}/staticInArray.php | 0 .../Validation/cases}/staticInArray.php.expected.json | 0 .../_cases => tests/Validation/cases}/stringVariable.php | 0 .../Validation/cases}/stringVariable.php.expected.json | 0 .../Validation/cases}/testQualifiedNameOutsideOfNamespace.php | 0 .../testQualifiedNameOutsideOfNamespace.php.expected.json | 0 .../Validation/cases}/verifyFqsenOnClassProperty.php | 0 .../cases}/verifyFqsenOnClassProperty.php.expected.json | 0 137 files changed, 2 insertions(+), 2 deletions(-) rename {validation/frameworks/_cases => tests/Validation/cases}/WithReturnTypehints.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/WithReturnTypehints.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/anonymousClassMembersShouldNotBeSymbols.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/anonymousClassMembersShouldNotBeSymbols.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/arrayValueShouldBeBoolean.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/arrayValueShouldBeBoolean.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/caseStatement1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/caseStatement1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/classDefinition1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/classDefinition1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/classProperty1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/classProperty1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants5.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constants5.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constantsInFunctionParamDefault.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/constantsInFunctionParamDefault.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/docBlocksOnNamespaceDefinition.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/docBlocksOnNamespaceDefinition.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/exceptions1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/exceptions1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/forLoopReference1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/forLoopReference1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/functionUse.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/functionUse.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/functionUse2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/functionUse2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/ifStatement1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/ifStatement1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/interfaceProperty.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/interfaceProperty.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/magicConstantsShouldBeGlobal.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/magicConstantsShouldBeGlobal.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/magicConsts.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/magicConsts.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess5.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberAccess5.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberCall1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/memberCall1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/multipleNamespaces.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/multipleNamespaces.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/multiplePreceedingComments.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/multiplePreceedingComments.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/nameToken.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/nameToken.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces5.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces5.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces6.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces6.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces7.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces7.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces8.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces8.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces9.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/namespaces9.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/newStatic.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/newStatic.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/objectCreation3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/param1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/param1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parameterTypeResolution1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parameterTypeResolution1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/parent3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/propertyName1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/propertyName1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/propertyName2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/propertyName2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/returnType.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/returnType.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess5.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/scopedPropertyAccess5.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self5.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/self5.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static1.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static1.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static2.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static2.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static3.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static3.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static4.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/static4.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/staticInArray.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/staticInArray.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/stringVariable.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/stringVariable.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/testQualifiedNameOutsideOfNamespace.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/testQualifiedNameOutsideOfNamespace.php.expected.json (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/verifyFqsenOnClassProperty.php (100%) rename {validation/frameworks/_cases => tests/Validation/cases}/verifyFqsenOnClassProperty.php.expected.json (100%) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 2bbb5651..5253d210 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -26,7 +26,7 @@ class ValidationTest extends TestCase public function validationTestProvider() { $testProviderArray = array(); - $testCasesDir = realpath(__DIR__ . '/../../validation/frameworks/_cases'); + $testCasesDir = realpath(__DIR__ . '/cases'); $iterator = new RecursiveDirectoryIterator($testCasesDir); $disabled = json_decode(file_get_contents(__DIR__ . '/disabled.json')); @@ -100,7 +100,7 @@ private function getActualTestValues($filename, $fileContents): array ); // Turn references into relative paths - $testCasesDir = realpath(__DIR__ . '/../../validation/frameworks/_cases'); + $testCasesDir = realpath(__DIR__ . '/cases'); foreach ($refsAndDefs['references'] as $key => $list) { $fixedPathRefs = array_map(function ($ref) use ($testCasesDir) { return str_replace($testCasesDir, '.', $ref); diff --git a/validation/frameworks/_cases/WithReturnTypehints.php b/tests/Validation/cases/WithReturnTypehints.php similarity index 100% rename from validation/frameworks/_cases/WithReturnTypehints.php rename to tests/Validation/cases/WithReturnTypehints.php diff --git a/validation/frameworks/_cases/WithReturnTypehints.php.expected.json b/tests/Validation/cases/WithReturnTypehints.php.expected.json similarity index 100% rename from validation/frameworks/_cases/WithReturnTypehints.php.expected.json rename to tests/Validation/cases/WithReturnTypehints.php.expected.json diff --git a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php similarity index 100% rename from validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php rename to tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php diff --git a/validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json similarity index 100% rename from validation/frameworks/_cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json rename to tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json diff --git a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php b/tests/Validation/cases/arrayValueShouldBeBoolean.php similarity index 100% rename from validation/frameworks/_cases/arrayValueShouldBeBoolean.php rename to tests/Validation/cases/arrayValueShouldBeBoolean.php diff --git a/validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json b/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json similarity index 100% rename from validation/frameworks/_cases/arrayValueShouldBeBoolean.php.expected.json rename to tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json diff --git a/validation/frameworks/_cases/caseStatement1.php b/tests/Validation/cases/caseStatement1.php similarity index 100% rename from validation/frameworks/_cases/caseStatement1.php rename to tests/Validation/cases/caseStatement1.php diff --git a/validation/frameworks/_cases/caseStatement1.php.expected.json b/tests/Validation/cases/caseStatement1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/caseStatement1.php.expected.json rename to tests/Validation/cases/caseStatement1.php.expected.json diff --git a/validation/frameworks/_cases/classDefinition1.php b/tests/Validation/cases/classDefinition1.php similarity index 100% rename from validation/frameworks/_cases/classDefinition1.php rename to tests/Validation/cases/classDefinition1.php diff --git a/validation/frameworks/_cases/classDefinition1.php.expected.json b/tests/Validation/cases/classDefinition1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/classDefinition1.php.expected.json rename to tests/Validation/cases/classDefinition1.php.expected.json diff --git a/validation/frameworks/_cases/classProperty1.php b/tests/Validation/cases/classProperty1.php similarity index 100% rename from validation/frameworks/_cases/classProperty1.php rename to tests/Validation/cases/classProperty1.php diff --git a/validation/frameworks/_cases/classProperty1.php.expected.json b/tests/Validation/cases/classProperty1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/classProperty1.php.expected.json rename to tests/Validation/cases/classProperty1.php.expected.json diff --git a/validation/frameworks/_cases/constants.php b/tests/Validation/cases/constants.php similarity index 100% rename from validation/frameworks/_cases/constants.php rename to tests/Validation/cases/constants.php diff --git a/validation/frameworks/_cases/constants.php.expected.json b/tests/Validation/cases/constants.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constants.php.expected.json rename to tests/Validation/cases/constants.php.expected.json diff --git a/validation/frameworks/_cases/constants2.php b/tests/Validation/cases/constants2.php similarity index 100% rename from validation/frameworks/_cases/constants2.php rename to tests/Validation/cases/constants2.php diff --git a/validation/frameworks/_cases/constants2.php.expected.json b/tests/Validation/cases/constants2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constants2.php.expected.json rename to tests/Validation/cases/constants2.php.expected.json diff --git a/validation/frameworks/_cases/constants3.php b/tests/Validation/cases/constants3.php similarity index 100% rename from validation/frameworks/_cases/constants3.php rename to tests/Validation/cases/constants3.php diff --git a/validation/frameworks/_cases/constants3.php.expected.json b/tests/Validation/cases/constants3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constants3.php.expected.json rename to tests/Validation/cases/constants3.php.expected.json diff --git a/validation/frameworks/_cases/constants4.php b/tests/Validation/cases/constants4.php similarity index 100% rename from validation/frameworks/_cases/constants4.php rename to tests/Validation/cases/constants4.php diff --git a/validation/frameworks/_cases/constants4.php.expected.json b/tests/Validation/cases/constants4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constants4.php.expected.json rename to tests/Validation/cases/constants4.php.expected.json diff --git a/validation/frameworks/_cases/constants5.php b/tests/Validation/cases/constants5.php similarity index 100% rename from validation/frameworks/_cases/constants5.php rename to tests/Validation/cases/constants5.php diff --git a/validation/frameworks/_cases/constants5.php.expected.json b/tests/Validation/cases/constants5.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constants5.php.expected.json rename to tests/Validation/cases/constants5.php.expected.json diff --git a/validation/frameworks/_cases/constantsInFunctionParamDefault.php b/tests/Validation/cases/constantsInFunctionParamDefault.php similarity index 100% rename from validation/frameworks/_cases/constantsInFunctionParamDefault.php rename to tests/Validation/cases/constantsInFunctionParamDefault.php diff --git a/validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json b/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json similarity index 100% rename from validation/frameworks/_cases/constantsInFunctionParamDefault.php.expected.json rename to tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json diff --git a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php similarity index 100% rename from validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php rename to tests/Validation/cases/docBlocksOnNamespaceDefinition.php diff --git a/validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json similarity index 100% rename from validation/frameworks/_cases/docBlocksOnNamespaceDefinition.php.expected.json rename to tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json diff --git a/validation/frameworks/_cases/exceptions1.php b/tests/Validation/cases/exceptions1.php similarity index 100% rename from validation/frameworks/_cases/exceptions1.php rename to tests/Validation/cases/exceptions1.php diff --git a/validation/frameworks/_cases/exceptions1.php.expected.json b/tests/Validation/cases/exceptions1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/exceptions1.php.expected.json rename to tests/Validation/cases/exceptions1.php.expected.json diff --git a/validation/frameworks/_cases/forLoopReference1.php b/tests/Validation/cases/forLoopReference1.php similarity index 100% rename from validation/frameworks/_cases/forLoopReference1.php rename to tests/Validation/cases/forLoopReference1.php diff --git a/validation/frameworks/_cases/forLoopReference1.php.expected.json b/tests/Validation/cases/forLoopReference1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/forLoopReference1.php.expected.json rename to tests/Validation/cases/forLoopReference1.php.expected.json diff --git a/validation/frameworks/_cases/functionUse.php b/tests/Validation/cases/functionUse.php similarity index 100% rename from validation/frameworks/_cases/functionUse.php rename to tests/Validation/cases/functionUse.php diff --git a/validation/frameworks/_cases/functionUse.php.expected.json b/tests/Validation/cases/functionUse.php.expected.json similarity index 100% rename from validation/frameworks/_cases/functionUse.php.expected.json rename to tests/Validation/cases/functionUse.php.expected.json diff --git a/validation/frameworks/_cases/functionUse2.php b/tests/Validation/cases/functionUse2.php similarity index 100% rename from validation/frameworks/_cases/functionUse2.php rename to tests/Validation/cases/functionUse2.php diff --git a/validation/frameworks/_cases/functionUse2.php.expected.json b/tests/Validation/cases/functionUse2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/functionUse2.php.expected.json rename to tests/Validation/cases/functionUse2.php.expected.json diff --git a/validation/frameworks/_cases/ifStatement1.php b/tests/Validation/cases/ifStatement1.php similarity index 100% rename from validation/frameworks/_cases/ifStatement1.php rename to tests/Validation/cases/ifStatement1.php diff --git a/validation/frameworks/_cases/ifStatement1.php.expected.json b/tests/Validation/cases/ifStatement1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/ifStatement1.php.expected.json rename to tests/Validation/cases/ifStatement1.php.expected.json diff --git a/validation/frameworks/_cases/interfaceProperty.php b/tests/Validation/cases/interfaceProperty.php similarity index 100% rename from validation/frameworks/_cases/interfaceProperty.php rename to tests/Validation/cases/interfaceProperty.php diff --git a/validation/frameworks/_cases/interfaceProperty.php.expected.json b/tests/Validation/cases/interfaceProperty.php.expected.json similarity index 100% rename from validation/frameworks/_cases/interfaceProperty.php.expected.json rename to tests/Validation/cases/interfaceProperty.php.expected.json diff --git a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php b/tests/Validation/cases/magicConstantsShouldBeGlobal.php similarity index 100% rename from validation/frameworks/_cases/magicConstantsShouldBeGlobal.php rename to tests/Validation/cases/magicConstantsShouldBeGlobal.php diff --git a/validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json b/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json similarity index 100% rename from validation/frameworks/_cases/magicConstantsShouldBeGlobal.php.expected.json rename to tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json diff --git a/validation/frameworks/_cases/magicConsts.php b/tests/Validation/cases/magicConsts.php similarity index 100% rename from validation/frameworks/_cases/magicConsts.php rename to tests/Validation/cases/magicConsts.php diff --git a/validation/frameworks/_cases/magicConsts.php.expected.json b/tests/Validation/cases/magicConsts.php.expected.json similarity index 100% rename from validation/frameworks/_cases/magicConsts.php.expected.json rename to tests/Validation/cases/magicConsts.php.expected.json diff --git a/validation/frameworks/_cases/memberAccess1.php b/tests/Validation/cases/memberAccess1.php similarity index 100% rename from validation/frameworks/_cases/memberAccess1.php rename to tests/Validation/cases/memberAccess1.php diff --git a/validation/frameworks/_cases/memberAccess1.php.expected.json b/tests/Validation/cases/memberAccess1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberAccess1.php.expected.json rename to tests/Validation/cases/memberAccess1.php.expected.json diff --git a/validation/frameworks/_cases/memberAccess2.php b/tests/Validation/cases/memberAccess2.php similarity index 100% rename from validation/frameworks/_cases/memberAccess2.php rename to tests/Validation/cases/memberAccess2.php diff --git a/validation/frameworks/_cases/memberAccess2.php.expected.json b/tests/Validation/cases/memberAccess2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberAccess2.php.expected.json rename to tests/Validation/cases/memberAccess2.php.expected.json diff --git a/validation/frameworks/_cases/memberAccess3.php b/tests/Validation/cases/memberAccess3.php similarity index 100% rename from validation/frameworks/_cases/memberAccess3.php rename to tests/Validation/cases/memberAccess3.php diff --git a/validation/frameworks/_cases/memberAccess3.php.expected.json b/tests/Validation/cases/memberAccess3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberAccess3.php.expected.json rename to tests/Validation/cases/memberAccess3.php.expected.json diff --git a/validation/frameworks/_cases/memberAccess4.php b/tests/Validation/cases/memberAccess4.php similarity index 100% rename from validation/frameworks/_cases/memberAccess4.php rename to tests/Validation/cases/memberAccess4.php diff --git a/validation/frameworks/_cases/memberAccess4.php.expected.json b/tests/Validation/cases/memberAccess4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberAccess4.php.expected.json rename to tests/Validation/cases/memberAccess4.php.expected.json diff --git a/validation/frameworks/_cases/memberAccess5.php b/tests/Validation/cases/memberAccess5.php similarity index 100% rename from validation/frameworks/_cases/memberAccess5.php rename to tests/Validation/cases/memberAccess5.php diff --git a/validation/frameworks/_cases/memberAccess5.php.expected.json b/tests/Validation/cases/memberAccess5.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberAccess5.php.expected.json rename to tests/Validation/cases/memberAccess5.php.expected.json diff --git a/validation/frameworks/_cases/memberCall1.php b/tests/Validation/cases/memberCall1.php similarity index 100% rename from validation/frameworks/_cases/memberCall1.php rename to tests/Validation/cases/memberCall1.php diff --git a/validation/frameworks/_cases/memberCall1.php.expected.json b/tests/Validation/cases/memberCall1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/memberCall1.php.expected.json rename to tests/Validation/cases/memberCall1.php.expected.json diff --git a/validation/frameworks/_cases/multipleNamespaces.php b/tests/Validation/cases/multipleNamespaces.php similarity index 100% rename from validation/frameworks/_cases/multipleNamespaces.php rename to tests/Validation/cases/multipleNamespaces.php diff --git a/validation/frameworks/_cases/multipleNamespaces.php.expected.json b/tests/Validation/cases/multipleNamespaces.php.expected.json similarity index 100% rename from validation/frameworks/_cases/multipleNamespaces.php.expected.json rename to tests/Validation/cases/multipleNamespaces.php.expected.json diff --git a/validation/frameworks/_cases/multiplePreceedingComments.php b/tests/Validation/cases/multiplePreceedingComments.php similarity index 100% rename from validation/frameworks/_cases/multiplePreceedingComments.php rename to tests/Validation/cases/multiplePreceedingComments.php diff --git a/validation/frameworks/_cases/multiplePreceedingComments.php.expected.json b/tests/Validation/cases/multiplePreceedingComments.php.expected.json similarity index 100% rename from validation/frameworks/_cases/multiplePreceedingComments.php.expected.json rename to tests/Validation/cases/multiplePreceedingComments.php.expected.json diff --git a/validation/frameworks/_cases/nameToken.php b/tests/Validation/cases/nameToken.php similarity index 100% rename from validation/frameworks/_cases/nameToken.php rename to tests/Validation/cases/nameToken.php diff --git a/validation/frameworks/_cases/nameToken.php.expected.json b/tests/Validation/cases/nameToken.php.expected.json similarity index 100% rename from validation/frameworks/_cases/nameToken.php.expected.json rename to tests/Validation/cases/nameToken.php.expected.json diff --git a/validation/frameworks/_cases/namespaces2.php b/tests/Validation/cases/namespaces2.php similarity index 100% rename from validation/frameworks/_cases/namespaces2.php rename to tests/Validation/cases/namespaces2.php diff --git a/validation/frameworks/_cases/namespaces2.php.expected.json b/tests/Validation/cases/namespaces2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces2.php.expected.json rename to tests/Validation/cases/namespaces2.php.expected.json diff --git a/validation/frameworks/_cases/namespaces3.php b/tests/Validation/cases/namespaces3.php similarity index 100% rename from validation/frameworks/_cases/namespaces3.php rename to tests/Validation/cases/namespaces3.php diff --git a/validation/frameworks/_cases/namespaces3.php.expected.json b/tests/Validation/cases/namespaces3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces3.php.expected.json rename to tests/Validation/cases/namespaces3.php.expected.json diff --git a/validation/frameworks/_cases/namespaces4.php b/tests/Validation/cases/namespaces4.php similarity index 100% rename from validation/frameworks/_cases/namespaces4.php rename to tests/Validation/cases/namespaces4.php diff --git a/validation/frameworks/_cases/namespaces4.php.expected.json b/tests/Validation/cases/namespaces4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces4.php.expected.json rename to tests/Validation/cases/namespaces4.php.expected.json diff --git a/validation/frameworks/_cases/namespaces5.php b/tests/Validation/cases/namespaces5.php similarity index 100% rename from validation/frameworks/_cases/namespaces5.php rename to tests/Validation/cases/namespaces5.php diff --git a/validation/frameworks/_cases/namespaces5.php.expected.json b/tests/Validation/cases/namespaces5.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces5.php.expected.json rename to tests/Validation/cases/namespaces5.php.expected.json diff --git a/validation/frameworks/_cases/namespaces6.php b/tests/Validation/cases/namespaces6.php similarity index 100% rename from validation/frameworks/_cases/namespaces6.php rename to tests/Validation/cases/namespaces6.php diff --git a/validation/frameworks/_cases/namespaces6.php.expected.json b/tests/Validation/cases/namespaces6.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces6.php.expected.json rename to tests/Validation/cases/namespaces6.php.expected.json diff --git a/validation/frameworks/_cases/namespaces7.php b/tests/Validation/cases/namespaces7.php similarity index 100% rename from validation/frameworks/_cases/namespaces7.php rename to tests/Validation/cases/namespaces7.php diff --git a/validation/frameworks/_cases/namespaces7.php.expected.json b/tests/Validation/cases/namespaces7.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces7.php.expected.json rename to tests/Validation/cases/namespaces7.php.expected.json diff --git a/validation/frameworks/_cases/namespaces8.php b/tests/Validation/cases/namespaces8.php similarity index 100% rename from validation/frameworks/_cases/namespaces8.php rename to tests/Validation/cases/namespaces8.php diff --git a/validation/frameworks/_cases/namespaces8.php.expected.json b/tests/Validation/cases/namespaces8.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces8.php.expected.json rename to tests/Validation/cases/namespaces8.php.expected.json diff --git a/validation/frameworks/_cases/namespaces9.php b/tests/Validation/cases/namespaces9.php similarity index 100% rename from validation/frameworks/_cases/namespaces9.php rename to tests/Validation/cases/namespaces9.php diff --git a/validation/frameworks/_cases/namespaces9.php.expected.json b/tests/Validation/cases/namespaces9.php.expected.json similarity index 100% rename from validation/frameworks/_cases/namespaces9.php.expected.json rename to tests/Validation/cases/namespaces9.php.expected.json diff --git a/validation/frameworks/_cases/newStatic.php b/tests/Validation/cases/newStatic.php similarity index 100% rename from validation/frameworks/_cases/newStatic.php rename to tests/Validation/cases/newStatic.php diff --git a/validation/frameworks/_cases/newStatic.php.expected.json b/tests/Validation/cases/newStatic.php.expected.json similarity index 100% rename from validation/frameworks/_cases/newStatic.php.expected.json rename to tests/Validation/cases/newStatic.php.expected.json diff --git a/validation/frameworks/_cases/objectCreation.php b/tests/Validation/cases/objectCreation.php similarity index 100% rename from validation/frameworks/_cases/objectCreation.php rename to tests/Validation/cases/objectCreation.php diff --git a/validation/frameworks/_cases/objectCreation.php.expected.json b/tests/Validation/cases/objectCreation.php.expected.json similarity index 100% rename from validation/frameworks/_cases/objectCreation.php.expected.json rename to tests/Validation/cases/objectCreation.php.expected.json diff --git a/validation/frameworks/_cases/objectCreation2.php b/tests/Validation/cases/objectCreation2.php similarity index 100% rename from validation/frameworks/_cases/objectCreation2.php rename to tests/Validation/cases/objectCreation2.php diff --git a/validation/frameworks/_cases/objectCreation2.php.expected.json b/tests/Validation/cases/objectCreation2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/objectCreation2.php.expected.json rename to tests/Validation/cases/objectCreation2.php.expected.json diff --git a/validation/frameworks/_cases/objectCreation3.php b/tests/Validation/cases/objectCreation3.php similarity index 100% rename from validation/frameworks/_cases/objectCreation3.php rename to tests/Validation/cases/objectCreation3.php diff --git a/validation/frameworks/_cases/objectCreation3.php.expected.json b/tests/Validation/cases/objectCreation3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/objectCreation3.php.expected.json rename to tests/Validation/cases/objectCreation3.php.expected.json diff --git a/validation/frameworks/_cases/param1.php b/tests/Validation/cases/param1.php similarity index 100% rename from validation/frameworks/_cases/param1.php rename to tests/Validation/cases/param1.php diff --git a/validation/frameworks/_cases/param1.php.expected.json b/tests/Validation/cases/param1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/param1.php.expected.json rename to tests/Validation/cases/param1.php.expected.json diff --git a/validation/frameworks/_cases/parameterTypeResolution1.php b/tests/Validation/cases/parameterTypeResolution1.php similarity index 100% rename from validation/frameworks/_cases/parameterTypeResolution1.php rename to tests/Validation/cases/parameterTypeResolution1.php diff --git a/validation/frameworks/_cases/parameterTypeResolution1.php.expected.json b/tests/Validation/cases/parameterTypeResolution1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/parameterTypeResolution1.php.expected.json rename to tests/Validation/cases/parameterTypeResolution1.php.expected.json diff --git a/validation/frameworks/_cases/parent1.php b/tests/Validation/cases/parent1.php similarity index 100% rename from validation/frameworks/_cases/parent1.php rename to tests/Validation/cases/parent1.php diff --git a/validation/frameworks/_cases/parent1.php.expected.json b/tests/Validation/cases/parent1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/parent1.php.expected.json rename to tests/Validation/cases/parent1.php.expected.json diff --git a/validation/frameworks/_cases/parent2.php b/tests/Validation/cases/parent2.php similarity index 100% rename from validation/frameworks/_cases/parent2.php rename to tests/Validation/cases/parent2.php diff --git a/validation/frameworks/_cases/parent2.php.expected.json b/tests/Validation/cases/parent2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/parent2.php.expected.json rename to tests/Validation/cases/parent2.php.expected.json diff --git a/validation/frameworks/_cases/parent3.php b/tests/Validation/cases/parent3.php similarity index 100% rename from validation/frameworks/_cases/parent3.php rename to tests/Validation/cases/parent3.php diff --git a/validation/frameworks/_cases/parent3.php.expected.json b/tests/Validation/cases/parent3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/parent3.php.expected.json rename to tests/Validation/cases/parent3.php.expected.json diff --git a/validation/frameworks/_cases/propertyName1.php b/tests/Validation/cases/propertyName1.php similarity index 100% rename from validation/frameworks/_cases/propertyName1.php rename to tests/Validation/cases/propertyName1.php diff --git a/validation/frameworks/_cases/propertyName1.php.expected.json b/tests/Validation/cases/propertyName1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/propertyName1.php.expected.json rename to tests/Validation/cases/propertyName1.php.expected.json diff --git a/validation/frameworks/_cases/propertyName2.php b/tests/Validation/cases/propertyName2.php similarity index 100% rename from validation/frameworks/_cases/propertyName2.php rename to tests/Validation/cases/propertyName2.php diff --git a/validation/frameworks/_cases/propertyName2.php.expected.json b/tests/Validation/cases/propertyName2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/propertyName2.php.expected.json rename to tests/Validation/cases/propertyName2.php.expected.json diff --git a/validation/frameworks/_cases/returnType.php b/tests/Validation/cases/returnType.php similarity index 100% rename from validation/frameworks/_cases/returnType.php rename to tests/Validation/cases/returnType.php diff --git a/validation/frameworks/_cases/returnType.php.expected.json b/tests/Validation/cases/returnType.php.expected.json similarity index 100% rename from validation/frameworks/_cases/returnType.php.expected.json rename to tests/Validation/cases/returnType.php.expected.json diff --git a/validation/frameworks/_cases/scopedPropertyAccess.php b/tests/Validation/cases/scopedPropertyAccess.php similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess.php rename to tests/Validation/cases/scopedPropertyAccess.php diff --git a/validation/frameworks/_cases/scopedPropertyAccess.php.expected.json b/tests/Validation/cases/scopedPropertyAccess.php.expected.json similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess.php.expected.json rename to tests/Validation/cases/scopedPropertyAccess.php.expected.json diff --git a/validation/frameworks/_cases/scopedPropertyAccess2.php b/tests/Validation/cases/scopedPropertyAccess2.php similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess2.php rename to tests/Validation/cases/scopedPropertyAccess2.php diff --git a/validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json b/tests/Validation/cases/scopedPropertyAccess2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess2.php.expected.json rename to tests/Validation/cases/scopedPropertyAccess2.php.expected.json diff --git a/validation/frameworks/_cases/scopedPropertyAccess3.php b/tests/Validation/cases/scopedPropertyAccess3.php similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess3.php rename to tests/Validation/cases/scopedPropertyAccess3.php diff --git a/validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json b/tests/Validation/cases/scopedPropertyAccess3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess3.php.expected.json rename to tests/Validation/cases/scopedPropertyAccess3.php.expected.json diff --git a/validation/frameworks/_cases/scopedPropertyAccess4.php b/tests/Validation/cases/scopedPropertyAccess4.php similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess4.php rename to tests/Validation/cases/scopedPropertyAccess4.php diff --git a/validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json b/tests/Validation/cases/scopedPropertyAccess4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess4.php.expected.json rename to tests/Validation/cases/scopedPropertyAccess4.php.expected.json diff --git a/validation/frameworks/_cases/scopedPropertyAccess5.php b/tests/Validation/cases/scopedPropertyAccess5.php similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess5.php rename to tests/Validation/cases/scopedPropertyAccess5.php diff --git a/validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json b/tests/Validation/cases/scopedPropertyAccess5.php.expected.json similarity index 100% rename from validation/frameworks/_cases/scopedPropertyAccess5.php.expected.json rename to tests/Validation/cases/scopedPropertyAccess5.php.expected.json diff --git a/validation/frameworks/_cases/self1.php b/tests/Validation/cases/self1.php similarity index 100% rename from validation/frameworks/_cases/self1.php rename to tests/Validation/cases/self1.php diff --git a/validation/frameworks/_cases/self1.php.expected.json b/tests/Validation/cases/self1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/self1.php.expected.json rename to tests/Validation/cases/self1.php.expected.json diff --git a/validation/frameworks/_cases/self2.php b/tests/Validation/cases/self2.php similarity index 100% rename from validation/frameworks/_cases/self2.php rename to tests/Validation/cases/self2.php diff --git a/validation/frameworks/_cases/self2.php.expected.json b/tests/Validation/cases/self2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/self2.php.expected.json rename to tests/Validation/cases/self2.php.expected.json diff --git a/validation/frameworks/_cases/self3.php b/tests/Validation/cases/self3.php similarity index 100% rename from validation/frameworks/_cases/self3.php rename to tests/Validation/cases/self3.php diff --git a/validation/frameworks/_cases/self3.php.expected.json b/tests/Validation/cases/self3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/self3.php.expected.json rename to tests/Validation/cases/self3.php.expected.json diff --git a/validation/frameworks/_cases/self4.php b/tests/Validation/cases/self4.php similarity index 100% rename from validation/frameworks/_cases/self4.php rename to tests/Validation/cases/self4.php diff --git a/validation/frameworks/_cases/self4.php.expected.json b/tests/Validation/cases/self4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/self4.php.expected.json rename to tests/Validation/cases/self4.php.expected.json diff --git a/validation/frameworks/_cases/self5.php b/tests/Validation/cases/self5.php similarity index 100% rename from validation/frameworks/_cases/self5.php rename to tests/Validation/cases/self5.php diff --git a/validation/frameworks/_cases/self5.php.expected.json b/tests/Validation/cases/self5.php.expected.json similarity index 100% rename from validation/frameworks/_cases/self5.php.expected.json rename to tests/Validation/cases/self5.php.expected.json diff --git a/validation/frameworks/_cases/static1.php b/tests/Validation/cases/static1.php similarity index 100% rename from validation/frameworks/_cases/static1.php rename to tests/Validation/cases/static1.php diff --git a/validation/frameworks/_cases/static1.php.expected.json b/tests/Validation/cases/static1.php.expected.json similarity index 100% rename from validation/frameworks/_cases/static1.php.expected.json rename to tests/Validation/cases/static1.php.expected.json diff --git a/validation/frameworks/_cases/static2.php b/tests/Validation/cases/static2.php similarity index 100% rename from validation/frameworks/_cases/static2.php rename to tests/Validation/cases/static2.php diff --git a/validation/frameworks/_cases/static2.php.expected.json b/tests/Validation/cases/static2.php.expected.json similarity index 100% rename from validation/frameworks/_cases/static2.php.expected.json rename to tests/Validation/cases/static2.php.expected.json diff --git a/validation/frameworks/_cases/static3.php b/tests/Validation/cases/static3.php similarity index 100% rename from validation/frameworks/_cases/static3.php rename to tests/Validation/cases/static3.php diff --git a/validation/frameworks/_cases/static3.php.expected.json b/tests/Validation/cases/static3.php.expected.json similarity index 100% rename from validation/frameworks/_cases/static3.php.expected.json rename to tests/Validation/cases/static3.php.expected.json diff --git a/validation/frameworks/_cases/static4.php b/tests/Validation/cases/static4.php similarity index 100% rename from validation/frameworks/_cases/static4.php rename to tests/Validation/cases/static4.php diff --git a/validation/frameworks/_cases/static4.php.expected.json b/tests/Validation/cases/static4.php.expected.json similarity index 100% rename from validation/frameworks/_cases/static4.php.expected.json rename to tests/Validation/cases/static4.php.expected.json diff --git a/validation/frameworks/_cases/staticInArray.php b/tests/Validation/cases/staticInArray.php similarity index 100% rename from validation/frameworks/_cases/staticInArray.php rename to tests/Validation/cases/staticInArray.php diff --git a/validation/frameworks/_cases/staticInArray.php.expected.json b/tests/Validation/cases/staticInArray.php.expected.json similarity index 100% rename from validation/frameworks/_cases/staticInArray.php.expected.json rename to tests/Validation/cases/staticInArray.php.expected.json diff --git a/validation/frameworks/_cases/stringVariable.php b/tests/Validation/cases/stringVariable.php similarity index 100% rename from validation/frameworks/_cases/stringVariable.php rename to tests/Validation/cases/stringVariable.php diff --git a/validation/frameworks/_cases/stringVariable.php.expected.json b/tests/Validation/cases/stringVariable.php.expected.json similarity index 100% rename from validation/frameworks/_cases/stringVariable.php.expected.json rename to tests/Validation/cases/stringVariable.php.expected.json diff --git a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php similarity index 100% rename from validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php rename to tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php diff --git a/validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json similarity index 100% rename from validation/frameworks/_cases/testQualifiedNameOutsideOfNamespace.php.expected.json rename to tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json diff --git a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php b/tests/Validation/cases/verifyFqsenOnClassProperty.php similarity index 100% rename from validation/frameworks/_cases/verifyFqsenOnClassProperty.php rename to tests/Validation/cases/verifyFqsenOnClassProperty.php diff --git a/validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json b/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json similarity index 100% rename from validation/frameworks/_cases/verifyFqsenOnClassProperty.php.expected.json rename to tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json From fc7d7f419edbac4d5dfa6ec94f191042a18bbd22 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 14:23:51 -0700 Subject: [PATCH 131/149] Use reflection to get Definition props (now includes fqn and declarationLine) --- tests/Validation/ValidationTest.php | 9 ++++----- .../cases/WithReturnTypehints.php.expected.json | 10 ++++++++++ ...sClassMembersShouldNotBeSymbols.php.expected.json | 2 ++ .../arrayValueShouldBeBoolean.php.expected.json | 4 ++++ .../cases/caseStatement1.php.expected.json | 2 ++ .../cases/classDefinition1.php.expected.json | 6 ++++++ .../cases/classProperty1.php.expected.json | 8 ++++++++ tests/Validation/cases/constants.php.expected.json | 6 ++++++ tests/Validation/cases/constants2.php.expected.json | 6 ++++++ tests/Validation/cases/constants3.php.expected.json | 6 ++++++ tests/Validation/cases/constants4.php.expected.json | 6 ++++++ tests/Validation/cases/constants5.php.expected.json | 6 ++++++ ...constantsInFunctionParamDefault.php.expected.json | 4 ++++ .../docBlocksOnNamespaceDefinition.php.expected.json | 2 ++ tests/Validation/cases/exceptions1.php.expected.json | 2 ++ .../Validation/cases/ifStatement1.php.expected.json | 2 ++ .../cases/interfaceProperty.php.expected.json | 2 ++ .../magicConstantsShouldBeGlobal.php.expected.json | 2 ++ tests/Validation/cases/magicConsts.php.expected.json | 4 ++++ .../Validation/cases/memberAccess1.php.expected.json | 6 ++++++ .../Validation/cases/memberAccess2.php.expected.json | 6 ++++++ .../Validation/cases/memberAccess3.php.expected.json | 6 ++++++ .../Validation/cases/memberAccess4.php.expected.json | 6 ++++++ .../Validation/cases/memberAccess5.php.expected.json | 6 ++++++ tests/Validation/cases/memberCall1.php.expected.json | 6 ++++++ .../cases/multipleNamespaces.php.expected.json | 12 ++++++++++++ .../multiplePreceedingComments.php.expected.json | 4 ++++ tests/Validation/cases/nameToken.php.expected.json | 4 ++++ tests/Validation/cases/namespaces2.php.expected.json | 2 ++ tests/Validation/cases/namespaces5.php.expected.json | 2 ++ tests/Validation/cases/namespaces6.php.expected.json | 2 ++ tests/Validation/cases/namespaces8.php.expected.json | 2 ++ .../cases/objectCreation.php.expected.json | 6 ++++++ .../cases/objectCreation2.php.expected.json | 8 ++++++++ .../cases/objectCreation3.php.expected.json | 4 ++++ tests/Validation/cases/param1.php.expected.json | 4 ++++ tests/Validation/cases/parent1.php.expected.json | 10 ++++++++++ tests/Validation/cases/parent3.php.expected.json | 10 ++++++++++ .../Validation/cases/propertyName1.php.expected.json | 4 ++++ .../Validation/cases/propertyName2.php.expected.json | 4 ++++ tests/Validation/cases/returnType.php.expected.json | 4 ++++ .../cases/scopedPropertyAccess.php.expected.json | 6 ++++++ .../cases/scopedPropertyAccess2.php.expected.json | 2 ++ .../cases/scopedPropertyAccess3.php.expected.json | 4 ++++ .../cases/scopedPropertyAccess5.php.expected.json | 4 ++++ tests/Validation/cases/self1.php.expected.json | 10 ++++++++++ tests/Validation/cases/self2.php.expected.json | 10 ++++++++++ tests/Validation/cases/self3.php.expected.json | 10 ++++++++++ tests/Validation/cases/self4.php.expected.json | 6 ++++++ tests/Validation/cases/self5.php.expected.json | 6 ++++++ tests/Validation/cases/static1.php.expected.json | 10 ++++++++++ tests/Validation/cases/static2.php.expected.json | 10 ++++++++++ tests/Validation/cases/static3.php.expected.json | 10 ++++++++++ tests/Validation/cases/static4.php.expected.json | 6 ++++++ .../cases/stringVariable.php.expected.json | 6 ++++++ ...QualifiedNameOutsideOfNamespace.php.expected.json | 2 ++ .../verifyFqsenOnClassProperty.php.expected.json | 6 ++++++ 57 files changed, 310 insertions(+), 5 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 5253d210..361ee5c3 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -92,8 +92,8 @@ private function getActualTestValues($filename, $fileContents): array $this->filterSkippedReferences($actualRefs); $actualDefs = $this->getTestValuesFromDefs($document->getDefinitions()); - // TODO - there's probably a more PHP-typical way to do this. Need to compare the objects parsed from json files - // to the real results. json_decode returns stdClass Objects, not arrays. + // There's probably a more PHP-typical way to do this. Need to compare the objects parsed from json files + // to the real objects. $refsAndDefs = array( 'references' => json_decode(json_encode($actualRefs)), 'definitions' => json_decode(json_encode($actualDefs)) @@ -126,14 +126,13 @@ private function getActualTestValues($filename, $fileContents): array */ private function getTestValuesFromDefs($definitions): array { - // TODO - use reflection to read these properties - $propertyNames = ['extends', 'isGlobal', 'isStatic', 'canBeInstantiated', 'symbolInformation', 'type', 'documentation']; + $propertyNames = get_class_vars(Definition::class); $defsForAssert = []; foreach ($definitions as $definition) { $fqn = $definition->fqn; - foreach ($propertyNames as $propertyName) { + foreach ($propertyNames as $propertyName => $value) { if ($propertyName === 'symbolInformation') { // Range is very often different - don't check it, for now unset($definition->$propertyName->location->range); diff --git a/tests/Validation/cases/WithReturnTypehints.php.expected.json b/tests/Validation/cases/WithReturnTypehints.php.expected.json index 43dc4b56..50801d93 100644 --- a/tests/Validation/cases/WithReturnTypehints.php.expected.json +++ b/tests/Validation/cases/WithReturnTypehints.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "Fixtures\\Prophecy": { + "fqn": "Fixtures\\Prophecy", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "Fixtures" }, "type": null, + "declarationLine": "namespace Fixtures\\Prophecy;", "documentation": null }, "Fixtures\\Prophecy\\WithReturnTypehints": { + "fqn": "Fixtures\\Prophecy\\WithReturnTypehints", "extends": [ "Fixtures\\Prophecy\\EmptyClass" ], @@ -43,9 +46,11 @@ "containerName": "Fixtures\\Prophecy" }, "type": null, + "declarationLine": "class WithReturnTypehints extends EmptyClass", "documentation": null }, "Fixtures\\Prophecy\\WithReturnTypehints->getSelf()": { + "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getSelf()", "extends": [], "isGlobal": false, "isStatic": false, @@ -60,9 +65,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "public function getSelf(): self {", "documentation": null }, "Fixtures\\Prophecy\\WithReturnTypehints->getName()": { + "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getName()", "extends": [], "isGlobal": false, "isStatic": false, @@ -77,9 +84,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\String_", "type": {}, + "declarationLine": "public function getName(): string {", "documentation": null }, "Fixtures\\Prophecy\\WithReturnTypehints->getParent()": { + "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getParent()", "extends": [], "isGlobal": false, "isStatic": false, @@ -94,6 +103,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "public function getParent(): parent {", "documentation": null } } diff --git a/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index 727210b7..189d1541 100644 --- a/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json b/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json index 4acb4ba7..c9b02d02 100644 --- a/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json +++ b/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "A->foo": { + "fqn": "A->foo", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Array_", "type": {}, + "declarationLine": "protected $foo;", "documentation": null } } diff --git a/tests/Validation/cases/caseStatement1.php.expected.json b/tests/Validation/cases/caseStatement1.php.expected.json index 8d8d968c..7b6dbf24 100644 --- a/tests/Validation/cases/caseStatement1.php.expected.json +++ b/tests/Validation/cases/caseStatement1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,6 +23,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/classDefinition1.php.expected.json b/tests/Validation/cases/classDefinition1.php.expected.json index f135c15c..aad36bbd 100644 --- a/tests/Validation/cases/classDefinition1.php.expected.json +++ b/tests/Validation/cases/classDefinition1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "TestNamespace": { + "fqn": "TestNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace TestNamespace;", "documentation": null }, "TestNamespace\\A": { + "fqn": "TestNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "TestNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "TestNamespace\\A->a": { + "fqn": "TestNamespace\\A->a", "extends": [], "isGlobal": false, "isStatic": false, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Integer", "type": {}, + "declarationLine": "public $a;", "documentation": null } } diff --git a/tests/Validation/cases/classProperty1.php.expected.json b/tests/Validation/cases/classProperty1.php.expected.json index 4469987c..671c0193 100644 --- a/tests/Validation/cases/classProperty1.php.expected.json +++ b/tests/Validation/cases/classProperty1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "TestNamespace": { + "fqn": "TestNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace TestNamespace;", "documentation": null }, "TestNamespace\\TestClass": { + "fqn": "TestNamespace\\TestClass", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "TestNamespace" }, "type": null, + "declarationLine": "class TestClass", "documentation": null }, "TestNamespace\\TestClass->testProperty": { + "fqn": "TestNamespace\\TestClass->testProperty", "extends": [], "isGlobal": false, "isStatic": false, @@ -55,9 +60,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public $testProperty;", "documentation": null }, "TestNamespace\\TestClass->testMethod()": { + "fqn": "TestNamespace\\TestClass->testMethod()", "extends": [], "isGlobal": false, "isStatic": false, @@ -72,6 +79,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function testMethod($testParameter)", "documentation": null } } diff --git a/tests/Validation/cases/constants.php.expected.json b/tests/Validation/cases/constants.php.expected.json index b38fbb86..eef5cdd2 100644 --- a/tests/Validation/cases/constants.php.expected.json +++ b/tests/Validation/cases/constants.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A::suite()": { + "fqn": "MyNamespace\\A::suite()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public static function suite()", "documentation": null } } diff --git a/tests/Validation/cases/constants2.php.expected.json b/tests/Validation/cases/constants2.php.expected.json index 978d0bfa..6ecb2a6a 100644 --- a/tests/Validation/cases/constants2.php.expected.json +++ b/tests/Validation/cases/constants2.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A::suite()": { + "fqn": "MyNamespace\\A::suite()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public static function suite()", "documentation": null } } diff --git a/tests/Validation/cases/constants3.php.expected.json b/tests/Validation/cases/constants3.php.expected.json index 6f8b7007..d49903c7 100644 --- a/tests/Validation/cases/constants3.php.expected.json +++ b/tests/Validation/cases/constants3.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A::suite()": { + "fqn": "MyNamespace\\A::suite()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public static function suite()", "documentation": null } } diff --git a/tests/Validation/cases/constants4.php.expected.json b/tests/Validation/cases/constants4.php.expected.json index 0d962efe..2c01864f 100644 --- a/tests/Validation/cases/constants4.php.expected.json +++ b/tests/Validation/cases/constants4.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A->suite()": { + "fqn": "MyNamespace\\A->suite()", "extends": [], "isGlobal": false, "isStatic": false, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function suite()", "documentation": null } } diff --git a/tests/Validation/cases/constants5.php.expected.json b/tests/Validation/cases/constants5.php.expected.json index d7a19835..a0876b5c 100644 --- a/tests/Validation/cases/constants5.php.expected.json +++ b/tests/Validation/cases/constants5.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\Mbstring": { + "fqn": "MyNamespace\\Mbstring", "extends": [], "isGlobal": true, "isStatic": false, @@ -35,9 +38,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class Mbstring", "documentation": null }, "MyNamespace\\Mbstring::MB_CASE_FOLD": { + "fqn": "MyNamespace\\Mbstring::MB_CASE_FOLD", "extends": [], "isGlobal": false, "isStatic": false, @@ -52,6 +57,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "const MB_CASE_FOLD = PHP_INT_MAX;", "documentation": null } } diff --git a/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json b/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json index cb24cfda..98aa7cda 100644 --- a/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json +++ b/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "interface A {", "documentation": null }, "A->b()": { + "fqn": "A->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -36,6 +39,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b ($a = MY_CONSTANT);", "documentation": null } } diff --git a/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json index dbd85f69..d73ecb52 100644 --- a/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json +++ b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/exceptions1.php.expected.json b/tests/Validation/cases/exceptions1.php.expected.json index 42981946..d74deffb 100644 --- a/tests/Validation/cases/exceptions1.php.expected.json +++ b/tests/Validation/cases/exceptions1.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/ifStatement1.php.expected.json b/tests/Validation/cases/ifStatement1.php.expected.json index d412ee16..4375a2a0 100644 --- a/tests/Validation/cases/ifStatement1.php.expected.json +++ b/tests/Validation/cases/ifStatement1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,6 +23,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/interfaceProperty.php.expected.json b/tests/Validation/cases/interfaceProperty.php.expected.json index 955456b1..896d09e9 100644 --- a/tests/Validation/cases/interfaceProperty.php.expected.json +++ b/tests/Validation/cases/interfaceProperty.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "" }, "type": null, + "declarationLine": "interface A {", "documentation": null } } diff --git a/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json b/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json index f40036ed..36a29425 100644 --- a/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json +++ b/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "B": { + "fqn": "B", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace B;", "documentation": null } } diff --git a/tests/Validation/cases/magicConsts.php.expected.json b/tests/Validation/cases/magicConsts.php.expected.json index e9b187fd..c017d49a 100644 --- a/tests/Validation/cases/magicConsts.php.expected.json +++ b/tests/Validation/cases/magicConsts.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "A::$deprecationsTriggered": { + "fqn": "A::$deprecationsTriggered", "extends": [], "isGlobal": false, "isStatic": true, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Array_", "type": {}, + "declarationLine": "private static $deprecationsTriggered;", "documentation": null } } diff --git a/tests/Validation/cases/memberAccess1.php.expected.json b/tests/Validation/cases/memberAccess1.php.expected.json index a8d7ff3d..ff4868b8 100644 --- a/tests/Validation/cases/memberAccess1.php.expected.json +++ b/tests/Validation/cases/memberAccess1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A::a()": { + "fqn": "MyNamespace\\A::a()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "static function a() {", "documentation": null } } diff --git a/tests/Validation/cases/memberAccess2.php.expected.json b/tests/Validation/cases/memberAccess2.php.expected.json index dd2493bb..a6707d00 100644 --- a/tests/Validation/cases/memberAccess2.php.expected.json +++ b/tests/Validation/cases/memberAccess2.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A::a()": { + "fqn": "MyNamespace\\A::a()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "static function a() {", "documentation": null } } diff --git a/tests/Validation/cases/memberAccess3.php.expected.json b/tests/Validation/cases/memberAccess3.php.expected.json index 60db5b55..df58d1ee 100644 --- a/tests/Validation/cases/memberAccess3.php.expected.json +++ b/tests/Validation/cases/memberAccess3.php.expected.json @@ -24,6 +24,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -37,9 +38,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -53,9 +56,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A::getInitializer()": { + "fqn": "MyNamespace\\A::getInitializer()", "extends": [], "isGlobal": false, "isStatic": true, @@ -70,6 +75,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public static function getInitializer(ClassLoader $loader)", "documentation": null } } diff --git a/tests/Validation/cases/memberAccess4.php.expected.json b/tests/Validation/cases/memberAccess4.php.expected.json index 78208ce8..1cfabb38 100644 --- a/tests/Validation/cases/memberAccess4.php.expected.json +++ b/tests/Validation/cases/memberAccess4.php.expected.json @@ -15,6 +15,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -28,9 +29,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -44,9 +47,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A->testRequest()": { + "fqn": "MyNamespace\\A->testRequest()", "extends": [], "isGlobal": false, "isStatic": false, @@ -61,6 +66,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function testRequest()", "documentation": null } } diff --git a/tests/Validation/cases/memberAccess5.php.expected.json b/tests/Validation/cases/memberAccess5.php.expected.json index 6e23151c..ae2b4acd 100644 --- a/tests/Validation/cases/memberAccess5.php.expected.json +++ b/tests/Validation/cases/memberAccess5.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\ParseErrorsTest": { + "fqn": "MyNamespace\\ParseErrorsTest", "extends": [], "isGlobal": true, "isStatic": false, @@ -31,9 +34,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class ParseErrorsTest {", "documentation": null }, "MyNamespace\\ParseErrorsTest->setUp()": { + "fqn": "MyNamespace\\ParseErrorsTest->setUp()", "extends": [], "isGlobal": false, "isStatic": false, @@ -48,6 +53,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function setUp()", "documentation": null } } diff --git a/tests/Validation/cases/memberCall1.php.expected.json b/tests/Validation/cases/memberCall1.php.expected.json index a94a8437..4cf2cd8b 100644 --- a/tests/Validation/cases/memberCall1.php.expected.json +++ b/tests/Validation/cases/memberCall1.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\ParseErrorsTest": { + "fqn": "MyNamespace\\ParseErrorsTest", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class ParseErrorsTest", "documentation": null }, "MyNamespace\\ParseErrorsTest->setAccount()": { + "fqn": "MyNamespace\\ParseErrorsTest->setAccount()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,6 +63,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function setAccount(AccountInterface $account)", "documentation": null } } diff --git a/tests/Validation/cases/multipleNamespaces.php.expected.json b/tests/Validation/cases/multipleNamespaces.php.expected.json index 5bf8760b..2ed59de6 100644 --- a/tests/Validation/cases/multipleNamespaces.php.expected.json +++ b/tests/Validation/cases/multipleNamespaces.php.expected.json @@ -15,6 +15,7 @@ }, "definitions": { "MyNamespace1": { + "fqn": "MyNamespace1", "extends": [], "isGlobal": true, "isStatic": false, @@ -28,9 +29,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace1;", "documentation": null }, "MyNamespace1\\B": { + "fqn": "MyNamespace1\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -44,9 +47,11 @@ "containerName": "MyNamespace1" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace1\\B->b()": { + "fqn": "MyNamespace1\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -61,9 +66,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace2": { + "fqn": "MyNamespace2", "extends": [], "isGlobal": true, "isStatic": false, @@ -77,9 +84,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace2;", "documentation": null }, "MyNamespace2\\A": { + "fqn": "MyNamespace2\\A", "extends": [ "MyNamespace2\\MyNamespace1\\B" ], @@ -95,9 +104,11 @@ "containerName": "MyNamespace2" }, "type": null, + "declarationLine": "class A extends MyNamespace1\\B {", "documentation": null }, "MyNamespace2\\A->a()": { + "fqn": "MyNamespace2\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -112,6 +123,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/multiplePreceedingComments.php.expected.json b/tests/Validation/cases/multiplePreceedingComments.php.expected.json index fe34f9a2..ca97671c 100644 --- a/tests/Validation/cases/multiplePreceedingComments.php.expected.json +++ b/tests/Validation/cases/multiplePreceedingComments.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "Foo": { + "fqn": "Foo", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class Foo", "documentation": null }, "Foo->fn()": { + "fqn": "Foo->fn()", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "public function fn()", "documentation": "Foo" } } diff --git a/tests/Validation/cases/nameToken.php.expected.json b/tests/Validation/cases/nameToken.php.expected.json index 42b9a084..1bd944de 100644 --- a/tests/Validation/cases/nameToken.php.expected.json +++ b/tests/Validation/cases/nameToken.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "A->b()": { + "fqn": "A->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null } } diff --git a/tests/Validation/cases/namespaces2.php.expected.json b/tests/Validation/cases/namespaces2.php.expected.json index d4b40342..903d5448 100644 --- a/tests/Validation/cases/namespaces2.php.expected.json +++ b/tests/Validation/cases/namespaces2.php.expected.json @@ -15,6 +15,7 @@ }, "definitions": { "MyNamespace1": { + "fqn": "MyNamespace1", "extends": [], "isGlobal": true, "isStatic": false, @@ -28,6 +29,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace1;", "documentation": null } } diff --git a/tests/Validation/cases/namespaces5.php.expected.json b/tests/Validation/cases/namespaces5.php.expected.json index 8c0b27db..ccc22fda 100644 --- a/tests/Validation/cases/namespaces5.php.expected.json +++ b/tests/Validation/cases/namespaces5.php.expected.json @@ -24,6 +24,7 @@ }, "definitions": { "B": { + "fqn": "B", "extends": [], "isGlobal": true, "isStatic": false, @@ -37,6 +38,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace B;", "documentation": null } } diff --git a/tests/Validation/cases/namespaces6.php.expected.json b/tests/Validation/cases/namespaces6.php.expected.json index 6a3fa818..874ee7fc 100644 --- a/tests/Validation/cases/namespaces6.php.expected.json +++ b/tests/Validation/cases/namespaces6.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "A\\B": { + "fqn": "A\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,6 +16,7 @@ "containerName": "A" }, "type": null, + "declarationLine": "namespace A \\ B;", "documentation": null } } diff --git a/tests/Validation/cases/namespaces8.php.expected.json b/tests/Validation/cases/namespaces8.php.expected.json index 20dd6fca..2fbd1fb4 100644 --- a/tests/Validation/cases/namespaces8.php.expected.json +++ b/tests/Validation/cases/namespaces8.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "LanguageServer\\Tests\\Utils": { + "fqn": "LanguageServer\\Tests\\Utils", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,6 +20,7 @@ "containerName": "LanguageServer\\Tests" }, "type": null, + "declarationLine": "namespace LanguageServer\\Tests\\Utils;", "documentation": null } } diff --git a/tests/Validation/cases/objectCreation.php.expected.json b/tests/Validation/cases/objectCreation.php.expected.json index 2a1cfa7a..cea03439 100644 --- a/tests/Validation/cases/objectCreation.php.expected.json +++ b/tests/Validation/cases/objectCreation.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -35,9 +38,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -52,6 +57,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/objectCreation2.php.expected.json b/tests/Validation/cases/objectCreation2.php.expected.json index 3968842f..7f856b14 100644 --- a/tests/Validation/cases/objectCreation2.php.expected.json +++ b/tests/Validation/cases/objectCreation2.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -54,9 +59,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -71,6 +78,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/objectCreation3.php.expected.json b/tests/Validation/cases/objectCreation3.php.expected.json index a411754d..c6dcab90 100644 --- a/tests/Validation/cases/objectCreation3.php.expected.json +++ b/tests/Validation/cases/objectCreation3.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "A->a()": { + "fqn": "A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -36,6 +39,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/param1.php.expected.json b/tests/Validation/cases/param1.php.expected.json index c3f977e3..adbe0022 100644 --- a/tests/Validation/cases/param1.php.expected.json +++ b/tests/Validation/cases/param1.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\init()": { + "fqn": "MyNamespace\\init()", "extends": [], "isGlobal": true, "isStatic": false, @@ -36,6 +39,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function init(Hi $view)", "documentation": null } } diff --git a/tests/Validation/cases/parent1.php.expected.json b/tests/Validation/cases/parent1.php.expected.json index dfe8caa5..3391cd42 100644 --- a/tests/Validation/cases/parent1.php.expected.json +++ b/tests/Validation/cases/parent1.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -55,9 +60,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -73,9 +80,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -90,6 +99,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/parent3.php.expected.json b/tests/Validation/cases/parent3.php.expected.json index 9065e301..2c4915d5 100644 --- a/tests/Validation/cases/parent3.php.expected.json +++ b/tests/Validation/cases/parent3.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/propertyName1.php.expected.json b/tests/Validation/cases/propertyName1.php.expected.json index a79f79ce..8032ecc1 100644 --- a/tests/Validation/cases/propertyName1.php.expected.json +++ b/tests/Validation/cases/propertyName1.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyClass": { + "fqn": "MyClass", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class MyClass", "documentation": null }, "MyClass->mainPropertyName": { + "fqn": "MyClass->mainPropertyName", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\String_", "type": {}, + "declarationLine": "protected $mainPropertyName;", "documentation": "The name of the main property, or NULL if there is none." } } diff --git a/tests/Validation/cases/propertyName2.php.expected.json b/tests/Validation/cases/propertyName2.php.expected.json index 45c54a7c..a70c515c 100644 --- a/tests/Validation/cases/propertyName2.php.expected.json +++ b/tests/Validation/cases/propertyName2.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "MyClass": { + "fqn": "MyClass", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class MyClass", "documentation": null }, "MyClass->mainPropertyName": { + "fqn": "MyClass->mainPropertyName", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,6 +35,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\String_", "type": {}, + "declarationLine": "protected $mainPropertyName;", "documentation": "The name of the main property, or NULL if there is none." } } diff --git a/tests/Validation/cases/returnType.php.expected.json b/tests/Validation/cases/returnType.php.expected.json index e131837d..9515a6b0 100644 --- a/tests/Validation/cases/returnType.php.expected.json +++ b/tests/Validation/cases/returnType.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "TestNamespace": { + "fqn": "TestNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace TestNamespace;", "documentation": null }, "TestNamespace\\whatever()": { + "fqn": "TestNamespace\\whatever()", "extends": [], "isGlobal": true, "isStatic": false, @@ -39,6 +42,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "function whatever(TestClass $param): TestClass2 {", "documentation": "Aute duis elit reprehenderit tempor cillum proident anim laborum eu laboris reprehenderit ea incididunt." } } diff --git a/tests/Validation/cases/scopedPropertyAccess.php.expected.json b/tests/Validation/cases/scopedPropertyAccess.php.expected.json index 9d3864bc..6797a0ed 100644 --- a/tests/Validation/cases/scopedPropertyAccess.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -38,9 +41,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "MyNamespace\\A::a()": { + "fqn": "MyNamespace\\A::a()", "extends": [], "isGlobal": false, "isStatic": true, @@ -55,6 +60,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "static function a() {", "documentation": null } } diff --git a/tests/Validation/cases/scopedPropertyAccess2.php.expected.json b/tests/Validation/cases/scopedPropertyAccess2.php.expected.json index 9b009519..69ac4c70 100644 --- a/tests/Validation/cases/scopedPropertyAccess2.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess2.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,6 +20,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null } } diff --git a/tests/Validation/cases/scopedPropertyAccess3.php.expected.json b/tests/Validation/cases/scopedPropertyAccess3.php.expected.json index 990f3819..d29387a2 100644 --- a/tests/Validation/cases/scopedPropertyAccess3.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess3.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "A": { + "fqn": "A", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class A {", "documentation": null }, "A::$a": { + "fqn": "A::$a", "extends": [], "isGlobal": false, "isStatic": true, @@ -39,6 +42,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\String_", "type": {}, + "declarationLine": "static $a;", "documentation": null } } diff --git a/tests/Validation/cases/scopedPropertyAccess5.php.expected.json b/tests/Validation/cases/scopedPropertyAccess5.php.expected.json index 1f3f3df3..ab1e2145 100644 --- a/tests/Validation/cases/scopedPropertyAccess5.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess5.php.expected.json @@ -15,6 +15,7 @@ }, "definitions": { "TestClass": { + "fqn": "TestClass", "extends": [], "isGlobal": true, "isStatic": false, @@ -28,9 +29,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class TestClass implements TestInterface {", "documentation": null }, "TestClass::$testProperty": { + "fqn": "TestClass::$testProperty", "extends": [], "isGlobal": false, "isStatic": true, @@ -45,6 +48,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Array_", "type": {}, + "declarationLine": "public static $testProperty;", "documentation": "Lorem excepteur officia sit anim velit veniam enim." } } diff --git a/tests/Validation/cases/self1.php.expected.json b/tests/Validation/cases/self1.php.expected.json index 6d569d35..6531b537 100644 --- a/tests/Validation/cases/self1.php.expected.json +++ b/tests/Validation/cases/self1.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/self2.php.expected.json b/tests/Validation/cases/self2.php.expected.json index 425e911f..8300de2d 100644 --- a/tests/Validation/cases/self2.php.expected.json +++ b/tests/Validation/cases/self2.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/self3.php.expected.json b/tests/Validation/cases/self3.php.expected.json index 764a424c..3d5d4ad6 100644 --- a/tests/Validation/cases/self3.php.expected.json +++ b/tests/Validation/cases/self3.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/self4.php.expected.json b/tests/Validation/cases/self4.php.expected.json index c055887e..5fac53f1 100644 --- a/tests/Validation/cases/self4.php.expected.json +++ b/tests/Validation/cases/self4.php.expected.json @@ -15,6 +15,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -28,9 +29,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -44,9 +47,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A::suite()": { + "fqn": "MyNamespace\\A::suite()", "extends": [], "isGlobal": false, "isStatic": true, @@ -61,6 +66,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public static function suite()", "documentation": null } } diff --git a/tests/Validation/cases/self5.php.expected.json b/tests/Validation/cases/self5.php.expected.json index 5cf42dd5..781cd249 100644 --- a/tests/Validation/cases/self5.php.expected.json +++ b/tests/Validation/cases/self5.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,9 +20,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [], "isGlobal": true, "isStatic": false, @@ -35,9 +38,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A", "documentation": null }, "MyNamespace\\A->typesProvider()": { + "fqn": "MyNamespace\\A->typesProvider()", "extends": [], "isGlobal": false, "isStatic": false, @@ -52,6 +57,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function typesProvider()", "documentation": null } } diff --git a/tests/Validation/cases/static1.php.expected.json b/tests/Validation/cases/static1.php.expected.json index 14a117a9..b0323b26 100644 --- a/tests/Validation/cases/static1.php.expected.json +++ b/tests/Validation/cases/static1.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/static2.php.expected.json b/tests/Validation/cases/static2.php.expected.json index cc8d400e..c8d81fbc 100644 --- a/tests/Validation/cases/static2.php.expected.json +++ b/tests/Validation/cases/static2.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/static3.php.expected.json b/tests/Validation/cases/static3.php.expected.json index c70f6a25..bb556bff 100644 --- a/tests/Validation/cases/static3.php.expected.json +++ b/tests/Validation/cases/static3.php.expected.json @@ -12,6 +12,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -25,9 +26,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\B": { + "fqn": "MyNamespace\\B", "extends": [], "isGlobal": true, "isStatic": false, @@ -41,9 +44,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class B {", "documentation": null }, "MyNamespace\\B->b()": { + "fqn": "MyNamespace\\B->b()", "extends": [], "isGlobal": false, "isStatic": false, @@ -58,9 +63,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function b() {", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -76,9 +83,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -93,6 +102,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/static4.php.expected.json b/tests/Validation/cases/static4.php.expected.json index 6ca8f974..6a280285 100644 --- a/tests/Validation/cases/static4.php.expected.json +++ b/tests/Validation/cases/static4.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "MyNamespace": { + "fqn": "MyNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace MyNamespace;", "documentation": null }, "MyNamespace\\A": { + "fqn": "MyNamespace\\A", "extends": [ "MyNamespace\\B" ], @@ -40,9 +43,11 @@ "containerName": "MyNamespace" }, "type": null, + "declarationLine": "class A extends B {", "documentation": null }, "MyNamespace\\A->a()": { + "fqn": "MyNamespace\\A->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -57,6 +62,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/stringVariable.php.expected.json b/tests/Validation/cases/stringVariable.php.expected.json index 569bdc95..5ac910ba 100644 --- a/tests/Validation/cases/stringVariable.php.expected.json +++ b/tests/Validation/cases/stringVariable.php.expected.json @@ -2,6 +2,7 @@ "references": [], "definitions": { "B": { + "fqn": "B", "extends": [], "isGlobal": true, "isStatic": false, @@ -15,9 +16,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class B", "documentation": null }, "B->hi": { + "fqn": "B->hi", "extends": [], "isGlobal": false, "isStatic": false, @@ -32,9 +35,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Integer", "type": {}, + "declarationLine": "public $hi;", "documentation": null }, "B->a()": { + "fqn": "B->a()", "extends": [], "isGlobal": false, "isStatic": false, @@ -49,6 +54,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "function a () {", "documentation": null } } diff --git a/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json index 0c7a37ce..1f71b37c 100644 --- a/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -6,6 +6,7 @@ }, "definitions": { "SomeNamespace": { + "fqn": "SomeNamespace", "extends": [], "isGlobal": true, "isStatic": false, @@ -19,6 +20,7 @@ "containerName": "" }, "type": null, + "declarationLine": "namespace SomeNamespace { }", "documentation": null } } diff --git a/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json b/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json index 1fefbf78..f0727227 100644 --- a/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json +++ b/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json @@ -9,6 +9,7 @@ }, "definitions": { "Foo": { + "fqn": "Foo", "extends": [], "isGlobal": true, "isStatic": false, @@ -22,9 +23,11 @@ "containerName": "" }, "type": null, + "declarationLine": "class Foo {", "documentation": null }, "Foo->bar": { + "fqn": "Foo->bar", "extends": [], "isGlobal": false, "isStatic": false, @@ -39,9 +42,11 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Object_", "type": {}, + "declarationLine": "protected $bar;", "documentation": null }, "Foo->foo()": { + "fqn": "Foo->foo()", "extends": [], "isGlobal": false, "isStatic": false, @@ -56,6 +61,7 @@ }, "type__class": "phpDocumentor\\Reflection\\Types\\Mixed", "type": {}, + "declarationLine": "public function foo () {", "documentation": null } } From 344a2cef31bf3851014b9f81256fe19097785360 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 14:24:50 -0700 Subject: [PATCH 132/149] Remove filterSkippedReferences, no longer relevant --- tests/Validation/ValidationTest.php | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 361ee5c3..0142fdf3 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -89,7 +89,6 @@ private function getActualTestValues($filename, $fileContents): array $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); $actualRefs = $index->getReferences(); - $this->filterSkippedReferences($actualRefs); $actualDefs = $this->getTestValuesFromDefs($document->getDefinitions()); // There's probably a more PHP-typical way to do this. Need to compare the objects parsed from json files @@ -149,29 +148,6 @@ private function getTestValuesFromDefs($definitions): array return $defsForAssert; } - - /** - * @return void - */ - private function filterSkippedReferences(&$references) - { - $skipped = [ - 'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', - '__', // magic constants are treated as normal constants - 'Exception', 'Error', // catch exception types missing from old definition resolver - 'Trait', // use Trait references are missing from old definition resolve - '->tableAlias', '->realField', '->field', '->first_name', '->last_name', '->quoteMatch', '->idCol', '->timeCol', '->dataCol', - 'pathToUri', 'uriToPath' // group function use declarations are broken in old definition resolver - ]; - - foreach ($references as $key => $value) { - foreach ($skipped as $s) { - if (strpos($key, $s) !== false) { - unset($references[$key]); - } - } - } - } } function getExpectedValuesFile($testCaseFile): string From 0a15afc130ea036a973c36bdf00d2a606dca1c65 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 14:34:18 -0700 Subject: [PATCH 133/149] Cleanup, fix incorrect count() usage --- src/DefinitionResolver.php | 6 +++--- src/Protocol/SymbolInformation.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 9fc5b5b5..b8ddc59f 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -880,7 +880,7 @@ public function resolveExpressionNodeToType($expr) * 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 * - * @param Node || PhpParser\Token $class + * @param Node | PhpParser\Token $class * @return Type */ public function resolveClassNameToType($class): Type @@ -1079,7 +1079,7 @@ public static function getDefinedFqn($node) // namespace A\B; A\B if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) { $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); - return \count($name) > 0 ? $name : null; + return \strlen($name) > 0 ? $name : null; } // INPUT OUTPUT: @@ -1088,7 +1088,7 @@ public static function getDefinedFqn($node) if ($node instanceof Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name $name = (string)$node->getNamespacedName(); - return \count($name) > 0 ? $name . '()' : null; + return \strlen($name) > 0 ? $name . '()' : null; } // INPUT OUTPUT diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index f3defbf4..b64cf917 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -67,7 +67,7 @@ public static function fromNode($node, string $fqn = null) $symbol->kind = SymbolKind::FUNCTION; } else if ($node instanceof Node\MethodDeclaration) { $nameText = $node->getName(); - if ($nameText === '__construct' || $nameText === '__destruct') { + if ($nameText === '__construct' || $nameText === '__destruct') { $symbol->kind = SymbolKind::CONSTRUCTOR; } else { $symbol->kind = SymbolKind::METHOD; From cfc8cc781558f789ababe662df75aba9d2e33cc4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 16:44:14 -0700 Subject: [PATCH 134/149] Make FqnUtilities a module of functions, not a static class --- composer.json | 3 ++- src/CompletionProvider.php | 4 ++-- src/FqnUtilities.php | 43 ++++++++++++++++++------------------- src/Server/TextDocument.php | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/composer.json b/composer.json index c896216f..a1aedfd6 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,8 @@ "LanguageServer\\": "src/" }, "files" : [ - "src/utils.php" + "src/utils.php", + "src/FqnUtilities.php" ] }, "autoload-dev": { diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index d1fd9508..74a8c6d8 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -179,7 +179,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $a->c# $a-># */ elseif ($node instanceof Node\Expression\MemberAccessExpression) { - $prefixes = FqnUtilities::getFqnsFromType( + $prefixes = FqnUtilities\getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) ); $prefixes = $this->expandParentFqns($prefixes); @@ -209,7 +209,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression || ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression ) { - $prefixes = FqnUtilities::getFqnsFromType( + $prefixes = FqnUtilities\getFqnsFromType( $classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier) ); diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index f0ff53cc..0fc06b20 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -1,34 +1,33 @@ getFqsen(); - if ($fqsen !== null) { - $fqns[] = substr((string)$fqsen, 1); - } + $fqns = []; + if ($type instanceof Types\Object_) { + $fqsen = $type->getFqsen(); + if ($fqsen !== null) { + $fqns[] = substr((string)$fqsen, 1); } - if ($type instanceof Types\Compound) { - for ($i = 0; $t = $type->get($i); $i++) { - foreach (self::getFqnsFromType($type) as $fqn) { - $fqns[] = $fqn; - } + } + if ($type instanceof Types\Compound) { + for ($i = 0; $t = $type->get($i); $i++) { + foreach (getFqnsFromType($type) as $fqn) { + $fqns[] = $fqn; } } - return $fqns; } + return $fqns; } diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index c07586cb..2e8e4bf6 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -4,7 +4,7 @@ namespace LanguageServer\Server; use LanguageServer\{ - CompletionProvider, FqnUtilities, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver + CompletionProvider, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver }; use LanguageServer\Index\ReadableIndex; use LanguageServer\Protocol\{ From ae37940e55ee055bf18cc78515d89749fec440e9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 16:44:41 -0700 Subject: [PATCH 135/149] Fix error when getting completions in anon function closure 'use' --- src/CompletionProvider.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 74a8c6d8..5457812d 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -375,7 +375,8 @@ private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): ar } } - if ($level instanceof Node\Expression\AnonymousFunctionCreationExpression && $level->anonymousFunctionUseClause !== null) { + if ($level instanceof Node\Expression\AnonymousFunctionCreationExpression && $level->anonymousFunctionUseClause !== null && + $level->anonymousFunctionUseClause->useVariableNameList !== null) { foreach ($level->anonymousFunctionUseClause->useVariableNameList->getValues() as $use) { $useName = $use->getName(); if (empty($namePrefix) || strpos($useName, $namePrefix) !== false) { From eda52a893fe55ba3329b5da7922c491858694e9e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 17:24:47 -0700 Subject: [PATCH 136/149] Fix error from calling ltrim on null variableName --- src/DefinitionResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index b8ddc59f..098220b5 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -1177,12 +1177,12 @@ public static function getDefinedFqn($node) /** * @param DocBlock | null $docBlock - * @param $variableName + * @param string | null $variableName * @return DocBlock\Tags\Param | null */ private function tryGetDocBlockTagForParameter($docBlock, $variableName) { - if ($docBlock === null) { + if ($docBlock === null || $variableName === null) { return null; } $tags = $docBlock->getTagsByName('param'); From 1d314deff0c7b4b66efebbdb00985363b8c12b60 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 17:26:03 -0700 Subject: [PATCH 137/149] Make ParserHelper a module of functions, not a static class --- composer.json | 3 +- src/CompletionProvider.php | 8 +- src/DefinitionResolver.php | 36 ++--- src/FqnUtilities.php | 2 - src/ParserHelpers.php | 211 ++++++++++++++--------------- src/Protocol/SymbolInformation.php | 2 +- src/TreeAnalyzer.php | 2 +- 7 files changed, 130 insertions(+), 134 deletions(-) diff --git a/composer.json b/composer.json index a1aedfd6..b9c413d1 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,8 @@ }, "files" : [ "src/utils.php", - "src/FqnUtilities.php" + "src/FqnUtilities.php", + "src/ParserHelpers.php" ] }, "autoload-dev": { diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 5457812d..6e083ff1 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -228,7 +228,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } } - } elseif (ParserHelpers::isConstantFetch($node) || + } elseif (ParserHelpers\isConstantFetch($node) || ($creation = $node->parent) instanceof Node\Expression\ObjectCreationExpression || (($creation = $node) instanceof Node\Expression\ObjectCreationExpression)) { $class = isset($creation) ? $creation->classTypeDesignator : $node; @@ -296,7 +296,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $list->items[] = $item; } } - } elseif (ParserHelpers::isConstantFetch($node)) { + } elseif (ParserHelpers\isConstantFetch($node)) { $prefix = (string) ($node->getResolvedName() ?? PhpParser\ResolvedName::buildName($node->nameParts, $node->getFileContents())); foreach (self::KEYWORDS as $keyword) { $item = new CompletionItem($keyword, CompletionItemKind::KEYWORD); @@ -353,7 +353,7 @@ private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): ar // Walk the AST upwards until a scope boundary is met $level = $node; - while ($level && !ParserHelpers::isFunctionLike($level)) { + while ($level && !ParserHelpers\isFunctionLike($level)) { // Walk siblings before the node $sibling = $level; while ($sibling = $sibling->getPreviousSibling()) { @@ -367,7 +367,7 @@ private function suggestVariablesAtNode(Node $node, string $namePrefix = ''): ar // If the traversal ended because a function was met, // also add its parameters and closure uses to the result list - if ($level && ParserHelpers::isFunctionLike($level) && $level->parameters !== null) { + if ($level && ParserHelpers\isFunctionLike($level) && $level->parameters !== null) { foreach ($level->parameters->getValues() as $param) { $paramName = $param->getName(); if (empty($namePrefix) || strpos($paramName, $namePrefix) !== false) { diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 098220b5..23de8956 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -56,8 +56,8 @@ public function getDeclarationLineFromNode($node): string // - [PropertyDeclaration] // public $a, [$b = 3], $c; => public $b = 3; // - [ConstDeclaration | ClassConstDeclaration] // "const A = 3, [B = 4];" => "const B = 4;" if ( - ($declaration = ParserHelpers::tryGetPropertyDeclaration($node)) && ($elements = $declaration->propertyElements) || - ($declaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) && ($elements = $declaration->constElements) + ($declaration = ParserHelpers\tryGetPropertyDeclaration($node)) && ($elements = $declaration->propertyElements) || + ($declaration = ParserHelpers\tryGetConstOrClassConstDeclaration($node)) && ($elements = $declaration->constElements) ) { $defLine = $declaration->getText(); $defLineStart = $declaration->getStart(); @@ -95,7 +95,7 @@ public function getDocumentationFromNode($node) // For properties and constants, set the node to the declaration node, rather than the individual property. // This is because they get defined as part of a list. - $constOrPropertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node) ?? ParserHelpers::tryGetConstOrClassConstDeclaration($node); + $constOrPropertyDeclaration = ParserHelpers\tryGetPropertyDeclaration($node) ?? ParserHelpers\tryGetConstOrClassConstDeclaration($node); if ($constOrPropertyDeclaration !== null) { $node = $constOrPropertyDeclaration; } @@ -104,7 +104,7 @@ public function getDocumentationFromNode($node) if ($node instanceof Node\Parameter) { $variableName = $node->getName(); - $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); + $functionLikeDeclaration = ParserHelpers\getFunctionLikeDeclarationFromParameter($node); $docBlock = $this->getDocBlock($functionLikeDeclaration); $parameterDocBlockTag = $this->tryGetDocBlockTagForParameter($docBlock, $variableName); @@ -193,7 +193,7 @@ public function createDefinitionFromNode(Node $node, string $fqn = null): Defini $def->isStatic = ( ($node instanceof Node\MethodDeclaration && $node->isStatic()) || - (($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null + (($propertyDeclaration = ParserHelpers\tryGetPropertyDeclaration($node)) !== null && $propertyDeclaration->isStatic()) ); @@ -258,7 +258,7 @@ public function resolveReferenceNodeToDefinition(Node $node) // 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 // TODO - verify that this is not a method - $globalFallback = ParserHelpers::isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression; + $globalFallback = ParserHelpers\isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression; // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -277,7 +277,7 @@ public function resolveReferenceNodeToFqn(Node $node) return $this->resolveQualifiedNameNodeToFqn($node); } else if ($node instanceof Node\Expression\MemberAccessExpression) { return $this->resolveMemberAccessExpressionNodeToFqn($node); - } else if (ParserHelpers::isConstantFetch($node)) { + } else if (ParserHelpers\isConstantFetch($node)) { return (string)($node->getNamespacedName()); } else if ( // A\B::C - constant access expression @@ -497,7 +497,7 @@ public function resolveVariableToNode($var) // Traverse the AST up do { // If a function is met, check the parameters and use statements - if (ParserHelpers::isFunctionLike($n)) { + if (ParserHelpers\isFunctionLike($n)) { if ($n->parameters !== null) { foreach ($n->parameters->getElements() as $param) { if ($param->getName() === $name) { @@ -611,7 +611,7 @@ public function resolveExpressionNodeToType($expr) // CONSTANT FETCH // Resolve constants by retrieving corresponding definition type from FQN - if (ParserHelpers::isConstantFetch($expr)) { + if (ParserHelpers\isConstantFetch($expr)) { $fqn = (string)$expr->getNamespacedName(); $def = $this->index->getDefinition($fqn, true); if ($def !== null) { @@ -728,7 +728,7 @@ public function resolveExpressionNodeToType($expr) // isset($var) // >, >=, <, <=, &&, ||, AND, OR, XOR, ==, ===, !=, !== if ( - ParserHelpers::isBooleanExpression($expr) + ParserHelpers\isBooleanExpression($expr) || ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::BoolCastToken) || ($expr instanceof Node\Expression\UnaryOpExpression && $expr->operator->kind === PhpParser\TokenKind::ExclamationToken) @@ -933,7 +933,7 @@ public function resolveClassNameToType($class): Type */ public function getTypeFromNode($node) { - if (ParserHelpers::isConstDefineExpression($node)) { + if (ParserHelpers\isConstDefineExpression($node)) { // constants with define() like // define('TEST_DEFINE_CONSTANT', false); return $this->resolveExpressionNodeToType($node->argumentExpressionList->children[2]->expression); @@ -950,7 +950,7 @@ public function getTypeFromNode($node) // * @param MyClass $myParam // */ // function foo($a) - $functionLikeDeclaration = ParserHelpers::getFunctionLikeDeclarationFromParameter($node); + $functionLikeDeclaration = ParserHelpers\getFunctionLikeDeclarationFromParameter($node); $variableName = $node->getName(); $docBlock = $this->getDocBlock($functionLikeDeclaration); @@ -987,7 +987,7 @@ public function getTypeFromNode($node) // 1. doc block // 2. return type hint // 3. TODO: infer from return statements - if (ParserHelpers::isFunctionLike($node)) { + if (ParserHelpers\isFunctionLike($node)) { // Functions/methods $docBlock = $this->getDocBlock($node); if ( @@ -1014,8 +1014,8 @@ public function getTypeFromNode($node) // Get the documented type the assignment resolves to. if ( ($declarationNode = - ParserHelpers::tryGetPropertyDeclaration($node) ?? - ParserHelpers::tryGetConstOrClassConstDeclaration($node) + ParserHelpers\tryGetPropertyDeclaration($node) ?? + ParserHelpers\tryGetConstOrClassConstDeclaration($node) ) !== null || ($node = $node->parent) instanceof Node\Expression\AssignmentExpression) { $declarationNode = $declarationNode ?? $node; @@ -1123,7 +1123,7 @@ public static function getDefinedFqn($node) // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name // } if ( - ($propertyDeclaration = ParserHelpers::tryGetPropertyDeclaration($node)) !== null && + ($propertyDeclaration = ParserHelpers\tryGetPropertyDeclaration($node)) !== null && ($classDeclaration = $node->getFirstAncestor( Node\Expression\ObjectCreationExpression::class, @@ -1148,7 +1148,7 @@ public static function getDefinedFqn($node) // class C { // const $a, $b = 4 A\B\C::$a(), A\B\C::$b // } - if (($constDeclaration = ParserHelpers::tryGetConstOrClassConstDeclaration($node)) !== null) { + if (($constDeclaration = ParserHelpers\tryGetConstOrClassConstDeclaration($node)) !== null) { if ($constDeclaration instanceof Node\Statement\ConstDeclaration) { // Basic constant: use CONSTANT_NAME as name return (string)$node->getNamespacedName(); @@ -1168,7 +1168,7 @@ public static function getDefinedFqn($node) return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName(); } - if (ParserHelpers::isConstDefineExpression($node)) { + if (ParserHelpers\isConstDefineExpression($node)) { return $node->argumentExpressionList->children[0]->expression->getStringContentsText(); } diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index 0fc06b20..a3aab054 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -5,8 +5,6 @@ use phpDocumentor\Reflection\{Type, Types}; use Microsoft\PhpParser; -echo "FQN_UTILIIES" . PHP_EOL; - /** * Returns all possible FQNs in a type * diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index 779c2839..d687d49c 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -1,127 +1,124 @@ parent; - return + $parent = $node->parent; + return + ( + $node instanceof Node\QualifiedName && + ( + $parent instanceof Node\Expression || + $parent instanceof Node\DelimitedList\ExpressionList || + $parent instanceof Node\ArrayElement || + ($parent instanceof Node\Parameter && $node->parent->default === $node) || + $parent instanceof Node\StatementNode || + $parent instanceof Node\CaseStatementNode + ) && + !( + $parent instanceof Node\Expression\MemberAccessExpression || + $parent instanceof Node\Expression\CallExpression || + $parent instanceof Node\Expression\ObjectCreationExpression || + $parent instanceof Node\Expression\ScopedPropertyAccessExpression || + isFunctionLike($parent) || ( - $node instanceof Node\QualifiedName && - ( - $parent instanceof Node\Expression || - $parent instanceof Node\DelimitedList\ExpressionList || - $parent instanceof Node\ArrayElement || - ($parent instanceof Node\Parameter && $node->parent->default === $node) || - $parent instanceof Node\StatementNode || - $parent instanceof Node\CaseStatementNode - ) && - !( - $parent instanceof Node\Expression\MemberAccessExpression || - $parent instanceof Node\Expression\CallExpression || - $parent instanceof Node\Expression\ObjectCreationExpression || - $parent instanceof Node\Expression\ScopedPropertyAccessExpression || - self::isFunctionLike($parent) || - ( - $parent instanceof Node\Expression\BinaryExpression && - $parent->operator->kind === PhpParser\TokenKind::InstanceOfKeyword - ) - )); - } + $parent instanceof Node\Expression\BinaryExpression && + $parent->operator->kind === PhpParser\TokenKind::InstanceOfKeyword + ) + )); +} - public static function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) - { - return $node->parent->parent; - } +function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) +{ + return $node->parent->parent; +} - public static function isFunctionLike(Node $node) - { - return - $node instanceof Node\Statement\FunctionDeclaration || - $node instanceof Node\MethodDeclaration || - $node instanceof Node\Expression\AnonymousFunctionCreationExpression; - } +function isFunctionLike(Node $node) +{ + return + $node instanceof Node\Statement\FunctionDeclaration || + $node instanceof Node\MethodDeclaration || + $node instanceof Node\Expression\AnonymousFunctionCreationExpression; +} - public static function isBooleanExpression($expression) : bool - { - if (!($expression instanceof Node\Expression\BinaryExpression)) { - return false; - } - switch ($expression->operator->kind) { - case PhpParser\TokenKind::InstanceOfKeyword: - case PhpParser\TokenKind::GreaterThanToken: - case PhpParser\TokenKind::GreaterThanEqualsToken: - case PhpParser\TokenKind::LessThanToken: - case PhpParser\TokenKind::LessThanEqualsToken: - case PhpParser\TokenKind::AndKeyword: - case PhpParser\TokenKind::AmpersandAmpersandToken: - case PhpParser\TokenKind::LessThanEqualsGreaterThanToken: - case PhpParser\TokenKind::OrKeyword: - case PhpParser\TokenKind::BarBarToken: - case PhpParser\TokenKind::XorKeyword: - case PhpParser\TokenKind::ExclamationEqualsEqualsToken: - case PhpParser\TokenKind::ExclamationEqualsToken: - case PhpParser\TokenKind::CaretToken: - case PhpParser\TokenKind::EqualsEqualsEqualsToken: - case PhpParser\TokenKind::EqualsToken: - return true; - } +function isBooleanExpression($expression) : bool +{ + if (!($expression instanceof Node\Expression\BinaryExpression)) { return false; } - - - /** - * Tries to get the parent property declaration given a Node - * @param Node $node - * @return Node\PropertyDeclaration | null $node - */ - public static function tryGetPropertyDeclaration(Node $node) - { - if ($node instanceof Node\Expression\Variable && - (($propertyDeclaration = $node->parent->parent) instanceof Node\PropertyDeclaration || - ($propertyDeclaration = $propertyDeclaration->parent) instanceof Node\PropertyDeclaration) - ) { - return $propertyDeclaration; - } - return null; + switch ($expression->operator->kind) { + case PhpParser\TokenKind::InstanceOfKeyword: + case PhpParser\TokenKind::GreaterThanToken: + case PhpParser\TokenKind::GreaterThanEqualsToken: + case PhpParser\TokenKind::LessThanToken: + case PhpParser\TokenKind::LessThanEqualsToken: + case PhpParser\TokenKind::AndKeyword: + case PhpParser\TokenKind::AmpersandAmpersandToken: + case PhpParser\TokenKind::LessThanEqualsGreaterThanToken: + case PhpParser\TokenKind::OrKeyword: + case PhpParser\TokenKind::BarBarToken: + case PhpParser\TokenKind::XorKeyword: + case PhpParser\TokenKind::ExclamationEqualsEqualsToken: + case PhpParser\TokenKind::ExclamationEqualsToken: + case PhpParser\TokenKind::CaretToken: + case PhpParser\TokenKind::EqualsEqualsEqualsToken: + case PhpParser\TokenKind::EqualsToken: + return true; } + return false; +} - /** - * Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node - * @param Node $node - * @return Node\Statement\ConstDeclaration | Node\ClassConstDeclaration | null $node - */ - public static function tryGetConstOrClassConstDeclaration(Node $node) - { - if ( - $node instanceof Node\ConstElement && ( - ($constDeclaration = $node->parent->parent) instanceof Node\ClassConstDeclaration || - $constDeclaration instanceof Node\Statement\ConstDeclaration ) - ) { - return $constDeclaration; - } - return null; + +/** + * Tries to get the parent property declaration given a Node + * @param Node $node + * @return Node\PropertyDeclaration | null $node + */ +function tryGetPropertyDeclaration(Node $node) +{ + if ($node instanceof Node\Expression\Variable && + (($propertyDeclaration = $node->parent->parent) instanceof Node\PropertyDeclaration || + ($propertyDeclaration = $propertyDeclaration->parent) instanceof Node\PropertyDeclaration) + ) { + return $propertyDeclaration; } + return null; +} - /** - * Returns true if the node is a usage of `define`. - * e.g. define('TEST_DEFINE_CONSTANT', false); - * @param Node $node - * @return bool - */ - public static function isConstDefineExpression(Node $node): bool - { - return $node instanceof Node\Expression\CallExpression - && $node->callableExpression instanceof Node\QualifiedName - && strtolower($node->callableExpression->getText()) === 'define' - && isset($node->argumentExpressionList->children[0]) - && $node->argumentExpressionList->children[0]->expression instanceof Node\StringLiteral - && isset($node->argumentExpressionList->children[2]); +/** + * Tries to get the parent ConstDeclaration or ClassConstDeclaration given a Node + * @param Node $node + * @return Node\Statement\ConstDeclaration | Node\ClassConstDeclaration | null $node + */ +function tryGetConstOrClassConstDeclaration(Node $node) +{ + if ( + $node instanceof Node\ConstElement && ( + ($constDeclaration = $node->parent->parent) instanceof Node\ClassConstDeclaration || + $constDeclaration instanceof Node\Statement\ConstDeclaration ) + ) { + return $constDeclaration; } + return null; } + +/** + * Returns true if the node is a usage of `define`. + * e.g. define('TEST_DEFINE_CONSTANT', false); + * @param Node $node + * @return bool + */ +function isConstDefineExpression(Node $node): bool +{ + return $node instanceof Node\Expression\CallExpression + && $node->callableExpression instanceof Node\QualifiedName + && strtolower($node->callableExpression->getText()) === 'define' + && isset($node->argumentExpressionList->children[0]) + && $node->argumentExpressionList->children[0]->expression instanceof Node\StringLiteral + && isset($node->argumentExpressionList->children[2]); +} \ No newline at end of file diff --git a/src/Protocol/SymbolInformation.php b/src/Protocol/SymbolInformation.php index b64cf917..6b4d39e3 100644 --- a/src/Protocol/SymbolInformation.php +++ b/src/Protocol/SymbolInformation.php @@ -54,7 +54,7 @@ public static function fromNode($node, string $fqn = null) $symbol->kind = SymbolKind::CLASS_; } else if ($node instanceof Node\Statement\TraitDeclaration) { $symbol->kind = SymbolKind::CLASS_; - } else if (\LanguageServer\ParserHelpers::isConstDefineExpression($node)) { + } else if (\LanguageServer\ParserHelpers\isConstDefineExpression($node)) { // constants with define() like // define('TEST_DEFINE_CONSTANT', false); $symbol->kind = SymbolKind::CONSTANT; diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 7921d011..b9545167 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -137,7 +137,7 @@ private function update(Node $node) // Namespaced constant access and function calls also need to register a reference // to the global version because PHP falls back to global at runtime // http://php.net/manual/en/language.namespaces.fallback.php - if (ParserHelpers::isConstantFetch($node) || + if (ParserHelpers\isConstantFetch($node) || ($parent instanceof Node\Expression\CallExpression && !( $node instanceof Node\Expression\ScopedPropertyAccessExpression || From 68656d966358e7a7fb113a9bc1f048823330ace3 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 17:46:05 -0700 Subject: [PATCH 138/149] Use === "" instead of strlen check --- src/DefinitionResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 23de8956..0570ed1f 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -1079,7 +1079,7 @@ public static function getDefinedFqn($node) // namespace A\B; A\B if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) { $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents()); - return \strlen($name) > 0 ? $name : null; + return $name === "" ? null : $name; } // INPUT OUTPUT: @@ -1088,7 +1088,7 @@ public static function getDefinedFqn($node) if ($node instanceof Node\Statement\FunctionDeclaration) { // Function: use functionName() as the name $name = (string)$node->getNamespacedName(); - return \strlen($name) > 0 ? $name . '()' : null; + return $name === "" ? null : $name . '()'; } // INPUT OUTPUT From 4ade5fdbb2f9baa72abb36401b22ff087c7ebacf Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 7 Jun 2017 18:26:58 -0700 Subject: [PATCH 139/149] Fix sniff issues, exclude 'cases' test files from codesniff --- phpcs.xml.dist | 1 + src/ParserHelpers.php | 2 +- tests/Validation/ValidationTest.php | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index e67104b0..f65f4fca 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -2,6 +2,7 @@ src tests + tests/Validation/cases diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index d687d49c..5025ae34 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -121,4 +121,4 @@ function isConstDefineExpression(Node $node): bool && isset($node->argumentExpressionList->children[0]) && $node->argumentExpressionList->children[0]->expression instanceof Node\StringLiteral && isset($node->argumentExpressionList->children[2]); -} \ No newline at end of file +} diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 0142fdf3..1973841d 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -43,8 +43,8 @@ public function validationTestProvider() } /** - * This test loads the test cases specified in .php files under cases/ and looks at the whole set of - * Definitions and References produced. It reads the expected results from associated .json files + * This test loads the test cases specified in .php files under cases/ and looks at the whole set of + * Definitions and References produced. It reads the expected results from associated .json files * and compares to the actual result. If they don't match, the test fails and it writes the new baseline * to the .json file. * @group validation From 3131a9c17252fbec34d2746c094f997e4dc52ccc Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 8 Jun 2017 14:48:46 +0200 Subject: [PATCH 140/149] Polish TreeAnalyzer --- src/TreeAnalyzer.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index b9545167..76955c8e 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -12,6 +12,7 @@ class TreeAnalyzer { + /** @var PhpParser\Parser */ private $parser; /** @var Node */ @@ -33,14 +34,13 @@ class TreeAnalyzer private $definitionNodes; /** - * TreeAnalyzer constructor. * @param PhpParser\Parser $parser - * @param $content - * @param $docBlockFactory + * @param string $content + * @param DocBlockFactory $docBlockFactory * @param DefinitionResolver $definitionResolver - * @param $uri + * @param string $uri */ - public function __construct($parser, $content, $docBlockFactory, $definitionResolver, $uri) + public function __construct(PhpParser\Parser $parser, string $content, DocBlockFactory $docBlockFactory, DefinitionResolver $definitionResolver, string $uri) { $this->parser = $parser; $this->docBlockFactory = $docBlockFactory; @@ -53,7 +53,7 @@ public function __construct($parser, $content, $docBlockFactory, $definitionReso $this->collectDefinitionsAndReferences($this->stmts); } - public function collectDefinitionsAndReferences(Node $stmts) + private function collectDefinitionsAndReferences(Node $stmts) { foreach ($stmts::CHILD_NAMES as $name) { $node = $stmts->$name; @@ -94,6 +94,7 @@ public function collectDefinitionsAndReferences(Node $stmts) /** * Collect definitions and references for the given node + * * @param Node $node */ private function update(Node $node) From 54073c56fc1e1bb5792ddefce214b76bbc5aefd1 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 8 Jun 2017 14:50:59 +0200 Subject: [PATCH 141/149] More polish --- src/TreeAnalyzer.php | 20 ++++++++++++++++++- tests/NodeVisitor/DefinitionCollectorTest.php | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 76955c8e..08c60b0f 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -156,11 +156,17 @@ private function update(Node $node) $this->collectDefinitionsAndReferences($node); } - public function getDiagnostics() + /** + * @return Diagnostic[] + */ + public function getDiagnostics(): array { return $this->diagnostics ?? []; } + /** + * @return void + */ private function addReference(string $fqn, Node $node) { if (!isset($this->referenceNodes[$fqn])) { @@ -169,21 +175,33 @@ private function addReference(string $fqn, Node $node) $this->referenceNodes[$fqn][] = $node; } + /** + * @return Definition + */ public function getDefinitions() { return $this->definitions ?? []; } + /** + * @return Node[] + */ public function getDefinitionNodes() { return $this->definitionNodes ?? []; } + /** + * @return Node[] + */ public function getReferenceNodes() { return $this->referenceNodes ?? []; } + /** + * @return Node[] + */ public function getStmts() { return $this->stmts; diff --git a/tests/NodeVisitor/DefinitionCollectorTest.php b/tests/NodeVisitor/DefinitionCollectorTest.php index 604f30d1..a092b625 100644 --- a/tests/NodeVisitor/DefinitionCollectorTest.php +++ b/tests/NodeVisitor/DefinitionCollectorTest.php @@ -68,7 +68,7 @@ public function testDoesNotCollectReferences() /** * @param $path */ - private function collectDefinitions($path): array + private function collectDefinitions(string $path): array { $uri = pathToUri($path); $parser = new PhpParser\Parser(); From adf65e5b11382872beb95c8e03b05a7fc3b4fdc3 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Thu, 8 Jun 2017 14:56:07 +0200 Subject: [PATCH 142/149] Polish CompletionProvider --- src/CompletionProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 6e083ff1..0509e04b 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -420,10 +420,10 @@ private function findVariableDefinitionsInNode(Node $node, string $namePrefix = return $vars; } - private function isAssignmentToVariableWithPrefix($node, $namePrefix) + private function isAssignmentToVariableWithPrefix(Node $node, string $namePrefix): bool { return $node instanceof Node\Expression\AssignmentExpression && $node->leftOperand instanceof Node\Expression\Variable - && (empty($namePrefix) || strpos($node->leftOperand->getName(), $namePrefix) !== false); + && ($namePrefix === '' || strpos($node->leftOperand->getName(), $namePrefix) !== false); } } From a1ae0f6e487409e35869d74bfddb1580421af151 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 8 Jun 2017 15:03:27 -0700 Subject: [PATCH 143/149] Take tolerant-php-parser from Packagist instead of github --- composer.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/composer.json b/composer.json index b9c413d1..93dec97d 100644 --- a/composer.json +++ b/composer.json @@ -38,15 +38,9 @@ "sabre/uri": "^2.0", "jetbrains/phpstorm-stubs": "dev-master", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "dev-master" + "Microsoft/tolerant-php-parser": "^0.0.2" }, "minimum-stability": "dev", - "repositories": [ - { - "type": "git", - "url": "https://github.com/Microsoft/tolerant-php-parser.git" - } - ], "prefer-stable": true, "autoload": { "psr-4": { From bc5717ab7926d25572a0651b811f3ea87f24f9fb Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Fri, 9 Jun 2017 13:32:02 +0200 Subject: [PATCH 144/149] Check if node has parent --- src/CompletionProvider.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 0509e04b..a4f074b1 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -127,8 +127,11 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $node = $doc->getNodeAtPosition($pos); $offset = $node === null ? -1 : $pos->toOffset($node->getFileContents()); - if ($node !== null && $offset > $node->getEndPosition() && - $node->parent->getLastChild() instanceof PhpParser\MissingToken + if ( + $node !== null + && $offset > $node->getEndPosition() + && $node->parent !== null + && $node->parent->getLastChild() instanceof PhpParser\MissingToken ) { $node = $node->parent; } From d3d7f7dafe742e2614069abe1b527e25d8c6ad33 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Fri, 9 Jun 2017 13:32:14 +0200 Subject: [PATCH 145/149] Remove unneeded group use --- src/CompletionProvider.php | 2 +- tests/Utils/UtilsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index a4f074b1..9266570f 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -12,7 +12,7 @@ CompletionItem, CompletionItemKind }; -use function LanguageServer\{strStartsWith}; +use function LanguageServer\strStartsWith; use Microsoft\PhpParser; use Microsoft\PhpParser\Node; diff --git a/tests/Utils/UtilsTest.php b/tests/Utils/UtilsTest.php index d14ce59c..234bf0c3 100644 --- a/tests/Utils/UtilsTest.php +++ b/tests/Utils/UtilsTest.php @@ -4,7 +4,7 @@ namespace LanguageServer\Tests\Utils; use PHPUnit\Framework\TestCase; -use function LanguageServer\{strStartsWith}; +use function LanguageServer\strStartsWith; class UtilsTest extends TestCase { From 9ad3c5aef6d2611e6a8f143665aeee856d187223 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 9 Jun 2017 10:39:51 -0700 Subject: [PATCH 146/149] Remove dead if block --- src/CompletionProvider.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 9266570f..47525254 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -268,9 +268,8 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } - if (!$isNotFullyQualified && ($fqnStartsWithPrefix || strStartsWith($fqn, $namespacePrefix . "\\" . $prefix))) { - // $fqn = $fqn; - } elseif (!$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { + $isFullyQualifiedAndPrefixMatches = !$isNotFullyQualified && ($fqnStartsWithPrefix || strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)); + if (!$isFullyQualifiedAndPrefixMatches && !$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { if (empty($prefix)) { $fqn = '\\' . $fqn; } elseif (strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)) { @@ -278,7 +277,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } else { continue; } - } elseif (!$isAliased) { + } elseif (!$isFullyQualifiedAndPrefixMatches && !$isAliased) { continue; } } elseif ($fqnStartsWithPrefix && $class instanceof Node\QualifiedName && $class->isFullyQualifiedName()) { From 4b573acde192dac226d7849a6a0ab8a080585e57 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 9 Jun 2017 10:51:09 -0700 Subject: [PATCH 147/149] Inline strStartsWith and remove it --- src/CompletionProvider.php | 12 ++++++------ src/utils.php | 5 ----- tests/Utils/UtilsTest.php | 35 ----------------------------------- 3 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 tests/Utils/UtilsTest.php diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 47525254..9299669e 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -12,7 +12,6 @@ CompletionItem, CompletionItemKind }; -use function LanguageServer\strStartsWith; use Microsoft\PhpParser; use Microsoft\PhpParser\Node; @@ -248,7 +247,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } foreach ($this->index->getDefinitions() as $fqn => $def) { - $fqnStartsWithPrefix = strStartsWith($fqn, $prefix); + $fqnStartsWithPrefix = substr($fqn, 0, strlen($prefix)) === $prefix; $fqnContainsPrefix = empty($prefix) || strpos($fqn, $prefix) !== false; if (($def->canBeInstantiated || ($def->isGlobal && !isset($creation))) && $fqnContainsPrefix) { if ($namespaceDefinition !== null && $namespaceDefinition->name !== null) { @@ -259,7 +258,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $isNotFullyQualified = !($class instanceof Node\QualifiedName) || !$class->isFullyQualifiedName(); if ($isNotFullyQualified) { foreach ($namespaceImportTable as $alias => $name) { - if (strStartsWith($fqn, $name)) { + if (substr($fqn, 0, strlen($name)) === $name) { $fqn = $alias; $isAliased = true; break; @@ -267,12 +266,13 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi } } - - $isFullyQualifiedAndPrefixMatches = !$isNotFullyQualified && ($fqnStartsWithPrefix || strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)); + $prefixWithNamespace = $namespacePrefix . "\\" . $prefix; + $fqnMatchesPrefixWithNamespace = substr($fqn, 0, strlen($prefixWithNamespace)) === $prefixWithNamespace; + $isFullyQualifiedAndPrefixMatches = !$isNotFullyQualified && ($fqnStartsWithPrefix || $fqnMatchesPrefixWithNamespace); if (!$isFullyQualifiedAndPrefixMatches && !$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { if (empty($prefix)) { $fqn = '\\' . $fqn; - } elseif (strStartsWith($fqn, $namespacePrefix . "\\" . $prefix)) { + } elseif ($fqnMatchesPrefixWithNamespace) { $fqn = substr($fqn, strlen($namespacePrefix) + 1); } else { continue; diff --git a/src/utils.php b/src/utils.php index 04553ce8..636b41ef 100644 --- a/src/utils.php +++ b/src/utils.php @@ -171,8 +171,3 @@ function getVendorDir(\stdClass $composerJson = null): string { return $composerJson->config->{'vendor-dir'} ?? 'vendor'; } - -function strStartsWith(string $haystack, string $prefix): bool -{ - return substr($haystack, 0, strlen($prefix)) === $prefix; -} diff --git a/tests/Utils/UtilsTest.php b/tests/Utils/UtilsTest.php deleted file mode 100644 index 234bf0c3..00000000 --- a/tests/Utils/UtilsTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertEquals(strStartsWith($haystack, $prefix), $expectedResult); - } -} From 4486ea0997ef42769536774d0b73e3131ce8d178 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Fri, 9 Jun 2017 20:00:21 +0200 Subject: [PATCH 148/149] Don't recheck condition --- src/CompletionProvider.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 9299669e..160798d3 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -269,16 +269,18 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi $prefixWithNamespace = $namespacePrefix . "\\" . $prefix; $fqnMatchesPrefixWithNamespace = substr($fqn, 0, strlen($prefixWithNamespace)) === $prefixWithNamespace; $isFullyQualifiedAndPrefixMatches = !$isNotFullyQualified && ($fqnStartsWithPrefix || $fqnMatchesPrefixWithNamespace); - if (!$isFullyQualifiedAndPrefixMatches && !$isAliased && !array_search($fqn, array_values($namespaceImportTable))) { - if (empty($prefix)) { - $fqn = '\\' . $fqn; - } elseif ($fqnMatchesPrefixWithNamespace) { - $fqn = substr($fqn, strlen($namespacePrefix) + 1); + if (!$isFullyQualifiedAndPrefixMatches && !$isAliased) { + if (!array_search($fqn, array_values($namespaceImportTable))) { + if (empty($prefix)) { + $fqn = '\\' . $fqn; + } elseif ($fqnMatchesPrefixWithNamespace) { + $fqn = substr($fqn, strlen($namespacePrefix) + 1); + } else { + continue; + } } else { continue; } - } elseif (!$isFullyQualifiedAndPrefixMatches && !$isAliased) { - continue; } } elseif ($fqnStartsWithPrefix && $class instanceof Node\QualifiedName && $class->isFullyQualifiedName()) { $fqn = '\\' . $fqn; From 349d3cb02eb504717c839d950bf73fb75d2f7be4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 9 Jun 2017 11:07:54 -0700 Subject: [PATCH 149/149] Remove ParserKind reference from Perf test --- Performance.php | 50 +++++++++++++---------------- tests/Validation/ValidationTest.php | 1 - 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/Performance.php b/Performance.php index 30b2fa6c..5022f847 100644 --- a/Performance.php +++ b/Performance.php @@ -5,7 +5,6 @@ use Exception; use LanguageServer\Index\Index; -use LanguageServer\ParserKind; use LanguageServer\PhpDocument; use LanguageServer\DefinitionResolver; use Microsoft\PhpParser; @@ -32,40 +31,35 @@ throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download."); } + $start = microtime(true); - $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; - foreach ($parserKinds as $kind) { - $start = microtime(true); - - foreach ($testProviderArray as $idx => $testCaseFile) { - if (filesize($testCaseFile) > 10000) { - continue; - } - if ($idx % 1000 === 0) { - echo "$idx\n"; - } + foreach ($testProviderArray as $idx => $testCaseFile) { + if (filesize($testCaseFile) > 10000) { + continue; + } + if ($idx % 1000 === 0) { + echo "$idx\n"; + } - $fileContents = file_get_contents($testCaseFile); + $fileContents = file_get_contents($testCaseFile); - $docBlockFactory = DocBlockFactory::createInstance(); - $index = new Index; - $maxRecursion = []; - $definitions = []; + $docBlockFactory = DocBlockFactory::createInstance(); + $index = new Index; + $maxRecursion = []; + $definitions = []; - $definitionResolver = new DefinitionResolver($index); - $parser = new PhpParser\Parser(); + $definitionResolver = new DefinitionResolver($index); + $parser = new PhpParser\Parser(); - try { - $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); - } catch (\Throwable $e) { - continue; - } + try { + $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); + } catch (\Throwable $e) { + continue; } + } - echo "------------------------------\n"; - - echo "Time [$framework, $kind]: " . (microtime(true) - $start) . PHP_EOL; + echo "------------------------------\n"; - } + echo "Time [$framework]: " . (microtime(true) - $start) . PHP_EOL; } diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 1973841d..649e9471 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -7,7 +7,6 @@ use Exception; use LanguageServer\Definition; use LanguageServer\Index\Index; -use LanguageServer\ParserKind; use LanguageServer\PhpDocument; use LanguageServer\DefinitionResolver; use phpDocumentor\Reflection\DocBlock;