Skip to content

Commit

Permalink
InvalidThrowsPhpDocValueRule - do not report inherited PHPDocs
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 10, 2020
1 parent 5d64483 commit b803293
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/PhpDoc/StubValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ private function getRuleRegistry(Container $container): Registry
$container->getByType(Lexer::class),
$container->getByType(PhpDocParser::class)
),
new InvalidThrowsPhpDocValueRule(),
new InvalidThrowsPhpDocValueRule($fileTypeMapper),

// level 6
new MissingFunctionParameterTypehintRule($reflectionProvider, $missingTypehintCheck),
Expand Down
54 changes: 30 additions & 24 deletions src/Rules/PhpDoc/InvalidThrowsPhpDocValueRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,71 @@

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Node\InFunctionNode;
use PHPStan\Node\VirtualNode;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use PHPStan\Type\VoidType;

/**
* @implements \PHPStan\Rules\Rule<VirtualNode>
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\FunctionLike>
*/
class InvalidThrowsPhpDocValueRule implements \PHPStan\Rules\Rule
{

/** @var FileTypeMapper */
private $fileTypeMapper;

public function __construct(FileTypeMapper $fileTypeMapper)
{
$this->fileTypeMapper = $fileTypeMapper;
}

public function getNodeType(): string
{
return VirtualNode::class;
return \PhpParser\Node\FunctionLike::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!$node instanceof InFunctionNode && !$node instanceof InClassMethodNode) {
$docComment = $node->getDocComment();
if ($docComment === null) {
return [];
}

if ($scope->getFunction() === null) {
throw new \PHPStan\ShouldNotHappenException();
$functionName = null;
if ($node instanceof Node\Stmt\ClassMethod) {
$functionName = $node->name->name;
} elseif ($node instanceof Node\Stmt\Function_) {
$functionName = trim($scope->getNamespace() . '\\' . $node->name->name, '\\');
}

$throwType = $scope->getFunction()->getThrowType();
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
$scope->getFile(),
$scope->isInClass() ? $scope->getClassReflection()->getName() : null,
$scope->isInTrait() ? $scope->getTraitReflection()->getName() : null,
$functionName,
$docComment->getText()
);

return $this->check($throwType);
}

/**
* @param Type|null $phpDocThrowType
* @return array<int, RuleError> errors
*/
private function check(?Type $phpDocThrowType): array
{
if ($phpDocThrowType === null) {
if ($resolvedPhpDoc->getThrowsTag() === null) {
return [];
}

if ((new VoidType())->isSuperTypeOf($phpDocThrowType)->yes()) {
$phpDocThrowsType = $resolvedPhpDoc->getThrowsTag()->getType();
if ((new VoidType())->isSuperTypeOf($phpDocThrowsType)->yes()) {
return [];
}

$isThrowsSuperType = (new ObjectType(\Throwable::class))->isSuperTypeOf($phpDocThrowType);
$isThrowsSuperType = (new ObjectType(\Throwable::class))->isSuperTypeOf($phpDocThrowsType);
if ($isThrowsSuperType->yes()) {
return [];
}

return [
RuleErrorBuilder::message(sprintf(
'PHPDoc tag @throws with type %s is not subtype of Throwable',
$phpDocThrowType->describe(VerbosityLevel::typeOnly())
$phpDocThrowsType->describe(VerbosityLevel::typeOnly())
))->build(),
];
}
Expand Down
14 changes: 4 additions & 10 deletions tests/PHPStan/Rules/PhpDoc/InvalidThrowsPhpDocValueRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace PHPStan\Rules\PhpDoc;

use PHPStan\Type\FileTypeMapper;

/**
* @extends \PHPStan\Testing\RuleTestCase<InvalidThrowsPhpDocValueRule>
*/
Expand All @@ -10,7 +12,7 @@ class InvalidThrowsPhpDocValueRuleTest extends \PHPStan\Testing\RuleTestCase

protected function getRule(): \PHPStan\Rules\Rule
{
return new InvalidThrowsPhpDocValueRule();
return new InvalidThrowsPhpDocValueRule(self::getContainer()->getByType(FileTypeMapper::class));
}

public function testRule(): void
Expand Down Expand Up @@ -47,7 +49,7 @@ public function testRule(): void
]);
}

public function testMergeInheritedPhpDocs(): void
public function testInheritedPhpDocs(): void
{
$this->analyse([__DIR__ . '/data/merge-inherited-throws.php'], [
[
Expand All @@ -62,14 +64,6 @@ public function testMergeInheritedPhpDocs(): void
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
28,
],
[
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
34,
],
[
'PHPDoc tag @throws with type InvalidThrowsPhpDocMergeInherited\C|InvalidThrowsPhpDocMergeInherited\D is not subtype of Throwable',
39,
],
]);
}

Expand Down

0 comments on commit b803293

Please sign in to comment.