1111use PHPStan \Analyser \NodeCallbackInvoker ;
1212use PHPStan \Analyser \Scope ;
1313use PHPStan \Analyser \ScopeContext ;
14+ use PHPStan \Node \Printer \ExprPrinter ;
1415use PHPStan \Php \PhpVersions ;
15- use PHPStan \Reflection \Assertions ;
1616use PHPStan \Reflection \ClassConstantReflection ;
1717use PHPStan \Reflection \ClassReflection ;
1818use PHPStan \Reflection \ExtendedMethodReflection ;
2323use PHPStan \ShouldNotHappenException ;
2424use PHPStan \TrinaryLogic ;
2525use PHPStan \Type \ClosureType ;
26- use PHPStan \Type \Generic \TemplateTypeMap ;
2726use PHPStan \Type \Type ;
2827use PHPStan \Type \TypeWithClassName ;
28+ use function array_key_exists ;
2929
3030final class GeneratorScope implements Scope, NodeCallbackInvoker
3131{
3232
33+ /** @var non-empty-string|null */
34+ private ?string $ namespace ;
35+
3336 /**
3437 * @param array<string, ExpressionTypeHolder> $expressionTypes
38+ * @param array<string, ExpressionTypeHolder> $nativeExpressionTypes
3539 */
3640 public function __construct (
3741 private InternalGeneratorScopeFactory $ scopeFactory ,
42+ private ExprPrinter $ exprPrinter ,
3843 private ScopeContext $ context ,
39- public array $ expressionTypes ,
44+ private bool $ declareStrictTypes = false ,
45+ private PhpFunctionFromParserNodeReflection |null $ function = null ,
46+ ?string $ namespace = null ,
47+ private array $ expressionTypes = [],
48+ private array $ nativeExpressionTypes = [],
4049 )
4150 {
51+ if ($ namespace === '' ) {
52+ $ namespace = null ;
53+ }
54+
55+ $ this ->namespace = $ namespace ;
56+ }
57+
58+ /**
59+ * This method is meant to be called for expressions for which the type
60+ * should be stored in Scope itself.
61+ *
62+ * This is meant to be used only by handlers in PHPStan\Analyser\Generator namespace.
63+ *
64+ * All other code should use `getType()` method.
65+ */
66+ public function getExpressionType (Expr $ expr ): ?Type
67+ {
68+ $ exprString = $ this ->exprPrinter ->printExpr ($ expr );
69+ if (array_key_exists ($ exprString , $ this ->expressionTypes )) {
70+ return $ this ->expressionTypes [$ exprString ]->getType ();
71+ }
72+
73+ return null ;
4274 }
4375
4476 public function assignVariable (string $ variableName , Type $ type ): self
@@ -50,57 +82,22 @@ public function assignVariable(string $variableName, Type $type): self
5082
5183 return $ this ->scopeFactory ->create (
5284 $ this ->context ,
85+ $ this ->declareStrictTypes ,
86+ $ this ->function ,
87+ $ this ->namespace ,
5388 $ expressionTypes ,
5489 );
5590 }
5691
92+ /** @api */
5793 public function enterNamespace (string $ namespaceName ): self
5894 {
59- // TODO: Implement enterNamespace() method.
60- throw new ShouldNotHappenException ('Not implemented yet ' );
61- }
62-
63- public function enterClass (ClassReflection $ classReflection ): self
64- {
65- // TODO: Implement enterClass() method.
66- throw new ShouldNotHappenException ('Not implemented yet ' );
67- }
68-
69- /**
70- * @param Type[] $phpDocParameterTypes
71- * @param Type[] $parameterOutTypes
72- * @param array<string, bool> $immediatelyInvokedCallableParameters
73- * @param array<string, Type> $phpDocClosureThisTypeParameters
74- */
75- public function enterClassMethod (
76- Node \Stmt \ClassMethod $ classMethod ,
77- TemplateTypeMap $ templateTypeMap ,
78- array $ phpDocParameterTypes ,
79- ?Type $ phpDocReturnType ,
80- ?Type $ throwType ,
81- ?string $ deprecatedDescription ,
82- bool $ isDeprecated ,
83- bool $ isInternal ,
84- bool $ isFinal ,
85- ?bool $ isPure = null ,
86- bool $ acceptsNamedArguments = true ,
87- ?Assertions $ asserts = null ,
88- ?Type $ selfOutType = null ,
89- ?string $ phpDocComment = null ,
90- array $ parameterOutTypes = [],
91- array $ immediatelyInvokedCallableParameters = [],
92- array $ phpDocClosureThisTypeParameters = [],
93- bool $ isConstructor = false ,
94- ): self
95- {
96- // TODO: Implement enterClassMethod() method.
97- throw new ShouldNotHappenException ('Not implemented yet ' );
98- }
99-
100- public function generalizeWith (self $ otherScope ): self
101- {
102- // TODO: Implement generalizeWith() method.
103- throw new ShouldNotHappenException ('Not implemented yet ' );
95+ return $ this ->scopeFactory ->create (
96+ $ this ->context ->beginFile (),
97+ $ this ->isDeclareStrictTypes (),
98+ null ,
99+ $ namespaceName ,
100+ );
104101 }
105102
106103 public function isInClass (): bool
@@ -145,10 +142,10 @@ public function canAccessConstant(ClassConstantReflection $constantReflection):
145142 throw new ShouldNotHappenException ('Not implemented yet ' );
146143 }
147144
145+ /** @api */
148146 public function getNamespace (): ?string
149147 {
150- // TODO: Implement getNamespace() method.
151- return null ;
148+ return $ this ->namespace ;
152149 }
153150
154151 public function getFile (): string
@@ -163,10 +160,22 @@ public function getFileDescription(): string
163160 return 'foo.php ' ;
164161 }
165162
163+ /** @api */
166164 public function isDeclareStrictTypes (): bool
167165 {
168- // TODO: Implement isDeclareStrictTypes() method.
169- throw new ShouldNotHappenException ('Not implemented yet ' );
166+ return $ this ->declareStrictTypes ;
167+ }
168+
169+ public function enterDeclareStrictTypes (): self
170+ {
171+ return $ this ->scopeFactory ->create (
172+ $ this ->context ,
173+ true ,
174+ null ,
175+ null ,
176+ $ this ->expressionTypes ,
177+ $ this ->nativeExpressionTypes ,
178+ );
170179 }
171180
172181 public function isInTrait (): bool
@@ -301,6 +310,7 @@ public function getAnonymousFunctionReturnType(): ?Type
301310 throw new ShouldNotHappenException ('Not implemented yet ' );
302311 }
303312
313+ /** @api */
304314 public function getType (Expr $ node ): Type
305315 {
306316 return Fiber::suspend (new ExprAnalysisRequest ($ node , $ this ))->type ;
0 commit comments