Skip to content

Commit

Permalink
Merge pull request #3239 from rectorphp/docs-refactoring
Browse files Browse the repository at this point in the history
simplify throws class resolving
  • Loading branch information
kodiakhq[bot] authored Apr 23, 2020
2 parents 2bb9488 + c84f5c1 commit b1143d5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 103 deletions.
86 changes: 44 additions & 42 deletions packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
Expand All @@ -34,6 +33,8 @@
use Rector\Core\Exception\NotImplementedException;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\PHPStan\TypeComparator;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
use Rector\PHPStan\Type\ShortenedObjectType;
use Rector\StaticTypeMapper\StaticTypeMapper;
use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory;

Expand Down Expand Up @@ -165,51 +166,12 @@ public function getTagsByName(string $name): array
return array_values($tags);
}

/**
* @return AttributeAwareNodeInterface|TypeNode
*/
public function getParamTypeNode(string $paramName): ?TypeNode
{
$paramName = '$' . ltrim($paramName, '$');

foreach ($this->phpDocNode->getParamTagValues() as $paramTagsValue) {
if ($paramTagsValue->parameterName === $paramName) {
return $paramTagsValue->type;
}
}

return null;
}

public function getParamType(string $name): Type
{
$paramTagValue = $this->getParamTagValueByName($name);
return $this->getTypeOrMixed($paramTagValue);
}

/**
* @return Type[]
*/
public function getThrowsTypes(): array
{
$throwsPhpDocNodes = $this->getTagsByName('throws');

$throwsTypes = [];

foreach ($throwsPhpDocNodes as $throwsPhpDocNode) {
if (! $throwsPhpDocNode->value instanceof ThrowsTagValueNode) {
continue;
}

$throwsTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType(
$throwsPhpDocNode->value,
$this->node
);
}

return $throwsTypes;
}

/**
* @return Type[]
*/
Expand Down Expand Up @@ -305,14 +267,14 @@ public function removeByType(string $type): void
}
}

public function removeByName(string $nameToRemove): void
public function removeByName(string $name): void
{
foreach ($this->phpDocNode->children as $key => $phpDocChildNode) {
if (! $phpDocChildNode instanceof PhpDocTagNode) {
continue;
}

if (! $this->areAnnotationNamesEqual($nameToRemove, $phpDocChildNode->name)) {
if (! $this->areAnnotationNamesEqual($name, $phpDocChildNode->name)) {
continue;
}

Expand Down Expand Up @@ -428,6 +390,46 @@ public function changeParamType(Type $type, Param $param, string $paramName): vo
$this->addTagValueNode($paramTagValueNode);
}

/**
* @return string[]
*/
public function getThrowsClassNames(): array
{
$throwsClasses = [];
foreach ($this->getThrowsTypes() as $throwsType) {
if ($throwsType instanceof ShortenedObjectType) {
$throwsClasses[] = $throwsType->getFullyQualifiedName();
}

if ($throwsType instanceof FullyQualifiedObjectType) {
$throwsClasses[] = $throwsType->getClassName();
}
}

return $throwsClasses;
}

/**
* @return Type[]
*/
private function getThrowsTypes(): array
{
$throwsTypes = [];

foreach ($this->getTagsByName('throws') as $throwsPhpDocNode) {
if (! $throwsPhpDocNode->value instanceof ThrowsTagValueNode) {
continue;
}

$throwsTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType(
$throwsPhpDocNode->value,
$this->node
);
}

return $throwsTypes;
}

private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode)
{
if ($phpDocTagValueNode === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Stmt\Nop;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
use Rector\BetterPhpDocParser\Type\PreSlashStringType;
use Rector\Core\HttpKernel\RectorKernel;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\PHPStan\TypeFactoryStaticHelper;
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;

final class PhpDocInfoTest extends AbstractKernelTestCase
Expand Down Expand Up @@ -58,24 +54,6 @@ public function testGetTagsByName(): void
$this->assertCount(2, $paramTags);
}

public function testParamTypeNode(): void
{
$typeNode = $this->phpDocInfo->getParamTypeNode('value');
$this->assertInstanceOf(TypeNode::class, $typeNode);

$paramType = $this->phpDocInfo->getParamType('value');

$expectedUnionType = TypeFactoryStaticHelper::createUnionObjectType([
new ObjectType('SomeType'),
new ObjectType('NoSlash'),
new ObjectType('\Preslashed'),
new NullType(),
new PreSlashStringType(),
]);

$this->assertEquals($expectedUnionType, $paramType);
}

public function testGetVarType(): void
{
$expectedObjectType = new ObjectType('SomeType');
Expand Down
25 changes: 15 additions & 10 deletions rules/coding-style/src/Rector/Throw_/AnnotateThrowablesRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpDoc\PhpDocTagsFinder;
use Rector\Core\PhpParser\Node\Value\ClassResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
Expand Down Expand Up @@ -53,21 +53,14 @@ final class AnnotateThrowablesRector extends AbstractRector
*/
private $classResolver;

/**
* @var PhpDocTagsFinder
*/
private $phpDocTagsFinder;

public function __construct(
ClassMethodReflectionHelper $classMethodReflectionHelper,
ClassResolver $classResolver,
FunctionReflectionHelper $functionReflectionHelper,
PhpDocTagsFinder $phpDocTagsFinder
FunctionReflectionHelper $functionReflectionHelper
) {
$this->functionReflectionHelper = $functionReflectionHelper;
$this->classMethodReflectionHelper = $classMethodReflectionHelper;
$this->classResolver = $classResolver;
$this->phpDocTagsFinder = $phpDocTagsFinder;
}

/**
Expand Down Expand Up @@ -266,11 +259,23 @@ private function extractMethodThrows(FullyQualified $fullyQualified, Identifier
return $this->classMethodReflectionHelper->extractTagsFromMethodDockblock($class, $method, '@throws');
}

/**
* @return string[]
*/
private function extractAlreadyAnnotatedThrowables(Node $node): array
{
$callee = $this->identifyCaller($node);
if ($callee === null) {
return [];
}

/** @var PhpDocInfo|null $callePhpDocInfo */
$callePhpDocInfo = $callee->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($callePhpDocInfo === null) {
return [];
}

return $callee === null ? [] : $this->phpDocTagsFinder->extractTagsThrowsFromNode($callee);
return $callePhpDocInfo->getThrowsClassNames();
}

private function diffThrowables(array $foundThrownThrowables, array $alreadyAnnotatedThrowables): int
Expand Down
29 changes: 0 additions & 29 deletions src/PhpDoc/PhpDocTagsFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
namespace Rector\Core\PhpDoc;

use Nette\Utils\Strings;
use PhpParser\Node;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
use Rector\PHPStan\Type\ShortenedObjectType;

final class PhpDocTagsFinder
{
Expand Down Expand Up @@ -40,28 +35,4 @@ public function extractTagsFromStringedDocblock(string $dockblock, string $tagNa

return array_merge(...$matchingTags);
}

public function extractTagsThrowsFromNode(Node $node): array
{
$throwsTags = [];

/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
foreach ($phpDocInfo->getThrowsTypes() as $throwsType) {
$thrownClass = null;
if ($throwsType instanceof ShortenedObjectType) {
$thrownClass = $throwsType->getFullyQualifiedName();
}

if ($throwsType instanceof FullyQualifiedObjectType) {
$thrownClass = $throwsType->getClassName();
}

if ($thrownClass !== null) {
$throwsTags[] = $thrownClass;
}
}

return $throwsTags;
}
}

0 comments on commit b1143d5

Please sign in to comment.