Skip to content

Commit 7167a79

Browse files
committed
Force the verification re-run to a dry run, so it also runs on apply runs
The verifier re-processes skipped files only to read which rules would change them. Building its own dry-run Configuration keeps FileProcessor from writing the skipped file, so the check is safe outside a dry run too. Drop the dry-run gate in ProcessCommand.
1 parent 2695b65 commit 7167a79

4 files changed

Lines changed: 20 additions & 18 deletions

File tree

‎src/Console/Command/ProcessCommand.php‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
202202
$this->missConfigurationReporter->reportSkippedNonRectorClasses();
203203
$this->missConfigurationReporter->reportUnusedSkips($processResult);
204204

205-
// re-runs skipped rules on their files, so only safe on a dry run that never writes
206-
if ($configuration->isDryRun()) {
207-
$this->missConfigurationReporter->reportUnnecessarySkips($configuration);
208-
}
205+
// the verification re-run is forced to a dry run, so it is safe on an apply run too
206+
$this->missConfigurationReporter->reportUnnecessarySkips();
209207

210208
return $this->resolveReturnCode($processResult, $configuration);
211209
}

‎src/Reporting/MissConfigurationReporter.php‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use Rector\Configuration\VendorMissAnalyseGuard;
1010
use Rector\Contract\Rector\RectorInterface;
1111
use Rector\PostRector\Contract\Rector\PostRectorInterface;
12-
use Rector\ValueObject\Configuration;
1312
use Rector\ValueObject\ProcessResult;
1413
use Symfony\Component\Console\Style\SymfonyStyle;
1514

@@ -51,12 +50,12 @@ public function reportUnusedSkips(ProcessResult $processResult): void
5150

5251
/**
5352
* Reports rule-scoped skips that matched a file but whose rule would not have changed it, so the
54-
* skip is unnecessary. Enabled with "->reportUnusedSkips()" and only on dry runs, as it re-runs
55-
* the rules on the skipped files.
53+
* skip is unnecessary. Enabled with "->reportUnusedSkips()". The re-run is forced to a dry run,
54+
* so it is safe on an apply run too.
5655
*/
57-
public function reportUnnecessarySkips(Configuration $configuration): void
56+
public function reportUnnecessarySkips(): void
5857
{
59-
$unnecessarySkips = $this->neededSkipVerifier->verify($configuration);
58+
$unnecessarySkips = $this->neededSkipVerifier->verify();
6059
if ($unnecessarySkips === []) {
6160
return;
6261
}

‎src/Reporting/NeededSkipVerifier.php‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
/**
1616
* Re-runs each rule-scoped skip on its exact file with skipping off. A skip whose rule still does
17-
* not change the file never prevented anything and can be removed. Runs on dry runs only, so the
18-
* re-processing never writes to disk.
17+
* not change the file never prevented anything and can be removed. The re-processing is forced to a
18+
* dry run, so it never writes, no matter the mode of the real run.
1919
*
2020
* @see \Rector\Tests\Reporting\NeededSkipVerifierTest
2121
*/
@@ -34,14 +34,14 @@ public function __construct(
3434
*
3535
* @return string[]
3636
*/
37-
public function verify(Configuration $configuration): array
37+
public function verify(): array
3838
{
3939
$skippedFilePathsByRule = $this->skipper->provideSkippedFilePathsByRule();
4040
if ($skippedFilePathsByRule === []) {
4141
return [];
4242
}
4343

44-
$changedRulesByFilePath = $this->resolveChangedRulesByFilePath($skippedFilePathsByRule, $configuration);
44+
$changedRulesByFilePath = $this->resolveChangedRulesByFilePath($skippedFilePathsByRule);
4545

4646
$unnecessarySkips = [];
4747
foreach ($skippedFilePathsByRule as $rectorClass => $filePaths) {
@@ -75,7 +75,7 @@ public function verify(Configuration $configuration): array
7575
* @param array<class-string, string[]> $skippedFilePathsByRule
7676
* @return array<string, string[]> real file path => rule classes that changed it
7777
*/
78-
private function resolveChangedRulesByFilePath(array $skippedFilePathsByRule, Configuration $configuration): array
78+
private function resolveChangedRulesByFilePath(array $skippedFilePathsByRule): array
7979
{
8080
$uniqueFilePaths = [];
8181
foreach ($skippedFilePathsByRule as $filePaths) {
@@ -84,6 +84,9 @@ private function resolveChangedRulesByFilePath(array $skippedFilePathsByRule, Co
8484
}
8585
}
8686

87+
// force a dry run, so re-processing detects the change but never writes the skipped file
88+
$dryRunConfiguration = new Configuration(isDryRun: true);
89+
8790
$this->skipper->startVerifyingSkips();
8891

8992
$changedRulesByFilePath = [];
@@ -92,7 +95,7 @@ private function resolveChangedRulesByFilePath(array $skippedFilePathsByRule, Co
9295
$file = new File($filePath, FileSystem::read($filePath));
9396
$this->currentFileProvider->setFile($file);
9497

95-
$fileProcessResult = $this->fileProcessor->processFile($file, $configuration);
98+
$fileProcessResult = $this->fileProcessor->processFile($file, $dryRunConfiguration);
9699

97100
// a broken file is not verifiable, leave it out so its skips are kept
98101
if ($fileProcessResult->getSystemErrors() !== []) {

‎tests/Reporting/NeededSkipVerifierTest.php‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use Rector\Skipper\Skipper\Skipper;
1414
use Rector\Testing\PHPUnit\AbstractLazyTestCase;
1515
use Rector\Tests\Reporting\Source\MakeClassFinalRector;
16-
use Rector\ValueObject\Configuration;
1716

1817
final class NeededSkipVerifierTest extends AbstractLazyTestCase
1918
{
@@ -58,21 +57,24 @@ public function testReportsSkipThatRuleWouldNotHaveChanged(): void
5857
$this->assertTrue($skipper->shouldSkipRectorAndFile($rule, $unnecessaryFilePath));
5958

6059
$neededSkipVerifier = $rectorConfig->make(NeededSkipVerifier::class);
61-
$unnecessarySkips = $neededSkipVerifier->verify(new Configuration(isDryRun: true));
60+
$unnecessarySkips = $neededSkipVerifier->verify();
6261

6362
// one rule group, listing only the unnecessary file
6463
$this->assertCount(1, $unnecessarySkips);
6564
$this->assertStringContainsString(MakeClassFinalRector::class, $unnecessarySkips[0]);
6665
$this->assertStringContainsString('unnecessary_skip.php', $unnecessarySkips[0]);
6766
$this->assertStringNotContainsString('needed_skip.php', $unnecessarySkips[0]);
67+
68+
// the verification is forced to a dry run, so the skipped file on disk stays untouched
69+
$this->assertSame('<?php class SomeClass {}', FileSystem::read($neededFilePath));
6870
}
6971

7072
public function testReportsNothingWithoutCapturedSkips(): void
7173
{
7274
$rectorConfig = $this->createContainerWithRule();
7375

7476
$neededSkipVerifier = $rectorConfig->make(NeededSkipVerifier::class);
75-
$this->assertSame([], $neededSkipVerifier->verify(new Configuration(isDryRun: true)));
77+
$this->assertSame([], $neededSkipVerifier->verify());
7678
}
7779

7880
private function createContainerWithRule(): RectorConfig

0 commit comments

Comments
 (0)