Test Failed
Push — master ( e3b5b4...43c430 )
by Kirill
04:55
created

Builder::bootDefaults()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 5
rs 10
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;
11
12
use Railt\Io\Readable;
13
use Railt\Parser\Ast\NodeInterface;
14
use Railt\Parser\Ast\RuleInterface;
15
use Railt\SDL\Exception\InternalException;
16
use Railt\SDL\Frontend\Builder\BuilderInterface;
17
use Railt\SDL\Frontend\Interceptor\InterceptorInterface;
18
use Railt\SDL\Frontend\Interceptor\RuleInterceptor;
19
20
/**
21
 * Class Builder
22
 */
23
class Builder
24
{
25
    /**
26
     * @var string[]|BuilderInterface[]
27
     */
28
    private const DEFAULT_BUILDER_DEFINITIONS = [
29
30
    ];
31
32
    /**
33
     * string[]|InterceptorInterface[]
34
     */
35
    private const DEFAULT_INTERCEPTORS = [
36
        RuleInterceptor::class,
37
    ];
38
39
    /**
40
     * @var array|BuilderInterface[]
41
     */
42
    private $builders = [];
43
44
    /**
45
     * @var SymbolTable
46
     */
47
    private $table;
48
49
    /**
50
     * @var array|InterceptorInterface[]
51
     */
52
    private $interceptors = [];
53
54
    /**
55
     * Builder constructor.
56
     */
57
    public function __construct()
58
    {
59
        $this->table = new SymbolTable();
60
        $this->bootDefaults();
61
    }
62
63
    /**
64
     * @return void
65
     */
66
    private function bootDefaults(): void
67
    {
68
        $this->bootDefaultBuilders();
69
        $this->bootDefaultInterceptors();
70
    }
71
72
    /**
73
     * @return void
74
     */
75
    private function bootDefaultBuilders(): void
76
    {
77
        foreach (self::DEFAULT_BUILDER_DEFINITIONS as $rule => $builder) {
78
            $this->builders[$rule] = new $builder($this, $this->table);
79
        }
80
    }
81
82
    /**
83
     * @return void
84
     */
85
    private function bootDefaultInterceptors(): void
86
    {
87
        foreach (self::DEFAULT_INTERCEPTORS as $interceptor) {
88
            $this->interceptors[] = new $interceptor($this, $this->table);
89
        }
90
    }
91
92
    /**
93
     * @param Readable $file
94
     * @param RuleInterface $ast
95
     * @return ValueObject
96
     * @throws \Railt\Io\Exception\ExternalFileException
97
     */
98
    public function build(Readable $file, RuleInterface $ast): ValueObject
99
    {
100
        $document = new ValueObject();
101
        $document->definitions = [];
0 ignored issues
show
Documentation introduced by
The property definitions does not exist on object<Railt\SDL\Frontend\ValueObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
102
103
        foreach ($ast->getChildren() as $child) {
104
            $document->definitions[] = $this->reduce($file, $child);
0 ignored issues
show
Documentation introduced by
The property definitions does not exist on object<Railt\SDL\Frontend\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
105
        }
106
107
        return $document;
108
    }
109
110
    /**
111
     * @param Readable $file
112
     * @param RuleInterface $ast
113
     * @return mixed
114
     * @throws \Railt\Io\Exception\ExternalFileException
115
     */
116
    public function reduce(Readable $file, RuleInterface $ast)
117
    {
118
        $process = $this->get($file, $ast)->reduce($ast);
119
120
        if ($process instanceof \Generator) {
121
            return $this->run($file, $process);
122
        }
123
124
        return $process;
125
    }
126
127
    /**
128
     * @param Readable $file
129
     * @param \Generator $process
130
     * @return mixed
131
     */
132
    private function run(Readable $file, \Generator $process)
133
    {
134
        while ($process->valid()) {
135
            $value = $process->current();
136
137
            foreach ($this->interceptors as $interceptor) {
138
                if ($interceptor->match($value)) {
139
                    $value = $interceptor->apply($file, $value);
140
                    break;
141
                }
142
            }
143
144
            $process->send($value);
145
        }
146
147
        return $process->getReturn();
148
    }
149
150
    /**
151
     * @param Readable $file
152
     * @param RuleInterface $ast
153
     * @return BuilderInterface
154
     * @throws \Railt\Io\Exception\ExternalFileException
155
     */
156
    private function get(Readable $file, RuleInterface $ast): BuilderInterface
157
    {
158
        $builder = $this->builders[$ast->getName()] ?? null;
159
160
        if ($builder === null) {
161
            $error = 'Unrecognized AST rule %s';
162
            throw (new InternalException(\sprintf($error, $ast->getName())))->throwsIn($file, $ast->getOffset());
163
        }
164
165
        return $builder;
166
    }
167
}
168