diff --git a/src/MethodSignatureString.php b/src/MethodSignatureString.php index 26536583..682773cb 100644 --- a/src/MethodSignatureString.php +++ b/src/MethodSignatureString.php @@ -5,6 +5,7 @@ namespace Ray\Aop; use Reflection; +use ReflectionAttribute; use ReflectionMethod; use ReflectionParameter; use UnitEnum; @@ -23,17 +24,16 @@ final class MethodSignatureString { - private const PHP_VERSION_8 = 80000; private const NULLABLE_PHP8 = 'null|'; private const NULLABLE_PHP7 = '?'; private const INDENT = ' '; - /** @var TypeString */ + /** @var TypeString */ private $typeString; public function __construct(int $phpVersion) { - $nullableStr = $phpVersion >= self::PHP_VERSION_8 ? self::NULLABLE_PHP8 : self::NULLABLE_PHP7; + $nullableStr = $phpVersion >= 80000 ? self::NULLABLE_PHP8 : self::NULLABLE_PHP7; $this->typeString = new TypeString($nullableStr); } @@ -69,14 +69,7 @@ private function addAttributes(ReflectionMethod $method, array &$signatureParts) $attributes = $method->getAttributes(); foreach ($attributes as $attribute) { - $argsList = $attribute->getArguments(); - $formattedArgs = []; - /** @var mixed $value */ - foreach ($argsList as $name => $value) { - $formattedArgs[] = $this->formatArg($name, $value); - } - - $signatureParts[] = sprintf(' #[\\%s(%s)]', $attribute->getName(), implode(', ', $formattedArgs)) . PHP_EOL; + $signatureParts[] = sprintf(' #[%s]', $this->formatAttributeStr($attribute)) . PHP_EOL; } if (empty($signatureParts)) { @@ -86,6 +79,19 @@ private function addAttributes(ReflectionMethod $method, array &$signatureParts) $signatureParts[] = self::INDENT; } + /** @param ReflectionAttribute $attribute */ + private function formatAttributeStr(ReflectionAttribute $attribute): string + { + $argsList = $attribute->getArguments(); + $formattedArgs = []; + /** @var scalar $value */ + foreach ($argsList as $name => $value) { + $formattedArgs[] = $this->formatArg($name, $value); + } + + return sprintf('\\%s(%s)', $attribute->getName(), implode(', ', $formattedArgs)); + } + /** * @param array $signatureParts * @@ -139,6 +145,7 @@ private function formatArg($name, $value): string private function generateParameterCode(ReflectionParameter $param): string { + $attributesStr = $this->getAttributeStr($param); $typeStr = ($this->typeString)($param->getType()); $typeStrWithSpace = $typeStr ? $typeStr . ' ' : $typeStr; $variadicStr = $param->isVariadic() ? '...' : ''; @@ -149,6 +156,26 @@ private function generateParameterCode(ReflectionParameter $param): string $defaultStr = ' = ' . str_replace(["\r", "\n"], '', $default); } - return "{$typeStrWithSpace}{$referenceStr}{$variadicStr}\${$param->getName()}{$defaultStr}"; + return "{$attributesStr}{$typeStrWithSpace}{$referenceStr}{$variadicStr}\${$param->getName()}{$defaultStr}"; + } + + public function getAttributeStr(ReflectionParameter $param): string + { + if (PHP_MAJOR_VERSION < 8) { + return ''; + } + + $attributesStr = ''; + $attributes = $param->getAttributes(); + if (! empty($attributes)) { + $attributeStrings = []; + foreach ($attributes as $attribute) { + $attributeStrings[] = sprintf('#[%s]', $this->formatAttributeStr($attribute)); + } + + $attributesStr = implode(' ', $attributeStrings) . ' '; + } + + return $attributesStr; } } diff --git a/tests/AopCodeTest.php b/tests/AopCodeTest.php index afcf7ff0..f05244ec 100644 --- a/tests/AopCodeTest.php +++ b/tests/AopCodeTest.php @@ -49,7 +49,7 @@ public function testReturnType(): void public function testVariousMethodSignature(): void { $bind = new Bind(); - for ($i = 1; $i <= 24; $i++) { + for ($i = 1; $i <= 25; $i++) { $bind->bindInterceptors('method' . (string) $i, []); } @@ -91,6 +91,7 @@ public function method22()', $code); public function method23()', $code); $this->assertStringContainsString('#[\\Ray\\Aop\\Annotation\\FakeMarker6(fruit1: \\Ray\\Aop\\FakePhp81Enum::Apple, fruit2: \\Ray\\Aop\\FakePhp81Enum::Orange)] public function method24()', $code); + $this->assertStringContainsString("public function method25(#[\Ray\Aop\Attribute\FakeAttr1()] \$a, #[\Ray\Aop\Attribute\FakeAttr1()] #[\Ray\Aop\Attribute\FakeAttr2(name: 'famicon', age: 40)] \$b): void", $code); } /** @requires PHP 8.2 */ diff --git a/tests/Fake/Attribute/FakeAttr1.php b/tests/Fake/Attribute/FakeAttr1.php new file mode 100644 index 00000000..69ceafc0 --- /dev/null +++ b/tests/Fake/Attribute/FakeAttr1.php @@ -0,0 +1,10 @@ +