From 872cf0ef0a6563e5b48bf03d08ebef7ce0e63b1d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 13 Oct 2026 10:37:54 +0200 Subject: [PATCH] [DeadCode] Skip static/$this union @return in RemoveUselessUnionReturnDocblockRector --- .../Fixture/skip_static_function.php.inc | 11 ++++++++ .../Fixture/skip_static_union.php.inc | 28 +++++++++++++++++++ ...RemoveUselessUnionReturnDocblockRector.php | 22 +++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 rules-tests/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector/Fixture/skip_static_function.php.inc create mode 100644 rules-tests/DeadCode/Rector/ClassMethod/RemoveUselessUnionReturnDocblockRector/Fixture/skip_static_union.php.inc 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; + } }