Skip to content

Commit 07d78b2

Browse files
authored
ClassReflection: make getTraits recursive
1 parent 498b868 commit 07d78b2

File tree

3 files changed

+163
-4
lines changed

3 files changed

+163
-4
lines changed

src/Reflection/ClassReflection.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,13 +670,36 @@ public function getInterfaces(): array
670670
}
671671

672672
/**
673-
* @return \PHPStan\Reflection\ClassReflection[]
673+
* @return array<string, \PHPStan\Reflection\ClassReflection>
674674
*/
675-
public function getTraits(): array
675+
public function getTraits(bool $recursive = false): array
676676
{
677-
return array_map(function (\ReflectionClass $trait): ClassReflection {
677+
$traits = [];
678+
679+
if ($recursive) {
680+
foreach ($this->collectTraits($this->getNativeReflection()) as $trait) {
681+
$traits[$trait->getName()] = $trait;
682+
}
683+
} else {
684+
$traits = $this->getNativeReflection()->getTraits();
685+
}
686+
687+
$traits = array_map(function (\ReflectionClass $trait): ClassReflection {
678688
return $this->reflectionProvider->getClass($trait->getName());
679-
}, $this->getNativeReflection()->getTraits());
689+
}, $traits);
690+
691+
if ($recursive) {
692+
$parentClass = $this->getNativeReflection()->getParentClass();
693+
694+
if ($parentClass !== false) {
695+
return array_merge(
696+
$traits,
697+
$this->reflectionProvider->getClass($parentClass->getName())->getTraits(true)
698+
);
699+
}
700+
}
701+
702+
return $traits;
680703
}
681704

682705
/**

tests/PHPStan/Reflection/ClassReflectionTest.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,100 @@ public function testDeprecatedConstantFromAnotherFile(): void
220220
$this->assertTrue($constant->isDeprecated()->yes());
221221
}
222222

223+
/**
224+
* @dataProvider dataNestedRecursiveTraits
225+
* @param class-string $className
226+
* @param array<class-string, class-string> $expected
227+
* @param bool $recursive
228+
*/
229+
public function testGetTraits(string $className, array $expected, bool $recursive): void
230+
{
231+
$reflectionProvider = $this->createBroker();
232+
233+
$this->assertSame(
234+
array_map(
235+
static function (ClassReflection $classReflection): string {
236+
return $classReflection->getNativeReflection()->getName();
237+
},
238+
$reflectionProvider->getClass($className)->getTraits($recursive)
239+
),
240+
$expected
241+
);
242+
}
243+
244+
public function dataNestedRecursiveTraits(): array
245+
{
246+
return [
247+
[
248+
\NestedTraits\NoTrait::class,
249+
[],
250+
false,
251+
],
252+
[
253+
\NestedTraits\NoTrait::class,
254+
[],
255+
true,
256+
],
257+
[
258+
\NestedTraits\Foo::class,
259+
[
260+
\NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class,
261+
],
262+
false,
263+
],
264+
[
265+
\NestedTraits\Foo::class,
266+
[
267+
\NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class,
268+
],
269+
true,
270+
],
271+
[
272+
\NestedTraits\Bar::class,
273+
[
274+
\NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class,
275+
],
276+
false,
277+
],
278+
[
279+
\NestedTraits\Bar::class,
280+
[
281+
\NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class,
282+
\NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class,
283+
],
284+
true,
285+
],
286+
[
287+
\NestedTraits\Baz::class,
288+
[
289+
\NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class,
290+
],
291+
false,
292+
],
293+
[
294+
\NestedTraits\Baz::class,
295+
[
296+
\NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class,
297+
\NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class,
298+
\NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class,
299+
],
300+
true,
301+
],
302+
[
303+
\NestedTraits\BazChild::class,
304+
[],
305+
false,
306+
],
307+
[
308+
\NestedTraits\BazChild::class,
309+
[
310+
\NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class,
311+
\NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class,
312+
\NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class,
313+
],
314+
true,
315+
],
316+
];
317+
}
318+
223319
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace NestedTraits;
4+
5+
trait FooTrait
6+
{
7+
}
8+
9+
trait BarTrait
10+
{
11+
use FooTrait;
12+
}
13+
14+
trait BazTrait
15+
{
16+
use BarTrait;
17+
}
18+
19+
class NoTrait
20+
{
21+
}
22+
23+
class Foo
24+
{
25+
use FooTrait;
26+
}
27+
28+
class Bar
29+
{
30+
use BarTrait;
31+
}
32+
33+
class Baz
34+
{
35+
use BazTrait;
36+
}
37+
38+
class BazChild extends Baz
39+
{
40+
}

0 commit comments

Comments
 (0)