misc: narrow union types during node build

This commit is contained in:
Romain Canon 2022-02-01 18:35:00 +01:00
parent b49ebf37be
commit 06e9dedfd8
3 changed files with 47 additions and 44 deletions

View File

@ -32,6 +32,7 @@ use CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\ScalarNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\ShapedArrayNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\ShellVisitorNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\UnionNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\ValueAlteringNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Builder\VisitorNodeBuilder;
use CuyZ\Valinor\Mapper\Tree\Visitor\AggregateShellVisitor;
@ -39,7 +40,6 @@ use CuyZ\Valinor\Mapper\Tree\Visitor\AttributeShellVisitor;
use CuyZ\Valinor\Mapper\Tree\Visitor\InterfaceShellVisitor;
use CuyZ\Valinor\Mapper\Tree\Visitor\ObjectBindingShellVisitor;
use CuyZ\Valinor\Mapper\Tree\Visitor\ShellVisitor;
use CuyZ\Valinor\Mapper\Tree\Visitor\UnionShellVisitor;
use CuyZ\Valinor\Mapper\TreeMapper;
use CuyZ\Valinor\Mapper\TreeMapperContainer;
use CuyZ\Valinor\Type\Parser\CachedParser;
@ -92,15 +92,6 @@ final class Container
ShellVisitor::class => function () use ($settings): ShellVisitor {
return new AggregateShellVisitor(
new UnionShellVisitor(
new UnionNullNarrower(
new UnionObjectNarrower(
new UnionScalarNarrower(),
$this->get(ClassDefinitionRepository::class),
$this->get(ObjectBuilderFactory::class),
)
)
),
new InterfaceShellVisitor(
$settings->interfaceMapping,
$this->get(TypeParser::class),
@ -129,6 +120,14 @@ final class Container
ScalarType::class => new ScalarNodeBuilder(),
]);
$builder = new UnionNodeBuilder($builder, new UnionNullNarrower(
new UnionObjectNarrower(
new UnionScalarNarrower(),
$this->get(ClassDefinitionRepository::class),
$this->get(ObjectBuilderFactory::class),
)
));
$builder = new VisitorNodeBuilder($builder, $settings->nodeVisitors);
$builder = new ValueAlteringNodeBuilder($builder, $settings->valueModifier);
$builder = new ShellVisitorNodeBuilder($builder, $this->get(ShellVisitor::class));

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Mapper\Tree\Builder;
use CuyZ\Valinor\Mapper\Tree\Node;
use CuyZ\Valinor\Mapper\Tree\Shell;
use CuyZ\Valinor\Type\Resolver\Union\UnionNarrower;
use CuyZ\Valinor\Type\Types\UnionType;
/** @internal */
final class UnionNodeBuilder implements NodeBuilder
{
private NodeBuilder $delegate;
private UnionNarrower $unionNarrower;
public function __construct(NodeBuilder $delegate, UnionNarrower $unionNarrower)
{
$this->delegate = $delegate;
$this->unionNarrower = $unionNarrower;
}
public function build(Shell $shell, RootNodeBuilder $rootBuilder): Node
{
$type = $shell->type();
$value = $shell->value();
if (! $type instanceof UnionType) {
return $this->delegate->build($shell, $rootBuilder);
}
$narrowedType = $this->unionNarrower->narrow($type, $value);
return $rootBuilder->build($shell->withType($narrowedType));
}
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Mapper\Tree\Visitor;
use CuyZ\Valinor\Mapper\Tree\Shell;
use CuyZ\Valinor\Type\Resolver\Union\UnionNarrower;
use CuyZ\Valinor\Type\Types\UnionType;
/** @internal */
final class UnionShellVisitor implements ShellVisitor
{
private UnionNarrower $unionNarrower;
public function __construct(UnionNarrower $unionNarrower)
{
$this->unionNarrower = $unionNarrower;
}
public function visit(Shell $shell): Shell
{
$type = $shell->type();
$value = $shell->value();
if (! $type instanceof UnionType) {
return $shell;
}
$narrowedType = $this->unionNarrower->narrow($type, $value);
return $shell->withType($narrowedType);
}
}