diff --git a/src/ClassReflection.php b/src/ClassReflection.php index fcace87..1a7c56c 100644 --- a/src/ClassReflection.php +++ b/src/ClassReflection.php @@ -551,16 +551,8 @@ public function withResolvedTemplates(array $templateArguments = []): self return $this; } - $resolvedTemplateArguments = []; - - foreach ($this->templates as $template) { - $resolvedTemplateArguments[$template->name] = $templateArguments[$template->name] - ?? $templateArguments[$template->getPosition()] - ?? $template->getConstraint(); - } - /** @var self */ - return $this->withResolvedTypes(new ClassTemplateResolver($this->name, $resolvedTemplateArguments)); + return $this->withResolvedTypes(ClassTemplateResolver::create($this->name, $this->templates, $templateArguments)); } /** diff --git a/src/TemplateReflection.php b/src/TemplateReflection.php index ae96041..1da8cf8 100644 --- a/src/TemplateReflection.php +++ b/src/TemplateReflection.php @@ -9,6 +9,7 @@ /** * @api + * @psalm-immutable */ final class TemplateReflection { diff --git a/src/TypeResolver/ClassTemplateResolver.php b/src/TypeResolver/ClassTemplateResolver.php index 9d37c0e..4e6c1f1 100644 --- a/src/TypeResolver/ClassTemplateResolver.php +++ b/src/TypeResolver/ClassTemplateResolver.php @@ -4,13 +4,13 @@ namespace Typhoon\Reflection\TypeResolver; +use Typhoon\Reflection\TemplateReflection; use Typhoon\Type; use Typhoon\Type\types; use Typhoon\Type\TypeVisitor; /** - * @internal - * @psalm-internal Typhoon\Reflection + * @api * @psalm-immutable * @implements TypeVisitor */ @@ -20,11 +20,30 @@ final class ClassTemplateResolver implements TypeVisitor * @param class-string $class * @param non-empty-array $templateArguments */ - public function __construct( + private function __construct( private readonly string $class, private readonly array $templateArguments, ) {} + /** + * @psalm-pure + * @param class-string $class + * @param non-empty-array $templates + * @param array $templateArguments + */ + public static function create(string $class, array $templates, array $templateArguments): self + { + $resolvedTemplateArguments = []; + + foreach ($templates as $template) { + $resolvedTemplateArguments[$template->name] = $templateArguments[$template->name] + ?? $templateArguments[$template->getPosition()] + ?? $template->getConstraint(); + } + + return new self($class, $resolvedTemplateArguments); + } + public function visitNever(Type\NeverType $type): mixed { return $type;