From f52c1809266b0cc2437a444e6bed21d442b4cfbc Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Mon, 15 Jul 2024 13:40:27 +0200 Subject: [PATCH 1/2] Print analysis time with -vvv --- bin/phpstan | 4 ++- src/Command/AnalyseCommand.php | 31 +++++++++++--------- src/Command/InceptionResult.php | 11 ++++++- tests/PHPStan/Command/AnalyseCommandTest.php | 3 +- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/bin/phpstan b/bin/phpstan index daf4cf747a..bb97758ff6 100755 --- a/bin/phpstan +++ b/bin/phpstan @@ -25,6 +25,8 @@ use Symfony\Component\Console\Helper\ProgressBar; define('__PHPSTAN_RUNNING__', true); + $analysisStartTime = microtime(true); + $devOrPharLoader = require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../preload.php'; $composer = ComposerHelper::getComposerConfig(getcwd()); @@ -158,7 +160,7 @@ use Symfony\Component\Console\Helper\ProgressBar; ProgressBar::setFormatDefinition('file_download', ' [%bar%] %percent:3s%% %fileSize%'); $reversedComposerAutoloaderProjectPaths = array_values(array_unique(array_reverse($composerAutoloaderProjectPaths))); - $application->add(new AnalyseCommand($reversedComposerAutoloaderProjectPaths)); + $application->add(new AnalyseCommand($reversedComposerAutoloaderProjectPaths, $analysisStartTime)); $application->add(new WorkerCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new ClearResultCacheCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new FixerWorkerCommand($reversedComposerAutoloaderProjectPaths)); diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index 21019ca695..6ecfba9105 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -70,6 +70,7 @@ class AnalyseCommand extends Command */ public function __construct( private array $composerAutoloaderProjectPaths, + private float $analysisStartTime, ) { parent::__construct(); @@ -171,7 +172,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($generateBaselineFile === null && $allowEmptyBaseline) { $inceptionResult->getStdOutput()->getStyle()->error('You must pass the --generate-baseline option alongside --allow-empty-baseline.'); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } $errorOutput = $inceptionResult->getErrorOutput(); @@ -214,13 +215,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $baselineExtension = pathinfo($generateBaselineFile, PATHINFO_EXTENSION); if ($baselineExtension === '') { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename must have an extension, %s provided instead.', pathinfo($generateBaselineFile, PATHINFO_BASENAME))); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } if (!in_array($baselineExtension, ['neon', 'php'], true)) { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename extension must be .neon or .php, .%s was used instead.', $baselineExtension)); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } @@ -244,12 +245,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $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.'); - return $inceptionResult->handleReturn(0, null); + return $inceptionResult->handleReturn(0, null, $this->analysisStartTime); } $inceptionResult->getErrorOutput()->getStyle()->error('No files found to analyse.'); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } $analysedConfigFiles = array_intersect($files, $container->getParameter('allConfigFiles')); @@ -275,7 +276,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($fix) { if ($generateBaselineFile !== null) { $inceptionResult->getStdOutput()->getStyle()->error('You cannot pass the --generate-baseline option when running PHPStan Pro.'); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } return $this->runFixer($inceptionResult, $container, $onlyFiles, $input, $output, $files); @@ -331,7 +332,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $previous = $previous->getPrevious(); } - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } throw $t; @@ -441,7 +442,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int count($internalErrors) === 1 ? 'An internal error' : 'Internal errors', )); - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } return $this->generateBaseline($generateBaselineFile, $inceptionResult, $analysisResult, $output, $allowEmptyBaseline, $baselineExtension, $failWithoutResultCache); @@ -477,6 +478,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return $inceptionResult->handleReturn( $exitCode, $analysisResult->getPeakMemoryUsageBytes(), + $this->analysisStartTime, ); } @@ -528,7 +530,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $bleedingEdge = (bool) $container->getParameter('featureToggles')['projectServicesNotInAnalysedPaths']; if ($bleedingEdge) { - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $errorOutput->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); @@ -540,6 +542,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return $inceptionResult->handleReturn( $exitCode, $analysisResult->getPeakMemoryUsageBytes(), + $this->analysisStartTime, ); } @@ -558,7 +561,7 @@ private function generateBaseline(string $generateBaselineFile, InceptionResult $inceptionResult->getStdOutput()->getStyle()->error('No errors were found during the analysis. Baseline could not be generated.'); $inceptionResult->getStdOutput()->writeLineFormatted('To allow generating empty baselines, pass --allow-empty-baseline option.'); - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $streamOutput = $this->createStreamOutput(); @@ -588,7 +591,7 @@ private function generateBaseline(string $generateBaselineFile, InceptionResult } catch (DirectoryCreatorException $e) { $inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage()); - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } try { @@ -596,7 +599,7 @@ private function generateBaseline(string $generateBaselineFile, InceptionResult } catch (CouldNotWriteFileException $e) { $inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage()); - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $errorsCount = 0; @@ -636,7 +639,7 @@ private function generateBaseline(string $generateBaselineFile, InceptionResult $exitCode = 2; } - return $inceptionResult->handleReturn($exitCode, $analysisResult->getPeakMemoryUsageBytes()); + return $inceptionResult->handleReturn($exitCode, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } /** @@ -648,7 +651,7 @@ private function runFixer(InceptionResult $inceptionResult, Container $container if ($ciDetector->isCiDetected()) { $inceptionResult->getStdOutput()->writeLineFormatted('PHPStan Pro can\'t run in CI environment yet. Stay tuned!'); - return $inceptionResult->handleReturn(1, null); + return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } /** @var FixerApplication $fixerApplication */ diff --git a/src/Command/InceptionResult.php b/src/Command/InceptionResult.php index 308935fb9d..2ac4e25a3a 100644 --- a/src/Command/InceptionResult.php +++ b/src/Command/InceptionResult.php @@ -7,6 +7,8 @@ use PHPStan\Internal\BytesHelper; use function max; use function memory_get_peak_usage; +use function microtime; +use function round; use function sprintf; class InceptionResult @@ -84,7 +86,7 @@ public function getGenerateBaselineFile(): ?string return $this->generateBaselineFile; } - public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes): int + public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes, ?float $analysisStartTime): int { if ($peakMemoryUsageBytes !== null && $this->getErrorOutput()->isVerbose()) { $this->getErrorOutput()->writeLineFormatted(sprintf( @@ -93,6 +95,13 @@ public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes): int )); } + if ($analysisStartTime !== null && $this->getErrorOutput()->isDebug()) { + $this->getErrorOutput()->writeLineFormatted(sprintf( + 'Analysis time: %0.1f seconds', + round(microtime(true) - $analysisStartTime, 1), + )); + } + return $exitCode; } diff --git a/tests/PHPStan/Command/AnalyseCommandTest.php b/tests/PHPStan/Command/AnalyseCommandTest.php index 7a548a5d54..2bec6dfa21 100644 --- a/tests/PHPStan/Command/AnalyseCommandTest.php +++ b/tests/PHPStan/Command/AnalyseCommandTest.php @@ -8,6 +8,7 @@ use Throwable; use function chdir; use function getcwd; +use function microtime; use function realpath; use function sprintf; use const DIRECTORY_SEPARATOR; @@ -104,7 +105,7 @@ public static function autoDiscoveryPathsProvider(): array */ private function runCommand(int $expectedStatusCode, array $parameters = []): string { - $commandTester = new CommandTester(new AnalyseCommand([])); + $commandTester = new CommandTester(new AnalyseCommand([], microtime(true))); $commandTester->execute([ 'paths' => [__DIR__ . DIRECTORY_SEPARATOR . 'test'], From b31b03af77d8dfba5867e065ab0eb4b8f056e705 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Mon, 15 Jul 2024 13:53:01 +0200 Subject: [PATCH 2/2] Remove useless nullability --- src/Command/InceptionResult.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Command/InceptionResult.php b/src/Command/InceptionResult.php index 2ac4e25a3a..5b38220f08 100644 --- a/src/Command/InceptionResult.php +++ b/src/Command/InceptionResult.php @@ -86,7 +86,7 @@ public function getGenerateBaselineFile(): ?string return $this->generateBaselineFile; } - public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes, ?float $analysisStartTime): int + public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes, float $analysisStartTime): int { if ($peakMemoryUsageBytes !== null && $this->getErrorOutput()->isVerbose()) { $this->getErrorOutput()->writeLineFormatted(sprintf( @@ -95,7 +95,7 @@ public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes, ?float $ )); } - if ($analysisStartTime !== null && $this->getErrorOutput()->isDebug()) { + if ($this->getErrorOutput()->isDebug()) { $this->getErrorOutput()->writeLineFormatted(sprintf( 'Analysis time: %0.1f seconds', round(microtime(true) - $analysisStartTime, 1),