Skip to content

Commit 22c84d2

Browse files
committed
Add diagnose command to run DiagnoseExtensions
1 parent 66a7578 commit 22c84d2

File tree

4 files changed

+112
-6
lines changed

4 files changed

+112
-6
lines changed

bin/phpstan

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use PHPStan\Command\AnalyseCommand;
55
use PHPStan\Command\ClearResultCacheCommand;
6+
use PHPStan\Command\DiagnoseCommand;
67
use PHPStan\Command\DumpParametersCommand;
78
use PHPStan\Command\FixerWorkerCommand;
89
use PHPStan\Command\WorkerCommand;
@@ -166,5 +167,6 @@ use Symfony\Component\Console\Helper\ProgressBar;
166167
$application->add(new ClearResultCacheCommand($reversedComposerAutoloaderProjectPaths));
167168
$application->add(new FixerWorkerCommand($reversedComposerAutoloaderProjectPaths));
168169
$application->add(new DumpParametersCommand($reversedComposerAutoloaderProjectPaths));
170+
$application->add(new DiagnoseCommand($reversedComposerAutoloaderProjectPaths));
169171
$application->run();
170172
})();

src/Command/DiagnoseCommand.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Command;
4+
5+
use PHPStan\Diagnose\DiagnoseExtension;
6+
use PHPStan\Diagnose\PHPStanDiagnoseExtension;
7+
use PHPStan\ShouldNotHappenException;
8+
use Symfony\Component\Console\Command\Command;
9+
use Symfony\Component\Console\Input\InputInterface;
10+
use Symfony\Component\Console\Input\InputOption;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
use function is_string;
13+
14+
class DiagnoseCommand extends Command
15+
{
16+
17+
private const NAME = 'diagnose';
18+
19+
/**
20+
* @param string[] $composerAutoloaderProjectPaths
21+
*/
22+
public function __construct(
23+
private array $composerAutoloaderProjectPaths,
24+
)
25+
{
26+
parent::__construct();
27+
}
28+
29+
protected function configure(): void
30+
{
31+
$this->setName(self::NAME)
32+
->setDescription('Shows diagnose information about PHPStan and extensions')
33+
->setDefinition([
34+
new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'),
35+
new InputOption(AnalyseCommand::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'),
36+
new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'),
37+
new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - do not catch internal errors'),
38+
new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for clearing result cache'),
39+
]);
40+
}
41+
42+
protected function initialize(InputInterface $input, OutputInterface $output): void
43+
{
44+
if ((bool) $input->getOption('debug')) {
45+
$application = $this->getApplication();
46+
if ($application === null) {
47+
throw new ShouldNotHappenException();
48+
}
49+
$application->setCatchExceptions(false);
50+
return;
51+
}
52+
}
53+
54+
protected function execute(InputInterface $input, OutputInterface $output): int
55+
{
56+
$memoryLimit = $input->getOption('memory-limit');
57+
$autoloadFile = $input->getOption('autoload-file');
58+
$configuration = $input->getOption('configuration');
59+
$level = $input->getOption(AnalyseCommand::OPTION_LEVEL);
60+
61+
if (
62+
(!is_string($memoryLimit) && $memoryLimit !== null)
63+
|| (!is_string($autoloadFile) && $autoloadFile !== null)
64+
|| (!is_string($configuration) && $configuration !== null)
65+
|| (!is_string($level) && $level !== null)
66+
) {
67+
throw new ShouldNotHappenException();
68+
}
69+
70+
try {
71+
$inceptionResult = CommandHelper::begin(
72+
$input,
73+
$output,
74+
[],
75+
$memoryLimit,
76+
$autoloadFile,
77+
$this->composerAutoloaderProjectPaths,
78+
$configuration,
79+
null,
80+
$level,
81+
false,
82+
);
83+
} catch (InceptionNotSuccessfulException) {
84+
return 1;
85+
}
86+
87+
$container = $inceptionResult->getContainer();
88+
$output = $inceptionResult->getStdOutput();
89+
90+
/** @var PHPStanDiagnoseExtension $phpstanDiagnoseExtension */
91+
$phpstanDiagnoseExtension = $container->getService('phpstanDiagnoseExtension');
92+
93+
// not using tag for this extension to make sure it's always first
94+
$phpstanDiagnoseExtension->print($output);
95+
96+
/** @var DiagnoseExtension $extension */
97+
foreach ($container->getServicesByTag(DiagnoseExtension::EXTENSION_TAG) as $extension) {
98+
$extension->print($output);
99+
}
100+
101+
return 0;
102+
}
103+
104+
}

src/Diagnose/DiagnoseExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ interface DiagnoseExtension
2626

2727
public const EXTENSION_TAG = 'phpstan.diagnoseExtension';
2828

29-
public function print(Output $errorOutput): void;
29+
public function print(Output $output): void;
3030

3131
}

src/Diagnose/PHPStanDiagnoseExtension.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,23 @@ public function __construct(private PhpVersion $phpVersion)
1515
{
1616
}
1717

18-
public function print(Output $errorOutput): void
18+
public function print(Output $output): void
1919
{
2020
$phpRuntimeVersion = new PhpVersion(PHP_VERSION_ID);
21-
$errorOutput->writeLineFormatted(sprintf(
21+
$output->writeLineFormatted(sprintf(
2222
'<info>PHP runtime version:</info> %s',
2323
$phpRuntimeVersion->getVersionString(),
2424
));
25-
$errorOutput->writeLineFormatted(sprintf(
25+
$output->writeLineFormatted(sprintf(
2626
'<info>PHP version for analysis:</info> %s (from %s)',
2727
$this->phpVersion->getVersionString(),
2828
$this->phpVersion->getSourceLabel(),
2929
));
30-
$errorOutput->writeLineFormatted(sprintf(
30+
$output->writeLineFormatted(sprintf(
3131
'<info>PHPStan version:</info> %s',
3232
ComposerHelper::getPhpStanVersion(),
3333
));
34-
$errorOutput->writeLineFormatted('');
34+
$output->writeLineFormatted('');
3535
}
3636

3737
}

0 commit comments

Comments
 (0)