Test Failed
Push — master ( 16c39a...9c7d46 )
by Kirill
07:07
created

DefinitionBuilder::reduce()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Frontend\Builder;
11
12
use Railt\Parser\Ast\RuleInterface;
13
use Railt\SDL\Frontend\AST\TypeNameNode;
14
use Railt\SDL\Frontend\Context\ContextInterface;
15
use Railt\SDL\Frontend\Record\Argument;
16
use Railt\SDL\Frontend\Record\Record;
17
use Railt\SDL\Frontend\Record\RecordInterface;
18
use Railt\SDL\Frontend\Type\Anonymous;
19
use Railt\SDL\Frontend\Type\Type;
20
use Railt\SDL\Frontend\Type\TypeInterface;
21
use Railt\SDL\Frontend\Type\TypeName;
22
use Railt\SDL\Frontend\Type\TypeNameInterface;
23
24
/**
25
 * Class DefinitionBuilder
26
 */
27
class DefinitionBuilder extends BaseBuilder
28
{
29
    /**
30
     * @var string[]
31
     */
32
    private const TYPE_DEFINITIONS = [
33
        'ObjectDefinition'    => Type::OBJECT,
34
        'SchemaDefinition'    => Type::SCHEMA,
35
        'DirectiveDefinition' => Type::DIRECTIVE,
36
    ];
37
38
    /**
39
     * @param RuleInterface $rule
40
     * @return bool
41
     */
42
    public function match(RuleInterface $rule): bool
43
    {
44
        return (bool)(self::TYPE_DEFINITIONS[$rule->getName()] ?? false);
45
    }
46
47
    /**
48
     * @param ContextInterface $ctx
49
     * @param RuleInterface $rule
50
     * @return \Generator|RecordInterface|TypeNameInterface|void
51
     */
52
    public function reduce(ContextInterface $ctx, RuleInterface $rule)
53
    {
54
        $name = yield $this->createTypeName($rule);
55
56
        $record = new Record($name, $this->getType($rule), $rule);
57
58
        foreach ($this->createTypeArguments($ctx, $rule) as $argument) {
59
            $record->addArgument($argument);
60
        }
61
62
        $ctx->close();
63
64
        return $record;
65
    }
66
67
    /**
68
     * @param RuleInterface $rule
69
     * @return TypeNameInterface
70
     */
71
    private function createTypeName(RuleInterface $rule): TypeNameInterface
72
    {
73
        /** @var TypeNameNode $node */
74
        $node = $rule->first('> #TypeDefinitionHeader > #TypeName');
75
76
        return $node ? $node->toTypeName() : new Anonymous();
77
    }
78
79
    /**
80
     * @param RuleInterface $rule
81
     * @return TypeInterface
82
     */
83
    private function getType(RuleInterface $rule): TypeInterface
84
    {
85
        $type = TypeName::fromString(self::TYPE_DEFINITIONS[$rule->getName()]);
86
87
        return Type::of($type);
88
    }
89
90
    /**
91
     * @param ContextInterface $ctx
92
     * @param RuleInterface $rule
93
     * @return iterable
94
     */
95
    private function createTypeArguments(ContextInterface $ctx, RuleInterface $rule): iterable
96
    {
97
        $arguments = $rule->find('> #TypeDefinitionHeader > #TypeArgumentDefinition');
98
99
        foreach ($arguments as $argument) {
100
            $name = $argument->first('> #Name > :T_NAME')->getValue();
101
            /** @var TypeNameNode $type */
102
            $type = $argument->first('> #TypeName');
103
104
            yield new Argument($name, Type::of($type->toTypeName()), $ctx);
105
        }
106
    }
107
}
108