From edcf56710e9a8344e4152175bd5d40710686b213 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 1 Mar 2025 13:52:38 +0100 Subject: [PATCH 1/6] Small performance improvement --- src/Psalm/Progress/DefaultProgress.php | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php index 4f08807d990..7640de7d3a1 100644 --- a/src/Psalm/Progress/DefaultProgress.php +++ b/src/Psalm/Progress/DefaultProgress.php @@ -17,10 +17,13 @@ class DefaultProgress extends LongProgress // Update the progress bar at most once per 0.1 seconds. // This reduces flickering and reduces the amount of time spent writing to STDERR and updating the terminal. - private const PROGRESS_BAR_SAMPLE_INTERVAL = 0.1; + private const PROGRESS_BAR_SAMPLE_INTERVAL_NANOSECONDS = 100_000_000; - /** @var float the last time when the progress bar UI was updated */ - private float $previous_update_time = 0.0; + /** the last time when the progress bar UI was updated (seconds) */ + private int $previous_update_seconds = 0; + + /** the last time when the progress bar UI was updated (nanoseconds) */ + private int $previous_update_nseconds = 0; #[Override] public function taskDone(int $level): void @@ -28,21 +31,21 @@ public function taskDone(int $level): void if ($this->fixed_size && $this->number_of_tasks > self::TOO_MANY_FILES) { ++$this->progress; - // Source for rate limiting: - // https://github.com/phan/phan/blob/9a788581ee1a4e1c35bebf89c435fd8a238c1d17/src/Phan/CLI.php - $time = microtime(true); + [$seconds, $nseconds] = hrtime(); // If not enough time has elapsed, then don't update the progress bar. // Making the update frequency based on time (instead of the number of files) // prevents the terminal from rapidly flickering while processing small/empty files, // and reduces the time spent writing to stderr. - if ($time - $this->previous_update_time < self::PROGRESS_BAR_SAMPLE_INTERVAL) { - // Make sure to output the section for 100% completion regardless of limits, to avoid confusion. - if ($this->progress !== $this->number_of_tasks) { - return; - } + // Make sure to output the section for 100% completion regardless of limits, to avoid confusion. + if ($seconds === $this->previous_update_seconds + && ($nseconds - $this->previous_update_nseconds < self::PROGRESS_BAR_SAMPLE_INTERVAL_NANOSECONDS) + && $this->progress !== $this->number_of_tasks + ) { + return; } - $this->previous_update_time = $time; + $this->previous_update_seconds = $seconds; + $this->previous_update_nseconds = $nseconds; $inner_progress = self::renderInnerProgressBar( self::NUMBER_OF_COLUMNS, From babe8b2b7ec6de4f60e589fe3afd6120c9c8cdc8 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 1 Mar 2025 14:35:00 +0100 Subject: [PATCH 2/6] More detailed progress --- .../Internal/Analyzer/ProjectAnalyzer.php | 17 ++++--- src/Psalm/Internal/Cli/Psalm.php | 4 ++ src/Psalm/Internal/Codebase/Analyzer.php | 7 +-- .../Internal/Codebase/TaintFlowGraph.php | 11 +++- .../Internal/LanguageServer/Progress.php | 26 ++++++++++ src/Psalm/Progress/DebugProgress.php | 20 +++++--- src/Psalm/Progress/DefaultProgress.php | 3 +- src/Psalm/Progress/LongProgress.php | 50 ++++++++++++------- src/Psalm/Progress/Progress.php | 36 +++---------- src/Psalm/Progress/VoidProgress.php | 30 +++++++++++ tests/AsyncTestCase.php | 2 +- tests/TestCase.php | 2 +- 12 files changed, 140 insertions(+), 68 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index d3c0de3d907..25f2106f59f 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -47,6 +47,7 @@ use Psalm\Issue\UnusedProperty; use Psalm\Issue\UnusedVariable; use Psalm\Plugin\EventHandler\Event\AfterCodebasePopulatedEvent; +use Psalm\Progress\Phase; use Psalm\Progress\Progress; use Psalm\Progress\VoidProgress; use Psalm\Report; @@ -461,7 +462,7 @@ public function check(string $base_dir, bool $is_diff = false): void } $this->progress->write($this->generatePHPVersionMessage()); - $this->progress->startScanningFiles(); + $this->progress->startPhase(Phase::SCAN); $diff_no_files = false; @@ -519,7 +520,7 @@ public function check(string $base_dir, bool $is_diff = false): void $this->config->eventDispatcher->dispatchAfterCodebasePopulated($event); } - $this->progress->startAnalyzingFiles(); + $this->progress->startPhase(Phase::ANALYSIS); $this->codebase->analyzer->analyzeFiles( $this, @@ -875,7 +876,7 @@ public function checkDir(string $dir_name): void $this->checkDirWithConfig($dir_name, $this->config, true); $this->progress->write($this->generatePHPVersionMessage()); - $this->progress->startScanningFiles(); + $this->progress->startPhase(Phase::SCAN); $this->config->initializePlugins($this); @@ -883,7 +884,7 @@ public function checkDir(string $dir_name): void $this->config->visitStubFiles($this->codebase, $this->progress); - $this->progress->startAnalyzingFiles(); + $this->progress->startPhase(Phase::ANALYSIS); $this->codebase->analyzer->analyzeFiles( $this, @@ -975,7 +976,7 @@ public function checkFile(string $file_path): void $this->file_reference_provider->loadReferenceCache(); $this->progress->write($this->generatePHPVersionMessage()); - $this->progress->startScanningFiles(); + $this->progress->startPhase(Phase::SCAN); $this->config->initializePlugins($this); @@ -983,7 +984,7 @@ public function checkFile(string $file_path): void $this->config->visitStubFiles($this->codebase, $this->progress); - $this->progress->startAnalyzingFiles(); + $this->progress->startPhase(Phase::ANALYSIS); $this->codebase->analyzer->analyzeFiles( $this, @@ -999,7 +1000,7 @@ public function checkFile(string $file_path): void public function checkPaths(array $paths_to_check): void { $this->progress->write($this->generatePHPVersionMessage()); - $this->progress->startScanningFiles(); + $this->progress->startPhase(Phase::SCAN); $this->config->visitPreloadedStubFiles($this->codebase, $this->progress); $this->visitAutoloadFiles(); @@ -1031,7 +1032,7 @@ public function checkPaths(array $paths_to_check): void $this->config->eventDispatcher->dispatchAfterCodebasePopulated($event); - $this->progress->startAnalyzingFiles(); + $this->progress->startPhase(Phase::ANALYSIS); $this->codebase->analyzer->analyzeFiles( $this, diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index 3482a4497d2..5d99a386d9b 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -13,6 +13,7 @@ use Psalm\Exception\ConfigException; use Psalm\Internal\Analyzer\ProjectAnalyzer; use Psalm\Internal\CliUtils; +use Psalm\Internal\Codebase\InternalCallMapHandler; use Psalm\Internal\Codebase\ReferenceMapGenerator; use Psalm\Internal\Composer; use Psalm\Internal\ErrorHandler; @@ -389,6 +390,9 @@ public static function run(array $argv): void $config->addPluginPath($plugin_path); } + // Prime cache + InternalCallMapHandler::getCallMap(); + if ($paths_to_check === null) { $project_analyzer->check($current_dir, $is_diff); } elseif ($paths_to_check) { diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index ec9969c87c9..ee664870864 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -25,6 +25,7 @@ use Psalm\Internal\Provider\FileProvider; use Psalm\Internal\Provider\FileStorageProvider; use Psalm\IssueBuffer; +use Psalm\Progress\Phase; use Psalm\Progress\Progress; use Psalm\Type; use Psalm\Type\Union; @@ -247,7 +248,7 @@ public function analyzeFiles( $scanned_files = $codebase->scanner->getScannedFiles(); if ($codebase->taint_flow_graph) { - $codebase->taint_flow_graph->connectSinksAndSources(); + $codebase->taint_flow_graph->connectSinksAndSources($codebase->progress); } $this->progress->finish(); @@ -280,7 +281,7 @@ public function analyzeFiles( } if ($alter_code) { - $this->progress->startAlteringFiles(); + $this->progress->startPhase(Phase::ALTERING); $project_analyzer->prepareMigration(); @@ -296,7 +297,7 @@ public function analyzeFiles( private function doAnalysis(ProjectAnalyzer $project_analyzer, int $pool_size): void { - $this->progress->start(count($this->files_to_analyze)); + $this->progress->expand(count($this->files_to_analyze)); ksort($this->files_to_analyze); diff --git a/src/Psalm/Internal/Codebase/TaintFlowGraph.php b/src/Psalm/Internal/Codebase/TaintFlowGraph.php index 64bc7ac67a0..8fdefcb172d 100644 --- a/src/Psalm/Internal/Codebase/TaintFlowGraph.php +++ b/src/Psalm/Internal/Codebase/TaintFlowGraph.php @@ -31,6 +31,8 @@ use Psalm\Issue\TaintedUserSecret; use Psalm\Issue\TaintedXpath; use Psalm\IssueBuffer; +use Psalm\Progress\Phase; +use Psalm\Progress\Progress; use Psalm\Type\TaintKind; use function array_diff; @@ -202,8 +204,10 @@ public function getIssueTrace(DataFlowNode $source): array return [$node]; } - public function connectSinksAndSources(): void + public function connectSinksAndSources(Progress $progress): void { + $progress->startPhase(Phase::TAINT_GRAPH_RESOLUTION); + $visited_source_ids = []; $sources = $this->sources; @@ -213,10 +217,11 @@ public function connectSinksAndSources(): void ksort($this->forward_edges); // reprocess resolved descendants up to a maximum nesting level of 40 - for ($i = 0; count($sinks) && count($sources) && $i < 40; $i++) { + for ($i = 0; count($sinks) && count($sources) && $i < 10000; $i++) { $new_sources = []; ksort($sources); + $progress->expand(count($sources)); foreach ($sources as $source) { $source_taints = $source->taints; @@ -234,6 +239,8 @@ public function connectSinksAndSources(): void $visited_source_ids, )]; } + + $progress->taskDone(0); } $sources = $new_sources; diff --git a/src/Psalm/Internal/LanguageServer/Progress.php b/src/Psalm/Internal/LanguageServer/Progress.php index cc21674b37b..3541b98dfbf 100644 --- a/src/Psalm/Internal/LanguageServer/Progress.php +++ b/src/Psalm/Internal/LanguageServer/Progress.php @@ -5,6 +5,7 @@ namespace Psalm\Internal\LanguageServer; use Override; +use Psalm\Progress\Phase; use Psalm\Progress\Progress as Base; use function str_replace; @@ -30,6 +31,31 @@ public function debug(string $message): void } } + #[Override] + public function startPhase(Phase $phase): void + { + } + + #[Override] + public function alterFileDone(string $file_name): void + { + } + + #[Override] + public function expand(int $number_of_tasks): void + { + } + + #[Override] + public function taskDone(int $level): void + { + } + + #[Override] + public function finish(): void + { + } + #[Override] public function write(string $message): void { diff --git a/src/Psalm/Progress/DebugProgress.php b/src/Psalm/Progress/DebugProgress.php index f20c26681ac..2c7c418560f 100644 --- a/src/Psalm/Progress/DebugProgress.php +++ b/src/Psalm/Progress/DebugProgress.php @@ -25,21 +25,29 @@ public function debug(string $message): void } #[Override] - public function startScanningFiles(): void + public function startPhase(Phase $phase): void + { + $this->write(match ($phase) { + Phase::SCAN => "\nScanning files...\n\n", + Phase::ANALYSIS => "\nAnalysing files...\n", + Phase::ALTERING => "\nUpdating files...\n", + Phase::TAINT_GRAPH_RESOLUTION => "\nResolving taint graph...\n", + }); + } + + #[Override] + public function expand(int $number_of_tasks): void { - $this->write("\n" . 'Scanning files...' . "\n\n"); } #[Override] - public function startAnalyzingFiles(): void + public function taskDone(int $level): void { - $this->write("\n" . 'Analyzing files...' . "\n"); } #[Override] - public function startAlteringFiles(): void + public function finish(): void { - $this->write('Updating files...' . "\n"); } #[Override] diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php index 7640de7d3a1..fd2293dce18 100644 --- a/src/Psalm/Progress/DefaultProgress.php +++ b/src/Psalm/Progress/DefaultProgress.php @@ -6,8 +6,8 @@ use Override; +use function hrtime; use function max; -use function microtime; use function str_repeat; use function strlen; @@ -106,6 +106,7 @@ public function finish(): void { if ($this->number_of_tasks > self::TOO_MANY_FILES) { $this->write(str_repeat(' ', self::NUMBER_OF_COLUMNS + strlen($this->getOverview()) + 1) . "\r"); + $this->reportPhaseDuration(null); } else { parent::finish(); } diff --git a/src/Psalm/Progress/LongProgress.php b/src/Psalm/Progress/LongProgress.php index 03dd630fd0a..6e3f2e28665 100644 --- a/src/Psalm/Progress/LongProgress.php +++ b/src/Psalm/Progress/LongProgress.php @@ -8,6 +8,8 @@ use Override; use function floor; +use function microtime; +use function round; use function sprintf; use function str_repeat; use function strlen; @@ -24,6 +26,9 @@ class LongProgress extends Progress protected bool $fixed_size = false; + protected ?Phase $prevPhase = null; + protected float $started = 0.0; + public function __construct( protected bool $print_errors = true, protected bool $print_infos = true, @@ -32,24 +37,41 @@ public function __construct( } #[Override] - public function startScanningFiles(): void + public function debug(string $message): void { - $this->fixed_size = false; - $this->write("\n" . 'Scanning files...' . ($this->in_ci ? '' : "\n\n")); } #[Override] - public function startAnalyzingFiles(): void + public function startPhase(Phase $phase): void { - $this->fixed_size = true; - $this->write("\n\n" . 'Analyzing files...' . "\n\n"); + $this->reportPhaseDuration($phase); + $this->write(match ($phase) { + Phase::SCAN => "\nScanning files...\n\n", + Phase::ANALYSIS => "\nAnalysing files...\n\n", + Phase::ALTERING => "\nUpdating files...\n", + Phase::TAINT_GRAPH_RESOLUTION => "\n\nResolving taint graph...\n\n", + }); + $this->fixed_size = $phase === Phase::ANALYSIS || $phase === Phase::ALTERING; } - #[Override] - public function startAlteringFiles(): void + protected function reportPhaseDuration(?Phase $newPhase = null): void { - $this->fixed_size = true; - $this->write('Altering files...' . "\n"); + if ($this->prevPhase === $newPhase) { + return; + } + $this->progress = 0; + $this->number_of_tasks = 0; + if ($this->prevPhase !== null) { + $took = round(microtime(true) - $this->started, 1); + $this->write(match ($this->prevPhase) { + Phase::SCAN => "\n\nScan took $took seconds.\n", + Phase::ANALYSIS => "\nAnalysis took $took seconds.\n", + Phase::ALTERING => "\n\nUpdating files took $took seconds.\n", + Phase::TAINT_GRAPH_RESOLUTION => "\n\nTaint graph resolution took $took seconds.\n", + }); + } + $this->started = microtime(true); + $this->prevPhase = $newPhase; } #[Override] @@ -58,13 +80,6 @@ public function alterFileDone(string $file_name): void $this->write('Altered ' . $file_name . "\n"); } - #[Override] - public function start(int $number_of_tasks): void - { - $this->number_of_tasks = $number_of_tasks; - $this->progress = 0; - } - #[Override] public function expand(int $number_of_tasks): void { @@ -114,6 +129,7 @@ public function taskDone(int $level): void #[Override] public function finish(): void { + $this->reportPhaseDuration(null); $this->write(PHP_EOL); } diff --git a/src/Psalm/Progress/Progress.php b/src/Psalm/Progress/Progress.php index 248878ff0a1..468e59ef26f 100644 --- a/src/Psalm/Progress/Progress.php +++ b/src/Psalm/Progress/Progress.php @@ -22,41 +22,19 @@ public function setErrorReporting(): void error_reporting(E_ERROR); } - public function debug(string $message): void - { - } + abstract public function debug(string $message): void; - public function startScanningFiles(): void - { - } - public function startAnalyzingFiles(): void - { - } + abstract public function startPhase(Phase $phase): void; - public function startAlteringFiles(): void - { - } + abstract public function expand(int $number_of_tasks): void; - public function alterFileDone(string $file_name): void - { - } + abstract public function taskDone(int $level): void; - public function start(int $number_of_tasks): void - { - } + abstract public function finish(): void; - public function expand(int $number_of_tasks): void - { - } - public function taskDone(int $level): void - { - } - - public function finish(): void - { - } + abstract public function alterFileDone(string $file_name): void; public function write(string $message): void { @@ -68,7 +46,7 @@ public function warning(string $message): void $this->write('Warning: ' . $message . PHP_EOL); } - protected static function doesTerminalSupportUtf8(): bool + final protected static function doesTerminalSupportUtf8(): bool { if (stripos(PHP_OS, 'WIN') === 0) { if (!function_exists('sapi_windows_cp_is_utf8') || !sapi_windows_cp_is_utf8()) { diff --git a/src/Psalm/Progress/VoidProgress.php b/src/Psalm/Progress/VoidProgress.php index 0758204900f..e339eb4ae40 100644 --- a/src/Psalm/Progress/VoidProgress.php +++ b/src/Psalm/Progress/VoidProgress.php @@ -8,6 +8,36 @@ final class VoidProgress extends Progress { + #[Override] + public function debug(string $message): void + { + } + + #[Override] + public function startPhase(Phase $phase): void + { + } + + #[Override] + public function alterFileDone(string $file_name): void + { + } + + #[Override] + public function expand(int $number_of_tasks): void + { + } + + #[Override] + public function taskDone(int $level): void + { + } + + #[Override] + public function finish(): void + { + } + #[Override] public function write(string $message): void { diff --git a/tests/AsyncTestCase.php b/tests/AsyncTestCase.php index fc50ee67f0e..7cb1948f754 100644 --- a/tests/AsyncTestCase.php +++ b/tests/AsyncTestCase.php @@ -129,7 +129,7 @@ public function analyzeFile(string $file_path, Context $context, bool $track_unu $file_analyzer->analyze($context); if ($codebase->taint_flow_graph) { - $codebase->taint_flow_graph->connectSinksAndSources(); + $codebase->taint_flow_graph->connectSinksAndSources($codebase->progress); } if ($track_unused_suppressions) { diff --git a/tests/TestCase.php b/tests/TestCase.php index e4638711c40..d69aa9a92d0 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -151,7 +151,7 @@ public function analyzeFile(string $file_path, Context $context, bool $track_unu $file_analyzer->analyze($context); if ($codebase->taint_flow_graph) { - $codebase->taint_flow_graph->connectSinksAndSources(); + $codebase->taint_flow_graph->connectSinksAndSources($codebase->progress); } if ($track_unused_suppressions) { From 9e6f458f4ca9ea384444465511c8aaf523df46d4 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 1 Mar 2025 14:36:38 +0100 Subject: [PATCH 3/6] Cleanup --- src/Psalm/Internal/Codebase/TaintFlowGraph.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Codebase/TaintFlowGraph.php b/src/Psalm/Internal/Codebase/TaintFlowGraph.php index 8fdefcb172d..1405581ac70 100644 --- a/src/Psalm/Internal/Codebase/TaintFlowGraph.php +++ b/src/Psalm/Internal/Codebase/TaintFlowGraph.php @@ -217,7 +217,7 @@ public function connectSinksAndSources(Progress $progress): void ksort($this->forward_edges); // reprocess resolved descendants up to a maximum nesting level of 40 - for ($i = 0; count($sinks) && count($sources) && $i < 10000; $i++) { + for ($i = 0; count($sinks) && count($sources) && $i < 40; $i++) { $new_sources = []; ksort($sources); From 38dd471dc5968a576b28efaf518c8b0257e67f1b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 1 Mar 2025 14:38:50 +0100 Subject: [PATCH 4/6] Add phase --- src/Psalm/Progress/Phase.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Psalm/Progress/Phase.php diff --git a/src/Psalm/Progress/Phase.php b/src/Psalm/Progress/Phase.php new file mode 100644 index 00000000000..b4fa2dce543 --- /dev/null +++ b/src/Psalm/Progress/Phase.php @@ -0,0 +1,13 @@ + Date: Mon, 3 Mar 2025 18:46:10 +0100 Subject: [PATCH 5/6] Finalize --- UPGRADING.md | 20 ++++++++++++++++++++ src/Psalm/Internal/Preloader.php | 9 ++++++--- src/Psalm/Progress/DebugProgress.php | 3 ++- src/Psalm/Progress/DefaultProgress.php | 4 +--- src/Psalm/Progress/LongProgress.php | 9 +++++---- src/Psalm/Progress/Phase.php | 5 +++++ 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index db8e1da6017..139777f1cbd 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,3 +1,23 @@ +# Upgrading from Psalm 6 to Psalm 7 + +## Changed + +- [BC] The `startScanningFiles`, `startAnalyzingFiles`, `startAlteringFiles` of `Psalm\Progress\Progress` and subclasses were removed and replaced with a new `startPhase` method, taking a `Psalm\Progress\Phase` enum case. + +- [BC] The `start` method was removed, use `expand`, instead; the progress is reset to 0 when changing the current phase. + +- [BC] Method `doesTerminalSupportUtf8` of class `Psalm\Progress\Progress` became final + +- [BC] Method debug() of class Psalm\Progress\Progress changed from concrete to abstract + +- [BC] Method alterFileDone() of class Psalm\Progress\Progress changed from concrete to abstract + +- [BC] Method expand() of class Psalm\Progress\Progress changed from concrete to abstract + +- [BC] Method taskDone() of class Psalm\Progress\Progress changed from concrete to abstract + +- [BC] Method finish() of class Psalm\Progress\Progress changed from concrete to abstract + # Upgrading from Psalm 5 to Psalm 6 ## Changed diff --git a/src/Psalm/Internal/Preloader.php b/src/Psalm/Internal/Preloader.php index 5e744625d59..35ab324812b 100644 --- a/src/Psalm/Internal/Preloader.php +++ b/src/Psalm/Internal/Preloader.php @@ -4,11 +4,12 @@ namespace Psalm\Internal; +use Psalm\Progress\Phase; use Psalm\Progress\Progress; use function class_exists; -use const PHP_EOL; +use function count; /** @internal */ final class Preloader @@ -21,13 +22,15 @@ public static function preload(?Progress $progress = null, bool $hasJit = false) } if ($hasJit) { - $progress?->write("JIT compilation in progress... "); + $progress?->startPhase(Phase::JIT_COMPILATION); + $progress?->expand(count(PreloaderList::CLASSES)+1); } foreach (PreloaderList::CLASSES as $class) { + $progress?->taskDone(0); class_exists($class); } if ($hasJit) { - $progress?->write("Done.".PHP_EOL.PHP_EOL); + $progress?->finish(); } self::$preloaded = true; } diff --git a/src/Psalm/Progress/DebugProgress.php b/src/Psalm/Progress/DebugProgress.php index 2c7c418560f..9c2d9587113 100644 --- a/src/Psalm/Progress/DebugProgress.php +++ b/src/Psalm/Progress/DebugProgress.php @@ -29,9 +29,10 @@ public function startPhase(Phase $phase): void { $this->write(match ($phase) { Phase::SCAN => "\nScanning files...\n\n", - Phase::ANALYSIS => "\nAnalysing files...\n", + Phase::ANALYSIS => "\nAnalyzing files...\n", Phase::ALTERING => "\nUpdating files...\n", Phase::TAINT_GRAPH_RESOLUTION => "\nResolving taint graph...\n", + Phase::JIT_COMPILATION => "\nJIT compilation in progress...\n", }); } diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php index fd2293dce18..46d28e266d2 100644 --- a/src/Psalm/Progress/DefaultProgress.php +++ b/src/Psalm/Progress/DefaultProgress.php @@ -106,9 +106,7 @@ public function finish(): void { if ($this->number_of_tasks > self::TOO_MANY_FILES) { $this->write(str_repeat(' ', self::NUMBER_OF_COLUMNS + strlen($this->getOverview()) + 1) . "\r"); - $this->reportPhaseDuration(null); - } else { - parent::finish(); } + parent::finish(); } } diff --git a/src/Psalm/Progress/LongProgress.php b/src/Psalm/Progress/LongProgress.php index 6e3f2e28665..40ad10bfc42 100644 --- a/src/Psalm/Progress/LongProgress.php +++ b/src/Psalm/Progress/LongProgress.php @@ -47,11 +47,12 @@ public function startPhase(Phase $phase): void $this->reportPhaseDuration($phase); $this->write(match ($phase) { Phase::SCAN => "\nScanning files...\n\n", - Phase::ANALYSIS => "\nAnalysing files...\n\n", + Phase::ANALYSIS => "\nAnalyzing files...\n\n", Phase::ALTERING => "\nUpdating files...\n", Phase::TAINT_GRAPH_RESOLUTION => "\n\nResolving taint graph...\n\n", + Phase::JIT_COMPILATION => "JIT compilation in progress...\n\n", }); - $this->fixed_size = $phase === Phase::ANALYSIS || $phase === Phase::ALTERING; + $this->fixed_size = $phase === Phase::ANALYSIS || $phase === Phase::ALTERING || $phase === Phase::JIT_COMPILATION; } protected function reportPhaseDuration(?Phase $newPhase = null): void @@ -65,9 +66,10 @@ protected function reportPhaseDuration(?Phase $newPhase = null): void $took = round(microtime(true) - $this->started, 1); $this->write(match ($this->prevPhase) { Phase::SCAN => "\n\nScan took $took seconds.\n", - Phase::ANALYSIS => "\nAnalysis took $took seconds.\n", + Phase::ANALYSIS => "\n\nAnalysis took $took seconds.\n", Phase::ALTERING => "\n\nUpdating files took $took seconds.\n", Phase::TAINT_GRAPH_RESOLUTION => "\n\nTaint graph resolution took $took seconds.\n", + Phase::JIT_COMPILATION => "JIT compilation took $took seconds.\n\n", }); } $this->started = microtime(true); @@ -130,7 +132,6 @@ public function taskDone(int $level): void public function finish(): void { $this->reportPhaseDuration(null); - $this->write(PHP_EOL); } protected function getOverview(): string diff --git a/src/Psalm/Progress/Phase.php b/src/Psalm/Progress/Phase.php index b4fa2dce543..701d0827048 100644 --- a/src/Psalm/Progress/Phase.php +++ b/src/Psalm/Progress/Phase.php @@ -4,10 +4,15 @@ namespace Psalm\Progress; +/** + * Note: this enum is not covered by the backwards compatibility promise, + * when implementing progress make sure to always include a fallback based on the name of the case. + */ enum Phase { case SCAN; case ANALYSIS; case ALTERING; case TAINT_GRAPH_RESOLUTION; + case JIT_COMPILATION; } From c899331308d948906bb9a12176b0bbf5e6f216fa Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 3 Mar 2025 18:48:49 +0100 Subject: [PATCH 6/6] Cleanup --- src/Psalm/Progress/LongProgress.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Progress/LongProgress.php b/src/Psalm/Progress/LongProgress.php index 40ad10bfc42..f55de1f01f2 100644 --- a/src/Psalm/Progress/LongProgress.php +++ b/src/Psalm/Progress/LongProgress.php @@ -52,7 +52,9 @@ public function startPhase(Phase $phase): void Phase::TAINT_GRAPH_RESOLUTION => "\n\nResolving taint graph...\n\n", Phase::JIT_COMPILATION => "JIT compilation in progress...\n\n", }); - $this->fixed_size = $phase === Phase::ANALYSIS || $phase === Phase::ALTERING || $phase === Phase::JIT_COMPILATION; + $this->fixed_size = $phase === Phase::ANALYSIS + || $phase === Phase::ALTERING + || $phase === Phase::JIT_COMPILATION; } protected function reportPhaseDuration(?Phase $newPhase = null): void