Skip to content

Commit ca6cf9c

Browse files
authored
[dx] warn early about deprecated skipped rules, as not neccessary to skip anymore (#7742)
* [dx] warn early about deprecated skipped rules, as not neccessary to skip anymore * [comp] Restore FirstClassCallableRector and make it explicitly deprecated, to ease transition
1 parent bdf9c43 commit ca6cf9c

File tree

7 files changed

+99
-17
lines changed

7 files changed

+99
-17
lines changed

phpstan.neon

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,12 @@ parameters:
433433
- rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php
434434
- rules/Php81/Enum/AttributeName.php
435435

436+
# deprecated rule
437+
- '#Rule Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector must implements Rector\\VersionBonding\\Contract\\MinPhpVersionInterface#'
438+
- '#Register "Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector" service to "php81\.php" config set#'
439+
- '#Access to constant on deprecated class Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector#'
440+
-
441+
message: '#Only abstract classes can be extended#'
442+
path: rules/Php81/Rector/Array_/FirstClassCallableRector.php
443+
444+

rules/Php81/Rector/Array_/ArrayToFirstClassCallableRector.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* @see RFC https://wiki.php.net/rfc/first_class_callable_syntax
3232
* @see \Rector\Tests\Php81\Rector\Array_\ArrayToFirstClassCallableRector\ArrayToFirstClassCallableRectorTest
3333
*/
34-
final class ArrayToFirstClassCallableRector extends AbstractRector implements MinPhpVersionInterface
34+
class ArrayToFirstClassCallableRector extends AbstractRector implements MinPhpVersionInterface
3535
{
3636
public function __construct(
3737
private readonly ArrayCallableMethodMatcher $arrayCallableMethodMatcher,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Php81\Rector\Array_;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\MethodCall;
9+
use PhpParser\Node\Expr\StaticCall;
10+
use Rector\Configuration\Deprecation\Contract\DeprecatedInterface;
11+
use Rector\Exception\ShouldNotHappenException;
12+
13+
/**
14+
* @deprecated Renamed to \Rector\Php81\Rector\Array_\ArrayToFirstClassCallableRector
15+
*/
16+
final class FirstClassCallableRector extends ArrayToFirstClassCallableRector implements DeprecatedInterface
17+
{
18+
public function refactor(Node $node): StaticCall|MethodCall|null
19+
{
20+
throw new ShouldNotHappenException(sprintf(
21+
'%s is deprecated and renamed to "%s". Use it instead.',
22+
self::class,
23+
ArrayToFirstClassCallableRector::class
24+
));
25+
}
26+
}

src/Console/Command/ListRulesCommand.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5151
{
5252
$rectorClasses = $this->resolveRectorClasses();
5353

54-
$skippedClasses = $this->getSkippedCheckers();
54+
$skippedClasses = $this->getSkippedRectorClasses();
5555

5656
$outputFormat = $input->getOption(Option::OUTPUT_FORMAT);
5757
if ($outputFormat === 'json') {
@@ -95,20 +95,21 @@ private function resolveRectorClasses(): array
9595
}
9696

9797
/**
98-
* @return string[]
98+
* @return array<class-string>
9999
*/
100-
private function getSkippedCheckers(): array
100+
private function getSkippedRectorClasses(): array
101101
{
102-
$skippedCheckers = [];
103-
foreach ($this->skippedClassResolver->resolve() as $checkerClass => $fileList) {
102+
$skippedRectorClasses = [];
103+
104+
foreach ($this->skippedClassResolver->resolve() as $rectorClass => $fileList) {
104105
// ignore specific skips
105106
if ($fileList !== null) {
106107
continue;
107108
}
108109

109-
$skippedCheckers[] = $checkerClass;
110+
$skippedRectorClasses[] = $rectorClass;
110111
}
111112

112-
return $skippedCheckers;
113+
return $skippedRectorClasses;
113114
}
114115
}

src/Console/Command/ProcessCommand.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Rector\Exception\ShouldNotHappenException;
2020
use Rector\Reporting\DeprecatedRulesReporter;
2121
use Rector\Reporting\MissConfigurationReporter;
22+
use Rector\Skipper\SkipCriteriaResolver\SkippedClassResolver;
2223
use Rector\StaticReflection\DynamicSourceLocatorDecorator;
2324
use Rector\Util\MemoryLimiter;
2425
use Rector\ValueObject\Configuration;
@@ -45,6 +46,7 @@ public function __construct(
4546
private readonly DeprecatedRulesReporter $deprecatedRulesReporter,
4647
private readonly MissConfigurationReporter $missConfigurationReporter,
4748
private readonly ConfigurationRuleFilter $configurationRuleFilter,
49+
private readonly SkippedClassResolver $skippedClassResolver,
4850
) {
4951
parent::__construct();
5052
}
@@ -105,6 +107,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
105107
$this->reportLevelOverflow($levelOverflow);
106108
}
107109

110+
// 0. warn about skipped rules that are deprecated
111+
if ($this->skippedClassResolver->resolveDeprecatedSkippedClasses() !== []) {
112+
$this->symfonyStyle->warning(sprintf(
113+
'These rules are skipped, but are deprecated. Most likely you do not need to skip them anymore as not part of any set and remove them: %s* %s',
114+
"\n\n",
115+
implode(' * ', $this->skippedClassResolver->resolveDeprecatedSkippedClasses()) . "\n"
116+
));
117+
}
118+
108119
// 1. warn about rules registered in both withRules() and sets to avoid bloated rector.php configs
109120
$setAndRulesDuplicatedRegistrations = $configuration->getBothSetAndRulesDuplicatedRegistrations();
110121
if ($setAndRulesDuplicatedRegistrations !== []) {

src/Skipper/SkipCriteriaResolver/SkippedClassResolver.php

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,51 @@
44

55
namespace Rector\Skipper\SkipCriteriaResolver;
66

7+
use Rector\Configuration\Deprecation\Contract\DeprecatedInterface;
78
use Rector\Configuration\Option;
89
use Rector\Configuration\Parameter\SimpleParameterProvider;
910
use Rector\Testing\PHPUnit\StaticPHPUnitEnvironment;
1011

12+
/**
13+
* @see \Rector\Tests\Skipper\Skipper\SkippedClassResolverTest
14+
*/
1115
final class SkippedClassResolver
1216
{
1317
/**
14-
* @var null|array<string, string[]|null>
18+
* @var null|array<class-string, string[]|null>
1519
*/
16-
private null|array $skippedClasses = null;
20+
private null|array $skippedClassesToFiles = null;
1721

1822
/**
19-
* @return array<string, string[]|null>
23+
* @return array<class-string<DeprecatedInterface>>
24+
*/
25+
public function resolveDeprecatedSkippedClasses(): array
26+
{
27+
$skippedClassNames = array_keys($this->resolve());
28+
29+
return array_filter(
30+
$skippedClassNames,
31+
fn (string $class): bool => is_a($class, DeprecatedInterface::class, true)
32+
);
33+
}
34+
35+
/**
36+
* @return array<class-string, string[]|null>
2037
*/
2138
public function resolve(): array
2239
{
2340
// disable cache in tests
2441
if (StaticPHPUnitEnvironment::isPHPUnitRun()) {
25-
$this->skippedClasses = null;
42+
$this->skippedClassesToFiles = null;
2643
}
2744

2845
// already cached, even only empty array
29-
if ($this->skippedClasses !== null) {
30-
return $this->skippedClasses;
46+
if ($this->skippedClassesToFiles !== null) {
47+
return $this->skippedClassesToFiles;
3148
}
3249

3350
$skip = SimpleParameterProvider::provideArrayParameter(Option::SKIP);
34-
$this->skippedClasses = [];
51+
$this->skippedClassesToFiles = [];
3552

3653
foreach ($skip as $key => $value) {
3754
// e.g. [SomeClass::class] → shift values to [SomeClass::class => null]
@@ -49,9 +66,9 @@ public function resolve(): array
4966
continue;
5067
}
5168

52-
$this->skippedClasses[$key] = $value;
69+
$this->skippedClassesToFiles[$key] = $value;
5370
}
5471

55-
return $this->skippedClasses;
72+
return $this->skippedClassesToFiles;
5673
}
5774
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Skipper\Skipper;
6+
7+
use Rector\Skipper\SkipCriteriaResolver\SkippedClassResolver;
8+
use Rector\Testing\PHPUnit\AbstractLazyTestCase;
9+
10+
final class SkippedClassResolverTest extends AbstractLazyTestCase
11+
{
12+
public function test(): void
13+
{
14+
$skippedClassResolver = $this->make(SkippedClassResolver::class);
15+
16+
$this->assertSame([], $skippedClassResolver->resolveDeprecatedSkippedClasses());
17+
}
18+
}

0 commit comments

Comments
 (0)