Skip to content

Commit 41fcb7d

Browse files
committed
Added support for ConstantString unions in RequireExtendsRule
1 parent 4f2408e commit 41fcb7d

File tree

3 files changed

+72
-31
lines changed

3 files changed

+72
-31
lines changed

src/Rules/Classes/RequireExtendsRule.php

+34-31
Original file line numberDiff line numberDiff line change
@@ -35,46 +35,49 @@ public function processNode(Node $node, Scope $scope): array
3535
$extendsTags = $interface->getRequireExtendsTags();
3636
foreach ($extendsTags as $extendsTag) {
3737
$type = $extendsTag->getType();
38-
$classNames = $type->getObjectClassNames();
39-
if (count($classNames) === 1 && $classReflection->is($classNames[0])) {
40-
continue;
41-
}
38+
foreach ($type->getObjectClassNames() as $className) {
39+
if ($classReflection->is($className)) {
40+
continue;
41+
}
42+
43+
$errors[] = RuleErrorBuilder::message(
44+
sprintf(
45+
'Interface %s requires implementing class to extend %s, but %s does not.',
46+
$interface->getDisplayName(),
47+
$type->describe(VerbosityLevel::typeOnly()),
48+
$classReflection->getDisplayName(),
49+
),
50+
)
51+
->identifier('class.missingExtends')
52+
->build();
4253

43-
$errors[] = RuleErrorBuilder::message(
44-
sprintf(
45-
'Interface %s requires implementing class to extend %s, but %s does not.',
46-
$interface->getDisplayName(),
47-
$type->describe(VerbosityLevel::typeOnly()),
48-
$classReflection->getDisplayName(),
49-
),
50-
)
51-
->identifier('class.missingExtends')
52-
->build();
54+
break;
55+
}
5356
}
5457
}
5558

5659
foreach ($classReflection->getTraits(true) as $trait) {
5760
$extendsTags = $trait->getRequireExtendsTags();
5861
foreach ($extendsTags as $extendsTag) {
5962
$type = $extendsTag->getType();
60-
$classNames = $type->getObjectClassNames();
61-
if (count($classNames) === 0) {
62-
continue;
63-
}
64-
if (count($classNames) === 1 && $classReflection->is($classNames[0])) {
65-
continue;
66-
}
63+
foreach ($type->getObjectClassNames() as $className) {
64+
if ($classReflection->is($className)) {
65+
continue;
66+
}
67+
68+
$errors[] = RuleErrorBuilder::message(
69+
sprintf(
70+
'Trait %s requires using class to extend %s, but %s does not.',
71+
$trait->getDisplayName(),
72+
$type->describe(VerbosityLevel::typeOnly()),
73+
$classReflection->getDisplayName(),
74+
),
75+
)
76+
->identifier('class.missingExtends')
77+
->build();
6778

68-
$errors[] = RuleErrorBuilder::message(
69-
sprintf(
70-
'Trait %s requires using class to extend %s, but %s does not.',
71-
$trait->getDisplayName(),
72-
$type->describe(VerbosityLevel::typeOnly()),
73-
$classReflection->getDisplayName(),
74-
),
75-
)
76-
->identifier('class.missingExtends')
77-
->build();
79+
break;
80+
}
7881
}
7982
}
8083

tests/PHPStan/Rules/Classes/RequireExtendsRuleTest.php

+16
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ public function testRule(): void
5252
'Trait IncompatibleRequireExtends\ValidPsalmTrait requires using class to extend IncompatibleRequireExtends\SomeClass, but class@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-extends.php:163 does not.',
5353
163,
5454
],
55+
[
56+
'Interface IncompatibleRequireExtends\RequireNonExisstentUnionClassinterface requires implementing class to extend IncompatibleRequireExtends\NonExistentClass|IncompatibleRequireExtends\SomeClass, but IncompatibleRequireExtends\RequireNonExisstentUnionClassinterface@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-extends.php:185 does not.',
57+
185,
58+
],
59+
[
60+
'Interface IncompatibleRequireExtends\RequireNonExisstentUnionClassinterface requires implementing class to extend IncompatibleRequireExtends\NonExistentClass|IncompatibleRequireExtends\SomeClass, but IncompatibleRequireExtends\SomeClass@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-extends.php:187 does not.',
61+
187,
62+
],
63+
[
64+
'Trait IncompatibleRequireExtends\RequireNonExisstentUnionClassTrait requires using class to extend IncompatibleRequireExtends\NonExistentClass|IncompatibleRequireExtends\SomeClass, but class@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-extends.php:194 does not.',
65+
194,
66+
],
67+
[
68+
'Trait IncompatibleRequireExtends\RequireNonExisstentUnionClassTrait requires using class to extend IncompatibleRequireExtends\NonExistentClass|IncompatibleRequireExtends\SomeClass, but IncompatibleRequireExtends\SomeClass@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-extends.php:198 does not.',
69+
198,
70+
],
5571
];
5672

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

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

+22
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,25 @@ trait TooMuchExtends {}
176176
* @phpstan-require-extends SomeOtherClass
177177
*/
178178
interface TooMuchExtendsIface {}
179+
180+
/**
181+
* @phpstan-require-extends SomeClass|NonExistentClass
182+
*/
183+
interface RequireNonExisstentUnionClassinterface {}
184+
185+
new class implements RequireNonExisstentUnionClassinterface {};
186+
187+
new class extends SomeClass implements RequireNonExisstentUnionClassinterface {};
188+
189+
/**
190+
* @phpstan-require-extends SomeClass|NonExistentClass
191+
*/
192+
trait RequireNonExisstentUnionClassTrait {}
193+
194+
new class {
195+
use RequireNonExisstentUnionClassTrait;
196+
};
197+
198+
new class extends SomeClass {
199+
use RequireNonExisstentUnionClassTrait;
200+
};

0 commit comments

Comments
 (0)