From 44673857cad8ffc3f53a8505fa3629d4599e1c04 Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Mon, 5 Jan 2026 14:27:03 +0000 Subject: [PATCH 1/8] Fixes showing files changed in JSON formatter --- .../Output/JsonOutputFormatter.php | 15 ++-- .../Output/Fixtures/without_diffs.json | 17 +++++ .../Output/JsonOutputFormatterTest.php | 70 +++++++++++++++++++ 3 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/ChangesReporting/Output/Fixtures/without_diffs.json create mode 100644 tests/ChangesReporting/Output/JsonOutputFormatterTest.php diff --git a/src/ChangesReporting/Output/JsonOutputFormatter.php b/src/ChangesReporting/Output/JsonOutputFormatter.php index 65062a4bb8e..f37835ba859 100644 --- a/src/ChangesReporting/Output/JsonOutputFormatter.php +++ b/src/ChangesReporting/Output/JsonOutputFormatter.php @@ -31,7 +31,8 @@ public function report(ProcessResult $processResult, Configuration $configuratio ], ]; - $fileDiffs = $processResult->getFileDiffs(); + // We need onlyWithChanges: false to include all file diffs + $fileDiffs = $processResult->getFileDiffs(onlyWithChanges: false); ksort($fileDiffs); foreach ($fileDiffs as $fileDiff) { $filePath = $configuration->isReportingWithRealPath() @@ -39,11 +40,13 @@ public function report(ProcessResult $processResult, Configuration $configuratio : $fileDiff->getRelativeFilePath() ; - $errorsJson[Bridge::FILE_DIFFS][] = [ - 'file' => $filePath, - 'diff' => $fileDiff->getDiff(), - 'applied_rectors' => $fileDiff->getRectorClasses(), - ]; + if ($configuration->shouldShowDiffs() && $fileDiff->getDiff() !== '') { + $errorsJson[Bridge::FILE_DIFFS][] = [ + 'file' => $filePath, + 'diff' => $fileDiff->getDiff(), + 'applied_rectors' => $fileDiff->getRectorClasses(), + ]; + } // for Rector CI $errorsJson['changed_files'][] = $filePath; diff --git a/tests/ChangesReporting/Output/Fixtures/without_diffs.json b/tests/ChangesReporting/Output/Fixtures/without_diffs.json new file mode 100644 index 00000000000..19629ae13dc --- /dev/null +++ b/tests/ChangesReporting/Output/Fixtures/without_diffs.json @@ -0,0 +1,17 @@ +{ + "totals": { + "changed_files": 2, + "errors": 1 + }, + "changed_files": [ + "some/file.php", + "some/file_foo.php" + ], + "errors": [ + { + "message": "Some error message", + "file": "some/file.php", + "line": 1 + } + ] +} diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php new file mode 100644 index 00000000000..8fe6f194346 --- /dev/null +++ b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php @@ -0,0 +1,70 @@ +jsonOutputFormatter = new JsonOutputFormatter(); + + parent::setUp(); + } + + public function testGetName(): void + { + $this->assertSame('json', $this->jsonOutputFormatter->getName()); + } + + public function testReportShouldShowNumberOfChangesWithNoDiffs(): void + { + $this->expectOsOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); + + $this->jsonOutputFormatter->report( + new ProcessResult( + [new SystemError('Some error message', 'some/file.php', 1)], + [ + new FileDiff( + 'some/file.php', + '--- Original' . PHP_EOL . '+++ New' . PHP_EOL . + '@@ -38,5 +39,6 @@' . PHP_EOL . + 'return true;' . PHP_EOL . '}' . PHP_EOL, + 'diff console formatted', + [new RectorWithLineChange(StrStartsWithRector::class, 38)] + ), + new FileDiff( + 'some/file_foo.php', + '', + '', + [new RectorWithLineChange(StrStartsWithRector::class, 38)] + ), + ], + 2 + ), + new Configuration(showDiffs: false) + ); + } + + protected function expectOsOutputString(string $expectedOutput): void + { + $isWindows = strncasecmp(PHP_OS, 'WIN', 3) === 0; + if ($isWindows) { + $expectedOutput = str_replace('%0A', '%0D%0A', $expectedOutput); + } + + parent::expectOutputString($expectedOutput); + } +} From 27f41ffd0d4c3de19f7b431da150dad0db842ee9 Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Mon, 5 Jan 2026 16:29:12 +0000 Subject: [PATCH 2/8] test change --- .../Output/JsonOutputFormatterTest.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php index 8fe6f194346..b5c2fc2dbbc 100644 --- a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php +++ b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php @@ -31,7 +31,7 @@ public function testGetName(): void public function testReportShouldShowNumberOfChangesWithNoDiffs(): void { - $this->expectOsOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); + $this->expectOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); $this->jsonOutputFormatter->report( new ProcessResult( @@ -57,14 +57,4 @@ public function testReportShouldShowNumberOfChangesWithNoDiffs(): void new Configuration(showDiffs: false) ); } - - protected function expectOsOutputString(string $expectedOutput): void - { - $isWindows = strncasecmp(PHP_OS, 'WIN', 3) === 0; - if ($isWindows) { - $expectedOutput = str_replace('%0A', '%0D%0A', $expectedOutput); - } - - parent::expectOutputString($expectedOutput); - } } From 3a1a2b14da1e1619e4b48fc32cb3770f294f03ec Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Mon, 5 Jan 2026 16:34:49 +0000 Subject: [PATCH 3/8] Revert "test change" This reverts commit e9b5a0f13addb2c4d9c5faf8b72cc51b48ec3088. --- .../Output/JsonOutputFormatterTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php index b5c2fc2dbbc..8fe6f194346 100644 --- a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php +++ b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php @@ -31,7 +31,7 @@ public function testGetName(): void public function testReportShouldShowNumberOfChangesWithNoDiffs(): void { - $this->expectOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); + $this->expectOsOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); $this->jsonOutputFormatter->report( new ProcessResult( @@ -57,4 +57,14 @@ public function testReportShouldShowNumberOfChangesWithNoDiffs(): void new Configuration(showDiffs: false) ); } + + protected function expectOsOutputString(string $expectedOutput): void + { + $isWindows = strncasecmp(PHP_OS, 'WIN', 3) === 0; + if ($isWindows) { + $expectedOutput = str_replace('%0A', '%0D%0A', $expectedOutput); + } + + parent::expectOutputString($expectedOutput); + } } From f3f049420888bf0a182bf3f7ef14ec73e21f6796 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 Jan 2026 13:53:27 +0700 Subject: [PATCH 4/8] normalized line ending --- .../Output/JsonOutputFormatterTest.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php index 8fe6f194346..e177a49c4d2 100644 --- a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php +++ b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php @@ -31,7 +31,7 @@ public function testGetName(): void public function testReportShouldShowNumberOfChangesWithNoDiffs(): void { - $this->expectOsOutputString((string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json')); + ob_start(); $this->jsonOutputFormatter->report( new ProcessResult( @@ -56,15 +56,14 @@ public function testReportShouldShowNumberOfChangesWithNoDiffs(): void ), new Configuration(showDiffs: false) ); - } - protected function expectOsOutputString(string $expectedOutput): void - { - $isWindows = strncasecmp(PHP_OS, 'WIN', 3) === 0; - if ($isWindows) { - $expectedOutput = str_replace('%0A', '%0D%0A', $expectedOutput); - } + $actualOutput = ob_get_clean(); + $expectedOutput = (string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json'); + + // Normalize line endings for comparison + $actualOutput = str_replace("\r\n", "\n", $actualOutput); + $expectedOutput = str_replace("\r\n", "\n", $expectedOutput); - parent::expectOutputString($expectedOutput); + $this->assertSame($expectedOutput, $actualOutput); } } From 47d556b4b52971173abb3282cf2ffcc9f16ce85c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 Jan 2026 14:30:59 +0700 Subject: [PATCH 5/8] fix phpstan --- tests/ChangesReporting/Output/JsonOutputFormatterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php index e177a49c4d2..36a295894a7 100644 --- a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php +++ b/tests/ChangesReporting/Output/JsonOutputFormatterTest.php @@ -57,7 +57,7 @@ public function testReportShouldShowNumberOfChangesWithNoDiffs(): void new Configuration(showDiffs: false) ); - $actualOutput = ob_get_clean(); + $actualOutput = (string) ob_get_clean(); $expectedOutput = (string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json'); // Normalize line endings for comparison From 00f4f5a2ccaed446c46d4e3ba24010c8211fd949 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 13 Jan 2026 18:22:48 +0700 Subject: [PATCH 6/8] [ChangesReporting][Alternative] Use JsonOutputFactory to make easy test for cross OS usage --- .../Output/Factory/JsonOutputFactory.php | 82 +++++++++++++++++++ .../Output/JsonOutputFormatter.php | 70 +--------------- .../JsonOutputFactoryTest.php} | 32 ++------ .../Output/Fixtures/without_diffs.json | 2 +- 4 files changed, 90 insertions(+), 96 deletions(-) create mode 100644 src/ChangesReporting/Output/Factory/JsonOutputFactory.php rename tests/ChangesReporting/Output/{JsonOutputFormatterTest.php => Factory/JsonOutputFactoryTest.php} (64%) diff --git a/src/ChangesReporting/Output/Factory/JsonOutputFactory.php b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php new file mode 100644 index 00000000000..b4b26251a43 --- /dev/null +++ b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php @@ -0,0 +1,82 @@ + [ + 'changed_files' => $processResult->getTotalChanged(), + ], + ]; + + // We need onlyWithChanges: false to include all file diffs + $fileDiffs = $processResult->getFileDiffs(onlyWithChanges: false); + ksort($fileDiffs); + foreach ($fileDiffs as $fileDiff) { + $filePath = $configuration->isReportingWithRealPath() + ? ($fileDiff->getAbsoluteFilePath() ?? '') + : $fileDiff->getRelativeFilePath() + ; + + if ($configuration->shouldShowDiffs() && $fileDiff->getDiff() !== '') { + $errorsJson[Bridge::FILE_DIFFS][] = [ + 'file' => $filePath, + 'diff' => $fileDiff->getDiff(), + 'applied_rectors' => $fileDiff->getRectorClasses(), + ]; + } + + // for Rector CI + $errorsJson['changed_files'][] = $filePath; + } + + $systemErrors = $processResult->getSystemErrors(); + $errorsJson['totals']['errors'] = count($systemErrors); + + $errorsData = self::createErrorsData($systemErrors, $configuration->isReportingWithRealPath()); + if ($errorsData !== []) { + $errorsJson['errors'] = $errorsData; + } + + return Json::encode($errorsJson, pretty: true); + } + + /** + * @param SystemError[] $errors + * @return mixed[] + */ + private static function createErrorsData(array $errors, bool $absoluteFilePath): array + { + $errorsData = []; + + foreach ($errors as $error) { + $errorDataJson = [ + 'message' => $error->getMessage(), + 'file' => $absoluteFilePath ? $error->getAbsoluteFilePath() : $error->getRelativeFilePath(), + ]; + + if ($error->getRectorClass() !== null) { + $errorDataJson['caused_by'] = $error->getRectorClass(); + } + + if ($error->getLine() !== null) { + $errorDataJson['line'] = $error->getLine(); + } + + $errorsData[] = $errorDataJson; + } + + return $errorsData; + } +} \ No newline at end of file diff --git a/src/ChangesReporting/Output/JsonOutputFormatter.php b/src/ChangesReporting/Output/JsonOutputFormatter.php index f37835ba859..7064487d25c 100644 --- a/src/ChangesReporting/Output/JsonOutputFormatter.php +++ b/src/ChangesReporting/Output/JsonOutputFormatter.php @@ -4,11 +4,9 @@ namespace Rector\ChangesReporting\Output; -use Nette\Utils\Json; use Rector\ChangesReporting\Contract\Output\OutputFormatterInterface; -use Rector\Parallel\ValueObject\Bridge; +use Rector\ChangesReporting\Output\Factory\JsonOutputFactory; use Rector\ValueObject\Configuration; -use Rector\ValueObject\Error\SystemError; use Rector\ValueObject\ProcessResult; final readonly class JsonOutputFormatter implements OutputFormatterInterface @@ -25,70 +23,6 @@ public function getName(): string public function report(ProcessResult $processResult, Configuration $configuration): void { - $errorsJson = [ - 'totals' => [ - 'changed_files' => $processResult->getTotalChanged(), - ], - ]; - - // We need onlyWithChanges: false to include all file diffs - $fileDiffs = $processResult->getFileDiffs(onlyWithChanges: false); - ksort($fileDiffs); - foreach ($fileDiffs as $fileDiff) { - $filePath = $configuration->isReportingWithRealPath() - ? ($fileDiff->getAbsoluteFilePath() ?? '') - : $fileDiff->getRelativeFilePath() - ; - - if ($configuration->shouldShowDiffs() && $fileDiff->getDiff() !== '') { - $errorsJson[Bridge::FILE_DIFFS][] = [ - 'file' => $filePath, - 'diff' => $fileDiff->getDiff(), - 'applied_rectors' => $fileDiff->getRectorClasses(), - ]; - } - - // for Rector CI - $errorsJson['changed_files'][] = $filePath; - } - - $systemErrors = $processResult->getSystemErrors(); - $errorsJson['totals']['errors'] = count($systemErrors); - - $errorsData = $this->createErrorsData($systemErrors, $configuration->isReportingWithRealPath()); - if ($errorsData !== []) { - $errorsJson['errors'] = $errorsData; - } - - $json = Json::encode($errorsJson, pretty: true); - echo $json . PHP_EOL; - } - - /** - * @param SystemError[] $errors - * @return mixed[] - */ - private function createErrorsData(array $errors, bool $absoluteFilePath): array - { - $errorsData = []; - - foreach ($errors as $error) { - $errorDataJson = [ - 'message' => $error->getMessage(), - 'file' => $absoluteFilePath ? $error->getAbsoluteFilePath() : $error->getRelativeFilePath(), - ]; - - if ($error->getRectorClass() !== null) { - $errorDataJson['caused_by'] = $error->getRectorClass(); - } - - if ($error->getLine() !== null) { - $errorDataJson['line'] = $error->getLine(); - } - - $errorsData[] = $errorDataJson; - } - - return $errorsData; + echo JsonOutputFactory::create($processResult, $configuration) . PHP_EOL; } } diff --git a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php b/tests/ChangesReporting/Output/Factory/JsonOutputFactoryTest.php similarity index 64% rename from tests/ChangesReporting/Output/JsonOutputFormatterTest.php rename to tests/ChangesReporting/Output/Factory/JsonOutputFactoryTest.php index 36a295894a7..5f7a467b910 100644 --- a/tests/ChangesReporting/Output/JsonOutputFormatterTest.php +++ b/tests/ChangesReporting/Output/Factory/JsonOutputFactoryTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace ChangesReporting\Output; +namespace Rector\Tests\ChangesReporting\Output\Factory; use PHPUnit\Framework\TestCase; -use Rector\ChangesReporting\Output\JsonOutputFormatter; +use Rector\ChangesReporting\Output\Factory\JsonOutputFactory; use Rector\ChangesReporting\ValueObject\RectorWithLineChange; use Rector\Php80\Rector\Identical\StrStartsWithRector; use Rector\ValueObject\Configuration; @@ -13,27 +13,11 @@ use Rector\ValueObject\ProcessResult; use Rector\ValueObject\Reporting\FileDiff; -final class JsonOutputFormatterTest extends TestCase +final class JsonOutputFactoryTest extends TestCase { - private readonly JsonOutputFormatter $jsonOutputFormatter; - - protected function setUp(): void - { - $this->jsonOutputFormatter = new JsonOutputFormatter(); - - parent::setUp(); - } - - public function testGetName(): void - { - $this->assertSame('json', $this->jsonOutputFormatter->getName()); - } - public function testReportShouldShowNumberOfChangesWithNoDiffs(): void { - ob_start(); - - $this->jsonOutputFormatter->report( + $actualOutput = JsonOutputFactory::create( new ProcessResult( [new SystemError('Some error message', 'some/file.php', 1)], [ @@ -57,13 +41,7 @@ public function testReportShouldShowNumberOfChangesWithNoDiffs(): void new Configuration(showDiffs: false) ); - $actualOutput = (string) ob_get_clean(); - $expectedOutput = (string) file_get_contents(__DIR__ . '/Fixtures/without_diffs.json'); - - // Normalize line endings for comparison - $actualOutput = str_replace("\r\n", "\n", $actualOutput); - $expectedOutput = str_replace("\r\n", "\n", $expectedOutput); - + $expectedOutput = (string) file_get_contents(__DIR__ . '/../Fixtures/without_diffs.json'); $this->assertSame($expectedOutput, $actualOutput); } } diff --git a/tests/ChangesReporting/Output/Fixtures/without_diffs.json b/tests/ChangesReporting/Output/Fixtures/without_diffs.json index 19629ae13dc..d15f37f36de 100644 --- a/tests/ChangesReporting/Output/Fixtures/without_diffs.json +++ b/tests/ChangesReporting/Output/Fixtures/without_diffs.json @@ -14,4 +14,4 @@ "line": 1 } ] -} +} \ No newline at end of file From 8f69825d25f9017c1066059b046c43debe7a40e7 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 13 Jan 2026 18:25:08 +0700 Subject: [PATCH 7/8] final touch: eol --- src/ChangesReporting/Output/Factory/JsonOutputFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ChangesReporting/Output/Factory/JsonOutputFactory.php b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php index b4b26251a43..e72240d8225 100644 --- a/src/ChangesReporting/Output/Factory/JsonOutputFactory.php +++ b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php @@ -79,4 +79,4 @@ private static function createErrorsData(array $errors, bool $absoluteFilePath): return $errorsData; } -} \ No newline at end of file +} From 7b3dab62b0d520931cad8ba7e9af94ad1eee4135 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 13 Jan 2026 11:41:19 +0000 Subject: [PATCH 8/8] [ci-review] Rector Rectify --- src/ChangesReporting/Output/Factory/JsonOutputFactory.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ChangesReporting/Output/Factory/JsonOutputFactory.php b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php index e72240d8225..aa75152d3ab 100644 --- a/src/ChangesReporting/Output/Factory/JsonOutputFactory.php +++ b/src/ChangesReporting/Output/Factory/JsonOutputFactory.php @@ -10,6 +10,9 @@ use Rector\ValueObject\Error\SystemError; use Rector\ValueObject\ProcessResult; +/** + * @see \Rector\Tests\ChangesReporting\Output\Factory\JsonOutputFactoryTest + */ final class JsonOutputFactory { public static function create(ProcessResult $processResult, Configuration $configuration): string