Skip to content

Commit fd71add

Browse files
committed
Use ParentMethodHelper and separate error identifiers
1 parent 5abc4b4 commit fd71add

2 files changed

Lines changed: 31 additions & 45 deletions

File tree

src/Rules/PhpDoc/InvalidInheritDocTagRule.php

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use PHPStan\PhpDocParser\Lexer\Lexer;
1010
use PHPStan\PhpDocParser\Parser\PhpDocParser;
1111
use PHPStan\PhpDocParser\Parser\TokenIterator;
12-
use PHPStan\Reflection\ClassReflection;
12+
use PHPStan\Rules\Methods\ParentMethodHelper;
1313
use PHPStan\Rules\Rule;
1414
use PHPStan\Rules\RuleErrorBuilder;
1515
use function preg_match;
@@ -27,6 +27,7 @@ final class InvalidInheritDocTagRule implements Rule
2727
public function __construct(
2828
private Lexer $phpDocLexer,
2929
private PhpDocParser $phpDocParser,
30+
private ParentMethodHelper $parentMethodHelper,
3031
)
3132
{
3233
}
@@ -78,8 +79,23 @@ public function processNode(Node $node, Scope $scope): array
7879
$inheritanceClass = $scope->isInTrait() ? $scope->getTraitReflection() : $node->getClassReflection();
7980
$methodName = $node->getMethodReflection()->getName();
8081

81-
if ($this->hasInheritablePhpDoc($inheritanceClass, $methodName)) {
82-
return [];
82+
$parentMethods = $this->parentMethodHelper->collectParentMethods($methodName, $inheritanceClass);
83+
84+
if ($parentMethods === []) {
85+
return [
86+
RuleErrorBuilder::message(sprintf(
87+
'PHPDoc tag %s on method %s::%s() does not override or implement any other method.',
88+
$inheritDocTagName,
89+
$inheritanceClass->getDisplayName(),
90+
$methodName,
91+
))->identifier('inheritDoc.noParent')->build(),
92+
];
93+
}
94+
95+
foreach ($parentMethods as [$parentMethod]) {
96+
if ($parentMethod->getResolvedPhpDoc() !== null) {
97+
return [];
98+
}
8399
}
84100

85101
return [
@@ -88,44 +104,8 @@ public function processNode(Node $node, Scope $scope): array
88104
$inheritDocTagName,
89105
$inheritanceClass->getDisplayName(),
90106
$methodName,
91-
))->identifier('phpDoc.invalidInheritDoc')->build(),
107+
))->identifier('inheritDoc.parentWithoutPhpDoc')->build(),
92108
];
93109
}
94110

95-
private function hasInheritablePhpDoc(ClassReflection $classReflection, string $methodName): bool
96-
{
97-
$parent = $classReflection->getParentClass();
98-
if ($parent !== null && $this->parentHasPhpDocForMethod($parent, $methodName)) {
99-
return true;
100-
}
101-
102-
foreach ($classReflection->getImmediateInterfaces() as $interface) {
103-
if ($this->parentHasPhpDocForMethod($interface, $methodName)) {
104-
return true;
105-
}
106-
}
107-
108-
foreach ($classReflection->getTraits() as $trait) {
109-
if ($this->parentHasPhpDocForMethod($trait, $methodName)) {
110-
return true;
111-
}
112-
}
113-
114-
return false;
115-
}
116-
117-
private function parentHasPhpDocForMethod(ClassReflection $parent, string $methodName): bool
118-
{
119-
if (!$parent->hasNativeMethod($methodName)) {
120-
return false;
121-
}
122-
123-
$parentMethod = $parent->getNativeMethod($methodName);
124-
if ($parentMethod->isPrivate()) {
125-
return false;
126-
}
127-
128-
return $parentMethod->getResolvedPhpDoc() !== null;
129-
}
130-
131111
}

tests/PHPStan/Rules/PhpDoc/InvalidInheritDocTagRuleTest.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\PhpDocParser\Lexer\Lexer;
66
use PHPStan\PhpDocParser\Parser\PhpDocParser;
7+
use PHPStan\Rules\Methods\ParentMethodHelper;
78
use PHPStan\Rules\Rule;
89
use PHPStan\Testing\RuleTestCase;
910

@@ -18,6 +19,7 @@ protected function getRule(): Rule
1819
return new InvalidInheritDocTagRule(
1920
self::getContainer()->getByType(Lexer::class),
2021
self::getContainer()->getByType(PhpDocParser::class),
22+
self::getContainer()->getByType(ParentMethodHelper::class),
2123
);
2224
}
2325

@@ -33,31 +35,35 @@ public function testRule(): void
3335
52,
3436
],
3537
[
36-
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\ClassWithoutParent::orphanedInheritDoc() refers to a parent method that does not have a PHPDoc.',
38+
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\ClassWithoutParent::orphanedInheritDoc() does not override or implement any other method.',
3739
73,
3840
],
3941
[
40-
'PHPDoc tag @inheritdoc on method InvalidInheritDocTag\ClassWithoutParent::orphanedBlockInheritDoc() refers to a parent method that does not have a PHPDoc.',
42+
'PHPDoc tag @inheritdoc on method InvalidInheritDocTag\ClassWithoutParent::orphanedBlockInheritDoc() does not override or implement any other method.',
4143
81,
4244
],
4345
[
4446
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\ImplementsInterface::interfaceMethodWithoutPhpDoc() refers to a parent method that does not have a PHPDoc.',
4547
106,
4648
],
4749
[
48-
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\UsesTraitWithoutPhpDoc::traitMethodWithoutPhpDoc() refers to a parent method that does not have a PHPDoc.',
50+
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\UsesTraitWithoutPhpDoc::traitMethodWithoutPhpDoc() does not override or implement any other method.',
4951
216,
5052
],
53+
[
54+
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\UsesTraitWithPhpDoc::traitMethodWithPhpDoc() does not override or implement any other method.',
55+
231,
56+
],
5157
[
5258
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\IssueExampleChild::f() refers to a parent method that does not have a PHPDoc.',
5359
254,
5460
],
5561
[
56-
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\ChildOfPrivateParentMethod::privateMethod() refers to a parent method that does not have a PHPDoc.',
62+
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\ChildOfPrivateParentMethod::privateMethod() does not override or implement any other method.',
5763
280,
5864
],
5965
[
60-
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\OrphanedInheritDocTrait::orphaned() refers to a parent method that does not have a PHPDoc.',
66+
'PHPDoc tag {@inheritdoc} on method InvalidInheritDocTag\OrphanedInheritDocTrait::orphaned() does not override or implement any other method.',
6167
293,
6268
],
6369
]);

0 commit comments

Comments
 (0)