Skip to content

Commit 20baec2

Browse files
committed
Missing types should always be reported on level 6, not sooner
1 parent ae6403f commit 20baec2

File tree

10 files changed

+61
-29
lines changed

10 files changed

+61
-29
lines changed

conf/config.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ services:
917917
class: PHPStan\Rules\Generics\GenericAncestorsCheck
918918
arguments:
919919
skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses%
920+
checkMissingTypehints: %checkMissingTypehints%
920921

921922
-
922923
class: PHPStan\Rules\Generics\GenericObjectTypeCheck

src/Rules/Generics/GenericAncestorsCheck.php

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public function __construct(
3434
private VarianceCheck $varianceCheck,
3535
private UnresolvableTypeHelper $unresolvableTypeHelper,
3636
private array $skipCheckGenericClasses,
37+
private bool $checkMissingTypehints,
3738
)
3839
{
3940
}
@@ -151,26 +152,28 @@ public function check(
151152
}
152153
}
153154

154-
foreach (array_keys($unusedNames) as $unusedName) {
155-
if (!$this->reflectionProvider->hasClass($unusedName)) {
156-
continue;
157-
}
155+
if ($this->checkMissingTypehints) {
156+
foreach (array_keys($unusedNames) as $unusedName) {
157+
if (!$this->reflectionProvider->hasClass($unusedName)) {
158+
continue;
159+
}
158160

159-
$unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName);
160-
if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) {
161-
continue;
162-
}
163-
if (!$unusedNameClassReflection->isGeneric()) {
164-
continue;
165-
}
161+
$unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName);
162+
if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) {
163+
continue;
164+
}
165+
if (!$unusedNameClassReflection->isGeneric()) {
166+
continue;
167+
}
166168

167-
$messages[] = RuleErrorBuilder::message(sprintf(
168-
$genericClassInNonGenericObjectType,
169-
$unusedName,
170-
implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())),
171-
))
172-
->identifier('missingType.generics')
173-
->build();
169+
$messages[] = RuleErrorBuilder::message(sprintf(
170+
$genericClassInNonGenericObjectType,
171+
$unusedName,
172+
implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())),
173+
))
174+
->identifier('missingType.generics')
175+
->build();
176+
}
174177
}
175178

176179
return $messages;

src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ public function processNode(Node $node, Scope $scope): array
9797
->identifier('missingType.iterableValue')
9898
->build();
9999
}
100+
101+
foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($varTagType) as [$innerName, $genericTypeNames]) {
102+
$errors[] = RuleErrorBuilder::message(sprintf(
103+
'%s contains generic %s but does not specify its types: %s',
104+
$identifier,
105+
$innerName,
106+
implode(', ', $genericTypeNames),
107+
))
108+
->identifier('missingType.generics')
109+
->build();
110+
}
100111
}
101112

102113
$escapedIdentifier = SprintfHelper::escapeFormatString($identifier);
@@ -110,17 +121,6 @@ public function processNode(Node $node, Scope $scope): array
110121
sprintf('Call-site variance of %%s in generic type %%s in %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedIdentifier),
111122
));
112123

113-
foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($varTagType) as [$innerName, $genericTypeNames]) {
114-
$errors[] = RuleErrorBuilder::message(sprintf(
115-
'%s contains generic %s but does not specify its types: %s',
116-
$identifier,
117-
$innerName,
118-
implode(', ', $genericTypeNames),
119-
))
120-
->identifier('missingType.generics')
121-
->build();
122-
}
123-
124124
$referencedClasses = $varTagType->getReferencedClasses();
125125
foreach ($referencedClasses as $referencedClass) {
126126
if ($this->reflectionProvider->hasClass($referencedClass)) {

tests/PHPStan/Levels/LevelsIntegrationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function dataTopics(): array
4141
['coalesce'],
4242
['arrayDestructuring'],
4343
['listType'],
44+
['missingTypes'],
4445
];
4546
if (PHP_VERSION_ID >= 80300) {
4647
$topics[] = ['constantAccesses83'];
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"message": "Class MissingTypesLevels\\Foo extends generic class MissingTypesLevels\\Generic but does not specify its types: T",
4+
"line": 13,
5+
"ignorable": true
6+
}
7+
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace MissingTypesLevels;
4+
5+
/**
6+
* @template T
7+
*/
8+
class Generic
9+
{
10+
11+
}
12+
13+
class Foo extends Generic
14+
{
15+
16+
}

tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ protected function getRule(): Rule
2121
new VarianceCheck(),
2222
new UnresolvableTypeHelper(),
2323
[],
24+
true,
2425
),
2526
new CrossCheckInterfacesHelper(),
2627
);

tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ protected function getRule(): Rule
2222
new VarianceCheck(),
2323
new UnresolvableTypeHelper(),
2424
[],
25+
true,
2526
),
2627
new CrossCheckInterfacesHelper(),
2728
);

tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ protected function getRule(): Rule
2121
new VarianceCheck(),
2222
new UnresolvableTypeHelper(),
2323
[],
24+
true,
2425
),
2526
new CrossCheckInterfacesHelper(),
2627
);

tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ protected function getRule(): Rule
2323
new VarianceCheck(),
2424
new UnresolvableTypeHelper(),
2525
[],
26+
true,
2627
),
2728
);
2829
}

0 commit comments

Comments
 (0)