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('');
+ }
+
+}