From e4f1f1bab4d008108bf537ba3877dc2c4e64fa25 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 8 Sep 2023 01:34:31 +0700 Subject: [PATCH] [NodeTypeResolver] Handle isObjectType() on new $class dynamic variable should return false compare to Object FQCN (#4936) * [NodeTypeResolver] Handle isObjectType() on new $class dynamic variable should return false compare to Object FQCN * Fixed :tada: * use equal check * return false directly, ObjectWithoutClassType is not ObjectType * Fix * failing fixture * Fix phpstan * Fixed :tada: * Fixed :tada: * [ci-review] Rector Rectify --------- Co-authored-by: GitHub Action --- .../NewTypeResolver/NewTypeResolverTest.php | 56 +++++++++++++++++++ .../NewTypeResolver/Source/NewDynamicNew.php | 11 ++++ .../Source/NewDynamicNewExtends.php | 11 ++++ .../NodeTypeResolver/NodeTypeResolver.php | 20 +++++++ 4 files changed, 98 insertions(+) create mode 100644 packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/NewTypeResolverTest.php create mode 100644 packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/Source/NewDynamicNew.php create mode 100644 packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/Source/NewDynamicNewExtends.php diff --git a/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/NewTypeResolverTest.php b/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/NewTypeResolverTest.php new file mode 100644 index 00000000000..e2de6dbc18b --- /dev/null +++ b/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/NewTypeResolverTest.php @@ -0,0 +1,56 @@ +getNodesForFileOfType($file, New_::class); + + $resolvedType = $this->nodeTypeResolver->getType($newNodes[$nodePosition]); + $this->assertEquals($expectedType, $resolvedType); + + $this->assertEquals( + $isObjectType, + $this->nodeTypeResolver->isObjectType( + $newNodes[$nodePosition], + new ObjectType('Symfony\Bundle\TwigBundle\Loader\FilesystemLoader') + ) + ); + } + + /** + * @return Iterator + */ + public static function provideData(): Iterator + { + $objectWithoutClassType = new ObjectWithoutClassType(); + + # test new + yield [__DIR__ . '/Source/NewDynamicNew.php', 0, $objectWithoutClassType, false]; + + $objectWithoutClassTypeWithParentTypes = new ObjectWithoutClassTypeWithParentTypes( + [ + new FullyQualifiedObjectType('Symfony\Bundle\TwigBundle\Loader\FilesystemLoader') + ] + ); + yield [__DIR__ . '/Source/NewDynamicNewExtends.php', 0, $objectWithoutClassTypeWithParentTypes, true]; + } +} diff --git a/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/Source/NewDynamicNew.php b/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/Source/NewDynamicNew.php new file mode 100644 index 00000000000..7b2fe673201 --- /dev/null +++ b/packages-tests/NodeTypeResolver/PerNodeTypeResolver/NewTypeResolver/Source/NewDynamicNew.php @@ -0,0 +1,11 @@ +isMatchObjectWithoutClassType($resolvedType, $requiredObjectType); + } + return $this->isMatchingUnionType($resolvedType, $requiredObjectType); } @@ -326,6 +331,21 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType return $classReflection->isSubclassOf($objectType->getClassName()); } + private function isMatchObjectWithoutClassType( + ObjectWithoutClassType $objectWithoutClassType, + ObjectType $requiredObjectType + ): bool { + if ($objectWithoutClassType instanceof ObjectWithoutClassTypeWithParentTypes) { + foreach ($objectWithoutClassType->getParentTypes() as $typeWithClassName) { + if ($requiredObjectType->isSuperTypeOf($typeWithClassName)->yes()) { + return true; + } + } + } + + return false; + } + private function isAnonymousObjectType(Type $type): bool { return $type instanceof ObjectType && $this->classAnalyzer->isAnonymousClassName($type->getClassName());