|
4 | 4 |
|
5 | 5 | namespace Rector\Console\Command; |
6 | 6 |
|
| 7 | +use Nette\Utils\Json; |
| 8 | +use Rector\ChangesReporting\Output\ConsoleOutputFormatter; |
| 9 | +use Rector\Configuration\Option; |
| 10 | +use Rector\Contract\Rector\RectorInterface; |
| 11 | +use Rector\PostRector\Contract\Rector\PostRectorInterface; |
| 12 | +use Rector\Skipper\SkipCriteriaResolver\SkippedClassResolver; |
7 | 13 | use Symfony\Component\Console\Command\Command; |
8 | 14 | use Symfony\Component\Console\Input\InputInterface; |
| 15 | +use Symfony\Component\Console\Input\InputOption; |
9 | 16 | use Symfony\Component\Console\Output\OutputInterface; |
10 | 17 | use Symfony\Component\Console\Style\SymfonyStyle; |
11 | 18 |
|
12 | 19 | final class ListRulesCommand extends Command |
13 | 20 | { |
| 21 | + /** |
| 22 | + * @param RectorInterface[] $rectors |
| 23 | + */ |
14 | 24 | public function __construct( |
15 | | - private readonly SymfonyStyle $symfonyStyle |
| 25 | + private readonly SymfonyStyle $symfonyStyle, |
| 26 | + private readonly SkippedClassResolver $skippedClassResolver, |
| 27 | + private readonly array $rectors |
16 | 28 | ) { |
17 | 29 | parent::__construct(); |
18 | 30 | } |
19 | 31 |
|
20 | 32 | protected function configure(): void |
21 | 33 | { |
22 | 34 | $this->setName('list-rules'); |
23 | | - $this->setDescription('[DEPRECATED] Show loaded Rectors'); |
| 35 | + $this->setDescription('Show loaded Rectors'); |
24 | 36 |
|
25 | 37 | $this->setAliases(['show-rules']); |
| 38 | + |
| 39 | + $this->addOption( |
| 40 | + Option::OUTPUT_FORMAT, |
| 41 | + null, |
| 42 | + InputOption::VALUE_REQUIRED, |
| 43 | + 'Select output format', |
| 44 | + ConsoleOutputFormatter::NAME |
| 45 | + ); |
| 46 | + |
| 47 | + $this->addOption(Option::ONLY, null, InputOption::VALUE_REQUIRED, 'Fully qualified rule class name'); |
26 | 48 | } |
27 | 49 |
|
28 | 50 | protected function execute(InputInterface $input, OutputInterface $output): int |
29 | 51 | { |
30 | | - $this->symfonyStyle->error( |
31 | | - 'The "list-rules" command is deprecated and no longer provided. Run Rector with the set or rules you desire instead.' |
| 52 | + $rectorClasses = $this->resolveRectorClasses(); |
| 53 | + |
| 54 | + $skippedClasses = $this->getSkippedRectorClasses(); |
| 55 | + |
| 56 | + $outputFormat = $input->getOption(Option::OUTPUT_FORMAT); |
| 57 | + if ($outputFormat === 'json') { |
| 58 | + $data = [ |
| 59 | + 'rectors' => $rectorClasses, |
| 60 | + 'skipped-rectors' => $skippedClasses, |
| 61 | + ]; |
| 62 | + |
| 63 | + echo Json::encode($data, pretty: true) . PHP_EOL; |
| 64 | + return Command::SUCCESS; |
| 65 | + } |
| 66 | + |
| 67 | + $this->symfonyStyle->title('Loaded Rector rules'); |
| 68 | + $this->symfonyStyle->listing($rectorClasses); |
| 69 | + |
| 70 | + if ($skippedClasses !== []) { |
| 71 | + $this->symfonyStyle->title('Skipped Rector rules'); |
| 72 | + $this->symfonyStyle->listing($skippedClasses); |
| 73 | + } |
| 74 | + |
| 75 | + $this->symfonyStyle->newLine(); |
| 76 | + $this->symfonyStyle->note(sprintf('Loaded %d rules', count($rectorClasses))); |
| 77 | + |
| 78 | + return Command::SUCCESS; |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * @return array<class-string<RectorInterface>> |
| 83 | + */ |
| 84 | + private function resolveRectorClasses(): array |
| 85 | + { |
| 86 | + $customRectors = array_filter( |
| 87 | + $this->rectors, |
| 88 | + static fn (RectorInterface $rector): bool => ! $rector instanceof PostRectorInterface |
32 | 89 | ); |
33 | 90 |
|
34 | | - return Command::FAILURE; |
| 91 | + $rectorClasses = array_map(static fn (RectorInterface $rector): string => $rector::class, $customRectors); |
| 92 | + sort($rectorClasses); |
| 93 | + |
| 94 | + return array_unique($rectorClasses); |
| 95 | + } |
| 96 | + |
| 97 | + /** |
| 98 | + * @return array<class-string> |
| 99 | + */ |
| 100 | + private function getSkippedRectorClasses(): array |
| 101 | + { |
| 102 | + $skippedRectorClasses = []; |
| 103 | + |
| 104 | + foreach ($this->skippedClassResolver->resolve() as $rectorClass => $fileList) { |
| 105 | + // ignore specific skips |
| 106 | + if ($fileList !== null) { |
| 107 | + continue; |
| 108 | + } |
| 109 | + |
| 110 | + $skippedRectorClasses[] = $rectorClass; |
| 111 | + } |
| 112 | + |
| 113 | + return $skippedRectorClasses; |
35 | 114 | } |
36 | 115 | } |
0 commit comments