diff --git a/src/Php/TypeAnalyzer.php b/src/Php/TypeAnalyzer.php index bbe97d7a1d7..1a51e14fed2 100644 --- a/src/Php/TypeAnalyzer.php +++ b/src/Php/TypeAnalyzer.php @@ -2,10 +2,17 @@ namespace Rector\Php; +use Nette\Utils\Strings; + final class TypeAnalyzer { public function isPhpReservedType(string $type): bool { return in_array($type, ['string', 'bool', 'mixed', 'object', 'iterable', 'array'], true); } + + public function isNullableType(string $type): bool + { + return Strings::startsWith($type, '?'); + } } diff --git a/src/Rector/Dynamic/ReturnTypehintRector.php b/src/Rector/Dynamic/ReturnTypehintRector.php index e6d4e58658b..4b362371d15 100644 --- a/src/Rector/Dynamic/ReturnTypehintRector.php +++ b/src/Rector/Dynamic/ReturnTypehintRector.php @@ -5,6 +5,7 @@ namespace Rector\Rector\Dynamic; use PhpParser\Node; use PhpParser\Node\Identifier; use PhpParser\Node\Name\FullyQualified; +use PhpParser\Node\NullableType; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassLike; @@ -150,8 +151,11 @@ CODE_SAMPLE return $classMethodNode; } + // @todo possibly decouple to smth like IdentifierRenamer? if ($this->typeAnalyzer->isPhpReservedType($newTypehint)) { $classMethodNode->returnType = new Identifier($newTypehint); + } elseif ($this->typeAnalyzer->isNullableType($newTypehint)) { + $classMethodNode->returnType = new NullableType('\\' . ltrim($newTypehint, '?')); } else { $classMethodNode->returnType = new FullyQualified($newTypehint); } diff --git a/tests/Rector/Dynamic/ReturnTypehintRector/Correct/correct3.php.inc b/tests/Rector/Dynamic/ReturnTypehintRector/Correct/correct3.php.inc new file mode 100644 index 00000000000..d1e10be2553 --- /dev/null +++ b/tests/Rector/Dynamic/ReturnTypehintRector/Correct/correct3.php.inc @@ -0,0 +1,10 @@ +