diff --git a/phpstan.neon b/phpstan.neon index 70f3fade031..fba5fbf77a9 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -266,7 +266,9 @@ parameters: # BC layer on Rector deprecation - - path: src/Configuration/RectorConfigBuilder.php + paths: + - src/Configuration/RectorConfigBuilder.php + - src/Reporting/DeprecatedRulesReporter.php identifier: classConstant.deprecatedInterface - '#Class Rector\\PhpParser\\Node\\CustomNode\\FileWithoutNamespace implements deprecated interface Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface#' diff --git a/src/Console/Command/ProcessCommand.php b/src/Console/Command/ProcessCommand.php index f43d600698d..e6521fdf246 100644 --- a/src/Console/Command/ProcessCommand.php +++ b/src/Console/Command/ProcessCommand.php @@ -170,6 +170,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->deprecatedRulesReporter->reportDeprecatedRules(); $this->deprecatedRulesReporter->reportDeprecatedSkippedRules(); + $this->deprecatedRulesReporter->reportDeprecatedNodeTypes(); $this->missConfigurationReporter->reportSkippedNeverRegisteredRules(); diff --git a/src/DependencyInjection/LazyContainerFactory.php b/src/DependencyInjection/LazyContainerFactory.php index 7eb88fb8228..5279e7394d3 100644 --- a/src/DependencyInjection/LazyContainerFactory.php +++ b/src/DependencyInjection/LazyContainerFactory.php @@ -165,6 +165,7 @@ use Rector\PHPStanStaticTypeMapper\TypeMapper\VoidTypeMapper; use Rector\PostRector\Application\PostFileProcessor; use Rector\Rector\AbstractRector; +use Rector\Reporting\DeprecatedRulesReporter; use Rector\Skipper\Skipper\Skipper; use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface; use Rector\StaticTypeMapper\Contract\PhpParser\PhpParserNodeMapperInterface; @@ -428,6 +429,10 @@ public function create(): RectorConfig ->needs('$rectors') ->giveTagged(RectorInterface::class); + $rectorConfig->when(DeprecatedRulesReporter::class) + ->needs('$rectors') + ->giveTagged(RectorInterface::class); + $rectorConfig->singleton(FileProcessor::class); $rectorConfig->singleton(PostFileProcessor::class); diff --git a/src/Reporting/DeprecatedRulesReporter.php b/src/Reporting/DeprecatedRulesReporter.php index ebb1472ea82..852dea6d775 100644 --- a/src/Reporting/DeprecatedRulesReporter.php +++ b/src/Reporting/DeprecatedRulesReporter.php @@ -4,15 +4,22 @@ namespace Rector\Reporting; +use Rector\PhpParser\Enum\NodeGroup; use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; use Rector\Configuration\Option; use Rector\Configuration\Parameter\SimpleParameterProvider; +use Rector\Contract\PhpParser\Node\StmtsAwareInterface; +use Rector\Contract\Rector\RectorInterface; use Symfony\Component\Console\Style\SymfonyStyle; final readonly class DeprecatedRulesReporter { + /** + * @param RectorInterface[] $rectors + */ public function __construct( - private SymfonyStyle $symfonyStyle + private SymfonyStyle $symfonyStyle, + private array $rectors ) { } @@ -48,4 +55,33 @@ public function reportDeprecatedSkippedRules(): void $this->symfonyStyle->warning(sprintf('Skipped rule "%s" is deprecated', $skippedRectorRule)); } } + + public function reportDeprecatedNodeTypes(): void + { + // helper property to avoid reporting multiple times + static $reportedClasses = []; + + foreach ($this->rectors as $rector) { + if (! in_array(StmtsAwareInterface::class, $rector->getNodeTypes())) { + continue; + } + + // already reported, skip + if (in_array($rector::class, $reportedClasses, true)) { + continue; + } + + $reportedClasses[] = $rector::class; + + $this->symfonyStyle->warning(sprintf( + 'Rector rule "%s" uses StmtsAwareInterface that is now deprecated.%sUse "%s::%s" instead.%sSee %s for more', + $rector::class, + PHP_EOL, + NodeGroup::class, + 'STMTS_AWARE', + PHP_EOL . PHP_EOL, + 'https://github.com/rectorphp/rector-src/pull/7679' + )); + } + } }