|
10 | 10 | use PHPStan\Rules\Rule;
|
11 | 11 | use PHPStan\Rules\RuleErrorBuilder;
|
12 | 12 | use PHPStan\Type\VerbosityLevel;
|
| 13 | +use function array_column; |
| 14 | +use function array_map; |
13 | 15 | use function array_merge;
|
14 | 16 | use function count;
|
15 | 17 | use function sprintf;
|
@@ -49,35 +51,38 @@ public function processNode(Node $node, Scope $scope): array
|
49 | 51 | $errors = [];
|
50 | 52 | foreach ($implementsTags as $implementsTag) {
|
51 | 53 | $type = $implementsTag->getType();
|
52 |
| - $classNames = $type->getObjectClassNames(); |
53 |
| - if (count($classNames) === 0) { |
| 54 | + if (count($type->getObjectClassNames()) === 0) { |
54 | 55 | $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))
|
55 | 56 | ->identifier('requireImplements.nonObject')
|
56 | 57 | ->build();
|
57 | 58 | continue;
|
58 | 59 | }
|
59 | 60 |
|
60 |
| - $class = $classNames[0]; |
61 |
| - $referencedClassReflection = $type->getObjectClassReflections()[0] ?? null; |
62 |
| - if ($referencedClassReflection === null) { |
63 |
| - $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class)) |
64 |
| - ->discoveringSymbolsTip() |
65 |
| - ->identifier('class.notFound') |
66 |
| - ->build(); |
67 |
| - continue; |
68 |
| - } |
| 61 | + $referencedClassReflections = array_map(static fn ($reflection) => [$reflection, $reflection->getName()], $type->getObjectClassReflections()); |
| 62 | + $referencedClassReflectionsMap = array_column($referencedClassReflections, 0, 1); |
| 63 | + foreach ($type->getObjectClassNames() as $class) { |
| 64 | + $referencedClassReflection = $referencedClassReflectionsMap[$class] ?? null; |
| 65 | + if ($referencedClassReflection === null) { |
| 66 | + $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class)) |
| 67 | + ->discoveringSymbolsTip() |
| 68 | + ->identifier('class.notFound') |
| 69 | + ->build(); |
| 70 | + continue; |
| 71 | + } |
| 72 | + |
| 73 | + if (!$referencedClassReflection->isInterface()) { |
| 74 | + $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements cannot contain non-interface type %s.', $class)) |
| 75 | + ->identifier(sprintf('requireImplements.%s', strtolower($referencedClassReflection->getClassTypeDescription()))) |
| 76 | + ->build(); |
| 77 | + } else { |
| 78 | + $errors = array_merge( |
| 79 | + $errors, |
| 80 | + $this->classCheck->checkClassNames([ |
| 81 | + new ClassNameNodePair($class, $node), |
| 82 | + ], $this->checkClassCaseSensitivity), |
| 83 | + ); |
| 84 | + } |
69 | 85 |
|
70 |
| - if (!$referencedClassReflection->isInterface()) { |
71 |
| - $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements cannot contain non-interface type %s.', $class)) |
72 |
| - ->identifier(sprintf('requireImplements.%s', strtolower($referencedClassReflection->getClassTypeDescription()))) |
73 |
| - ->build(); |
74 |
| - } else { |
75 |
| - $errors = array_merge( |
76 |
| - $errors, |
77 |
| - $this->classCheck->checkClassNames([ |
78 |
| - new ClassNameNodePair($class, $node), |
79 |
| - ], $this->checkClassCaseSensitivity), |
80 |
| - ); |
81 | 86 | }
|
82 | 87 | }
|
83 | 88 |
|
|
0 commit comments