diff --git a/src/Reflection/ReflectionProperty.php b/src/Reflection/ReflectionProperty.php index 8761a32df..87b1a861e 100644 --- a/src/Reflection/ReflectionProperty.php +++ b/src/Reflection/ReflectionProperty.php @@ -309,7 +309,8 @@ public function isFinal(): bool public function isAbstract(): bool { - return (bool) ($this->modifiers & ReflectionPropertyAdapter::IS_ABSTRACT_COMPATIBILITY); + return (bool) ($this->modifiers & ReflectionPropertyAdapter::IS_ABSTRACT_COMPATIBILITY) + || $this->declaringClass->isInterface(); } public function isPromoted(): bool diff --git a/test/unit/Fixture/PropertyHooks.php b/test/unit/Fixture/PropertyHooks.php index 830162b23..1619c6588 100644 --- a/test/unit/Fixture/PropertyHooks.php +++ b/test/unit/Fixture/PropertyHooks.php @@ -164,3 +164,8 @@ class FinalPropertyHooks final set => strtolower($value); } } + +interface InterfaceWithProperty +{ + public int $abstractPropertyFromInterface { get; set; } +} diff --git a/test/unit/Reflection/ReflectionPropertyTest.php b/test/unit/Reflection/ReflectionPropertyTest.php index 4ccff5977..3c52951ef 100644 --- a/test/unit/Reflection/ReflectionPropertyTest.php +++ b/test/unit/Reflection/ReflectionPropertyTest.php @@ -1021,6 +1021,15 @@ public function testIsAbstract(): void self::assertTrue($hookProperty->isAbstract()); } + public function testIsAbstractInInterface(): void + { + $reflector = new DefaultReflector(new SingleFileSourceLocator(__DIR__ . '/../Fixture/PropertyHooks.php', $this->astLocator)); + $classInfo = $reflector->reflectClass('Roave\BetterReflectionTest\Fixture\InterfaceWithProperty'); + + $abstractProperty = $classInfo->getProperty('abstractPropertyFromInterface'); + self::assertTrue($abstractProperty->isAbstract()); + } + public function testNoHooks(): void { $classInfo = $this->reflector->reflectClass(ExampleClass::class);