diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6d94e410929..d3077dc485e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,8 +2,9 @@ includes: - phpstan-baseline.neon parameters: - level: 3 + level: 4 paths: - src excludePaths: - src/Test + treatPhpDocTypesAsCertain: false diff --git a/src/Environment.php b/src/Environment.php index 80c578d766d..a9cbb0b44e5 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -371,6 +371,7 @@ public function loadTemplate(string $cls, string $name, ?int $index = null): Tem if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { $this->cache->load($key); + /** @var class-string $cls -- to reset `class_exists($cls, false)` result for PHPStan */ } if (!class_exists($cls, false)) { @@ -379,6 +380,7 @@ public function loadTemplate(string $cls, string $name, ?int $index = null): Tem if (!isset($this->hotCache[$name])) { $this->cache->write($key, $content); $this->cache->load($key); + /** @var class-string $cls -- to reset `class_exists($cls, false)` result for PHPStan */ } if (!class_exists($mainCls, false)) { diff --git a/src/Error/Error.php b/src/Error/Error.php index 3ccdda2cdc3..bfb5f6e44dd 100644 --- a/src/Error/Error.php +++ b/src/Error/Error.php @@ -142,12 +142,7 @@ private function updateRepr(): void } if ($this->name) { - if (\is_string($this->name) || $this->name instanceof \Stringable) { - $name = \sprintf('"%s"', $this->name); - } else { - $name = json_encode($this->name); - } - $this->message .= \sprintf(' in %s', $name); + $this->message .= \sprintf(' in "%s"', $this->name); } if ($this->lineno && $this->lineno >= 0) { diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 88dbc58a46c..9f01341dd3b 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1199,7 +1199,7 @@ public static function length(string $charset, $thing): int return mb_strlen($thing, $charset); } - if (is_countable($thing) || $thing instanceof \SimpleXMLElement) { + if (is_countable($thing)) { return \count($thing); } diff --git a/src/NodeVisitor/EscaperNodeVisitor.php b/src/NodeVisitor/EscaperNodeVisitor.php index 31e0bd75e19..851bde43bf8 100644 --- a/src/NodeVisitor/EscaperNodeVisitor.php +++ b/src/NodeVisitor/EscaperNodeVisitor.php @@ -71,7 +71,7 @@ public function enterNode(Node $node, Environment $env): Node return $node; } - public function leaveNode(Node $node, Environment $env): ?Node + public function leaveNode(Node $node, Environment $env): Node { if ($node instanceof ModuleNode) { $this->defaultStrategy = false; diff --git a/src/NodeVisitor/OptimizerNodeVisitor.php b/src/NodeVisitor/OptimizerNodeVisitor.php index 4f92ce14f14..734363f0e8e 100644 --- a/src/NodeVisitor/OptimizerNodeVisitor.php +++ b/src/NodeVisitor/OptimizerNodeVisitor.php @@ -72,7 +72,7 @@ public function enterNode(Node $node, Environment $env): Node return $node; } - public function leaveNode(Node $node, Environment $env): ?Node + public function leaveNode(Node $node, Environment $env): Node { if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { $this->leaveOptimizeFor($node); diff --git a/src/NodeVisitor/SafeAnalysisNodeVisitor.php b/src/NodeVisitor/SafeAnalysisNodeVisitor.php index a38bb63ce49..1dce9b51b5e 100644 --- a/src/NodeVisitor/SafeAnalysisNodeVisitor.php +++ b/src/NodeVisitor/SafeAnalysisNodeVisitor.php @@ -84,7 +84,7 @@ public function enterNode(Node $node, Environment $env): Node return $node; } - public function leaveNode(Node $node, Environment $env): ?Node + public function leaveNode(Node $node, Environment $env): Node { if ($node instanceof ConstantExpression) { // constants are marked safe for all diff --git a/src/NodeVisitor/SandboxNodeVisitor.php b/src/NodeVisitor/SandboxNodeVisitor.php index f9724353d1f..1cb4bcb16a4 100644 --- a/src/NodeVisitor/SandboxNodeVisitor.php +++ b/src/NodeVisitor/SandboxNodeVisitor.php @@ -103,7 +103,7 @@ public function enterNode(Node $node, Environment $env): Node return $node; } - public function leaveNode(Node $node, Environment $env): ?Node + public function leaveNode(Node $node, Environment $env): Node { if ($node instanceof ModuleNode) { $this->inAModule = false; diff --git a/src/Parser.php b/src/Parser.php index 1b10a656187..6fdb9cbd5bc 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -152,6 +152,9 @@ public function subparseIgnoreUnknownTwigCallables($test, bool $dropNeedle = fal } } + /** + * @phpstan-impure + */ public function subparse($test, bool $dropNeedle = false): Node { $lineno = $this->getCurrentToken()->getLine(); @@ -362,7 +365,7 @@ private function filterBodyNodes(Node $node, bool $nested = false): ?Node // we need to discard the wrapping "Node" for the "body" node $nested = $nested || !$node instanceof Nodes; foreach ($node as $k => $n) { - if (null !== $n && null === $this->filterBodyNodes($n, $nested)) { + if (null === $this->filterBodyNodes($n, $nested)) { $node->removeNode($k); } } diff --git a/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php index ad7ce623400..a587260dd70 100644 --- a/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php +++ b/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php @@ -41,7 +41,7 @@ public function enterNode(Node $node, Environment $env): Node return $node; } - public function leaveNode(Node $node, Environment $env): ?Node + public function leaveNode(Node $node, Environment $env): Node { if ($node instanceof ModuleNode) { $node->setNode('display_start', new Nodes([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $this->varName), $node->getNode('display_start')])); diff --git a/src/TokenStream.php b/src/TokenStream.php index 4ff299d5ed0..191c91085ca 100644 --- a/src/TokenStream.php +++ b/src/TokenStream.php @@ -44,6 +44,8 @@ public function injectTokens(array $tokens) /** * Sets the pointer to the next token and returns the old one. + * + * @phpstan-impure */ public function next(): Token { @@ -58,6 +60,8 @@ public function next(): Token * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. * * @return Token|null The next token if the condition is true, null otherwise + * + * @phpstan-impure */ public function nextIf($primary, $secondary = null) { @@ -66,6 +70,8 @@ public function nextIf($primary, $secondary = null) /** * Tests a token and returns it or throws a syntax error. + * + * @phpstan-impure */ public function expect($type, $value = null, ?string $message = null): Token { diff --git a/src/Util/CallableArgumentsExtractor.php b/src/Util/CallableArgumentsExtractor.php index 8ca8bb602c5..c129a320a0d 100644 --- a/src/Util/CallableArgumentsExtractor.php +++ b/src/Util/CallableArgumentsExtractor.php @@ -39,6 +39,7 @@ public function __construct( */ public function extractArguments(Node $arguments): array { + /** @var array $extractedArguments */ $extractedArguments = []; $extractedArgumentNameMap = []; $named = false; diff --git a/src/Util/ReflectionCallable.php b/src/Util/ReflectionCallable.php index 5fd5d1ba754..31207201bd0 100644 --- a/src/Util/ReflectionCallable.php +++ b/src/Util/ReflectionCallable.php @@ -77,7 +77,7 @@ public function getReflector(): \ReflectionFunctionAbstract return $this->reflector; } - public function getCallable(): \Closure|string|array|null + public function getCallable(): \Closure|string|array { return $this->callable; }