diff --git a/src/Library/Container.php b/src/Library/Container.php index 523dab68..f453fc43 100644 --- a/src/Library/Container.php +++ b/src/Library/Container.php @@ -86,12 +86,14 @@ public function __construct(Settings $settings) $this->factories = [ TreeMapper::class => fn () => new TypeTreeMapper( $this->get(TypeParser::class), - $this->get(RootNodeBuilder::class) + $this->get(RootNodeBuilder::class), + $settings, ), ArgumentsMapper::class => fn () => new TypeArgumentsMapper( $this->get(FunctionDefinitionRepository::class), - $this->get(RootNodeBuilder::class) + $this->get(RootNodeBuilder::class), + $settings, ), RootNodeBuilder::class => fn () => new RootNodeBuilder( @@ -99,8 +101,8 @@ public function __construct(Settings $settings) ), NodeBuilder::class => function () use ($settings) { - $listNodeBuilder = new ListNodeBuilder($settings->enableFlexibleCasting); - $arrayNodeBuilder = new ArrayNodeBuilder($settings->enableFlexibleCasting); + $listNodeBuilder = new ListNodeBuilder(); + $arrayNodeBuilder = new ArrayNodeBuilder(); $builder = new CasterNodeBuilder([ ListType::class => $listNodeBuilder, @@ -108,14 +110,13 @@ public function __construct(Settings $settings) ArrayType::class => $arrayNodeBuilder, NonEmptyArrayType::class => $arrayNodeBuilder, IterableType::class => $arrayNodeBuilder, - ShapedArrayType::class => new ShapedArrayNodeBuilder($settings->allowSuperfluousKeys), - ScalarType::class => new ScalarNodeBuilder($settings->enableFlexibleCasting), + ShapedArrayType::class => new ShapedArrayNodeBuilder(), + ScalarType::class => new ScalarNodeBuilder(), NullType::class => new NullNodeBuilder(), ObjectType::class => new ObjectNodeBuilder( $this->get(ClassDefinitionRepository::class), $this->get(ObjectBuilderFactory::class), $this->get(FilteredObjectNodeBuilder::class), - $settings->enableFlexibleCasting, ), ]); @@ -131,8 +132,6 @@ public function __construct(Settings $settings) $this->get(FunctionDefinitionRepository::class), $settings->customConstructors ), - $settings->enableFlexibleCasting, - $settings->allowSuperfluousKeys, ); $builder = new CasterProxyNodeBuilder($builder); @@ -148,12 +147,12 @@ public function __construct(Settings $settings) ); } - $builder = new StrictNodeBuilder($builder, $settings->allowPermissiveTypes, $settings->enableFlexibleCasting); + $builder = new StrictNodeBuilder($builder); return new ErrorCatcherNodeBuilder($builder, $settings->exceptionFilter); }, - FilteredObjectNodeBuilder::class => fn () => new FilteredObjectNodeBuilder($settings->allowSuperfluousKeys), + FilteredObjectNodeBuilder::class => fn () => new FilteredObjectNodeBuilder(), ObjectImplementations::class => fn () => new ObjectImplementations( new FunctionsContainer( diff --git a/src/Mapper/Object/ArgumentsValues.php b/src/Mapper/Object/ArgumentsValues.php index f2d7aee4..407112d9 100644 --- a/src/Mapper/Object/ArgumentsValues.php +++ b/src/Mapper/Object/ArgumentsValues.php @@ -5,12 +5,12 @@ namespace CuyZ\Valinor\Mapper\Object; use CuyZ\Valinor\Mapper\Object\Exception\InvalidSource; +use CuyZ\Valinor\Mapper\Tree\Shell; use CuyZ\Valinor\Type\CompositeTraversableType; use CuyZ\Valinor\Type\Types\ArrayKeyType; use IteratorAggregate; use Traversable; -use function array_filter; use function array_key_exists; use function count; use function is_array; @@ -36,22 +36,22 @@ private function __construct(Arguments $arguments) $this->arguments = $arguments; } - public static function forInterface(Arguments $arguments, mixed $value, bool $allowSuperfluousKeys): self + public static function forInterface(Arguments $arguments, Shell $shell): self { $self = new self($arguments); $self->forInterface = true; if (count($arguments) > 0) { - $self = $self->transform($value, $allowSuperfluousKeys); + $self = $self->transform($shell); } return $self; } - public static function forClass(Arguments $arguments, mixed $value, bool $allowSuperfluousKeys): self + public static function forClass(Arguments $arguments, Shell $shell): self { $self = new self($arguments); - $self = $self->transform($value, $allowSuperfluousKeys); + $self = $self->transform($shell); return $self; } @@ -66,33 +66,22 @@ public function getValue(string $name): mixed return $this->value[$name]; } - /** - * @return array - */ - public function superfluousKeys(): array - { - return array_filter( - array_keys($this->value), - fn ($key) => ! $this->arguments->has((string)$key) - ); - } - public function hadSingleArgument(): bool { return $this->hadSingleArgument; } - private function transform(mixed $value, bool $allowSuperfluousKeys): self + private function transform(Shell $shell): self { $clone = clone $this; - $transformedValue = $this->transformValueForSingleArgument($value, $allowSuperfluousKeys); + $transformedValue = $this->transformValueForSingleArgument($shell); if (! is_array($transformedValue)) { throw new InvalidSource($transformedValue, $this->arguments); } - if ($transformedValue !== $value) { + if ($transformedValue !== $shell->value()) { $clone->hadSingleArgument = true; } @@ -109,8 +98,10 @@ private function transform(mixed $value, bool $allowSuperfluousKeys): self return $clone; } - private function transformValueForSingleArgument(mixed $value, bool $allowSuperfluousKeys): mixed + private function transformValueForSingleArgument(Shell $shell): mixed { + $value = $shell->value(); + if (count($this->arguments) !== 1) { return $value; } @@ -122,7 +113,7 @@ private function transformValueForSingleArgument(mixed $value, bool $allowSuperf && $type->keyType() !== ArrayKeyType::integer(); if (is_array($value) && array_key_exists($name, $value)) { - if ($this->forInterface || ! $isTraversableAndAllowsStringKeys || $allowSuperfluousKeys || count($value) === 1) { + if ($this->forInterface || ! $isTraversableAndAllowsStringKeys || $shell->allowSuperfluousKeys() || count($value) === 1) { return $value; } } diff --git a/src/Mapper/Tree/Builder/ArrayNodeBuilder.php b/src/Mapper/Tree/Builder/ArrayNodeBuilder.php index 2ab1340a..c75e67e9 100644 --- a/src/Mapper/Tree/Builder/ArrayNodeBuilder.php +++ b/src/Mapper/Tree/Builder/ArrayNodeBuilder.php @@ -18,8 +18,6 @@ /** @internal */ final class ArrayNodeBuilder implements NodeBuilder { - public function __construct(private bool $enableFlexibleCasting) {} - public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { $type = $shell->type(); @@ -27,7 +25,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode assert($type instanceof ArrayType || $type instanceof NonEmptyArrayType || $type instanceof IterableType); - if ($this->enableFlexibleCasting && $value === null) { + if ($shell->enableFlexibleCasting() && $value === null) { return TreeNode::branch($shell, [], []); } diff --git a/src/Mapper/Tree/Builder/FilteredObjectNodeBuilder.php b/src/Mapper/Tree/Builder/FilteredObjectNodeBuilder.php index 712de130..5eb70e07 100644 --- a/src/Mapper/Tree/Builder/FilteredObjectNodeBuilder.php +++ b/src/Mapper/Tree/Builder/FilteredObjectNodeBuilder.php @@ -6,33 +6,22 @@ use CuyZ\Valinor\Mapper\Object\ArgumentsValues; use CuyZ\Valinor\Mapper\Object\ObjectBuilder; -use CuyZ\Valinor\Mapper\Tree\Exception\UnexpectedArrayKeysForClass; use CuyZ\Valinor\Mapper\Tree\Shell; -use function count; - /** @internal */ final class FilteredObjectNodeBuilder { - public function __construct(private bool $allowSuperfluousKeys) {} - public function build(ObjectBuilder $builder, Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { - $arguments = ArgumentsValues::forClass($builder->describeArguments(), $shell->value(), $this->allowSuperfluousKeys); + $arguments = ArgumentsValues::forClass($builder->describeArguments(), $shell); $children = $this->children($shell, $arguments, $rootBuilder); $object = $this->buildObject($builder, $children); - $node = $arguments->hadSingleArgument() + return $arguments->hadSingleArgument() ? TreeNode::flattenedBranch($shell, $object, $children[0]) : TreeNode::branch($shell, $object, $children); - - if (! $this->allowSuperfluousKeys && count($arguments->superfluousKeys()) > 0) { - $node = $node->withMessage(new UnexpectedArrayKeysForClass($arguments)); - } - - return $node; } /** diff --git a/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php b/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php index b96b663a..73c9b7e2 100644 --- a/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php +++ b/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php @@ -30,8 +30,6 @@ public function __construct( private ObjectBuilderFactory $objectBuilderFactory, private FilteredObjectNodeBuilder $filteredObjectNodeBuilder, private FunctionsContainer $constructors, - private bool $enableFlexibleCasting, - private bool $allowSuperfluousKeys, ) {} public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode @@ -50,7 +48,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode return $this->delegate->build($shell, $rootBuilder); } - if ($this->enableFlexibleCasting && $shell->value() === null) { + if ($shell->enableFlexibleCasting() && $shell->value() === null) { $shell = $shell->withValue([]); } @@ -140,7 +138,7 @@ private function transformSourceForClass(Shell $shell, Arguments $interfaceArgum */ private function children(Shell $shell, Arguments $arguments, RootNodeBuilder $rootBuilder): array { - $arguments = ArgumentsValues::forInterface($arguments, $shell->value(), $this->allowSuperfluousKeys); + $arguments = ArgumentsValues::forInterface($arguments, $shell); $children = []; diff --git a/src/Mapper/Tree/Builder/ListNodeBuilder.php b/src/Mapper/Tree/Builder/ListNodeBuilder.php index 8033c4d8..83406881 100644 --- a/src/Mapper/Tree/Builder/ListNodeBuilder.php +++ b/src/Mapper/Tree/Builder/ListNodeBuilder.php @@ -17,8 +17,6 @@ /** @internal */ final class ListNodeBuilder implements NodeBuilder { - public function __construct(private bool $enableFlexibleCasting) {} - public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { $type = $shell->type(); @@ -26,7 +24,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode assert($type instanceof ListType || $type instanceof NonEmptyListType); - if ($this->enableFlexibleCasting && $value === null) { + if ($shell->enableFlexibleCasting() && $value === null) { return TreeNode::branch($shell, [], []); } @@ -53,7 +51,7 @@ private function children(CompositeTraversableType $type, Shell $shell, RootNode $children = []; foreach ($values as $key => $value) { - if ($this->enableFlexibleCasting || $key === $expected) { + if ($shell->enableFlexibleCasting() || $key === $expected) { $child = $shell->child((string)$expected, $subType); $children[$expected] = $rootBuilder->build($child->withValue($value)); } else { diff --git a/src/Mapper/Tree/Builder/ObjectNodeBuilder.php b/src/Mapper/Tree/Builder/ObjectNodeBuilder.php index e67b613a..007de11a 100644 --- a/src/Mapper/Tree/Builder/ObjectNodeBuilder.php +++ b/src/Mapper/Tree/Builder/ObjectNodeBuilder.php @@ -20,7 +20,6 @@ public function __construct( private ClassDefinitionRepository $classDefinitionRepository, private ObjectBuilderFactory $objectBuilderFactory, private FilteredObjectNodeBuilder $filteredObjectNodeBuilder, - private bool $enableFlexibleCasting, ) {} public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode @@ -30,7 +29,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode // @infection-ignore-all assert($type instanceof ObjectType); - if ($this->enableFlexibleCasting && $shell->value() === null) { + if ($shell->enableFlexibleCasting() && $shell->value() === null) { $shell = $shell->withValue([]); } diff --git a/src/Mapper/Tree/Builder/ScalarNodeBuilder.php b/src/Mapper/Tree/Builder/ScalarNodeBuilder.php index 9a0d8a76..63b3df6a 100644 --- a/src/Mapper/Tree/Builder/ScalarNodeBuilder.php +++ b/src/Mapper/Tree/Builder/ScalarNodeBuilder.php @@ -12,8 +12,6 @@ /** @internal */ final class ScalarNodeBuilder implements NodeBuilder { - public function __construct(private bool $enableFlexibleCasting) {} - public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { $type = $shell->type(); @@ -21,7 +19,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode assert($type instanceof ScalarType); - if (! $this->enableFlexibleCasting || ! $type->canCast($value)) { + if (! $shell->enableFlexibleCasting() || ! $type->canCast($value)) { throw $type->errorMessage(); } diff --git a/src/Mapper/Tree/Builder/ShapedArrayNodeBuilder.php b/src/Mapper/Tree/Builder/ShapedArrayNodeBuilder.php index 6dc633f2..e270f36a 100644 --- a/src/Mapper/Tree/Builder/ShapedArrayNodeBuilder.php +++ b/src/Mapper/Tree/Builder/ShapedArrayNodeBuilder.php @@ -5,20 +5,16 @@ namespace CuyZ\Valinor\Mapper\Tree\Builder; use CuyZ\Valinor\Mapper\Tree\Exception\SourceMustBeIterable; -use CuyZ\Valinor\Mapper\Tree\Exception\UnexpectedShapedArrayKeys; use CuyZ\Valinor\Mapper\Tree\Shell; use CuyZ\Valinor\Type\Types\ShapedArrayType; use function array_key_exists; use function assert; -use function count; use function is_array; /** @internal */ final class ShapedArrayNodeBuilder implements NodeBuilder { - public function __construct(private bool $allowSuperfluousKeys) {} - public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { $type = $shell->type(); @@ -34,13 +30,7 @@ public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode $array = $this->buildArray($children); - $node = TreeNode::branch($shell, $array, $children); - - if (! $this->allowSuperfluousKeys && count($value) > count($children)) { - $node = $node->withMessage(new UnexpectedShapedArrayKeys($value, $children)); - } - - return $node; + return TreeNode::branch($shell, $array, $children); } /** diff --git a/src/Mapper/Tree/Builder/StrictNodeBuilder.php b/src/Mapper/Tree/Builder/StrictNodeBuilder.php index ecff6142..7361e9f2 100644 --- a/src/Mapper/Tree/Builder/StrictNodeBuilder.php +++ b/src/Mapper/Tree/Builder/StrictNodeBuilder.php @@ -13,20 +13,18 @@ final class StrictNodeBuilder implements NodeBuilder { public function __construct( private NodeBuilder $delegate, - private bool $allowPermissiveTypes, - private bool $enableFlexibleCasting ) {} public function build(Shell $shell, RootNodeBuilder $rootBuilder): TreeNode { $type = $shell->type(); - if (! $this->allowPermissiveTypes) { + if (! $shell->allowPermissiveTypes()) { TypeHelper::checkPermissiveType($type); } if (! $shell->hasValue()) { - if ($this->enableFlexibleCasting) { + if ($shell->enableFlexibleCasting()) { return $this->delegate->build($shell->withValue(null), $rootBuilder); } diff --git a/src/Mapper/Tree/Builder/TreeNode.php b/src/Mapper/Tree/Builder/TreeNode.php index 890c2ec0..ae31fdb5 100644 --- a/src/Mapper/Tree/Builder/TreeNode.php +++ b/src/Mapper/Tree/Builder/TreeNode.php @@ -5,6 +5,7 @@ namespace CuyZ\Valinor\Mapper\Tree\Builder; use CuyZ\Valinor\Mapper\Tree\Exception\InvalidNodeValue; +use CuyZ\Valinor\Mapper\Tree\Exception\UnexpectedKeysInSource; use CuyZ\Valinor\Mapper\Tree\Message\Message; use CuyZ\Valinor\Mapper\Tree\Node; use CuyZ\Valinor\Mapper\Tree\Shell; @@ -14,6 +15,8 @@ use function array_map; use function assert; +use function count; +use function is_array; /** @internal */ final class TreeNode @@ -141,14 +144,23 @@ private function check(): void foreach ($this->children as $child) { if (! $child->valid) { $this->valid = false; - - return; } } - if ($this->valid && ! $this->shell->type()->accepts($this->value)) { + $value = $this->shell->value(); + $type = $this->shell->type(); + + if (! $this->shell->allowSuperfluousKeys() + && is_array($value) + && count($value) > count($this->children) + ) { + $this->valid = false; + $this->messages[] = new UnexpectedKeysInSource($value, $this->children); + } + + if ($this->valid && ! $type->accepts($this->value)) { $this->valid = false; - $this->messages[] = new InvalidNodeValue($this->shell->type()); + $this->messages[] = new InvalidNodeValue($type); } } diff --git a/src/Mapper/Tree/Exception/UnexpectedArrayKeysForClass.php b/src/Mapper/Tree/Exception/UnexpectedArrayKeysForClass.php deleted file mode 100644 index 9ae2de4b..00000000 --- a/src/Mapper/Tree/Exception/UnexpectedArrayKeysForClass.php +++ /dev/null @@ -1,46 +0,0 @@ - */ - private array $parameters; - - public function __construct(ArgumentsValues $arguments) - { - $expected = array_map(fn (Argument $argument) => $argument->name(), [...$arguments]); - - $this->parameters = [ - 'keys' => '`' . implode('`, `', $arguments->superfluousKeys()) . '`', - 'expected_keys' => '`' . implode('`, `', $expected) . '`', - ]; - - parent::__construct(StringFormatter::for($this), 1655149208); - } - - public function body(): string - { - return $this->body; - } - - public function parameters(): array - { - return $this->parameters; - } -} diff --git a/src/Mapper/Tree/Exception/UnexpectedShapedArrayKeys.php b/src/Mapper/Tree/Exception/UnexpectedKeysInSource.php similarity index 93% rename from src/Mapper/Tree/Exception/UnexpectedShapedArrayKeys.php rename to src/Mapper/Tree/Exception/UnexpectedKeysInSource.php index dc55919b..c32ff4d5 100644 --- a/src/Mapper/Tree/Exception/UnexpectedShapedArrayKeys.php +++ b/src/Mapper/Tree/Exception/UnexpectedKeysInSource.php @@ -17,7 +17,7 @@ use function in_array; /** @internal */ -final class UnexpectedShapedArrayKeys extends RuntimeException implements ErrorMessage, HasParameters +final class UnexpectedKeysInSource extends RuntimeException implements ErrorMessage, HasParameters { private string $body = 'Unexpected key(s) {keys}, expected {expected_keys}.'; diff --git a/src/Mapper/Tree/Shell.php b/src/Mapper/Tree/Shell.php index ca87bafe..f7e2235a 100644 --- a/src/Mapper/Tree/Shell.php +++ b/src/Mapper/Tree/Shell.php @@ -5,6 +5,7 @@ namespace CuyZ\Valinor\Mapper\Tree; use CuyZ\Valinor\Definition\Attributes; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Exception\UnresolvableShellType; use CuyZ\Valinor\Type\Type; use CuyZ\Valinor\Type\Types\UnresolvableType; @@ -16,6 +17,10 @@ /** @internal */ final class Shell { + private Settings $settings; + + private Type $type; + private string $name; private bool $hasValue = false; @@ -26,21 +31,27 @@ final class Shell private self $parent; - private function __construct(private Type $type) + private function __construct(Settings $settings, Type $type) { if ($type instanceof UnresolvableType) { throw new UnresolvableShellType($type); } + + $this->settings = $settings; + $this->type = $type; } - public static function root(Type $type, mixed $value): self - { - return (new self($type))->withValue($value); + public static function root( + Settings $settings, + Type $type, + mixed $value, + ): self { + return (new self($settings, $type))->withValue($value); } public function child(string $name, Type $type, Attributes $attributes = null): self { - $instance = new self($type); + $instance = new self($this->settings, $type); $instance->name = $name; $instance->parent = $this; @@ -95,6 +106,21 @@ public function value(): mixed return $this->value; } + public function enableFlexibleCasting(): bool + { + return $this->settings->enableFlexibleCasting; + } + + public function allowSuperfluousKeys(): bool + { + return $this->settings->allowSuperfluousKeys; + } + + public function allowPermissiveTypes(): bool + { + return $this->settings->allowPermissiveTypes; + } + public function attributes(): Attributes { return $this->attributes ?? Attributes::empty(); diff --git a/src/Mapper/TypeArgumentsMapper.php b/src/Mapper/TypeArgumentsMapper.php index f0d73f81..465ec624 100644 --- a/src/Mapper/TypeArgumentsMapper.php +++ b/src/Mapper/TypeArgumentsMapper.php @@ -6,6 +6,7 @@ use CuyZ\Valinor\Definition\ParameterDefinition; use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Exception\TypeErrorDuringArgumentsMapping; use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder; use CuyZ\Valinor\Mapper\Tree\Exception\UnresolvableShellType; @@ -17,15 +18,11 @@ /** @internal */ final class TypeArgumentsMapper implements ArgumentsMapper { - private FunctionDefinitionRepository $functionDefinitionRepository; - - private RootNodeBuilder $nodeBuilder; - - public function __construct(FunctionDefinitionRepository $functionDefinitionRepository, RootNodeBuilder $nodeBuilder) - { - $this->functionDefinitionRepository = $functionDefinitionRepository; - $this->nodeBuilder = $nodeBuilder; - } + public function __construct( + private FunctionDefinitionRepository $functionDefinitionRepository, + private RootNodeBuilder $nodeBuilder, + private Settings $settings, + ) {} /** @pure */ public function mapArguments(callable $callable, mixed $source): array @@ -42,7 +39,7 @@ public function mapArguments(callable $callable, mixed $source): array ); $type = new ShapedArrayType(...$elements); - $shell = Shell::root($type, $source); + $shell = Shell::root($this->settings, $type, $source); try { $node = $this->nodeBuilder->build($shell); diff --git a/src/Mapper/TypeTreeMapper.php b/src/Mapper/TypeTreeMapper.php index d7691dc1..6c0734ca 100644 --- a/src/Mapper/TypeTreeMapper.php +++ b/src/Mapper/TypeTreeMapper.php @@ -4,6 +4,7 @@ namespace CuyZ\Valinor\Mapper; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Exception\InvalidMappingTypeSignature; use CuyZ\Valinor\Mapper\Exception\TypeErrorDuringMapping; use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder; @@ -18,7 +19,8 @@ final class TypeTreeMapper implements TreeMapper { public function __construct( private TypeParser $typeParser, - private RootNodeBuilder $nodeBuilder + private RootNodeBuilder $nodeBuilder, + private Settings $settings, ) {} /** @pure */ @@ -41,7 +43,7 @@ private function node(string $signature, mixed $source): TreeNode throw new InvalidMappingTypeSignature($signature, $exception); } - $shell = Shell::root($type, $source); + $shell = Shell::root($this->settings, $type, $source); try { return $this->nodeBuilder->build($shell); diff --git a/tests/Fake/Mapper/FakeShell.php b/tests/Fake/Mapper/FakeShell.php index eddfef42..91e5bb2b 100644 --- a/tests/Fake/Mapper/FakeShell.php +++ b/tests/Fake/Mapper/FakeShell.php @@ -4,15 +4,16 @@ namespace CuyZ\Valinor\Tests\Fake\Mapper; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Shell; use CuyZ\Valinor\Tests\Fake\Type\FakeType; use CuyZ\Valinor\Type\Type; final class FakeShell { - public static function new(Type $type, mixed $value = null): Shell + public static function new(Type $type, mixed $value = null, ?Settings $settings = null): Shell { - return Shell::root($type, $value); + return Shell::root($settings ?? new Settings(), $type, $value); } public static function any(): Shell diff --git a/tests/Integration/Mapping/InterfaceInferringMappingTest.php b/tests/Integration/Mapping/InterfaceInferringMappingTest.php index a4a8457d..159ee3ab 100644 --- a/tests/Integration/Mapping/InterfaceInferringMappingTest.php +++ b/tests/Integration/Mapping/InterfaceInferringMappingTest.php @@ -393,7 +393,7 @@ public function test_superfluous_values_throws_exception(): void } catch (MappingError $exception) { $error = $exception->node()->messages()[0]; - self::assertSame('1655149208', $error->code()); + self::assertSame('1655117782', $error->code()); self::assertSame('Unexpected key(s) `superfluousValue`, expected `valueA`.', (string)$error); } } diff --git a/tests/Integration/Mapping/Object/ObjectValuesMappingTest.php b/tests/Integration/Mapping/Object/ObjectValuesMappingTest.php index 04681cb8..0fc8dcd2 100644 --- a/tests/Integration/Mapping/Object/ObjectValuesMappingTest.php +++ b/tests/Integration/Mapping/Object/ObjectValuesMappingTest.php @@ -59,7 +59,7 @@ public function test_superfluous_values_throws_exception_and_keeps_nested_errors $rootError = $exception->node()->messages()[0]; $nestedError = $exception->node()->children()['stringA']->messages()[0]; - self::assertSame('1655149208', $rootError->code()); + self::assertSame('1655117782', $rootError->code()); self::assertSame('Unexpected key(s) `unexpectedValueA`, `unexpectedValueB`, `42`, expected `stringA`, `stringB`.', (string)$rootError); self::assertSame('Value 42 is not a valid string.', (string)$nestedError); } diff --git a/tests/Unit/Mapper/Tree/Builder/ArrayNodeBuilderTest.php b/tests/Unit/Mapper/Tree/Builder/ArrayNodeBuilderTest.php index d5510b5a..71720616 100644 --- a/tests/Unit/Mapper/Tree/Builder/ArrayNodeBuilderTest.php +++ b/tests/Unit/Mapper/Tree/Builder/ArrayNodeBuilderTest.php @@ -5,6 +5,7 @@ namespace CuyZ\Valinor\Tests\Unit\Mapper\Tree\Builder; use AssertionError; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Builder\ArrayNodeBuilder; use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder; use CuyZ\Valinor\Tests\Fake\Mapper\FakeShell; @@ -16,7 +17,12 @@ final class ArrayNodeBuilderTest extends TestCase { public function test_build_with_null_value_in_flexible_mode_returns_empty_branch_node(): void { - $node = (new RootNodeBuilder(new ArrayNodeBuilder(true)))->build(FakeShell::new(ArrayType::native())); + $setting = new Settings(); + $setting->enableFlexibleCasting = true; + + $shell = FakeShell::new(ArrayType::native(), settings: $setting); + + $node = (new RootNodeBuilder(new ArrayNodeBuilder()))->build($shell); self::assertSame([], $node->value()); self::assertEmpty($node->node()->children()); @@ -26,6 +32,6 @@ public function test_invalid_type_fails_assertion(): void { $this->expectException(AssertionError::class); - (new RootNodeBuilder(new ArrayNodeBuilder(true)))->build(FakeShell::new(new FakeType())); + (new RootNodeBuilder(new ArrayNodeBuilder()))->build(FakeShell::new(new FakeType())); } } diff --git a/tests/Unit/Mapper/Tree/Builder/ListNodeBuilderTest.php b/tests/Unit/Mapper/Tree/Builder/ListNodeBuilderTest.php index 17cf660f..312b7ee2 100644 --- a/tests/Unit/Mapper/Tree/Builder/ListNodeBuilderTest.php +++ b/tests/Unit/Mapper/Tree/Builder/ListNodeBuilderTest.php @@ -5,6 +5,7 @@ namespace CuyZ\Valinor\Tests\Unit\Mapper\Tree\Builder; use AssertionError; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Builder\ListNodeBuilder; use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder; use CuyZ\Valinor\Tests\Fake\Mapper\FakeShell; @@ -16,7 +17,12 @@ final class ListNodeBuilderTest extends TestCase { public function test_build_with_null_value_in_flexible_mode_returns_empty_branch_node(): void { - $node = (new RootNodeBuilder(new ListNodeBuilder(true)))->build(FakeShell::new(ListType::native())); + $setting = new Settings(); + $setting->enableFlexibleCasting = true; + + $shell = FakeShell::new(ListType::native(), settings: $setting); + + $node = (new RootNodeBuilder(new ListNodeBuilder()))->build($shell); self::assertSame([], $node->value()); self::assertEmpty($node->node()->children()); @@ -26,6 +32,6 @@ public function test_invalid_type_fails_assertion(): void { $this->expectException(AssertionError::class); - (new RootNodeBuilder(new ListNodeBuilder(true)))->build(FakeShell::new(new FakeType())); + (new RootNodeBuilder(new ListNodeBuilder()))->build(FakeShell::new(new FakeType())); } } diff --git a/tests/Unit/Mapper/Tree/Builder/ScalarNodeBuilderTest.php b/tests/Unit/Mapper/Tree/Builder/ScalarNodeBuilderTest.php index ebdc268f..e1785ff7 100644 --- a/tests/Unit/Mapper/Tree/Builder/ScalarNodeBuilderTest.php +++ b/tests/Unit/Mapper/Tree/Builder/ScalarNodeBuilderTest.php @@ -16,6 +16,6 @@ public function test_invalid_type_fails_assertion(): void { $this->expectException(AssertionError::class); - (new RootNodeBuilder(new ScalarNodeBuilder(true)))->build(FakeShell::any()); + (new RootNodeBuilder(new ScalarNodeBuilder()))->build(FakeShell::any()); } } diff --git a/tests/Unit/Mapper/Tree/Builder/ShapedArrayNodeBuilderTest.php b/tests/Unit/Mapper/Tree/Builder/ShapedArrayNodeBuilderTest.php index 9c8d6cce..71b2cc56 100644 --- a/tests/Unit/Mapper/Tree/Builder/ShapedArrayNodeBuilderTest.php +++ b/tests/Unit/Mapper/Tree/Builder/ShapedArrayNodeBuilderTest.php @@ -21,7 +21,7 @@ public function test_invalid_type_fails_assertion(): void { $this->expectException(AssertionError::class); - (new RootNodeBuilder(new ShapedArrayNodeBuilder(true)))->build(FakeShell::any()); + (new RootNodeBuilder(new ShapedArrayNodeBuilder()))->build(FakeShell::any()); } public function test_build_with_null_source_throws_exception(): void @@ -32,6 +32,6 @@ public function test_build_with_null_source_throws_exception(): void $this->expectExceptionCode(1618739163); $this->expectExceptionMessage("Cannot be empty and must be filled with a value matching type `array{foo: SomeType}`."); - (new RootNodeBuilder(new ShapedArrayNodeBuilder(true)))->build(FakeShell::new($type)); + (new RootNodeBuilder(new ShapedArrayNodeBuilder()))->build(FakeShell::new($type)); } } diff --git a/tests/Unit/Mapper/Tree/Builder/TreeNodeTest.php b/tests/Unit/Mapper/Tree/Builder/TreeNodeTest.php index e9bfb4c7..fc329e34 100644 --- a/tests/Unit/Mapper/Tree/Builder/TreeNodeTest.php +++ b/tests/Unit/Mapper/Tree/Builder/TreeNodeTest.php @@ -6,6 +6,7 @@ use AssertionError; use CuyZ\Valinor\Definition\Attributes; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Builder\TreeNode; use CuyZ\Valinor\Mapper\Tree\Shell; use CuyZ\Valinor\Tests\Fake\Mapper\Tree\Builder\FakeTreeNode; @@ -22,7 +23,7 @@ public function test_node_leaf_values_can_be_retrieved(): void { $type = FakeType::permissive(); - $shell = Shell::root($type, 'some source value'); + $shell = Shell::root(new Settings(), $type, 'some source value'); $node = TreeNode::leaf($shell, 'some value')->node(); self::assertTrue($node->isRoot()); diff --git a/tests/Unit/Mapper/Tree/ShellTest.php b/tests/Unit/Mapper/Tree/ShellTest.php index 40571784..96cb70b0 100644 --- a/tests/Unit/Mapper/Tree/ShellTest.php +++ b/tests/Unit/Mapper/Tree/ShellTest.php @@ -5,6 +5,7 @@ namespace CuyZ\Valinor\Tests\Unit\Mapper\Tree; use CuyZ\Valinor\Definition\Attributes; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Tree\Shell; use CuyZ\Valinor\Tests\Fake\Type\FakeType; use PHPUnit\Framework\TestCase; @@ -16,7 +17,7 @@ public function test_type_and_value_can_be_retrieved(): void $type = new FakeType(); $value = 'foo'; - $shell = Shell::root($type, $value); + $shell = Shell::root(new Settings(), $type, $value); self::assertSame($type, $shell->type()); self::assertSame($value, $shell->value()); @@ -24,7 +25,7 @@ public function test_type_and_value_can_be_retrieved(): void public function test_root_path_is_fixed(): void { - $shell = Shell::root(new FakeType(), 'foo'); + $shell = Shell::root(new Settings(), new FakeType(), 'foo'); self::assertSame('*root*', $shell->path()); } @@ -34,7 +35,7 @@ public function test_change_type_changes_type(): void $typeA = new FakeType(); $typeB = FakeType::matching($typeA); - $shellA = Shell::root($typeA, []); + $shellA = Shell::root(new Settings(), $typeA, []); $shellB = $shellA->withType($typeB); self::assertNotSame($shellA, $shellB); @@ -46,7 +47,7 @@ public function test_change_value_changes_value(): void $valueA = 'foo'; $valueB = 'bar'; - $shellA = Shell::root(new FakeType(), $valueA); + $shellA = Shell::root(new Settings(), new FakeType(), $valueA); $shellB = $shellA->withValue($valueB); self::assertNotSame($shellA, $shellB); @@ -55,7 +56,7 @@ public function test_change_value_changes_value(): void public function test_root_shell_is_root(): void { - $shell = Shell::root(new FakeType(), []); + $shell = Shell::root(new Settings(), new FakeType(), []); self::assertTrue($shell->isRoot()); self::assertSame('', $shell->name()); @@ -67,7 +68,7 @@ public function test_shell_child_values_can_be_retrieved(): void $type = FakeType::permissive(); $attributes = new Attributes(); - $shell = Shell::root(new FakeType(), []); + $shell = Shell::root(new Settings(), new FakeType(), []); $child = $shell->child('foo', $type, $attributes)->withValue($value); self::assertSame('foo', $child->name()); diff --git a/tests/Unit/Mapper/TypeTreeMapperTest.php b/tests/Unit/Mapper/TypeTreeMapperTest.php index c31117dc..ba9c6db9 100644 --- a/tests/Unit/Mapper/TypeTreeMapperTest.php +++ b/tests/Unit/Mapper/TypeTreeMapperTest.php @@ -4,6 +4,7 @@ namespace CuyZ\Valinor\Tests\Unit\Mapper; +use CuyZ\Valinor\Library\Settings; use CuyZ\Valinor\Mapper\Exception\InvalidMappingTypeSignature; use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder; use CuyZ\Valinor\Mapper\TypeTreeMapper; @@ -22,6 +23,7 @@ protected function setUp(): void $this->mapper = new TypeTreeMapper( new FakeTypeParser(), new RootNodeBuilder(new FakeNodeBuilder()), + new Settings(), ); }