diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector/Fixture/skip_static_function.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector/Fixture/skip_static_function.php.inc new file mode 100644 index 00000000000..fd74c2e4af5 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector/Fixture/skip_static_function.php.inc @@ -0,0 +1,11 @@ +parent; + } + + /** + * @return $this|null + */ + public function getThisParent(): ?SomeStaticInterface + { + return $this->parent; + } +} diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector.php index e7b584846d2..681f9a4c7b1 100644 --- a/rules/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector.php +++ b/rules/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector.php @@ -8,6 +8,8 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; +use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; +use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode; use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; @@ -104,6 +106,11 @@ public function refactor(Node $node): ?Node return null; } + // keep static/$this, they denote the runtime subclass the native type cannot express + if ($this->hasStaticOrThisType($returnTagValueNode->type)) { + return null; + } + $nativeReturnType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($node->returnType); // keep array-involving native type (array, ?array, union with array), the docblock may carry element types @@ -131,4 +138,19 @@ public function provideMinPhpVersion(): int { return PhpVersionFeature::UNION_TYPES; } + + private function hasStaticOrThisType(UnionTypeNode $unionTypeNode): bool + { + foreach ($unionTypeNode->types as $typeNode) { + if ($typeNode instanceof ThisTypeNode) { + return true; + } + + if ($typeNode instanceof IdentifierTypeNode && $typeNode->name === 'static') { + return true; + } + } + + return false; + } }