Passed
Push — master ( c47e08...96e565 )
by Quang
02:51
created

ValueLiteralASTBuilder::parseValueLiteral()   C

Complexity

Conditions 13
Paths 12

Size

Total Lines 65
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 65
rs 5.9671
c 0
b 0
f 0
cc 13
eloc 44
nc 12
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
namespace Digia\GraphQL\Language\ASTBuilder;
4
5
6
use Digia\GraphQL\Error\SyntaxErrorException;
7
use Digia\GraphQL\Language\LexerInterface;
8
use Digia\GraphQL\Language\Node\NodeKindEnum;
9
use Digia\GraphQL\Language\TokenKindEnum;
10
11
class ValueLiteralASTBuilder extends AbstractASTBuilder
12
{
13
    /**
14
     * @inheritdoc
15
     */
16
    public function supportsBuilder(string $kind): bool
17
    {
18
        return $kind === ASTKindEnum::VALUE_LITERAL;
19
    }
20
21
    /**
22
     * @inheritdoc
23
     */
24
    public function build(LexerInterface $lexer, array $params): ?array
25
    {
26
        return $this->parseValueLiteral($lexer, $params['isConst'] ?? false);
27
    }
28
29
    /**
30
     * @param LexerInterface $lexer
31
     * @param bool           $isConst
32
     * @return array
33
     * @throws SyntaxErrorException
34
     */
35
    protected function parseValueLiteral(LexerInterface $lexer, bool $isConst): array
36
    {
37
        $token = $lexer->getToken();
38
39
        switch ($token->getKind()) {
40
            case TokenKindEnum::BRACKET_L:
41
                return $this->parseList($lexer, $isConst);
42
            case TokenKindEnum::BRACE_L:
43
                return $this->parseObject($lexer, $isConst);
44
            case TokenKindEnum::INT:
45
                $lexer->advance();
46
47
                return [
48
                    'kind'  => NodeKindEnum::INT,
49
                    'value' => $token->getValue(),
50
                    'loc'   => $this->buildLocation($lexer, $token),
51
                ];
52
            case TokenKindEnum::FLOAT:
53
                $lexer->advance();
54
55
                return [
56
                    'kind'  => NodeKindEnum::FLOAT,
57
                    'value' => $token->getValue(),
58
                    'loc'   => $this->buildLocation($lexer, $token),
59
                ];
60
            case TokenKindEnum::STRING:
61
            case TokenKindEnum::BLOCK_STRING:
62
                return $this->buildAST(ASTKindEnum::STRING_LITERAL, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...STRING_LITERAL, $lexer) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
63
            case TokenKindEnum::NAME:
64
                $value = $token->getValue();
65
66
                if ($value === 'true' || $value === 'false') {
67
                    $lexer->advance();
68
69
                    return [
70
                        'kind'  => NodeKindEnum::BOOLEAN,
71
                        'value' => $value === 'true',
72
                        'loc'   => $this->buildLocation($lexer, $token),
73
                    ];
74
                }
75
76
                if ($value === 'null') {
77
                    $lexer->advance();
78
79
                    return [
80
                        'kind' => NodeKindEnum::NULL,
81
                        'loc'  => $this->buildLocation($lexer, $token),
82
                    ];
83
                }
84
85
                $lexer->advance();
86
87
                return [
88
                    'kind'  => NodeKindEnum::ENUM,
89
                    'value' => $token->getValue(),
90
                    'loc'   => $this->buildLocation($lexer, $token),
91
                ];
92
            case TokenKindEnum::DOLLAR:
93
                if (!$isConst) {
94
                    return $this->buildAST(ASTKindEnum::VARIABLE, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...Enum::VARIABLE, $lexer) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
95
                }
96
                break;
97
        }
98
99
        throw $this->unexpected($lexer);
100
    }
101
102
    /**
103
     * @param LexerInterface $lexer
104
     * @return array
105
     * @throws SyntaxErrorException
106
     */
107
    protected function parseConstValue(LexerInterface $lexer): array
108
    {
109
        return $this->parseValueLiteral($lexer, true);
110
    }
111
112
    /**
113
     * @param LexerInterface $lexer
114
     * @return array
115
     * @throws SyntaxErrorException
116
     */
117
    protected function parseValue(LexerInterface $lexer): array
118
    {
119
        return $this->parseValueLiteral($lexer, false);
120
    }
121
122
    /**
123
     * @param LexerInterface $lexer
124
     * @param bool           $isConst
125
     * @return array
126
     * @throws SyntaxErrorException
127
     */
128
    protected function parseList(LexerInterface $lexer, bool $isConst): array
129
    {
130
        $start = $lexer->getToken();
131
132
        return [
133
            'kind'   => NodeKindEnum::LIST,
134
            'values' => $this->any(
135
                $lexer,
136
                TokenKindEnum::BRACKET_L,
137
                [$this, $isConst ? 'parseConstValue' : 'parseValue'],
138
                TokenKindEnum::BRACKET_R
139
            ),
140
            'loc'    => $this->buildLocation($lexer, $start),
141
        ];
142
    }
143
144
    /**
145
     * @param LexerInterface $lexer
146
     * @param bool           $isConst
147
     * @return array
148
     * @throws SyntaxErrorException
149
     */
150
    protected function parseObject(LexerInterface $lexer, bool $isConst): array
151
    {
152
        $start = $lexer->getToken();
153
154
        $this->expect($lexer, TokenKindEnum::BRACE_L);
155
156
        $fields = [];
157
158
        while (!$this->skip($lexer, TokenKindEnum::BRACE_R)) {
159
            $fields[] = $this->parseObjectField($lexer, $isConst);
160
        }
161
162
        return [
163
            'kind'   => NodeKindEnum::OBJECT,
164
            'fields' => $fields,
165
            'loc'    => $this->buildLocation($lexer, $start),
166
        ];
167
    }
168
169
    /**
170
     * @param LexerInterface $lexer
171
     * @param bool           $isConst
172
     * @return array
173
     * @throws SyntaxErrorException
174
     */
175
    protected function parseObjectField(LexerInterface $lexer, bool $isConst): array
176
    {
177
        $start = $lexer->getToken();
178
179
        $parseValue = function (LexerInterface $lexer, bool $isConst) {
180
            $this->expect($lexer, TokenKindEnum::COLON);
181
182
            return $this->parseValueLiteral($lexer, $isConst);
183
        };
184
185
        return [
186
            'kind'  => NodeKindEnum::OBJECT_FIELD,
187
            'name'  => $this->buildAST(ASTKindEnum::NAME, $lexer),
188
            'value' => $parseValue($lexer, $isConst),
189
            'loc'   => $this->buildLocation($lexer, $start),
190
        ];
191
    }
192
}
193