3030use PHPStan \PhpDocParser \Ast \PhpDoc \TemplateTagValueNode ;
3131use PHPStan \Reflection \PassedByReference ;
3232use PHPStan \Rules \PhpDoc \UnresolvableTypeHelper ;
33+ use PHPStan \Type \Generic \TemplateTypeFactory ;
34+ use PHPStan \Type \Generic \TemplateTypeMap ;
35+ use PHPStan \Type \Generic \TemplateTypeScope ;
3336use PHPStan \Type \Generic \TemplateTypeVariance ;
3437use PHPStan \Type \MixedType ;
3538use PHPStan \Type \Type ;
@@ -160,6 +163,24 @@ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope):
160163
161164 foreach (['@method ' , '@psalm-method ' , '@phpstan-method ' ] as $ tagName ) {
162165 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+
163184 $ parameters = [];
164185 foreach ($ tagValue ->parameters as $ parameterNode ) {
165186 $ parameterName = substr ($ parameterNode ->parameterName , 1 );
@@ -185,24 +206,13 @@ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope):
185206 );
186207 }
187208
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-
199209 $ resolved [$ tagValue ->methodName ] = new MethodTag (
200210 $ tagValue ->returnType !== null
201211 ? $ this ->typeNodeResolver ->resolve ($ tagValue ->returnType , $ nameScope )
202212 : new MixedType (),
203213 $ tagValue ->isStatic ,
204214 $ parameters ,
205- $ templates
215+ $ templateTags ,
206216 );
207217 }
208218 }
0 commit comments