Passed
Pull Request — master (#315)
by Théo
06:13 queued 01:44
created

AnnotationDumper   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 81
dl 0
loc 174
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A transformNodesToString() 0 7 1
A dump() 0 15 2
D transformNodeToString() 0 124 20
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\Annotation;
16
17
use Assert\Assertion;
18
use Hoa\Compiler\Llk\TreeNode;
19
use function array_filter;
20
use function array_map;
21
use function array_shift;
22
use function array_values;
23
use function implode;
24
use function in_array;
25
use function sprintf;
26
use function strtolower;
27
28
/**
29
 * @private
30
 */
31
final class AnnotationDumper
32
{
33
    /**
34
     * Dumps the list of annotations from the given tree.
35
     *
36
     * @param string[] $ignored List of annotations to ignore
37
     *
38
     * @throws InvalidToken
39
     *
40
     * @return string[]
41
     */
42
    public function dump(TreeNode $node, array $ignored): array
43
    {
44
        Assertion::allString($ignored);
45
46
        $ignored = array_map('strtolower', $ignored);
47
48
        if ('#annotations' !== $node->getId()) {
49
            return [];
50
        }
51
52
        return array_values(
53
            array_filter(
54
                $this->transformNodesToString(
55
                    $node->getChildren(),
56
                    $ignored
57
                )
58
            )
59
        );
60
    }
61
62
    /**
63
     * @param TreeNode $nodes
64
     * @param string[] $ignored
65
     *
66
     * @return (string|null)[]
67
     */
68
    private function transformNodesToString(array $nodes, array $ignored): array
69
    {
70
        return array_map(
71
            function (TreeNode $node) use ($ignored): ?string {
72
                return $this->transformNodeToString($node, $ignored);
73
            },
74
            $nodes
75
        );
76
    }
77
78
    /**
79
     * @param string[] $ignored
80
     */
81
    private function transformNodeToString(TreeNode $node, array $ignored): ?string
82
    {
83
        if ('token' === $node->getId()) {
84
            if (in_array($node->getValueToken(), ['identifier', 'simple_identifier', 'integer', 'float', 'boolean', 'identifier_ns'], true)) {
85
                return $node->getValueValue();
86
            }
87
88
            if ('string' === $node->getValueToken()) {
89
                return sprintf('"%s"', $node->getValueValue());
90
            }
91
92
            if ('valued_identifier' === $node->getValueToken()) {
93
                return sprintf('%s()', $node->getValueValue());
94
            }
95
96
            throw InvalidToken::createForUnknownType($node);
97
        }
98
99
        if ('#parameters' === $node->getId()) {
100
            $transformedChildren = $this->transformNodesToString(
101
                $node->getChildren(),
102
                $ignored
103
            );
104
105
            return implode(',', $transformedChildren);
106
        }
107
108
        if ('#named_parameter' === $node->getId() || '#pair' === $node->getId()) {
109
            Assertion::same($node->getChildrenNumber(), 2);
110
111
            $name = $node->getChild(0);
112
            $parameter = $node->getChild(1);
113
114
            return sprintf(
115
                '%s=%s',
116
                $this->transformNodeToString($name, $ignored),
117
                $this->transformNodeToString($parameter, $ignored)
118
            );
119
        }
120
121
        if ('#value' === $node->getId()) {
122
            Assertion::same($node->getChildrenNumber(), 1);
123
124
            return $this->transformNodeToString($node->getChild(0), $ignored);
125
        }
126
127
        if ('#string' === $node->getId()) {
128
            Assertion::lessOrEqualThan($node->getChildrenNumber(), 1);
129
130
            return 1 === $node->getChildrenNumber() ? $this->transformNodeToString($node->getChild(0), $ignored) : '""';
131
        }
132
133
        if ('#list' === $node->getId() || '#map' === $node->getId()) {
134
            $transformedChildren = $this->transformNodesToString(
135
                $node->getChildren(),
136
                $ignored
137
            );
138
139
            return sprintf(
140
                '{%s}',
141
                implode(
142
                    ',',
143
                    $transformedChildren
144
                )
145
            );
146
        }
147
148
        if ('#annotation' === $node->getId()) {
149
            Assertion::greaterOrEqualThan($node->getChildrenNumber(), 1);
150
151
            $children = $node->getChildren();
152
153
            /** @var TreeNode $token */
154
            $token = array_shift($children);
155
            $parameters = array_values($children);
156
157
            if ('simple_identifier' === $token->getValueToken()) {
158
                Assertion::count($parameters, 0);
159
160
                $tokenValue = $token->getValueValue();
161
162
                return in_array(strtolower($tokenValue), $ignored, true) ? null : '@'.$tokenValue;
163
            }
164
165
            if ('valued_identifier' === $token->getValueToken()) {
166
                $transformedChildren = $this->transformNodesToString(
167
                    $parameters,
168
                    $ignored
169
                );
170
171
                return sprintf(
172
                    '@%s(%s)',
173
                    $token->getValueValue(),
174
                    implode(
175
                        '',
176
                        $transformedChildren
177
                    )
178
                );
179
            }
180
        }
181
182
        if ('#unnamed_parameter' === $node->getId()) {
183
            Assertion::same($node->getChildrenNumber(), 1);
184
185
            return $this->transformNodeToString($node->getChild(0), $ignored);
186
        }
187
188
        if ('#reference' === $node->getId()) {
189
            Assertion::same($node->getChildrenNumber(), 1);
190
191
            return $this->transformNodeToString($node->getChild(0), $ignored);
192
        }
193
194
        if ('#constant' === $node->getId()) {
195
            Assertion::same($node->getChildrenNumber(), 2);
196
197
            return sprintf(
198
                '%s::%s',
199
                $this->transformNodeToString($node->getChild(0), $ignored),
200
                $this->transformNodeToString($node->getChild(1), $ignored)
201
            );
202
        }
203
204
        $x = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $x is dead and can be removed.
Loading history...
205
    }
206
}
207