mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-30 20:16:45 +00:00
Use generics in ExpressionParsers
This commit is contained in:
@@ -162,10 +162,10 @@ class ExpressionParser
|
||||
$parsers = new \ReflectionProperty($this->parser, 'parsers');
|
||||
|
||||
if ('.' === $this->parser->getStream()->next()->getValue()) {
|
||||
return $parsers->getValue($this->parser)->getInfixByClass(DotExpressionParser::class)->parse($this->parser, $node, $this->parser->getCurrentToken());
|
||||
return $parsers->getValue($this->parser)->getByClass(DotExpressionParser::class)->parse($this->parser, $node, $this->parser->getCurrentToken());
|
||||
}
|
||||
|
||||
return $parsers->getValue($this->parser)->getInfixByClass(SquareBracketExpressionParser::class)->parse($this->parser, $node, $this->parser->getCurrentToken());
|
||||
return $parsers->getValue($this->parser)->getByClass(SquareBracketExpressionParser::class)->parse($this->parser, $node, $this->parser->getCurrentToken());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ class ExpressionParser
|
||||
|
||||
$parsers = new \ReflectionProperty($this->parser, 'parsers');
|
||||
|
||||
$op = $parsers->getValue($this->parser)->getInfixByClass(FilterExpressionParser::class);
|
||||
$op = $parsers->getValue($this->parser)->getByClass(FilterExpressionParser::class);
|
||||
while (true) {
|
||||
$node = $op->parse($this->parser, $node, $this->parser->getCurrentToken());
|
||||
if (!$this->parser->getStream()->test(Token::OPERATOR_TYPE, '|')) {
|
||||
|
||||
@@ -19,20 +19,15 @@ namespace Twig\ExpressionParser;
|
||||
final class ExpressionParsers implements \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var array<value-of<ExpressionParserType>, array<string, ExpressionParserInterface>>
|
||||
* @var array<class-string<ExpressionParserInterface>, array<string, ExpressionParserInterface>>
|
||||
*/
|
||||
private array $parsers = [];
|
||||
private array $parsersByName = [];
|
||||
|
||||
/**
|
||||
* @var array<value-of<ExpressionParserType>, array<class-string<ExpressionParserInterface>, ExpressionParserInterface>>
|
||||
* @var array<class-string<ExpressionParserInterface>, ExpressionParserInterface>
|
||||
*/
|
||||
private array $parsersByClass = [];
|
||||
|
||||
/**
|
||||
* @var array<value-of<ExpressionParserType>, array<string, ExpressionParserInterface>>
|
||||
*/
|
||||
private array $aliases = [];
|
||||
|
||||
/**
|
||||
* @var \WeakMap<ExpressionParserInterface, array<ExpressionParserInterface>>|null
|
||||
*/
|
||||
@@ -59,11 +54,11 @@ final class ExpressionParsers implements \IteratorAggregate
|
||||
trigger_deprecation('twig/twig', '3.20', 'Precedence for "%s" must be between 0 and 512, got %d.', $parser->getName(), $parser->getPrecedence());
|
||||
// throw new \InvalidArgumentException(\sprintf('Precedence for "%s" must be between 0 and 512, got %d.', $parser->getName(), $parser->getPrecedence()));
|
||||
}
|
||||
$type = ExpressionParserType::getType($parser);
|
||||
$this->parsers[$type->value][$parser->getName()] = $parser;
|
||||
$this->parsersByClass[$type->value][get_class($parser)] = $parser;
|
||||
$interface = $parser instanceof PrefixExpressionParserInterface ? PrefixExpressionParserInterface::class : InfixExpressionParserInterface::class;
|
||||
$this->parsersByName[$interface][$parser->getName()] = $parser;
|
||||
$this->parsersByClass[get_class($parser)] = $parser;
|
||||
foreach ($parser->getAliases() as $alias) {
|
||||
$this->aliases[$type->value][$alias] = $parser;
|
||||
$this->parsersByName[$interface][$alias] = $parser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,42 +66,32 @@ final class ExpressionParsers implements \IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<PrefixExpressionParserInterface> $name
|
||||
* @template T of ExpressionParserInterface
|
||||
*
|
||||
* @param class-string<T> $class
|
||||
*
|
||||
* @return T|null
|
||||
*/
|
||||
public function getPrefixByClass(string $name): ?PrefixExpressionParserInterface
|
||||
public function getByClass(string $class): ?ExpressionParserInterface
|
||||
{
|
||||
return $this->parsersByClass[ExpressionParserType::Prefix->value][$name] ?? null;
|
||||
}
|
||||
|
||||
public function getPrefix(string $name): ?PrefixExpressionParserInterface
|
||||
{
|
||||
return
|
||||
$this->parsers[ExpressionParserType::Prefix->value][$name]
|
||||
?? $this->aliases[ExpressionParserType::Prefix->value][$name]
|
||||
?? null
|
||||
;
|
||||
return $this->parsersByClass[$class] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<InfixExpressionParserInterface> $name
|
||||
* @template T of ExpressionParserInterface
|
||||
*
|
||||
* @param class-string<T> $interface
|
||||
*
|
||||
* @return T|null
|
||||
*/
|
||||
public function getInfixByClass(string $name): ?InfixExpressionParserInterface
|
||||
public function getByName(string $interface, string $name): ?ExpressionParserInterface
|
||||
{
|
||||
return $this->parsersByClass[ExpressionParserType::Infix->value][$name] ?? null;
|
||||
}
|
||||
|
||||
public function getInfix(string $name): ?InfixExpressionParserInterface
|
||||
{
|
||||
return
|
||||
$this->parsers[ExpressionParserType::Infix->value][$name]
|
||||
?? $this->aliases[ExpressionParserType::Infix->value][$name]
|
||||
?? null
|
||||
;
|
||||
return $this->parsersByName[$interface][$name] ?? null;
|
||||
}
|
||||
|
||||
public function getIterator(): \Traversable
|
||||
{
|
||||
foreach ($this->parsers as $parsers) {
|
||||
foreach ($this->parsersByName as $parsers) {
|
||||
// we don't yield the keys
|
||||
yield from $parsers;
|
||||
}
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@ use Twig\Error\SyntaxError;
|
||||
use Twig\ExpressionParser\ExpressionParserInterface;
|
||||
use Twig\ExpressionParser\ExpressionParsers;
|
||||
use Twig\ExpressionParser\ExpressionParserType;
|
||||
use Twig\ExpressionParser\InfixExpressionParserInterface;
|
||||
use Twig\ExpressionParser\Prefix\LiteralExpressionParser;
|
||||
use Twig\ExpressionParser\PrefixExpressionParserInterface;
|
||||
use Twig\Node\BlockNode;
|
||||
@@ -357,16 +358,16 @@ class Parser
|
||||
public function parseExpression(int $precedence = 0): AbstractExpression
|
||||
{
|
||||
$token = $this->getCurrentToken();
|
||||
if ($token->test(Token::OPERATOR_TYPE) && $ep = $this->parsers->getPrefix($token->getValue())) {
|
||||
if ($token->test(Token::OPERATOR_TYPE) && $ep = $this->parsers->getByName(PrefixExpressionParserInterface::class, $token->getValue())) {
|
||||
$this->getStream()->next();
|
||||
$expr = $ep->parse($this, $token);
|
||||
$this->checkPrecedenceDeprecations($ep, $expr);
|
||||
} else {
|
||||
$expr = $this->parsers->getPrefixByClass(LiteralExpressionParser::class)->parse($this, $token);
|
||||
$expr = $this->parsers->getByClass(LiteralExpressionParser::class)->parse($this, $token);
|
||||
}
|
||||
|
||||
$token = $this->getCurrentToken();
|
||||
while ($token->test(Token::OPERATOR_TYPE) && ($ep = $this->parsers->getInfix($token->getValue())) && $ep->getPrecedence() >= $precedence) {
|
||||
while ($token->test(Token::OPERATOR_TYPE) && ($ep = $this->parsers->getByName(InfixExpressionParserInterface::class, $token->getValue())) && $ep->getPrecedence() >= $precedence) {
|
||||
$this->getStream()->next();
|
||||
$expr = $ep->parse($this, $expr, $token);
|
||||
$this->checkPrecedenceDeprecations($ep, $expr);
|
||||
|
||||
@@ -35,7 +35,7 @@ final class ApplyTokenParser extends AbstractTokenParser
|
||||
$lineno = $token->getLine();
|
||||
$ref = new LocalVariable(null, $lineno);
|
||||
$filter = $ref;
|
||||
$op = $this->parser->getEnvironment()->getExpressionParsers()->getInfixByClass(FilterExpressionParser::class);
|
||||
$op = $this->parser->getEnvironment()->getExpressionParsers()->getByClass(FilterExpressionParser::class);
|
||||
while (true) {
|
||||
$filter = $op->parse($this->parser, $filter, $this->parser->getCurrentToken());
|
||||
if (!$this->parser->getStream()->test(Token::OPERATOR_TYPE, '|')) {
|
||||
|
||||
@@ -19,7 +19,9 @@ use Twig\Environment;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\ExpressionParser\Infix\BinaryOperatorExpressionParser;
|
||||
use Twig\ExpressionParser\InfixExpressionParserInterface;
|
||||
use Twig\ExpressionParser\Prefix\UnaryOperatorExpressionParser;
|
||||
use Twig\ExpressionParser\PrefixExpressionParserInterface;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\Extension\ExtensionInterface;
|
||||
use Twig\Extension\GlobalsInterface;
|
||||
@@ -309,8 +311,8 @@ class EnvironmentTest extends TestCase
|
||||
$this->assertArrayHasKey('foo_filter', $twig->getFilters());
|
||||
$this->assertArrayHasKey('foo_function', $twig->getFunctions());
|
||||
$this->assertArrayHasKey('foo_test', $twig->getTests());
|
||||
$this->assertNotNull($twig->getExpressionParsers()->getPrefix('foo_unary'));
|
||||
$this->assertNotNull($twig->getExpressionParsers()->getInfix('foo_binary'));
|
||||
$this->assertNotNull($twig->getExpressionParsers()->getByName(PrefixExpressionParserInterface::class, 'foo_unary'));
|
||||
$this->assertNotNull($twig->getExpressionParsers()->getByName(InfixExpressionParserInterface::class, 'foo_binary'));
|
||||
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
||||
$visitors = $twig->getNodeVisitors();
|
||||
$found = false;
|
||||
|
||||
Reference in New Issue
Block a user