30
30
use PHPStan \PhpDocParser \Ast \PhpDoc \TemplateTagValueNode ;
31
31
use PHPStan \Reflection \PassedByReference ;
32
32
use PHPStan \Rules \PhpDoc \UnresolvableTypeHelper ;
33
+ use PHPStan \Type \Generic \TemplateTypeFactory ;
34
+ use PHPStan \Type \Generic \TemplateTypeMap ;
35
+ use PHPStan \Type \Generic \TemplateTypeScope ;
33
36
use PHPStan \Type \Generic \TemplateTypeVariance ;
34
37
use PHPStan \Type \MixedType ;
35
38
use PHPStan \Type \Type ;
@@ -160,6 +163,24 @@ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope):
160
163
161
164
foreach (['@method ' , '@psalm-method ' , '@phpstan-method ' ] as $ tagName ) {
162
165
foreach ($ phpDocNode ->getMethodTagValues ($ tagName ) as $ tagValue ) {
166
+ $ templateTags = [];
167
+
168
+ if (count ($ tagValue ->templateTypes ) > 0 ) {
169
+ foreach ($ tagValue ->templateTypes as $ templateType ) {
170
+ $ templateTags [$ templateType ->name ] = new TemplateTag (
171
+ $ templateType ->name ,
172
+ $ templateType ->bound !== null
173
+ ? $ this ->typeNodeResolver ->resolve ($ templateType ->bound , $ nameScope )
174
+ : new MixedType (),
175
+ TemplateTypeVariance::createInvariant ()
176
+ );
177
+ }
178
+
179
+ $ templateTypeScope = TemplateTypeScope::createWithMethod ($ nameScope ->getClassName (), $ tagValue ->methodName );
180
+ $ templateTypeMap = new TemplateTypeMap (array_map (static fn (TemplateTag $ tag ): Type => TemplateTypeFactory::fromTemplateTag ($ templateTypeScope , $ tag ), $ templateTags ));
181
+ $ nameScope = $ nameScope ->withTemplateTypeMap ($ templateTypeMap );
182
+ }
183
+
163
184
$ parameters = [];
164
185
foreach ($ tagValue ->parameters as $ parameterNode ) {
165
186
$ parameterName = substr ($ parameterNode ->parameterName , 1 );
@@ -185,24 +206,13 @@ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope):
185
206
);
186
207
}
187
208
188
- $ templates = [];
189
- foreach ($ tagValue ->templateTypes as $ templateType ) {
190
- $ templates [$ templateType ->name ] = new TemplateTag (
191
- $ templateType ->name ,
192
- $ templateType ->bound !== null
193
- ? $ this ->typeNodeResolver ->resolve ($ templateType ->bound , $ nameScope )
194
- : new MixedType (),
195
- TemplateTypeVariance::createInvariant ()
196
- );
197
- }
198
-
199
209
$ resolved [$ tagValue ->methodName ] = new MethodTag (
200
210
$ tagValue ->returnType !== null
201
211
? $ this ->typeNodeResolver ->resolve ($ tagValue ->returnType , $ nameScope )
202
212
: new MixedType (),
203
213
$ tagValue ->isStatic ,
204
214
$ parameters ,
205
- $ templates
215
+ $ templateTags ,
206
216
);
207
217
}
208
218
}
0 commit comments