* * @internal */ final class ForNodeVisitor implements NodeVisitorInterface { private int $loops = 0; public function enterNode(Node $node, Environment $env): Node { if ($node instanceof ForNode) { ++$this->loops; return $node; } elseif (!$this->loops) { // we are outside a loop return $node; } if (!$node instanceof PrintNode) { return $node; } // We look for exactly {{ loop.__invoke(...) }} $exprNode = $node->getNode('expr'); if ( $exprNode instanceof GetAttrExpression && $exprNode->getNode('node') instanceof NameExpression && 'loop' === $exprNode->getNode('node')->getAttribute('name') && $exprNode->getNode('attribute') instanceof ConstantExpression && '__invoke' === $exprNode->getNode('attribute')->getAttribute('value') ) { $exprNode->setAttribute('is_generator', true); } return $node; } public function leaveNode(Node $node, Environment $env): ?Node { if ($node instanceof ForNode) { --$this->loops; } return $node; } public function getPriority(): int { return 0; } }