Skip to content

Commit b0cdf91

Browse files
committed
GNSR continued
1 parent f0b62b6 commit b0cdf91

17 files changed

+321
-87
lines changed

build/PHPStan/Build/IgnoreGeneratorNodeScopeResolverUsageProvider.php

Lines changed: 0 additions & 24 deletions
This file was deleted.

build/phpstan.neon

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,3 @@ services:
147147
class: PHPStan\Build\ContainerDynamicReturnTypeExtension
148148
tags:
149149
- phpstan.broker.dynamicMethodReturnTypeExtension
150-
-
151-
class: PHPStan\Build\IgnoreGeneratorNodeScopeResolverUsageProvider
152-
tags:
153-
- shipmonk.deadCode.memberUsageProvider

src/Analyser/Analyser.php

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

55
use Closure;
6+
use PHPStan\Analyser\Generator\GeneratorNodeScopeResolver;
67
use PHPStan\Collectors\CollectedData;
78
use PHPStan\Collectors\Registry as CollectorRegistry;
89
use PHPStan\DependencyInjection\AutowiredParameter;
@@ -25,7 +26,8 @@ public function __construct(
2526
private FileAnalyser $fileAnalyser,
2627
private RuleRegistry $ruleRegistry,
2728
private CollectorRegistry $collectorRegistry,
28-
private NodeScopeResolver $nodeScopeResolver,
29+
#[AutowiredParameter(ref: '@' . NodeScopeResolver::class)]
30+
private GeneratorNodeScopeResolver|NodeScopeResolver $nodeScopeResolver,
2931
#[AutowiredParameter]
3032
private int $internalErrorsCountLimit,
3133
)

src/Analyser/FileAnalyser.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpParser\Node;
66
use PHPStan\AnalysedCodeException;
7+
use PHPStan\Analyser\Generator\GeneratorNodeScopeResolver;
78
use PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode;
89
use PHPStan\BetterReflection\Reflection\Exception\CircularReference;
910
use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
@@ -55,7 +56,8 @@ final class FileAnalyser
5556

5657
public function __construct(
5758
private ScopeFactory $scopeFactory,
58-
private NodeScopeResolver $nodeScopeResolver,
59+
#[AutowiredParameter(ref: '@' . NodeScopeResolver::class)]
60+
private GeneratorNodeScopeResolver|NodeScopeResolver $nodeScopeResolver,
5961
#[AutowiredParameter(ref: '@defaultAnalysisParser')]
6062
private Parser $parser,
6163
private DependencyResolver $dependencyResolver,

src/Analyser/Generator/GeneratorNodeScopeResolver.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,25 @@ public function processNodes(
8787
): void
8888
{
8989
$storage = new NodeScopeResolverRunStorage();
90+
$this->processStmtNodes(
91+
$storage,
92+
$stmts,
93+
$scope,
94+
$nodeCallback,
95+
);
96+
}
9097

98+
/**
99+
* @param array<Node\Stmt> $stmts
100+
* @param callable(Node, Scope): void $nodeCallback
101+
*/
102+
private function processStmtNodes(
103+
NodeScopeResolverRunStorage $storage,
104+
array $stmts,
105+
GeneratorScope $scope,
106+
callable $nodeCallback,
107+
): StmtAnalysisResult
108+
{
91109
$stack = [];
92110

93111
$gen = $this->analyzeStmts($stmts, $scope);
@@ -126,10 +144,29 @@ public function processNodes(
126144
}
127145

128146
$result = $gen->getReturn();
129-
130147
if (count($stack) === 0) {
148+
foreach ($storage->pendingFibers as $pending) {
149+
$request = $pending['request'];
150+
$exprAnalysisResult = $this->lookupExprAnalysisResult($storage, $request->expr);
151+
152+
if ($exprAnalysisResult !== null) {
153+
throw new ShouldNotHappenException('Pending fibers with an empty stack should be about synthetic nodes');
154+
}
155+
156+
$this->processStmtNodes(
157+
$storage,
158+
[new Stmt\Expression($request->expr)],
159+
$request->scope,
160+
static function () {
161+
},
162+
);
163+
}
164+
131165
if (count($storage->pendingFibers) === 0) {
132-
return;
166+
if (!$result instanceof StmtAnalysisResult) {
167+
throw new ShouldNotHappenException('Top node should be Stmt');
168+
}
169+
return $result;
133170
}
134171

135172
throw new ShouldNotHappenException(sprintf('Cannot finish analysis, pending fibers about: %s', implode(', ', array_map(static fn (array $fiber) => get_class($fiber['request']->expr), $storage->pendingFibers))));

src/Analyser/Generator/GeneratorScope.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPStan\Analyser\NodeCallbackInvoker;
1212
use PHPStan\Analyser\Scope;
1313
use PHPStan\Php\PhpVersions;
14+
use PHPStan\Reflection\Assertions;
1415
use PHPStan\Reflection\ClassConstantReflection;
1516
use PHPStan\Reflection\ClassReflection;
1617
use PHPStan\Reflection\ExtendedMethodReflection;
@@ -21,6 +22,7 @@
2122
use PHPStan\ShouldNotHappenException;
2223
use PHPStan\TrinaryLogic;
2324
use PHPStan\Type\ClosureType;
25+
use PHPStan\Type\Generic\TemplateTypeMap;
2426
use PHPStan\Type\Type;
2527
use PHPStan\Type\TypeWithClassName;
2628

@@ -47,6 +49,55 @@ public function assignVariable(string $variableName, Type $type): self
4749
return new self($expressionTypes);
4850
}
4951

52+
public function enterNamespace(string $namespaceName): self
53+
{
54+
// TODO: Implement enterNamespace() method.
55+
throw new ShouldNotHappenException('Not implemented yet');
56+
}
57+
58+
public function enterClass(ClassReflection $classReflection): self
59+
{
60+
// TODO: Implement enterClass() method.
61+
throw new ShouldNotHappenException('Not implemented yet');
62+
}
63+
64+
/**
65+
* @param Type[] $phpDocParameterTypes
66+
* @param Type[] $parameterOutTypes
67+
* @param array<string, bool> $immediatelyInvokedCallableParameters
68+
* @param array<string, Type> $phpDocClosureThisTypeParameters
69+
*/
70+
public function enterClassMethod(
71+
Node\Stmt\ClassMethod $classMethod,
72+
TemplateTypeMap $templateTypeMap,
73+
array $phpDocParameterTypes,
74+
?Type $phpDocReturnType,
75+
?Type $throwType,
76+
?string $deprecatedDescription,
77+
bool $isDeprecated,
78+
bool $isInternal,
79+
bool $isFinal,
80+
?bool $isPure = null,
81+
bool $acceptsNamedArguments = true,
82+
?Assertions $asserts = null,
83+
?Type $selfOutType = null,
84+
?string $phpDocComment = null,
85+
array $parameterOutTypes = [],
86+
array $immediatelyInvokedCallableParameters = [],
87+
array $phpDocClosureThisTypeParameters = [],
88+
bool $isConstructor = false,
89+
): self
90+
{
91+
// TODO: Implement enterClassMethod() method.
92+
throw new ShouldNotHappenException('Not implemented yet');
93+
}
94+
95+
public function generalizeWith(self $otherScope): self
96+
{
97+
// TODO: Implement generalizeWith() method.
98+
throw new ShouldNotHappenException('Not implemented yet');
99+
}
100+
50101
public function isInClass(): bool
51102
{
52103
// TODO: Implement isInClass() method.
@@ -98,13 +149,13 @@ public function getNamespace(): ?string
98149
public function getFile(): string
99150
{
100151
// TODO: Implement getFile() method.
101-
throw new ShouldNotHappenException('Not implemented yet');
152+
return 'foo.php';
102153
}
103154

104155
public function getFileDescription(): string
105156
{
106157
// TODO: Implement getFileDescription() method.
107-
throw new ShouldNotHappenException('Not implemented yet');
158+
return 'foo.php';
108159
}
109160

110161
public function isDeclareStrictTypes(): bool
@@ -116,7 +167,7 @@ public function isDeclareStrictTypes(): bool
116167
public function isInTrait(): bool
117168
{
118169
// TODO: Implement isInTrait() method.
119-
throw new ShouldNotHappenException('Not implemented yet');
170+
return false;
120171
}
121172

122173
public function getTraitReflection(): ?ClassReflection
@@ -200,7 +251,7 @@ public function getStaticPropertyReflection(Type $typeWithProperty, string $prop
200251
public function getMethodReflection(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection
201252
{
202253
// TODO: Implement getMethodReflection() method.
203-
throw new ShouldNotHappenException('Not implemented yet');
254+
return null;
204255
}
205256

206257
public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection

src/Analyser/NodeScopeResolver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7019,6 +7019,9 @@ 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+
}
70227025
$this->processStmtNode($stmt, $scope, $nodeCallback, StatementContext::createTopLevel());
70237026
}
70247027
return;

src/Analyser/ScopeFactory.php

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

55
use PhpParser\Node;
6+
use PHPStan\Analyser\Generator\GeneratorScope;
67
use PHPStan\DependencyInjection\AutowiredService;
78

89
/**
@@ -12,15 +13,30 @@
1213
final class ScopeFactory
1314
{
1415

15-
public function __construct(private InternalScopeFactoryFactory $internalScopeFactoryFactory)
16+
public function __construct(
17+
private InternalScopeFactoryFactory $internalScopeFactoryFactory,
18+
private bool $createGeneratorScope = false,
19+
)
1620
{
1721
}
1822

23+
/**
24+
* @internal
25+
*/
26+
public function getInternalScopeFactoryFactory(): InternalScopeFactoryFactory
27+
{
28+
return $this->internalScopeFactoryFactory;
29+
}
30+
1931
/**
2032
* @param callable(Node $node, Scope $scope): void $nodeCallback
2133
*/
22-
public function create(ScopeContext $context, ?callable $nodeCallback = null): MutatingScope
34+
public function create(ScopeContext $context, ?callable $nodeCallback = null): MutatingScope|GeneratorScope
2335
{
36+
if ($this->createGeneratorScope) {
37+
return new GeneratorScope([]);
38+
}
39+
2440
return $this->internalScopeFactoryFactory->create($nodeCallback)->create($context);
2541
}
2642

src/Testing/PHPStanTestCase.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use PHPStan\Analyser\NodeScopeResolver;
99
use PHPStan\Analyser\RicherScopeGetTypeHelper;
1010
use PHPStan\Analyser\ScopeFactory;
11-
use PHPStan\Analyser\TypeSpecifier;
1211
use PHPStan\BetterReflection\Reflector\Reflector;
1312
use PHPStan\DependencyInjection\Container;
1413
use PHPStan\DependencyInjection\ContainerFactory;
@@ -130,14 +129,16 @@ public static function getClassReflectionExtensionRegistryProvider(): ClassRefle
130129
/**
131130
* @param string[] $dynamicConstantNames
132131
*/
133-
public static function createScopeFactory(ReflectionProvider $reflectionProvider, TypeSpecifier $typeSpecifier, array $dynamicConstantNames = []): ScopeFactory
132+
public static function createScopeFactory(array $dynamicConstantNames = []): ScopeFactory
134133
{
135134
$container = self::getContainer();
136135

137136
if (count($dynamicConstantNames) === 0) {
138137
$dynamicConstantNames = $container->getParameter('dynamicConstantNames');
139138
}
140139

140+
$reflectionProvider = self::createReflectionProvider();
141+
$typeSpecifier = self::getContainer()->getService('typeSpecifier');
141142
$reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider);
142143
$composerPhpVersionFactory = $container->getByType(ComposerPhpVersionFactory::class);
143144
$constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames, null, $composerPhpVersionFactory, $container);

0 commit comments

Comments
 (0)