Skip to content

Commit 56e8cfb

Browse files
committed
enforce required generic params
1 parent cab84d3 commit 56e8cfb

18 files changed

+326
-0
lines changed

src/Rules/Classes/LocalTypeAliasesCheck.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ public function checkInTraitDefinitionContext(ClassReflection $reflection): arra
221221
->build();
222222
}
223223

224+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($resolvedType) as [$innerAliasName, $missingParams]) {
225+
if ($innerAliasName === $aliasName) {
226+
continue; // alias body contains its own template type placeholders — not a raw usage
227+
}
228+
$errors[] = RuleErrorBuilder::message(sprintf(
229+
'%s %s has type alias %s with generic type alias %s but does not specify its types: %s',
230+
$reflection->getClassTypeDescription(),
231+
$reflection->getDisplayName(),
232+
$aliasName,
233+
$innerAliasName,
234+
$missingParams,
235+
))
236+
->identifier('missingType.generics')
237+
->build();
238+
}
239+
224240
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($resolvedType) as $callableType) {
225241
$errors[] = RuleErrorBuilder::message(sprintf(
226242
'%s %s has type alias %s with no signature specified for %s.',

src/Rules/Classes/MethodTagCheck.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,19 @@ private function checkMethodTypeInTraitDefinitionContext(ClassReflection $classR
190190
->build();
191191
}
192192

193+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($type) as [$aliasName, $missingParams]) {
194+
$errors[] = RuleErrorBuilder::message(sprintf(
195+
'PHPDoc tag @method for method %s::%s() %s contains generic type alias %s but does not specify its types: %s',
196+
$classReflection->getDisplayName(),
197+
$methodName,
198+
$description,
199+
$aliasName,
200+
$missingParams,
201+
))
202+
->identifier('missingType.generics')
203+
->build();
204+
}
205+
193206
foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) {
194207
$iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly());
195208
$errors[] = RuleErrorBuilder::message(sprintf(

src/Rules/Classes/MixinCheck.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ public function checkInTraitDefinitionContext(ClassReflection $classReflection):
9999
->build();
100100
}
101101

102+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($type) as [$aliasName, $missingParams]) {
103+
$errors[] = RuleErrorBuilder::message(sprintf(
104+
'PHPDoc tag @mixin contains generic type alias %s but does not specify its types: %s',
105+
$aliasName,
106+
$missingParams,
107+
))
108+
->identifier('missingType.generics')
109+
->build();
110+
}
111+
102112
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($type) as $callableType) {
103113
$errors[] = RuleErrorBuilder::message(sprintf(
104114
'%s %s has PHPDoc tag @mixin with no signature specified for %s.',

src/Rules/Classes/PropertyTagCheck.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,19 @@ private function checkPropertyTypeInTraitDefinitionContext(ClassReflection $clas
171171
->build();
172172
}
173173

174+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($type) as [$aliasName, $missingParams]) {
175+
$errors[] = RuleErrorBuilder::message(sprintf(
176+
'PHPDoc tag %s for property %s::$%s contains generic type alias %s but does not specify its types: %s',
177+
$tagName,
178+
$classReflection->getDisplayName(),
179+
$propertyName,
180+
$aliasName,
181+
$missingParams,
182+
))
183+
->identifier('missingType.generics')
184+
->build();
185+
}
186+
174187
foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) {
175188
$iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly());
176189
$errors[] = RuleErrorBuilder::message(sprintf(

src/Rules/Constants/MissingClassConstantTypehintRule.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ private function processSingleConstant(ClassReflection $classReflection, string
8383
->build();
8484
}
8585

86+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($constantType) as [$aliasName, $missingParams]) {
87+
$errors[] = RuleErrorBuilder::message(sprintf(
88+
'Constant %s::%s with generic type alias %s does not specify its types: %s',
89+
$constantReflection->getDeclaringClass()->getDisplayName(),
90+
$constantName,
91+
$aliasName,
92+
$missingParams,
93+
))
94+
->identifier('missingType.generics')
95+
->build();
96+
}
97+
8698
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($constantType) as $callableType) {
8799
$errors[] = RuleErrorBuilder::message(sprintf(
88100
'Constant %s::%s type has no signature specified for %s.',

src/Rules/Functions/MissingFunctionParameterTypehintRule.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ private function checkFunctionParameter(FunctionReflection $functionReflection,
105105
->build();
106106
}
107107

108+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($parameterType) as [$aliasName, $missingParams]) {
109+
$messages[] = RuleErrorBuilder::message(sprintf(
110+
'Function %s() has %s with generic type alias %s but does not specify its types: %s',
111+
$functionReflection->getName(),
112+
$parameterMessage,
113+
$aliasName,
114+
$missingParams,
115+
))
116+
->identifier('missingType.generics')
117+
->build();
118+
}
119+
108120
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($parameterType) as $callableType) {
109121
$messages[] = RuleErrorBuilder::message(sprintf(
110122
'Function %s() has %s with no signature specified for %s.',

src/Rules/Functions/MissingFunctionReturnTypehintRule.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ public function processNode(Node $node, Scope $scope): array
6767
->build();
6868
}
6969

70+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($returnType) as [$aliasName, $missingParams]) {
71+
$messages[] = RuleErrorBuilder::message(sprintf(
72+
'Function %s() return type with generic type alias %s does not specify its types: %s',
73+
$functionReflection->getName(),
74+
$aliasName,
75+
$missingParams,
76+
))
77+
->identifier('missingType.generics')
78+
->build();
79+
}
80+
7081
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($returnType) as $callableType) {
7182
$messages[] = RuleErrorBuilder::message(sprintf(
7283
'Function %s() return type has no signature specified for %s.',

src/Rules/Methods/MissingMethodParameterTypehintRule.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ private function checkMethodParameter(MethodReflection $methodReflection, string
108108
->build();
109109
}
110110

111+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($parameterType) as [$aliasName, $missingParams]) {
112+
$messages[] = RuleErrorBuilder::message(sprintf(
113+
'Method %s::%s() has %s with generic type alias %s but does not specify its types: %s',
114+
$methodReflection->getDeclaringClass()->getDisplayName(),
115+
$methodReflection->getName(),
116+
$parameterMessage,
117+
$aliasName,
118+
$missingParams,
119+
))
120+
->identifier('missingType.generics')
121+
->build();
122+
}
123+
111124
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($parameterType) as $callableType) {
112125
$messages[] = RuleErrorBuilder::message(sprintf(
113126
'Method %s::%s() has %s with no signature specified for %s.',

src/Rules/Methods/MissingMethodReturnTypehintRule.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ public function processNode(Node $node, Scope $scope): array
7979
->build();
8080
}
8181

82+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($returnType) as [$aliasName, $missingParams]) {
83+
$messages[] = RuleErrorBuilder::message(sprintf(
84+
'Method %s::%s() return type with generic type alias %s does not specify its types: %s',
85+
$methodReflection->getDeclaringClass()->getDisplayName(),
86+
$methodReflection->getName(),
87+
$aliasName,
88+
$missingParams,
89+
))
90+
->identifier('missingType.generics')
91+
->build();
92+
}
93+
8294
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($returnType) as $callableType) {
8395
$messages[] = RuleErrorBuilder::message(sprintf(
8496
'Method %s::%s() return type has no signature specified for %s.',

src/Rules/Methods/MissingMethodSelfOutTypeRule.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,19 @@ public function processNode(Node $node, Scope $scope): array
7272
->build();
7373
}
7474

75+
foreach ($this->missingTypehintCheck->getRawGenericTypeAliasesUsage($selfOutType) as [$aliasName, $missingParams]) {
76+
$messages[] = RuleErrorBuilder::message(sprintf(
77+
'Method %s::%s() has %s with generic type alias %s but does not specify its types: %s',
78+
$classReflection->getDisplayName(),
79+
$methodReflection->getName(),
80+
$phpDocTagMessage,
81+
$aliasName,
82+
$missingParams,
83+
))
84+
->identifier('missingType.generics')
85+
->build();
86+
}
87+
7588
foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($selfOutType) as $callableType) {
7689
$messages[] = RuleErrorBuilder::message(sprintf(
7790
'Method %s::%s() has %s with no signature specified for %s.',

0 commit comments

Comments
 (0)