From d4443465bb93d2f3cf3013b5c4a3ee482b66f905 Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Thu, 28 Sep 2017 21:53:12 +0200 Subject: [PATCH] Fix missing diagnostics for nodes (#484) * Fix missing diagnostics for nodes * Refactor TreeAnalyzer --- src/TreeAnalyzer.php | 92 +++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 2e34aa6..0e43a8c 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -49,44 +49,73 @@ class TreeAnalyzer // TODO - docblock errors - $this->collectDefinitionsAndReferences($this->sourceFileNode); + $this->traverse($this->sourceFileNode); } - private function collectDefinitionsAndReferences(Node $sourceFileNode) + /** + * Collects Parser diagnostic messages for the Node/Token + * and transforms them into LSP Format + * + * @param Node|Token $node + * @return Diagnostic + */ + private function collectDiagnostics($node) { - foreach ($sourceFileNode::CHILD_NAMES as $name) { - $node = $sourceFileNode->$name; + if (($error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = PhpParser\PositionUtilities::getRangeFromPosition($error->start, $error->length, $this->sourceFileNode->fileContents); - if ($node === null) { - continue; + switch ($error->kind) { + case \Microsoft\PhpParser\DiagnosticKind::Error: + $severity = DiagnosticSeverity::ERROR; + break; + case \Microsoft\PhpParser\DiagnosticKind::Warning: + default: + $severity = DiagnosticSeverity::WARNING; + break; } - if (\is_array($node)) { - foreach ($node as $child) { - if ($child instanceof Node) { - $this->update($child); - } + $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, + $severity, + 'php' + ); + } + } + + /** + * Recursive AST traversal to collect definitions/references and diagnostics + * + * @param Node|Token $currentNode The node/token to process + */ + private function traverse($currentNode) + { + $this->collectDiagnostics($currentNode); + + // Only update/descend into Nodes, Tokens are leaves + if ($currentNode instanceof Node) { + $this->collectDefinitionsAndReferences($currentNode); + + foreach ($currentNode::CHILD_NAMES as $name) { + $child = $currentNode->$name; + + if ($child === null) { + continue; } - continue; - } - if ($node instanceof Node) { - $this->update($node); - } - - if (($error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = PhpParser\PositionUtilities::getRangeFromPosition($error->start, $error->length, $this->sourceFileNode->fileContents); - - $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' - ); + if (\is_array($child)) { + foreach ($child as $actualChild) { + if ($actualChild !== null) { + $this->traverse($actualChild); + } + } + } else { + $this->traverse($child); + } } } } @@ -96,7 +125,7 @@ class TreeAnalyzer * * @param Node $node */ - private function update(Node $node) + private function collectDefinitionsAndReferences(Node $node) { $fqn = ($this->definitionResolver)::getDefinedFqn($node); // Only index definitions with an FQN (no variables) @@ -152,7 +181,6 @@ class TreeAnalyzer } } } - $this->collectDefinitionsAndReferences($node); } /**