7
7
use PHPStan \Rules \ClassCaseSensitivityCheck ;
8
8
use PHPStan \Rules \ClassNameNodePair ;
9
9
use PHPStan \Rules \RuleErrorBuilder ;
10
- use PHPStan \Type \Generic \TemplateTypeScope ;
10
+ use PHPStan \Type \Generic \GenericObjectType ;
11
+ use PHPStan \Type \Generic \TemplateType ;
11
12
use PHPStan \Type \IntegerType ;
12
13
use PHPStan \Type \MixedType ;
13
14
use PHPStan \Type \ObjectType ;
@@ -27,6 +28,8 @@ class TemplateTypeCheck
27
28
28
29
private \PHPStan \Rules \ClassCaseSensitivityCheck $ classCaseSensitivityCheck ;
29
30
31
+ private GenericObjectTypeCheck $ genericObjectTypeCheck ;
32
+
30
33
/** @var array<string, string> */
31
34
private array $ typeAliases ;
32
35
@@ -35,31 +38,32 @@ class TemplateTypeCheck
35
38
/**
36
39
* @param ReflectionProvider $reflectionProvider
37
40
* @param ClassCaseSensitivityCheck $classCaseSensitivityCheck
41
+ * @param GenericObjectTypeCheck $genericObjectTypeCheck
38
42
* @param array<string, string> $typeAliases
39
43
* @param bool $checkClassCaseSensitivity
40
44
*/
41
45
public function __construct (
42
46
ReflectionProvider $ reflectionProvider ,
43
47
ClassCaseSensitivityCheck $ classCaseSensitivityCheck ,
48
+ GenericObjectTypeCheck $ genericObjectTypeCheck ,
44
49
array $ typeAliases ,
45
50
bool $ checkClassCaseSensitivity
46
51
)
47
52
{
48
53
$ this ->reflectionProvider = $ reflectionProvider ;
49
54
$ this ->classCaseSensitivityCheck = $ classCaseSensitivityCheck ;
55
+ $ this ->genericObjectTypeCheck = $ genericObjectTypeCheck ;
50
56
$ this ->typeAliases = $ typeAliases ;
51
57
$ this ->checkClassCaseSensitivity = $ checkClassCaseSensitivity ;
52
58
}
53
59
54
60
/**
55
61
* @param \PhpParser\Node $node
56
- * @param \PHPStan\Type\Generic\TemplateTypeScope $templateTypeScope
57
62
* @param array<string, \PHPStan\PhpDoc\Tag\TemplateTag> $templateTags
58
63
* @return \PHPStan\Rules\RuleError[]
59
64
*/
60
65
public function check (
61
66
Node $ node ,
62
- TemplateTypeScope $ templateTypeScope ,
63
67
array $ templateTags ,
64
68
string $ sameTemplateTypeNameAsClassMessage ,
65
69
string $ sameTemplateTypeNameAsTypeMessage ,
@@ -113,7 +117,9 @@ public function check(
113
117
|| $ boundClass === IntegerType::class
114
118
|| $ boundClass === ObjectWithoutClassType::class
115
119
|| $ boundClass === ObjectType::class
120
+ || $ boundClass === GenericObjectType::class
116
121
|| $ type instanceof UnionType
122
+ || $ type instanceof TemplateType
117
123
) {
118
124
return $ traverse ($ type );
119
125
}
@@ -122,6 +128,17 @@ public function check(
122
128
123
129
return $ type ;
124
130
});
131
+
132
+ $ genericObjectErrors = $ this ->genericObjectTypeCheck ->check (
133
+ $ boundType ,
134
+ sprintf ('PHPDoc tag @template %s bound contains generic type %%s but class %%s is not generic. ' , $ templateTagName ),
135
+ sprintf ('PHPDoc tag @template %s bound has type %%s which does not specify all template types of class %%s: %%s ' , $ templateTagName ),
136
+ sprintf ('PHPDoc tag @template %s bound has type %%s which specifies %%d template types, but class %%s supports only %%d: %%s ' , $ templateTagName ),
137
+ sprintf ('Type %%s in generic type %%s in PHPDoc tag @template %s is not subtype of template type %%s of class %%s. ' , $ templateTagName ),
138
+ );
139
+ foreach ($ genericObjectErrors as $ genericObjectError ) {
140
+ $ messages [] = $ genericObjectError ;
141
+ }
125
142
}
126
143
127
144
return $ messages ;
0 commit comments