Move to PHPStan level 5

This commit is contained in:
Fabien Potencier
2026-02-07 08:50:23 +01:00
parent 825af0e7f1
commit b3cbcedced
10 changed files with 29 additions and 7 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ includes:
- phpstan-baseline.neon
parameters:
level: 4
level: 5
paths:
- src
excludePaths:
+1 -1
View File
@@ -495,7 +495,7 @@ class Environment
return $this->load($name);
}
throw new LoaderError(\sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
throw new LoaderError(\sprintf('Unable to find one of the following templates: "%s".', implode('", "', array_map(fn ($name) => $name instanceof TemplateWrapper ? $name->getTemplateName() : $name, $names))));
}
/**
@@ -12,6 +12,7 @@
namespace Twig\ExpressionParser\Infix;
use Twig\Error\SyntaxError;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\Binary\SetBinary;
use Twig\Node\Expression\Unary\SpreadUnary;
@@ -27,6 +28,7 @@ trait ArgumentsTrait
{
$arguments = new ArrayExpression([], $line);
foreach ($this->parseNamedArguments($parser, $parseOpenParenthesis) as $k => $n) {
/** @var AbstractExpression $n */
$arguments->addElement($n, new LocalVariable($k, $line));
}
@@ -20,6 +20,7 @@ use Twig\Node\EmptyNode;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\MacroReferenceExpression;
use Twig\Node\Expression\Variable\ContextVariable;
use Twig\Node\Expression\Variable\TemplateVariable;
use Twig\Parser;
use Twig\Token;
@@ -40,7 +41,10 @@ final class FunctionExpressionParser extends AbstractExpressionParser implements
$name = $expr->getAttribute('name');
if (null !== $alias = $parser->getImportedSymbol('function', $name)) {
return new MacroReferenceExpression($alias['node']->getNode('var'), $alias['name'], $this->parseCallableArguments($parser, $line, false), $line);
/** @var TemplateVariable $var */
$var = $alias['node']->getNode('var');
return new MacroReferenceExpression($var, $alias['name'], $this->parseCallableArguments($parser, $line, false), $line);
}
$args = $this->parseNamedArguments($parser, false);
@@ -19,6 +19,7 @@ use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\MacroReferenceExpression;
use Twig\Node\Expression\Variable\ContextVariable;
use Twig\Node\Expression\Variable\TemplateVariable;
use Twig\Node\Nodes;
use Twig\Parser;
use Twig\Token;
@@ -43,7 +44,9 @@ class IsExpressionParser extends AbstractExpressionParser implements InfixExpres
}
if ('defined' === $test->getName() && $expr instanceof ContextVariable && null !== $alias = $parser->getImportedSymbol('function', $expr->getAttribute('name'))) {
$expr = new MacroReferenceExpression($alias['node']->getNode('var'), $alias['name'], new ArrayExpression([], $expr->getTemplateLine()), $expr->getTemplateLine());
/** @var TemplateVariable $var */
$var = $alias['node']->getNode('var');
$expr = new MacroReferenceExpression($var, $alias['name'], new ArrayExpression([], $expr->getTemplateLine()), $expr->getTemplateLine());
}
return new ($test->getNodeClass())($expr, $test, $arguments, $stream->getCurrent()->getLine());
+4 -1
View File
@@ -2041,7 +2041,10 @@ final class CoreExtension extends AbstractExtension
$dep->triggerDeprecation($src->getPath() ?: $src->getName(), $line);
*/
return new GetAttrExpression($args[0], $args[1], $args[2] ?? null, Template::ANY_CALL, $line);
/** @var ArrayExpression|ContextVariable|null $arguments */
$arguments = $args[2] ?? null;
return new GetAttrExpression($args[0], $args[1], $arguments, Template::ANY_CALL, $line);
}
/**
@@ -42,6 +42,7 @@ class DefaultFilter extends FilterExpression
if ('default' === $name && ($node instanceof ContextVariable || $node instanceof GetAttrExpression)) {
$test = new DefinedTest(clone $node, new TwigTest('defined'), new EmptyNode(), $node->getTemplateLine());
/** @var AbstractExpression $false */
$false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine());
$node = new ConditionalTernary($test, $default, $false, $node->getTemplateLine());
+2
View File
@@ -14,6 +14,7 @@ namespace Twig\Node;
use Twig\Attribute\YieldReady;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ReturnPrimitiveTypeInterface;
use Twig\Node\Expression\Test\TrueTest;
use Twig\TwigTest;
@@ -31,6 +32,7 @@ class IfNode extends Node
for ($i = 0, $count = \count($tests); $i < $count; $i += 2) {
$test = $tests->getNode((string) $i);
if (!$test instanceof ReturnPrimitiveTypeInterface) {
/** @var AbstractExpression $test */
$tests->setNode($i, new TrueTest($test, new TwigTest('true'), null, $test->getTemplateLine()));
}
}
+4
View File
@@ -80,8 +80,10 @@ final class EscaperNodeVisitor implements NodeVisitorInterface
} elseif ($node instanceof FilterExpression) {
return $this->preEscapeFilterNode($node, $env);
} elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping()) {
/** @var AbstractExpression $expression */
$expression = $node->getNode('expr');
if ($expression instanceof OperatorEscapeInterface) {
/** @var AbstractExpression&OperatorEscapeInterface $expression */
$this->escapeConditional($expression, $env, $type);
} else {
$node->setNode('expr', $this->escapeExpression($expression, $env, $type));
@@ -102,8 +104,10 @@ final class EscaperNodeVisitor implements NodeVisitorInterface
private function escapeConditional(AbstractExpression&OperatorEscapeInterface $expression, Environment $env, string $type): void
{
foreach ($expression->getOperandNamesToEscape() as $name) {
/** @var AbstractExpression $operand */
$operand = $expression->getNode($name);
if ($operand instanceof OperatorEscapeInterface) {
/** @var AbstractExpression&OperatorEscapeInterface $operand */
$this->escapeConditional($operand, $env, $type);
} else {
$expression->setNode($name, $this->escapeExpression($operand, $env, $type));
+5 -2
View File
@@ -12,6 +12,7 @@
namespace Twig\Util;
use Twig\Error\SyntaxError;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\VariadicExpression;
@@ -35,15 +36,16 @@ final class CallableArgumentsExtractor
}
/**
* @return array<Node>
* @return array<AbstractExpression>
*/
public function extractArguments(Node $arguments): array
{
/** @var array<int|string, Node> $extractedArguments */
/** @var array<int|string, AbstractExpression> $extractedArguments */
$extractedArguments = [];
$extractedArgumentNameMap = [];
$named = false;
foreach ($arguments as $name => $node) {
/** @var AbstractExpression $node */
if (!\is_int($name)) {
$named = true;
} elseif ($named) {
@@ -74,6 +76,7 @@ final class CallableArgumentsExtractor
}
[$callableParameters, $isPhpVariadic] = $this->getCallableParameters();
/** @var list<AbstractExpression> $arguments */
$arguments = [];
$callableParameterNames = [];
$missingArguments = [];