Skip to content

Commit

Permalink
[DX] Add RectorConfig upgrade rule to make upgrade easier :) (#2098)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Apr 20, 2022
1 parent b92465d commit d90953d
Show file tree
Hide file tree
Showing 11 changed files with 448 additions and 13 deletions.
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ parameters:
- rules/Php70/EregToPcreTransformer.php
- packages/NodeTypeResolver/NodeTypeResolver.php
- rules/Renaming/NodeManipulator/ClassRenamer.php
- rules/DogFood/Rector/Closure/UpgradeRectorConfigRector.php

- "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 10$#"
- '#Cognitive complexity for "Rector\\Core\\PhpParser\\Node\\Value\\ValueResolver\:\:getValue\(\)" is \d+, keep it under 10#'
Expand Down Expand Up @@ -202,6 +203,7 @@ parameters:
- '#Access to an undefined property PhpParser\\Node\\FunctionLike\|PhpParser\\Node\\Stmt\\If_\:\:\$stmts#'

- '#Cognitive complexity for "Rector\\CodeQuality\\Rector\\Isset_\\IssetOnPropertyObjectToPropertyExistsRector\:\:refactor\(\)" is \d+, keep it under 10#'
- '#Cognitive complexity for "Rector\\DogFood\\Rector\\Closure\\UpgradeRectorConfigRector\:\:refactor\(\)" is \d+, keep it under 10#'

- '#(.*?) class\-string, string given#'

Expand Down Expand Up @@ -249,6 +251,7 @@ parameters:
paths:
- packages/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php
- rules/Php80/Rector/FunctionLike/UnionTypesRector.php
- rules/Php70/Rector/If_/IfToSpaceshipRector.php

-
message: '#Property with protected modifier is not allowed\. Use interface contract method instead#'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Renaming\Rector\Name\RenameClassRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(RenameClassRector::class)
->configure([
'old_class' => 'new_class',
]);
};

?>
-----
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Renaming\Rector\Name\RenameClassRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (\Rector\Config\RectorConfig $rectorConfig): void {
$rectorConfig
->ruleWithConfiguration(RenameClassRector::class, [
'old_class' => 'new_class',
]);
};

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$services = $rectorConfig->services();
};

?>
-----
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig) : void {
};

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Core\Configuration\Option;
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PARALLEL, true);
$parameters->set(Option::AUTO_IMPORT_NAMES, true);

$services = $containerConfigurator->services();
$services->set(TypedPropertyRector::class);
};

?>
-----
<?php

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector\Fixture;

use Rector\Core\Configuration\Option;
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (\Rector\Config\RectorConfig $rectorConfig): void {
$rectorConfig->parallel();
$rectorConfig->importNames();
$rectorConfig->rule(TypedPropertyRector::class);
};

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\DogFood\Rector\Closure\UpgradeRectorConfigRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class UpgradeRectorConfigRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DogFood\Rector\Closure\UpgradeRectorConfigRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(UpgradeRectorConfigRector::class);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@
use Rector\Php70\Rector\If_\IfToSpaceshipRector;

return static function (RectorConfig $rectorConfig): void {
$services = $rectorConfig->services();
$services->set(IfToSpaceshipRector::class);
$rectorConfig->rule(IfToSpaceshipRector::class);
};
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,20 @@ public function refactor(Node $node): ?Node
}

// The first value may not be at index 0
$tag = reset($tags);
$phpDocTagNode = reset($tags);

if (! in_array($tag->name, $this->annotationsToConsiderForInlining, true)) {
if (! in_array($phpDocTagNode->name, $this->annotationsToConsiderForInlining, true)) {
return null;
}

if (str_contains((string) $tag, "\n")) {
if (str_contains((string) $phpDocTagNode, "\n")) {
return null;
}

// Handle edge cases where stringified tag is not same as it was originally
/** @var Doc $comment */
$comment = $comments[0];
if (! str_contains($comment->getText(), (string) $tag)) {
if (! str_contains($comment->getText(), (string) $phpDocTagNode)) {
return null;
}

Expand All @@ -140,7 +140,7 @@ public function refactor(Node $node): ?Node
$newPhpDocInfo->makeSingleLined();

$newPhpDocNode = $newPhpDocInfo->getPhpDocNode();
$newPhpDocNode->children = [$tag];
$newPhpDocNode->children = [$phpDocTagNode];

return $node;
}
Expand Down
54 changes: 54 additions & 0 deletions rules/DogFood/NodeAnalyzer/ContainerConfiguratorCallAnalyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Rector\DogFood\NodeAnalyzer;

use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Contract\Rector\RectorInterface;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
use Rector\NodeNameResolver\NodeNameResolver;

final class ContainerConfiguratorCallAnalyzer
{
public function __construct(
private readonly ValueResolver $valueResolver,
private readonly NodeNameResolver $nodeNameResolver,
) {
}

public function isMethodCallWithServicesSetConfiguredRectorRule(MethodCall $methodCall): bool
{
return $this->nodeNameResolver->isName($methodCall->name, 'configure');
}

public function isMethodCallWithServicesSetRectorRule(MethodCall $methodCall): bool
{
if (! $this->isMethodCallNamed($methodCall, 'services', 'set')) {
return false;
}

$firstArg = $methodCall->getArgs()[0];
$serviceClass = $this->valueResolver->getValue($firstArg->value);

if (! is_string($serviceClass)) {
return false;
}

return is_a($serviceClass, RectorInterface::class, true);
}

public function isMethodCallNamed(Expr $expr, string $variableName, string $methodName): bool
{
if (! $expr instanceof MethodCall) {
return false;
}

if (! $this->nodeNameResolver->isName($expr->var, $variableName)) {
return false;
}

return $this->nodeNameResolver->isName($expr->name, $methodName);
}
}

0 comments on commit d90953d

Please sign in to comment.