diff --git a/src/ReflectionParameterTyped.php b/src/ReflectionParameterTyped.php index 528c898..f1c40a0 100644 --- a/src/ReflectionParameterTyped.php +++ b/src/ReflectionParameterTyped.php @@ -15,12 +15,13 @@ use Chevere\Parameter\Interfaces\ParameterInterface; use Chevere\Parameter\Interfaces\ReflectionParameterTypedInterface; -use InvalidArgumentException; +use LogicException; use ReflectionIntersectionType; use ReflectionNamedType; use ReflectionParameter; use ReflectionUnionType; use Throwable; +use TypeError; use function Chevere\Message\message; final class ReflectionParameterTyped implements ReflectionParameterTypedInterface @@ -37,13 +38,26 @@ public function __construct( try { $attribute = reflectedParameterAttribute($reflection); - $parameter = $attribute->parameter(); } catch (Throwable) { - // Do nothing + // do nothing + } + if (isset($attribute, $this->type)) { + $typeHint = $this->type->getName(); + $attrHint = $attribute->parameter()->type()->typeHinting(); + if ($typeHint !== $attrHint) { + throw new TypeError( + (string) message( + 'Parameter %name% of type %type% is not compatible with %attr% attribute', + name: $reflection->getName(), + type: $typeHint, + attr: $attribute->parameter()::class + ) + ); + } + $parameter = $attribute->parameter(); } if ($this->reflection->isDefaultValueAvailable() && method_exists($parameter, 'withDefault') - && $this->reflection->getDefaultValue() !== null ) { /** @var ParameterInterface $parameter */ $parameter = $parameter @@ -71,7 +85,7 @@ private function getType(): ?ReflectionNamedType $name = '$' . $this->reflection->getName(); $type = $this->getReflectionType($reflection); - throw new InvalidArgumentException( + throw new LogicException( (string) message( 'Parameter %name% of type %type% is not supported', name: $name, diff --git a/tests/ReflectionParameterTypedTest.php b/tests/ReflectionParameterTypedTest.php index 1517379..12afafc 100644 --- a/tests/ReflectionParameterTypedTest.php +++ b/tests/ReflectionParameterTypedTest.php @@ -19,11 +19,12 @@ use Chevere\Parameter\Interfaces\StringParameterInterface; use Chevere\Parameter\ReflectionParameterTyped; use Chevere\Tests\src\Depends; -use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\TestCase; use ReflectionMethod; use ReflectionParameter; use stdClass; +use TypeError; final class ReflectionParameterTypedTest extends TestCase { @@ -71,7 +72,7 @@ public function testParameterDefault(): void public function testUnion(): void { $parameter = $this->getReflection('useUnion'); - $this->expectException(InvalidArgumentException::class); + $this->expectException(LogicException::class); $this->expectExceptionMessage('$union of type union is not supported'); new ReflectionParameterTyped($parameter); } @@ -79,11 +80,19 @@ public function testUnion(): void public function testIntersection(): void { $parameter = $this->getReflection('useIntersection'); - $this->expectException(InvalidArgumentException::class); + $this->expectException(LogicException::class); $this->expectExceptionMessage('$intersection of type intersection is not supported'); new ReflectionParameterTyped($parameter); } + public function testInvalidAttribute(): void + { + $parameter = $this->getReflection('useInvalidAttribute'); + $this->expectException(TypeError::class); + $this->expectExceptionMessage('Parameter int of type int is not compatible with Chevere\Parameter\StringParameter attribute'); + new ReflectionParameterTyped($parameter); + } + private function getReflection(string $method, int $pos = 0): ReflectionParameter { $reflection = new ReflectionMethod(Depends::class, $method); diff --git a/tests/src/Depends.php b/tests/src/Depends.php index 95483cb..a58cf68 100644 --- a/tests/src/Depends.php +++ b/tests/src/Depends.php @@ -43,4 +43,10 @@ public function useUnion(string|int $union) public function useIntersection(stdClass&Depends $intersection) { } + + public function useInvalidAttribute( + #[StringAttr()] + int $int + ) { + } }