diff --git a/conf/config.neon b/conf/config.neon index b7521b88aa..183d223e5a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2098,6 +2098,10 @@ services: php8Parser: @php8Parser autowired: false + phpstanDiagnoseExtension: + class: PHPStan\Diagnose\PHPStanDiagnoseExtension + autowired: false + # Error formatters - diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index 12b35ee1ec..f30200feef 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -10,6 +10,8 @@ use PHPStan\Command\Symfony\SymfonyOutput; use PHPStan\Command\Symfony\SymfonyStyle; use PHPStan\DependencyInjection\Container; +use PHPStan\Diagnose\DiagnoseExtension; +use PHPStan\Diagnose\PHPStanDiagnoseExtension; use PHPStan\File\CouldNotWriteFileException; use PHPStan\File\FileReader; use PHPStan\File\FileWriter; @@ -225,14 +227,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { [$files, $onlyFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException $e) { + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); $inceptionResult->getErrorOutput()->writeLineFormatted(sprintf('%s', $e->getMessage())); return 1; } catch (InceptionNotSuccessfulException) { + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); return 1; } if (count($files) === 0) { $bleedingEdge = (bool) $container->getParameter('featureToggles')['zeroFiles']; + + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); + if (!$bleedingEdge) { $inceptionResult->getErrorOutput()->getStyle()->note('No files found to analyse.'); $inceptionResult->getErrorOutput()->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); @@ -422,6 +429,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($generateBaselineFile !== null) { + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); if (count($internalErrorsTuples) > 0) { foreach ($internalErrorsTuples as [$internalError]) { $inceptionResult->getStdOutput()->writeLineFormatted($internalError->getMessage()); @@ -459,6 +467,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $exitCode = $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()); + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); + $errorOutput->writeLineFormatted('⚠️ Result is incomplete because of severe errors. ⚠️'); $errorOutput->writeLineFormatted(' Fix these errors first and then re-run PHPStan'); $errorOutput->writeLineFormatted(' to get all reported errors.'); @@ -525,6 +535,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } + $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); + return $inceptionResult->handleReturn( $exitCode, $analysisResult->getPeakMemoryUsageBytes(), @@ -647,4 +659,22 @@ private function runFixer(InceptionResult $inceptionResult, Container $container ); } + private function runDiagnoseExtensions(Container $container, Output $errorOutput): void + { + if (!$errorOutput->isDebug()) { + return; + } + + /** @var PHPStanDiagnoseExtension $phpstanDiagnoseExtension */ + $phpstanDiagnoseExtension = $container->getService('phpstanDiagnoseExtension'); + + // not using tag for this extension to make sure it's always first + $phpstanDiagnoseExtension->print($errorOutput); + + /** @var DiagnoseExtension $extension */ + foreach ($container->getServicesByTag(DiagnoseExtension::EXTENSION_TAG) as $extension) { + $extension->print($errorOutput); + } + } + } diff --git a/src/DependencyInjection/ConditionalTagsExtension.php b/src/DependencyInjection/ConditionalTagsExtension.php index 7b286eae88..e11f095fda 100644 --- a/src/DependencyInjection/ConditionalTagsExtension.php +++ b/src/DependencyInjection/ConditionalTagsExtension.php @@ -11,6 +11,7 @@ use PHPStan\DependencyInjection\Type\LazyDynamicThrowTypeExtensionProvider; use PHPStan\DependencyInjection\Type\LazyParameterClosureTypeExtensionProvider; use PHPStan\DependencyInjection\Type\LazyParameterOutTypeExtensionProvider; +use PHPStan\Diagnose\DiagnoseExtension; use PHPStan\Parser\RichParser; use PHPStan\PhpDoc\StubFilesExtension; use PHPStan\PhpDoc\TypeNodeResolverExtension; @@ -57,6 +58,7 @@ public function getConfigSchema(): Nette\Schema\Schema LazyParameterOutTypeExtensionProvider::FUNCTION_TAG => $bool, LazyParameterOutTypeExtensionProvider::METHOD_TAG => $bool, LazyParameterOutTypeExtensionProvider::STATIC_METHOD_TAG => $bool, + DiagnoseExtension::EXTENSION_TAG => $bool, ])->min(1)); } diff --git a/src/Diagnose/DiagnoseExtension.php b/src/Diagnose/DiagnoseExtension.php new file mode 100644 index 0000000000..5df5d628ef --- /dev/null +++ b/src/Diagnose/DiagnoseExtension.php @@ -0,0 +1,31 @@ +writeLineFormatted(sprintf( + 'PHP runtime version: %s', + $phpRuntimeVersion->getVersionString(), + )); + $errorOutput->writeLineFormatted(sprintf( + 'PHPStan version: %s', + ComposerHelper::getPhpStanVersion(), + )); + $errorOutput->writeLineFormatted(''); + } + +}