From d0e9305a3300d2ef271f5ff8cf43455e13022f56 Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov Date: Fri, 19 Jan 2024 15:11:44 +0300 Subject: [PATCH] Switch to typhoon/type v0.3 --- composer.json | 4 +- composer.lock | 38 ++++---- src/ClassReflection.php | 6 +- src/MethodReflection.php | 4 +- src/NameResolution/NameAsClassResolver.php | 7 +- src/NameResolution/NameAsTypeResolver.php | 11 +-- src/NameResolution/NameContext.php | 12 +-- src/NameResolution/NameResolver.php | 11 +-- src/ParameterReflection.php | 4 +- src/PropertyReflection.php | 4 +- src/Reflector/NameContextVisitor.php | 5 +- src/Reflector/NativeReflectionReflector.php | 2 +- src/Reflector/PhpDocTypeReflector.php | 6 +- src/Reflector/PhpParserReflector.php | 8 +- src/TypeReflection.php | 4 +- src/TypeResolver/StaticResolver.php | 69 +++++++++++---- ...plateResolver.php => TemplateResolver.php} | 87 +++++++++++++------ 17 files changed, 163 insertions(+), 119 deletions(-) rename src/TypeResolver/{ClassTemplateResolver.php => TemplateResolver.php} (79%) diff --git a/composer.json b/composer.json index 894621a..b65e41b 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ "nikic/php-parser": "^4.15", "phpstan/phpdoc-parser": "^1.0", "psr/simple-cache": "^3.0", - "typhoon/type": "^0.2@dev", - "typhoon/type-stringifier": "^0.2@dev" + "typhoon/type": "^0.3@dev", + "typhoon/type-stringifier": "^0.3@dev" }, "require-dev": { "ergebnis/composer-normalize": "^2.41.1", diff --git a/composer.lock b/composer.lock index 2fa818d..983c447 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6875d589d9c905a29b915a65303e8370", + "content-hash": "2330e1faf17e6f505363a057e2f6194c", "packages": [ { "name": "nikic/php-parser", @@ -162,16 +162,16 @@ }, { "name": "typhoon/type", - "version": "0.2.x-dev", + "version": "0.3.x-dev", "source": { "type": "git", "url": "https://github.com/typhoon-php/type.git", - "reference": "39db9d53f572a051e15387aece4ba35833dc0afc" + "reference": "2c58b639f6f276424b9df9435744f4a52e1a59a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/typhoon-php/type/zipball/39db9d53f572a051e15387aece4ba35833dc0afc", - "reference": "39db9d53f572a051e15387aece4ba35833dc0afc", + "url": "https://api.github.com/repos/typhoon-php/type/zipball/2c58b639f6f276424b9df9435744f4a52e1a59a2", + "reference": "2c58b639f6f276424b9df9435744f4a52e1a59a2", "shasum": "" }, "require": { @@ -203,35 +203,35 @@ "description": "Typhoon Type", "support": { "issues": "https://github.com/typhoon-php/type/issues", - "source": "https://github.com/typhoon-php/type/tree/0.2.x" + "source": "https://github.com/typhoon-php/type/tree/0.3.x" }, - "time": "2023-09-22T01:28:22+00:00" + "time": "2024-01-19T00:17:58+00:00" }, { "name": "typhoon/type-stringifier", - "version": "0.2.x-dev", + "version": "0.3.x-dev", "source": { "type": "git", "url": "https://github.com/typhoon-php/type-stringifier.git", - "reference": "7de855d5fff5cbe9cf2dcff5057975af53873252" + "reference": "5e85beedca66992be23124e756a47e82f9c66e31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/typhoon-php/type-stringifier/zipball/7de855d5fff5cbe9cf2dcff5057975af53873252", - "reference": "7de855d5fff5cbe9cf2dcff5057975af53873252", + "url": "https://api.github.com/repos/typhoon-php/type-stringifier/zipball/5e85beedca66992be23124e756a47e82f9c66e31", + "reference": "5e85beedca66992be23124e756a47e82f9c66e31", "shasum": "" }, "require": { "php": "^8.1", - "typhoon/type": "^0.2@dev" + "typhoon/type": "^0.3@dev" }, "require-dev": { - "ergebnis/composer-normalize": "^2.36.0", - "friendsofphp/php-cs-fixer": "^3.26.1", - "phpunit/phpunit": "^10.3.4", - "phpyh/coding-standard": "^2.5.0", + "ergebnis/composer-normalize": "^2.41.1", + "friendsofphp/php-cs-fixer": "^3.47.1", + "phpunit/phpunit": "^10.5.7", + "phpyh/coding-standard": "^2.6.0", "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.15.0" + "vimeo/psalm": "^5.20.0" }, "default-branch": true, "type": "library", @@ -253,9 +253,9 @@ "description": "Typhoon Type Stringifier", "support": { "issues": "https://github.com/typhoon-php/type-stringifier/issues", - "source": "https://github.com/typhoon-php/type-stringifier/tree/0.2.x" + "source": "https://github.com/typhoon-php/type-stringifier/tree/0.3.x" }, - "time": "2024-01-18T23:01:40+00:00" + "time": "2024-01-19T09:26:14+00:00" } ], "packages-dev": [ diff --git a/src/ClassReflection.php b/src/ClassReflection.php index 0471daf..376cf15 100644 --- a/src/ClassReflection.php +++ b/src/ClassReflection.php @@ -6,8 +6,8 @@ use Typhoon\Reflection\Reflector\ContextAwareReflection; use Typhoon\Reflection\Reflector\RootReflection; -use Typhoon\Reflection\TypeResolver\ClassTemplateResolver; use Typhoon\Reflection\TypeResolver\StaticResolver; +use Typhoon\Reflection\TypeResolver\TemplateResolver; use Typhoon\Type; /** @@ -571,7 +571,7 @@ public function resolveTemplates(array $templateArguments = []): self } /** @var self */ - return $this->resolvedTypes(ClassTemplateResolver::create($this->name, $this->templates, $templateArguments)); + return $this->resolvedTypes(TemplateResolver::create($this->templates, $templateArguments)); } /** @@ -668,7 +668,7 @@ protected function setContext(ReflectionContext $reflectionContext): void } } - private function resolvedTypes(ClassTemplateResolver|StaticResolver $typeResolver): self + private function resolvedTypes(TemplateResolver|StaticResolver $typeResolver): self { $class = clone $this; $class->propertiesIndexedByName = array_map( diff --git a/src/MethodReflection.php b/src/MethodReflection.php index 9c01147..ca692e2 100644 --- a/src/MethodReflection.php +++ b/src/MethodReflection.php @@ -5,8 +5,8 @@ namespace Typhoon\Reflection; use Typhoon\Reflection\Reflector\ContextAwareReflection; -use Typhoon\Reflection\TypeResolver\ClassTemplateResolver; use Typhoon\Reflection\TypeResolver\StaticResolver; +use Typhoon\Reflection\TypeResolver\TemplateResolver; /** * @api @@ -411,7 +411,7 @@ public function getNativeReflection(): \ReflectionMethod return $this->nativeReflection ??= new \ReflectionMethod($this->class, $this->name); } - public function resolveTypes(ClassTemplateResolver|StaticResolver $typeResolver): self + public function resolveTypes(TemplateResolver|StaticResolver $typeResolver): self { $method = clone $this; $method->parameters = array_map( diff --git a/src/NameResolution/NameAsClassResolver.php b/src/NameResolution/NameAsClassResolver.php index 8f51f07..7eefaad 100644 --- a/src/NameResolution/NameAsClassResolver.php +++ b/src/NameResolution/NameAsClassResolver.php @@ -28,12 +28,7 @@ public function constant(string $name): mixed throw new ReflectionException(sprintf('Name "%s" cannot be resolved as class.', $name)); } - public function classTemplate(string $class, string $name): mixed - { - throw new ReflectionException(sprintf('Name "%s" cannot be resolved as class.', $class)); - } - - public function methodTemplate(string $class, string $method, string $name): mixed + public function template(string $name): mixed { throw new ReflectionException(sprintf('Name "%s" cannot be resolved as class.', $name)); } diff --git a/src/NameResolution/NameAsTypeResolver.php b/src/NameResolution/NameAsTypeResolver.php index 3315b4f..e64b637 100644 --- a/src/NameResolution/NameAsTypeResolver.php +++ b/src/NameResolution/NameAsTypeResolver.php @@ -31,7 +31,7 @@ public function class(string $name): mixed public function static(string $self): mixed { - return types::static($self, ...$this->templateArguments); + return types::static(...$this->templateArguments); } public function constant(string $name): mixed @@ -39,14 +39,9 @@ public function constant(string $name): mixed return types::constant($name); } - public function classTemplate(string $class, string $name): mixed + public function template(string $name): mixed { - return types::classTemplate($class, $name); - } - - public function methodTemplate(string $class, string $method, string $name): mixed - { - return types::methodTemplate($class, $method, $name); + return types::template($name); } public function classOrConstants(string $classCandidate, array $constantCandidates): mixed diff --git a/src/NameResolution/NameContext.php b/src/NameResolution/NameContext.php index 46fa97d..871c3da 100644 --- a/src/NameResolution/NameContext.php +++ b/src/NameResolution/NameContext.php @@ -35,8 +35,6 @@ final class NameContext */ private array $classTemplateNamesMap = []; - private ?UnqualifiedName $method = null; - /** * @var array */ @@ -107,11 +105,10 @@ public function enterClass(string $name, ?string $parent = null, array $template /** * @param array $templateNames */ - public function enterMethod(string $name, array $templateNames = []): void + public function enterMethod(array $templateNames = []): void { $this->leaveMethod(); - $this->method = new UnqualifiedName($name); $this->methodTemplateNamesMap = array_fill_keys( array_map( /** @return non-empty-string */ @@ -124,7 +121,6 @@ public function enterMethod(string $name, array $templateNames = []): void public function leaveMethod(): void { - $this->method = null; $this->methodTemplateNamesMap = []; } @@ -223,12 +219,12 @@ public function resolveName(string|Name $name, NameResolver $resolver): mixed return $resolver->static($this->resolveNameAsClass($this->self)); } - if ($this->method !== null && isset($this->methodTemplateNamesMap[$nameAsString])) { - return $resolver->methodTemplate($this->resolveNameAsClass($this->self), $this->method->toString(), $nameAsString); + if (isset($this->methodTemplateNamesMap[$nameAsString])) { + return $resolver->template($nameAsString); } if (isset($this->classTemplateNamesMap[$nameAsString])) { - return $resolver->classTemplate($this->resolveNameAsClass($this->self), $nameAsString); + return $resolver->template($nameAsString); } } diff --git a/src/NameResolution/NameResolver.php b/src/NameResolution/NameResolver.php index 44617b5..eb9800d 100644 --- a/src/NameResolution/NameResolver.php +++ b/src/NameResolution/NameResolver.php @@ -30,19 +30,10 @@ public function static(string $self): mixed; public function constant(string $name): mixed; /** - * @param class-string $class * @param non-empty-string $name * @return T */ - public function classTemplate(string $class, string $name): mixed; - - /** - * @param class-string $class - * @param non-empty-string $method - * @param non-empty-string $name - * @return T - */ - public function methodTemplate(string $class, string $method, string $name): mixed; + public function template(string $name): mixed; /** * @param non-empty-string $classCandidate diff --git a/src/ParameterReflection.php b/src/ParameterReflection.php index 4e8f330..1f0ad58 100644 --- a/src/ParameterReflection.php +++ b/src/ParameterReflection.php @@ -5,8 +5,8 @@ namespace Typhoon\Reflection; use Typhoon\Reflection\Reflector\ContextAwareReflection; -use Typhoon\Reflection\TypeResolver\ClassTemplateResolver; use Typhoon\Reflection\TypeResolver\StaticResolver; +use Typhoon\Reflection\TypeResolver\TemplateResolver; /** * @api @@ -176,7 +176,7 @@ public function getNativeReflection(): \ReflectionParameter ); } - public function resolveTypes(ClassTemplateResolver|StaticResolver $typeResolver): self + public function resolveTypes(TemplateResolver|StaticResolver $typeResolver): self { $parameter = clone $this; $parameter->type = $this->type->resolve($typeResolver); diff --git a/src/PropertyReflection.php b/src/PropertyReflection.php index 3f13ccc..0bc7eb3 100644 --- a/src/PropertyReflection.php +++ b/src/PropertyReflection.php @@ -5,8 +5,8 @@ namespace Typhoon\Reflection; use Typhoon\Reflection\Reflector\ContextAwareReflection; -use Typhoon\Reflection\TypeResolver\ClassTemplateResolver; use Typhoon\Reflection\TypeResolver\StaticResolver; +use Typhoon\Reflection\TypeResolver\TemplateResolver; /** * @api @@ -203,7 +203,7 @@ public function getNativeReflection(): \ReflectionProperty return $this->nativeReflection ??= new \ReflectionProperty($this->class, $this->name); } - public function resolveTypes(ClassTemplateResolver|StaticResolver $typeResolver): self + public function resolveTypes(TemplateResolver|StaticResolver $typeResolver): self { $property = clone $this; $property->type = $this->type->resolve($typeResolver); diff --git a/src/Reflector/NameContextVisitor.php b/src/Reflector/NameContextVisitor.php index 02b9389..58636e6 100644 --- a/src/Reflector/NameContextVisitor.php +++ b/src/Reflector/NameContextVisitor.php @@ -67,10 +67,7 @@ public function enterNode(Node $node): ?int } if ($node instanceof Stmt\ClassMethod) { - $this->nameContext->enterMethod( - name: $node->name->name, - templateNames: PhpDocParsingVisitor::fromNode($node)->templateNames(), - ); + $this->nameContext->enterMethod(PhpDocParsingVisitor::fromNode($node)->templateNames()); return null; } diff --git a/src/Reflector/NativeReflectionReflector.php b/src/Reflector/NativeReflectionReflector.php index 7489500..52d1a2e 100644 --- a/src/Reflector/NativeReflectionReflector.php +++ b/src/Reflector/NativeReflectionReflector.php @@ -280,7 +280,7 @@ private function reflectNativeType(?\ReflectionType $reflectionType, ?string $cl throw new \LogicException('Cannot use type "static" outside of class scope.'); } - return types::static($class); + return types::static(); } $type = match ($name) { diff --git a/src/Reflector/PhpDocTypeReflector.php b/src/Reflector/PhpDocTypeReflector.php index 68e5507..92b70ae 100644 --- a/src/Reflector/PhpDocTypeReflector.php +++ b/src/Reflector/PhpDocTypeReflector.php @@ -274,12 +274,12 @@ private function reflectIterable(array $templateArguments): Type\Type }; } - private function reflectArrayShape(ArrayShapeNode $node): Type\ShapeType + private function reflectArrayShape(ArrayShapeNode $node): Type\ArrayShapeType { $elements = []; foreach ($node->items as $item) { - $type = types::element($this->doReflect($item->valueType), $item->optional); + $type = types::arrayElement($this->doReflect($item->valueType), $item->optional); if ($item->keyName === null) { $elements[] = $type; @@ -299,7 +299,7 @@ private function reflectArrayShape(ArrayShapeNode $node): Type\ShapeType $elements[$key] = $type; } - return types::shape($elements, $node->sealed); + return types::arrayShape($elements, $node->sealed); } private function reflectConstExpr(ConstTypeNode $node): Type\Type diff --git a/src/Reflector/PhpParserReflector.php b/src/Reflector/PhpParserReflector.php index ae1fee5..3369b32 100644 --- a/src/Reflector/PhpParserReflector.php +++ b/src/Reflector/PhpParserReflector.php @@ -333,7 +333,7 @@ private function reflectOwnMethods(string $class, Stmt\ClassLike $classNode): ar $phpDoc = PhpDocParsingVisitor::fromNode($node); try { - $this->nameContext->enterMethod($name, $phpDoc->templateNames()); + $this->nameContext->enterMethod($phpDoc->templateNames()); $methods[] = new MethodReflection( class: $class, @@ -534,13 +534,11 @@ private function reflectNativeType(?Node $node): ?Type\Type } if ($node instanceof Name) { - $resolvedName = $this->nameContext->resolveNameAsClass($node->toCodeString()); - if ($node->toString() === 'static') { - return types::static($resolvedName); + return types::static(); } - return types::object($resolvedName); + return types::object($this->nameContext->resolveNameAsClass($node->toCodeString())); } throw new ReflectionException(sprintf('%s is not supported.', $node::class)); diff --git a/src/TypeReflection.php b/src/TypeReflection.php index 5224470..2a340c5 100644 --- a/src/TypeReflection.php +++ b/src/TypeReflection.php @@ -4,8 +4,8 @@ namespace Typhoon\Reflection; -use Typhoon\Reflection\TypeResolver\ClassTemplateResolver; use Typhoon\Reflection\TypeResolver\StaticResolver; +use Typhoon\Reflection\TypeResolver\TemplateResolver; use Typhoon\Type\Type; use Typhoon\Type\types; @@ -69,7 +69,7 @@ public function getResolved(): Type return $this->resolved; } - public function resolve(ClassTemplateResolver|StaticResolver $typeResolver): self + public function resolve(TemplateResolver|StaticResolver $typeResolver): self { return new self( native: $this->native, diff --git a/src/TypeResolver/StaticResolver.php b/src/TypeResolver/StaticResolver.php index 38a8398..3950a71 100644 --- a/src/TypeResolver/StaticResolver.php +++ b/src/TypeResolver/StaticResolver.php @@ -5,6 +5,11 @@ namespace Typhoon\Reflection\TypeResolver; use Typhoon\Type; +use Typhoon\Type\ClassStringLiteralType; +use Typhoon\Type\IntMaskOfType; +use Typhoon\Type\IntMaskType; +use Typhoon\Type\ObjectShapeType; +use Typhoon\Type\TruthyString; use Typhoon\Type\types; use Typhoon\Type\TypeVisitor; @@ -68,6 +73,16 @@ public function visitIntRange(Type\IntRangeType $type): mixed return $type; } + public function visitIntMask(IntMaskType $type): mixed + { + return $type; + } + + public function visitIntMaskOf(IntMaskOfType $type): mixed + { + return $type; + } + public function visitInt(Type\IntType $type): mixed { return $type; @@ -98,6 +113,11 @@ public function visitNumericString(Type\NumericStringType $type): mixed return $type; } + public function visitClassStringLiteral(ClassStringLiteralType $type): mixed + { + return $type; + } + public function visitNamedClassString(Type\NamedClassStringType $type): mixed { /** @psalm-suppress MixedArgumentTypeCoercion */ @@ -134,6 +154,11 @@ public function visitNonEmptyString(Type\NonEmptyStringType $type): mixed return $type; } + public function visitTruthyString(TruthyString $type): mixed + { + return $type; + } + public function visitString(Type\StringType $type): mixed { return $type; @@ -164,12 +189,12 @@ public function visitList(Type\ListType $type): mixed return types::list($type->valueType->accept($this)); } - public function visitShape(Type\ShapeType $type): mixed + public function visitArrayShape(Type\ArrayShapeType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ - return types::shape( + return types::arrayShape( array_map( - fn(Type\ShapeElement $element): Type\ShapeElement => types::element( + fn(Type\ArrayElement $element): Type\ArrayElement => types::arrayElement( $element->type->accept($this), $element->optional, ), @@ -205,7 +230,7 @@ public function visitNamedObject(Type\NamedObjectType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::object($type->class, ...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $templateArgument): Type\Type => $templateArgument->accept($this), $type->templateArguments, )); } @@ -214,11 +239,25 @@ public function visitStatic(Type\StaticType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::object($this->class, ...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $templateArgument): Type\Type => $templateArgument->accept($this), $type->templateArguments, )); } + public function visitObjectShape(ObjectShapeType $type): mixed + { + /** @psalm-suppress ImpureFunctionCall */ + return types::objectShape( + array_map( + fn(Type\Property $property): Type\Property => types::prop( + $property->type->accept($this), + $property->optional, + ), + $type->properties, + ), + ); + } + public function visitObject(Type\ObjectType $type): mixed { return $type; @@ -286,26 +325,26 @@ public function visitValueOf(Type\ValueOfType $type): mixed return types::valueOf($type->type->accept($this)); } - public function visitFunctionTemplate(Type\FunctionTemplateType $type): mixed + public function visitTemplate(Type\TemplateType $type): mixed { return $type; } - public function visitClassTemplate(Type\ClassTemplateType $type): mixed + public function visitConditional(Type\ConditionalType $type): mixed { - return $type; - } - - public function visitMethodTemplate(Type\MethodTemplateType $type): mixed - { - return $type; + return types::conditional( + $type->subject, + $type->is->accept($this), + $type->if->accept($this), + $type->else->accept($this), + ); } public function visitIntersection(Type\IntersectionType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::intersection(...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $part): Type\Type => $part->accept($this), $type->types, )); } @@ -314,7 +353,7 @@ public function visitUnion(Type\UnionType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::union(...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $part): Type\Type => $part->accept($this), $type->types, )); } diff --git a/src/TypeResolver/ClassTemplateResolver.php b/src/TypeResolver/TemplateResolver.php similarity index 79% rename from src/TypeResolver/ClassTemplateResolver.php rename to src/TypeResolver/TemplateResolver.php index f5c7f48..615ab39 100644 --- a/src/TypeResolver/ClassTemplateResolver.php +++ b/src/TypeResolver/TemplateResolver.php @@ -6,6 +6,12 @@ use Typhoon\Reflection\TemplateReflection; use Typhoon\Type; +use Typhoon\Type\ClassStringLiteralType; +use Typhoon\Type\ConditionalType; +use Typhoon\Type\IntMaskOfType; +use Typhoon\Type\IntMaskType; +use Typhoon\Type\ObjectShapeType; +use Typhoon\Type\TruthyString; use Typhoon\Type\types; use Typhoon\Type\TypeVisitor; @@ -14,25 +20,22 @@ * @psalm-immutable * @implements TypeVisitor */ -final class ClassTemplateResolver implements TypeVisitor +final class TemplateResolver implements TypeVisitor { /** - * @param class-string $class * @param non-empty-array $templateArguments */ private function __construct( - private readonly string $class, private readonly array $templateArguments, ) {} /** * @psalm-pure * @psalm-suppress ImpurePropertyFetch - * @param class-string $class * @param non-empty-array $templates * @param array $templateArguments */ - public static function create(string $class, array $templates, array $templateArguments): self + public static function create(array $templates, array $templateArguments): self { $resolvedTemplateArguments = []; @@ -42,7 +45,7 @@ public static function create(string $class, array $templates, array $templateAr ?? $template->getConstraint(); } - return new self($class, $resolvedTemplateArguments); + return new self($resolvedTemplateArguments); } public function visitNever(Type\NeverType $type): mixed @@ -90,6 +93,16 @@ public function visitIntRange(Type\IntRangeType $type): mixed return $type; } + public function visitIntMask(IntMaskType $type): mixed + { + return $type; + } + + public function visitIntMaskOf(IntMaskOfType $type): mixed + { + return $type; + } + public function visitInt(Type\IntType $type): mixed { return $type; @@ -120,6 +133,11 @@ public function visitNumericString(Type\NumericStringType $type): mixed return $type; } + public function visitClassStringLiteral(ClassStringLiteralType $type): mixed + { + return $type; + } + public function visitNamedClassString(Type\NamedClassStringType $type): mixed { /** @psalm-suppress MixedArgumentTypeCoercion */ @@ -156,6 +174,11 @@ public function visitNonEmptyString(Type\NonEmptyStringType $type): mixed return $type; } + public function visitTruthyString(TruthyString $type): mixed + { + return $type; + } + public function visitString(Type\StringType $type): mixed { return $type; @@ -186,12 +209,12 @@ public function visitList(Type\ListType $type): mixed return types::list($type->valueType->accept($this)); } - public function visitShape(Type\ShapeType $type): mixed + public function visitArrayShape(Type\ArrayShapeType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ - return types::shape( + return types::arrayShape( array_map( - fn(Type\ShapeElement $element): Type\ShapeElement => types::element( + fn(Type\ArrayElement $element): Type\ArrayElement => types::arrayElement( $element->type->accept($this), $element->optional, ), @@ -227,7 +250,7 @@ public function visitNamedObject(Type\NamedObjectType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::object($type->class, ...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $templateArgument): Type\Type => $templateArgument->accept($this), $type->templateArguments, )); } @@ -235,12 +258,26 @@ public function visitNamedObject(Type\NamedObjectType $type): mixed public function visitStatic(Type\StaticType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ - return types::static($type->declaringClass, ...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + return types::static(...array_map( + fn(Type\Type $templateArgument): Type\Type => $templateArgument->accept($this), $type->templateArguments, )); } + public function visitObjectShape(ObjectShapeType $type): mixed + { + /** @psalm-suppress ImpureFunctionCall */ + return types::objectShape( + array_map( + fn(Type\Property $property): Type\Property => types::prop( + $property->type->accept($this), + $property->optional, + ), + $type->properties, + ), + ); + } + public function visitObject(Type\ObjectType $type): mixed { return $type; @@ -308,30 +345,26 @@ public function visitValueOf(Type\ValueOfType $type): mixed return types::valueOf($type->type->accept($this)); } - public function visitFunctionTemplate(Type\FunctionTemplateType $type): mixed - { - return $type; - } - - public function visitClassTemplate(Type\ClassTemplateType $type): mixed + public function visitTemplate(Type\TemplateType $type): mixed { - if ($type->class === $this->class && isset($this->templateArguments[$type->name])) { - return $this->templateArguments[$type->name]; - } - - return $type; + return $this->templateArguments[$type->name] ?? $type; } - public function visitMethodTemplate(Type\MethodTemplateType $type): mixed + public function visitConditional(ConditionalType $type): mixed { - return $type; + return types::conditional( + $type->subject, + $type->is->accept($this), + $type->if->accept($this), + $type->else->accept($this), + ); } public function visitIntersection(Type\IntersectionType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::intersection(...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $part): Type\Type => $part->accept($this), $type->types, )); } @@ -340,7 +373,7 @@ public function visitUnion(Type\UnionType $type): mixed { /** @psalm-suppress ImpureFunctionCall */ return types::union(...array_map( - fn(Type\Type $type): Type\Type => $type->accept($this), + fn(Type\Type $part): Type\Type => $part->accept($this), $type->types, )); }