Skip to content

Commit

Permalink
Merge pull request rectorphp#2780 from rectorphp/doc-api-cleanup
Browse files Browse the repository at this point in the history
remove deprecated removeBy* in DocBlockManipulator
  • Loading branch information
TomasVotruba authored Jan 31, 2020
2 parents d1757f2 + cdd2feb commit e232523
Show file tree
Hide file tree
Showing 18 changed files with 295 additions and 387 deletions.
1 change: 1 addition & 0 deletions ecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ parameters:
- 'src/Rector/AbstractRector.php'

Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff:
- 'packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php'
- 'packages/MinimalScope/src/Rector/Class_/ChangeLocalPropertyToVariableRector.php'
- 'packages/CodingStyle/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php'
# solve later
Expand Down
28 changes: 28 additions & 0 deletions packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ public function hasByType(string $type): bool
return (bool) $this->getByType($type);
}

public function hasByName(string $name): bool
{
return (bool) $this->getTagsByName($name);
}

public function getByType(string $type): ?PhpDocTagValueNode
{
$this->ensureTypeIsTagValueNode($type, __METHOD__);
Expand Down Expand Up @@ -256,6 +261,21 @@ public function removeByType(string $type): void
}
}

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

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

unset($this->phpDocNode->children[$key]);
}
}

private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
{
$phpDocNode = $this->getPhpDocNode();
Expand Down Expand Up @@ -283,4 +303,12 @@ private function ensureTypeIsTagValueNode(string $type, string $location): void
PhpDocTagValueNode::class
));
}

private function areAnnotationNamesEqual(string $firstAnnotationName, string $secondAnnotationName): bool
{
$firstAnnotationName = trim($firstAnnotationName, '@');
$secondAnnotationName = trim($secondAnnotationName, '@');

return $firstAnnotationName === $secondAnnotationName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Return_;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\NodeTransformer;
Expand Down Expand Up @@ -156,8 +158,11 @@ private function transformArrayToYieldsOnMethodNode(ClassMethod $classMethod, Ar

$this->removeNode($parentNode);

// remove doc block
$this->docBlockManipulator->removeTagFromNode($classMethod, 'return');
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->removeByType(ReturnTagValueNode::class);
}

// change return typehint
$classMethod->returnType = new FullyQualified(Iterator::class);
Expand Down
107 changes: 107 additions & 0 deletions packages/NodeTypeResolver/src/PHPStan/TypeComparator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare(strict_types=1);

namespace Rector\NodeTypeResolver\PHPStan;

use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\PHPStan\Type\AliasedObjectType;
use Rector\PHPStan\Type\ShortenedObjectType;

final class TypeComparator
{
/**
* @var TypeHasher
*/
private $typeHasher;

public function __construct(TypeHasher $typeHasher)
{
$this->typeHasher = $typeHasher;
}

public function areTypesEquals(Type $firstType, Type $secondType): bool
{
if ($this->areBothSameScalarType($firstType, $secondType)) {
return true;
}

// aliases and types
if ($this->areAliasedObjectMatchingFqnObject($firstType, $secondType)) {
return true;
}

if ($this->typeHasher->areTypesEqual($firstType, $secondType)) {
return true;
}

return $this->areArrayTypeWithSingleObjectChildToParent($firstType, $secondType);
}

private function areBothSameScalarType(Type $firstType, Type $secondType): bool
{
if ($firstType instanceof StringType && $secondType instanceof StringType) {
return true;
}

if ($firstType instanceof IntegerType && $secondType instanceof IntegerType) {
return true;
}

if ($firstType instanceof FloatType && $secondType instanceof FloatType) {
return true;
}
return $firstType instanceof BooleanType && $secondType instanceof BooleanType;
}

private function areAliasedObjectMatchingFqnObject(Type $firstType, Type $secondType): bool
{
if ($firstType instanceof AliasedObjectType && $secondType instanceof ObjectType && $firstType->getFullyQualifiedClass() === $secondType->getClassName()) {
return true;
}
return $secondType instanceof AliasedObjectType && $firstType instanceof ObjectType && $secondType->getFullyQualifiedClass() === $firstType->getClassName();
}

/**
* E.g. class A extends B, class B → A[] is subtype of B[] → keep A[]
*/
private function areArrayTypeWithSingleObjectChildToParent(Type $firstType, Type $secondType): bool
{
if (! $firstType instanceof ArrayType || ! $secondType instanceof ArrayType) {
return false;
}

$firstArrayItemType = $firstType->getItemType();
$secondArrayItemType = $secondType->getItemType();

if ($firstArrayItemType instanceof ObjectType && $secondArrayItemType instanceof ObjectType) {
$firstFqnClassName = $this->getFqnClassName($firstArrayItemType);
$secondFqnClassName = $this->getFqnClassName($secondArrayItemType);

if (is_a($firstFqnClassName, $secondFqnClassName, true)) {
return true;
}

if (is_a($secondFqnClassName, $firstFqnClassName, true)) {
return true;
}
}

return false;
}

private function getFqnClassName(ObjectType $objectType): string
{
if ($objectType instanceof ShortenedObjectType) {
return $objectType->getFullyQualifiedName();
}

return $objectType->getClassName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\PhpParser\Node\Resolver\NameResolver;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;

Expand All @@ -30,11 +30,6 @@ final class ParamTypeResolver implements PerNodeTypeResolverInterface
*/
private $nameResolver;

/**
* @var DocBlockManipulator
*/
private $docBlockManipulator;

/**
* @var CallableNodeTraverser
*/
Expand All @@ -45,13 +40,9 @@ final class ParamTypeResolver implements PerNodeTypeResolverInterface
*/
private $nodeTypeResolver;

public function __construct(
NameResolver $nameResolver,
DocBlockManipulator $docBlockManipulator,
CallableNodeTraverser $callableNodeTraverser
) {
public function __construct(NameResolver $nameResolver, CallableNodeTraverser $callableNodeTraverser)
{
$this->nameResolver = $nameResolver;
$this->docBlockManipulator = $docBlockManipulator;
$this->callableNodeTraverser = $callableNodeTraverser;
}

Expand Down Expand Up @@ -129,7 +120,13 @@ private function resolveFromFunctionDocBlock(Param $param): Type
/** @var string $paramName */
$paramName = $this->nameResolver->getName($param);

return $this->docBlockManipulator->getParamTypeByName($parentNode, '$' . $paramName);
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $parentNode->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return new MixedType();
}

return $phpDocInfo->getParamType($paramName);
}

private function resolveFromType(Node $node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
use PHPStan\Analyser\Scope;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\NodeTypeResolver\PHPStan\Collector\TraitNodeScopeCollector;
use Rector\PhpParser\Node\Resolver\NameResolver;

Expand All @@ -23,11 +23,6 @@
*/
final class VariableTypeResolver implements PerNodeTypeResolverInterface
{
/**
* @var DocBlockManipulator
*/
private $docBlockManipulator;

/**
* @var NameResolver
*/
Expand All @@ -43,12 +38,8 @@ final class VariableTypeResolver implements PerNodeTypeResolverInterface
*/
private $traitNodeScopeCollector;

public function __construct(
DocBlockManipulator $docBlockManipulator,
NameResolver $nameResolver,
TraitNodeScopeCollector $traitNodeScopeCollector
) {
$this->docBlockManipulator = $docBlockManipulator;
public function __construct(NameResolver $nameResolver, TraitNodeScopeCollector $traitNodeScopeCollector)
{
$this->nameResolver = $nameResolver;
$this->traitNodeScopeCollector = $traitNodeScopeCollector;
}
Expand Down Expand Up @@ -82,7 +73,12 @@ public function resolve(Node $variableNode): Type
}

// get from annotation
return $this->docBlockManipulator->getVarType($variableNode);
$phpDocInfo = $variableNode->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->getVarType();
}

return new MixedType();
}

/**
Expand Down
Loading

0 comments on commit e232523

Please sign in to comment.