Completed
Pull Request — master (#315)
by Théo
03:03
created

AnnotationDumper::transformNodeToString()   D

Complexity

Conditions 20
Paths 20

Size

Total Lines 116
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 116
rs 4.1666
c 0
b 0
f 0
cc 20
nc 20
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        switch ($node->getId()) {
84
            case '#annotation':
85
                Assertion::greaterOrEqualThan($node->getChildrenNumber(), 1);
86
87
                $children = $node->getChildren();
88
89
                /** @var TreeNode $token */
90
                $token = array_shift($children);
91
                $parameters = array_values($children);
92
93
                if ('simple_identifier' === $token->getValueToken()) {
94
                    Assertion::count($parameters, 0);
95
96
                    $tokenValue = $token->getValueValue();
97
98
                    return in_array(strtolower($tokenValue), $ignored, true) ? null : '@'.$tokenValue;
99
                }
100
101
                if ('valued_identifier' === $token->getValueToken()) {
102
                    $transformedChildren = $this->transformNodesToString(
103
                        $parameters,
104
                        $ignored
105
                    );
106
107
                    return sprintf(
108
                        '@%s(%s)',
109
                        $token->getValueValue(),
110
                        implode(
111
                            '',
112
                            $transformedChildren
113
                        )
114
                    );
115
                }
116
117
                throw InvalidToken::createForUnknownType($token);
118
119
            case 'token':
120
                if (in_array($node->getValueToken(), ['identifier', 'simple_identifier', 'integer', 'float', 'boolean', 'identifier_ns'], true)) {
121
                    return $node->getValueValue();
122
                }
123
124
                if ('string' === $node->getValueToken()) {
125
                    return sprintf('"%s"', $node->getValueValue());
126
                }
127
128
                if ('valued_identifier' === $node->getValueToken()) {
129
                    return sprintf('%s()', $node->getValueValue());
130
                }
131
132
                throw InvalidToken::createForUnknownType($node);
133
134
            case '#parameters':
135
                $transformedChildren = $this->transformNodesToString(
136
                    $node->getChildren(),
137
                    $ignored
138
                );
139
140
                return implode(',', $transformedChildren);
141
142
            case '#named_parameter':
143
            case '#pair':
144
                Assertion::same($node->getChildrenNumber(), 2);
145
146
                $name = $node->getChild(0);
147
                $parameter = $node->getChild(1);
148
149
                return sprintf(
150
                    '%s=%s',
151
                    $this->transformNodeToString($name, $ignored),
152
                    $this->transformNodeToString($parameter, $ignored)
153
                );
154
155
            case '#value':
156
                Assertion::same($node->getChildrenNumber(), 1);
157
158
                return $this->transformNodeToString($node->getChild(0), $ignored);
159
160
            case '#string':
161
                Assertion::lessOrEqualThan($node->getChildrenNumber(), 1);
162
163
                return 1 === $node->getChildrenNumber() ? $this->transformNodeToString($node->getChild(0), $ignored) : '""';
164
165
            case '#list':
166
            case '#map':
167
                $transformedChildren = $this->transformNodesToString(
168
                    $node->getChildren(),
169
                    $ignored
170
                );
171
172
                return sprintf(
173
                    '{%s}',
174
                    implode(
175
                        ',',
176
                        $transformedChildren
177
                    )
178
                );
179
180
            case '#unnamed_parameter':
181
            case '#reference':
182
                Assertion::same($node->getChildrenNumber(), 1);
183
184
                return $this->transformNodeToString($node->getChild(0), $ignored);
185
186
            case '#constant':
187
                Assertion::same($node->getChildrenNumber(), 2);
188
189
                return sprintf(
190
                    '%s::%s',
191
                    $this->transformNodeToString($node->getChild(0), $ignored),
192
                    $this->transformNodeToString($node->getChild(1), $ignored)
193
                );
194
        }
195
196
        throw InvalidToken::createForUnknownId($node);
197
    }
198
}
199