Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Final improvements for reduced scanning#11809

Merged
danog merged 1 commit into
masterfrom
improve_reduced_scanning
Apr 15, 2026
Merged

Final improvements for reduced scanning#11809
danog merged 1 commit into
masterfrom
improve_reduced_scanning

Conversation

@danog
Copy link
Copy Markdown
Collaborator

@danog danog commented Apr 15, 2026

Note

Medium Risk
Changes core file-inclusion logic for issue reporting and targeted scans; incorrect project_files population could cause issues to be skipped or reported unexpectedly for some checkPaths() invocations.

Overview
Tightens how Psalm decides whether it can report issues for a file by removing the fallback to Config::isInProjectDirs() when project files haven’t been initialized, making canReportIssues() rely solely on the computed project_files set.

To keep checkPaths() functional under this stricter behavior, it now lazily populates project_files from the explicitly provided files/directories (recursing directories via getFilesInDir) instead of initializing the full configured project file list, reducing scan scope for targeted runs.

Reviewed by Cursor Bugbot for commit 9b0fee0. Bugbot is set up for automated code reviews on this repo. Configure here.

@danog danog added the release:fix The PR will be included in 'Fixes' section of the release notes label Apr 15, 2026
Copilot AI review requested due to automatic review settings April 15, 2026 20:44
@danog danog merged commit 7e751c0 into master Apr 15, 2026
121 of 122 checks passed
@danog danog deleted the improve_reduced_scanning branch April 15, 2026 20:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to reduce scanning work during checkPaths() runs by avoiding a full project file initialization and instead populating the project file list from the explicitly provided paths.

Changes:

  • Removed the fallback behavior in ProjectAnalyzer::canReportIssues() when project files are not initialized.
  • Added logic in ProjectAnalyzer::checkPaths() to build $this->project_files from the provided paths (including directory recursion).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -371,9 +371,6 @@ public static function getInstance(): ProjectAnalyzer
/** @psalm-mutation-free */
public function canReportIssues(string $file_path): bool
{
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

canReportIssues() now unconditionally reads $this->project_files, but $project_files is a typed property that is intentionally not initialized in the constructor (Config::INIT_PROJECT_FILES_NOW is false). If canReportIssues() is called before initProjectFiles()/checkPaths() populates $project_files (e.g. in checkFile() flows or any external call site), this will trigger a fatal error (“Typed property ... must not be accessed before initialization”). Consider restoring a safe fallback (e.g. use Config::isInProjectDirs() when $project_files is not set), or initialize $project_files to an empty array by default and ensure the intended semantics for non-full runs remain correct.

Suggested change
{
{
if (!isset($this->project_files)) {
return $this->config->isInProjectDirs($file_path);
}

Copilot uses AI. Check for mistakes.
Comment on lines +989 to +999
foreach ($paths_to_check as $file_path) {
if (is_dir($file_path)) {
foreach ($this->file_provider->getFilesInDir(
$file_path,
$file_extensions,
) as $file_path) {
$this->project_files[$file_path] = $file_path;
}
} elseif (is_file($file_path)) {
$this->project_files[$file_path] = $file_path;
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In checkPaths(), when a passed path is a directory you traverse it once here to build $this->project_files, and then traverse it again later via checkDirWithConfig($path, ..., true) (which calls getFilesInDir() again). For large directories this double-walk can noticeably increase scan time and may offset the intended “reduced scanning” improvement. Consider reusing the file list already produced in checkDirWithConfig() (or refactoring so directory enumeration happens once and populates both the analyze list and $project_files).

Copilot uses AI. Check for mistakes.
if (!$this->project_files_initialized) {
return $this->config->isInProjectDirs($file_path);
}
$list = $this->project_files;
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes alter how checkFile()/non-full runs may decide whether issues are reportable (via ProjectAnalyzer::canReportIssues()), but there doesn’t appear to be any unit/integration test that exercises ProjectAnalyzer::checkFile() (tests currently cover checkPaths() only). Adding a regression test that runs checkFile() and asserts it neither crashes nor suppresses expected issues would help prevent future regressions around project file initialization/reportability.

Suggested change
$list = $this->project_files;
$list = $this->project_files;
if ($list === []) {
return true;
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 9b0fee0. Configure here.

$this->project_files[$file_path] = $file_path;
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing flag update leaves inconsistent initialization state

Medium Severity

The new inline initialization of $this->project_files in checkPaths() never sets $this->project_files_initialized = true. The initProjectFiles() method checks this flag as a guard and will overwrite the reduced file list with the full project directories if it's ever called afterward, silently defeating the reduced-scanning optimization.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9b0fee0. Configure here.

$file_extensions,
) as $file_path) {
$this->project_files[$file_path] = $file_path;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loop variable shadowing causes confusing reuse of identifier

Low Severity

The inner foreach at as $file_path reuses the same variable name as the outer foreach ($paths_to_check as $file_path), shadowing it. While PHP's foreach iteration is unaffected at runtime, this makes the code confusing and fragile — any future modification that accesses $file_path after the inner loop within the same outer iteration would silently use the wrong value.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9b0fee0. Configure here.

{
if (!$this->project_files_initialized) {
return $this->config->isInProjectDirs($file_path);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed fallback crashes uninitialized project_files code paths

High Severity

The canReportIssues() fallback for when project_files_initialized is false was removed, but $this->project_files is declared as a typed property with no default value. The checkDir() and checkFile() methods (used by Psalter) never call initProjectFiles() or the new inline initialization added to checkPaths(). When analysis triggers canReportIssues() through these paths, accessing the uninitialized $this->project_files will throw an Error.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9b0fee0. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:fix The PR will be included in 'Fixes' section of the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants