From 54f866dcecb909e4796f4e6b8ba98443db26a540 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:15:02 +0700 Subject: [PATCH 01/11] [Differ] Remove ConsoleDiffer, use DefaultDiffer that utilize ColorConsoleDiffFormatter instead to avoid double diffing process fix cs --- e2e/e2eTestRunner.php | 6 ++-- e2e/e2eTestRunnerWithCache.php | 6 ++-- .../ValueObjectFactory/FileDiffFactory.php | 10 ++++--- .../Formatter/ColorConsoleDiffFormatter.php | 15 ++++++++++ src/Console/Formatter/ConsoleDiffer.php | 28 ------------------- 5 files changed, 29 insertions(+), 36 deletions(-) delete mode 100644 src/Console/Formatter/ConsoleDiffer.php diff --git a/e2e/e2eTestRunner.php b/e2e/e2eTestRunner.php index 3ce312202f2..8814ee05511 100644 --- a/e2e/e2eTestRunner.php +++ b/e2e/e2eTestRunner.php @@ -7,6 +7,7 @@ use Rector\Console\Formatter\ColorConsoleDiffFormatter; use Rector\Console\Formatter\ConsoleDiffer; use Rector\Console\Style\SymfonyStyleFactory; +use Rector\Differ\DefaultDiffer; use Rector\Util\Reflection\PrivatesAccessor; use Symfony\Component\Console\Command\Command; @@ -62,8 +63,9 @@ } // print color diff, to make easy find the differences -$consoleDiffer = new ConsoleDiffer(new ColorConsoleDiffFormatter()); -$diff = $consoleDiffer->diff($output, $expectedOutput); +$defaultDiffer = new DefaultDiffer(); +$colorConsoleDiffFormatter = new ColorConsoleDiffFormatter(); +$diff = $colorConsoleDiffFormatter->format($consoleDiffer->diff($output, $expectedOutput)); $symfonyStyle->writeln($diff); exit(Command::FAILURE); diff --git a/e2e/e2eTestRunnerWithCache.php b/e2e/e2eTestRunnerWithCache.php index c45533534e8..93cc4867a00 100644 --- a/e2e/e2eTestRunnerWithCache.php +++ b/e2e/e2eTestRunnerWithCache.php @@ -7,6 +7,7 @@ use Rector\Console\Formatter\ColorConsoleDiffFormatter; use Rector\Console\Formatter\ConsoleDiffer; use Rector\Console\Style\SymfonyStyleFactory; +use Rector\Differ\DefaultDiffer; use Rector\Util\Reflection\PrivatesAccessor; use Symfony\Component\Console\Command\Command; @@ -40,8 +41,9 @@ } // print color diff, to make easy find the differences -$consoleDiffer = new ConsoleDiffer(new ColorConsoleDiffFormatter()); -$diff = $consoleDiffer->diff($output, $expectedOutput); +$defaultDiffer = new DefaultDiffer(); +$colorConsoleDiffFormatter = new ColorConsoleDiffFormatter(); +$diff = $colorConsoleDiffFormatter->format($consoleDiffer->diff($output, $expectedOutput)); $symfonyStyle->writeln($diff); exit(Command::FAILURE); diff --git a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php index babbe6bd860..e4203fadffc 100644 --- a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php +++ b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php @@ -5,7 +5,7 @@ namespace Rector\ChangesReporting\ValueObjectFactory; use Rector\ChangesReporting\ValueObject\RectorWithLineChange; -use Rector\Console\Formatter\ConsoleDiffer; +use Rector\Console\Formatter\ColorConsoleDiffFormatter; use Rector\Differ\DefaultDiffer; use Rector\FileSystem\FilePathHelper; use Rector\ValueObject\Application\File; @@ -15,8 +15,8 @@ { public function __construct( private DefaultDiffer $defaultDiffer, - private ConsoleDiffer $consoleDiffer, private FilePathHelper $filePathHelper, + private ColorConsoleDiffFormatter $colorConsoleDiffFormatter ) { } @@ -32,11 +32,13 @@ public function createFileDiffWithLineChanges( ): FileDiff { $relativeFilePath = $this->filePathHelper->relativePath($file->getFilePath()); + $diff = $this->defaultDiffer->diff($oldContent, $newContent); + // always keep the most recent diff return new FileDiff( $relativeFilePath, - $shouldShowDiffs ? $this->defaultDiffer->diff($oldContent, $newContent) : '', - $shouldShowDiffs ? $this->consoleDiffer->diff($oldContent, $newContent) : '', + $shouldShowDiffs ? $diff : '', + $shouldShowDiffs ? $this->colorConsoleDiffFormatter->format($diff) : '', $rectorsWithLineChanges ); } diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index 73d235dc726..b4d9725f347 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -34,6 +34,12 @@ */ private const AT_START_REGEX = '#^(@.*)#'; + /** + * @var string + * @see https://regex101.com/r/8MXnfa/1 + */ + private const AT_DIFF_LINE_REGEX = '#^\@@( \-\d+,\d+ \+\d+,\d+ )@@\<\/fg=cyan\>$#'; + private string $template; public function __construct() @@ -71,6 +77,7 @@ private function formatWithTemplate(string $diff, string $template): string $string = $this->makePlusLinesGreen($string); $string = $this->makeMinusLinesRed($string); $string = $this->makeAtNoteCyan($string); + $string = $this->normalizeLineAtDiff($string); if ($string === ' ') { return ''; @@ -82,6 +89,14 @@ private function formatWithTemplate(string $diff, string $template): string return sprintf($template, implode(PHP_EOL, $coloredLines)); } + /** + * Remove number diff, eg; @@ -67,6 +67,8 @@ to become @@ @@ + */ + private function normalizeLineAtDiff(string $line): string + { + return Strings::replace($line, self::AT_DIFF_LINE_REGEX, '@@ @@'); + } + private function makePlusLinesGreen(string $string): string { return Strings::replace($string, self::PLUS_START_REGEX, '$1'); diff --git a/src/Console/Formatter/ConsoleDiffer.php b/src/Console/Formatter/ConsoleDiffer.php deleted file mode 100644 index a50c1d4e91f..00000000000 --- a/src/Console/Formatter/ConsoleDiffer.php +++ /dev/null @@ -1,28 +0,0 @@ -differ = new Differ($unifiedDiffOutputBuilder); - } - - public function diff(string $old, string $new): string - { - $diff = $this->differ->diff($old, $new); - return $this->colorConsoleDiffFormatter->format($diff); - } -} From 1f4b88b19ed691963d13d05eb8ef5d9bf143e399 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:35:20 +0700 Subject: [PATCH 02/11] Fix e2e --- e2e/e2eTestRunner.php | 2 +- e2e/e2eTestRunnerWithCache.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/e2eTestRunner.php b/e2e/e2eTestRunner.php index 8814ee05511..74268ea9bad 100644 --- a/e2e/e2eTestRunner.php +++ b/e2e/e2eTestRunner.php @@ -65,7 +65,7 @@ // print color diff, to make easy find the differences $defaultDiffer = new DefaultDiffer(); $colorConsoleDiffFormatter = new ColorConsoleDiffFormatter(); -$diff = $colorConsoleDiffFormatter->format($consoleDiffer->diff($output, $expectedOutput)); +$diff = $colorConsoleDiffFormatter->format($defaultDiffer->diff($output, $expectedOutput)); $symfonyStyle->writeln($diff); exit(Command::FAILURE); diff --git a/e2e/e2eTestRunnerWithCache.php b/e2e/e2eTestRunnerWithCache.php index 93cc4867a00..12dc23f1ab8 100644 --- a/e2e/e2eTestRunnerWithCache.php +++ b/e2e/e2eTestRunnerWithCache.php @@ -43,7 +43,7 @@ // print color diff, to make easy find the differences $defaultDiffer = new DefaultDiffer(); $colorConsoleDiffFormatter = new ColorConsoleDiffFormatter(); -$diff = $colorConsoleDiffFormatter->format($consoleDiffer->diff($output, $expectedOutput)); +$diff = $colorConsoleDiffFormatter->format($defaultDiffer->diff($output, $expectedOutput)); $symfonyStyle->writeln($diff); exit(Command::FAILURE); From da23246f02eed26ae8c026ecc917134455a08cba Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:38:27 +0700 Subject: [PATCH 03/11] final touch: register e2e test runner script to phpstan so it detected by phpstan if any issue --- e2e/e2eTestRunner.php | 4 ++-- e2e/e2eTestRunnerWithCache.php | 2 +- phpstan.neon | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/e2eTestRunner.php b/e2e/e2eTestRunner.php index 74268ea9bad..e99630b161f 100644 --- a/e2e/e2eTestRunner.php +++ b/e2e/e2eTestRunner.php @@ -38,7 +38,7 @@ $cliOptions = 'cli-options.txt'; if (file_exists($cliOptions)) { - $e2eCommand .= ' ' . trim(file_get_contents($cliOptions)); + $e2eCommand .= ' ' . trim((string) file_get_contents($cliOptions)); } @@ -56,7 +56,7 @@ $symfonyStyle = $symfonyStyleFactory->create(); $matchedExpectedOutput = false; -$expectedOutput = trim(file_get_contents($expectedDiff)); +$expectedOutput = trim((string) file_get_contents($expectedDiff)); if ($output === $expectedOutput) { $symfonyStyle->success('End-to-end test successfully completed'); exit(Command::SUCCESS); diff --git a/e2e/e2eTestRunnerWithCache.php b/e2e/e2eTestRunnerWithCache.php index 12dc23f1ab8..033b7fd2440 100644 --- a/e2e/e2eTestRunnerWithCache.php +++ b/e2e/e2eTestRunnerWithCache.php @@ -34,7 +34,7 @@ $symfonyStyle = $symfonyStyleFactory->create(); $matchedExpectedOutput = false; -$expectedOutput = trim(file_get_contents($expectedDiff)); +$expectedOutput = trim((string) file_get_contents($expectedDiff)); if ($output === $expectedOutput) { $symfonyStyle->success('End-to-end test successfully completed'); exit(Command::SUCCESS); diff --git a/phpstan.neon b/phpstan.neon index c1b8e3aa3b2..0a263b7d6fa 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -26,6 +26,8 @@ parameters: - tests - rules-tests - utils + - e2e/e2eTestRunnerWithCache.php + - e2e/e2e/e2eTestRunner.php scanDirectories: - stubs From 0633aa21014910ad91fc29bf813e951d2db74a74 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:43:12 +0700 Subject: [PATCH 04/11] Final touch: fix phpstan --- phpstan.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 0a263b7d6fa..756eba937d9 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -27,7 +27,7 @@ parameters: - rules-tests - utils - e2e/e2eTestRunnerWithCache.php - - e2e/e2e/e2eTestRunner.php + - e2e/e2eTestRunner.php scanDirectories: - stubs From 18b85ebb8a428e62039436eb458c9b6706456003 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:46:56 +0700 Subject: [PATCH 05/11] Final touch: clean up regex --- src/Console/Formatter/ColorConsoleDiffFormatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index b4d9725f347..963d269f569 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -36,9 +36,9 @@ /** * @var string - * @see https://regex101.com/r/8MXnfa/1 + * @see https://regex101.com/r/8MXnfa/2 */ - private const AT_DIFF_LINE_REGEX = '#^\@@( \-\d+,\d+ \+\d+,\d+ )@@\<\/fg=cyan\>$#'; + private const AT_DIFF_LINE_REGEX = '#^\@@ \-\d+,\d+ \+\d+,\d+ @@\<\/fg=cyan\>$#'; private string $template; From 00975d4b691ed4e4ca209f46e6c6660eeefae44f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:51:19 +0700 Subject: [PATCH 06/11] final touch: clean up logic --- .../ValueObjectFactory/FileDiffFactory.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php index e4203fadffc..f884480d3b9 100644 --- a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php +++ b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php @@ -32,13 +32,14 @@ public function createFileDiffWithLineChanges( ): FileDiff { $relativeFilePath = $this->filePathHelper->relativePath($file->getFilePath()); - $diff = $this->defaultDiffer->diff($oldContent, $newContent); + $diff = $shouldShowDiffs ? $this->defaultDiffer->diff($oldContent, $newContent) : ''; + $conosoleDiff = $shouldShowDiffs ? $this->colorConsoleDiffFormatter->format($diff) : ''; // always keep the most recent diff return new FileDiff( $relativeFilePath, - $shouldShowDiffs ? $diff : '', - $shouldShowDiffs ? $this->colorConsoleDiffFormatter->format($diff) : '', + $diff, + $conosoleDiff, $rectorsWithLineChanges ); } From 22df24fe6df17b70b0539fa929b0c43b7a247065 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 04:52:40 +0700 Subject: [PATCH 07/11] final touch: fix variable --- src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php index f884480d3b9..c816c615cec 100644 --- a/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php +++ b/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.php @@ -33,13 +33,13 @@ public function createFileDiffWithLineChanges( $relativeFilePath = $this->filePathHelper->relativePath($file->getFilePath()); $diff = $shouldShowDiffs ? $this->defaultDiffer->diff($oldContent, $newContent) : ''; - $conosoleDiff = $shouldShowDiffs ? $this->colorConsoleDiffFormatter->format($diff) : ''; + $consoleDiff = $shouldShowDiffs ? $this->colorConsoleDiffFormatter->format($diff) : ''; // always keep the most recent diff return new FileDiff( $relativeFilePath, $diff, - $conosoleDiff, + $consoleDiff, $rectorsWithLineChanges ); } From 44c05f58ca9d1302ac3805480e924e9ca306ccd8 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 12:20:59 +0700 Subject: [PATCH 08/11] final touch: keep fg=cyan color --- src/Console/Formatter/ColorConsoleDiffFormatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index 963d269f569..e7a00a89f51 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -94,7 +94,7 @@ private function formatWithTemplate(string $diff, string $template): string */ private function normalizeLineAtDiff(string $line): string { - return Strings::replace($line, self::AT_DIFF_LINE_REGEX, '@@ @@'); + return Strings::replace($line, self::AT_DIFF_LINE_REGEX, '@@ @@'); } private function makePlusLinesGreen(string $string): string From 032a9298690de42094e545bbee4404fac1c7ecfa Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 12:35:20 +0700 Subject: [PATCH 09/11] final touch: keep variable name for consistency --- src/Console/Formatter/ColorConsoleDiffFormatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index e7a00a89f51..522bb807f77 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -92,9 +92,9 @@ private function formatWithTemplate(string $diff, string $template): string /** * Remove number diff, eg; @@ -67,6 +67,8 @@ to become @@ @@ */ - private function normalizeLineAtDiff(string $line): string + private function normalizeLineAtDiff(string $string): string { - return Strings::replace($line, self::AT_DIFF_LINE_REGEX, '@@ @@'); + return Strings::replace($string, self::AT_DIFF_LINE_REGEX, '@@ @@'); } private function makePlusLinesGreen(string $string): string From 6ddfa80e068743b3c24d71e64662277c36faeec4 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 16:49:51 +0700 Subject: [PATCH 10/11] Final touch: stop loop when --- Original and +++ New already removed --- src/Console/Formatter/ColorConsoleDiffFormatter.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index 522bb807f77..3705b329a41 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -63,13 +63,22 @@ private function formatWithTemplate(string $diff, string $template): string $escapedDiffLines = NewLineSplitter::split($escapedDiff); // remove description of added + remove; obvious on diffs + $changedOriginal = false; + $changedNew = false; foreach ($escapedDiffLines as $key => $escapedDiffLine) { + // already found both, no need to continue + if ($changedOriginal && $changedNew) { + break; + } + if ($escapedDiffLine === '--- Original') { unset($escapedDiffLines[$key]); + $changedOriginal = true; } if ($escapedDiffLine === '+++ New') { unset($escapedDiffLines[$key]); + $changedNew = true; } } From 6f7777552bccbc89218fed48b978d93f7ec7f4f9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 Sep 2025 19:56:30 +0700 Subject: [PATCH 11/11] reduce loop --- .../Formatter/ColorConsoleDiffFormatter.php | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/Console/Formatter/ColorConsoleDiffFormatter.php b/src/Console/Formatter/ColorConsoleDiffFormatter.php index 3705b329a41..dfc6c7cb4ab 100644 --- a/src/Console/Formatter/ColorConsoleDiffFormatter.php +++ b/src/Console/Formatter/ColorConsoleDiffFormatter.php @@ -62,40 +62,34 @@ private function formatWithTemplate(string $diff, string $template): string $escapedDiffLines = NewLineSplitter::split($escapedDiff); - // remove description of added + remove; obvious on diffs - $changedOriginal = false; - $changedNew = false; + // remove description of added + remove, obvious on diffs + // decorize lines foreach ($escapedDiffLines as $key => $escapedDiffLine) { - // already found both, no need to continue - if ($changedOriginal && $changedNew) { - break; - } - if ($escapedDiffLine === '--- Original') { unset($escapedDiffLines[$key]); - $changedOriginal = true; + continue; } if ($escapedDiffLine === '+++ New') { unset($escapedDiffLines[$key]); - $changedNew = true; + continue; } - } - $coloredLines = array_map(function (string $string): string { - $string = $this->makePlusLinesGreen($string); - $string = $this->makeMinusLinesRed($string); - $string = $this->makeAtNoteCyan($string); - $string = $this->normalizeLineAtDiff($string); - - if ($string === ' ') { - return ''; + if ($escapedDiffLine === ' ') { + $escapedDiffLines[$key] = ''; + continue; } - return $string; - }, $escapedDiffLines); + $escapedDiffLine = $this->makePlusLinesGreen($escapedDiffLine); + $escapedDiffLine = $this->makeMinusLinesRed($escapedDiffLine); + $escapedDiffLine = $this->makeAtNoteCyan($escapedDiffLine); + $escapedDiffLine = $this->normalizeLineAtDiff($escapedDiffLine); + + // final decorized line + $escapedDiffLines[$key] = $escapedDiffLine; + } - return sprintf($template, implode(PHP_EOL, $coloredLines)); + return sprintf($template, implode(PHP_EOL, $escapedDiffLines)); } /**