Skip to content

Commit d04b313

Browse files
committed
InternalGeneratorScopeFactory
1 parent ada15c5 commit d04b313

16 files changed

+96
-58
lines changed

src/Analyser/FileAnalyser.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpParser\Node;
66
use PHPStan\AnalysedCodeException;
77
use PHPStan\Analyser\Generator\GeneratorNodeScopeResolver;
8+
use PHPStan\Analyser\Generator\GeneratorScopeFactory;
89
use PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode;
910
use PHPStan\BetterReflection\Reflection\Exception\CircularReference;
1011
use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
@@ -56,6 +57,7 @@ final class FileAnalyser
5657

5758
public function __construct(
5859
private ScopeFactory $scopeFactory,
60+
private GeneratorScopeFactory $generatorScopeFactory,
5961
#[AutowiredParameter(ref: '@' . NodeScopeResolver::class)]
6062
private GeneratorNodeScopeResolver|NodeScopeResolver $nodeScopeResolver,
6163
#[AutowiredParameter(ref: '@defaultAnalysisParser')]
@@ -245,7 +247,11 @@ public function analyseFile(
245247
}
246248
};
247249

248-
$scope = $this->scopeFactory->create(ScopeContext::create($file), $nodeCallback);
250+
if ($this->nodeScopeResolver instanceof NodeScopeResolver) {
251+
$scope = $this->scopeFactory->create(ScopeContext::create($file), $nodeCallback);
252+
} else {
253+
$scope = $this->generatorScopeFactory->create(ScopeContext::create($file));
254+
}
249255
$nodeCallback(new FileNode($parserNodes), $scope);
250256
$this->nodeScopeResolver->processNodes(
251257
$parserNodes,

src/Analyser/Generator/ExprHandler/VariableHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function analyseExpr(Expr $expr, GeneratorScope $scope): Generator
3333

3434
$exprTypeFromScope = $scope->expressionTypes['$' . $expr->name] ?? null;
3535
if ($exprTypeFromScope !== null) {
36-
return new ExprAnalysisResult($exprTypeFromScope, $scope);
36+
return new ExprAnalysisResult($exprTypeFromScope->getType(), $scope);
3737
}
3838

3939
yield from [];

src/Analyser/Generator/GeneratorScope.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
namespace PHPStan\Analyser\Generator;
44

55
use Fiber;
6-
use NoDiscard;
76
use PhpParser\Node;
87
use PhpParser\Node\Expr;
98
use PhpParser\Node\Name;
109
use PhpParser\Node\Param;
10+
use PHPStan\Analyser\ExpressionTypeHolder;
1111
use PHPStan\Analyser\NodeCallbackInvoker;
1212
use PHPStan\Analyser\Scope;
13+
use PHPStan\Analyser\ScopeContext;
1314
use PHPStan\Php\PhpVersions;
1415
use PHPStan\Reflection\Assertions;
1516
use PHPStan\Reflection\ClassConstantReflection;
@@ -30,23 +31,27 @@ final class GeneratorScope implements Scope, NodeCallbackInvoker
3031
{
3132

3233
/**
33-
* @param array<string, Type> $expressionTypes
34+
* @param array<string, ExpressionTypeHolder> $expressionTypes
3435
*/
3536
public function __construct(
37+
private InternalGeneratorScopeFactory $scopeFactory,
38+
private ScopeContext $context,
3639
public array $expressionTypes,
3740
)
3841
{
3942
}
4043

41-
#[NoDiscard]
4244
public function assignVariable(string $variableName, Type $type): self
4345
{
4446
$exprString = '$' . $variableName;
4547

4648
$expressionTypes = $this->expressionTypes;
47-
$expressionTypes[$exprString] = $type;
49+
$expressionTypes[$exprString] = ExpressionTypeHolder::createYes(new Expr\Variable($variableName), $type);
4850

49-
return new self($expressionTypes);
51+
return $this->scopeFactory->create(
52+
$this->context,
53+
$expressionTypes,
54+
);
5055
}
5156

5257
public function enterNamespace(string $namespaceName): self
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator;
4+
5+
use PHPStan\Analyser\ScopeContext;
6+
use PHPStan\DependencyInjection\AutowiredService;
7+
8+
#[AutowiredService]
9+
final class GeneratorScopeFactory
10+
{
11+
12+
public function __construct(
13+
private InternalGeneratorScopeFactory $internalScopeFactory,
14+
)
15+
{
16+
}
17+
18+
public function create(ScopeContext $context): GeneratorScope
19+
{
20+
return $this->internalScopeFactory->create($context);
21+
}
22+
23+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator;
4+
5+
use PHPStan\Analyser\ExpressionTypeHolder;
6+
use PHPStan\Analyser\ScopeContext;
7+
8+
interface InternalGeneratorScopeFactory
9+
{
10+
11+
/**
12+
* @param array<string, ExpressionTypeHolder> $expressionTypes
13+
*/
14+
public function create(
15+
ScopeContext $context,
16+
array $expressionTypes = [],
17+
): GeneratorScope;
18+
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator;
4+
5+
use PHPStan\Analyser\ScopeContext;
6+
use PHPStan\DependencyInjection\AutowiredService;
7+
8+
#[AutowiredService(as: InternalGeneratorScopeFactory::class)]
9+
final class LazyInternalGeneratorScopeFactory implements InternalGeneratorScopeFactory
10+
{
11+
12+
public function create(ScopeContext $context, array $expressionTypes = []): GeneratorScope
13+
{
14+
return new GeneratorScope(
15+
$this,
16+
$context,
17+
$expressionTypes,
18+
);
19+
}
20+
21+
}

src/Analyser/NodeScopeResolver.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7019,9 +7019,6 @@ private function processNodesForCalledMethod($node, string $fileName, MethodRefl
70197019
}
70207020

70217021
$scope = $this->scopeFactory->create(ScopeContext::create($fileName))->enterClass($declaringClass);
7022-
if (!$scope instanceof MutatingScope) {
7023-
throw new ShouldNotHappenException();
7024-
}
70257022
$this->processStmtNode($stmt, $scope, $nodeCallback, StatementContext::createTopLevel());
70267023
}
70277024
return;

src/Analyser/ScopeFactory.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace PHPStan\Analyser;
44

55
use PhpParser\Node;
6-
use PHPStan\Analyser\Generator\GeneratorScope;
76
use PHPStan\DependencyInjection\AutowiredService;
87

98
/**
@@ -15,28 +14,15 @@ final class ScopeFactory
1514

1615
public function __construct(
1716
private InternalScopeFactoryFactory $internalScopeFactoryFactory,
18-
private bool $createGeneratorScope = false,
1917
)
2018
{
2119
}
2220

23-
/**
24-
* @internal
25-
*/
26-
public function getInternalScopeFactoryFactory(): InternalScopeFactoryFactory
27-
{
28-
return $this->internalScopeFactoryFactory;
29-
}
30-
3121
/**
3222
* @param callable(Node $node, Scope $scope): void $nodeCallback
3323
*/
34-
public function create(ScopeContext $context, ?callable $nodeCallback = null): MutatingScope|GeneratorScope
24+
public function create(ScopeContext $context, ?callable $nodeCallback = null): MutatingScope
3525
{
36-
if ($this->createGeneratorScope) {
37-
return new GeneratorScope([]);
38-
}
39-
4026
return $this->internalScopeFactoryFactory->create($nodeCallback)->create($context);
4127
}
4228

src/Testing/RuleTestCase.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPStan\Analyser\Error;
99
use PHPStan\Analyser\FileAnalyser;
1010
use PHPStan\Analyser\Generator\GeneratorNodeScopeResolver;
11+
use PHPStan\Analyser\Generator\GeneratorScopeFactory;
1112
use PHPStan\Analyser\IgnoreErrorExtensionProvider;
1213
use PHPStan\Analyser\InternalError;
1314
use PHPStan\Analyser\LocalIgnoresProcessor;
@@ -106,7 +107,7 @@ protected function createNodeScopeResolver(): NodeScopeResolver|GeneratorNodeSco
106107
$readWritePropertiesExtensions !== [] ? new DirectReadWritePropertiesExtensionProvider($readWritePropertiesExtensions) : self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class),
107108
self::getContainer()->getByType(ParameterClosureThisExtensionProvider::class),
108109
self::getContainer()->getByType(ParameterClosureTypeExtensionProvider::class),
109-
static::createScopeFactory(),
110+
self::createScopeFactory(),
110111
$this->shouldPolluteScopeWithLoopInitialAssignments(),
111112
$this->shouldPolluteScopeWithAlwaysIterableForeach(),
112113
self::getContainer()->getParameter('polluteScopeWithBlock'),
@@ -127,7 +128,8 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser
127128
$nodeScopeResolver = $this->createNodeScopeResolver();
128129

129130
$fileAnalyser = new FileAnalyser(
130-
static::createScopeFactory(),
131+
self::createScopeFactory(),
132+
self::getContainer()->getByType(GeneratorScopeFactory::class),
131133
$nodeScopeResolver,
132134
$this->getParser(),
133135
self::getContainer()->getByType(DependencyResolver::class),
@@ -274,7 +276,7 @@ private function gatherAnalyserErrorsWithDelayedErrors(array $files): array
274276
$ruleRegistry,
275277
new IgnoreErrorExtensionProvider(self::getContainer()),
276278
self::getContainer()->getByType(RuleErrorTransformer::class),
277-
static::createScopeFactory(),
279+
self::createScopeFactory(),
278280
new LocalIgnoresProcessor(),
279281
true,
280282
);

src/Testing/TypeInferenceTestCase.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use PhpParser\Node\Expr\StaticCall;
77
use PhpParser\Node\Name;
88
use PHPStan\Analyser\Generator\GeneratorNodeScopeResolver;
9-
use PHPStan\Analyser\Generator\GeneratorScope;
9+
use PHPStan\Analyser\Generator\GeneratorScopeFactory;
1010
use PHPStan\Analyser\MutatingScope;
1111
use PHPStan\Analyser\NodeScopeResolver;
1212
use PHPStan\Analyser\Scope;
@@ -100,7 +100,7 @@ protected static function createNodeScopeResolver(): NodeScopeResolver|Generator
100100
protected static function createScope(
101101
string $file,
102102
array $dynamicConstantNames = [],
103-
): MutatingScope|GeneratorScope
103+
): MutatingScope
104104
{
105105
$scopeFactory = self::createScopeFactory($dynamicConstantNames);
106106
return $scopeFactory->create(ScopeContext::create($file));
@@ -122,7 +122,7 @@ public static function processFile(
122122

123123
$resolver->processNodes(
124124
self::getParser()->parseFile($file),
125-
static::createScope($file, $dynamicConstantNames),
125+
$resolver instanceof NodeScopeResolver ? self::createScope($file, $dynamicConstantNames) : self::getContainer()->getByType(GeneratorScopeFactory::class)->create(ScopeContext::create($file)),
126126
$callback,
127127
);
128128
}

0 commit comments

Comments
 (0)