From c327e0eb16f75e45696a2e424b5950d6d2912f1a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 24 Aug 2025 21:16:44 +0700 Subject: [PATCH 1/2] [TypeDeclaration] Skip Valid type from return doc and typed param on AddMethodCallBasedStrictParamTypeRector --- .../skip_valid_type_from_return_doc.php.inc | 28 ++++++++++++++++ .../Source/ConnectionInterface.php | 9 +++++ .../Source/ConnectionResolverInterface.php | 14 ++++++++ .../Source/SqlServerConnection.php | 9 +++++ .../NodeAnalyzer/CallTypesResolver.php | 10 +++--- .../AccessoryNonEmptyArrayTypeCorrector.php | 33 +++++++++++++++++++ src/NodeTypeResolver/NodeTypeResolver.php | 20 +++++++---- 7 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/skip_valid_type_from_return_doc.php.inc create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/ConnectionInterface.php create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/ConnectionResolverInterface.php create mode 100644 rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/SqlServerConnection.php create mode 100644 src/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyArrayTypeCorrector.php diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/skip_valid_type_from_return_doc.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/skip_valid_type_from_return_doc.php.inc new file mode 100644 index 00000000000..cc18e96b6a0 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/FixtureIntersection/skip_valid_type_from_return_doc.php.inc @@ -0,0 +1,28 @@ +connection(); + + if ( + $connection instanceof SqlServerConnection + || ! method_exists($connection, 'getSchemaState') + ) { + return; + } + + $this->ensureCleanDatabase($connection); + } + + private function ensureCleanDatabase(ConnectionInterface $connection): void + { + } +} diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/ConnectionInterface.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/ConnectionInterface.php new file mode 100644 index 00000000000..2ce18164db5 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector/Source/ConnectionInterface.php @@ -0,0 +1,9 @@ +correctSelfType($argValueType); + $type = $this->nodeTypeResolver->getType($arg->value); + if (! $type->equals($argValueType) && $this->typeComparator->isSubtype($type, $argValueType)) { + return $type; + } + if (! $argValueType instanceof ObjectType) { return $argValueType; } @@ -69,11 +74,6 @@ private function resolveStrictArgValueType(Arg $arg): Type return new MixedType(); } - $type = $this->nodeTypeResolver->getType($arg->value); - if (! $type->equals($argValueType) && $this->typeComparator->isSubtype($type, $argValueType)) { - return $type; - } - return $argValueType; } diff --git a/src/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyArrayTypeCorrector.php b/src/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyArrayTypeCorrector.php new file mode 100644 index 00000000000..4c7b0bb32bc --- /dev/null +++ b/src/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyArrayTypeCorrector.php @@ -0,0 +1,33 @@ +isArray()->yes()) { + return $mainType; + } + + foreach ($mainType->getTypes() as $type) { + if ($type instanceof NonEmptyArrayType) { + return new ArrayType(new MixedType(), new MixedType()); + } + } + + return $mainType; + } +} diff --git a/src/NodeTypeResolver/NodeTypeResolver.php b/src/NodeTypeResolver/NodeTypeResolver.php index f26b0915393..54d97e4e712 100644 --- a/src/NodeTypeResolver/NodeTypeResolver.php +++ b/src/NodeTypeResolver/NodeTypeResolver.php @@ -51,6 +51,7 @@ 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; @@ -79,6 +80,7 @@ public function __construct( private readonly GenericClassStringTypeCorrector $genericClassStringTypeCorrector, private readonly ReflectionProvider $reflectionProvider, private readonly AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector, + private readonly AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector, private readonly RenamedClassesDataCollector $renamedClassesDataCollector, private readonly NodeNameResolver $nodeNameResolver, iterable $nodeTypeResolvers @@ -195,8 +197,7 @@ public function getType(Node $node): Type $type = $this->resolveByNodeTypeResolvers($node); if ($type instanceof Type) { - $type = $this->accessoryNonEmptyStringTypeCorrector->correct($type); - $type = $this->genericClassStringTypeCorrector->correct($type); + $type = $this->correctType($type); if ($type instanceof ObjectType) { $scope = $node->getAttribute(AttributeKey::SCOPE); @@ -231,9 +232,7 @@ public function getType(Node $node): Type return new MixedType(); } - $type = $scope->getType($node); - $type = $this->accessoryNonEmptyStringTypeCorrector->correct($type); - $type = $this->genericClassStringTypeCorrector->correct($type); + $type = $this->correctType($scope->getType($node)); // hot fix for phpstan not resolving chain method calls if (! $node instanceof MethodCall) { @@ -256,6 +255,15 @@ public function isNullableType(Node $node): bool return TypeCombinator::containsNull($nodeType); } + private function correctType(Type $type): Type + { + $type = $this->accessoryNonEmptyStringTypeCorrector->correct($type); + $type = $this->genericClassStringTypeCorrector->correct($type); + $type = $this->accessoryNonEmptyArrayTypeCorrector->correct($type); + + return $type; + } + public function getNativeType(Expr $expr): Type { $scope = $expr->getAttribute(AttributeKey::SCOPE); @@ -281,7 +289,7 @@ public function getNativeType(Expr $expr): Type return new ObjectWithoutClassType(); } - return $this->accessoryNonEmptyStringTypeCorrector->correct($type); + return $this->correctType($type); } return $this->resolveNativeUnionType($type); From 23f8fe9f621dfd7a189cf8931f96a515280df390 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 24 Aug 2025 14:19:26 +0000 Subject: [PATCH 2/2] [ci-review] Rector Rectify --- src/NodeTypeResolver/NodeTypeResolver.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/NodeTypeResolver/NodeTypeResolver.php b/src/NodeTypeResolver/NodeTypeResolver.php index 54d97e4e712..5ae596a31c1 100644 --- a/src/NodeTypeResolver/NodeTypeResolver.php +++ b/src/NodeTypeResolver/NodeTypeResolver.php @@ -259,9 +259,8 @@ private function correctType(Type $type): Type { $type = $this->accessoryNonEmptyStringTypeCorrector->correct($type); $type = $this->genericClassStringTypeCorrector->correct($type); - $type = $this->accessoryNonEmptyArrayTypeCorrector->correct($type); - return $type; + return $this->accessoryNonEmptyArrayTypeCorrector->correct($type); } public function getNativeType(Expr $expr): Type