Builder   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 2
dl 0
loc 103
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A bootReducers() 0 6 2
A buildClass() 0 10 3
A build() 0 13 4
A coroutine() 0 14 3
1
<?php
2
/**
3
 * This file is part of Properties 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 Serafim\Properties;
11
12
use Railt\Parser\Ast\RuleInterface;
13
use Serafim\Properties\Attribute\AttributeInterface;
14
use Serafim\Properties\Parser\Parser;
15
use Serafim\Properties\Reducers;
16
use Serafim\Properties\Reducers\ReducerInterface;
17
18
/**
19
 * Class Builder
20
 */
21
class Builder
22
{
23
    /**
24
     * @var string[]
25
     */
26
    private const DEFAULT_REDUCERS = [
27
        Reducers\DocBlockReducer::class,
28
        Reducers\DocTitleReducer::class,
29
        Reducers\VariableReducer::class,
30
        Reducers\TypeHintReducer::class,
31
        Reducers\TypeNameReducer::class,
32
        Reducers\TypeHint\ScalarReducer::class,
33
        Reducers\TypeHint\ArrayReducer::class,
34
        Reducers\TypeHint\GenericReducer::class,
35
        Reducers\TypeHint\DisjunctionReducer::class,
36
        Reducers\TypeHint\ConjunctionReducer::class,
37
    ];
38
39
    /**
40
     * @var Parser
41
     */
42
    private $parser;
43
44
    /**
45
     * @var array|ReducerInterface[]
46
     */
47
    private $reducers = [];
48
49
    /**
50
     * Builder constructor.
51
     */
52
    public function __construct()
53
    {
54
        $this->parser = new Parser();
55
56
        $this->bootReducers();
57
    }
58
59
    /**
60
     * @return void
61
     */
62
    private function bootReducers(): void
63
    {
64
        foreach (self::DEFAULT_REDUCERS as $reducer) {
65
            $this->reducers[] = new $reducer;
66
        }
67
    }
68
69
    /**
70
     * @param string $class
71
     * @return iterable|AttributeInterface[]
72
     * @throws \RuntimeException
73
     */
74
    public function buildClass(string $class): iterable
75
    {
76
        $ast = $this->parser->parseClassDocComment($class);
77
78
        if ($ast instanceof RuleInterface) {
79
            foreach ($ast->getChildren() as $child) {
80
                yield $this->build($child);
81
            }
82
        }
83
    }
84
85
    /**
86
     * @param RuleInterface $rule
87
     * @return mixed
88
     * @throws \RuntimeException
89
     */
90
    private function build(RuleInterface $rule)
91
    {
92
        foreach ($this->reducers as $reducer) {
93
            if ($reducer->match($rule)) {
94
                $result = $reducer->reduce($rule);
95
96
                return $result instanceof \Generator ? $this->coroutine($result) : $result;
97
            }
98
        }
99
100
        $error = \sprintf('Unrecognized rule %s', $rule->getName());
101
        throw new \RuntimeException($error);
102
    }
103
104
    /**
105
     * @param \Generator $coroutine
106
     * @return mixed
107
     * @throws \RuntimeException
108
     */
109
    private function coroutine(\Generator $coroutine)
110
    {
111
        while ($coroutine->valid()) {
112
            $value = $coroutine->current();
113
114
            if ($value instanceof RuleInterface) {
115
                $value = $this->build($value);
116
            }
117
118
            $coroutine->send($value);
119
        }
120
121
        return $coroutine->getReturn();
122
    }
123
}
124