From ffd7f9fcc5e7c4c53225fb7b8f8f8a9f1dea1f15 Mon Sep 17 00:00:00 2001 From: Julien Tattevin Date: Tue, 4 Aug 2026 12:45:13 +0200 Subject: [PATCH 1/3] Show previous exceptions during bootstrap --- bin/rector.php | 10 ++++- tests/Bin/RectorTest.php | 45 ++++++++++++++++++++ tests/Bin/config/incorrect-phpstan-files.php | 11 +++++ tests/Bin/config/phpstan.neon | 3 ++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 tests/Bin/RectorTest.php create mode 100644 tests/Bin/config/incorrect-phpstan-files.php create mode 100644 tests/Bin/config/phpstan.neon diff --git a/bin/rector.php b/bin/rector.php index 07eea9a09cc..ef8161e1ffa 100755 --- a/bin/rector.php +++ b/bin/rector.php @@ -143,14 +143,20 @@ public function loadIfExistsAndNotLoadedYet(string $filePath): void // report fatal error in json format if ($outputFormat === JsonOutputFormatter::NAME) { + $errors = []; + do { + $errors[] = $throwable->getMessage(); + } while ($throwable = $throwable->getPrevious()); echo Json::encode([ - 'fatal_errors' => [$throwable->getMessage()], + 'fatal_errors' => $errors, ]); } else { // report fatal errors in console format $symfonyStyleFactory = new SymfonyStyleFactory(new PrivatesAccessor()); $symfonyStyle = $symfonyStyleFactory->create(); - $symfonyStyle->error(str_replace("\r\n", "\n", $throwable->getMessage())); + do { + $symfonyStyle->error(str_replace("\r\n", "\n", $throwable->getMessage())); + } while ($throwable = $throwable->getPrevious()); } exit(Command::FAILURE); diff --git a/tests/Bin/RectorTest.php b/tests/Bin/RectorTest.php new file mode 100644 index 00000000000..f6169dc0d93 --- /dev/null +++ b/tests/Bin/RectorTest.php @@ -0,0 +1,45 @@ + [ + 'command' => 'bin/rector --version', + 'expectedOutput' => "Rector @package_version@\n", + ]; + + yield "Exception with previous console output" => [ + 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php', + 'expectedOutput' => << [ + 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php --output-format json', + 'expectedOutput' => '{"fatal_errors":["Rector\\\\NodeTypeResolver\\\\DependencyInjection\\\\PHPStanServicesFactory","Unexpected item \'parameters › invalidParameters\'."]}' + ]; + } + + #[DataProvider('outputProvider')] + public function testConsoleOutput(string $command, string $expectedOutput): void + { + $process = Process::fromShellCommandline($command); + $process->run(); + $this->assertSame($expectedOutput, $process->getOutput()); + } +} diff --git a/tests/Bin/config/incorrect-phpstan-files.php b/tests/Bin/config/incorrect-phpstan-files.php new file mode 100644 index 00000000000..724be93875a --- /dev/null +++ b/tests/Bin/config/incorrect-phpstan-files.php @@ -0,0 +1,11 @@ +withPhpSets() + ->withPaths([__DIR__]) + ->withPHPStanConfigs([__DIR__ . "/phpstan.neon"]); diff --git a/tests/Bin/config/phpstan.neon b/tests/Bin/config/phpstan.neon new file mode 100644 index 00000000000..efd970b5f28 --- /dev/null +++ b/tests/Bin/config/phpstan.neon @@ -0,0 +1,3 @@ + +parameters: + invalidParameters: true From 821285690bf495ed6412918b08e3e72eff81d421 Mon Sep 17 00:00:00 2001 From: Julien Tattevin Date: Tue, 4 Aug 2026 13:01:31 +0200 Subject: [PATCH 2/3] Fix cs --- tests/Bin/RectorTest.php | 31 ++++++++------------ tests/Bin/config/incorrect-phpstan-files.php | 3 +- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/tests/Bin/RectorTest.php b/tests/Bin/RectorTest.php index f6169dc0d93..12c93a56530 100644 --- a/tests/Bin/RectorTest.php +++ b/tests/Bin/RectorTest.php @@ -4,34 +4,29 @@ namespace Rector\Tests\Bin; +use Iterator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Process\Process; final class RectorTest extends TestCase { - public static function outputProvider() + /** + * @return Iterator + */ + public static function outputProvider(): Iterator { - - yield "Version" => [ - 'command' => 'bin/rector --version', + yield 'Version' => [ + 'command' => 'bin/rector --version', 'expectedOutput' => "Rector @package_version@\n", ]; - - yield "Exception with previous console output" => [ - 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php', - 'expectedOutput' => << [ + 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php', + 'expectedOutput' => "\n [ERROR] Rector\\NodeTypeResolver\\DependencyInjection\\PHPStanServicesFactory \n\n [ERROR] Unexpected item 'parameters › invalidParameters'. \n\n", ]; - yield "Exception with previous console output in JSON format" => [ - 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php --output-format json', - 'expectedOutput' => '{"fatal_errors":["Rector\\\\NodeTypeResolver\\\\DependencyInjection\\\\PHPStanServicesFactory","Unexpected item \'parameters › invalidParameters\'."]}' + yield 'Exception with previous console output in JSON format' => [ + 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php --output-format json', + 'expectedOutput' => '{"fatal_errors":["Rector\\\\NodeTypeResolver\\\\DependencyInjection\\\\PHPStanServicesFactory","Unexpected item \'parameters › invalidParameters\'."]}', ]; } diff --git a/tests/Bin/config/incorrect-phpstan-files.php b/tests/Bin/config/incorrect-phpstan-files.php index 724be93875a..3d570489773 100644 --- a/tests/Bin/config/incorrect-phpstan-files.php +++ b/tests/Bin/config/incorrect-phpstan-files.php @@ -1,6 +1,5 @@ withPhpSets() ->withPaths([__DIR__]) - ->withPHPStanConfigs([__DIR__ . "/phpstan.neon"]); + ->withPHPStanConfigs([__DIR__ . '/phpstan.neon']); From e8893006385f152053ef87378a0bc4988b3fb5d3 Mon Sep 17 00:00:00 2001 From: Julien Tattevin Date: Tue, 4 Aug 2026 13:39:10 +0200 Subject: [PATCH 3/3] Fix tests on windows-latest --- tests/Bin/RectorTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Bin/RectorTest.php b/tests/Bin/RectorTest.php index 12c93a56530..11f37ff522e 100644 --- a/tests/Bin/RectorTest.php +++ b/tests/Bin/RectorTest.php @@ -17,15 +17,15 @@ final class RectorTest extends TestCase public static function outputProvider(): Iterator { yield 'Version' => [ - 'command' => 'bin/rector --version', - 'expectedOutput' => "Rector @package_version@\n", + 'command' => PHP_BINARY . ' bin/rector --version', + 'expectedOutput' => "Rector @package_version@" . PHP_EOL, ]; yield 'Exception with previous console output' => [ - 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php', - 'expectedOutput' => "\n [ERROR] Rector\\NodeTypeResolver\\DependencyInjection\\PHPStanServicesFactory \n\n [ERROR] Unexpected item 'parameters › invalidParameters'. \n\n", + 'command' => PHP_BINARY . ' bin/rector -c tests/Bin/config/incorrect-phpstan-files.php', + 'expectedOutput' => PHP_EOL . " [ERROR] Rector\\NodeTypeResolver\\DependencyInjection\\PHPStanServicesFactory " . PHP_EOL . PHP_EOL . " [ERROR] Unexpected item 'parameters › invalidParameters'. " . PHP_EOL . PHP_EOL, ]; yield 'Exception with previous console output in JSON format' => [ - 'command' => 'bin/rector -c tests/Bin/config/incorrect-phpstan-files.php --output-format json', + 'command' => PHP_BINARY . ' bin/rector -c tests/Bin/config/incorrect-phpstan-files.php --output-format json', 'expectedOutput' => '{"fatal_errors":["Rector\\\\NodeTypeResolver\\\\DependencyInjection\\\\PHPStanServicesFactory","Unexpected item \'parameters › invalidParameters\'."]}', ]; } @@ -35,6 +35,6 @@ public function testConsoleOutput(string $command, string $expectedOutput): void { $process = Process::fromShellCommandline($command); $process->run(); - $this->assertSame($expectedOutput, $process->getOutput()); + $this->assertSame($expectedOutput, preg_replace("/ +/", " ", $process->getOutput())); } }