Skip to content

Commit

Permalink
fix wrong inClassLike after stack pop
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Oct 8, 2024
1 parent 287f74f commit 9d57607
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/Parser/VariadicMethodsVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
use PHPStan\TrinaryLogic;
use function array_key_exists;
use function array_pop;
use function count;
use function implode;
use function in_array;
use function sprintf;
use function str_contains;

final class VariadicMethodsVisitor extends NodeVisitorAbstract
{
Expand All @@ -33,6 +35,8 @@ final class VariadicMethodsVisitor extends NodeVisitorAbstract

public const ATTRIBUTE_NAME = 'variadicMethods';

private const ANONYMOUS_CLASS_PREFIX = 'class@anonymous';

public function beforeTraverse(array $nodes): ?array
{
$this->topNode = null;
Expand All @@ -57,7 +61,7 @@ public function enterNode(Node $node): ?Node

if ($node instanceof Node\Stmt\ClassLike) {
if (!$node->name instanceof Node\Identifier) {
$className = sprintf('class@anonymous:%s:%s', $node->getStartLine(), $node->getEndLine());
$className = sprintf('%s:%s:%s', self::ANONYMOUS_CLASS_PREFIX, $node->getStartLine(), $node->getEndLine());
$this->classStack[] = $className;
$this->inClassLike = $className; // anonymous classes are in global namespace
} else {
Expand Down Expand Up @@ -105,7 +109,13 @@ public function leaveNode(Node $node): ?Node
array_pop($this->classStack);

if ($this->classStack !== []) {
$this->inClassLike = $this->inNamespace !== null ? $this->inNamespace . '\\' . implode('\\', $this->classStack) : implode('\\', $this->classStack);
$lastClass = $this->classStack[count($this->classStack) - 1];

if (str_contains($lastClass, self::ANONYMOUS_CLASS_PREFIX)) {
$this->inClassLike = $lastClass;
} else {
$this->inClassLike = $this->inNamespace !== null ? $this->inNamespace . '\\' . implode('\\', $this->classStack) : implode('\\', $this->classStack);
}
} else {
$this->inClassLike = null;
}
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Parser/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public function dataVariadicCallLikes(): iterable
'implicit_variadic_fn' => TrinaryLogic::createYes(),
],
'class@anonymous:54:54' => [],
'class@anonymous:61:68' => [
'nestedClass' => TrinaryLogic::createNo(),
'implicit_variadic_fn' => TrinaryLogic::createYes(),
],
'class@anonymous:63:63' => [],
],
];

Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Parser/data/variadic-methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,13 @@ function implicit_variadic_fn() {
$args = func_get_args();
}
};


$c = new class () {
function nestedClass() {
$nested = new class () {};
}
function implicit_variadic_fn() {
$args = func_get_args();
}
};

0 comments on commit 9d57607

Please sign in to comment.