Skip to content

Commit 34dbf01

Browse files
committed
[VarDumper] Support for ReflectionAttribute.
1 parent 163a2ab commit 34dbf01

File tree

7 files changed

+285
-6
lines changed

7 files changed

+285
-6
lines changed

.github/patch-types.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@
3535
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php80Dummy.php'):
3636
case false !== strpos($file, '/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures'):
3737
case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'):
38+
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/LotsOfAttributes.php'):
39+
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php'):
3840
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'):
3941
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php') && \PHP_VERSION_ID < 70400:
42+
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php'):
4043
continue 2;
4144
}
4245

src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $
105105
return $a;
106106
}
107107

108+
public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
109+
{
110+
self::addMap($a, $c, [
111+
'name' => 'getName',
112+
'arguments' => 'getArguments',
113+
]);
114+
115+
return $a;
116+
}
117+
108118
public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)
109119
{
110120
$prefix = Caster::PREFIX_VIRTUAL;
@@ -151,7 +161,7 @@ public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool
151161
self::addMap($a, $c, [
152162
'extends' => 'getParentClass',
153163
'implements' => 'getInterfaceNames',
154-
'constants' => 'getConstants',
164+
'constants' => 'getReflectionConstants',
155165
]);
156166

157167
foreach ($c->getProperties() as $n) {
@@ -162,6 +172,8 @@ public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool
162172
$a[$prefix.'methods'][$n->name] = $n;
163173
}
164174

175+
self::addAttributes($a, $c, $prefix);
176+
165177
if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
166178
self::addExtra($a, $c);
167179
}
@@ -206,6 +218,8 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra
206218
$a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);
207219
}
208220

221+
self::addAttributes($a, $c, $prefix);
222+
209223
if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {
210224
foreach ($v as $k => &$v) {
211225
if (\is_object($v)) {
@@ -225,6 +239,16 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra
225239
return $a;
226240
}
227241

242+
public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)
243+
{
244+
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
245+
$a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();
246+
247+
self::addAttributes($a, $c);
248+
249+
return $a;
250+
}
251+
228252
public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)
229253
{
230254
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
@@ -243,6 +267,8 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st
243267
'allowsNull' => 'allowsNull',
244268
]);
245269

270+
self::addAttributes($a, $c, $prefix);
271+
246272
if ($v = $c->getType()) {
247273
$a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
248274
}
@@ -271,6 +297,8 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st
271297
public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)
272298
{
273299
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
300+
301+
self::addAttributes($a, $c);
274302
self::addExtra($a, $c);
275303

276304
return $a;
@@ -377,7 +405,7 @@ private static function addExtra(array &$a, \Reflector $c)
377405
}
378406
}
379407

380-
private static function addMap(array &$a, \Reflector $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
408+
private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
381409
{
382410
foreach ($map as $k => $m) {
383411
if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) {
@@ -389,4 +417,13 @@ private static function addMap(array &$a, \Reflector $c, array $map, string $pre
389417
}
390418
}
391419
}
420+
421+
private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void
422+
{
423+
if (\PHP_VERSION_ID >= 80000) {
424+
foreach ($c->getAttributes() as $n) {
425+
$a[$prefix.'attributes'][] = $n;
426+
}
427+
}
428+
}
392429
}

src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ abstract class AbstractCloner implements ClonerInterface
3232
'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'],
3333
'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'],
3434
'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'],
35+
'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'],
3536
'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'],
3637
'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'],
38+
'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'],
3739
'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'],
3840
'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'],
3941
'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'],

src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php

Lines changed: 149 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\VarDumper\Caster\Caster;
1616
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
1717
use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
18+
use Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes;
1819
use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass;
1920

2021
/**
@@ -36,9 +37,24 @@ public function testReflectionCaster()
3637
0 => "Reflector"
3738
%A]
3839
constants: array:3 [
39-
"IS_IMPLICIT_ABSTRACT" => 16
40-
"IS_EXPLICIT_ABSTRACT" => %d
41-
"IS_FINAL" => %d
40+
0 => ReflectionClassConstant {
41+
+name: "IS_IMPLICIT_ABSTRACT"
42+
+class: "ReflectionClass"
43+
modifiers: "public"
44+
value: 16
45+
}
46+
1 => ReflectionClassConstant {
47+
+name: "IS_EXPLICIT_ABSTRACT"
48+
+class: "ReflectionClass"
49+
modifiers: "public"
50+
value: %d
51+
}
52+
2 => ReflectionClassConstant {
53+
+name: "IS_FINAL"
54+
+class: "ReflectionClass"
55+
modifiers: "public"
56+
value: %d
57+
}
4258
]
4359
properties: array:%d [
4460
"name" => ReflectionProperty {
@@ -75,7 +91,7 @@ public function testClosureCaster()
7591
$b: & 123
7692
}
7793
file: "%sReflectionCasterTest.php"
78-
line: "68 to 68"
94+
line: "84 to 84"
7995
}
8096
EOTXT
8197
, $var
@@ -242,6 +258,135 @@ public function testGenerator()
242258
$this->assertDumpMatchesFormat($expectedDump, $generator);
243259
}
244260

261+
/**
262+
* @requires PHP 8
263+
*/
264+
public function testReflectionClassWithAttribute()
265+
{
266+
$var = new \ReflectionClass(LotsOfAttributes::class);
267+
268+
$this->assertDumpMatchesFormat(<<< 'EOTXT'
269+
ReflectionClass {
270+
+name: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
271+
%A attributes: array:1 [
272+
0 => ReflectionAttribute {
273+
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
274+
arguments: []
275+
}
276+
]
277+
%A
278+
}
279+
EOTXT
280+
, $var);
281+
}
282+
283+
/**
284+
* @requires PHP 8
285+
*/
286+
public function testReflectionMethodWithAttribute()
287+
{
288+
$var = new \ReflectionMethod(LotsOfAttributes::class, 'someMethod');
289+
290+
$this->assertDumpMatchesFormat(<<< 'EOTXT'
291+
ReflectionMethod {
292+
+name: "someMethod"
293+
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
294+
%A attributes: array:1 [
295+
0 => ReflectionAttribute {
296+
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
297+
arguments: array:1 [
298+
0 => "two"
299+
]
300+
}
301+
]
302+
%A
303+
}
304+
EOTXT
305+
, $var);
306+
}
307+
308+
/**
309+
* @requires PHP 8
310+
*/
311+
public function testReflectionPropertyWithAttribute()
312+
{
313+
$var = new \ReflectionProperty(LotsOfAttributes::class, 'someProperty');
314+
315+
$this->assertDumpMatchesFormat(<<< 'EOTXT'
316+
ReflectionProperty {
317+
+name: "someProperty"
318+
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
319+
%A attributes: array:1 [
320+
0 => ReflectionAttribute {
321+
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
322+
arguments: array:2 [
323+
0 => "one"
324+
"extra" => "hello"
325+
]
326+
}
327+
]
328+
}
329+
EOTXT
330+
, $var);
331+
}
332+
333+
/**
334+
* @requires PHP 8
335+
*/
336+
public function testReflectionClassConstantWithAttribute()
337+
{
338+
$var = new \ReflectionClassConstant(LotsOfAttributes::class, 'SOME_CONSTANT');
339+
340+
$this->assertDumpMatchesFormat(<<< 'EOTXT'
341+
ReflectionClassConstant {
342+
+name: "SOME_CONSTANT"
343+
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
344+
modifiers: "public"
345+
value: "some value"
346+
attributes: array:2 [
347+
0 => ReflectionAttribute {
348+
name: "Symfony\Component\VarDumper\Tests\Fixtures\RepeatableAttribute"
349+
arguments: array:1 [
350+
0 => "one"
351+
]
352+
}
353+
1 => ReflectionAttribute {
354+
name: "Symfony\Component\VarDumper\Tests\Fixtures\RepeatableAttribute"
355+
arguments: array:1 [
356+
0 => "two"
357+
]
358+
}
359+
]
360+
}
361+
EOTXT
362+
, $var);
363+
}
364+
365+
/**
366+
* @requires PHP 8
367+
*/
368+
public function testReflectionParameterWithAttribute()
369+
{
370+
$var = new \ReflectionParameter([LotsOfAttributes::class, 'someMethod'], 'someParameter');
371+
372+
$this->assertDumpMatchesFormat(<<< 'EOTXT'
373+
ReflectionParameter {
374+
+name: "someParameter"
375+
position: 0
376+
attributes: array:1 [
377+
0 => ReflectionAttribute {
378+
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
379+
arguments: array:1 [
380+
0 => "three"
381+
]
382+
}
383+
]
384+
%A
385+
}
386+
EOTXT
387+
, $var);
388+
}
389+
245390
public static function stub(): void
246391
{
247392
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Fixtures;
13+
14+
#[MyAttribute]
15+
final class LotsOfAttributes
16+
{
17+
#[RepeatableAttribute('one'), RepeatableAttribute('two')]
18+
public const SOME_CONSTANT = 'some value';
19+
20+
#[MyAttribute('one', extra: 'hello')]
21+
private string $someProperty;
22+
23+
#[MyAttribute('two')]
24+
public function someMethod(
25+
#[MyAttribute('three')] string $someParameter
26+
): void {
27+
}
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Fixtures;
13+
14+
use Attribute;
15+
16+
#[Attribute]
17+
final class MyAttribute
18+
{
19+
public function __construct(
20+
private string $foo = 'default',
21+
private ?string $extra = null,
22+
) {
23+
}
24+
25+
public function getFoo(): string
26+
{
27+
return $this->foo;
28+
}
29+
30+
public function getExtra(): ?string
31+
{
32+
return $this->extra;
33+
}
34+
}

0 commit comments

Comments
 (0)