Test Failed
Push — master ( 08b170...e6bc2a )
by Kirill
02:02
created

Backend::exec()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 3
nc 3
nop 2
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\Compiler;
11
12
use Railt\Parser\Ast\RuleInterface;
13
use Railt\Reflection\Contracts\Definition as DefinitionInterface;
14
use Railt\Reflection\Contracts\Document;
15
use Railt\SDL\Builder\BuilderInterface;
16
use Railt\SDL\Builder\Context;
17
use Railt\SDL\Builder\Definition;
18
use Railt\SDL\Builder\Invocation;
19
use Railt\SDL\Exception\TypeException;
20
21
/**
22
 * Class Backend
23
 */
24
class Backend
25
{
26
    /**
27
     * @var string
28
     */
29
    private const ERR_UNSUPPORTED_RULE = '%s is not supported by this compiler';
30
31
    /**
32
     * @var string
33
     */
34
    private const ERR_UNRECOGNIZED_RULE = 'The language rule <%s> is not supported or implemented by this compiler';
35
36
    /**
37
     * @var string[]
38
     */
39
    private const BUILDERS = [
40
        // Root definitions
41
        'SchemaDefinition'    => Definition\SchemaBuilder::class,
42
        'ObjectDefinition'    => Definition\ObjectBuilder::class,
43
        'EnumDefinition'      => Definition\EnumBuilder::class,
44
        'ScalarDefinition'    => Definition\ScalarBuilder::class,
45
        'InputDefinition'     => Definition\InputBuilder::class,
46
        'DirectiveDefinition' => Definition\DirectiveBuilder::class,
47
        'InterfaceDefinition' => Definition\InterfaceBuilder::class,
48
        'UnionDefinition'     => Definition\UnionBuilder::class,
49
        // Invocations
50
        'Directive'           => Invocation\DirectiveBuilder::class,
51
    ];
52
53
    /**
54
     * @var string[]
55
     */
56
    private const UNSUPPORTED_BUILDERS = [
57
        'QueryOperation'        => 'Query expression',
58
        'MutationOperation'     => 'Mutation expression',
59
        'SubscriptionOperation' => 'Subscription expression',
60
        'FragmentDefinition'    => 'Fragment definition',
61
    ];
62
63
    /**
64
     * @var Process
65
     */
66
    private $process;
67
68
    /**
69
     * Backend constructor.
70
     * @param Process $process
71
     */
72
    public function __construct(Process $process)
73
    {
74
        $this->process = $process;
75
    }
76
77
    /**
78
     * @param Document $document
79
     * @return Context
80
     */
81
    public function context(Document $document): Context
82
    {
83
        return new Context($document->getFile(), $document);
84
    }
85
86
    /**
87
     * @param Context $context
88
     * @param RuleInterface $ast
89
     * @return Document
90
     * @throws TypeException
91
     */
92
    public function each(Context $context, RuleInterface $ast): Document
93
    {
94
        /** @var \Railt\Reflection\Document $document */
95
        $document = $context->getDocument();
96
97
        foreach ($ast->getChildren() as $child) {
98
            $definition = $this->exec($context, $child);
99
100
            $document->withDefinition($definition);
101
        }
102
103
        return $document;
104
    }
105
106
    /**
107
     * @param Context $context
108
     * @param RuleInterface $ast
109
     * @return DefinitionInterface
110
     * @throws TypeException
111
     */
112
    public function exec(Context $context, RuleInterface $ast): DefinitionInterface
113
    {
114
        if ($builder = self::BUILDERS[$ast->getName()] ?? null) {
115
            return $this->execBuilder(new $builder($context, $ast, $this->process));
116
        }
117
118
        if ($unsupported = self::UNSUPPORTED_BUILDERS[$ast->getName()] ?? null) {
119
            $exception = new TypeException(\sprintf(self::ERR_UNSUPPORTED_RULE, $unsupported));
120
            $exception->throwsIn($context->getFile(), $ast->getOffset());
121
122
            throw $exception;
123
        }
124
125
        $exception = new TypeException(\sprintf(self::ERR_UNRECOGNIZED_RULE, $ast->getName()));
126
        $exception->throwsIn($context->getFile(), $ast->getOffset());
127
128
        throw $exception;
129
    }
130
131
    /**
132
     * @param BuilderInterface $builder
133
     * @return DefinitionInterface
134
     */
135
    private function execBuilder(BuilderInterface $builder): DefinitionInterface
136
    {
137
        return $builder->build();
138
    }
139
}
140