diff --git a/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php b/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php index c208a71c9c21..79be6ec6c5e8 100644 --- a/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php +++ b/packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php @@ -26,7 +26,6 @@ use Rector\Core\Configuration\CurrentNodeProvider; use Rector\Core\Exception\NotImplementedYetException; use Rector\Core\Exception\ShouldNotHappenException; -use Rector\Core\Util\StaticInstanceOf; use Rector\StaticTypeMapper\StaticTypeMapper; /** @@ -486,16 +485,21 @@ private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode): Type return $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($phpDocTagValueNode, $this->node); } + /** + * @param class-string $type + */ private function ensureTypeIsTagValueNode(string $type, string $location): void { - /** @var array $desiredTypes */ + /** @var array> $desiredTypes */ $desiredTypes = array_merge([ PhpDocTagValueNode::class, PhpDocTagNode::class, ], NodeTypes::TYPE_AWARE_NODES); - if (StaticInstanceOf::isOneOf($type, $desiredTypes)) { - return; + foreach ($desiredTypes as $desiredType) { + if (is_a($type, $desiredType, true)) { + return; + } } throw new ShouldNotHappenException(sprintf( @@ -509,7 +513,8 @@ private function ensureTypeIsTagValueNode(string $type, string $location): void private function resolveNameForPhpDocTagValueNode(PhpDocTagValueNode $phpDocTagValueNode): string { foreach (self::TAGS_TYPES_TO_NAMES as $tagValueNodeType => $name) { - if ($phpDocTagValueNode instanceof $tagValueNodeType) { + /** @var class-string $tagValueNodeType */ + if (is_a($phpDocTagValueNode, $tagValueNodeType, true)) { return $name; } } diff --git a/packages/NodeCollector/NodeCollector/ParsedNodeCollector.php b/packages/NodeCollector/NodeCollector/ParsedNodeCollector.php index 1d7fb6fcffe4..c5f74ba2cc6c 100644 --- a/packages/NodeCollector/NodeCollector/ParsedNodeCollector.php +++ b/packages/NodeCollector/NodeCollector/ParsedNodeCollector.php @@ -167,6 +167,7 @@ public function findClassConstant(string $className, string $constantName): ?Cla public function isCollectableNode(Node $node): bool { foreach (self::COLLECTABLE_NODE_TYPES as $collectableNodeType) { + /** @var class-string $collectableNodeType */ if (is_a($node, $collectableNodeType, true)) { return true; } diff --git a/packages/NodeCollector/NodeCollector/ParsedPropertyFetchNodeCollector.php b/packages/NodeCollector/NodeCollector/ParsedPropertyFetchNodeCollector.php index 488047039792..1cb74072cc01 100644 --- a/packages/NodeCollector/NodeCollector/ParsedPropertyFetchNodeCollector.php +++ b/packages/NodeCollector/NodeCollector/ParsedPropertyFetchNodeCollector.php @@ -13,7 +13,7 @@ use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; use PHPStan\Type\UnionType; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\NodeTypeResolver; @@ -55,7 +55,7 @@ public function collect(Node $node): void } // make sure name is valid - if (StaticInstanceOf::isOneOf($node->name, [StaticCall::class, MethodCall::class])) { + if (StaticNodeInstanceOf::isOneOf($node->name, [StaticCall::class, MethodCall::class])) { return; } diff --git a/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php b/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php index de6e93f59d21..cb02e3e864fe 100644 --- a/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php +++ b/packages/NodeNameResolver/Contract/NodeNameResolverInterface.php @@ -8,6 +8,9 @@ interface NodeNameResolverInterface { + /** + * @return class-string + */ public function getNode(): string; public function resolve(Node $node): ?string; diff --git a/packages/NodeNameResolver/NodeNameResolver.php b/packages/NodeNameResolver/NodeNameResolver.php index bc1b926b26f5..d9bd6a38fcb8 100644 --- a/packages/NodeNameResolver/NodeNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver.php @@ -17,7 +17,7 @@ use Rector\Core\Contract\Rector\RectorInterface; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Printer\BetterStandardPrinter; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\Contract\NodeNameResolverInterface; use Rector\NodeNameResolver\Regex\RegexPatternDetector; use Rector\NodeTypeResolver\FileSystem\CurrentFileInfoProvider; @@ -220,7 +220,7 @@ public function matchNameFromMap(Node $node, array $renameMap): ?string private function isCallOrIdentifier(Node $node): bool { - return StaticInstanceOf::isOneOf($node, [MethodCall::class, StaticCall::class, Identifier::class]); + return StaticNodeInstanceOf::isOneOf($node, [MethodCall::class, StaticCall::class, Identifier::class]); } /** diff --git a/packages/NodeNameResolver/NodeNameResolver/ClassConstFetchNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/ClassConstFetchNameResolver.php index 8139b29c96db..a811d8520015 100644 --- a/packages/NodeNameResolver/NodeNameResolver/ClassConstFetchNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/ClassConstFetchNameResolver.php @@ -24,6 +24,9 @@ public function autowireClassConstFetchNameResolver(NodeNameResolver $nodeNameRe $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return ClassConstFetch::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/ClassConstNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/ClassConstNameResolver.php index 5db9a3c3247e..c682105667c3 100644 --- a/packages/NodeNameResolver/NodeNameResolver/ClassConstNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/ClassConstNameResolver.php @@ -24,6 +24,9 @@ public function autowireClassConstNameResolver(NodeNameResolver $nodeNameResolve $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return ClassConst::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/ClassNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/ClassNameResolver.php index eb827bb74bff..182bd0851294 100644 --- a/packages/NodeNameResolver/NodeNameResolver/ClassNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/ClassNameResolver.php @@ -25,6 +25,9 @@ public function autowireClassNameResolver(NodeNameResolver $nodeNameResolver): v $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return ClassLike::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/EmptyNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/EmptyNameResolver.php index e9e6be67187b..cabc52ff45e4 100644 --- a/packages/NodeNameResolver/NodeNameResolver/EmptyNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/EmptyNameResolver.php @@ -10,6 +10,9 @@ final class EmptyNameResolver implements NodeNameResolverInterface { + /** + * @return class-string + */ public function getNode(): string { return Empty_::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/FuncCallNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/FuncCallNameResolver.php index 63e5c86e9a6f..d32420d4632c 100644 --- a/packages/NodeNameResolver/NodeNameResolver/FuncCallNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/FuncCallNameResolver.php @@ -24,6 +24,9 @@ public function __construct(ReflectionProvider $reflectionProvider) $this->reflectionProvider = $reflectionProvider; } + /** + * @return class-string + */ public function getNode(): string { return FuncCall::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/FunctionNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/FunctionNameResolver.php index 2c8369e7b8e4..96fe1695daba 100644 --- a/packages/NodeNameResolver/NodeNameResolver/FunctionNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/FunctionNameResolver.php @@ -12,6 +12,9 @@ final class FunctionNameResolver implements NodeNameResolverInterface { + /** + * @return class-string + */ public function getNode(): string { return Function_::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/NameNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/NameNameResolver.php index fbefa18ac5b8..63a50421c12a 100644 --- a/packages/NodeNameResolver/NodeNameResolver/NameNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/NameNameResolver.php @@ -23,6 +23,9 @@ public function __construct(FuncCallNameResolver $funcCallNameResolver) $this->funcCallNameResolver = $funcCallNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return Name::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/ParamNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/ParamNameResolver.php index 63d8c8a69ba9..a5910693dc03 100644 --- a/packages/NodeNameResolver/NodeNameResolver/ParamNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/ParamNameResolver.php @@ -24,6 +24,9 @@ public function autowireParamNameResolver(NodeNameResolver $nodeNameResolver): v $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return Param::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/PropertyNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/PropertyNameResolver.php index 62bff23a616b..502f331a1c88 100644 --- a/packages/NodeNameResolver/NodeNameResolver/PropertyNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/PropertyNameResolver.php @@ -24,6 +24,9 @@ public function autowirePropertyNameResolver(NodeNameResolver $nodeNameResolver) $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return Property::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/UseNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/UseNameResolver.php index c08a2478f957..794cd3922d73 100644 --- a/packages/NodeNameResolver/NodeNameResolver/UseNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/UseNameResolver.php @@ -24,6 +24,9 @@ public function autowireUseNameResolver(NodeNameResolver $nodeNameResolver): voi $this->nodeNameResolver = $nodeNameResolver; } + /** + * @return class-string + */ public function getNode(): string { return Use_::class; diff --git a/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php b/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php index f3143aed4ca3..0ccf9102cd83 100644 --- a/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php +++ b/packages/NodeNameResolver/NodeNameResolver/VariableNameResolver.php @@ -14,6 +14,9 @@ final class VariableNameResolver implements NodeNameResolverInterface { + /** + * @return class-string + */ public function getNode(): string { return Variable::class; diff --git a/packages/NodeNestingScope/ContextAnalyzer.php b/packages/NodeNestingScope/ContextAnalyzer.php index 28759d1d9db3..d93911ae754d 100644 --- a/packages/NodeNestingScope/ContextAnalyzer.php +++ b/packages/NodeNestingScope/ContextAnalyzer.php @@ -15,7 +15,7 @@ use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\While_; use Rector\Core\PhpParser\Node\BetterNodeFinder; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; final class ContextAnalyzer { @@ -49,7 +49,7 @@ public function isInLoop(Node $node): bool return false; } - return StaticInstanceOf::isOneOf($firstParent, self::LOOP_NODES); + return StaticNodeInstanceOf::isOneOf($firstParent, self::LOOP_NODES); } public function isInIf(Node $node): bool diff --git a/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php b/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php index e11205c26217..6af2b42fdcf1 100644 --- a/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php +++ b/packages/NodeNestingScope/NodeFinder/ScopeAwareNodeFinder.php @@ -48,10 +48,11 @@ public function findParentType(Node $node, array $allowedTypes): ?Node /** * Find node based on $callable or null, when the nesting scope is broken - * @param class-string[] $allowedTypes + * @param array> $allowedTypes */ public function findParent(Node $node, callable $callable, array $allowedTypes): ?Node { + /** @var array> $parentNestingBreakTypes */ $parentNestingBreakTypes = array_diff(ControlStructure::BREAKING_SCOPE_NODE_TYPES, $allowedTypes); $this->isBreakingNodeFoundFirst = false; diff --git a/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php b/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php index cdf5cc4210d8..bf1472914cc4 100644 --- a/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php +++ b/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php @@ -195,11 +195,7 @@ private function resolveClassOrInterfaceScope(ClassLike $classLike, Scope $scope return $scope->enterClass($classReflection); } -<<<<<<< HEAD private function resolveDependentFiles(Node $node, MutatingScope $mutatingScope): void -======= - private function resolveDependentFiles(Node $node, MutatingScope $scope): void ->>>>>>> cba12e3ab1... narrow return types { if (! $this->configuration->isCacheEnabled()) { return; diff --git a/packages/PostRector/Collector/NodesToAddCollector.php b/packages/PostRector/Collector/NodesToAddCollector.php index 8acf6bc83ea8..a59a5e4794e3 100644 --- a/packages/PostRector/Collector/NodesToAddCollector.php +++ b/packages/PostRector/Collector/NodesToAddCollector.php @@ -11,7 +11,7 @@ use Rector\ChangesReporting\Collector\RectorChangeCollector; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Node\BetterNodeFinder; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\PostRector\Contract\Collector\NodeCollectorInterface; @@ -128,7 +128,7 @@ public function addNodesBeforeNode(array $newNodes, Node $positionNode): void private function resolveNearestExpressionPosition(Node $node): string { - if (StaticInstanceOf::isOneOf($node, [Expression::class, Stmt::class])) { + if (StaticNodeInstanceOf::isOneOf($node, [Expression::class, Stmt::class])) { return spl_object_hash($node); } diff --git a/packages/StaticTypeMapper/StaticTypeMapper.php b/packages/StaticTypeMapper/StaticTypeMapper.php index 6c3fccfb541b..e4a4d6befb09 100644 --- a/packages/StaticTypeMapper/StaticTypeMapper.php +++ b/packages/StaticTypeMapper/StaticTypeMapper.php @@ -19,7 +19,6 @@ use PHPStan\Type\MixedType; use PHPStan\Type\Type; use Rector\Core\Exception\NotImplementedYetException; -use Rector\Core\Util\StaticInstanceOf; use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper; use Rector\StaticTypeMapper\Mapper\PhpParserNodeMapper; use Rector\StaticTypeMapper\Naming\NameScopeFactory; @@ -99,11 +98,16 @@ public function mapPHPStanPhpDocTypeToPHPStanType(PhpDocTagValueNode $phpDocTagV return $this->phpDocTypeMapper->mapToPHPStanType($phpDocTagValueNode->bound, $node, $nameScope); } - - if (StaticInstanceOf::isOneOf( - $phpDocTagValueNode, - [ReturnTagValueNode::class, ParamTagValueNode::class, VarTagValueNode::class, ThrowsTagValueNode::class] - )) { + if ($phpDocTagValueNode instanceof ReturnTagValueNode) { + return $this->mapPHPStanPhpDocTypeNodeToPHPStanType($phpDocTagValueNode->type, $node); + } + if ($phpDocTagValueNode instanceof ParamTagValueNode) { + return $this->mapPHPStanPhpDocTypeNodeToPHPStanType($phpDocTagValueNode->type, $node); + } + if ($phpDocTagValueNode instanceof VarTagValueNode) { + return $this->mapPHPStanPhpDocTypeNodeToPHPStanType($phpDocTagValueNode->type, $node); + } + if ($phpDocTagValueNode instanceof ThrowsTagValueNode) { return $this->mapPHPStanPhpDocTypeNodeToPHPStanType($phpDocTagValueNode->type, $node); } diff --git a/packages/StaticTypeMapper/ValueObject/Type/ShortenedObjectType.php b/packages/StaticTypeMapper/ValueObject/Type/ShortenedObjectType.php index 1ab524225012..7c91eda714f4 100644 --- a/packages/StaticTypeMapper/ValueObject/Type/ShortenedObjectType.php +++ b/packages/StaticTypeMapper/ValueObject/Type/ShortenedObjectType.php @@ -4,7 +4,9 @@ namespace Rector\StaticTypeMapper\ValueObject\Type; +use PHPStan\TrinaryLogic; use PHPStan\Type\ObjectType; +use PHPStan\Type\Type; final class ShortenedObjectType extends ObjectType { @@ -23,6 +25,12 @@ public function __construct(string $shortName, string $fullyQualifiedName) $this->fullyQualifiedName = $fullyQualifiedName; } + public function isSuperTypeOf(Type $type): TrinaryLogic + { + $fullyQualifiedObjectType = new ObjectType($this->fullyQualifiedName); + return $fullyQualifiedObjectType->isSuperTypeOf($type); + } + public function getShortName(): string { return $this->getClassName(); diff --git a/phpstan.neon b/phpstan.neon index 832d4a8c13d6..45dec838dee5 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -519,12 +519,16 @@ parameters: message: '#Do not inherit from abstract class, better use composition#' path: utils/phpstan-extensions/src/Rule/NoInstanceOfStaticReflectionRule.php - # first wave resolved, merge PR - - '#Instead of "(.*?)" use ReflectionProvider service (.*?) for static reflection to work#' - # known internal types on correct location - message: '#Instead of "(.*?)" use ReflectionProvider service (.*?) for static reflection to work#' paths: - src/Application/RectorApplication.php - src/Console/Command/ProcessCommand.php + + # annotations + - + message: '#Instead of "instanceof/is_a\(\)" use ReflectionProvider service or "\(new ObjectType\(\)\)\-\>isSuperTypeOf\(\)" for static reflection to work#' + paths: + - packages/BetterPhpDocParser/AnnotationReader/NodeAnnotationReader.php + - packages/BetterPhpDocParser/PhpDocNodeFactory/*NodeFactory.php diff --git a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/fixture.php.inc b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/fixture.php.inc index 9ec3dca09448..757a450de62b 100644 --- a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/fixture.php.inc +++ b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/fixture.php.inc @@ -5,7 +5,9 @@ namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fix use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface; class SomeClass implements OneToManyInterface -{ +{ /** + * @return class-string<\PhpParser\Node> + */ public function getNode(): string { return 'Echo_'; diff --git a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/multi_return.php.inc b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/multi_return.php.inc index 974235dad0bc..1be4971a6364 100644 --- a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/multi_return.php.inc +++ b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/multi_return.php.inc @@ -5,7 +5,9 @@ namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fix use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface; class MultiReturn implements OneToManyInterface -{ +{ /** + * @return class-string<\PhpParser\Node> + */ public function getNode(): string { if (true) { diff --git a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/return_class_const_fetch.php.inc b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/return_class_const_fetch.php.inc index 00fcd7ccc283..7b951690a472 100644 --- a/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/return_class_const_fetch.php.inc +++ b/rules-tests/Transform/Rector/ClassMethod/SingleToManyMethodRector/Fixture/return_class_const_fetch.php.inc @@ -5,7 +5,9 @@ namespace Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Fix use Rector\Tests\Transform\Rector\ClassMethod\SingleToManyMethodRector\Source\OneToManyInterface; class ReturnClassConstFetch implements OneToManyInterface -{ +{ /** + * @return class-string<\PhpParser\Node> + */ public function getNode(): string { return self::class; diff --git a/rules/CodeQuality/NodeAnalyzer/ForAnalyzer.php b/rules/CodeQuality/NodeAnalyzer/ForAnalyzer.php index 725f31ec9abf..fb5b8f927129 100644 --- a/rules/CodeQuality/NodeAnalyzer/ForAnalyzer.php +++ b/rules/CodeQuality/NodeAnalyzer/ForAnalyzer.php @@ -20,7 +20,7 @@ use Rector\Core\NodeManipulator\AssignManipulator; use Rector\Core\PhpParser\Comparing\NodeComparator; use Rector\Core\PhpParser\Node\BetterNodeFinder; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -105,7 +105,7 @@ public function isLoopMatch(array $loopExprs, ?string $keyValueName): bool /** @var PreInc|PostInc $prePostInc */ $prePostInc = $loopExprs[0]; - if (StaticInstanceOf::isOneOf($prePostInc, [PreInc::class, PostInc::class])) { + if (StaticNodeInstanceOf::isOneOf($prePostInc, [PreInc::class, PostInc::class])) { return $this->nodeNameResolver->isName($prePostInc->var, $keyValueName); } diff --git a/rules/CodeQuality/Rector/Foreach_/SimplifyForeachToCoalescingRector.php b/rules/CodeQuality/Rector/Foreach_/SimplifyForeachToCoalescingRector.php index 52465f15e9f6..9c1580108886 100644 --- a/rules/CodeQuality/Rector/Foreach_/SimplifyForeachToCoalescingRector.php +++ b/rules/CodeQuality/Rector/Foreach_/SimplifyForeachToCoalescingRector.php @@ -15,7 +15,7 @@ use PhpParser\Node\Stmt\Return_; use Rector\Core\NodeManipulator\ForeachManipulator; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -127,7 +127,7 @@ private function matchReturnOrAssignNode(Foreach_ $foreach): ?Node } $innerNode = $node->stmts[0] instanceof Expression ? $node->stmts[0]->expr : $node->stmts[0]; - if (StaticInstanceOf::isOneOf($innerNode, [Assign::class, Return_::class])) { + if (StaticNodeInstanceOf::isOneOf($innerNode, [Assign::class, Return_::class])) { return $innerNode; } diff --git a/rules/CodeQuality/Rector/FuncCall/SetTypeToCastRector.php b/rules/CodeQuality/Rector/FuncCall/SetTypeToCastRector.php index 179778bfaaae..8d0ee748b0af 100644 --- a/rules/CodeQuality/Rector/FuncCall/SetTypeToCastRector.php +++ b/rules/CodeQuality/Rector/FuncCall/SetTypeToCastRector.php @@ -18,7 +18,7 @@ use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Stmt\Expression; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -104,7 +104,7 @@ public function refactor(Node $node): ?Node $parentNode = $node->getAttribute(AttributeKey::PARENT_NODE); // result of function or probably used - if (StaticInstanceOf::isOneOf($parentNode, [Expr::class, Arg::class])) { + if (StaticNodeInstanceOf::isOneOf($parentNode, [Expr::class, Arg::class])) { return null; } diff --git a/rules/CodeQualityStrict/TypeAnalyzer/SubTypeAnalyzer.php b/rules/CodeQualityStrict/TypeAnalyzer/SubTypeAnalyzer.php index 26a726e911df..72e52fc5274b 100644 --- a/rules/CodeQualityStrict/TypeAnalyzer/SubTypeAnalyzer.php +++ b/rules/CodeQualityStrict/TypeAnalyzer/SubTypeAnalyzer.php @@ -6,7 +6,6 @@ use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; -use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType; final class SubTypeAnalyzer { @@ -20,14 +19,12 @@ public function isObjectSubType(Type $checkedType, Type $mainType): bool return false; } - $checkedClassName = $checkedType instanceof ShortenedObjectType ? $checkedType->getFullyQualifiedName() : $checkedType->getClassName(); - $mainClassName = $mainType instanceof ShortenedObjectType ? $mainType->getFullyQualifiedName() : $mainType->getClassName(); - - if (is_a($checkedClassName, $mainClassName, true)) { + // parent type to all objects + if ($mainType->getClassName() === 'stdClass') { return true; } - // child of every object - return $mainClassName === 'stdClass'; + return $mainType->isSuperTypeOf($checkedType) + ->yes(); } } diff --git a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php index 0df08cd822e8..531293123aa8 100644 --- a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php +++ b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php @@ -30,7 +30,7 @@ use PhpParser\Node\Expr\Variable; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt\Expression; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\PostRector\Collector\NodesToAddCollector; final class LivingCodeManipulator @@ -63,7 +63,7 @@ public function keepLivingCodeFromExpr($expr): array return []; } - if (StaticInstanceOf::isOneOf($expr, [Closure::class, Scalar::class, ConstFetch::class])) { + if (StaticNodeInstanceOf::isOneOf($expr, [Closure::class, Scalar::class, ConstFetch::class])) { return []; } @@ -88,7 +88,7 @@ public function keepLivingCodeFromExpr($expr): array $this->keepLivingCodeFromExpr($expr->dim) ); } - if (StaticInstanceOf::isOneOf($expr, [ClassConstFetch::class, StaticPropertyFetch::class])) { + if (StaticNodeInstanceOf::isOneOf($expr, [ClassConstFetch::class, StaticPropertyFetch::class])) { /** @var ClassConstFetch|StaticPropertyFetch $expr */ return array_merge( $this->keepLivingCodeFromExpr($expr->class), diff --git a/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php b/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php index 0d0bfd0a3f2a..b2a1658a8594 100644 --- a/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php +++ b/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php @@ -15,7 +15,7 @@ use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt\Expression; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNestingScope\ScopeNestingComparator; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -100,7 +100,7 @@ public function refactor(Node $node): ?Node private function isCall(Expr $expr): bool { - return StaticInstanceOf::isOneOf($expr, [FuncCall::class, StaticCall::class, MethodCall::class]); + return StaticNodeInstanceOf::isOneOf($expr, [FuncCall::class, StaticCall::class, MethodCall::class]); } private function shouldSkipForDifferentScope(Assign $assign, Expression $expression): bool diff --git a/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php b/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php index 9fcd5e409bc9..79db6ea66f30 100644 --- a/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php +++ b/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php @@ -18,7 +18,7 @@ use PhpParser\Node\Expr\BinaryOp\Plus; use PhpParser\Node\Expr\UnaryMinus; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -139,7 +139,7 @@ private function processAssignOp(Node $node): ?Expr private function processBinaryOp(Node $node): ?Expr { - if (StaticInstanceOf::isOneOf($node, [Plus::class, Minus::class])) { + if (StaticNodeInstanceOf::isOneOf($node, [Plus::class, Minus::class])) { /** @var Plus|Minus $node */ return $this->processBinaryPlusAndMinus($node); } diff --git a/rules/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php b/rules/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php index 6e45212b99e0..b51ee9d5fbaf 100644 --- a/rules/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php +++ b/rules/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php @@ -16,7 +16,7 @@ use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\Defluent\Reflection\MethodCallToClassMethodParser; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -239,7 +239,7 @@ public function resolveRootMethodCall(MethodCall $methodCall): ?MethodCall private function isCall(Expr $expr): bool { - return StaticInstanceOf::isOneOf($expr, [MethodCall::class, StaticCall::class]); + return StaticNodeInstanceOf::isOneOf($expr, [MethodCall::class, StaticCall::class]); } private function isMethodCallCreatingNewInstance(MethodCall $methodCall): bool diff --git a/rules/Defluent/NodeAnalyzer/FluentChainMethodCallRootExtractor.php b/rules/Defluent/NodeAnalyzer/FluentChainMethodCallRootExtractor.php index 4a10766d2f92..be3474b75e54 100644 --- a/rules/Defluent/NodeAnalyzer/FluentChainMethodCallRootExtractor.php +++ b/rules/Defluent/NodeAnalyzer/FluentChainMethodCallRootExtractor.php @@ -13,7 +13,7 @@ use PhpParser\Node\Stmt\Return_; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Node\BetterNodeFinder; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\Defluent\ValueObject\AssignAndRootExpr; use Rector\Defluent\ValueObject\FluentCallsKind; use Rector\Naming\Naming\PropertyNaming; @@ -86,7 +86,7 @@ public function extractFromMethodCalls(array $methodCalls, string $kind): ?Assig } foreach ($methodCalls as $methodCall) { - if (StaticInstanceOf::isOneOf($methodCall->var, [Variable::class, PropertyFetch::class])) { + if (StaticNodeInstanceOf::isOneOf($methodCall->var, [Variable::class, PropertyFetch::class])) { return $this->createAssignAndRootExprForVariableOrPropertyFetch($methodCall); } if ($methodCall->var instanceof New_) { diff --git a/rules/DowngradePhp80/Rector/ClassMethod/DowngradeTrailingCommasInParamUseRector.php b/rules/DowngradePhp80/Rector/ClassMethod/DowngradeTrailingCommasInParamUseRector.php index 8dc098ea2396..ef3a4acbce7a 100644 --- a/rules/DowngradePhp80/Rector/ClassMethod/DowngradeTrailingCommasInParamUseRector.php +++ b/rules/DowngradePhp80/Rector/ClassMethod/DowngradeTrailingCommasInParamUseRector.php @@ -16,7 +16,7 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\DowngradePhp73\Tokenizer\FollowedByCommaAnalyzer; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -102,7 +102,12 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (StaticInstanceOf::isOneOf($node, [MethodCall::class, FuncCall::class, StaticCall::class, New_::class])) { + if (StaticNodeInstanceOf::isOneOf($node, [ + MethodCall::class, + FuncCall::class, + StaticCall::class, + New_::class, + ])) { /** @var MethodCall|FuncCall|StaticCall|New_ $node */ return $this->processArgs($node); } diff --git a/rules/Naming/Naming/VariableNaming.php b/rules/Naming/Naming/VariableNaming.php index 67e728cfbcc2..48aa3facf140 100644 --- a/rules/Naming/Naming/VariableNaming.php +++ b/rules/Naming/Naming/VariableNaming.php @@ -22,7 +22,7 @@ use PHPStan\Type\Type; use Rector\Core\Exception\NotImplementedYetException; use Rector\Core\PhpParser\Node\Value\ValueResolver; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\NodeTypeResolver; use Stringy\Stringy; @@ -89,7 +89,7 @@ private function resolveBareFromNode(Node $node): ?string return $this->resolveFromPropertyFetch($node); } - if ($node !== null && StaticInstanceOf::isOneOf( + if ($node !== null && StaticNodeInstanceOf::isOneOf( $node, [MethodCall::class, NullsafeMethodCall::class, StaticCall::class])) { return $this->resolveFromMethodCall($node); diff --git a/rules/Php56/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php b/rules/Php56/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php index 379e5f48827d..972e15d33d94 100644 --- a/rules/Php56/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php +++ b/rules/Php56/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php @@ -27,7 +27,7 @@ use PhpParser\NodeTraverser; use PHPStan\Analyser\Scope; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -213,7 +213,7 @@ private function shouldSkipVariable(Variable $variable): bool )) { return true; } - if (StaticInstanceOf::isOneOf($parentNode, [Unset_::class, UnsetCast::class])) { + if (StaticNodeInstanceOf::isOneOf($parentNode, [Unset_::class, UnsetCast::class])) { return true; } @@ -253,6 +253,6 @@ private function isStaticVariable(Node $parentNode): bool private function isListAssign(Node $node): bool { $parentParentNode = $node->getAttribute(AttributeKey::PARENT_NODE); - return StaticInstanceOf::isOneOf($parentParentNode, [List_::class, Array_::class]); + return StaticNodeInstanceOf::isOneOf($parentParentNode, [List_::class, Array_::class]); } } diff --git a/rules/Php70/NodeAnalyzer/VariableNaming.php b/rules/Php70/NodeAnalyzer/VariableNaming.php index 95fbfbc1bcd7..575035035f5c 100644 --- a/rules/Php70/NodeAnalyzer/VariableNaming.php +++ b/rules/Php70/NodeAnalyzer/VariableNaming.php @@ -25,7 +25,7 @@ use PHPStan\Type\Type; use Rector\Core\Exception\NotImplementedYetException; use Rector\Core\PhpParser\Node\Value\ValueResolver; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\NodeTypeResolver; use Stringy\Stringy; @@ -181,7 +181,7 @@ private function resolveBareFromNode(Node $node): ?string return $this->resolveFromPropertyFetch($node); } - if ($node !== null && StaticInstanceOf::isOneOf( + if ($node !== null && StaticNodeInstanceOf::isOneOf( $node, [MethodCall::class, NullsafeMethodCall::class, StaticCall::class])) { diff --git a/rules/Privatization/Rector/Class_/ChangeLocalPropertyToVariableRector.php b/rules/Privatization/Rector/Class_/ChangeLocalPropertyToVariableRector.php index 6eb86753b9b9..29fbbee6fc31 100644 --- a/rules/Privatization/Rector/Class_/ChangeLocalPropertyToVariableRector.php +++ b/rules/Privatization/Rector/Class_/ChangeLocalPropertyToVariableRector.php @@ -18,7 +18,7 @@ use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer; use Rector\Core\NodeManipulator\ClassManipulator; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Privatization\NodeReplacer\PropertyFetchWithVariableReplacer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -222,7 +222,7 @@ private function isPropertyChangingInMultipleMethodCalls( private function isScopeChangingNode(Node $node): bool { - return StaticInstanceOf::isOneOf($node, self::SCOPE_CHANGING_NODE_TYPES); + return StaticNodeInstanceOf::isOneOf($node, self::SCOPE_CHANGING_NODE_TYPES); } private function refactorIf(If_ $if, string $privatePropertyName): ?bool diff --git a/rules/Renaming/NodeManipulator/IdentifierManipulator.php b/rules/Renaming/NodeManipulator/IdentifierManipulator.php index 2024dec30bcf..6fdbdcaffc11 100644 --- a/rules/Renaming/NodeManipulator/IdentifierManipulator.php +++ b/rules/Renaming/NodeManipulator/IdentifierManipulator.php @@ -12,7 +12,7 @@ use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Identifier; use PhpParser\Node\Stmt\ClassMethod; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Webmozart\Assert\Assert; @@ -81,7 +81,7 @@ public function removeSuffix(Node $node, string $suffixToRemove): void */ private function resolveOldMethodName(Node $node): ?string { - if (StaticInstanceOf::isOneOf($node, [StaticCall::class, MethodCall::class])) { + if (StaticNodeInstanceOf::isOneOf($node, [StaticCall::class, MethodCall::class])) { return $this->nodeNameResolver->getName($node->name); } diff --git a/rules/Renaming/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector.php b/rules/Renaming/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector.php index 05d5c16805c1..6012a823178c 100644 --- a/rules/Renaming/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector.php +++ b/rules/Renaming/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector.php @@ -17,7 +17,7 @@ use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PhpDoc\PhpDocTypeRenamer; use Rector\Renaming\ValueObject\PseudoNamespaceToNamespace; @@ -138,7 +138,7 @@ public function configure(array $configuration): void private function refactorStmts(array $stmts): array { $this->traverseNodesWithCallable($stmts, function (Node $node): ?Node { - if (! StaticInstanceOf::isOneOf( + if (! StaticNodeInstanceOf::isOneOf( $node, [Name::class, Identifier::class, Property::class, FunctionLike::class])) { return null; diff --git a/rules/Transform/Rector/Assign/GetAndSetToMethodCallRector.php b/rules/Transform/Rector/Assign/GetAndSetToMethodCallRector.php index f30a11d16829..b6c9d4cd8959 100644 --- a/rules/Transform/Rector/Assign/GetAndSetToMethodCallRector.php +++ b/rules/Transform/Rector/Assign/GetAndSetToMethodCallRector.php @@ -16,7 +16,7 @@ use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer; use Rector\Core\NodeManipulator\MagicPropertyFetchAnalyzer; use Rector\Core\Rector\AbstractRector; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -117,7 +117,7 @@ public function getNodeTypes(): array public function refactor(Node $node): ?Node { if ($node instanceof Assign) { - if (StaticInstanceOf::isOneOf($node->var, [PropertyFetch::class, StaticPropertyFetch::class])) { + if (StaticNodeInstanceOf::isOneOf($node->var, [PropertyFetch::class, StaticPropertyFetch::class])) { return $this->processMagicSet($node); } return null; diff --git a/rules/Transform/Rector/ClassMethod/SingleToManyMethodRector.php b/rules/Transform/Rector/ClassMethod/SingleToManyMethodRector.php index dd75051f01ed..a63d059c1d38 100644 --- a/rules/Transform/Rector/ClassMethod/SingleToManyMethodRector.php +++ b/rules/Transform/Rector/ClassMethod/SingleToManyMethodRector.php @@ -52,7 +52,9 @@ public function getRuleDefinition(): RuleDefinition new ConfiguredCodeSample( <<<'CODE_SAMPLE' class SomeClass -{ +{ /** + * @return class-string<\PhpParser\Node> + */ public function getNode(): string { return 'Echo_'; diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 76bed3681a63..22e188418037 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -133,7 +133,7 @@ private function narrowParentObjectTreeToSingleObjectChildType(Type $type): Type return $type; } - if (! is_a($firstUnionedType->getClassName(), $unionedType->getClassName(), true)) { + if ($unionedType->isSuperTypeOf($firstUnionedType)->yes()) { return $type; } } diff --git a/rules/TypeDeclaration/TypeAnalyzer/ObjectTypeComparator.php b/rules/TypeDeclaration/TypeAnalyzer/ObjectTypeComparator.php index d31a90b15076..96f4b8842b32 100644 --- a/rules/TypeDeclaration/TypeAnalyzer/ObjectTypeComparator.php +++ b/rules/TypeDeclaration/TypeAnalyzer/ObjectTypeComparator.php @@ -25,10 +25,6 @@ public function isCurrentObjectTypeSubType(Type $currentType, Type $newType): bo return true; } - if ($this->isBothIterableIteratorGeneratorTraversable($currentType, $newType)) { - return true; - } - if (! $currentType instanceof ObjectType) { return false; } @@ -37,12 +33,8 @@ public function isCurrentObjectTypeSubType(Type $currentType, Type $newType): bo return false; } - return is_a($currentType->getClassName(), $newType->getClassName(), true); - } - - private function isClosure(Type $type): bool - { - return $type instanceof ObjectType && $type->getClassName() === 'Closure'; + return $newType->isSuperTypeOf($currentType) + ->yes(); } private function isBothCallable(Type $currentType, Type $newType): bool @@ -54,29 +46,9 @@ private function isBothCallable(Type $currentType, Type $newType): bool return $newType instanceof CallableType && $this->isClosure($currentType); } - private function isBothIterableIteratorGeneratorTraversable(Type $currentType, Type $newType): bool - { - if (! $currentType instanceof ObjectType) { - return false; - } - - if (! $newType instanceof ObjectType) { - return false; - } - - if ($currentType->getClassName() === 'iterable' && $this->isTraversableGeneratorIterator($newType)) { - return true; - } - - if ($newType->getClassName() !== 'iterable') { - return false; - } - - return $this->isTraversableGeneratorIterator($currentType); - } - - private function isTraversableGeneratorIterator(ObjectType $objectType): bool + private function isClosure(Type $type): bool { - return in_array($objectType->getClassName(), ['Traversable', 'Generator', 'Iterator'], true); + $closureObjectType = new ObjectType('Closure'); + return $closureObjectType->equals($type); } } diff --git a/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer/YieldNodesReturnTypeInferer.php b/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer/YieldNodesReturnTypeInferer.php index 9bd5d3f4b019..314c4a735d88 100644 --- a/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer/YieldNodesReturnTypeInferer.php +++ b/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer/YieldNodesReturnTypeInferer.php @@ -18,6 +18,7 @@ use Rector\NodeTypeResolver\NodeTypeResolver; use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory; use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedGenericObjectType; +use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType; use Rector\TypeDeclaration\Contract\TypeInferer\ReturnTypeInfererInterface; use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser; @@ -66,7 +67,15 @@ public function inferFunctionLike(FunctionLike $functionLike): Type continue; } - $types[] = $this->nodeTypeResolver->getStaticType($value); + $resolvedType = $this->nodeTypeResolver->getStaticType($value); + if ($resolvedType instanceof MixedType) { + continue; + } + $types[] = $resolvedType; + } + + if ($types === []) { + return new FullyQualifiedObjectType('Iterator'); } $types = $this->typeFactory->createMixedPassedOrUnionType($types); diff --git a/src/NodeManipulator/ClassMethodAssignManipulator.php b/src/NodeManipulator/ClassMethodAssignManipulator.php index 7f0435472455..416124146f30 100644 --- a/src/NodeManipulator/ClassMethodAssignManipulator.php +++ b/src/NodeManipulator/ClassMethodAssignManipulator.php @@ -27,7 +27,7 @@ use Rector\Core\PhpParser\Node\BetterNodeFinder; use Rector\Core\PhpParser\Node\NodeFactory; use Rector\Core\PHPStan\Reflection\CallReflectionResolver; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser; @@ -307,7 +307,7 @@ private function isExplicitlyReferenced(Node $node): bool return false; } - if (StaticInstanceOf::isOneOf($node, [Arg::class, ClosureUse::class, Param::class])) { + if (StaticNodeInstanceOf::isOneOf($node, [Arg::class, ClosureUse::class, Param::class])) { return $node->byRef; } diff --git a/src/NodeManipulator/ClassMethodPropertyFetchManipulator.php b/src/NodeManipulator/ClassMethodPropertyFetchManipulator.php index e7035a4ac7bd..7420e9dccec0 100644 --- a/src/NodeManipulator/ClassMethodPropertyFetchManipulator.php +++ b/src/NodeManipulator/ClassMethodPropertyFetchManipulator.php @@ -11,7 +11,7 @@ use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\NodeTraverser; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser; @@ -59,7 +59,7 @@ function (Node $node) use ($propertyName, &$assignedParamName): ?int { return null; } - if (StaticInstanceOf::isOneOf($node->expr, [MethodCall::class, StaticCall::class])) { + if (StaticNodeInstanceOf::isOneOf($node->expr, [MethodCall::class, StaticCall::class])) { return null; } diff --git a/src/NodeManipulator/NullsafeManipulator.php b/src/NodeManipulator/NullsafeManipulator.php index 2f2b1ef245bc..b1b464dd44bc 100644 --- a/src/NodeManipulator/NullsafeManipulator.php +++ b/src/NodeManipulator/NullsafeManipulator.php @@ -10,7 +10,7 @@ use PhpParser\Node\Expr\NullsafePropertyFetch; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Identifier; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\Node\AttributeKey; final class NullsafeManipulator @@ -36,7 +36,7 @@ public function processNullSafeExprResult(?Expr $expr, Identifier $nextExprIdent $parentIdentifier = $nextExprIdentifier->getAttribute(AttributeKey::PARENT_NODE); - if (StaticInstanceOf::isOneOf($parentIdentifier, [MethodCall::class, NullsafeMethodCall::class])) { + if (StaticNodeInstanceOf::isOneOf($parentIdentifier, [MethodCall::class, NullsafeMethodCall::class])) { return new NullsafeMethodCall($expr, $nextExprIdentifier); } diff --git a/src/PhpParser/Node/BetterNodeFinder.php b/src/PhpParser/Node/BetterNodeFinder.php index c530439911da..659656170f75 100644 --- a/src/PhpParser/Node/BetterNodeFinder.php +++ b/src/PhpParser/Node/BetterNodeFinder.php @@ -14,7 +14,7 @@ use PhpParser\Node\Stmt\Expression; use PhpParser\NodeFinder; use Rector\Core\PhpParser\Comparing\NodeComparator; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\PackageBuilder\Php\TypeChecker; @@ -99,7 +99,7 @@ public function findParentTypes(Node $node, array $types): ?Node } do { - if (StaticInstanceOf::isOneOf($parent, $types)) { + if (StaticNodeInstanceOf::isOneOf($parent, $types)) { return $parent; } diff --git a/src/PhpParser/Parser/InlineCodeParser.php b/src/PhpParser/Parser/InlineCodeParser.php index 0243fa249b98..78b06d877a13 100644 --- a/src/PhpParser/Parser/InlineCodeParser.php +++ b/src/PhpParser/Parser/InlineCodeParser.php @@ -16,7 +16,7 @@ use PhpParser\Parser; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\PhpParser\Printer\BetterStandardPrinter; -use Rector\Core\Util\StaticInstanceOf; +use Rector\Core\Util\StaticNodeInstanceOf; use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator; final class InlineCodeParser @@ -91,7 +91,7 @@ public function stringify(Expr $expr): string return $this->stringify($expr->left) . $this->stringify($expr->right); } - if (StaticInstanceOf::isOneOf($expr, [Variable::class, PropertyFetch::class, StaticPropertyFetch::class])) { + if (StaticNodeInstanceOf::isOneOf($expr, [Variable::class, PropertyFetch::class, StaticPropertyFetch::class])) { return $this->betterStandardPrinter->print($expr); } diff --git a/src/Util/StaticInstanceOf.php b/src/Util/StaticInstanceOf.php deleted file mode 100644 index 53ae4af42204..000000000000 --- a/src/Util/StaticInstanceOf.php +++ /dev/null @@ -1,30 +0,0 @@ -> $nodeTypes + */ + public static function isOneOf($element, array $nodeTypes): bool + { + if ($element === null) { + return false; + } + + // at least 2 types; use instanceof otherwise + if (count($nodeTypes) < 2) { + throw new ShouldNotHappenException(); + } + + foreach ($nodeTypes as $nodeType) { + if (is_a($element, $nodeType, true)) { + return true; + } + } + + return false; + } +} diff --git a/tests/Util/StaticInstanceOfTest.php b/tests/Util/StaticInstanceOfTest.php deleted file mode 100644 index 89f7dce34338..000000000000 --- a/tests/Util/StaticInstanceOfTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertSame($expected, StaticInstanceOf::isOneOf($object, $array)); - } - - public function provideIsOneOf(): Iterator - { - yield [new DateTime('now'), [DateTime::class, stdClass::class], true]; - yield [new stdClass(), [DateTime::class, Iterator::class], false]; - yield [null, [DateTime::class, Iterator::class], false]; - } -} diff --git a/tests/Util/StaticNodeInstanceOfTest.php b/tests/Util/StaticNodeInstanceOfTest.php new file mode 100644 index 000000000000..ee2b8cfe1da8 --- /dev/null +++ b/tests/Util/StaticNodeInstanceOfTest.php @@ -0,0 +1,34 @@ +> $array + * @param DateTime|stdClass|null $object + */ + public function testIsOneOf(?object $object, array $array, bool $expected): void + { + $this->assertSame($expected, StaticNodeInstanceOf::isOneOf($object, $array)); + } + + public function provideIsOneOf(): Iterator + { + yield [new String_('hey'), [LNumber::class, String_::class], true]; + yield [null, [Nop::class], false]; + } +}