Skip to content

Commit d5cdeb9

Browse files
authored
Merge pull request #1383 from kukulich/final
Support for final modifier in traits
2 parents b656bf3 + 483e9d6 commit d5cdeb9

File tree

5 files changed

+57
-4
lines changed

5 files changed

+57
-4
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Better Reflection - an improved code reflection API",
44
"license": "MIT",
55
"require": {
6-
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
6+
"php": "~8.1.0 || ~8.2.0 || ~8.3.2",
77
"ext-json": "*",
88
"jetbrains/phpstorm-stubs": "2023.3",
99
"nikic/php-parser": "^4.18.0",

composer.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Reflection/ReflectionClass.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,13 @@ private function createMethodsFromTrait(ReflectionMethod $method): array
357357

358358
if (array_key_exists($methodHash, $this->traitsData['modifiers'])) {
359359
// PhpParser modifiers are compatible with PHP reflection modifiers
360-
$methodModifiers = ($methodModifiers & ~ Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) | $this->traitsData['modifiers'][$methodHash];
360+
if ($this->traitsData['modifiers'][$methodHash] & Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) {
361+
$methodModifiers = ($methodModifiers & ~ Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) | $this->traitsData['modifiers'][$methodHash];
362+
}
363+
364+
if ($this->traitsData['modifiers'][$methodHash] & Node\Stmt\Class_::MODIFIER_FINAL) {
365+
$methodModifiers |= Node\Stmt\Class_::MODIFIER_FINAL;
366+
}
361367
}
362368

363369
$createMethod = function (string|null $aliasMethodName) use ($method, $methodModifiers): ReflectionMethod {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
trait SimpleTrait
4+
{
5+
protected function foo() {}
6+
final protected function boo() {}
7+
}
8+
9+
class TraitFixtureWithFinal
10+
{
11+
use SimpleTrait {
12+
foo as final;
13+
}
14+
}
15+
16+
class TraitFixtureWithPublic
17+
{
18+
use SimpleTrait {
19+
boo as public;
20+
}
21+
}

test/unit/Reflection/ReflectionClassTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PHPUnit\Framework\Attributes\CoversClass;
1616
use PHPUnit\Framework\Attributes\CoversNothing;
1717
use PHPUnit\Framework\Attributes\DataProvider;
18+
use PHPUnit\Framework\Attributes\RequiresPhp;
1819
use PHPUnit\Framework\TestCase;
1920
use Qux;
2021
use ReflectionClass as CoreReflectionClass;
@@ -1617,6 +1618,31 @@ public function testMethodsFromTraits(): void
16171618
self::assertSame('TraitFixtureTraitC2', $classInfo->getMethod('d_renamed')->getDeclaringClass()->getName());
16181619
}
16191620

1621+
#[RequiresPhp('8.3')]
1622+
public function testMethodsFromTraitsWithFinal(): void
1623+
{
1624+
$reflector = new DefaultReflector(new SingleFileSourceLocator(
1625+
__DIR__ . '/../Fixture/TraitFixtureWithFinal.php',
1626+
$this->astLocator,
1627+
));
1628+
1629+
$classInfo = $reflector->reflectClass('TraitFixtureWithFinal');
1630+
1631+
self::assertTrue($classInfo->hasMethod('foo'));
1632+
self::assertTrue($classInfo->getMethod('foo')->isFinal());
1633+
self::assertFalse($classInfo->getMethod('foo')->isPrivate());
1634+
self::assertTrue($classInfo->getMethod('foo')->isProtected());
1635+
self::assertFalse($classInfo->getMethod('foo')->isPublic());
1636+
1637+
$classInfo = $reflector->reflectClass('TraitFixtureWithPublic');
1638+
1639+
self::assertTrue($classInfo->hasMethod('boo'));
1640+
self::assertTrue($classInfo->getMethod('boo')->isFinal());
1641+
self::assertFalse($classInfo->getMethod('boo')->isPrivate());
1642+
self::assertFalse($classInfo->getMethod('boo')->isProtected());
1643+
self::assertTrue($classInfo->getMethod('boo')->isPublic());
1644+
}
1645+
16201646
public function testMethodsFromTraitsWithConflicts(): void
16211647
{
16221648
$reflector = new DefaultReflector(new SingleFileSourceLocator(

0 commit comments

Comments
 (0)