Test Setup Failed
Push — master ( 1595cb...050b68 )
by Kirill
21:00
created

Specification::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of Railt package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Railt\SDL\Spec;
13
14
use Phplrt\Contracts\Ast\NodeInterface;
15
use Phplrt\Contracts\Source\FileInterface;
16
use Phplrt\Source\Exception\NotFoundException;
17
use Phplrt\Source\Exception\NotReadableException;
18
use Phplrt\Source\File;
19
use Phplrt\Visitor\Traverser;
20
use Phplrt\Visitor\TraverserInterface;
21
use Phplrt\Visitor\Visitor;
22
use Railt\SDL\CompilerInterface;
23
use Railt\SDL\Spec\Constraint\Constraint;
24
use Railt\SDL\Spec\Constraint\GenericTypes;
25
use Railt\SDL\Spec\Constraint\RepeatableDirectives;
26
use Railt\SDL\Spec\Constraint\TypeSystemExtensions;
27
use Railt\SDL\Spec\Constraint\Variables;
28
29
/**
30
 * Class Specification
31
 */
32
abstract class Specification extends Visitor implements SpecificationInterface
33
{
34
    /**
35
     * @var string[]|Constraint[]
36
     */
37
    protected const STANDARD_CONSTRAINTS = [
38
        RepeatableDirectives::class,
39
        TypeSystemExtensions::class,
40
        GenericTypes::class,
41
        Variables::class,
42
    ];
43
44
    /**
45
     * @var string
46
     */
47
    private const RESOURCES_PATHNAME = __DIR__ . '/../../resources/stdlib/%s.graphql';
48
49
    /**
50
     * List of language version constraints.
51
     * That is, additional restrictions which should be added to
52
     * standard constraints.
53
     *
54
     * @var array|Constraint[]
55
     */
56
    protected array $constraints = [];
57
58
    /**
59
     * List of the language abilities.
60
     * That is, features that are excluded from
61
     * standard constraints.
62
     *
63
     * @var array|Constraint[]
64
     */
65
    protected array $abilities = [];
66
67
    /**
68
     * List of the language types.
69
     *
70
     * @var array|string[]
71
     */
72
    protected array $types = [];
73
74
    /**
75
     * @var Traverser|TraverserInterface
76
     */
77
    private TraverserInterface $traverser;
78
79
    /**
80
     * Specification constructor.
81
     */
82
    public function __construct()
83
    {
84
        $this->bootConstraints();
85
86
        $this->traverser = new Traverser([$this]);
87
    }
88
89
    /**
90
     * @return void
91
     */
92
    private function bootConstraints(): void
93
    {
94
        foreach (static::STANDARD_CONSTRAINTS as $constraint) {
95
            if (! \in_array($constraint, $this->abilities, true)) {
96
                $this->constraints[] = $constraint;
97
            }
98
        }
99
100
        $this->constraints = \array_unique($this->constraints);
101
    }
102
103
    /**
104
     * @param iterable $ast
105
     * @return iterable
106
     */
107
    public function execute(iterable $ast): iterable
108
    {
109
        return $this->traverser->traverse($ast);
110
    }
111
112
    /**
113
     * @param CompilerInterface $compiler
114
     * @return void
115
     * @throws NotFoundException
116
     * @throws NotReadableException
117
     */
118
    public function load(CompilerInterface $compiler): void
119
    {
120
        $this->includeMany($compiler, $this->types);
121
    }
122
123
    /**
124
     * @param CompilerInterface $compiler
125
     * @param array $names
126
     * @return void
127
     * @throws NotFoundException
128
     * @throws NotReadableException
129
     */
130
    protected function includeMany(CompilerInterface $compiler, array $names): void
131
    {
132
        foreach ($names as $name) {
133
            $this->include($compiler, $name);
134
        }
135
    }
136
137
    /**
138
     * @param CompilerInterface $compiler
139
     * @param string $name
140
     * @return void
141
     * @throws NotFoundException
142
     * @throws NotReadableException
143
     */
144
    protected function include(CompilerInterface $compiler, string $name): void
145
    {
146
        $compiler->preload($this->fromResources($name));
147
    }
148
149
    /**
150
     * @param string $name
151
     * @return FileInterface
152
     * @throws NotFoundException
153
     * @throws NotReadableException
154
     */
155
    protected function fromResources(string $name): FileInterface
156
    {
157
        return File::fromPathname(\sprintf(self::RESOURCES_PATHNAME, $name));
158
    }
159
160
    /**
161
     * @param NodeInterface $node
162
     * @return void
163
     */
164
    public function enter(NodeInterface $node): void
165
    {
166
        foreach ($this->constraints as $constraint) {
167
            $constraint::assert($node, $this);
168
        }
169
    }
170
}
171