diff --git a/build/target-repository/composer.json b/build/target-repository/composer.json index 01d33b7ac75..02630bbc841 100644 --- a/build/target-repository/composer.json +++ b/build/target-repository/composer.json @@ -23,8 +23,5 @@ "rector/rector-downgrade-php": "*" }, "minimum-stability": "dev", - "prefer-stable": true, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" - } + "prefer-stable": true } diff --git a/src/Console/Command/CustomRuleCommand.php b/src/Console/Command/CustomRuleCommand.php index c51909f1e25..af97edcce63 100644 --- a/src/Console/Command/CustomRuleCommand.php +++ b/src/Console/Command/CustomRuleCommand.php @@ -4,24 +4,15 @@ namespace Rector\Console\Command; -use Nette\Utils\FileSystem; -use Nette\Utils\Strings; -use PHPStan\Reflection\ReflectionProvider; -use Rector\Enum\ClassName; -use Rector\Exception\ShouldNotHappenException; -use Rector\FileSystem\JsonFileSystem; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\SplFileInfo; final class CustomRuleCommand extends Command { public function __construct( - private readonly SymfonyStyle $symfonyStyle, - private readonly ReflectionProvider $reflectionProvider + private readonly SymfonyStyle $symfonyStyle ) { parent::__construct(); } @@ -29,118 +20,15 @@ public function __construct( protected function configure(): void { $this->setName('custom-rule'); - $this->setDescription('Create base of local custom rule with tests'); + $this->setDescription('[DEPRECATED] Create base of local custom rule with tests'); } protected function execute(InputInterface $input, OutputInterface $output): int { - // ask for rule name - $rectorName = $this->symfonyStyle->ask( - 'What is the rule class name? (e.g. "LegacyCallToDbalMethodCall")?', - null, - static function (?string $answer): string { - if ($answer === '' || $answer === null) { - throw new ShouldNotHappenException('Rector name cannot be empty'); - } - - return $answer; - } + $this->symfonyStyle->error( + 'The "custom-rule" command is deprecated and no longer generates files. Use an AI agent to scaffold a custom rule instead - it handles the setup faster and with less guesswork.' ); - // suffix with Rector by convention - if (! str_ends_with((string) $rectorName, 'Rector')) { - $rectorName .= 'Rector'; - } - - $rectorName = ucfirst((string) $rectorName); - - // find all files in templates directory - $finder = Finder::create() - ->files() - ->in(__DIR__ . '/../../../templates/custom-rule') - ->notName('__Name__Test.php.phtml'); - - // 0. resolve if local phpunit is at least PHPUnit 10 (which supports #[DataProvider]) - // to provide annotation if not - if ($this->isPHPUnitAttributeSupported()) { - $finder->append([ - new SplFileInfo( - __DIR__ . '/../../../templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', - 'utils/rector/tests/Rector/__Name__', - 'utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', - ), - ]); - } else { - // use @annotations for PHPUnit 9 and bellow - $finder->append([ - new SplFileInfo( - __DIR__ . '/../../../templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', - 'utils/rector/tests/Rector/__Name__', - 'utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', - ), - ]); - } - - $currentDirectory = getcwd(); - - $generatedFilePaths = []; - - $fileInfos = iterator_to_array($finder->getIterator()); - - foreach ($fileInfos as $fileInfo) { - // replace "__Name__" with $rectorName - $newContent = $this->replaceNameVariable($rectorName, $fileInfo->getContents()); - $newFilePath = $this->replaceNameVariable($rectorName, $fileInfo->getRelativePathname()); - - // remove "phtml" suffix - $newFilePath = Strings::substring($newFilePath, 0, -strlen('.phtml')); - - FileSystem::write($currentDirectory . '/' . $newFilePath, $newContent, null); - - $generatedFilePaths[] = $newFilePath; - } - - $title = sprintf('Skeleton for "%s" rule was created. Now write rule logic to solve your problem', $rectorName); - $this->symfonyStyle->title($title); - $this->symfonyStyle->listing($generatedFilePaths); - - // 2. update autoload-dev in composer.json - $composerJsonFilePath = $currentDirectory . '/composer.json'; - if (file_exists($composerJsonFilePath)) { - $hasChanged = false; - $composerJson = JsonFileSystem::readFilePath($composerJsonFilePath); - - if (! isset($composerJson['autoload-dev']['psr-4']['Utils\\Rector\\'])) { - $composerJson['autoload-dev']['psr-4']['Utils\\Rector\\'] = 'utils/rector/src'; - $composerJson['autoload-dev']['psr-4']['Utils\\Rector\\Tests\\'] = 'utils/rector/tests'; - $hasChanged = true; - } - - if ($hasChanged) { - $this->symfonyStyle->writeln('We updated "composer.json" autoload-dev to load Rector rules.'); - $this->symfonyStyle->writeln('Now run "composer dump-autoload" to update paths'); - JsonFileSystem::writeFile($composerJsonFilePath, $composerJson); - } - } - - $this->symfonyStyle->newLine(1); - - // 3. update phpunit.xml(.dist) to include rector test suite - $this->symfonyStyle->writeln('Run Rector tests via PHPUnit:'); - $this->symfonyStyle->newLine(1); - $this->symfonyStyle->writeln(' vendor/bin/phpunit utils/rector/tests'); - $this->symfonyStyle->newLine(1); - - return Command::SUCCESS; - } - - private function replaceNameVariable(string $rectorName, string $contents): string - { - return str_replace('__Name__', $rectorName, $contents); - } - - private function isPHPUnitAttributeSupported(): bool - { - return $this->reflectionProvider->hasClass(ClassName::DATA_PROVIDER); + return Command::FAILURE; } } diff --git a/src/Enum/ClassName.php b/src/Enum/ClassName.php index f3a71087f6f..7c79bd5f51f 100644 --- a/src/Enum/ClassName.php +++ b/src/Enum/ClassName.php @@ -15,6 +15,4 @@ final class ClassName public const string JMS_TYPE = 'JMS\Serializer\Annotation\Type'; public const string DOCTRINE_ENTITY = 'Doctrine\ORM\Mapping\Entity'; - - public const string DATA_PROVIDER = 'PHPUnit\Framework\Attributes\DataProvider'; } diff --git a/src/FileSystem/JsonFileSystem.php b/src/FileSystem/JsonFileSystem.php index 052add9ba9a..6b53e456686 100644 --- a/src/FileSystem/JsonFileSystem.php +++ b/src/FileSystem/JsonFileSystem.php @@ -18,13 +18,4 @@ public static function readFilePath(string $filePath): array return Json::decode($fileContents, forceArrays: true); } - - /** - * @param array $data - */ - public static function writeFile(string $filePath, array $data): void - { - $json = Json::encode($data, pretty: true); - FileSystem::write($filePath, $json, null); - } } diff --git a/templates/custom-rule/utils/rector/src/Rector/__Name__.php.phtml b/templates/custom-rule/utils/rector/src/Rector/__Name__.php.phtml deleted file mode 100644 index fbbccf28be9..00000000000 --- a/templates/custom-rule/utils/rector/src/Rector/__Name__.php.phtml +++ /dev/null @@ -1,33 +0,0 @@ -> - */ - public function getNodeTypes(): array - { - // @todo select node type - return [\PhpParser\Node\Stmt\Class_::class]; - } - - /** - * @param \PhpParser\Node\Stmt\Class_ $node - */ - public function refactor(Node $node): ?Node - { - // @todo change the node - - return $node; - } -} diff --git a/templates/custom-rule/utils/rector/tests/Rector/__Name__/Fixture/some_class.php.inc.phtml b/templates/custom-rule/utils/rector/tests/Rector/__Name__/Fixture/some_class.php.inc.phtml deleted file mode 100644 index 6cf9dc365f0..00000000000 --- a/templates/custom-rule/utils/rector/tests/Rector/__Name__/Fixture/some_class.php.inc.phtml +++ /dev/null @@ -1,15 +0,0 @@ - ------ - diff --git a/templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml b/templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml deleted file mode 100644 index 370713d87a3..00000000000 --- a/templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml +++ /dev/null @@ -1,27 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): \Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/templates/custom-rule/utils/rector/tests/Rector/__Name__/config/configured_rule.php.phtml b/templates/custom-rule/utils/rector/tests/Rector/__Name__/config/configured_rule.php.phtml deleted file mode 100644 index 25ee3a80e6d..00000000000 --- a/templates/custom-rule/utils/rector/tests/Rector/__Name__/config/configured_rule.php.phtml +++ /dev/null @@ -1,9 +0,0 @@ -rule(\Utils\Rector\Rector\__Name__::class); -}; diff --git a/templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml b/templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml deleted file mode 100644 index 6cad0044274..00000000000 --- a/templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): \Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -}