Add getOperatorTokens() to ExpressionParserInterface to separate operator token registration from parser identity

This commit is contained in:
Fabien Potencier
2026-02-23 23:12:24 +01:00
parent 2ec5479d4c
commit e5eb95d0d7
10 changed files with 115 additions and 29 deletions
+33
View File
@@ -27,7 +27,10 @@ use Twig\Compiler;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\ExpressionParser\InfixExpressionParserInterface;
use Twig\ExpressionParser\Prefix\LiteralExpressionParser;
use Twig\ExpressionParser\Prefix\UnaryOperatorExpressionParser;
use Twig\ExpressionParser\PrefixExpressionParserInterface;
use Twig\Extension\AbstractExtension;
use Twig\Loader\ArrayLoader;
use Twig\Node\Expression\ArrayExpression;
@@ -796,6 +799,36 @@ class ExpressionParserTest extends TestCase
yield '= stronger than logical' => ['{% do a = false or true %}{{ a }}', '{% do a = (false or true) %}{{ a }}', eval('$a = false || true; return $a;')];
yield '= stronger than ternary' => ['{% do c = 4 ? 0 : -1 %}{{ c }}', '{% do c = (4 ? 0 : -1) %}{{ c }}', eval('return 4 ? 0 : -1;')];
}
public function testLiteralExpressionParserGetOperatorTokensReturnsEmptyArray()
{
$env = new Environment(new ArrayLoader());
$parser = $env->getExpressionParsers()->getByClass(LiteralExpressionParser::class);
$this->assertSame([], $parser->getOperatorTokens());
$this->assertSame('literal', $parser->getName());
}
public function testExpressionParserGetOperatorTokensDefaultBehavior()
{
$env = new Environment(new ArrayLoader());
foreach ($env->getExpressionParsers() as $parser) {
if ($parser instanceof LiteralExpressionParser) {
continue;
}
$expected = [$parser->getName(), ...$parser->getAliases()];
$this->assertSame($expected, $parser->getOperatorTokens(), \sprintf('getOperatorTokens() for %s should return name + aliases.', $parser::class));
}
}
public function testLiteralIsNotRegisteredAsOperator()
{
// Ensure "literal" is not in the operator registry
$env = new Environment(new ArrayLoader());
$this->assertNull($env->getExpressionParsers()->getByName(PrefixExpressionParserInterface::class, 'literal'));
$this->assertNull($env->getExpressionParsers()->getByName(InfixExpressionParserInterface::class, 'literal'));
}
}
class NotReadyFunctionExpression extends FunctionExpression