[VarDumper] Support for ReflectionAttribute.
This commit is contained in:
parent
163a2ab2b3
commit
34dbf01618
3
.github/patch-types.php
vendored
3
.github/patch-types.php
vendored
@ -35,8 +35,11 @@ foreach ($loader->getClassMap() as $class => $file) {
|
||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php80Dummy.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/LotsOfAttributes.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php') && \PHP_VERSION_ID < 70400:
|
||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php'):
|
||||
continue 2;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,16 @@ class ReflectionCaster
|
||||
return $a;
|
||||
}
|
||||
|
||||
public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
self::addMap($a, $c, [
|
||||
'name' => 'getName',
|
||||
'arguments' => 'getArguments',
|
||||
]);
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
$prefix = Caster::PREFIX_VIRTUAL;
|
||||
@ -151,7 +161,7 @@ class ReflectionCaster
|
||||
self::addMap($a, $c, [
|
||||
'extends' => 'getParentClass',
|
||||
'implements' => 'getInterfaceNames',
|
||||
'constants' => 'getConstants',
|
||||
'constants' => 'getReflectionConstants',
|
||||
]);
|
||||
|
||||
foreach ($c->getProperties() as $n) {
|
||||
@ -162,6 +172,8 @@ class ReflectionCaster
|
||||
$a[$prefix.'methods'][$n->name] = $n;
|
||||
}
|
||||
|
||||
self::addAttributes($a, $c, $prefix);
|
||||
|
||||
if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
|
||||
self::addExtra($a, $c);
|
||||
}
|
||||
@ -206,6 +218,8 @@ class ReflectionCaster
|
||||
$a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);
|
||||
}
|
||||
|
||||
self::addAttributes($a, $c, $prefix);
|
||||
|
||||
if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {
|
||||
foreach ($v as $k => &$v) {
|
||||
if (\is_object($v)) {
|
||||
@ -225,6 +239,16 @@ class ReflectionCaster
|
||||
return $a;
|
||||
}
|
||||
|
||||
public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
|
||||
$a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();
|
||||
|
||||
self::addAttributes($a, $c);
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
|
||||
@ -243,6 +267,8 @@ class ReflectionCaster
|
||||
'allowsNull' => 'allowsNull',
|
||||
]);
|
||||
|
||||
self::addAttributes($a, $c, $prefix);
|
||||
|
||||
if ($v = $c->getType()) {
|
||||
$a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
|
||||
}
|
||||
@ -271,6 +297,8 @@ class ReflectionCaster
|
||||
public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)
|
||||
{
|
||||
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
|
||||
|
||||
self::addAttributes($a, $c);
|
||||
self::addExtra($a, $c);
|
||||
|
||||
return $a;
|
||||
@ -377,7 +405,7 @@ class ReflectionCaster
|
||||
}
|
||||
}
|
||||
|
||||
private static function addMap(array &$a, \Reflector $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
|
||||
private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
|
||||
{
|
||||
foreach ($map as $k => $m) {
|
||||
if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) {
|
||||
@ -389,4 +417,13 @@ class ReflectionCaster
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
foreach ($c->getAttributes() as $n) {
|
||||
$a[$prefix.'attributes'][] = $n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'],
|
||||
'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'],
|
||||
'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'],
|
||||
'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'],
|
||||
'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'],
|
||||
'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'],
|
||||
'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'],
|
||||
'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'],
|
||||
'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'],
|
||||
'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'],
|
||||
|
@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\Caster\Caster;
|
||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||
use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
|
||||
use Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes;
|
||||
use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass;
|
||||
|
||||
/**
|
||||
@ -36,9 +37,24 @@ ReflectionClass {
|
||||
0 => "Reflector"
|
||||
%A]
|
||||
constants: array:3 [
|
||||
"IS_IMPLICIT_ABSTRACT" => 16
|
||||
"IS_EXPLICIT_ABSTRACT" => %d
|
||||
"IS_FINAL" => %d
|
||||
0 => ReflectionClassConstant {
|
||||
+name: "IS_IMPLICIT_ABSTRACT"
|
||||
+class: "ReflectionClass"
|
||||
modifiers: "public"
|
||||
value: 16
|
||||
}
|
||||
1 => ReflectionClassConstant {
|
||||
+name: "IS_EXPLICIT_ABSTRACT"
|
||||
+class: "ReflectionClass"
|
||||
modifiers: "public"
|
||||
value: %d
|
||||
}
|
||||
2 => ReflectionClassConstant {
|
||||
+name: "IS_FINAL"
|
||||
+class: "ReflectionClass"
|
||||
modifiers: "public"
|
||||
value: %d
|
||||
}
|
||||
]
|
||||
properties: array:%d [
|
||||
"name" => ReflectionProperty {
|
||||
@ -75,7 +91,7 @@ Closure($x) {
|
||||
$b: & 123
|
||||
}
|
||||
file: "%sReflectionCasterTest.php"
|
||||
line: "68 to 68"
|
||||
line: "84 to 84"
|
||||
}
|
||||
EOTXT
|
||||
, $var
|
||||
@ -242,6 +258,135 @@ EODUMP;
|
||||
$this->assertDumpMatchesFormat($expectedDump, $generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testReflectionClassWithAttribute()
|
||||
{
|
||||
$var = new \ReflectionClass(LotsOfAttributes::class);
|
||||
|
||||
$this->assertDumpMatchesFormat(<<< 'EOTXT'
|
||||
ReflectionClass {
|
||||
+name: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
|
||||
%A attributes: array:1 [
|
||||
0 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
|
||||
arguments: []
|
||||
}
|
||||
]
|
||||
%A
|
||||
}
|
||||
EOTXT
|
||||
, $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testReflectionMethodWithAttribute()
|
||||
{
|
||||
$var = new \ReflectionMethod(LotsOfAttributes::class, 'someMethod');
|
||||
|
||||
$this->assertDumpMatchesFormat(<<< 'EOTXT'
|
||||
ReflectionMethod {
|
||||
+name: "someMethod"
|
||||
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
|
||||
%A attributes: array:1 [
|
||||
0 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
|
||||
arguments: array:1 [
|
||||
0 => "two"
|
||||
]
|
||||
}
|
||||
]
|
||||
%A
|
||||
}
|
||||
EOTXT
|
||||
, $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testReflectionPropertyWithAttribute()
|
||||
{
|
||||
$var = new \ReflectionProperty(LotsOfAttributes::class, 'someProperty');
|
||||
|
||||
$this->assertDumpMatchesFormat(<<< 'EOTXT'
|
||||
ReflectionProperty {
|
||||
+name: "someProperty"
|
||||
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
|
||||
%A attributes: array:1 [
|
||||
0 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
|
||||
arguments: array:2 [
|
||||
0 => "one"
|
||||
"extra" => "hello"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOTXT
|
||||
, $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testReflectionClassConstantWithAttribute()
|
||||
{
|
||||
$var = new \ReflectionClassConstant(LotsOfAttributes::class, 'SOME_CONSTANT');
|
||||
|
||||
$this->assertDumpMatchesFormat(<<< 'EOTXT'
|
||||
ReflectionClassConstant {
|
||||
+name: "SOME_CONSTANT"
|
||||
+class: "Symfony\Component\VarDumper\Tests\Fixtures\LotsOfAttributes"
|
||||
modifiers: "public"
|
||||
value: "some value"
|
||||
attributes: array:2 [
|
||||
0 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\RepeatableAttribute"
|
||||
arguments: array:1 [
|
||||
0 => "one"
|
||||
]
|
||||
}
|
||||
1 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\RepeatableAttribute"
|
||||
arguments: array:1 [
|
||||
0 => "two"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOTXT
|
||||
, $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testReflectionParameterWithAttribute()
|
||||
{
|
||||
$var = new \ReflectionParameter([LotsOfAttributes::class, 'someMethod'], 'someParameter');
|
||||
|
||||
$this->assertDumpMatchesFormat(<<< 'EOTXT'
|
||||
ReflectionParameter {
|
||||
+name: "someParameter"
|
||||
position: 0
|
||||
attributes: array:1 [
|
||||
0 => ReflectionAttribute {
|
||||
name: "Symfony\Component\VarDumper\Tests\Fixtures\MyAttribute"
|
||||
arguments: array:1 [
|
||||
0 => "three"
|
||||
]
|
||||
}
|
||||
]
|
||||
%A
|
||||
}
|
||||
EOTXT
|
||||
, $var);
|
||||
}
|
||||
|
||||
public static function stub(): void
|
||||
{
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests\Fixtures;
|
||||
|
||||
#[MyAttribute]
|
||||
final class LotsOfAttributes
|
||||
{
|
||||
#[RepeatableAttribute('one'), RepeatableAttribute('two')]
|
||||
public const SOME_CONSTANT = 'some value';
|
||||
|
||||
#[MyAttribute('one', extra: 'hello')]
|
||||
private string $someProperty;
|
||||
|
||||
#[MyAttribute('two')]
|
||||
public function someMethod(
|
||||
#[MyAttribute('three')] string $someParameter
|
||||
): void {
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests\Fixtures;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute]
|
||||
final class MyAttribute
|
||||
{
|
||||
public function __construct(
|
||||
private string $foo = 'default',
|
||||
private ?string $extra = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getFoo(): string
|
||||
{
|
||||
return $this->foo;
|
||||
}
|
||||
|
||||
public function getExtra(): ?string
|
||||
{
|
||||
return $this->extra;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests\Fixtures;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS_CONST | Attribute::TARGET_PROPERTY)]
|
||||
final class RepeatableAttribute
|
||||
{
|
||||
private string $string;
|
||||
|
||||
public function __construct(string $string = 'default')
|
||||
{
|
||||
$this->string = $string;
|
||||
}
|
||||
|
||||
public function getString(): string
|
||||
{
|
||||
return $this->string;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user