|
14 | 14 | use PHPStan\Type\Type;
|
15 | 15 | use PHPStan\Type\TypeTraverser;
|
16 | 16 | use PHPStan\Type\VerbosityLevel;
|
| 17 | +use function array_filter; |
17 | 18 | use function array_keys;
|
18 | 19 | use function array_values;
|
19 | 20 | use function count;
|
@@ -59,27 +60,37 @@ public function check(
|
59 | 60 | $genericTypeVariances = $genericType->getVariances();
|
60 | 61 | $templateTypesCount = count($templateTypes);
|
61 | 62 | $genericTypeTypesCount = count($genericTypeTypes);
|
62 |
| - if ($templateTypesCount > $genericTypeTypesCount) { |
| 63 | + $requiredTemplateTypesCount = count(array_filter($templateTypes, static fn (Type $type) => $type instanceof TemplateType && $type->getDefault() === null)); |
| 64 | + if ($requiredTemplateTypesCount > $genericTypeTypesCount) { |
| 65 | + $templateTypesList = implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())); |
| 66 | + if ($requiredTemplateTypesCount !== $templateTypesCount) { |
| 67 | + $templateTypesList .= sprintf(' (%d-%d required).', $requiredTemplateTypesCount, $templateTypesCount); |
| 68 | + } |
| 69 | + |
63 | 70 | $messages[] = RuleErrorBuilder::message(sprintf(
|
64 | 71 | $notEnoughTypesMessage,
|
65 | 72 | $genericType->describe(VerbosityLevel::typeOnly()),
|
66 | 73 | $classLikeDescription,
|
67 | 74 | $classReflection->getDisplayName(false),
|
68 |
| - implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())), |
| 75 | + $templateTypesList, |
69 | 76 | ))->identifier('generics.lessTypes')->build();
|
70 | 77 | } elseif ($templateTypesCount < $genericTypeTypesCount) {
|
| 78 | + $templateTypesList = implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())); |
| 79 | + if ($requiredTemplateTypesCount !== $templateTypesCount) { |
| 80 | + $templateTypesList .= sprintf(' (%d-%d required)', $requiredTemplateTypesCount, $templateTypesCount); |
| 81 | + } |
| 82 | + |
71 | 83 | $messages[] = RuleErrorBuilder::message(sprintf(
|
72 | 84 | $extraTypesMessage,
|
73 | 85 | $genericType->describe(VerbosityLevel::typeOnly()),
|
74 | 86 | $genericTypeTypesCount,
|
75 | 87 | $classLikeDescription,
|
76 | 88 | $classReflection->getDisplayName(false),
|
77 | 89 | $templateTypesCount,
|
78 |
| - implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())), |
| 90 | + $templateTypesList, |
79 | 91 | ))->identifier('generics.moreTypes')->build();
|
80 | 92 | }
|
81 | 93 |
|
82 |
| - $templateTypesCount = count($templateTypes); |
83 | 94 | for ($i = 0; $i < $templateTypesCount; $i++) {
|
84 | 95 | if (!isset($genericTypeTypes[$i])) {
|
85 | 96 | continue;
|
|
0 commit comments