diff --git a/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php b/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php index f77ef8c1..7824749b 100644 --- a/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php +++ b/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php @@ -26,6 +26,7 @@ use CuyZ\Valinor\Type\Type; use CuyZ\Valinor\Type\Types\UnresolvableType; use CuyZ\Valinor\Utility\Reflection\Reflection; +use ReflectionClass; use ReflectionMethod; use ReflectionProperty; use CuyZ\Valinor\Utility\Reflection\DocParser; @@ -77,7 +78,7 @@ private function properties(ClassType $type): array { return array_map( function (ReflectionProperty $property) use ($type) { - $typeResolver = $this->typeResolver($type, $property->class); + $typeResolver = $this->typeResolver($type, $property->getDeclaringClass()); return $this->propertyBuilder->for($property, $typeResolver); }, @@ -101,21 +102,26 @@ private function methods(ClassType $type): array } return array_map(function (ReflectionMethod $method) use ($type) { - $typeResolver = $this->typeResolver($type, $method->class); + $typeResolver = $this->typeResolver($type, $method->getDeclaringClass()); return $this->methodBuilder->for($method, $typeResolver); }, $methods); } - private function typeResolver(ClassType $type, string $targetClass): ReflectionTypeResolver + /** + * @param ReflectionClass $target + */ + private function typeResolver(ClassType $type, ReflectionClass $target): ReflectionTypeResolver { - $typeKey = "{$type->toString()}/$targetClass"; + $typeKey = $target->isInterface() + ? "{$type->toString()}/{$type->className()}" + : "{$type->toString()}/$target->name"; if (isset($this->typeResolver[$typeKey])) { return $this->typeResolver[$typeKey]; } - while ($type->className() !== $targetClass) { + while ($type->className() !== $target->name) { $type = $type->parent(); } diff --git a/tests/Fixture/Object/AbstractObjectWithInterface.php b/tests/Fixture/Object/AbstractObjectWithInterface.php new file mode 100644 index 00000000..b3a7d6d0 --- /dev/null +++ b/tests/Fixture/Object/AbstractObjectWithInterface.php @@ -0,0 +1,10 @@ +defaultValue()); } + public function test_methods_can_be_retrieved_from_abstract_object_with_interface_and_with_method_referencing_self(): void + { + $type = new NativeClassType(AbstractObjectWithInterface::class); + $methods = $this->repository->for($type)->methods(); + + self::assertTrue($methods->has('of')); + self::assertTrue($methods->has('jsonSerialize')); + } + public function test_private_parent_constructor_is_listed_in_methods(): void { $type = new NativeClassType(ClassWithInheritedPrivateConstructor::class, parent: new NativeClassType(AbstractClassWithPrivateConstructor::class));