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 */
7172public function __construct (
7273private 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+
8696public function getClassName (): string
8797{
8898return $ this ->objectType ->getClassName ();
@@ -194,6 +204,7 @@ function (): string {
194204$ this ->templateTypeMap ,
195205$ this ->resolvedTemplateTypeMap ,
196206$ this ->callSiteVarianceMap ,
207+ $ this ->templateTags ,
197208);
198209
199210return $ 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