|
13 | 13 | use PHPStan\DependencyInjection\AutowiredParameter; |
14 | 14 | use PHPStan\DependencyInjection\AutowiredService; |
15 | 15 | use PHPStan\Node\FileNode; |
16 | | -use PHPStan\Node\InClassNode; |
17 | | -use PHPStan\Node\InTraitNode; |
18 | 16 | use PHPStan\Parser\Parser; |
19 | 17 | use PHPStan\Parser\ParserErrorsException; |
20 | 18 | use PHPStan\Rules\Registry as RuleRegistry; |
21 | | -use function array_keys; |
22 | 19 | use function array_unique; |
23 | 20 | use function array_values; |
24 | 21 | use function count; |
25 | 22 | use function error_reporting; |
26 | | -use function get_class; |
27 | 23 | use function hash; |
28 | 24 | use function is_dir; |
29 | 25 | use function is_file; |
@@ -102,168 +98,36 @@ public function analyseFile( |
102 | 98 | $this->collectErrors($analysedFiles); |
103 | 99 | $parserNodes = $this->parser->parseFile($file); |
104 | 100 | $processedFiles[] = $file; |
105 | | - $linesToIgnore = $unmatchedLineIgnores = [$file => $this->getLinesToIgnoreFromTokens($parserNodes)]; |
106 | | - $ignoreErrorExtensions = $this->ignoreErrorExtensionProvider->getExtensions(); |
107 | | - $temporaryFileErrors = []; |
108 | | - $nodeCallback = function (Node $node, $scope) use (&$fileErrors, &$fileCollectedData, &$fileDependencies, &$usedTraitFileDependencies, &$exportedNodes, $file, $ruleRegistry, $collectorRegistry, $outerNodeCallback, $analysedFiles, &$linesToIgnore, &$unmatchedLineIgnores, &$temporaryFileErrors, &$processedFiles, $parserNodes, $ignoreErrorExtensions): void { |
109 | | - /** @var Scope&NodeCallbackInvoker $scope */ |
110 | | - if ($node instanceof Node\Stmt\Trait_) { |
111 | | - foreach (array_keys($linesToIgnore[$file] ?? []) as $lineToIgnore) { |
112 | | - if ($lineToIgnore < $node->getStartLine() || $lineToIgnore > $node->getEndLine()) { |
113 | | - continue; |
114 | | - } |
115 | | - |
116 | | - unset($unmatchedLineIgnores[$file][$lineToIgnore]); |
117 | | - } |
118 | | - } |
119 | | - if ($node instanceof InTraitNode) { |
120 | | - $traitNode = $node->getOriginalNode(); |
121 | | - $fileDescription = $scope->getFileDescription(); |
122 | | - $linesToIgnore[$fileDescription] ??= []; |
123 | | - $linesToIgnore[$fileDescription] += $this->getLinesToIgnoreFromTokens([$traitNode]); |
124 | | - |
125 | | - $traitFileName = $node->getTraitReflection()->getFileName(); |
126 | | - if ($traitFileName !== null) { |
127 | | - $processedFiles[] = $traitFileName; |
128 | | - } |
129 | | - } |
130 | | - |
131 | | - if ($scope->isInTrait()) { |
132 | | - $traitReflection = $scope->getTraitReflection(); |
133 | | - if ($traitReflection->getFileName() !== null) { |
134 | | - $traitFilePath = $traitReflection->getFileName(); |
135 | | - $parserNodes = $this->parser->parseFile($traitFilePath); |
136 | | - } |
137 | | - } |
138 | | - |
139 | | - if ($outerNodeCallback !== null) { |
140 | | - $outerNodeCallback($node, $scope); |
141 | | - } |
142 | | - $uniquedAnalysedCodeExceptionMessages = []; |
143 | | - $nodeType = get_class($node); |
144 | | - foreach ($ruleRegistry->getRules($nodeType) as $rule) { |
145 | | - try { |
146 | | - $ruleErrors = $rule->processNode($node, $scope); |
147 | | - } catch (AnalysedCodeException $e) { |
148 | | - if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { |
149 | | - continue; |
150 | | - } |
151 | | - |
152 | | - $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = true; |
153 | | - $fileErrors[] = (new Error($e->getMessage(), $file, $node->getStartLine(), $e, tip: $e->getTip())) |
154 | | - ->withIdentifier('phpstan.internal') |
155 | | - ->withMetadata([ |
156 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
157 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
158 | | - ]); |
159 | | - continue; |
160 | | - } catch (IdentifierNotFound $e) { |
161 | | - $fileErrors[] = (new Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, $node->getStartLine(), $e, tip: 'Learn more at https://phpstan.org/user-guide/discovering-symbols')) |
162 | | - ->withIdentifier('phpstan.reflection') |
163 | | - ->withMetadata([ |
164 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
165 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
166 | | - ]); |
167 | | - continue; |
168 | | - } catch (UnableToCompileNode | CircularReference $e) { |
169 | | - $fileErrors[] = (new Error(sprintf('Reflection error: %s', $e->getMessage()), $file, $node->getStartLine(), $e)) |
170 | | - ->withIdentifier('phpstan.reflection') |
171 | | - ->withMetadata([ |
172 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
173 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
174 | | - ]); |
175 | | - continue; |
176 | | - } |
177 | | - |
178 | | - foreach ($ruleErrors as $ruleError) { |
179 | | - $error = $this->ruleErrorTransformer->transform($ruleError, $scope, $parserNodes, $node); |
180 | | - |
181 | | - if ($error->canBeIgnored()) { |
182 | | - foreach ($ignoreErrorExtensions as $ignoreErrorExtension) { |
183 | | - if ($ignoreErrorExtension->shouldIgnore($error, $node, $scope)) { |
184 | | - continue 2; |
185 | | - } |
186 | | - } |
187 | | - } |
188 | | - |
189 | | - $temporaryFileErrors[] = $error; |
190 | | - } |
191 | | - } |
192 | | - |
193 | | - foreach ($collectorRegistry->getCollectors($nodeType) as $collector) { |
194 | | - try { |
195 | | - $collectedData = $collector->processNode($node, $scope); |
196 | | - } catch (AnalysedCodeException $e) { |
197 | | - if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { |
198 | | - continue; |
199 | | - } |
200 | | - |
201 | | - $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = true; |
202 | | - $fileErrors[] = (new Error($e->getMessage(), $file, $node->getStartLine(), $e, tip: $e->getTip())) |
203 | | - ->withIdentifier('phpstan.internal') |
204 | | - ->withMetadata([ |
205 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
206 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
207 | | - ]); |
208 | | - continue; |
209 | | - } catch (IdentifierNotFound $e) { |
210 | | - $fileErrors[] = (new Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, $node->getStartLine(), $e, tip: 'Learn more at https://phpstan.org/user-guide/discovering-symbols')) |
211 | | - ->withIdentifier('phpstan.reflection') |
212 | | - ->withMetadata([ |
213 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
214 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
215 | | - ]); |
216 | | - continue; |
217 | | - } catch (UnableToCompileNode | CircularReference $e) { |
218 | | - $fileErrors[] = (new Error(sprintf('Reflection error: %s', $e->getMessage()), $file, $node->getStartLine(), $e)) |
219 | | - ->withIdentifier('phpstan.reflection') |
220 | | - ->withMetadata([ |
221 | | - InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), |
222 | | - InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString(), |
223 | | - ]); |
224 | | - continue; |
225 | | - } |
226 | | - |
227 | | - if ($collectedData === null) { |
228 | | - continue; |
229 | | - } |
230 | | - |
231 | | - $fileCollectedData[$scope->getFile()][get_class($collector)][] = $collectedData; |
232 | | - } |
233 | | - |
234 | | - try { |
235 | | - $dependencies = $this->dependencyResolver->resolveDependencies($node, $scope); |
236 | | - foreach ($dependencies->getFileDependencies($scope->getFile(), $analysedFiles) as $dependentFile) { |
237 | | - $fileDependencies[] = $dependentFile; |
238 | | - } |
239 | | - if ($dependencies->getExportedNode() !== null) { |
240 | | - $exportedNodes[] = $dependencies->getExportedNode(); |
241 | | - } |
242 | | - } catch (AnalysedCodeException) { |
243 | | - // pass |
244 | | - } catch (IdentifierNotFound) { |
245 | | - // pass |
246 | | - } catch (UnableToCompileNode) { |
247 | | - // pass |
248 | | - } |
249 | | - |
250 | | - if (!$node instanceof InClassNode) { |
251 | | - return; |
252 | | - } |
253 | | - |
254 | | - $usedTraitDependencies = $this->dependencyResolver->resolveUsedTraitDependencies($node); |
255 | | - foreach ($usedTraitDependencies->getFileDependencies($scope->getFile(), $analysedFiles) as $dependentFile) { |
256 | | - $usedTraitFileDependencies[] = $dependentFile; |
257 | | - } |
258 | | - }; |
259 | 101 |
|
| 102 | + $nodeCallback = new FileAnalyserCallback( |
| 103 | + $file, |
| 104 | + $analysedFiles, |
| 105 | + $ruleRegistry, |
| 106 | + $collectorRegistry, |
| 107 | + $outerNodeCallback, |
| 108 | + $parserNodes, |
| 109 | + $this->ignoreErrorExtensionProvider->getExtensions(), |
| 110 | + $this->parser, |
| 111 | + $this->dependencyResolver, |
| 112 | + $this->ruleErrorTransformer, |
| 113 | + $processedFiles, |
| 114 | + ); |
260 | 115 | $scope = $this->scopeFactory->create(ScopeContext::create($file), $nodeCallback); |
261 | 116 | $nodeCallback(new FileNode($parserNodes), $scope); |
262 | 117 | $this->nodeScopeResolver->processNodes( |
263 | 118 | $parserNodes, |
264 | 119 | $scope, |
265 | 120 | $nodeCallback, |
266 | 121 | ); |
| 122 | + $fileErrors = $nodeCallback->getFileErrors(); |
| 123 | + $fileCollectedData = $nodeCallback->getFileCollectedData(); |
| 124 | + $fileDependencies = $nodeCallback->getFileDependencies(); |
| 125 | + $usedTraitFileDependencies = $nodeCallback->getUsedTraitFileDependencies(); |
| 126 | + $exportedNodes = $nodeCallback->getExportedNodes(); |
| 127 | + $linesToIgnore = $nodeCallback->getLinesToIgnore(); |
| 128 | + $unmatchedLineIgnores = $nodeCallback->getUnmatchedLineIgnores(); |
| 129 | + $temporaryFileErrors = $nodeCallback->getTemporaryFileErrors(); |
| 130 | + $processedFiles = $nodeCallback->getProcessedFiles(); |
267 | 131 |
|
268 | 132 | $localIgnoresProcessorResult = $this->localIgnoresProcessor->process( |
269 | 133 | $temporaryFileErrors, |
@@ -345,20 +209,6 @@ public function analyseFile( |
345 | 209 | ); |
346 | 210 | } |
347 | 211 |
|
348 | | - /** |
349 | | - * @param Node[] $nodes |
350 | | - * @return array<int, non-empty-list<string>|null> |
351 | | - */ |
352 | | - private function getLinesToIgnoreFromTokens(array $nodes): array |
353 | | - { |
354 | | - if (!isset($nodes[0])) { |
355 | | - return []; |
356 | | - } |
357 | | - |
358 | | - /** @var array<int, non-empty-list<string>|null> */ |
359 | | - return $nodes[0]->getAttribute('linesToIgnore', []); |
360 | | - } |
361 | | - |
362 | 212 | /** |
363 | 213 | * @param array<string, true> $analysedFiles |
364 | 214 | */ |
|
0 commit comments