diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_array.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_array.php.inc new file mode 100644 index 00000000000..7118bd500af --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_array.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_string.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_string.php.inc new file mode 100644 index 00000000000..5bb6fefb243 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/remove_object_return_over_string.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/skip_generic_array_narrowing.php.inc b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/skip_generic_array_narrowing.php.inc new file mode 100644 index 00000000000..f395f12eb54 --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/Fixture/skip_generic_array_narrowing.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/RemoveReturnTagIncompatibleWithNativeTypeRector/config/configured_rule.php b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/config/configured_rule.php new file mode 100644 index 00000000000..dd090c236ac --- /dev/null +++ b/rules-tests/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector/config/configured_rule.php @@ -0,0 +1,9 @@ +withRules([RemoveReturnTagIncompatibleWithNativeTypeRector::class]); diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector.php new file mode 100644 index 00000000000..845fa514e03 --- /dev/null +++ b/rules/DeadCode/Rector/ClassMethod/RemoveReturnTagIncompatibleWithNativeTypeRector.php @@ -0,0 +1,118 @@ +someObject->getName(); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +final class SomeClass +{ + public function getName(): string + { + return $this->someObject->getName(); + } +} +CODE_SAMPLE + ), + ] + ); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [ClassMethod::class, Function_::class]; + } + + /** + * @param ClassMethod|Function_ $node + */ + public function refactor(Node $node): ?Node + { + // no native return type to compare against + if ($node->returnType === null) { + return null; + } + + // nothing to remove + if ($node->getComments() === []) { + return null; + } + + $phpDocInfo = $this->phpDocInfoFactory->createFromNode($node); + if (! $phpDocInfo instanceof PhpDocInfo) { + return null; + } + + $returnTagValueNode = $phpDocInfo->getReturnTagValue(); + if (! $returnTagValueNode instanceof ReturnTagValueNode) { + return null; + } + + // keep any documented explanation + if ($returnTagValueNode->description !== '') { + return null; + } + + $nativeReturnType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($node->returnType); + $docReturnType = $phpDocInfo->getReturnType(); + + // a subtype/narrowing is legitimate; only a contradiction is dead + if (! $nativeReturnType->isSuperTypeOf($docReturnType)->no()) { + return null; + } + + if (! $phpDocInfo->removeByType(ReturnTagValueNode::class)) { + return null; + } + + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + + return $node; + } +} diff --git a/src/Config/Level/DeadCodeLevel.php b/src/Config/Level/DeadCodeLevel.php index e16dc63841c..230770622c6 100644 --- a/src/Config/Level/DeadCodeLevel.php +++ b/src/Config/Level/DeadCodeLevel.php @@ -19,6 +19,7 @@ use Rector\DeadCode\Rector\ClassMethod\RemoveMixedDocblockOverruledByNativeTypeRector; use Rector\DeadCode\Rector\ClassMethod\RemoveNullTagValueNodeRector; use Rector\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector; +use Rector\DeadCode\Rector\ClassMethod\RemoveReturnTagIncompatibleWithNativeTypeRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedConstructorParamRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodRector; @@ -120,6 +121,7 @@ final class DeadCodeLevel RemoveUselessReturnTagRector::class, RemoveDuplicatedReturnSelfDocblockRector::class, RemoveMixedDocblockOverruledByNativeTypeRector::class, + RemoveReturnTagIncompatibleWithNativeTypeRector::class, RemoveUselessUnionReturnDocblockRector::class, RemoveUselessReadOnlyTagRector::class, RemoveNonExistingVarAnnotationRector::class,