diff --git a/src/Attributes/functions.php b/src/Attributes/functions.php index c37ddec..d4a09ea 100644 --- a/src/Attributes/functions.php +++ b/src/Attributes/functions.php @@ -14,6 +14,7 @@ namespace Chevere\Parameter\Attributes; use Chevere\Parameter\Interfaces\ArgumentsInterface; +use LogicException; use ReflectionFunction; use ReflectionMethod; use function Chevere\Parameter\parameterAttr; @@ -67,6 +68,9 @@ function genericAttr(string $name): GenericAttr return parameterAttr($name, $caller); } +/** + * Get Arguments for an array parameter. + */ function arrayArguments(string $name): ArgumentsInterface { $caller = debug_backtrace(0, 2)[1]; @@ -95,7 +99,6 @@ function arrayArguments(string $name): ArgumentsInterface /** * Validates argument `$name` against attribute rules. - * @throws LogicException */ function validate(?string $name = null): void { @@ -120,3 +123,23 @@ function validate(?string $name = null): void } $parameters->get($name)->__invoke($arguments[$name]); } + +/** + * Validates `$var` against the return attribute. + * + * @return mixed The validated `$var`. + */ +function returnAttr(mixed $var): mixed +{ + $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]; + $class = $caller['class'] ?? null; + $method = $caller['function']; + $reflection = $class + ? new ReflectionMethod($class, $method) + : new ReflectionFunction($method); + /** @var ReflectionAttribute $attribute */ + $attribute = $reflection->getAttributes(ReturnAttr::class)[0] + ?? throw new LogicException('No return attribute found'); + + return $attribute->newInstance()->__invoke($var); +} diff --git a/src/ReflectionParameterTyped.php b/src/ReflectionParameterTyped.php index 8a47402..396bc3a 100644 --- a/src/ReflectionParameterTyped.php +++ b/src/ReflectionParameterTyped.php @@ -26,18 +26,6 @@ final class ReflectionParameterTyped implements ReflectionParameterTypedInterface { - /** - * @var array - */ - public const TYPE_TO_PARAMETER = [ - 'array' => ArrayParameter::class, - 'bool' => BoolParameter::class, - 'float' => FloatParameter::class, - 'int' => IntParameter::class, - 'string' => StringParameter::class, - 'object' => ObjectParameter::class, - ]; - private ReflectionNamedType $type; private ParameterInterface $parameter; @@ -76,7 +64,7 @@ private function getType(): ReflectionNamedType if ($reflectionType === null) { throw new TypeError( (string) message( - 'Missing type declaration for parameter %parameter%', + 'Missing type declaration for parameter `%parameter%`', parameter: '$' . $this->reflection->getName() ) ); diff --git a/src/functions.php b/src/functions.php index f08150e..f978c71 100644 --- a/src/functions.php +++ b/src/functions.php @@ -170,37 +170,21 @@ function assertNamedArgument( } } -function reflectionToParameters(ReflectionFunction|ReflectionMethod $functionOrMethod): ParametersInterface +function toParameter(string $type): ParameterInterface { - $parameters = parameters(); - foreach ($functionOrMethod->getParameters() as $reflection) { - $reflectionParameter = new ReflectionParameterTyped($reflection); - $callable = match ($reflection->isOptional()) { - true => 'withOptional', - default => 'withRequired', - }; - - $parameters = $parameters->{$callable}( - $reflection->getName(), - $reflectionParameter->parameter() - ); + $class = TypeInterface::TYPE_TO_PARAMETER[$type] + ?? null; + if ($class === null) { + $class = TypeInterface::TYPE_TO_PARAMETER['object']; + $className = $type; } - - return $parameters; -} - -function reflectionToReturnParameter(ReflectionFunction|ReflectionMethod $reflection): ParameterInterface -{ - $attributes = $reflection->getAttributes(ReturnAttr::class); - if ($attributes === []) { - $type = - throw new LogicException('No `ReturnAttr` attribute found'); + $parameter = new $class(); + if (isset($className)) { + // @phpstan-ignore-next-line + $parameter = $parameter->withClassName($className); } - /** @var ReflectionAttribute $attribute */ - $attribute = $attributes[0]; - - return $attribute->newInstance()->parameter(); + return $parameter; } function arrayFrom( @@ -266,26 +250,6 @@ function getType(mixed $variable): string }; } -/** - * Validates `$var` against the return attribute. - * - * @return mixed The validated `$var`. - */ -function returnAttr(mixed $var): mixed -{ - $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]; - $class = $caller['class'] ?? null; - $method = $caller['function']; - $reflection = $class - ? new ReflectionMethod($class, $method) - : new ReflectionFunction($method); - /** @var ReflectionAttribute $attribute */ - $attribute = $reflection->getAttributes(ReturnAttr::class)[0] - ?? throw new LogicException('No return attribute found'); - - return $attribute->newInstance()->__invoke($var); -} - /** * Retrieves a Parameter attribute instance from a function or method parameter. * @param array $caller The result of debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] @@ -309,6 +273,46 @@ function parameterAttr(string $parameter, array $caller): ParameterAttributeInte ); } +/** + * Get Parameters from a function or method reflection. + */ +function reflectionToParameters(ReflectionFunction|ReflectionMethod $reflection): ParametersInterface +{ + $parameters = parameters(); + foreach ($reflection->getParameters() as $parameter) { + $reflectionParameter = new ReflectionParameterTyped($parameter); + $callable = match ($parameter->isOptional()) { + true => 'withOptional', + default => 'withRequired', + }; + + $parameters = $parameters->{$callable}( + $parameter->getName(), + $reflectionParameter->parameter() + ); + } + + return $parameters; +} + +/** + * Get a return Parameter from a function or method reflection. + */ +function reflectionToReturnParameter(ReflectionFunction|ReflectionMethod $reflection): ParameterInterface +{ + $attributes = $reflection->getAttributes(ReturnAttr::class); + if ($attributes === []) { + $returnType = (string) $reflection->getReturnType(); + + return toParameter($returnType); + } + + /** @var ReflectionAttribute $attribute */ + $attribute = $attributes[0]; + + return $attribute->newInstance()->parameter(); +} + function reflectedParameterAttribute( string $parameter, ReflectionParameter $reflection, @@ -329,19 +333,3 @@ function reflectedParameterAttribute( (string) message('No parameter attribute for `%name%`', name: $parameter) ); } - -function toParameter(string $type): ParameterInterface -{ - $class = TypeInterface::TYPE_TO_PARAMETER[$type] - ?? null; - if ($class === null) { - $class = TypeInterface::TYPE_TO_PARAMETER['object']; - $className = $type; - } - $parameter = new $class(); - if (isset($className)) { - $parameter = $parameter->withClassName($className); - } - - return $parameter; -} diff --git a/tests/src/UsesParameterAttributes.php b/tests/src/UsesParameterAttributes.php index 27225c1..752bbd2 100644 --- a/tests/src/UsesParameterAttributes.php +++ b/tests/src/UsesParameterAttributes.php @@ -22,9 +22,9 @@ use function Chevere\Parameter\Attributes\arrayAttr; use function Chevere\Parameter\Attributes\genericAttr; use function Chevere\Parameter\Attributes\intAttr; +use function Chevere\Parameter\Attributes\returnAttr; use function Chevere\Parameter\Attributes\stringAttr; use function Chevere\Parameter\Attributes\validate; -use function Chevere\Parameter\returnAttr; final class UsesParameterAttributes {