diff --git a/packages/node-type-resolver/src/Node/AttributeKey.php b/packages/node-type-resolver/src/Node/AttributeKey.php index e5b27f1e6977..b825890bea8e 100644 --- a/packages/node-type-resolver/src/Node/AttributeKey.php +++ b/packages/node-type-resolver/src/Node/AttributeKey.php @@ -149,4 +149,9 @@ final class AttributeKey * @var string */ public const IS_REGULAR_PATTERN = 'is_regular_pattern'; + + /** + * @var string + */ + public const DO_NOT_CHANGE = 'do_not_change'; } diff --git a/packages/phpstan-static-type-mapper/src/TypeMapper/StaticTypeMapper.php b/packages/phpstan-static-type-mapper/src/TypeMapper/StaticTypeMapper.php index 8cb90d4bc6c7..d158ee9181f7 100644 --- a/packages/phpstan-static-type-mapper/src/TypeMapper/StaticTypeMapper.php +++ b/packages/phpstan-static-type-mapper/src/TypeMapper/StaticTypeMapper.php @@ -12,10 +12,22 @@ use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; use Rector\Core\Exception\NotImplementedException; +use Rector\Core\Php\PhpVersionProvider; +use Rector\Core\ValueObject\PhpVersionFeature; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class StaticTypeMapper implements TypeMapperInterface { + /** + * @var PhpVersionProvider + */ + private $phpVersionProvider; + + public function __construct(PhpVersionProvider $phpVersionProvider) + { + $this->phpVersionProvider = $phpVersionProvider; + } + public function getNodeClass(): string { return StaticType::class; @@ -35,6 +47,11 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { if ($type instanceof ThisType) { + // @todo wait for PHPStan to differentiate between self/static + if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::STATIC_RETURN_TYPE)) { + return new Identifier('static'); + } + return new Identifier('self'); } diff --git a/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php b/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php index f18982010644..1651f2874c8b 100644 --- a/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php +++ b/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php @@ -39,11 +39,6 @@ final class ReturnTypeDeclarationRector extends AbstractTypeDeclarationRector */ private const EXCLUDED_METHOD_NAMES = ['__construct', '__destruct', '__clone']; - /** - * @var string - */ - private const DO_NOT_CHANGE = 'do_not_change'; - /** * @var bool */ @@ -183,8 +178,9 @@ private function shouldSkipInferredReturnNode(FunctionLike $functionLike, ?Node if ($this->isVoidDueToThrow($functionLike, $inferredReturnNode)) { return true; } + // already overridden by previous populateChild() method run - return $functionLike->returnType && $functionLike->returnType->getAttribute(self::DO_NOT_CHANGE); + return $functionLike->returnType && $functionLike->returnType->getAttribute(AttributeKey::DO_NOT_CHANGE); } private function shouldSkipExistingReturnType(Node $node, Type $inferedType): bool @@ -271,7 +267,7 @@ private function addReturnTypeToChildMethod( $currentClassMethod->returnType = $resolvedChildTypeNode; // make sure the type is not overridden - $currentClassMethod->returnType->setAttribute(self::DO_NOT_CHANGE, true); + $currentClassMethod->returnType->setAttribute(AttributeKey::DO_NOT_CHANGE, true); $this->notifyNodeFileInfo($currentClassMethod); } diff --git a/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/FixtureForPhp80/static_.php.inc b/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/FixtureForPhp80/static_.php.inc new file mode 100644 index 000000000000..cf039a615ad4 --- /dev/null +++ b/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/FixtureForPhp80/static_.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/Php80RectorTest.php b/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/Php80RectorTest.php new file mode 100644 index 000000000000..9f4212a665e0 --- /dev/null +++ b/rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/Php80RectorTest.php @@ -0,0 +1,36 @@ +doTestFile($file); + } + + public function provideData(): Iterator + { + return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureForPhp80'); + } + + protected function getPhpVersion(): string + { + return PhpVersionFeature::STATIC_RETURN_TYPE; + } + + protected function getRectorClass(): string + { + return ReturnTypeDeclarationRector::class; + } +} diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 4274da21ae11..b4d0cb41de4a 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -151,4 +151,9 @@ final class PhpVersionFeature * @var string */ public const CLASS_ON_OBJECT = '8.0'; + + /** + * @var string + */ + public const STATIC_RETURN_TYPE = '8.0'; }