Skip to content

Commit 1eead47

Browse files
Fix UnionType::getObjectClassReflections
1 parent 5adafcb commit 1eead47

9 files changed

+38
-36
lines changed

src/Rules/PhpDoc/RequireExtendsCheck.php

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77
use PHPStan\DependencyInjection\AutowiredParameter;
88
use PHPStan\DependencyInjection\AutowiredService;
99
use PHPStan\PhpDoc\Tag\RequireExtendsTag;
10+
use PHPStan\Reflection\ReflectionProvider;
1011
use PHPStan\Rules\ClassNameCheck;
1112
use PHPStan\Rules\ClassNameNodePair;
1213
use PHPStan\Rules\ClassNameUsageLocation;
1314
use PHPStan\Rules\IdentifierRuleError;
1415
use PHPStan\Rules\RuleErrorBuilder;
1516
use PHPStan\Type\VerbosityLevel;
16-
use function array_column;
17-
use function array_map;
1817
use function array_merge;
1918
use function count;
20-
use function sort;
2119
use function sprintf;
2220
use function strtolower;
2321

@@ -26,6 +24,7 @@ final class RequireExtendsCheck
2624
{
2725

2826
public function __construct(
27+
private ReflectionProvider $reflectionProvider,
2928
private ClassNameCheck $classCheck,
3029
#[AutowiredParameter]
3130
private bool $checkClassCaseSensitivity,
@@ -59,12 +58,8 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
5958
continue;
6059
}
6160

62-
sort($classNames);
63-
$referencedClassReflections = array_map(static fn ($reflection) => [$reflection, $reflection->getName()], $type->getObjectClassReflections());
64-
$referencedClassReflectionsMap = array_column($referencedClassReflections, 0, 1);
6561
foreach ($classNames as $class) {
66-
$referencedClassReflection = $referencedClassReflectionsMap[$class] ?? null;
67-
if ($referencedClassReflection === null) {
62+
if (!$this->reflectionProvider->hasClass($class)) {
6863
$errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains unknown class %s.', $class))
6964
->identifier('class.notFound');
7065

@@ -76,16 +71,17 @@ public function checkExtendsTags(Scope $scope, Node $node, array $extendsTags):
7671
continue;
7772
}
7873

79-
if ($referencedClassReflection->isInterface()) {
74+
$reflection = $this->reflectionProvider->getClass($class);
75+
if ($reflection->isInterface()) {
8076
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain an interface %s, expected a class.', $class))
8177
->tip('If you meant an interface, use @phpstan-require-implements instead.')
8278
->identifier('requireExtends.interface')
8379
->build();
84-
} elseif (!$referencedClassReflection->isClass()) {
80+
} elseif (!$reflection->isClass()) {
8581
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain non-class type %s.', $class))
86-
->identifier(sprintf('requireExtends.%s', strtolower($referencedClassReflection->getClassTypeDescription())))
82+
->identifier(sprintf('requireExtends.%s', strtolower($reflection->getClassTypeDescription())))
8783
->build();
88-
} elseif ($referencedClassReflection->isFinal()) {
84+
} elseif ($reflection->isFinal()) {
8985
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain final class %s.', $class))
9086
->identifier('requireExtends.finalClass')
9187
->build();

src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
use PHPStan\Rules\Rule;
1414
use PHPStan\Rules\RuleErrorBuilder;
1515
use PHPStan\Type\VerbosityLevel;
16-
use function array_column;
17-
use function array_map;
1816
use function array_merge;
1917
use function count;
2018
use function sprintf;
@@ -66,11 +64,8 @@ public function processNode(Node $node, Scope $scope): array
6664
continue;
6765
}
6866

69-
$referencedClassReflections = array_map(static fn ($reflection) => [$reflection, $reflection->getName()], $type->getObjectClassReflections());
70-
$referencedClassReflectionsMap = array_column($referencedClassReflections, 0, 1);
7167
foreach ($classNames as $class) {
72-
$referencedClassReflection = $referencedClassReflectionsMap[$class] ?? null;
73-
if ($referencedClassReflection === null) {
68+
if (!$this->reflectionProvider->hasClass($class)) {
7469
$errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class))
7570
->identifier('class.notFound');
7671

@@ -82,9 +77,10 @@ public function processNode(Node $node, Scope $scope): array
8277
continue;
8378
}
8479

85-
if (!$referencedClassReflection->isInterface()) {
80+
$reflection = $this->reflectionProvider->getClass($class);
81+
if (!$reflection->isInterface()) {
8682
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements cannot contain non-interface type %s.', $class))
87-
->identifier(sprintf('requireImplements.%s', strtolower($referencedClassReflection->getClassTypeDescription())))
83+
->identifier(sprintf('requireImplements.%s', strtolower($reflection->getClassTypeDescription())))
8884
->build();
8985
} else {
9086
$errors = array_merge(

src/Rules/PhpDoc/SealedDefinitionClassRule.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
use PHPStan\DependencyInjection\AutowiredParameter;
88
use PHPStan\DependencyInjection\RegisteredRule;
99
use PHPStan\Node\InClassNode;
10+
use PHPStan\Reflection\ReflectionProvider;
1011
use PHPStan\Rules\ClassNameCheck;
1112
use PHPStan\Rules\ClassNameNodePair;
1213
use PHPStan\Rules\ClassNameUsageLocation;
1314
use PHPStan\Rules\Rule;
1415
use PHPStan\Rules\RuleErrorBuilder;
1516
use PHPStan\Type\VerbosityLevel;
16-
use function array_column;
17-
use function array_map;
1817
use function array_merge;
1918
use function count;
2019
use function sprintf;
@@ -27,6 +26,7 @@ final class SealedDefinitionClassRule implements Rule
2726
{
2827

2928
public function __construct(
29+
private ReflectionProvider $reflectionProvider,
3030
private ClassNameCheck $classCheck,
3131
#[AutowiredParameter]
3232
private bool $checkClassCaseSensitivity,
@@ -69,11 +69,8 @@ public function processNode(Node $node, Scope $scope): array
6969
continue;
7070
}
7171

72-
$referencedClassReflections = array_map(static fn ($reflection) => [$reflection, $reflection->getName()], $type->getObjectClassReflections());
73-
$referencedClassReflectionsMap = array_column($referencedClassReflections, 0, 1);
7472
foreach ($classNames as $class) {
75-
$referencedClassReflection = $referencedClassReflectionsMap[$class] ?? null;
76-
if ($referencedClassReflection === null) {
73+
if (!$this->reflectionProvider->hasClass($class)) {
7774
$errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-sealed contains unknown class %s.', $class))
7875
->identifier('class.notFound');
7976

tests/PHPStan/Rules/PhpDoc/RequireExtendsDefinitionClassRuleTest.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ protected function getRule(): Rule
2222
$container = self::getContainer();
2323
return new RequireExtendsDefinitionClassRule(
2424
new RequireExtendsCheck(
25+
$reflectionProvider,
2526
new ClassNameCheck(
2627
new ClassCaseSensitivityCheck($reflectionProvider, true),
2728
new ClassForbiddenNameCheck($container),
@@ -86,11 +87,6 @@ public function testRule(): void
8687
183,
8788
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
8889
],
89-
[
90-
'PHPDoc tag @phpstan-require-extends contains unknown class IncompatibleRequireExtends\SomeClass.',
91-
183,
92-
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
93-
],
9490
]);
9591
}
9692

tests/PHPStan/Rules/PhpDoc/RequireExtendsDefinitionTraitRuleTest.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ protected function getRule(): Rule
2323
return new RequireExtendsDefinitionTraitRule(
2424
$reflectionProvider,
2525
new RequireExtendsCheck(
26+
$reflectionProvider,
2627
new ClassNameCheck(
2728
new ClassCaseSensitivityCheck($reflectionProvider, true),
2829
new ClassForbiddenNameCheck($container),
@@ -56,11 +57,6 @@ public function testRule(): void
5657
192,
5758
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
5859
],
59-
[
60-
'PHPDoc tag @phpstan-require-extends contains unknown class IncompatibleRequireExtends\SomeClass.',
61-
192,
62-
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
63-
],
6460
]);
6561
}
6662

tests/PHPStan/Rules/PhpDoc/RequireImplementsDefinitionTraitRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ public function testRule(): void
6262
'PHPDoc tag @phpstan-require-implements contains non-object type *NEVER*.',
6363
34,
6464
],
65+
[
66+
'PHPDoc tag @phpstan-require-implements contains unknown class IncompatibleRequireImplements\TypeDoesNotExist.',
67+
175,
68+
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
69+
],
6570
];
6671

6772
$this->analyse([__DIR__ . '/data/incompatible-require-implements.php'], $expectedErrors);

tests/PHPStan/Rules/PhpDoc/SealedDefinitionClassRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ protected function getRule(): Rule
2121

2222
$container = self::getContainer();
2323
return new SealedDefinitionClassRule(
24+
$reflectionProvider,
2425
new ClassNameCheck(
2526
new ClassCaseSensitivityCheck($reflectionProvider, true),
2627
new ClassForbiddenNameCheck($container),
@@ -50,6 +51,11 @@ public function testRule(): void
5051
26,
5152
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
5253
],
54+
[
55+
'PHPDoc tag @phpstan-sealed contains unknown class IncompatibleSealed\UnknownClass.',
56+
46,
57+
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
58+
],
5359
]);
5460
}
5561

tests/PHPStan/Rules/PhpDoc/data/incompatible-require-implements.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,8 @@ trait ValidPsalmTrait {}
168168
new class {
169169
use ValidPsalmTrait;
170170
};
171+
172+
/**
173+
* @phpstan-require-implements RequiredInterface|TypeDoesNotExist
174+
*/
175+
trait InvalidTraitWithUnknown {}

tests/PHPStan/Rules/PhpDoc/data/incompatible-sealed.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ interface ValidInterface {}
3939
* @phpstan-sealed SomeInterface
4040
*/
4141
interface ValidInterface2 {}
42+
43+
/**
44+
* @phpstan-sealed UnknownClass|SomeClass
45+
*/
46+
class InvalidClassWithUnion {}

0 commit comments

Comments
 (0)