Completed
Push — master ( c1a156...8cadde )
by Kirill
08:14
created

Builder::run()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.1158

Importance

Changes 0
Metric Value
cc 5
nc 12
nop 3
dl 0
loc 25
ccs 10
cts 12
cp 0.8333
crap 5.1158
rs 9.2088
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\Compiler;
11
12
use Psr\Log\LoggerAwareInterface;
13
use Psr\Log\LoggerAwareTrait;
14
use Psr\Log\LoggerInterface;
15
use Railt\Io\Readable;
16
use Railt\Parser\Ast\RuleInterface;
17
use Railt\Reflection\Contracts\Definition as DefinitionInterface;
18
use Railt\Reflection\Contracts\Reflection;
19
use Railt\Reflection\Document;
20
use Railt\SDL\Ast\ProvidesDefinition;
21
use Railt\SDL\Compiler\Process\Emittable;
22
use Railt\SDL\Compiler\Process\Pipeline;
23
use Railt\SDL\Exception\CompilerException;
24
use Railt\SDL\Exception\InternalException;
25
26
/**
27
 * Class Factory
28
 */
29
class Builder implements LoggerAwareInterface
30
{
31
    use LoggerAwareTrait;
32
33
    /**
34
     * @var SystemManager
35
     */
36
    private $systems;
37
38
    /**
39
     * @var Pipeline
40
     */
41
    private $pipeline;
42
43
    /**
44
     * Process constructor.
45
     */
46 119
    public function __construct()
47
    {
48 119
        $this->pipeline = new Pipeline();
49 119
        $this->systems = new SystemManager($this, $this->pipeline);
50 119
    }
51
52
    /**
53
     * @param Reflection $root
54
     * @param Readable $file
55
     * @param RuleInterface $ast
56
     * @return Document
57
     */
58 119
    public function run(Reflection $root, Readable $file, RuleInterface $ast): Document
59
    {
60 119
        $document = new Document($root, $file);
0 ignored issues
show
Compatibility introduced by
$root of type object<Railt\Reflection\Contracts\Reflection> is not a sub-type of object<Railt\Reflection\Reflection>. It seems like you assume a concrete implementation of the interface Railt\Reflection\Contracts\Reflection to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
61
62 119
        if ($this->logger) {
63
            $this->logger->debug(\sprintf('Create document %s', $document));
64
        }
65
66 119
        $this->systems->resolve($document, $ast);
67
68
        /** @var Emittable $deferred */
69 119
        foreach ($this->pipeline as $deferred) {
70 119
            $handler = $deferred->emit();
71
72 119
            while ($handler->valid()) {
73 119
                $handler->next();
74
            }
75
        }
76
77 119
        if ($this->logger) {
78
            $this->logger->debug(\sprintf('Complete document %s', $document));
79
        }
80
81 119
        return $document;
82
    }
83
84
    /**
85
     * @param RuleInterface $rule
86
     * @param DefinitionInterface $parent
87
     * @return DefinitionInterface
88
     */
89 119
    public function build(RuleInterface $rule, DefinitionInterface $parent): DefinitionInterface
90
    {
91 119
        return $this->buildDefinition($rule, $parent);
92
    }
93
94
    /**
95
     * @param ProvidesDefinition|RuleInterface $rule
96
     * @param DefinitionInterface $parent
97
     * @return DefinitionInterface
98
     * @throws CompilerException
99
     */
100 119
    private function buildDefinition(RuleInterface $rule, DefinitionInterface $parent): DefinitionInterface
101
    {
102 119
        if (! $rule instanceof ProvidesDefinition) {
103
            $error = \vsprintf('%s AST should implement %s interface', [
104
                $rule->getName(), ProvidesDefinition::class]);
105
106
            throw new InternalException($error);
107
        }
108
109 119
        $definition = $rule->resolve($parent);
110
111 119
        if ($this->logger) {
112
            $this->logger->debug(\sprintf('Create type definition %s from %s', $definition, $parent));
113
        }
114
115 119
        $this->systems->resolve($definition, $rule);
116
117 119
        return $definition;
118
    }
119
120
    /**
121
     * Sets a logger instance on the object.
122
     * @param LoggerInterface $logger
123
     * @return void
124
     */
125
    public function setLogger(LoggerInterface $logger): void
126
    {
127
        $this->logger = $logger;
128
129
        $this->pipeline->setLogger($logger);
130
        $this->systems->setLogger($logger);
131
    }
132
}
133