diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 7c97dfe518..1b48497491 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -87,6 +87,7 @@ use PHPStan\Type\UnionType; use PHPStan\Type\VerbosityLevel; use PHPStan\Type\VoidType; +use function array_key_exists; class MutatingScope implements Scope { @@ -2269,7 +2270,8 @@ public function enterClassMethod( $isDeprecated, $isInternal, $isFinal - ) + ), + !$classMethod->isStatic() ); } @@ -2354,12 +2356,14 @@ public function enterFunction( $isDeprecated, $isInternal, $isFinal - ) + ), + false ); } private function enterFunctionLike( - PhpFunctionFromParserNodeReflection $functionReflection + PhpFunctionFromParserNodeReflection $functionReflection, + bool $preserveThis ): self { $variableTypes = $this->getVariableTypes(); @@ -2373,6 +2377,10 @@ private function enterFunctionLike( $nativeExpressionTypes[sprintf('$%s', $parameter->getName())] = $parameter->getNativeType(); } + if (!$preserveThis && array_key_exists('this', $variableTypes)) { + unset($variableTypes['this']); + } + return $this->scopeFactory->create( $this->context, $this->isDeclareStrictTypes(), diff --git a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php index 0967819bb3..d82872d89e 100644 --- a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php +++ b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php @@ -744,4 +744,50 @@ public function testRootScopeMaybeDefined(): void $this->analyse([__DIR__ . '/data/root-scope-maybe.php'], []); } + public function testRootScopeMaybeDefinedCheck(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->polluteCatchScopeWithTryAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + $this->analyse([__DIR__ . '/data/root-scope-maybe.php'], [ + [ + 'Variable $maybe might not be defined.', + 3, + ], + [ + 'Variable $this might not be defined.', + 5, + ], + ]); + } + + public function testFormerThisVariableRule(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->polluteCatchScopeWithTryAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + $this->analyse([__DIR__ . '/data/this.php'], [ + [ + 'Undefined variable: $this', + 16, + ], + [ + 'Undefined variable: $this', + 20, + ], + [ + 'Undefined variable: $this', + 26, + ], + [ + 'Undefined variable: $this', + 38, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/root-scope-maybe.php b/tests/PHPStan/Rules/Variables/data/root-scope-maybe.php index 58c84f167b..9bfaf528a8 100644 --- a/tests/PHPStan/Rules/Variables/data/root-scope-maybe.php +++ b/tests/PHPStan/Rules/Variables/data/root-scope-maybe.php @@ -1,3 +1,5 @@ test; - $foo->test; + } public static function doBar() { $this->test; - $foo->test; - $$bar->test; + + $this->blabla = 'fooo'; }