1717use PHPStan \Rules \Registry as RuleRegistry ;
1818use function array_keys ;
1919use function get_class ;
20+ use function spl_object_id ;
2021use function sprintf ;
2122
2223/**
@@ -45,6 +46,9 @@ final class FileAnalyserCallback
4546 /** @var list<Error> */
4647 private array $ temporaryFileErrors = [];
4748
49+ /** @var array<string, list<PendingFix>> */
50+ private array $ pendingFixesByFile = [];
51+
4852 /** @var LinesToIgnore */
4953 private array $ linesToIgnore ;
5054
@@ -77,8 +81,6 @@ public function __construct(
7781
7882 public function __invoke (Node $ node , Scope $ scope ): void
7983 {
80- $ parserNodes = $ this ->parserNodes ;
81-
8284 /** @var Scope&NodeCallbackInvoker $scope */
8385 if ($ node instanceof Node \Stmt \Trait_) {
8486 foreach (array_keys ($ this ->linesToIgnore [$ this ->file ] ?? []) as $ lineToIgnore ) {
@@ -101,14 +103,6 @@ public function __invoke(Node $node, Scope $scope): void
101103 }
102104 }
103105
104- if ($ scope ->isInTrait ()) {
105- $ traitReflection = $ scope ->getTraitReflection ();
106- if ($ traitReflection ->getFileName () !== null ) {
107- $ traitFilePath = $ traitReflection ->getFileName ();
108- $ parserNodes = $ this ->parser ->parseFile ($ traitFilePath );
109- }
110- }
111-
112106 if ($ this ->outerNodeCallback !== null ) {
113107 ($ this ->outerNodeCallback )($ node , $ scope );
114108 }
@@ -149,7 +143,7 @@ public function __invoke(Node $node, Scope $scope): void
149143 }
150144
151145 foreach ($ ruleErrors as $ ruleError ) {
152- $ error = $ this ->ruleErrorTransformer ->transform ($ ruleError , $ scope, $ parserNodes , $ node );
146+ [ $ error, $ pendingFix ] = $ this ->ruleErrorTransformer ->transformPreserveFixable ($ ruleError , $ scope , $ node );
153147
154148 if ($ error ->canBeIgnored ()) {
155149 foreach ($ this ->ignoreErrorExtensions as $ ignoreErrorExtension ) {
@@ -160,6 +154,11 @@ public function __invoke(Node $node, Scope $scope): void
160154 }
161155
162156 $ this ->temporaryFileErrors [] = $ error ;
157+ if ($ pendingFix === null ) {
158+ continue ;
159+ }
160+
161+ $ this ->pendingFixesByFile [$ pendingFix ->fixingFilePath ][] = $ pendingFix ;
163162 }
164163 }
165164
@@ -305,7 +304,34 @@ public function getUnmatchedLineIgnores(): array
305304 */
306305 public function getTemporaryFileErrors (): array
307306 {
308- return $ this ->temporaryFileErrors ;
307+ if ($ this ->pendingFixesByFile === []) {
308+ return $ this ->temporaryFileErrors ;
309+ }
310+
311+ $ parserNodesByFile = [$ this ->file => $ this ->parserNodes ];
312+ foreach (array_keys ($ this ->pendingFixesByFile ) as $ fixingFilePath ) {
313+ if (isset ($ parserNodesByFile [$ fixingFilePath ])) {
314+ continue ;
315+ }
316+ $ parserNodesByFile [$ fixingFilePath ] = $ this ->parser ->parseFile ($ fixingFilePath );
317+ }
318+
319+ $ diffsByErrorId = $ this ->ruleErrorTransformer ->finalizePendingFixes (
320+ $ this ->pendingFixesByFile ,
321+ $ parserNodesByFile ,
322+ );
323+
324+ if ($ diffsByErrorId === []) {
325+ return $ this ->temporaryFileErrors ;
326+ }
327+
328+ $ finalErrors = [];
329+ foreach ($ this ->temporaryFileErrors as $ error ) {
330+ $ diff = $ diffsByErrorId [spl_object_id ($ error )] ?? null ;
331+ $ finalErrors [] = $ diff !== null ? $ error ->withFixedErrorDiff ($ diff ) : $ error ;
332+ }
333+
334+ return $ finalErrors ;
309335 }
310336
311337 /**
0 commit comments