Fix file path of trait errors reported directly in the trait#5780
Fix file path of trait errors reported directly in the trait#5780janedbal wants to merge 5 commits into
Conversation
When an error inside a trait is reported once directly in the trait (Error::removeTraitContext()), the displayed file is moved to the trait file but filePath was left pointing at the using-class file. This broke inline @PHPStan-Ignore matching (looked up by filePath) and the editorUrl (getTraitFilePath() ?? getFilePath()), both resolving to the wrong file. Make filePath follow the file onto the trait, matching changeFilePath(). Fixes phpstan/phpstan#14718 Co-Authored-By: Claude Code
|
Would be nice to have the repro repo here in e2e/ and e2e-tests, showing all the behaviour described in the issue - non-working ignore comment, impossible baseline generation, problem disappearing with primed result cache etc. |
Covers the behaviours from the issue against the fix: - inline @PHPStan-Ignore on a trait-deduplicated error suppresses it, consistently with an empty and a primed result cache - with the ignore removed, the error is reported in the trait file and a generated baseline records the trait file path, not the using-class file Co-Authored-By: Claude Code
|
Added
For comparison, reverting the one-line fix flips all of these: the ignore is skipped, the editor URL / baseline path point at the using-class file ( One honest caveat: I could not reproduce the "error disappears on the second (primed-cache) run" facet in this minimal two-file fixture — it's deterministic across cache states here, so I didn't encode an assertion for it. That facet looks like it depends on the Standalone repro repo (same case): https://github.com/janedbal/phpstan-bug-14718-repro Note: (Claude anwering) |
|
Superb, please fix the build and mark it as ready. |
The phrase tripped PHPStan's own ignore.parseError rule during self-analysis. Reword the comment. Co-Authored-By: Claude Code
The identical.alwaysFalse error in MbFunctionsReturnTypeExtensionTrait (used by StrSplitFunctionReturnTypeExtension) is now attributed to the trait file instead of the using class, so move its baseline entry. Co-Authored-By: Claude Code
|
This pull request has been marked as ready for review. |
| identifier: identical.alwaysFalse | ||
| count: 1 | ||
| path: ../src/Type/Php/StrSplitFunctionReturnTypeExtension.php | ||
| path: ../src/Type/Php/MbFunctionsReturnTypeExtensionTrait.php |
There was a problem hiding this comment.
Isn't this a BC break? The ignore work correctly before. It's a bit awkward, but for errors reported in traits, I think on current stable version, both the trait or the class path can be used in path in ignoreErrors.
There was a problem hiding this comment.
This is achieved here:
phpstan-src/src/Analyser/Ignore/IgnoredErrorHelperResult.php
Lines 158 to 187 in 04d314d
I suspect, wouldn't be a better place to fix this in FileAnalyser where @phpstan-ignore are processed?
The previous approach overwrote filePath with the trait path in removeTraitContext(), which broke ignoreErrors/baseline entries keyed on the using-class path - a BC break (both paths used to match). Instead, removeTraitContext() now keeps traitFilePath set, leaving filePath as the using-class file. As a result: - the editor URL resolves to the trait via getTraitFilePath() - IgnoredErrorHelperResult keeps matching BOTH the using-class path and the trait path, so no existing ignore/baseline breaks The inline @PHPStan-Ignore lookup for these collector errors is fixed at its actual processing site (AnalyserResultFinalizer, where collector errors are finalized) by selecting the ignore bucket with getTraitFilePath() ?? getFilePath(). Reverts the self-analysis baseline relocation, and reworks the e2e to assert both ignore paths and a clean baseline round-trip. Co-Authored-By: Claude Code
|
You're right that the previous commit was a BC break — overwriting New approach, pushed:
On your FileAnalyser suggestion: for these specific errors the inline The e2e now asserts both the trait-path and using-class-path Note: (Claude answering) |
Fixes phpstan/phpstan#14718.
Problem
Since 2.2.0, an error originating inside a
traitthat is collapsed into a single error and reported once directly in the trait (via the newConstantConditionInTraitRule→Error::removeTraitContext()path) ends up with an inconsistent file pair:getFile()→ the trait file (correct)getFilePath()→ the using class's file (stale)getTraitFilePath()→nullremoveTraitContext()movedfileonto the trait file but leftfilePathpointing at the using-class file. Two things break as a result:@phpstan-ignoreno longer suppresses the error (the regression reported in #14718).AnalyserResultFinalizerlooks up line-ignores bygetFilePath(), which points at the using-class file, so the ignore registered for the trait never matches.editorUrllink points at the wrong file.TableErrorFormatterbuilds it fromgetTraitFilePath() ?? getFilePath()→null ?? <using-class file>, i.e. the using-class file glued to the trait's line number.Both worked correctly in 2.1.x.
Fix
Make
filePathfollowfileonto the trait file inremoveTraitContext(), the same waychangeFilePath()keepsfileandfilePathin sync. One line.Verification
Minimal reproduction: https://github.com/janedbal/phpstan-bug-14718-repro
Before (2.2.0): error reported despite the inline ignore, editor link → using-class file.
After:
getFile() === getFilePath() === <trait file>,getTraitFilePath() === null.Added a unit test in
ErrorTestcoveringremoveTraitContext().Co-Authored-By: Claude Code