diff --git a/Makefile b/Makefile index 5fdb666448..a0b15cef22 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,7 @@ lint: --exclude tests/PHPStan/Rules/Functions/data/bug-14241.php \ --exclude tests/PHPStan/Rules/Variables/data/bug-14349.php \ --exclude tests/PHPStan/Rules/Variables/data/bug-14352.php \ + --exclude tests/PHPStan/Rules/Variables/data/bug-14351.php \ src tests install-paratest: diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8935ade8e2..ca1daa6f34 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1974,6 +1974,7 @@ public function processStmtNode( } $variableName = $catchNode->var->name; + $this->callNodeCallback($nodeCallback, new VariableAssignNode($catchNode->var, new TypeExpr($catchType)), $scope, $storage); } $catchScopeResult = $this->processStmtNodesInternal($catchNode, $catchNode->stmts, $catchScope->enterCatchType($catchType, $variableName), $storage, $nodeCallback, $context); diff --git a/src/Rules/Variables/ThisInGlobalStatementRule.php b/src/Rules/Variables/ThisInGlobalStatementRule.php new file mode 100644 index 0000000000..99e7918367 --- /dev/null +++ b/src/Rules/Variables/ThisInGlobalStatementRule.php @@ -0,0 +1,48 @@ + + */ +#[RegisteredRule(level: 0)] +final class ThisInGlobalStatementRule implements Rule +{ + + public function getNodeType(): string + { + return Node\Stmt\Global_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + foreach ($node->vars as $var) { + if (!$var instanceof Variable) { + continue; + } + if (!is_string($var->name)) { + continue; + } + if ($var->name !== 'this') { + continue; + } + + $errors[] = RuleErrorBuilder::message('Cannot use $this as global variable.') + ->identifier('global.this') + ->nonIgnorable() + ->build(); + } + + return $errors; + } + +} diff --git a/src/Rules/Variables/ThisInStaticStatementRule.php b/src/Rules/Variables/ThisInStaticStatementRule.php new file mode 100644 index 0000000000..d6a36d1129 --- /dev/null +++ b/src/Rules/Variables/ThisInStaticStatementRule.php @@ -0,0 +1,44 @@ + + */ +#[RegisteredRule(level: 0)] +final class ThisInStaticStatementRule implements Rule +{ + + public function getNodeType(): string + { + return Node\Stmt\Static_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + foreach ($node->vars as $var) { + if (!is_string($var->var->name)) { + continue; + } + if ($var->var->name !== 'this') { + continue; + } + + $errors[] = RuleErrorBuilder::message('Cannot use $this as static variable.') + ->identifier('static.this') + ->nonIgnorable() + ->build(); + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Rules/Variables/InvalidVariableAssignRuleTest.php b/tests/PHPStan/Rules/Variables/InvalidVariableAssignRuleTest.php index 77cbf2c1b4..47df063cef 100644 --- a/tests/PHPStan/Rules/Variables/InvalidVariableAssignRuleTest.php +++ b/tests/PHPStan/Rules/Variables/InvalidVariableAssignRuleTest.php @@ -88,6 +88,16 @@ public function testBug14352(): void ]); } + public function testBug14351(): void + { + $this->analyse([__DIR__ . '/data/bug-14351.php'], [ + [ + 'Cannot re-assign $this.', + 9, + ], + ]); + } + public function testBug14349(): void { $this->analyse([__DIR__ . '/data/bug-14349.php'], [ diff --git a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php index 6da45dd248..9587af37e2 100644 --- a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php +++ b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php @@ -91,4 +91,19 @@ public function testBug14124b(): void $this->analyse([__DIR__ . '/data/bug-14124b.php'], []); } + public function testCatchVariable(): void + { + $this->analyse([__DIR__ . '/data/parameter-out-catch-variable.php'], [ + [ + 'Parameter &$p @param-out type of function ParameterOutCatchVariable\foo() expects int, Exception given.', + 11, + ], + [ + 'Parameter &$p by-ref type of function ParameterOutCatchVariable\bar() expects int, Exception given.', + 19, + 'You can change the parameter out type with @param-out PHPDoc tag.', + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Variables/ThisInGlobalStatementRuleTest.php b/tests/PHPStan/Rules/Variables/ThisInGlobalStatementRuleTest.php new file mode 100644 index 0000000000..85ba69cc38 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/ThisInGlobalStatementRuleTest.php @@ -0,0 +1,29 @@ + + */ +class ThisInGlobalStatementRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new ThisInGlobalStatementRule(); + } + + public function testBug14351(): void + { + $this->analyse([__DIR__ . '/data/bug-14351.php'], [ + [ + 'Cannot use $this as global variable.', + 15, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Variables/ThisInStaticStatementRuleTest.php b/tests/PHPStan/Rules/Variables/ThisInStaticStatementRuleTest.php new file mode 100644 index 0000000000..2e53887778 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/ThisInStaticStatementRuleTest.php @@ -0,0 +1,29 @@ + + */ +class ThisInStaticStatementRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new ThisInStaticStatementRule(); + } + + public function testBug14351(): void + { + $this->analyse([__DIR__ . '/data/bug-14351.php'], [ + [ + 'Cannot use $this as static variable.', + 19, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Variables/data/bug-14351.php b/tests/PHPStan/Rules/Variables/data/bug-14351.php new file mode 100644 index 0000000000..6d9745a0ef --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-14351.php @@ -0,0 +1,20 @@ +