From 49b526d7e129d4977c965a6a5b3847dd51a6b1bd Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Sun, 20 Nov 2016 23:33:00 +0100 Subject: [PATCH] Allow getTypeFromNode() to take Variable nodes --- src/CompletionProvider.php | 11 ++--------- src/DefinitionResolver.php | 35 +++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 80604fe..b51e652 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -85,16 +85,9 @@ class CompletionProvider foreach ($this->suggestVariablesAtNode($node) 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); - if ($var instanceof Node\Param) { - $item->label = '$' . $var->name; - $item->detail = (string)$this->definitionResolver->getTypeFromNode($var); // TODO make it handle variables as well. Makes sense because needs to handle @var tag too! - } else if ($var instanceof Node\Expr\Variable || $var instanceof Node\Expr\ClosureUse) { - $item->label = '$' . ($var instanceof Node\Expr\ClosureUse ? $var->var : $var->name); - $item->detail = (string)$this->definitionResolver->resolveExpressionNodeToType($var->getAttribute('parentNode')); - } else { - throw new \LogicException; - } + $item->detail = (string)$this->definitionResolver->getTypeFromNode($var); $items[] = $item; } } diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 677cf89..9f20b1b 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -113,13 +113,8 @@ class DefinitionResolver $def->declarationLine = $this->getDeclarationLineFromNode($defNode); // Documentation $def->documentation = $this->getDocumentationFromNode($defNode); - if ($defNode instanceof Node\Param) { - // Get parameter type - $def->type = $this->getTypeFromNode($defNode); - } else { - // Resolve the type of the assignment/closure use node - $def->type = $this->resolveExpressionNodeToType($defNode); - } + // Get type from docblock + $def->type = $this->getTypeFromNode($defNode); return $def; } // Other references are references to a global symbol that have an FQN @@ -608,7 +603,7 @@ class DefinitionResolver * 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). - * Variables are not indexed for performance reasons. + * 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. @@ -666,16 +661,28 @@ class DefinitionResolver // Unknown return type return new Types\Mixed; } - if ($node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Const_) { - // Property or constant - $docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock'); + 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 + ) { + // Property, constant or variable if ( - $docBlock !== null + ($parent = $node->getAttribute('parentNode')) + && ($docBlock = $parent->getAttribute('docBlock')) && !empty($varTags = $docBlock->getTagsByName('var')) - && $varTags[0]->getType() + && ($type = $varTags[0]->getType()) ) { // Use @var tag - return $varTags[0]->getType(); + return $type; + } + if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) { + // Resolve the expression + return $this->resolveExpressionNodeToType($node); } // TODO: read @property tags of class // TODO: Try to infer the type from default value / constant value