diff --git a/src/Parser/NewAssignedToPropertyVisitor.php b/src/Parser/NewAssignedToPropertyVisitor.php index 60fd8fd72e..7808d82fce 100644 --- a/src/Parser/NewAssignedToPropertyVisitor.php +++ b/src/Parser/NewAssignedToPropertyVisitor.php @@ -16,7 +16,7 @@ final class NewAssignedToPropertyVisitor extends NodeVisitorAbstract #[Override] public function enterNode(Node $node): ?Node { - if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignRef) { + if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignRef || $node instanceof Node\Expr\AssignOp) { if ( ($node->var instanceof Node\Expr\PropertyFetch || $node->var instanceof Node\Expr\StaticPropertyFetch) && $node->expr instanceof Node\Expr\New_ diff --git a/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php b/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php index 2a75a6c8c6..d0d20f4ba9 100644 --- a/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php +++ b/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php @@ -88,7 +88,11 @@ public function processNode(Node $node, Scope $scope): array return []; } if ($node instanceof Node\Stmt\Expression) { - if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef) { + if ( + !$node->expr instanceof Node\Expr\Assign + && !$node->expr instanceof Node\Expr\AssignRef + && !$node->expr instanceof Node\Expr\AssignOp + ) { return []; } } diff --git a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php index 4b18ca789a..edf59cd62f 100644 --- a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php +++ b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php @@ -47,7 +47,11 @@ public function processNode(Node $node, Scope $scope): array return []; } if ($node instanceof Node\Stmt\Expression) { - if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef) { + if ( + !$node->expr instanceof Node\Expr\Assign + && !$node->expr instanceof Node\Expr\AssignRef + && !$node->expr instanceof Node\Expr\AssignOp + ) { return []; } } diff --git a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php index 4c78688ff1..6296e12ca6 100644 --- a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php +++ b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php @@ -288,7 +288,11 @@ private function processForeach(Scope $scope, Node\Expr $iterateeExpr, ?Node\Exp */ private function processExpression(Scope $scope, Expr $expr, array $varTags): array { - if ($expr instanceof Node\Expr\Assign || $expr instanceof Node\Expr\AssignRef) { + if ( + $expr instanceof Node\Expr\Assign + || $expr instanceof Node\Expr\AssignRef + || $expr instanceof Node\Expr\AssignOp + ) { return $this->processAssign($scope, $expr->var, $expr->expr, $varTags); } diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php index ba9b73ad41..e6005045ac 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php @@ -54,6 +54,16 @@ public function testBug8697(): void $this->analyse([__DIR__ . '/data/bug-8697.php'], []); } + public function testAssignOperator(): void + { + $this->analyse([__DIR__ . '/data/invalid-phpstan-doc-assign-operator.php'], [ + [ + 'Unknown PHPDoc tag: @phpstan-va', + 9, + ], + ]); + } + #[RequiresPhp('>= 8.4')] public function testPropertyHooks(): void { diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php index dcb6f03bbf..0fbe4ced57 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php @@ -126,6 +126,16 @@ public function testIgnoreWithinPhpDoc(): void $this->analyse([__DIR__ . '/data/ignore-line-within-phpdoc.php'], []); } + public function testAssignOperator(): void + { + $this->analyse([__DIR__ . '/data/invalid-phpdoc-assign-operator.php'], [ + [ + 'PHPDoc tag @var has invalid value (\\\\Foo|\Bar $test): Unexpected token "\\\\\\\\Foo|\\\\Bar", expected type at offset 9 on line 1', + 8, + ], + ]); + } + public function testBug6299(): void { $this->analyse([__DIR__ . '/data/bug-6299.php'], [ diff --git a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php index b0d9948e37..838211838e 100644 --- a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php @@ -548,6 +548,28 @@ public function testReportWrongType( $this->analyse([__DIR__ . '/data/wrong-var-native-type.php'], $expectedErrors); } + public function testAssignOperator(): void + { + $this->analyse([__DIR__ . '/data/wrong-variable-name-var-assign-op.php'], [ + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 11, + ], + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 14, + ], + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 20, + ], + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 23, + ], + ]); + } + public function testBug12457(): void { $this->checkTypeAgainstPhpDocType = true; diff --git a/tests/PHPStan/Rules/PhpDoc/data/invalid-phpdoc-assign-operator.php b/tests/PHPStan/Rules/PhpDoc/data/invalid-phpdoc-assign-operator.php new file mode 100644 index 0000000000..c45c91135a --- /dev/null +++ b/tests/PHPStan/Rules/PhpDoc/data/invalid-phpdoc-assign-operator.php @@ -0,0 +1,11 @@ += 8.0')] + public function testBug12250(): void + { + $this->analyse([__DIR__ . '/data/bug-12250.php'], []); + } + + public function testBug4525(): void + { + $this->analyse([__DIR__ . '/data/bug-4525.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Properties/data/bug-12250.php b/tests/PHPStan/Rules/Properties/data/bug-12250.php new file mode 100644 index 0000000000..4c0ebea53e --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/bug-12250.php @@ -0,0 +1,17 @@ += 8.0 + +namespace Bug12250; + +class HelloWorld +{ + /** + * @var \WeakMap<\stdClass, \stdClass> + */ + protected \WeakMap $bug, $ok; + + public function bug(): void + { + $this->bug ??= new \WeakMap(); + $this->ok = new \WeakMap(); + } +} diff --git a/tests/PHPStan/Rules/Properties/data/bug-4525.php b/tests/PHPStan/Rules/Properties/data/bug-4525.php new file mode 100644 index 0000000000..3441b25c88 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/bug-4525.php @@ -0,0 +1,24 @@ += 7.4 + +namespace Bug4525; + +use SplObjectStorage; + +class HelloWorld +{ + /** + * @var SplObjectStorage<\DateTime, \DateTimeImmutable> + */ + private SplObjectStorage $map; + + public function sayHello(): void + { + $this->map = new SplObjectStorage(); + } + + /** @phpstan-return SplObjectStorage<\DateTime, \DateTimeImmutable> */ + public function getMap(): SplObjectStorage + { + return $this->map ??= new SplObjectStorage(); + } +}