20
20
use PHPStan \Reflection \ReflectionProvider \ReflectionProviderProvider ;
21
21
use PHPStan \ShouldNotHappenException ;
22
22
use PHPStan \Type \Generic \GenericObjectType ;
23
- use PHPStan \Type \Generic \TemplateType ;
24
23
use PHPStan \Type \Generic \TemplateTypeFactory ;
25
24
use PHPStan \Type \Generic \TemplateTypeHelper ;
26
25
use PHPStan \Type \Generic \TemplateTypeMap ;
@@ -134,29 +133,6 @@ public function getResolvedPhpDoc(
134
133
private function createResolvedPhpDocBlock (string $ phpDocKey , NameScope $ nameScope , string $ phpDocString , string $ fileName ): ResolvedPhpDocBlock
135
134
{
136
135
$ phpDocNode = $ this ->resolvePhpDocStringToDocNode ($ phpDocString );
137
- $ templateTags = $ this ->phpDocNodeResolver ->resolveTemplateTags ($ phpDocNode , $ nameScope );
138
- $ templateTypeScope = $ nameScope ->getTemplateTypeScope ();
139
-
140
- if ($ templateTypeScope !== null ) {
141
- $ templateTypeMap = new TemplateTypeMap (array_map (static fn (TemplateTag $ tag ): Type => TemplateTypeFactory::fromTemplateTag ($ templateTypeScope , $ tag ), $ templateTags ));
142
- $ nameScope = $ nameScope ->withTemplateTypeMap (
143
- new TemplateTypeMap (array_merge (
144
- $ nameScope ->getTemplateTypeMap ()->getTypes (),
145
- $ templateTypeMap ->getTypes (),
146
- )),
147
- );
148
- $ templateTags = $ this ->phpDocNodeResolver ->resolveTemplateTags ($ phpDocNode , $ nameScope );
149
- $ templateTypeMap = new TemplateTypeMap (array_map (static fn (TemplateTag $ tag ): Type => TemplateTypeFactory::fromTemplateTag ($ templateTypeScope , $ tag ), $ templateTags ));
150
- $ nameScope = $ nameScope ->withTemplateTypeMap (
151
- new TemplateTypeMap (array_merge (
152
- $ nameScope ->getTemplateTypeMap ()->getTypes (),
153
- $ templateTypeMap ->getTypes (),
154
- )),
155
- );
156
- } else {
157
- $ templateTypeMap = TemplateTypeMap::createEmpty ();
158
- }
159
-
160
136
if ($ this ->resolvedPhpDocBlockCacheCount >= 512 ) {
161
137
$ this ->resolvedPhpDocBlockCache = array_slice (
162
138
$ this ->resolvedPhpDocBlockCache ,
@@ -168,12 +144,23 @@ private function createResolvedPhpDocBlock(string $phpDocKey, NameScope $nameSco
168
144
$ this ->resolvedPhpDocBlockCacheCount --;
169
145
}
170
146
147
+ $ templateTypeMap = $ nameScope ->getTemplateTypeMap ();
148
+ $ phpDocTemplateTypes = [];
149
+ $ templateTags = $ this ->phpDocNodeResolver ->resolveTemplateTags ($ phpDocNode , $ nameScope );
150
+ foreach (array_keys ($ templateTags ) as $ name ) {
151
+ $ templateType = $ templateTypeMap ->getType ($ name );
152
+ if ($ templateType === null ) {
153
+ continue ;
154
+ }
155
+ $ phpDocTemplateTypes [$ name ] = $ templateType ;
156
+ }
157
+
171
158
$ this ->resolvedPhpDocBlockCache [$ phpDocKey ] = ResolvedPhpDocBlock::create (
172
159
$ phpDocNode ,
173
160
$ phpDocString ,
174
161
$ fileName ,
175
162
$ nameScope ,
176
- $ templateTypeMap ,
163
+ new TemplateTypeMap ( $ phpDocTemplateTypes ) ,
177
164
$ templateTags ,
178
165
$ this ->phpDocNodeResolver ,
179
166
);
@@ -193,7 +180,7 @@ private function resolvePhpDocStringToDocNode(string $phpDocString): PhpDocNode
193
180
private function getNameScopeMap (string $ fileName ): array
194
181
{
195
182
if (!isset ($ this ->memoryCache [$ fileName ])) {
196
- $ cacheKey = sprintf ('%s-phpdocstring-v19-trait-detection-recursion ' , $ fileName );
183
+ $ cacheKey = sprintf ('%s-phpdocstring-v20-template-tags ' , $ fileName );
197
184
$ variableCacheKey = sprintf ('%s-%s ' , implode (', ' , array_map (static fn (array $ file ): string => sprintf ('%s-%d ' , $ file ['filename ' ], $ file ['modifiedTime ' ]), $ this ->getCachedDependentFilesWithTimestamps ($ fileName ))), $ this ->phpVersion ->getVersionString ());
198
185
$ map = $ this ->cache ->load ($ cacheKey , $ variableCacheKey );
199
186
@@ -322,14 +309,15 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
322
309
323
310
$ className = $ classStack [count ($ classStack ) - 1 ] ?? null ;
324
311
$ functionName = $ functionStack [count ($ functionStack ) - 1 ] ?? null ;
325
- $ resolvableTemplateTypes = ($ className !== null && $ lookForTrait === null ) || $ functionName !== null ;
326
312
327
313
if ($ node instanceof Node \Stmt \ClassLike || $ node instanceof Node \Stmt \ClassMethod || $ node instanceof Node \Stmt \Function_) {
328
314
$ phpDocString = GetLastDocComment::forNode ($ node );
329
315
if ($ phpDocString !== '' ) {
330
- $ typeMapStack [] = function () use ($ namespace , $ uses , $ className , $ functionName , $ phpDocString , $ typeMapStack, $ resolvableTemplateTypes ): TemplateTypeMap {
316
+ $ typeMapStack [] = function () use ($ namespace , $ uses , $ className , $ functionName , $ phpDocString , $ typeMapStack ): TemplateTypeMap {
331
317
$ phpDocNode = $ this ->resolvePhpDocStringToDocNode ($ phpDocString );
332
- $ nameScope = new NameScope ($ namespace , $ uses , $ className , $ functionName );
318
+ $ typeMapCb = $ typeMapStack [count ($ typeMapStack ) - 1 ] ?? null ;
319
+ $ currentTypeMap = $ typeMapCb !== null ? $ typeMapCb () : null ;
320
+ $ nameScope = new NameScope ($ namespace , $ uses , $ className , $ functionName , $ currentTypeMap );
333
321
$ templateTags = $ this ->phpDocNodeResolver ->resolveTemplateTags ($ phpDocNode , $ nameScope );
334
322
$ templateTypeScope = $ nameScope ->getTemplateTypeScope ();
335
323
if ($ templateTypeScope === null ) {
@@ -339,28 +327,11 @@ function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodA
339
327
$ nameScope = $ nameScope ->withTemplateTypeMap ($ templateTypeMap );
340
328
$ templateTags = $ this ->phpDocNodeResolver ->resolveTemplateTags ($ phpDocNode , $ nameScope );
341
329
$ templateTypeMap = new TemplateTypeMap (array_map (static fn (TemplateTag $ tag ): Type => TemplateTypeFactory::fromTemplateTag ($ templateTypeScope , $ tag ), $ templateTags ));
342
- $ typeMapCb = $ typeMapStack [count ($ typeMapStack ) - 1 ] ?? null ;
343
330
344
- return ( new TemplateTypeMap (array_merge (
345
- $ typeMapCb !== null ? $ typeMapCb () ->getTypes () : [],
331
+ return new TemplateTypeMap (array_merge (
332
+ $ currentTypeMap !== null ? $ currentTypeMap ->getTypes () : [],
346
333
$ templateTypeMap ->getTypes (),
347
- )))->map (static fn (string $ name , Type $ type ): Type => TypeTraverser::map ($ type , static function (Type $ type , callable $ traverse ) use ($ className , $ resolvableTemplateTypes ): Type {
348
- if (!$ type instanceof TemplateType) {
349
- return $ traverse ($ type );
350
- }
351
-
352
- if (!$ resolvableTemplateTypes ) {
353
- return $ traverse ($ type ->toArgument ());
354
- }
355
-
356
- $ scope = $ type ->getScope ();
357
-
358
- if ($ scope ->getClassName () === null || $ scope ->getFunctionName () !== null || $ scope ->getClassName () !== $ className ) {
359
- return $ traverse ($ type ->toArgument ());
360
- }
361
-
362
- return $ traverse ($ type );
363
- }));
334
+ ));
364
335
};
365
336
}
366
337
}
0 commit comments