Remove the new yield nodes

This commit is contained in:
Fabien Potencier
2024-01-05 19:12:23 +01:00
parent 3b6cbf98d8
commit 15879406c8
22 changed files with 61 additions and 213 deletions
-2
View File
@@ -22,7 +22,6 @@ use Twig\Extension\CoreExtension;
use Twig\Extension\EscaperExtension;
use Twig\Extension\ExtensionInterface;
use Twig\Extension\OptimizerExtension;
use Twig\Extension\YieldingExtension;
use Twig\Loader\ArrayLoader;
use Twig\Loader\ChainLoader;
use Twig\Loader\LoaderInterface;
@@ -130,7 +129,6 @@ class Environment
$this->addExtension(new CoreExtension());
$this->addExtension(new EscaperExtension($options['autoescape']));
$this->addExtension(new OptimizerExtension($options['optimizations']));
$this->addExtension(new YieldingExtension($options['use_yield']));
}
/**
-29
View File
@@ -1,29 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Twig\Extension;
use Twig\NodeVisitor\YieldingNodeVisitor;
class YieldingExtension extends AbstractExtension
{
private $yielding;
public function __construct(bool $yielding)
{
$this->yielding = $yielding;
}
public function getNodeVisitors(): array
{
return [new YieldingNodeVisitor($this->yielding)];
}
}
+8 -2
View File
@@ -29,9 +29,15 @@ class PrintNode extends Node implements NodeOutputInterface
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield ');
} else {
$compiler->write('echo ');
}
$compiler
->addDebugInfo($this)
->write('echo ')
->subcompile($this->getNode('expr'))
->raw(";\n")
;
+8 -2
View File
@@ -28,9 +28,15 @@ class TextNode extends Node implements NodeOutputInterface
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield ');
} else {
$compiler->write('echo ');
}
$compiler
->addDebugInfo($this)
->write('echo ')
->string($this->getAttribute('data'))
->raw(";\n")
;
-32
View File
@@ -1,32 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a node that outputs an expression.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class YieldExpressionNode extends PrintNode
{
public function compile(Compiler $compiler): void
{
$compiler
->addDebugInfo($this)
->write('yield ')
->subcompile($this->getNode('expr'))
->raw(";\n")
;
}
}
-32
View File
@@ -1,32 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a text node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class YieldTextNode extends TextNode
{
public function compile(Compiler $compiler): void
{
$compiler
->addDebugInfo($this)
->write('yield ')
->string($this->getAttribute('data'))
->raw(";\n")
;
}
}
-81
View File
@@ -1,81 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Twig\NodeVisitor;
use Twig\Environment;
use Twig\Node\Node;
use Twig\Node\PrintNode;
use Twig\Node\TextNode;
use Twig\Node\YieldExpressionNode;
use Twig\Node\YieldTextNode;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
final class YieldingNodeVisitor implements NodeVisitorInterface
{
private $yielding;
public function __construct(bool $yielding)
{
$this->yielding = $yielding;
}
public function enterNode(Node $node, Environment $env): Node
{
if ($node instanceof YieldExpressionNode) {
if ($this->yielding) {
return $node;
}
return new PrintNode($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag());
}
if ($node instanceof YieldTextNode) {
if ($this->yielding) {
return $node;
}
return new TextNode($node->getAttribute('data'), $node->getTemplateLine());
}
if ($node instanceof PrintNode) {
// FIXME: deprecation
if (!$this->yielding) {
return $node;
}
return new YieldExpressionNode($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag());
}
if ($node instanceof TextNode) {
// FIXME: deprecation
if (!$this->yielding) {
return $node;
}
return new YieldTextNode($node->getAttribute('data'), $node->getTemplateLine());
}
return $node;
}
public function leaveNode(Node $node, Environment $env): ?Node
{
return $node;
}
public function getPriority(): int
{
return 255;
}
}
+3 -4
View File
@@ -22,9 +22,8 @@ use Twig\Node\ModuleNode;
use Twig\Node\Node;
use Twig\Node\NodeCaptureInterface;
use Twig\Node\NodeOutputInterface;
use Twig\Node\PrintNode;
use Twig\Node\TextNode;
use Twig\Node\YieldExpressionNode;
use Twig\Node\YieldTextNode;
use Twig\TokenParser\TokenParserInterface;
/**
@@ -120,14 +119,14 @@ class Parser
switch ($this->getCurrentToken()->getType()) {
case /* Token::TEXT_TYPE */ 0:
$token = $this->stream->next();
$rv[] = new YieldTextNode($token->getValue(), $token->getLine());
$rv[] = new TextNode($token->getValue(), $token->getLine());
break;
case /* Token::VAR_START_TYPE */ 2:
$token = $this->stream->next();
$expr = $this->expressionParser->parseExpression();
$this->stream->expect(/* Token::VAR_END_TYPE */ 4);
$rv[] = new YieldExpressionNode($expr, $token->getLine());
$rv[] = new PrintNode($expr, $token->getLine());
break;
case /* Token::BLOCK_START_TYPE */ 1:
+10 -3
View File
@@ -19,6 +19,8 @@ use Twig\Node\Node;
abstract class NodeTestCase extends TestCase
{
private Environment $currentEnv;
abstract public function getTests();
/**
@@ -48,7 +50,7 @@ abstract class NodeTestCase extends TestCase
protected function getEnvironment()
{
return new Environment(new ArrayLoader([]));
return $this->currentEnv = new Environment(new ArrayLoader([]));
}
protected function getVariableGetter($name, $line = false)
@@ -63,13 +65,18 @@ abstract class NodeTestCase extends TestCase
return 'CoreExtension::getAttribute($this->env, $this->source, ';
}
protected function getEchoOrYield(): string
{
return ($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield' : 'echo';
}
protected function getDisplayOrYield(string $expr): string
{
return sprintf($this->getEnvironment()->useYield() ? 'yield from %s->unwrap()->yield' : '%s->display', $expr);
return sprintf(($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield from %s->unwrap()->yield' : '%s->display', $expr);
}
protected function getDisplayOrYieldBlock(string $expr): string
{
return sprintf($this->getEnvironment()->useYield() ? 'yield from %s->unwrap()->yieldBlock' : '%s->displayBlock', $expr);
return sprintf(($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield from %s->unwrap()->yieldBlock' : '%s->displayBlock', $expr);
}
}
+2 -2
View File
@@ -13,8 +13,8 @@ namespace Twig\TokenParser;
use Twig\Node\Expression\TempNameExpression;
use Twig\Node\Node;
use Twig\Node\PrintNode;
use Twig\Node\SetNode;
use Twig\Node\YieldExpressionNode;
use Twig\Token;
/**
@@ -44,7 +44,7 @@ final class ApplyTokenParser extends AbstractTokenParser
return new Node([
new SetNode(true, $ref, $body, $lineno, $this->getTag()),
new YieldExpressionNode($filter, $lineno, $this->getTag()),
new PrintNode($filter, $lineno, $this->getTag()),
]);
}
+2 -2
View File
@@ -16,7 +16,7 @@ use Twig\Error\SyntaxError;
use Twig\Node\BlockNode;
use Twig\Node\BlockReferenceNode;
use Twig\Node\Node;
use Twig\Node\YieldExpressionNode;
use Twig\Node\PrintNode;
use Twig\Token;
/**
@@ -54,7 +54,7 @@ final class BlockTokenParser extends AbstractTokenParser
}
} else {
$body = new Node([
new YieldExpressionNode($this->parser->getExpressionParser()->parseExpression(), $lineno),
new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno),
]);
}
$stream->expect(/* Token::BLOCK_END_TYPE */ 3);
+2 -2
View File
@@ -18,7 +18,7 @@ use Twig\Extension\SandboxExtension;
use Twig\Extension\StringLoaderExtension;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Node;
use Twig\Node\YieldExpressionNode;
use Twig\Node\PrintNode;
use Twig\Sandbox\SecurityPolicy;
use Twig\Test\IntegrationTestCase;
use Twig\Token;
@@ -135,7 +135,7 @@ class TwigTestTokenParser_§ extends AbstractTokenParser
{
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
return new YieldExpressionNode(new ConstantExpression('§', -1), -1);
return new PrintNode(new ConstantExpression('§', -1), -1);
}
public function getTag(): string
+2 -1
View File
@@ -31,9 +31,10 @@ class AutoEscapeTest extends NodeTestCase
{
$body = new Node([new TextNode('foo', 1)]);
$node = new AutoEscapeNode(true, $body, 1);
$displayStmt = $this->getEchoOrYield();
return [
[$node, "// line 1\necho \"foo\";"],
[$node, "// line 1\n$displayStmt \"foo\";"],
];
}
}
+1 -2
View File
@@ -16,7 +16,6 @@ use Twig\Loader\ArrayLoader;
use Twig\Node\BlockNode;
use Twig\Node\Node;
use Twig\Node\TextNode;
use Twig\Node\YieldTextNode;
use Twig\Test\NodeTestCase;
class BlockTest extends NodeTestCase
@@ -34,7 +33,7 @@ class BlockTest extends NodeTestCase
{
$tests = [];
$tests[] = [new BlockNode('foo', new YieldTextNode('foo', 1), 1), <<<EOF
$tests[] = [new BlockNode('foo', new TextNode('foo', 1), 1), <<<EOF
// line 1
public function block_foo(\$context, array \$blocks = [])
{
+6 -5
View File
@@ -53,13 +53,14 @@ class ForTest extends NodeTestCase
$else = null;
$node = new ForNode($keyTarget, $valueTarget, $seq, null, $body, $else, 1);
$node->setAttribute('with_loop', false);
$displayStmt = $this->getEchoOrYield();
$tests[] = [$node, <<<EOF
// line 1
\$context['_parent'] = \$context;
\$context['_seq'] = CoreExtension::ensureTraversable({$this->getVariableGetter('items')});
foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
@@ -93,7 +94,7 @@ if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_
\$context['loop']['last'] = 1 === \$length;
}
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
++\$context['loop']['index0'];
++\$context['loop']['index'];
\$context['loop']['first'] = false;
@@ -135,7 +136,7 @@ if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_
\$context['loop']['last'] = 1 === \$length;
}
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
++\$context['loop']['index0'];
++\$context['loop']['index'];
\$context['loop']['first'] = false;
@@ -178,7 +179,7 @@ if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_
\$context['loop']['last'] = 1 === \$length;
}
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
\$context['_iterated'] = true;
++\$context['loop']['index0'];
++\$context['loop']['index'];
@@ -190,7 +191,7 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
}
}
if (!\$context['_iterated']) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
+6 -5
View File
@@ -47,11 +47,12 @@ class IfTest extends NodeTestCase
], [], 1);
$else = null;
$node = new IfNode($t, $else, 1);
$displayStmt = $this->getEchoOrYield();
$tests[] = [$node, <<<EOF
// line 1
if (true) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
}
EOF
];
@@ -68,9 +69,9 @@ EOF
$tests[] = [$node, <<<EOF
// line 1
if (true) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
} elseif (false) {
echo {$this->getVariableGetter('bar')};
$displayStmt {$this->getVariableGetter('bar')};
}
EOF
];
@@ -85,9 +86,9 @@ EOF
$tests[] = [$node, <<<EOF
// line 1
if (true) {
echo {$this->getVariableGetter('foo')};
$displayStmt {$this->getVariableGetter('foo')};
} else {
echo {$this->getVariableGetter('bar')};
$displayStmt {$this->getVariableGetter('bar')};
}
EOF
];
+1 -2
View File
@@ -18,7 +18,6 @@ use Twig\Node\Expression\NameExpression;
use Twig\Node\MacroNode;
use Twig\Node\Node;
use Twig\Node\TextNode;
use Twig\Node\YieldTextNode;
use Twig\Test\NodeTestCase;
class MacroTest extends NodeTestCase
@@ -43,7 +42,7 @@ class MacroTest extends NodeTestCase
'bar' => new ConstantExpression('Foo', 1),
], [], 1);
$body = new YieldTextNode('foo', 1);
$body = new TextNode('foo', 1);
$node = new MacroNode('foo', $body, $arguments, 1);
$text[] = [$node, <<<EOF
+2 -1
View File
@@ -56,6 +56,7 @@ class ModuleTest extends NodeTestCase
$traits = new Node();
$source = new Source('{{ foo }}', 'foo.twig');
$parentTemplate = $this->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template';
$displayStmt = $this->getEchoOrYield();
$node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source);
$tests[] = [$node, <<<EOF
@@ -96,7 +97,7 @@ class __TwigTemplate_%x extends $parentTemplate
{
\$macros = \$this->macros;
// line 1
echo "foo";
$displayStmt "foo";
}
/**
+3 -1
View File
@@ -28,7 +28,9 @@ class PrintTest extends NodeTestCase
public function getTests()
{
$tests = [];
$tests[] = [new PrintNode(new ConstantExpression('foo', 1), 1), "// line 1\necho \"foo\";"];
$displayStmt = $this->getEchoOrYield();
$tests[] = [new PrintNode(new ConstantExpression('foo', 1), 1), "// line 1\n$displayStmt \"foo\";"];
return $tests;
}
+2 -1
View File
@@ -31,6 +31,7 @@ class SandboxTest extends NodeTestCase
$body = new TextNode('foo', 1);
$node = new SandboxNode($body, 1);
$displayStmt = $this->getEchoOrYield();
$tests[] = [$node, <<<EOF
// line 1
@@ -38,7 +39,7 @@ if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) {
\$this->sandbox->enableSandbox();
}
try {
echo "foo";
$displayStmt "foo";
} finally {
if (!\$alreadySandboxed) {
\$this->sandbox->disableSandbox();
+1 -1
View File
@@ -55,7 +55,7 @@ EOF
$tests[] = [$node, <<<EOF
// line 1
\$context["foo"] = ('' === \$tmp = implode('', iterator_to_array((function () use (&\$context, \$macros, \$blocks) {
echo "foo";
yield "foo";
})() ?? new \EmptyIterator()))) ? '' : new Markup(\$tmp, \$this->env->getCharset());
EOF
, new Environment(new ArrayLoader(), ['use_yield' => true]),
+2 -1
View File
@@ -26,7 +26,8 @@ class TextTest extends NodeTestCase
public function getTests()
{
$tests = [];
$tests[] = [new TextNode('foo', 1), "// line 1\necho \"foo\";"];
$displayStmt = $this->getEchoOrYield();
$tests[] = [new TextNode('foo', 1), "// line 1\n$displayStmt \"foo\";"];
return $tests;
}