From fcde1ca1168dea602c54e3a9ee98d60f7ae57c2d Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 30 Apr 2025 12:25:42 +0200 Subject: [PATCH 1/2] Fix crash on dynamic numeric-string symbols --- src/Rules/Classes/ClassConstantRule.php | 6 +++++- src/Rules/Methods/CallMethodsRule.php | 6 +++++- src/Rules/Methods/CallStaticMethodsRule.php | 6 +++++- src/Rules/Variables/DefinedVariableRule.php | 6 +++++- .../Analyser/AnalyserIntegrationTest.php | 9 +++++++++ tests/PHPStan/Analyser/data/bug-12949.php | 19 +++++++++++++++++++ 6 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-12949.php diff --git a/src/Rules/Classes/ClassConstantRule.php b/src/Rules/Classes/ClassConstantRule.php index 2d08602985..a14428d890 100644 --- a/src/Rules/Classes/ClassConstantRule.php +++ b/src/Rules/Classes/ClassConstantRule.php @@ -64,7 +64,11 @@ public function processNode(Node $node, Scope $scope): array } foreach ($constantNameScopes as $constantName => $constantScope) { - $errors = array_merge($errors, $this->processSingleClassConstFetch($constantScope, $node, $constantName)); + $errors = array_merge($errors, $this->processSingleClassConstFetch( + $constantScope, + $node, + (string) $constantName, // @phpstan-ignore cast.useless + )); } return $errors; diff --git a/src/Rules/Methods/CallMethodsRule.php b/src/Rules/Methods/CallMethodsRule.php index 8c01d0118a..984e5c8efe 100644 --- a/src/Rules/Methods/CallMethodsRule.php +++ b/src/Rules/Methods/CallMethodsRule.php @@ -47,7 +47,11 @@ public function processNode(Node $node, Scope $scope): array } foreach ($methodNameScopes as $methodName => $methodScope) { - $errors = array_merge($errors, $this->processSingleMethodCall($methodScope, $node, $methodName)); + $errors = array_merge($errors, $this->processSingleMethodCall( + $methodScope, + $node, + (string) $methodName, // @phpstan-ignore cast.useless + )); } return $errors; diff --git a/src/Rules/Methods/CallStaticMethodsRule.php b/src/Rules/Methods/CallStaticMethodsRule.php index 954c3a8669..04ffc64325 100644 --- a/src/Rules/Methods/CallStaticMethodsRule.php +++ b/src/Rules/Methods/CallStaticMethodsRule.php @@ -48,7 +48,11 @@ public function processNode(Node $node, Scope $scope): array } foreach ($methodNameScopes as $methodName => $methodScope) { - $errors = array_merge($errors, $this->processSingleMethodCall($methodScope, $node, $methodName)); + $errors = array_merge($errors, $this->processSingleMethodCall( + $methodScope, + $node, + (string) $methodName, // @phpstan-ignore cast.useless + )); } return $errors; diff --git a/src/Rules/Variables/DefinedVariableRule.php b/src/Rules/Variables/DefinedVariableRule.php index 2c7163434c..2056a89dbe 100644 --- a/src/Rules/Variables/DefinedVariableRule.php +++ b/src/Rules/Variables/DefinedVariableRule.php @@ -48,7 +48,11 @@ public function processNode(Node $node, Scope $scope): array } foreach ($variableNameScopes as $name => $variableScope) { - $errors = array_merge($errors, $this->processSingleVariable($variableScope, $node, $name)); + $errors = array_merge($errors, $this->processSingleVariable( + $variableScope, + $node, + (string) $name, // @phpstan-ignore cast.useless + )); } return $errors; diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 156b26cffa..910e8fbfb3 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1570,6 +1570,15 @@ public function testBug12800(): void $this->assertNoErrors($errors); } + public function testBug12949(): void + { + $errors = $this->runAnalyse(__DIR__ . '/data/bug-12949.php'); + $this->assertCount(3, $errors); + $this->assertSame('Call to an undefined method object::0().', $errors[0]->getMessage()); + $this->assertSame('Call to an undefined static method object::0().', $errors[1]->getMessage()); + $this->assertSame('Access to undefined constant object::0.', $errors[2]->getMessage()); + } + /** * @param string[]|null $allAnalysedFiles * @return Error[] diff --git a/tests/PHPStan/Analyser/data/bug-12949.php b/tests/PHPStan/Analyser/data/bug-12949.php new file mode 100644 index 0000000000..eeafccb0de --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-12949.php @@ -0,0 +1,19 @@ +{$b}(); + $o::{$b}(); + echo $o::{$b}; + + echo ""; +} From 6e327c282e084381f0e7bad3f8ec529759db2572 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 30 Apr 2025 12:39:36 +0200 Subject: [PATCH 2/2] fix test pre php 8.3 --- tests/PHPStan/Analyser/AnalyserIntegrationTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 910e8fbfb3..c94a5cff18 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1572,6 +1572,11 @@ public function testBug12800(): void public function testBug12949(): void { + // Fetching class constants with a dynamic name is supported only on PHP 8.3 and later + if (PHP_VERSION_ID < 80300) { + $this->markTestSkipped('Test requires PHP 8.3.'); + } + $errors = $this->runAnalyse(__DIR__ . '/data/bug-12949.php'); $this->assertCount(3, $errors); $this->assertSame('Call to an undefined method object::0().', $errors[0]->getMessage());