Repository: Roave/BetterReflection (php)

Issue:
Verify implementation of `ReflectionMethod#isAbstract()`
Ref https://github.com/Roave/BetterReflection/pull/586#discussion_r430921287

BetterReflection does not seem to mark reflection methods as abstract when they are declared in interfaces, but not defined in concrete classes.

Pull request:
ReflectionMethod::isAbstract() should return true for interface methods
Fixes #596 

Patch:
diff --git a/src/Reflection/Adapter/ReflectionMethod.php b/src/Reflection/Adapter/ReflectionMethod.php
index 53709fbc..2bf25a2d 100644
--- a/src/Reflection/Adapter/ReflectionMethod.php
+++ b/src/Reflection/Adapter/ReflectionMethod.php
@@ -276,7 +276,7 @@ class ReflectionMethod extends CoreReflectionMethod
      */
     public function isAbstract()
     {
-        return $this->betterReflectionMethod->isAbstract() || $this->betterReflectionMethod->getDeclaringClass()->isInterface();
+        return $this->betterReflectionMethod->isAbstract();
     }
 
     /**
diff --git a/src/Reflection/ReflectionMethod.php b/src/Reflection/ReflectionMethod.php
index 323a8217..a6449b7e 100644
--- a/src/Reflection/ReflectionMethod.php
+++ b/src/Reflection/ReflectionMethod.php
@@ -171,7 +171,7 @@ class ReflectionMethod extends ReflectionFunctionAbstract
      */
     public function isAbstract() : bool
     {
-        return $this->methodNode->isAbstract();
+        return $this->methodNode->isAbstract() || $this->declaringClass->isInterface();
     }
 
     /**


Test patch:
diff --git a/test/unit/Reflection/Adapter/ReflectionMethodTest.php b/test/unit/Reflection/Adapter/ReflectionMethodTest.php
index 04cb9ff9..fae6b782 100644
--- a/test/unit/Reflection/Adapter/ReflectionMethodTest.php
+++ b/test/unit/Reflection/Adapter/ReflectionMethodTest.php
@@ -392,24 +392,4 @@ class ReflectionMethodTest extends TestCase
         $this->expectException(CoreReflectionException::class);
         $reflectionMethodAdapter->invokeArgs();
     }
-
-    public function testIsAbstractWhenDeclaringClassIsInterface() : void
-    {
-        $betterReflectionClass = $this->createMock(BetterReflectionClass::class);
-        $betterReflectionClass
-            ->method('isInterface')
-            ->willReturn(true);
-
-        $betterReflectionMethod = $this->createMock(BetterReflectionMethod::class);
-        $betterReflectionMethod
-            ->method('isAbstract')
-            ->willReturn(false);
-        $betterReflectionMethod
-            ->method('getDeclaringClass')
-            ->willReturn($betterReflectionClass);
-
-        $reflectionMethodAdapter = new ReflectionMethodAdapter($betterReflectionMethod);
-
-        self::assertTrue($reflectionMethodAdapter->isAbstract());
-    }
 }
diff --git a/test/unit/Reflection/ReflectionMethodTest.php b/test/unit/Reflection/ReflectionMethodTest.php
index 2324234d..0f0c36e5 100644
--- a/test/unit/Reflection/ReflectionMethodTest.php
+++ b/test/unit/Reflection/ReflectionMethodTest.php
@@ -123,6 +123,14 @@ class ReflectionMethodTest extends TestCase
         self::assertSame($shouldBeStatic, $reflectionMethod->isStatic());
     }
 
+    public function testIsAbstractForMethodInInterface() : void
+    {
+        $classInfo  = $this->reflector->reflect(InterfaceWithMethod::class);
+        $methodInfo = $classInfo->getMethod('someMethod');
+
+        self::assertTrue($methodInfo->isAbstract());
+    }
+
     public function testIsConstructorDestructor() : void
     {
         $classInfo = $this->reflector->reflect(Methods::class);