[TypeDeclaration] Improve param by caller type #3 (#5792)

Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
Tomas Votruba 2021-03-07 20:37:48 +01:00 committed by GitHub
parent 29487b75bb
commit b052d46b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 128 additions and 274 deletions

View File

@ -10,14 +10,9 @@ use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
@ -40,12 +35,10 @@ use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector;
use Rector\NodeTypeResolver\TypeAnalyzer\ArrayTypeAnalyzer;
use Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper;
use Rector\StaticTypeMapper\TypeFactory\UnionTypeFactory;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
@ -68,11 +61,6 @@ final class NodeTypeResolver
*/
private $arrayTypeAnalyzer;
/**
* @var TypeUnwrapper
*/
private $typeUnwrapper;
/**
* @var ClassAnalyzer
*/
@ -93,22 +81,15 @@ final class NodeTypeResolver
*/
private $reflectionProvider;
/**
* @var NodeNameResolver
*/
private $nodeNameResolver;
/**
* @param NodeTypeResolverInterface[] $nodeTypeResolvers
*/
public function __construct(
ObjectTypeSpecifier $objectTypeSpecifier,
TypeUnwrapper $typeUnwrapper,
ClassAnalyzer $classAnalyzer,
GenericClassStringTypeCorrector $genericClassStringTypeCorrector,
UnionTypeFactory $unionTypeFactory,
ReflectionProvider $reflectionProvider,
NodeNameResolver $nodeNameResolver,
array $nodeTypeResolvers
) {
foreach ($nodeTypeResolvers as $nodeTypeResolver) {
@ -116,12 +97,10 @@ final class NodeTypeResolver
}
$this->objectTypeSpecifier = $objectTypeSpecifier;
$this->typeUnwrapper = $typeUnwrapper;
$this->classAnalyzer = $classAnalyzer;
$this->genericClassStringTypeCorrector = $genericClassStringTypeCorrector;
$this->unionTypeFactory = $unionTypeFactory;
$this->reflectionProvider = $reflectionProvider;
$this->nodeNameResolver = $nodeNameResolver;
}
/**
@ -168,14 +147,6 @@ final class NodeTypeResolver
return $this->isObjectTypeOfObjectType($resolvedType, $requiredObjectType);
}
if ($requiredObjectType->isSuperTypeOf($resolvedType)->yes()) {
return true;
}
if ($resolvedType->equals($requiredObjectType)) {
return true;
}
return $this->isMatchingUnionType($resolvedType, $requiredObjectType);
}
@ -186,23 +157,21 @@ final class NodeTypeResolver
return $type;
}
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if (! $nodeScope instanceof Scope) {
$scope = $node->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
return new MixedType();
}
if (! $node instanceof Expr) {
return new MixedType();
}
// skip anonymous classes, ref https://github.com/rectorphp/rector/issues/1574
if ($node instanceof New_) {
$isAnonymousClass = $this->classAnalyzer->isAnonymousClass($node->class);
if ($isAnonymousClass) {
return new ObjectWithoutClassType();
}
if ($node instanceof New_ && $this->classAnalyzer->isAnonymousClass($node->class)) {
return new ObjectWithoutClassType();
}
$type = $nodeScope->getType($node);
$type = $scope->getType($node);
// hot fix for phpstan not resolving chain method calls
if (! $node instanceof MethodCall) {
@ -303,34 +272,6 @@ final class NodeTypeResolver
return is_a($this->resolve($node), $staticTypeClass);
}
public function isObjectTypeOrNullableObjectType(Node $node, ObjectType $desiredObjectType): bool
{
if ($node instanceof Param && $node->type instanceof NullableType) {
/** @var Name|Identifier $node */
$node = $node->type->type;
}
if ($node instanceof Param && ! $node->type instanceof Name) {
return false;
}
if ($this->isObjectType($node, $desiredObjectType)) {
return true;
}
$nodeType = $this->getStaticType($node);
if (! $nodeType instanceof UnionType) {
return false;
}
$unwrappedNodeType = $this->typeUnwrapper->unwrapNullableType($nodeType);
if (! $unwrappedNodeType instanceof TypeWithClassName) {
return false;
}
return is_a($unwrappedNodeType->getClassName(), $desiredObjectType->getClassName(), true);
}
public function isNullableObjectType(Node $node): bool
{
return $this->isNullableTypeOfSpecificType($node, ObjectType::class);
@ -422,45 +363,6 @@ final class NodeTypeResolver
return $this->isObjectType($classLike, $objectType);
}
public function resolveObjectTypeToCompare(Node $node): ?ObjectType
{
if ($node instanceof StaticCall) {
return $this->resolveStaticCallClassNameObjectTypeToCompare($node);
}
if ($node instanceof Stmt) {
$classLike = $node->getAttribute(ClassLike::class);
if ($classLike === null) {
return null;
}
$className = $this->nodeNameResolver->getName($classLike);
if ($className === null) {
return null;
}
if (! $this->reflectionProvider->hasClass($className)) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($className);
if ($classReflection instanceof ClassReflection) {
return new ObjectType($classReflection->getName(), null, $classReflection);
}
}
$callerType = $this->resolve($node);
if ($callerType instanceof ThisType) {
$callerType = $callerType->getStaticObjectType();
}
if (! $callerType instanceof ObjectType) {
return null;
}
return $callerType;
}
public function resolveObjectTypeFromScope(Scope $scope): ?ObjectType
{
$classReflection = $scope->getClassReflection();
@ -483,17 +385,9 @@ final class NodeTypeResolver
}
}
/**
* @deprecated
*/
private function isMatchingUnionType(Type $resolvedType, ObjectType $requiredObjectType): bool
{
if (! $resolvedType instanceof UnionType) {
return false;
}
$type = TypeCombinator::removeNull($resolvedType);
// for falsy nullables
$type = TypeCombinator::remove($type, new ConstantBooleanType(false));
@ -595,34 +489,6 @@ final class NodeTypeResolver
return $otherType;
}
private function resolveStaticCallClassNameObjectTypeToCompare(StaticCall $staticCall): ?ObjectType
{
$className = $this->nodeNameResolver->getName($staticCall->class);
if ($className === 'parent') {
/** @var Scope $scope */
$scope = $staticCall->getAttribute(AttributeKey::SCOPE);
$classReflection = $scope->getClassReflection();
if (! $classReflection instanceof ClassReflection) {
throw new ShouldNotHappenException();
}
$className = $classReflection->getName();
}
if ($className === null) {
return null;
}
if (! $this->reflectionProvider->hasClass($className)) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($className);
return new ObjectType($classReflection->getName(), null, $classReflection);
}
private function isObjectTypeOfObjectType(ObjectType $resolvedObjectType, ObjectType $requiredObjectType): bool
{
if ($resolvedObjectType->isInstanceOf($requiredObjectType->getClassName())->yes()) {

View File

@ -34,13 +34,14 @@ final class ClassAndInterfaceTypeResolver implements NodeTypeResolverInterface
*/
public function resolve(Node $node): Type
{
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if (! $nodeScope instanceof Scope) {
$scope = $node->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
// new node probably
return new MixedType();
}
$classReflection = $nodeScope->getClassReflection();
$classReflection = $scope->getClassReflection();
if (! $classReflection instanceof ClassReflection) {
return new MixedType();
}

View File

@ -7,7 +7,7 @@ namespace Rector\NodeTypeResolver\NodeTypeResolver;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\Php\PhpMethodReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
@ -83,15 +83,16 @@ final class StaticCallTypeResolver implements NodeTypeResolverInterface
return $classType;
}
/** @var ClassReflection[] $currentAndParentClassReflections */
$currentAndParentClassReflections = array_merge([$classReflection], $classReflection->getParents());
foreach ($currentAndParentClassReflections as $currentAndParentClassReflection) {
if (! $currentAndParentClassReflection->hasMethod($methodName)) {
foreach ($classReflection->getAncestors() as $ancestorClassReflection) {
if (! $ancestorClassReflection->hasMethod($methodName)) {
continue;
}
return $scope->getType($node);
$methodReflection = $ancestorClassReflection->getMethod($methodName, $scope);
if ($methodReflection instanceof PhpMethodReflection) {
$parametersAcceptor = $methodReflection->getVariants()[0];
return $parametersAcceptor->getReturnType();
}
}
return $classType;

View File

@ -15,7 +15,6 @@ use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\PHPStan\Collector\TraitNodeScopeCollector;
/**
@ -33,11 +32,6 @@ final class VariableTypeResolver implements NodeTypeResolverInterface
*/
private $nodeNameResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var TraitNodeScopeCollector
*/
@ -71,11 +65,6 @@ final class VariableTypeResolver implements NodeTypeResolverInterface
*/
public function resolve(Node $node): Type
{
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
if ($parent instanceof Param) {
return $this->nodeTypeResolver->resolve($parent);
}
$variableName = $this->nodeNameResolver->getName($node);
if ($variableName === null) {
return new MixedType();
@ -91,14 +80,6 @@ final class VariableTypeResolver implements NodeTypeResolverInterface
return $phpDocInfo->getVarType();
}
/**
* @required
*/
public function autowireVariableTypeResolver(NodeTypeResolver $nodeTypeResolver): void
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
private function resolveTypesFromScope(Variable $variable, string $variableName): Type
{
$scope = $this->resolveNodeScope($variable);

View File

@ -95,7 +95,7 @@ CODE_SAMPLE
$isModifiedNode = false;
foreach ($node->getParams() as $param) {
if (! $this->isDateTimeParam($param)) {
if (! $this->isObjectType($param, new ObjectType('DateTime'))) {
continue;
}
@ -112,11 +112,6 @@ CODE_SAMPLE
return $node;
}
private function isDateTimeParam(Param $param): bool
{
return $this->nodeTypeResolver->isObjectTypeOrNullableObjectType($param, new ObjectType('DateTime'));
}
private function refactorParamTypeHint(Param $param): void
{
$fullyQualified = new FullyQualified('DateTimeInterface');

View File

@ -73,10 +73,8 @@ CODE_SAMPLE
return null;
}
$nodeStaticType = $this->getStaticType($node->expr);
// void type
if (! $nodeStaticType instanceof VoidType) {
$exprType = $this->nodeTypeResolver->resolve($node->expr);
if (! $exprType instanceof VoidType) {
return null;
}

View File

@ -0,0 +1,35 @@
<?php
namespace Rector\DeadCode\Tests\Rector\Assign\RemoveAssignOfVoidReturnFunctionRector\Fixture;
final class SomeStaticCall
{
public function run()
{
$value = self::someMethod();
}
private static function someMethod(): void
{
}
}
?>
-----
<?php
namespace Rector\DeadCode\Tests\Rector\Assign\RemoveAssignOfVoidReturnFunctionRector\Fixture;
final class SomeStaticCall
{
public function run()
{
self::someMethod();
}
private static function someMethod(): void
{
}
}
?>

View File

@ -10,15 +10,15 @@ final class KeepReUse
{
public function resolveFirstTypes(Expr $node)
{
/** @var Scope|null $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope === null) {
/** @var Scope|null $scope */
$scope = $node->getAttribute(AttributeKey::SCOPE);
if ($scope === null) {
return [];
}
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
$scope = $node->getAttribute(AttributeKey::SCOPE);
return $nodeScope->getType($node);
return $scope->getType($node);
}
}

View File

@ -217,14 +217,10 @@ CODE_SAMPLE
private function isUuidType(Expr $expr): bool
{
$argumentStaticType = $this->getStaticType($expr);
// UUID is already set
if (! $argumentStaticType instanceof ObjectType) {
return false;
if ($expr instanceof ClassConstFetch) {
return $this->nodeTypeResolver->isObjectType($expr->class, new ObjectType('Ramsey\Uuid\Uuid'));
}
return $argumentStaticType->isInstanceOf('Ramsey\Uuid\Uuid')
->yes();
return $this->nodeTypeResolver->isObjectType($expr, new ObjectType('Ramsey\Uuid\Uuid'));
}
}

View File

@ -79,12 +79,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$callerObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node->var);
if (! $callerObjectType instanceof ObjectType) {
return null;
}
if (! $callerObjectType->isInstanceOf('Doctrine\ORM\EntityRepository')->yes()) {
if (! $this->isObjectType($node->var, new ObjectType('Doctrine\ORM\EntityRepository'))) {
return null;
}

View File

@ -76,7 +76,7 @@ final class ControlDimFetchAnalyzer
}
foreach ($objectTypes as $objectType) {
if ($this->nodeTypeResolver->isObjectTypeOrNullableObjectType($node, $objectType)) {
if ($this->nodeTypeResolver->isObjectType($node, $objectType)) {
return true;
}
}

View File

@ -18,7 +18,7 @@ use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\NetteTesterToPHPUnit\Tests\Rector\Class_\NetteTesterClassToPHPUnitClassRector\NetteTesterPHPUnitRectorTest
* @see \Rector\NetteTesterToPHPUnit\Tests\Rector\Class_\NetteTesterClassToPHPUnitClassRector\NetteTesterClassToPHPUnitClassRectorTest
*/
final class NetteTesterClassToPHPUnitClassRector extends AbstractRector
{
@ -85,12 +85,7 @@ CODE_SAMPLE
return null;
}
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $objectType instanceof ObjectType) {
return null;
}
if (! $objectType->isInstanceOf('Tester\TestCase')->yes()) {
if (! $this->isObjectType($node, new ObjectType('Tester\TestCase'))) {
return null;
}

View File

@ -13,7 +13,7 @@ use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\NetteTesterToPHPUnit\Tests\Rector\Class_\NetteTesterClassToPHPUnitClassRector\NetteTesterPHPUnitRectorTest
* @see \Rector\NetteTesterToPHPUnit\Tests\Rector\Class_\NetteTesterClassToPHPUnitClassRector\NetteTesterClassToPHPUnitClassRectorTest
*/
final class NetteAssertToPHPUnitAssertRector extends AbstractRector
{
@ -65,12 +65,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $objectType instanceof ObjectType) {
return null;
}
if (! $objectType->isInstanceOf('Tester\Assert')->yes()) {
if (! $this->isObjectType($node->class, new ObjectType('Tester\Assert'))) {
return null;
}

View File

@ -8,7 +8,7 @@ use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class NetteTesterPHPUnitRectorTest extends AbstractRectorTestCase
final class NetteTesterClassToPHPUnitClassRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()

View File

@ -67,12 +67,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$callerObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node->var);
if (! $callerObjectType instanceof ObjectType) {
return null;
}
if (! $callerObjectType->isInstanceOf('PHPExcel_Style_Conditional')->yes()) {
if (! $this->isObjectType($node->var, new ObjectType('PHPExcel_Style_Conditional'))) {
return null;
}

View File

@ -65,13 +65,8 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $objectType instanceof ObjectType) {
return null;
}
foreach (PHPExcelMethodDefaultValues::METHOD_NAMES_BY_TYPE_WITH_VALUE as $type => $defaultValuesByMethodName) {
if (! $objectType->isInstanceOf($type)->yes()) {
if (! $this->isCallerObjectType($node, new ObjectType($type))) {
continue;
}
@ -110,4 +105,12 @@ CODE_SAMPLE
$node->args[$position] = $arg;
}
}
/**
* @param StaticCall|MethodCall $node
*/
private function isCallerObjectType(Node $node, ObjectType $objectType): bool
{
return $this->isObjectType($node instanceof MethodCall ? $node->var : $node->class, $objectType);
}
}

View File

@ -80,12 +80,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$staticClassObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $staticClassObjectType instanceof ObjectType) {
return null;
}
if (! $staticClassObjectType->isInstanceOf('PHPExcel_Cell')->yes()) {
if (! $this->isObjectType($node->class, new ObjectType('PHPExcel_Cell'))) {
return null;
}

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\PHPOffice\Tests\Rector\StaticCall\AddRemovedDefaultValuesRector\Fixture;
final class SomeStaticCall
{
public function run(): void
{
\PHPExcel_Cell_DataValidation::setType();
}
}
?>
-----
<?php
namespace Rector\PHPOffice\Tests\Rector\StaticCall\AddRemovedDefaultValuesRector\Fixture;
final class SomeStaticCall
{
public function run(): void
{
\PHPExcel_Cell_DataValidation::setType(\PHPExcel_Cell_DataValidation::TYPE_NONE);
}
}
?>

View File

@ -149,9 +149,9 @@ CODE_SAMPLE
$variableName = $this->getName($node);
// defined 100 %
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope->hasVariableType($variableName)->yes()) {
/** @var Scope $scope */
$scope = $node->getAttribute(AttributeKey::SCOPE);
if ($scope->hasVariableType($variableName)->yes()) {
return null;
}

View File

@ -120,12 +120,7 @@ CODE_SAMPLE
return null;
}
$classObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($class);
if (! $classObjectType instanceof ObjectType) {
return null;
}
if (! $classObjectType->isInstanceOf($className)->yes()) {
if (! $this->isObjectType($class, new ObjectType($className))) {
return null;
}
}

View File

@ -8,7 +8,6 @@ use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Type\ObjectType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Privatization\NodeFactory\ClassConstantFetchValueFactory;
@ -131,12 +130,7 @@ CODE_SAMPLE
MethodCall $methodCall,
ReplaceStringWithClassConstant $replaceStringWithClassConstant
): ?Arg {
$callerObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($methodCall->var);
if (! $callerObjectType instanceof ObjectType) {
return null;
}
if (! $callerObjectType->isInstanceOf($replaceStringWithClassConstant->getClass())->yes()) {
if (! $this->isObjectType($methodCall->var, $replaceStringWithClassConstant->getObjectType())) {
return null;
}

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Rector\Privatization\ValueObject;
use PHPStan\Type\ObjectType;
final class ReplaceStringWithClassConstant
{
/**
@ -37,9 +39,9 @@ final class ReplaceStringWithClassConstant
$this->argPosition = $argPosition;
}
public function getClass(): string
public function getObjectType(): ObjectType
{
return $this->class;
return new ObjectType($this->class);
}
public function getMethod(): string

View File

@ -82,12 +82,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $objectType instanceof ObjectType) {
return null;
}
if (! $objectType->isInstanceOf('Symfony\Component\Console\Command\Command')->yes()) {
if (! $this->isObjectType($node, new ObjectType('Symfony\Component\Console\Command\Command'))) {
return null;
}
@ -127,12 +122,7 @@ CODE_SAMPLE
return null;
}
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node->class);
if (! $objectType instanceof ObjectType) {
return null;
}
if (! $objectType->isInstanceOf('Symfony\Component\Console\Command\Command')->yes()) {
if (! $this->isObjectType($node->class, new ObjectType('Symfony\Component\Console\Command\Command'))) {
return null;
}

View File

@ -80,12 +80,7 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$callerObjectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node->var);
if (! $callerObjectType instanceof ObjectType) {
return null;
}
if (! $callerObjectType->isInstanceOf('Symfony\Component\Form\FormConfigBuilderInterface')->yes()) {
if (! $this->isObjectType($node->var, new ObjectType('Symfony\Component\Form\FormConfigBuilderInterface'))) {
return null;
}

View File

@ -8,7 +8,6 @@ use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
@ -88,13 +87,8 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
$objectType = $this->nodeTypeResolver->resolveObjectTypeToCompare($node);
if (! $objectType instanceof ObjectType) {
return null;
}
foreach ($this->methodReturnTypes as $methodReturnType) {
if (! $objectType->isInstanceOf($methodReturnType->getClass())->yes()) {
if (! $this->isObjectType($node, $methodReturnType->getObjectType())) {
continue;
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Rector\TypeDeclaration\ValueObject;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
final class AddReturnTypeDeclaration
@ -44,4 +45,9 @@ final class AddReturnTypeDeclaration
{
return $this->returnType;
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
}