|
9 | 9 | use PhpParser\Node\Stmt; |
10 | 10 | use PHPStan\Analyser\ExpressionContext; |
11 | 11 | use PHPStan\Analyser\Generator\NodeHandler\AttrGroupsHandler; |
| 12 | +use PHPStan\Analyser\Generator\NodeHandler\StmtsHandler; |
12 | 13 | use PHPStan\Analyser\Scope; |
13 | 14 | use PHPStan\Analyser\StatementContext; |
14 | 15 | use PHPStan\DependencyInjection\Container; |
@@ -114,15 +115,15 @@ private function processStmtNodes( |
114 | 115 | GeneratorScope $scope, |
115 | 116 | callable $nodeCallback, |
116 | 117 | StatementContext $context, |
117 | | - ): StmtAnalysisResult |
| 118 | + ): void |
118 | 119 | { |
119 | | - $gen = new IdentifiedGeneratorInStack($this->analyseStmts($stmts, $scope, $context, null), $stmts, null, null); |
| 120 | + $gen = new IdentifiedGeneratorInStack($this->analyseInitialStmts($stmts, $scope, $context, null), $stmts, null, null); |
120 | 121 | $gen->generator->current(); |
121 | 122 |
|
122 | 123 | $stack = []; |
123 | 124 |
|
124 | 125 | try { |
125 | | - return $this->runTrampoline( |
| 126 | + $this->runTrampoline( |
126 | 127 | $fibersStorage, |
127 | 128 | $exprAnalysisResultStorage, |
128 | 129 | $gen, |
@@ -158,7 +159,7 @@ private function runTrampoline( |
158 | 159 | IdentifiedGeneratorInStack &$gen, |
159 | 160 | callable $nodeCallback, |
160 | 161 | array &$stack, |
161 | | - ): StmtAnalysisResult |
| 162 | + ): void |
162 | 163 | { |
163 | 164 | while (true) { |
164 | 165 | $pendingFibersGen = $this->processPendingFibers($fibersStorage, $exprAnalysisResultStorage); |
@@ -224,7 +225,7 @@ private function runTrampoline( |
224 | 225 | } elseif ($yielded instanceof StmtsAnalysisRequest) { |
225 | 226 | $stack[] = $gen; |
226 | 227 | $gen = new IdentifiedGeneratorInStack( |
227 | | - $this->analyseStmts($yielded->stmts, $yielded->scope, $yielded->context, $yielded->alternativeNodeCallback), |
| 228 | + $this->analyseStmts($yielded->parentNode, $yielded->stmts, $yielded->scope, $yielded->context, $yielded->alternativeNodeCallback), |
228 | 229 | $yielded->stmts, |
229 | 230 | $yielded->originFile, |
230 | 231 | $yielded->originLine, |
@@ -291,49 +292,43 @@ private function runTrampoline( |
291 | 292 | continue 2; |
292 | 293 | } |
293 | 294 |
|
294 | | - if (!$result instanceof StmtAnalysisResult) { |
295 | | - throw new ShouldNotHappenException('Top node should be Stmt'); |
| 295 | + if ($result !== null) { |
| 296 | + throw new ShouldNotHappenException(sprintf('Null result is expected from analyseInitialStmts, given %s', get_debug_type($result))); |
296 | 297 | } |
297 | | - return $result; |
| 298 | + return; |
298 | 299 | } |
299 | 300 |
|
300 | 301 | $gen = array_pop($stack); |
301 | 302 | $gen->generator->send($result); |
302 | 303 | } |
303 | 304 | } |
304 | 305 |
|
| 306 | + /** |
| 307 | + * @param array<Stmt> $stmts |
| 308 | + * @param (callable(Node, Scope, callable(Node, Scope): void): void)|null $alternativeNodeCallback |
| 309 | + * |
| 310 | + * @return Generator<int, GeneratorTValueType, GeneratorTSendType, void> |
| 311 | + */ |
| 312 | + private function analyseInitialStmts(array $stmts, GeneratorScope $scope, StatementContext $context, ?callable $alternativeNodeCallback): Generator |
| 313 | + { |
| 314 | + $handler = $this->container->getByType(StmtsHandler::class); |
| 315 | + $gen = $handler->analyseInitialStmts($stmts, $scope, $context, $alternativeNodeCallback); |
| 316 | + yield from $gen; |
| 317 | + } |
| 318 | + |
305 | 319 | /** |
306 | 320 | * @param array<Stmt> $stmts |
307 | 321 | * @param (callable(Node, Scope, callable(Node, Scope): void): void)|null $alternativeNodeCallback |
308 | 322 | * |
309 | 323 | * @return Generator<int, GeneratorTValueType, GeneratorTSendType, StmtAnalysisResult> |
310 | 324 | */ |
311 | | - private function analyseStmts(array $stmts, GeneratorScope $scope, StatementContext $context, ?callable $alternativeNodeCallback): Generator |
| 325 | + private function analyseStmts(Node $parentNode, array $stmts, GeneratorScope $scope, StatementContext $context, ?callable $alternativeNodeCallback): Generator |
312 | 326 | { |
313 | | - $exitPoints = []; |
314 | | - $throwPoints = []; |
315 | | - $impurePoints = []; |
316 | | - $alreadyTerminated = false; |
317 | | - $hasYield = false; |
318 | | - |
319 | | - foreach ($stmts as $stmt) { |
320 | | - $result = yield new StmtAnalysisRequest($stmt, $scope, $context, $alternativeNodeCallback); |
321 | | - $scope = $result->scope; |
322 | | - $hasYield = $hasYield || $result->hasYield; |
323 | | - $exitPoints = array_merge($exitPoints, $result->exitPoints); |
324 | | - $throwPoints = array_merge($throwPoints, $result->throwPoints); |
325 | | - $impurePoints = array_merge($impurePoints, $result->impurePoints); |
326 | | - $alreadyTerminated = $alreadyTerminated || $result->isAlwaysTerminating; |
327 | | - } |
| 327 | + $handler = $this->container->getByType(StmtsHandler::class); |
| 328 | + $gen = $handler->analyseStmts($parentNode, $stmts, $scope, $context, $alternativeNodeCallback); |
| 329 | + yield from $gen; |
328 | 330 |
|
329 | | - return new StmtAnalysisResult( |
330 | | - $scope, |
331 | | - hasYield: $hasYield, |
332 | | - isAlwaysTerminating: $alreadyTerminated, |
333 | | - exitPoints: $exitPoints, |
334 | | - throwPoints: $throwPoints, |
335 | | - impurePoints: $impurePoints, |
336 | | - ); |
| 331 | + return $gen->getReturn(); |
337 | 332 | } |
338 | 333 |
|
339 | 334 | /** |
|
0 commit comments