diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index 0ce72174205..bc31ac99c01 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -181,6 +181,9 @@ final class Codebase public bool $diff_methods = false; + /** whether or not we only checked a part of the codebase */ + public bool $diff_run = false; + /** * @var array */ diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index 3187bd05e29..8b02ae9a255 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -502,6 +502,7 @@ public function check(string $base_dir, bool $is_diff = false): void $this->codebase->infer_types_from_usage = true; } else { + $this->codebase->diff_run = true; $this->progress->debug(count($diff_files) . ' changed files: ' . "\n"); $this->progress->debug(' ' . implode("\n ", $diff_files) . "\n"); diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index dd35480c48f..2e6690b9252 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -80,6 +80,7 @@ use function usort; use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const PHP_EOL; use const PSALM_VERSION; use const STDERR; @@ -650,39 +651,42 @@ public static function finish( } if ($codebase->config->find_unused_issue_handler_suppression) { - foreach ($codebase->config->getIssueHandlers() as $type => $handler) { - foreach ($handler->getFilters() as $filter) { - if ($filter->suppressions > 0 && $filter->getErrorLevel() == Config::REPORT_SUPPRESS) { - continue; - } - $issues_data['config'][] = new IssueData( - IssueData::SEVERITY_ERROR, - 0, - 0, - UnusedIssueHandlerSuppression::getIssueType(), - sprintf( - 'Suppressed issue type "%s" for %s was not thrown.', - $type, - str_replace( - $codebase->config->base_dir, - '', - implode(', ', [...$filter->getFiles(), ...$filter->getDirectories()]), + if ($is_full && !$codebase->diff_run) { + foreach ($codebase->config->getIssueHandlers() as $type => $handler) { + foreach ($handler->getFilters() as $filter) { + if ($filter->suppressions > 0 && $filter->getErrorLevel() == Config::REPORT_SUPPRESS) { + continue; + } + $issues_data['config'][] = new IssueData( + IssueData::SEVERITY_ERROR, + 0, + 0, + UnusedIssueHandlerSuppression::getIssueType(), + sprintf( + 'Suppressed issue type "%s" for %s was not thrown.', + $type, + str_replace( + $codebase->config->base_dir, + '', + implode(', ', [...$filter->getFiles(), ...$filter->getDirectories()]), + ), ), - ), - $codebase->config->source_filename ?? '', - '', - '', - '', - 0, - 0, - 0, - 0, - 0, - 0, - UnusedIssueHandlerSuppression::SHORTCODE, - UnusedIssueHandlerSuppression::ERROR_LEVEL, - ); + $codebase->config->source_filename ?? '', + '', + '', + '', + 0, + 0, + 0, + 0, + 0, + 0, + UnusedIssueHandlerSuppression::SHORTCODE, + UnusedIssueHandlerSuppression::ERROR_LEVEL, + ); + } } + } else { } } @@ -827,6 +831,15 @@ public static function finish( echo "\n"; } } + + if ($codebase->config->find_unused_issue_handler_suppression && (!$is_full || $codebase->diff_run)) { + fwrite( + STDERR, + PHP_EOL . 'To whom it may concern: Psalm cannot detect unused issue handler suppressions when' + . PHP_EOL . 'analyzing individual files and folders or running in diff mode. Run on the full' + . PHP_EOL . 'project with diff mode off to enable unused issue handler detection.' . PHP_EOL, + ); + } } if ($is_full && $start_time) {