mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-19 06:18:07 +01:00
Merge pull request #3792 from rectorphp/typed-set-get
This commit is contained in:
commit
90b921b1dd
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
{
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -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 {
|
||||
/**
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -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 {
|
||||
/**
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Rector\Downgrade\Tests\Rector\Property\DowngradeTypedPropertyRector\Source;
|
||||
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -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;
|
||||
}
|
||||
|
||||
?>
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Rector\Downgrade\Tests\Rector\Property\TypedPropertyRector\Source;
|
||||
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ final class PropertyTypeInferer extends AbstractPriorityAwareTypeInferer
|
||||
}
|
||||
|
||||
$types = [$type, $defaultValueType];
|
||||
|
||||
return $this->typeFactory->createMixedPassedOrUnionType($types);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class GetterBased
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \stdClass[]
|
||||
* @return \stdClass[]|null
|
||||
*/
|
||||
public function getValues(): array
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
|
||||
final class CallableJustForTestType
|
||||
{
|
||||
/**
|
||||
* @var callable
|
||||
* @var callable|null
|
||||
*/
|
||||
private $code;
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
|
||||
class TypedArray
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
* @var string[]|null
|
||||
*/
|
||||
private $items;
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropert
|
||||
class TypedArrayNested
|
||||
{
|
||||
/**
|
||||
* @var int[][]|bool[]
|
||||
* @var int[][]|bool[]|null
|
||||
*/
|
||||
private $itemsNested;
|
||||
|
||||
|
@ -85,7 +85,7 @@ final class GetterType
|
||||
|
||||
/**
|
||||
* @Serializer\Type("string")
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
private $language;
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRe
|
||||
class PhpUnitTestCase
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @var int|null
|
||||
*/
|
||||
private $value;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user