Skip to content

Commit b803293

Browse files
committed
InvalidThrowsPhpDocValueRule - do not report inherited PHPDocs
1 parent 5d64483 commit b803293

3 files changed

Lines changed: 35 additions & 35 deletions

File tree

src/PhpDoc/StubValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private function getRuleRegistry(Container $container): Registry
146146
$container->getByType(Lexer::class),
147147
$container->getByType(PhpDocParser::class)
148148
),
149-
new InvalidThrowsPhpDocValueRule(),
149+
new InvalidThrowsPhpDocValueRule($fileTypeMapper),
150150

151151
// level 6
152152
new MissingFunctionParameterTypehintRule($reflectionProvider, $missingTypehintCheck),

src/Rules/PhpDoc/InvalidThrowsPhpDocValueRule.php

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,71 @@
44

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7-
use PHPStan\Node\InClassMethodNode;
8-
use PHPStan\Node\InFunctionNode;
9-
use PHPStan\Node\VirtualNode;
10-
use PHPStan\Rules\RuleError;
117
use PHPStan\Rules\RuleErrorBuilder;
8+
use PHPStan\Type\FileTypeMapper;
129
use PHPStan\Type\ObjectType;
13-
use PHPStan\Type\Type;
1410
use PHPStan\Type\VerbosityLevel;
1511
use PHPStan\Type\VoidType;
1612

1713
/**
18-
* @implements \PHPStan\Rules\Rule<VirtualNode>
14+
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\FunctionLike>
1915
*/
2016
class InvalidThrowsPhpDocValueRule implements \PHPStan\Rules\Rule
2117
{
2218

19+
/** @var FileTypeMapper */
20+
private $fileTypeMapper;
21+
22+
public function __construct(FileTypeMapper $fileTypeMapper)
23+
{
24+
$this->fileTypeMapper = $fileTypeMapper;
25+
}
26+
2327
public function getNodeType(): string
2428
{
25-
return VirtualNode::class;
29+
return \PhpParser\Node\FunctionLike::class;
2630
}
2731

2832
public function processNode(Node $node, Scope $scope): array
2933
{
30-
if (!$node instanceof InFunctionNode && !$node instanceof InClassMethodNode) {
34+
$docComment = $node->getDocComment();
35+
if ($docComment === null) {
3136
return [];
3237
}
3338

34-
if ($scope->getFunction() === null) {
35-
throw new \PHPStan\ShouldNotHappenException();
39+
$functionName = null;
40+
if ($node instanceof Node\Stmt\ClassMethod) {
41+
$functionName = $node->name->name;
42+
} elseif ($node instanceof Node\Stmt\Function_) {
43+
$functionName = trim($scope->getNamespace() . '\\' . $node->name->name, '\\');
3644
}
3745

38-
$throwType = $scope->getFunction()->getThrowType();
46+
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
47+
$scope->getFile(),
48+
$scope->isInClass() ? $scope->getClassReflection()->getName() : null,
49+
$scope->isInTrait() ? $scope->getTraitReflection()->getName() : null,
50+
$functionName,
51+
$docComment->getText()
52+
);
3953

40-
return $this->check($throwType);
41-
}
42-
43-
/**
44-
* @param Type|null $phpDocThrowType
45-
* @return array<int, RuleError> errors
46-
*/
47-
private function check(?Type $phpDocThrowType): array
48-
{
49-
if ($phpDocThrowType === null) {
54+
if ($resolvedPhpDoc->getThrowsTag() === null) {
5055
return [];
5156
}
5257

53-
if ((new VoidType())->isSuperTypeOf($phpDocThrowType)->yes()) {
58+
$phpDocThrowsType = $resolvedPhpDoc->getThrowsTag()->getType();
59+
if ((new VoidType())->isSuperTypeOf($phpDocThrowsType)->yes()) {
5460
return [];
5561
}
5662

57-
$isThrowsSuperType = (new ObjectType(\Throwable::class))->isSuperTypeOf($phpDocThrowType);
63+
$isThrowsSuperType = (new ObjectType(\Throwable::class))->isSuperTypeOf($phpDocThrowsType);
5864
if ($isThrowsSuperType->yes()) {
5965
return [];
6066
}
6167

6268
return [
6369
RuleErrorBuilder::message(sprintf(
6470
'PHPDoc tag @throws with type %s is not subtype of Throwable',
65-
$phpDocThrowType->describe(VerbosityLevel::typeOnly())
71+
$phpDocThrowsType->describe(VerbosityLevel::typeOnly())
6672
))->build(),
6773
];
6874
}

tests/PHPStan/Rules/PhpDoc/InvalidThrowsPhpDocValueRuleTest.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace PHPStan\Rules\PhpDoc;
44

5+
use PHPStan\Type\FileTypeMapper;
6+
57
/**
68
* @extends \PHPStan\Testing\RuleTestCase<InvalidThrowsPhpDocValueRule>
79
*/
@@ -10,7 +12,7 @@ class InvalidThrowsPhpDocValueRuleTest extends \PHPStan\Testing\RuleTestCase
1012

1113
protected function getRule(): \PHPStan\Rules\Rule
1214
{
13-
return new InvalidThrowsPhpDocValueRule();
15+
return new InvalidThrowsPhpDocValueRule(self::getContainer()->getByType(FileTypeMapper::class));
1416
}
1517

1618
public function testRule(): void
@@ -47,7 +49,7 @@ public function testRule(): void
4749
]);
4850
}
4951

50-
public function testMergeInheritedPhpDocs(): void
52+
public function testInheritedPhpDocs(): void
5153
{
5254
$this->analyse([__DIR__ . '/data/merge-inherited-throws.php'], [
5355
[
@@ -62,14 +64,6 @@ public function testMergeInheritedPhpDocs(): void
6264
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
6365
28,
6466
],
65-
[
66-
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
67-
34,
68-
],
69-
[
70-
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
71-
39,
72-
],
7367
]);
7468
}
7569

0 commit comments

Comments
 (0)