diff --git a/config/config.yaml b/config/config.yaml index ddc1787f50d..91a0aa9ae45 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -14,6 +14,9 @@ parameters: autoload_paths: [] rector_recipe: [] + # this helps to separate opened 3rd party code vs private code approach (e.g. use of public constants) + project_type: "proprietary" # or "open-source" + # lower for performance; higher to prevent bugs with fluent interfaces like https://github.com/rectorphp/rector/issues/1646, or https://github.com/rectorphp/rector/issues/2444 nested_chain_method_call_limit: 30 diff --git a/rules/dead-code/src/Rector/ClassMethod/RemoveUnusedParameterRector.php b/rules/dead-code/src/Rector/ClassMethod/RemoveUnusedParameterRector.php index e81c84fc209..e14ed0da5e6 100644 --- a/rules/dead-code/src/Rector/ClassMethod/RemoveUnusedParameterRector.php +++ b/rules/dead-code/src/Rector/ClassMethod/RemoveUnusedParameterRector.php @@ -8,12 +8,14 @@ use PhpParser\Node; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use Rector\Core\Configuration\Option; use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator; use Rector\Core\PhpParser\Node\Manipulator\ClassMethodManipulator; use Rector\Core\Rector\AbstractRector; use Rector\Core\RectorDefinition\CodeSample; use Rector\Core\RectorDefinition\RectorDefinition; use Rector\NodeTypeResolver\Node\AttributeKey; +use Symplify\PackageBuilder\Parameter\ParameterProvider; /** * @see https://www.php.net/manual/en/function.compact.php @@ -52,12 +54,19 @@ final class RemoveUnusedParameterRector extends AbstractRector */ private $classMethodManipulator; + /** + * @var ParameterProvider + */ + private $parameterProvider; + public function __construct( ClassManipulator $classManipulator, - ClassMethodManipulator $classMethodManipulator + ClassMethodManipulator $classMethodManipulator, + ParameterProvider $parameterProvider ) { $this->classManipulator = $classManipulator; $this->classMethodManipulator = $classMethodManipulator; + $this->parameterProvider = $parameterProvider; } public function getDefinition(): RectorDefinition @@ -203,7 +212,8 @@ PHP } // skip as possible contract for 3rd party - if ($classMethod->isAbstract()) { + $projetType = $this->parameterProvider->provideParameter(Option::PROJECT_TYPE); + if ($classMethod->isAbstract() && $projetType === Option::PROJECT_TYPE_OPEN_SOURCE) { return true; } diff --git a/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/change_when_not_using_in_children.php.inc b/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/change_when_not_using_in_children.php.inc new file mode 100644 index 00000000000..d40995325ee --- /dev/null +++ b/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/change_when_not_using_in_children.php.inc @@ -0,0 +1,39 @@ + +----- + diff --git a/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/skip_abstract.php.inc b/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/FixtureOpenSource/skip_abstract.php.inc similarity index 89% rename from rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/skip_abstract.php.inc rename to rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/FixtureOpenSource/skip_abstract.php.inc index 777ef9274cb..b2f99081aec 100644 --- a/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/Fixture/skip_abstract.php.inc +++ b/rules/dead-code/tests/Rector/ClassMethod/RemoveUnusedParameterRector/FixtureOpenSource/skip_abstract.php.inc @@ -1,6 +1,6 @@ setParameter(Option::PROJECT_TYPE, Option::PROJECT_TYPE_OPEN_SOURCE); + $this->doTestFile($file); + } + + public function provideData(): Iterator + { + return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureOpenSource'); + } + + protected function getRectorClass(): string + { + return RemoveUnusedParameterRector::class; + } +} diff --git a/src/Configuration/Option.php b/src/Configuration/Option.php index cf7290c0c9d..9aa6900c903 100644 --- a/src/Configuration/Option.php +++ b/src/Configuration/Option.php @@ -75,4 +75,14 @@ final class Option * @var string */ public const OPTION_OUTPUT_FILE = 'output-file'; + + /** + * @var string + */ + public const PROJECT_TYPE = 'project_type'; + + /** + * @var string + */ + public const PROJECT_TYPE_OPEN_SOURCE = 'open-source'; } diff --git a/src/Testing/PHPUnit/AbstractRectorTestCase.php b/src/Testing/PHPUnit/AbstractRectorTestCase.php index 9b45e1963e6..158e045e11a 100644 --- a/src/Testing/PHPUnit/AbstractRectorTestCase.php +++ b/src/Testing/PHPUnit/AbstractRectorTestCase.php @@ -55,8 +55,14 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase */ private $nodeScopeResolver; + /** + * @var mixed[] + */ + private $oldParameterValues = []; + protected function setUp(): void { + $this->oldParameterValues = []; $this->fixtureSplitter = new FixtureSplitter($this->getTempPath()); if ($this->provideConfig() !== '') { @@ -117,6 +123,8 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase if ($this->getAutoImportNames() !== null) { $this->setParameter(Option::AUTO_IMPORT_NAMES, false); } + + $this->restoreOldParameterValues(); } protected function doTestFileWithoutAutoload(string $file): void @@ -163,6 +171,12 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase protected function setParameter(string $name, $value): void { $parameterProvider = self::$container->get(ParameterProvider::class); + + if (! in_array($name, [Option::PHP_VERSION_FEATURES, Option::AUTO_IMPORT_NAMES], true)) { + $oldParameterValue = $parameterProvider->provideParameter($name); + $this->oldParameterValues[$name] = $oldParameterValue; + } + $parameterProvider->changeParameter($name, $value); } @@ -282,4 +296,17 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase $this->assertStringMatchesFormat($expectedFileContent, $changedContent, 'Caused by ' . $fixtureFile); } } + + private function restoreOldParameterValues(): void + { + if ($this->oldParameterValues === []) { + return; + } + + $parameterProvider = self::$container->get(ParameterProvider::class); + + foreach ($this->oldParameterValues as $name => $oldParameterValue) { + $parameterProvider->changeParameter($name, $oldParameterValue); + } + } }