diff --git a/src/NodeVisitor/OptimizerNodeVisitor.php b/src/NodeVisitor/OptimizerNodeVisitor.php index 6b39f0094..9f9b81cbf 100644 --- a/src/NodeVisitor/OptimizerNodeVisitor.php +++ b/src/NodeVisitor/OptimizerNodeVisitor.php @@ -24,6 +24,7 @@ use Twig\Node\IncludeNode; use Twig\Node\Node; use Twig\Node\PrintNode; +use Twig\Node\TextNode; /** * Tries to optimize the AST. @@ -43,6 +44,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface public const OPTIMIZE_NONE = 0; public const OPTIMIZE_FOR = 2; public const OPTIMIZE_RAW_FILTER = 4; + public const OPTIMIZE_TEXT_NODES = 8; private $loops = []; private $loopsTargets = []; @@ -81,6 +83,42 @@ public function leaveNode(Node $node, Environment $env): ?Node $node = $this->optimizePrintNode($node); + if (self::OPTIMIZE_TEXT_NODES === (self::OPTIMIZE_TEXT_NODES & $this->optimizers)) { + $node = $this->mergeTextNodeCalls($node); + } + + return $node; + } + + private function mergeTextNodeCalls(Node $node): Node + { + $text = ''; + $names = []; + foreach ($node as $k => $n) { + if (!$n instanceof TextNode) { + return $node; + } + + $text .= $n->getAttribute('data'); + $names[] = $k; + } + + if (!$text) { + return $node; + } + + if (Node::class === get_class($node)) { + return new TextNode($text, $node->getTemplateLine()); + } + + foreach ($names as $i => $name) { + if (0 === $i) { + $node->setNode($name, new TextNode($text, $node->getTemplateLine())); + } else { + $node->removeNode($name); + } + } + return $node; } @@ -98,6 +136,11 @@ private function optimizePrintNode(Node $node): Node } $exprNode = $node->getNode('expr'); + + if ($exprNode instanceof ConstantExpression && is_string($exprNode->getAttribute('value'))) { + return new TextNode($exprNode->getAttribute('value'), $exprNode->getTemplateLine()); + } + if ( $exprNode instanceof BlockReferenceExpression || $exprNode instanceof ParentExpression diff --git a/tests/ExpressionParserTest.php b/tests/ExpressionParserTest.php index ab02296b6..afd1884d8 100644 --- a/tests/ExpressionParserTest.php +++ b/tests/ExpressionParserTest.php @@ -223,9 +223,6 @@ public function testStringExpression($template, $expected) public function getTestsForString() { return [ - [ - '{{ "foo" }}', new ConstantExpression('foo', 1), - ], [ '{{ "foo #{bar}" }}', new ConcatBinary( new ConstantExpression('foo ', 1),