diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_current_object_docblock.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_current_object_docblock.php.inc new file mode 100644 index 00000000000..541ff7767aa --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_current_object_docblock.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_self_docblock.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_self_docblock.php.inc new file mode 100644 index 00000000000..9d1763c72cb --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_self_docblock.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_static_docblock.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_static_docblock.php.inc new file mode 100644 index 00000000000..a2e0b980dae --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_static_docblock.php.inc @@ -0,0 +1,32 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_this_docblock.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_this_docblock.php.inc new file mode 100644 index 00000000000..53578dc5101 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/remove_return_this_docblock.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/skip_other_type.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/skip_other_type.php.inc new file mode 100644 index 00000000000..75365f17a8c --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/Fixture/skip_other_type.php.inc @@ -0,0 +1,14 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/config/configured_rule.php b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/config/configured_rule.php new file mode 100644 index 00000000000..fbd77ab370a --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector/config/configured_rule.php @@ -0,0 +1,9 @@ +withRules([RemoveDuplicatedReturnSelfDocblockRector::class]); diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector.php new file mode 100644 index 00000000000..2cf76163778 --- /dev/null +++ b/rules/DeadCode/Rector/ClassMethod/RemoveDuplicatedReturnSelfDocblockRector.php @@ -0,0 +1,141 @@ +> + */ + public function getNodeTypes(): array + { + return [ClassMethod::class]; + } + + /** + * @param ClassMethod $node + */ + public function refactor(Node $node): ?Node + { + if (! $node->returnType instanceof Identifier && ! $node->returnType instanceof Name) { + return null; + } + + $returnTypeName = $node->returnType->toString(); + if (! in_array($returnTypeName, ['self', 'static'], true)) { + return null; + } + + $classReflection = $this->reflectionResolver->resolveClassReflection($node); + if (! $classReflection instanceof ClassReflection) { + return null; + } + + $phpDocInfo = $this->phpDocInfoFactory->createFromNode($node); + if (! $phpDocInfo instanceof PhpDocInfo) { + return null; + } + + $returnTagValueNode = $phpDocInfo->getReturnTagValue(); + if (! $returnTagValueNode instanceof ReturnTagValueNode) { + return null; + } + + if ($returnTagValueNode->description !== '') { + return null; + } + + if (! $this->isCurrentObjectReturnDocType($returnTagValueNode->type, $node, $classReflection)) { + return null; + } + + $phpDocInfo->removeByType(ReturnTagValueNode::class); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + + return $node; + } + + private function isCurrentObjectReturnDocType( + TypeNode $typeNode, + ClassMethod $classMethod, + ClassReflection $classReflection + ): bool { + $docType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($typeNode, $classMethod); + + // covers @return $this and @return static + if ($docType instanceof StaticType) { + return $docType->getClassName() === $classReflection->getName(); + } + + // covers @return self and @return CurrentObject + if ($docType instanceof ObjectType) { + return $docType->getClassName() === $classReflection->getName(); + } + + return false; + } +} diff --git a/src/Config/Level/DeadCodeLevel.php b/src/Config/Level/DeadCodeLevel.php index b543d1392a3..3422b0d49e6 100644 --- a/src/Config/Level/DeadCodeLevel.php +++ b/src/Config/Level/DeadCodeLevel.php @@ -15,6 +15,7 @@ use Rector\DeadCode\Rector\ClassConst\RemoveUnusedPrivateClassConstantRector; use Rector\DeadCode\Rector\ClassLike\RemoveTypedPropertyNonMockDocblockRector; use Rector\DeadCode\Rector\ClassMethod\RemoveArgumentFromDefaultParentCallRector; +use Rector\DeadCode\Rector\ClassMethod\RemoveDuplicatedReturnSelfDocblockRector; use Rector\DeadCode\Rector\ClassMethod\RemoveEmptyClassMethodRector; use Rector\DeadCode\Rector\ClassMethod\RemoveNullTagValueNodeRector; use Rector\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector; @@ -116,6 +117,7 @@ final class DeadCodeLevel RemoveVoidDocblockFromMagicMethodRector::class, RemoveUselessParamTagRector::class, RemoveUselessReturnTagRector::class, + RemoveDuplicatedReturnSelfDocblockRector::class, RemoveUselessReadOnlyTagRector::class, RemoveNonExistingVarAnnotationRector::class, RemoveUselessVarTagRector::class,