diff --git a/src/StaticAnalysis/AttributeParentConnectingVisitor.php b/src/StaticAnalysis/AttributeParentConnectingVisitor.php new file mode 100644 index 000000000..4436e9a86 --- /dev/null +++ b/src/StaticAnalysis/AttributeParentConnectingVisitor.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_pop; +use function count; +use PhpParser\Node; +use PhpParser\NodeVisitor; + +/** + * Visitor that connects a child node to its parent node optimzed for Attribute nodes. + * + * On the child node, the parent node can be accessed through + * $node->getAttribute('parent'). + */ +final class AttributeParentConnectingVisitor implements NodeVisitor +{ + /** + * @var Node[] + */ + private array $stack = []; + + public function beforeTraverse(array $nodes): null + { + $this->stack = []; + + return null; + } + + public function enterNode(Node $node): null + { + if ( + $this->stack !== [] && + ($node instanceof Node\Attribute || $node instanceof Node\AttributeGroup) + ) { + $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + } + + $this->stack[] = $node; + + return null; + } + + public function leaveNode(Node $node): null + { + array_pop($this->stack); + + return null; + } + + public function afterTraverse(array $nodes): null + { + return null; + } +} diff --git a/src/StaticAnalysis/ParsingFileAnalyser.php b/src/StaticAnalysis/ParsingFileAnalyser.php index 79f51e987..dfca1dd0c 100644 --- a/src/StaticAnalysis/ParsingFileAnalyser.php +++ b/src/StaticAnalysis/ParsingFileAnalyser.php @@ -26,7 +26,6 @@ use PhpParser\Error; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; -use PhpParser\NodeVisitor\ParentConnectingVisitor; use PhpParser\ParserFactory; use SebastianBergmann\CodeCoverage\ParserException; use SebastianBergmann\LinesOfCode\LineCountingVisitor; @@ -180,7 +179,7 @@ private function analyse(string $filename): void $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor($source); $traverser->addVisitor(new NameResolver); - $traverser->addVisitor(new ParentConnectingVisitor); + $traverser->addVisitor(new AttributeParentConnectingVisitor); $traverser->addVisitor($codeUnitFindingVisitor); $traverser->addVisitor($lineCountingVisitor); $traverser->addVisitor($ignoredLinesFindingVisitor);