diff --git a/config/set/type-declaration.php b/config/set/type-declaration.php index e3d73358663..4529f7490a2 100644 --- a/config/set/type-declaration.php +++ b/config/set/type-declaration.php @@ -31,6 +31,7 @@ use Rector\TypeDeclaration\Rector\ClassMethod\ReturnUnionTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector; use Rector\TypeDeclaration\Rector\ClassMethod\StrictStringParamConcatRector; +use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector; use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector; use Rector\TypeDeclaration\Rector\FunctionLike\AddReturnTypeDeclarationFromYieldsRector; @@ -46,6 +47,7 @@ AddReturnTypeDeclarationBasedOnParentClassMethodRector::class, ReturnTypeFromStrictTypedPropertyRector::class, TypedPropertyFromStrictConstructorRector::class, + AddClosureVoidReturnTypeWhereNoReturnRector::class, AddVoidReturnTypeWhereNoReturnRector::class, ReturnTypeFromStrictFluentReturnRector::class, ReturnTypeFromReturnNewRector::class, diff --git a/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/AddClosureVoidReturnTypeWhereNoReturnRectorTest.php b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/AddClosureVoidReturnTypeWhereNoReturnRectorTest.php new file mode 100644 index 00000000000..0ff0ab3e2b2 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/AddClosureVoidReturnTypeWhereNoReturnRectorTest.php @@ -0,0 +1,28 @@ +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/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/Fixture/return_inside_inner_function.php.inc b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/Fixture/return_inside_inner_function.php.inc new file mode 100644 index 00000000000..4ae3e7826c9 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/Fixture/return_inside_inner_function.php.inc @@ -0,0 +1,41 @@ + +----- + diff --git a/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/config/configured_rule.php b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/config/configured_rule.php new file mode 100644 index 00000000000..4747e7c418c --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(AddClosureVoidReturnTypeWhereNoReturnRector::class); +}; diff --git a/rules/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector.php b/rules/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector.php new file mode 100644 index 00000000000..37bb5f36758 --- /dev/null +++ b/rules/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector.php @@ -0,0 +1,75 @@ +> + */ + public function getNodeTypes(): array + { + return [Closure::class]; + } + + /** + * @param Closure $node + */ + public function refactor(Node $node): ?Node + { + // already has return type → skip + if ($node->returnType instanceof Node) { + return null; + } + + if (! $this->silentVoidResolver->hasExclusiveVoid($node)) { + return null; + } + + $node->returnType = new Identifier('void'); + return $node; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::VOID_TYPE; + } +} diff --git a/src/Configuration/Levels/TypeCoverageLevel.php b/src/Configuration/Levels/TypeCoverageLevel.php index 244bce42569..d6e09b40884 100644 --- a/src/Configuration/Levels/TypeCoverageLevel.php +++ b/src/Configuration/Levels/TypeCoverageLevel.php @@ -27,6 +27,7 @@ use Rector\TypeDeclaration\Rector\ClassMethod\ReturnUnionTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector; use Rector\TypeDeclaration\Rector\ClassMethod\StrictStringParamConcatRector; +use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector; use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector; use Rector\TypeDeclaration\Rector\FunctionLike\AddReturnTypeDeclarationFromYieldsRector; @@ -53,7 +54,11 @@ final class TypeCoverageLevel */ public const RULE_LIST = [ // php 7.0 + // start with closure first, as safest + AddClosureVoidReturnTypeWhereNoReturnRector::class, + // @todo continue with functions AddVoidReturnTypeWhereNoReturnRector::class, + // php 7.4 AddArrowFunctionReturnTypeRector::class, ReturnTypeFromStrictNewArrayRector::class,