55use Closure ;
66use PHPStan \Analyser \OutOfClassScope ;
77use PHPStan \Php \PhpVersion ;
8+ use PHPStan \PhpDoc \Tag \TemplateTag ;
89use PHPStan \PhpDocParser \Ast \PhpDoc \TemplateTagValueNode ;
910use PHPStan \PhpDocParser \Ast \Type \CallableTypeNode ;
1011use PHPStan \PhpDocParser \Ast \Type \CallableTypeParameterNode ;
2425use PHPStan \Reflection \PropertyReflection ;
2526use PHPStan \Reflection \Type \UnresolvedMethodPrototypeReflection ;
2627use PHPStan \Reflection \Type \UnresolvedPropertyPrototypeReflection ;
27- use PHPStan \ShouldNotHappenException ;
2828use PHPStan \TrinaryLogic ;
2929use PHPStan \Type \Constant \ConstantArrayType ;
3030use PHPStan \Type \Constant \ConstantBooleanType ;
@@ -67,6 +67,7 @@ class ClosureType implements TypeWithClassName, ParametersAcceptor
6767 /**
6868 * @api
6969 * @param array<int, ParameterReflection> $parameters
70+ * @param array<string, TemplateTag> $templateTags
7071 */
7172 public function __construct (
7273 private array $ parameters ,
@@ -75,6 +76,7 @@ public function __construct(
7576 ?TemplateTypeMap $ templateTypeMap = null ,
7677 ?TemplateTypeMap $ resolvedTemplateTypeMap = null ,
7778 ?TemplateTypeVarianceMap $ callSiteVarianceMap = null ,
79+ private array $ templateTags = [],
7880 )
7981 {
8082 $ this ->objectType = new ObjectType (Closure::class);
@@ -83,6 +85,14 @@ public function __construct(
8385 $ this ->callSiteVarianceMap = $ callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty ();
8486 }
8587
88+ /**
89+ * @return array<string, TemplateTag>
90+ */
91+ public function getTemplateTags (): array
92+ {
93+ return $ this ->templateTags ;
94+ }
95+
8696 public function getClassName (): string
8797 {
8898 return $ this ->objectType ->getClassName ();
@@ -194,6 +204,7 @@ function (): string {
194204 $ this ->templateTypeMap ,
195205 $ this ->resolvedTemplateTypeMap ,
196206 $ this ->callSiteVarianceMap ,
207+ $ this ->templateTags ,
197208 );
198209
199210 return $ printer ->print ($ selfWithoutParameterNames ->toPhpDocNode ());
@@ -452,6 +463,7 @@ public function traverse(callable $cb): Type
452463 $ this ->templateTypeMap ,
453464 $ this ->resolvedTemplateTypeMap ,
454465 $ this ->callSiteVarianceMap ,
466+ $ this ->templateTags ,
455467 );
456468 }
457469
@@ -489,6 +501,10 @@ public function traverseSimultaneously(Type $right, callable $cb): Type
489501 $ parameters ,
490502 $ cb ($ this ->getReturnType (), $ right ->getReturnType ()),
491503 $ this ->isVariadic (),
504+ $ this ->templateTypeMap ,
505+ $ this ->resolvedTemplateTypeMap ,
506+ $ this ->callSiteVarianceMap ,
507+ $ this ->templateTags ,
492508 );
493509 }
494510
@@ -621,14 +637,10 @@ public function toPhpDocNode(): TypeNode
621637 }
622638
623639 $ templateTags = [];
624- foreach ($ this ->templateTypeMap ->getTypes () as $ templateName => $ templateType ) {
625- if (!$ templateType instanceof TemplateType) {
626- throw new ShouldNotHappenException ();
627- }
628-
640+ foreach ($ this ->templateTags as $ templateName => $ templateTag ) {
629641 $ templateTags [] = new TemplateTagValueNode (
630642 $ templateName ,
631- $ templateType ->getBound ()->toPhpDocNode (),
643+ $ templateTag ->getBound ()->toPhpDocNode (),
632644 '' ,
633645 );
634646 }
0 commit comments