Merge pull request #3792 from rectorphp/typed-set-get

This commit is contained in:
Tomas Votruba 2020-07-26 18:29:29 +02:00 committed by GitHub
commit 90b921b1dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 218 additions and 113 deletions

View File

@ -2,11 +2,11 @@
declare(strict_types=1);
use Rector\Downgrade\Rector\Property\TypedPropertyRector;
use Rector\Downgrade\Rector\Property\DowngradeTypedPropertyRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(TypedPropertyRector::class);
$services->set(DowngradeTypedPropertyRector::class);
};

View File

@ -13,9 +13,9 @@ use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\TypedPropertyRectorTest
* @see \Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\DowngradeTypedPropertyRectorTest
*/
final class TypedPropertyRector extends AbstractRector
final class DowngradeTypedPropertyRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{

View File

@ -2,14 +2,14 @@
declare(strict_types=1);
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector;
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Downgrade\Rector\Property\TypedPropertyRector;
use Rector\Downgrade\Rector\Property\DowngradeTypedPropertyRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class TypedPropertyRectorTest extends AbstractRectorTestCase
final class DowngradeTypedPropertyRectorTest extends AbstractRectorTestCase
{
/**
* @requires PHP >= 7.4
@ -27,6 +27,6 @@ final class TypedPropertyRectorTest extends AbstractRectorTestCase
protected function getRectorClass(): string
{
return TypedPropertyRector::class;
return DowngradeTypedPropertyRector::class;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
use Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source\AnotherClass;
class ClassNameNullableTypeClass
{
private ?AnotherClass $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
use Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source\AnotherClass;
class ClassNameNullableTypeClass
{
/**
* @var \Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source\AnotherClass|null
*/
private $property;
}
?>

View File

@ -0,0 +1,22 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class ClassNameClass {
private \Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source\AnotherClass $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class ClassNameClass {
/**
* @var \Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source\AnotherClass
*/
private $property;
}
?>

View File

@ -1,6 +1,6 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class DocBlockExists {
/**
@ -13,7 +13,7 @@ class DocBlockExists {
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class DocBlockExists {
/**

View File

@ -0,0 +1,22 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class SomeClass {
private string $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class SomeClass {
/**
* @var string
*/
private $property;
}
?>

View File

@ -1,6 +1,6 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class NullableTypeClass {
private ?string $property;
@ -10,7 +10,7 @@ class NullableTypeClass {
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
class NullableTypeClass {
/**

View File

@ -0,0 +1,10 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source;
class AnotherClass
{
}

View File

@ -1,22 +0,0 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class ClassNameNullableTypeClass {
private ?\Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source\AnotherClass $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class ClassNameNullableTypeClass {
/**
* @var \Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source\AnotherClass|null
*/
private $property;
}
?>

View File

@ -1,22 +0,0 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class ClassNameClass {
private \Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source\AnotherClass $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class ClassNameClass {
/**
* @var \Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source\AnotherClass
*/
private $property;
}
?>

View File

@ -1,22 +0,0 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class SomeClass {
private string $property;
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Fixture;
class SomeClass {
/**
* @var string
*/
private $property;
}
?>

View File

@ -1,10 +0,0 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source;
class AnotherClass
{
}

View File

@ -0,0 +1,44 @@
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
final class InferSetGet
{
/**
* @var string|null
*/
private $name;
public function setName(string $name): void
{
$this->name = $name;
}
public function compareName(string $name): bool
{
return $name === $this->name;
}
}
?>
-----
<?php
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Fixture;
final class InferSetGet
{
private ?string $name = null;
public function setName(string $name): void
{
$this->name = $name;
}
public function compareName(string $name): bool
{
return $name === $this->name;
}
}
?>

View File

@ -20,7 +20,7 @@ namespace Rector\Php74\Tests\Rector\Property\TypedPropertyRector\Fixture;
final class StaticAnalysisBased
{
private int $count;
private ?int $count = null;
public function setCount(int $count)
{

View File

@ -13,13 +13,21 @@ use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class AssignToPropertyTypeInferer extends AbstractTypeInferer
{
/**
* @var bool
*/
private $isAssignedInConstructor = false;
public function inferPropertyInClassLike(string $propertyName, ClassLike $classLike): Type
{
$assignedExprStaticTypes = [];
$this->isAssignedInConstructor = false;
$this->callableNodeTraverser->traverseNodesWithCallable($classLike->stmts, function (Node $node) use (
$propertyName,
@ -43,11 +51,22 @@ final class AssignToPropertyTypeInferer extends AbstractTypeInferer
$exprStaticType = new ArrayType(new MixedType(), $exprStaticType);
}
// is in constructor?
$methodName = $node->getAttribute(AttributeKey::METHOD_NAME);
if ($methodName === '__construct') {
$this->isAssignedInConstructor = true;
}
$assignedExprStaticTypes[] = $exprStaticType;
return null;
});
// add default type, as not initialized in the constructor
if (count($assignedExprStaticTypes) && ! $this->isAssignedInConstructor) {
$assignedExprStaticTypes[] = new NullType();
}
return $this->typeFactory->createMixedPassedOrUnionType($assignedExprStaticTypes);
}

View File

@ -88,6 +88,7 @@ final class PropertyTypeInferer extends AbstractPriorityAwareTypeInferer
}
$types = [$type, $defaultValueType];
return $this->typeFactory->createMixedPassedOrUnionType($types);
}
}

View File

@ -43,7 +43,7 @@ class GetterBased
}
/**
* @return \stdClass[]
* @return \stdClass[]|null
*/
public function getValues(): array
{

View File

@ -30,7 +30,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
final class CallableJustForTestType
{
/**
* @var callable
* @var callable|null
*/
private $code;
/**

View File

@ -27,7 +27,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
class KeepComment
{
/**
* @var string[]|string e.g. 123
* @var string[]|string|null e.g. 123
*/
private $ids;

View File

@ -591,7 +591,7 @@ class Command
*/
private $name;
/**
* @var string
* @var string|null
*/
private $processTitle;
/**
@ -623,7 +623,7 @@ class Command
*/
private $applicationDefinitionMergedWithArgs = false;
/**
* @var callable
* @var callable|null
*/
private $code;
/**

View File

@ -24,7 +24,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
class TypedArray
{
/**
* @var string[]
* @var string[]|null
*/
private $items;

View File

@ -24,7 +24,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
class TypedArrayNested
{
/**
* @var int[][]|bool[]
* @var int[][]|bool[]|null
*/
private $itemsNested;

View File

@ -85,7 +85,7 @@ final class GetterType
/**
* @Serializer\Type("string")
* @var string
* @var string|null
*/
private $language;

View File

@ -21,7 +21,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRe
class PhpUnitTestCase
{
/**
* @var int
* @var int|null
*/
private $value;

View File

@ -34,11 +34,11 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRe
final class SetterType
{
/**
* @var string
* @var string|null
*/
private $email;
/**
* @var string
* @var string|null
*/
private $name;

View File

@ -34,11 +34,11 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRe
class StaticPropertyWithDefaultNull
{
/**
* @var string|null
* @var null|string
*/
protected static $cacheFile = null;
/**
* @var string[]|null
* @var null|string[]
*/
protected static $cacheFiles = null;

View File

@ -120,12 +120,7 @@ final class RectorApplication
return;
}
if (! $this->symfonyStyle->isVerbose() && $this->configuration->showProgressBar()) {
// why 5? one for each cycle, so user sees some activity all the time
$this->symfonyStyle->progressStart($fileCount * 5);
$this->configureStepCount($this->symfonyStyle);
}
$this->prepareProgressBar($fileCount);
// PHPStan has to know about all files!
$this->configurePHPStanNodeScopeResolver($phpFileInfos);
@ -289,4 +284,25 @@ final class RectorApplication
}, 'refactoring');
}
}
private function prepareProgressBar(int $fileCount): void
{
if ($this->symfonyStyle->isVerbose()) {
return;
}
if (! $this->configuration->showProgressBar()) {
return;
}
// why 5? one for each cycle, so user sees some activity all the time
$stepMultiplier = 4;
if ($this->fileSystemFileProcessor->getFileSystemRectorsCount() !== 0) {
++$stepMultiplier;
}
$this->symfonyStyle->progressStart($fileCount * $stepMultiplier);
$this->configureStepCount($this->symfonyStyle);
}
}

View File

@ -293,10 +293,7 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase
} catch (ExpectationFailedException $expectationFailedException) {
$contents = $expectedFileInfo->getContents();
if (getenv('UPDATE_TESTS')) {
$newOriginalContent = $originalFileInfo->getContents() . SplitLine::LINE . $changedContent . '?>' . PHP_EOL;
$this->smartFileSystem->dumpFile($fixtureFileInfo->getRealPath(), $newOriginalContent);
}
$this->updateFixtureContent($originalFileInfo, $changedContent, $fixtureFileInfo);
// if not exact match, check the regex version (useful for generated hashes/uuids in the code)
$this->assertStringMatchesFormat($contents, $changedContent, $relativeFilePathFromCwd);
@ -328,4 +325,26 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase
return array_merge($configFileInfos, $setFileInfos);
}
private function updateFixtureContent(
SmartFileInfo $originalFileInfo,
string $changedContent,
SmartFileInfo $fixtureFileInfo
): void {
if (! getenv('UPDATE_TESTS') && ! getenv('UT')) {
return;
}
$newOriginalContent = $this->resolveNewFixtureContent($originalFileInfo, $changedContent);
$this->smartFileSystem->dumpFile($fixtureFileInfo->getRealPath(), $newOriginalContent);
}
private function resolveNewFixtureContent(SmartFileInfo $originalFileInfo, string $changedContent): string
{
if ($originalFileInfo->getContents() === $changedContent) {
return $originalFileInfo->getContents();
}
return $originalFileInfo->getContents() . SplitLine::LINE . $changedContent;
}
}

View File

@ -18,6 +18,6 @@ class Uuid implements UuidInterface
public function toString()
{
// dummy value
return '4398dda9-3bc0-45ec-ae81-3d81a86ad84a';
return '%s-%s-%s-%s-%s';
}
}