Merge pull request #3278 from rectorphp/php80-static

This commit is contained in:
Tomas Votruba 2020-04-29 23:10:03 +02:00 committed by GitHub
commit f0d9340008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 7 deletions

View File

@ -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';
}

View File

@ -12,10 +12,22 @@ use PHPStan\Type\ThisType;
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 @@ final class StaticTypeMapper implements TypeMapperInterface
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');
}

View File

@ -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 @@ PHP
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 @@ PHP
$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);
}

View File

@ -0,0 +1,33 @@
<?php
namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\FixtureForPhp80;
class Static_
{
/**
* @return static
*/
public function getSelf()
{
return $this;
}
}
?>
-----
<?php
namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\FixtureForPhp80;
class Static_
{
/**
* @return static
*/
public function getSelf(): static
{
return $this;
}
}
?>

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Rector\TypeDeclaration\Tests\Rector\FunctionLike\ReturnTypeDeclarationRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\TypeDeclaration\Rector\FunctionLike\ReturnTypeDeclarationRector;
final class Php80RectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->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;
}
}

View File

@ -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';
}