From e832df4e9912e2a0616922f508290dafefcf73a0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 23 Jan 2021 12:59:42 +0100 Subject: [PATCH] Inline `@var` above property should not pollute scope inside methods --- src/Analyser/MutatingScope.php | 6 +++--- src/Analyser/NodeScopeResolver.php | 4 ++++ .../Variables/DefinedVariableRuleTest.php | 15 ++++++++++++++ .../PHPStan/Rules/Variables/data/bug-4412.php | 20 +++++++++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 tests/PHPStan/Rules/Variables/data/bug-4412.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 31b8af5e49..ea967494ba 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2663,7 +2663,7 @@ private function enterFunctionLike( bool $preserveThis ): self { - $variableTypes = $this->getVariableTypes(); + $variableTypes = []; $nativeExpressionTypes = []; foreach (ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getParameters() as $parameter) { $parameterType = $parameter->getType(); @@ -2674,8 +2674,8 @@ private function enterFunctionLike( $nativeExpressionTypes[sprintf('$%s', $parameter->getName())] = $parameter->getNativeType(); } - if (!$preserveThis && array_key_exists('this', $variableTypes)) { - unset($variableTypes['this']); + if ($preserveThis && array_key_exists('this', $this->variableTypes)) { + $variableTypes['this'] = $this->variableTypes['this']; } return $this->scopeFactory->create( diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index dc94fe0a97..70de374379 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -2777,6 +2777,10 @@ private function processStmtVarAnnotation(MutatingScope $scope, Node\Stmt $stmt, continue; } + if ($scope->isInClass() && $scope->getFunction() === null) { + continue; + } + if ($scope->canAnyVariableExist()) { $certainty = TrinaryLogic::createYes(); } diff --git a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php index 5fd71c1d07..41150a8c21 100644 --- a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php +++ b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php @@ -884,4 +884,19 @@ public function testBug3515(): void ]); } + public function testBug4412(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->polluteCatchScopeWithTryAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + $this->analyse([__DIR__ . '/data/bug-4412.php'], [ + [ + 'Undefined variable: $a', + 17, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/bug-4412.php b/tests/PHPStan/Rules/Variables/data/bug-4412.php new file mode 100644 index 0000000000..a8fd1970fe --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-4412.php @@ -0,0 +1,20 @@ + $a */ + public $a; + + /** + * @phpstan-return T + */ + public function get() { + return $a->get(); + } + +}