diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/cover_intersection.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/cover_intersection.php.inc new file mode 100644 index 00000000000..5e80b9f7f8d --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/cover_intersection.php.inc @@ -0,0 +1,51 @@ +nextItems($items); + } + + private function nextItems($items): void + { + } +} + +?> +----- +nextItems($items); + } + + private function nextItems(array $items): void + { + } +} + +?> diff --git a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php index 22c10a5e0ae..90109dc2b8b 100644 --- a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php +++ b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php @@ -210,9 +210,9 @@ private function resolveExceptionArgumentPosition(Name $exceptionName): ?int $extendedMethodReflection->getVariants() ); - foreach ($extendedParametersAcceptor->getParameters() as $position => $parameterReflectionWithPhpDoc) { - $parameterType = $parameterReflectionWithPhpDoc->getType(); - $className = ClassNameFromObjectTypeResolver::resolve($parameterReflectionWithPhpDoc->getType()); + foreach ($extendedParametersAcceptor->getParameters() as $position => $extendedParameterReflection) { + $parameterType = $extendedParameterReflection->getType(); + $className = ClassNameFromObjectTypeResolver::resolve($extendedParameterReflection->getType()); if ($className === null) { continue; diff --git a/rules/CodingStyle/Rector/ClassConst/RemoveFinalFromConstRector.php b/rules/CodingStyle/Rector/ClassConst/RemoveFinalFromConstRector.php index 5d4f65ea9ec..b9438c586d1 100644 --- a/rules/CodingStyle/Rector/ClassConst/RemoveFinalFromConstRector.php +++ b/rules/CodingStyle/Rector/ClassConst/RemoveFinalFromConstRector.php @@ -63,12 +63,12 @@ public function refactor(Node $node): ?Node } $hasChanged = false; - foreach ($node->getConstants() as $constant) { - if (! $constant->isFinal()) { + foreach ($node->getConstants() as $classConst) { + if (! $classConst->isFinal()) { continue; } - $this->visibilityManipulator->removeFinal($constant); + $this->visibilityManipulator->removeFinal($classConst); $hasChanged = true; } diff --git a/rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.php b/rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.php index f9d30d5cb69..71d6e02022b 100644 --- a/rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.php +++ b/rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.php @@ -147,8 +147,8 @@ private function resolveMaximumAllowedParameterCount( MethodReflection | FunctionReflection $functionLikeReflection ): int { $parameterCounts = [0]; - foreach ($functionLikeReflection->getVariants() as $variant) { - $parameterCounts[] = count($variant->getParameters()); + foreach ($functionLikeReflection->getVariants() as $parametersAcceptor) { + $parameterCounts[] = count($parametersAcceptor->getParameters()); } return max($parameterCounts); diff --git a/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanStrictReturnsRector.php b/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanStrictReturnsRector.php index 67686c20157..567b14895f6 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanStrictReturnsRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanStrictReturnsRector.php @@ -170,8 +170,8 @@ private function isNativeBooleanReturnTypeFuncCall(FuncCall $funcCall): bool return false; } - foreach ($functionReflection->getVariants() as $variant) { - if (! $variant->getNativeReturnType()->isBoolean()->yes()) { + foreach ($functionReflection->getVariants() as $extendedParametersAcceptor) { + if (! $extendedParametersAcceptor->getNativeReturnType()->isBoolean()->yes()) { return false; } } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php index bf38a8df846..5809dc3f431 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php @@ -14,9 +14,7 @@ use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Return_; use PhpParser\NodeVisitor; -use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\ArrayType; -use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -151,23 +149,17 @@ public function refactor(Node $node): ?Node return $node; } - private function matchArrayObjectType(Type $returnedType): ?Type + private function matchArrayObjectType(Type $type): ?Type { - if ($returnedType instanceof IntersectionType) { - foreach ($returnedType->getTypes() as $intersectionedType) { - if ($intersectionedType instanceof AccessoryArrayListType) { - continue; - } - - if ($intersectionedType instanceof ArrayType && $intersectionedType->getItemType() instanceof ObjectType) { - return $intersectionedType->getItemType(); - } + if (! $type instanceof ArrayType) { + return null; + } - return null; - } + if (! $type->getItemType() instanceof ObjectType) { + return null; } - return null; + return $type->getItemType(); } private function isVariableExclusivelyArrayDimAssigned( diff --git a/src/NodeAnalyzer/VariadicAnalyzer.php b/src/NodeAnalyzer/VariadicAnalyzer.php index 0ce71370199..b120be23fc5 100644 --- a/src/NodeAnalyzer/VariadicAnalyzer.php +++ b/src/NodeAnalyzer/VariadicAnalyzer.php @@ -30,9 +30,9 @@ public function hasVariadicParameters(FuncCall | StaticCall | MethodCall $call): private function hasVariadicVariant(MethodReflection | FunctionReflection $functionLikeReflection): bool { - foreach ($functionLikeReflection->getVariants() as $variant) { + foreach ($functionLikeReflection->getVariants() as $parametersAcceptor) { // can be any number of arguments → nothing to limit here - if ($variant->isVariadic()) { + if ($parametersAcceptor->isVariadic()) { return true; } } diff --git a/src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php b/src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php index a67a308fbe2..d655ca56113 100644 --- a/src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php +++ b/src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php @@ -178,8 +178,8 @@ private function resolveClassContextType( $extendedMethodReflection->getVariants() ); - foreach ($extendedParametersAcceptor->getParameters() as $parameterReflectionWithPhpDoc) { - if (! $parameterReflectionWithPhpDoc->getDefaultValue() instanceof Type) { + foreach ($extendedParametersAcceptor->getParameters() as $extendedParameterReflection) { + if (! $extendedParameterReflection->getDefaultValue() instanceof Type) { return new MixedType(); } } diff --git a/src/NodeTypeResolver/NodeTypeCorrector.php b/src/NodeTypeResolver/NodeTypeCorrector.php new file mode 100644 index 00000000000..bfa3512eaf8 --- /dev/null +++ b/src/NodeTypeResolver/NodeTypeCorrector.php @@ -0,0 +1,62 @@ +accessoryNonEmptyStringTypeCorrector->correct($type); + $type = $this->genericClassStringTypeCorrector->correct($type); + + $type = $this->removeAccessoryArrayListType($type); + + return $this->accessoryNonEmptyArrayTypeCorrector->correct($type); + } + + private function removeAccessoryArrayListType(Type $type): Type + { + if (! $type instanceof IntersectionType) { + return $type; + } + + $cleanTypes = []; + foreach ($type->getTypes() as $intersectionType) { + if ($intersectionType instanceof AccessoryArrayListType) { + continue; + } + + $cleanTypes[] = $intersectionType; + } + + // dump($cleanTypes); + // die; + + if (count($cleanTypes) === 1) { + return $cleanTypes[0]; + } + + return new IntersectionType($cleanTypes); + } +} diff --git a/src/NodeTypeResolver/NodeTypeResolver.php b/src/NodeTypeResolver/NodeTypeResolver.php index 41dad8c7b3e..03872f7ec4e 100644 --- a/src/NodeTypeResolver/NodeTypeResolver.php +++ b/src/NodeTypeResolver/NodeTypeResolver.php @@ -52,9 +52,6 @@ use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface; use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyArrayTypeCorrector; -use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector; -use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector; use Rector\NodeTypeResolver\PHPStan\ObjectWithoutClassTypeWithParentTypes; use Rector\Php\PhpVersionProvider; use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType; @@ -80,10 +77,8 @@ final class NodeTypeResolver public function __construct( private readonly ObjectTypeSpecifier $objectTypeSpecifier, private readonly ClassAnalyzer $classAnalyzer, - private readonly GenericClassStringTypeCorrector $genericClassStringTypeCorrector, + private readonly NodeTypeCorrector $nodeTypeCorrector, private readonly ReflectionProvider $reflectionProvider, - private readonly AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector, - private readonly AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector, private readonly RenamedClassesDataCollector $renamedClassesDataCollector, private readonly NodeNameResolver $nodeNameResolver, private readonly PhpVersionProvider $phpVersionProvider, @@ -201,7 +196,7 @@ public function getType(Node $node): Type $type = $this->resolveByNodeTypeResolvers($node); if ($type instanceof Type) { - $type = $this->correctType($type); + $type = $this->nodeTypeCorrector->correctType($type); if ($type instanceof ObjectType) { $scope = $node->getAttribute(AttributeKey::SCOPE); @@ -236,7 +231,7 @@ public function getType(Node $node): Type return new MixedType(); } - $type = $this->correctType($scope->getType($node)); + $type = $this->nodeTypeCorrector->correctType($scope->getType($node)); // hot fix for phpstan not resolving chain method calls if (! $node instanceof MethodCall) { @@ -284,7 +279,7 @@ public function getNativeType(Expr $expr): Type return new ObjectWithoutClassType(); } - return $this->correctType($type); + return $this->nodeTypeCorrector->correctType($type); } return $this->resolveNativeUnionType($type); @@ -372,14 +367,6 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType return $classReflection->hasTraitUse($objectType->getClassName()); } - private function correctType(Type $type): Type - { - $type = $this->accessoryNonEmptyStringTypeCorrector->correct($type); - $type = $this->genericClassStringTypeCorrector->correct($type); - - return $this->accessoryNonEmptyArrayTypeCorrector->correct($type); - } - /** * Allow pull type from *