fix: handle nested attributes compilation

This commit is contained in:
Aurimas Niekis 2021-12-27 21:02:48 +02:00 committed by Romain Canon
parent 54f608e5b1
commit d2795bc6b9
4 changed files with 124 additions and 1 deletions

View File

@ -91,7 +91,8 @@ final class AttributesCompiler
/** @infection-ignore-all */
if (count($arguments) > 0) {
$arguments = var_export($arguments, true);
$arguments = serialize($arguments);
$arguments = 'unserialize(' . var_export($arguments, true) . ')';
return "new $name(...$arguments)";
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Fixture\Attribute;
use Attribute;
#[Attribute]
final class NestedAttribute
{
public function __construct(
/** @var list<object> */
public array $nestedAttributes,
) {
}
}

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Fixture\Object;
use CuyZ\Valinor\Tests\Fixture\Attribute\AttributeWithArguments;
use CuyZ\Valinor\Tests\Fixture\Attribute\BasicAttribute;
use CuyZ\Valinor\Tests\Fixture\Attribute\NestedAttribute;
#[BasicAttribute]
#[AttributeWithArguments('foo', 'bar')]
#[NestedAttribute([
new BasicAttribute(),
new AttributeWithArguments('foo', 'bar'),
])]
// @PHP8.0 move to anonymous class
final class ObjectWithNestedAttributes
{
#[BasicAttribute]
#[AttributeWithArguments('foo', 'bar')]
#[NestedAttribute([
new BasicAttribute(),
new AttributeWithArguments('foo', 'bar'),
])]
public bool $property;
#[BasicAttribute]
#[AttributeWithArguments('foo', 'bar')]
#[NestedAttribute([
new BasicAttribute(),
new AttributeWithArguments('foo', 'bar'),
])]
public function method(#[BasicAttribute] string $parameter): void
{
}
}

View File

@ -13,7 +13,9 @@ use CuyZ\Valinor\Tests\Fixture\Annotation\AnnotationWithArguments;
use CuyZ\Valinor\Tests\Fixture\Annotation\BasicAnnotation;
use CuyZ\Valinor\Tests\Fixture\Attribute\AttributeWithArguments;
use CuyZ\Valinor\Tests\Fixture\Attribute\BasicAttribute;
use CuyZ\Valinor\Tests\Fixture\Attribute\NestedAttribute;
use CuyZ\Valinor\Tests\Fixture\Object\ObjectWithAttributes;
use CuyZ\Valinor\Tests\Fixture\Object\ObjectWithNestedAttributes;
use Error;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
@ -254,6 +256,72 @@ final class AttributesCompilerTest extends TestCase
self::assertTrue($attributes->has(AnnotationWithArguments::class));
}
/**
* @requires PHP >= 8.1
*/
public function test_compiles_native_php_attributes_for_class_with_nested_attributes(): void
{
$reflection = new ReflectionClass(ObjectWithNestedAttributes::class);
$attributes = $this->compile(new NativeAttributes($reflection));
self::assertCount(3, $attributes);
self::assertTrue($attributes->has(BasicAttribute::class));
self::assertTrue($attributes->has(AttributeWithArguments::class));
self::assertTrue($attributes->has(NestedAttribute::class));
/** @var AttributeWithArguments $attribute */
$attribute = [...$attributes->ofType(AttributeWithArguments::class)][0];
self::assertSame('foo', $attribute->foo);
self::assertSame('bar', $attribute->bar);
/** @var NestedAttribute $attribute */
$attribute = [...$attributes->ofType(NestedAttribute::class)][0];
self::assertCount(2, $attribute->nestedAttributes);
self::assertInstanceOf(BasicAttribute::class, $attribute->nestedAttributes[0]);
self::assertInstanceOf(AttributeWithArguments::class, $attribute->nestedAttributes[1]);
/** @var AttributeWithArguments $nestedAttribute */
$nestedAttribute = $attribute->nestedAttributes[1];
self::assertSame('foo', $nestedAttribute->foo);
self::assertSame('bar', $nestedAttribute->bar);
}
/**
* @requires PHP >= 8.1
*/
public function test_compiles_native_php_attributes_for_property_with_nested_attributes(): void
{
$reflection = new ReflectionClass(ObjectWithNestedAttributes::class);
$reflection = $reflection->getProperty('property');
$attributes = $this->compile(new NativeAttributes($reflection));
self::assertCount(3, $attributes);
self::assertTrue($attributes->has(BasicAttribute::class));
self::assertTrue($attributes->has(AttributeWithArguments::class));
self::assertTrue($attributes->has(NestedAttribute::class));
}
/**
* @requires PHP >= 8.1
*/
public function test_compiles_native_php_attributes_for_method_with_nested_attributes(): void
{
$reflection = new ReflectionClass(ObjectWithNestedAttributes::class);
$reflection = $reflection->getMethod('method');
$attributes = $this->compile(new NativeAttributes($reflection));
self::assertCount(3, $attributes);
self::assertTrue($attributes->has(BasicAttribute::class));
self::assertTrue($attributes->has(AttributeWithArguments::class));
self::assertTrue($attributes->has(NestedAttribute::class));
}
private function compile(Attributes $attributes): Attributes
{
$code = $this->attributesCompiler->compile($attributes);