44
55use PHPStan \Type \Accessory \AccessoryNumericStringType ;
66use PHPStan \Type \Accessory \NonEmptyArrayType ;
7+ use PHPStan \Type \Generic \GenericObjectType ;
8+ use PHPStan \Type \Generic \TemplateType ;
79
810class VerbosityLevel
911{
@@ -49,10 +51,9 @@ public static function cache(): self
4951return self ::create (self ::CACHE );
5052}
5153
52- public static function getRecommendedLevelByType (Type $ type ): self
54+ public static function getRecommendedLevelByType (Type $ acceptingType , ? Type $ acceptedType = null ): self
5355{
54- $ moreVerbose = false ;
55- TypeTraverser::map ($ type , static function (Type $ type , callable $ traverse ) use (&$ moreVerbose ): Type {
56+ $ moreVerboseCallback = static function (Type $ type , callable $ traverse ) use (&$ moreVerbose ): Type {
5657if ($ type ->isCallable ()->yes ()) {
5758$ moreVerbose = true ;
5859return $ type ;
@@ -69,9 +70,53 @@ public static function getRecommendedLevelByType(Type $type): self
6970$ moreVerbose = true ;
7071return $ type ;
7172}
73+ return $ traverse ($ type );
74+ };
75+
76+ /** @var bool $moreVerbose */
77+ $ moreVerbose = false ;
78+ TypeTraverser::map ($ acceptingType , $ moreVerboseCallback );
79+
80+ if ($ moreVerbose ) {
81+ return self ::value ();
82+ }
83+
84+ if ($ acceptedType === null ) {
85+ return self ::typeOnly ();
86+ }
87+
88+ $ containsInvariantTemplateType = false ;
89+ TypeTraverser::map ($ acceptingType , static function (Type $ type , callable $ traverse ) use (&$ containsInvariantTemplateType ): Type {
90+ if ($ type instanceof GenericObjectType) {
91+ $ reflection = $ type ->getClassReflection ();
92+ if ($ reflection !== null ) {
93+ $ templateTypeMap = $ reflection ->getTemplateTypeMap ();
94+ foreach ($ templateTypeMap ->getTypes () as $ templateType ) {
95+ if (!$ templateType instanceof TemplateType) {
96+ continue ;
97+ }
98+
99+ if (!$ templateType ->getVariance ()->invariant ()) {
100+ continue ;
101+ }
102+
103+ $ containsInvariantTemplateType = true ;
104+ return $ type ;
105+ }
106+ }
107+ }
108+
72109return $ traverse ($ type );
73110});
74111
112+ if (!$ containsInvariantTemplateType ) {
113+ return self ::typeOnly ();
114+ }
115+
116+ /** @var bool $moreVerbose */
117+ $ moreVerbose = false ;
118+ TypeTraverser::map ($ acceptedType , $ moreVerboseCallback );
119+
75120return $ moreVerbose ? self ::value () : self ::typeOnly ();
76121}
77122
0 commit comments