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

DocumentASTBuilder::parseExecutableDefinition()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 8.2222
c 0
b 0
f 0
cc 7
eloc 11
nc 7
nop 1
1
<?php
2
3
namespace Digia\GraphQL\Language\ASTBuilder;
4
5
use Digia\GraphQL\Error\SyntaxErrorException;
6
use Digia\GraphQL\Language\KeywordEnum;
7
use Digia\GraphQL\Language\LexerInterface;
8
use Digia\GraphQL\Language\Node\NodeKindEnum;
9
use Digia\GraphQL\Language\TokenKindEnum;
10
11
class DocumentASTBuilder extends AbstractASTBuilder
12
{
13
    /**
14
     * @param LexerInterface $lexer
15
     * @return bool
16
     */
17
    public function supportsBuilder(string $kind): bool
18
    {
19
        return $kind === ASTKindEnum::DOCUMENT;
20
    }
21
22
    /**
23
     * @inheritdoc
24
     * @throws SyntaxErrorException
25
     */
26
    public function build(LexerInterface $lexer, array $params): ?array
27
    {
28
        $start = $lexer->getToken();
29
30
        $this->expect($lexer, TokenKindEnum::SOF);
31
32
        $definitions = [];
33
34
        do {
35
            $definitions[] = $this->parseDefinition($lexer);
36
        } while (!$this->skip($lexer, TokenKindEnum::EOF));
37
38
        return [
39
            'kind'        => NodeKindEnum::DOCUMENT,
40
            'definitions' => $definitions,
41
            'loc'         => $this->buildLocation($lexer, $start),
42
        ];
43
    }
44
45
    /**
46
     * @param LexerInterface $lexer
47
     * @return array
48
     * @throws SyntaxErrorException
49
     * @throws \ReflectionException
50
     */
51
    protected function parseDefinition(LexerInterface $lexer): array
52
    {
53
        if ($this->peek($lexer, TokenKindEnum::NAME)) {
54
            switch ($lexer->getTokenValue()) {
55
                case KeywordEnum::QUERY:
56
                case KeywordEnum::MUTATION:
57
                case KeywordEnum::SUBSCRIPTION:
58
                case KeywordEnum::FRAGMENT:
59
                    return $this->parseExecutableDefinition($lexer);
60
                case KeywordEnum::SCHEMA:
61
                case KeywordEnum::SCALAR:
62
                case KeywordEnum::TYPE:
63
                case KeywordEnum::INTERFACE:
64
                case KeywordEnum::UNION:
65
                case KeywordEnum::ENUM:
66
                case KeywordEnum::INPUT:
67
                case KeywordEnum::EXTEND:
68
                case KeywordEnum::DIRECTIVE:
69
                    // Note: The schema definition language is an experimental addition.
70
                    return $this->parseTypeSystemDefinition($lexer);
71
            }
72
        } elseif ($this->peek($lexer, TokenKindEnum::BRACE_L)) {
73
            return $this->parseExecutableDefinition($lexer);
74
        } elseif ($this->peekDescription($lexer)) {
75
            // Note: The schema definition language is an experimental addition.
76
            return $this->parseTypeSystemDefinition($lexer);
77
        }
78
79
        throw $this->unexpected($lexer);
80
    }
81
82
    /**
83
     * @param LexerInterface $lexer
84
     * @return array
85
     * @throws SyntaxErrorException
86
     */
87
    protected function parseExecutableDefinition(LexerInterface $lexer): array
88
    {
89
        if ($this->peek($lexer, TokenKindEnum::NAME)) {
90
            // valid names are: query, mutation, subscription and fragment
91
            switch ($lexer->getToken()->getValue()) {
92
                case KeywordEnum::QUERY:
93
                case KeywordEnum::MUTATION:
94
                case KeywordEnum::SUBSCRIPTION:
95
                    return $this->buildAST(ASTKindEnum::OPERATION_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...ION_DEFINITION, $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...
96
                case KeywordEnum::FRAGMENT:
97
                    return $this->buildAST(ASTKindEnum::FRAGMENT_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...ENT_DEFINITION, $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...
98
            }
99
        } elseif ($this->peek($lexer, TokenKindEnum::BRACE_L)) {
100
            // Anonymous query
101
            return $this->buildAST(ASTKindEnum::OPERATION_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...ION_DEFINITION, $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...
102
        }
103
104
        throw $this->unexpected($lexer);
105
    }
106
107
    /**
108
     * @param LexerInterface $lexer
109
     * @return array
110
     * @throws SyntaxErrorException
111
     */
112
    protected function parseTypeSystemDefinition(LexerInterface $lexer): array
113
    {
114
        // Many definitions begin with a description and require a lookahead.
115
        $keywordToken = $this->peekDescription($lexer) ? $lexer->lookahead() : $lexer->getToken();
116
117
        if ($keywordToken->getKind() === TokenKindEnum::NAME) {
118
            switch ($keywordToken->getValue()) {
119
                case KeywordEnum::SCHEMA:
120
                    return $this->buildAST(ASTKindEnum::SCHEMA_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...EMA_DEFINITION, $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...
121
                case KeywordEnum::SCALAR:
122
                    return $this->buildAST(ASTKindEnum::SCALAR_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
123
                case KeywordEnum::TYPE:
124
                    return $this->buildAST(ASTKindEnum::OBJECT_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
125
                case KeywordEnum::INTERFACE:
126
                    return $this->buildAST(ASTKindEnum::INTERFACE_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
127
                case KeywordEnum::UNION:
128
                    return $this->buildAST(ASTKindEnum::UNION_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
129
                case KeywordEnum::ENUM:
130
                    return $this->buildAST(ASTKindEnum::ENUM_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
131
                case KeywordEnum::INPUT:
132
                    return $this->buildAST(ASTKindEnum::INPUT_OBJECT_TYPE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...YPE_DEFINITION, $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...
133
                case KeywordEnum::DIRECTIVE:
134
                    return $this->buildAST(ASTKindEnum::DIRECTIVE_DEFINITION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...IVE_DEFINITION, $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...
135
                case KeywordEnum::EXTEND:
136
                    return $this->parseTypeSystemExtension($lexer);
137
            }
138
        }
139
140
        throw $this->unexpected($lexer, $keywordToken);
141
    }
142
143
    /**
144
     * @param LexerInterface $lexer
145
     * @return array
146
     * @throws SyntaxErrorException
147
     */
148
    protected function parseTypeSystemExtension(LexerInterface $lexer): array
149
    {
150
        $keywordToken = $lexer->lookahead();
151
152
        if ($keywordToken->getKind() === TokenKindEnum::NAME) {
153
            switch ($keywordToken->getValue()) {
154
                case KeywordEnum::SCALAR:
155
                    return $this->buildAST(ASTKindEnum::SCALAR_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
156
                case KeywordEnum::TYPE:
157
                    return $this->buildAST(ASTKindEnum::OBJECT_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
158
                case KeywordEnum::INTERFACE:
159
                    return $this->buildAST(ASTKindEnum::INTERFACE_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
160
                case KeywordEnum::UNION:
161
                    return $this->buildAST(ASTKindEnum::UNION_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
162
                case KeywordEnum::ENUM:
163
                    return $this->buildAST(ASTKindEnum::ENUM_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
164
                case KeywordEnum::INPUT:
165
                    return $this->buildAST(ASTKindEnum::INPUT_OBJECT_TYPE_EXTENSION, $lexer);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildAST(D...TYPE_EXTENSION, $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...
166
            }
167
        }
168
169
        throw $this->unexpected($lexer, $keywordToken);
170
    }
171
}
172