Completed
Push — master ( 578d3a...04a929 )
by Maurício
34s queued 14s
created

IndexHints::parse()   D

Complexity

Conditions 24
Paths 6

Size

Total Lines 109
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 24

Importance

Changes 0
Metric Value
cc 24
eloc 60
nc 6
nop 3
dl 0
loc 109
ccs 54
cts 54
cp 1
crap 24
rs 4.1666
c 0
b 0
f 0

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
namespace PhpMyAdmin\SqlParser\Components\Parsers;
6
7
use PhpMyAdmin\SqlParser\Components\IndexHint;
8
use PhpMyAdmin\SqlParser\Parseable;
9
use PhpMyAdmin\SqlParser\Parser;
10
use PhpMyAdmin\SqlParser\TokensList;
11
use PhpMyAdmin\SqlParser\TokenType;
12
13
use function implode;
14
15
/**
16
 * Parses an Index hint.
17
 */
18
final class IndexHints implements Parseable
19
{
20
    /**
21
     * @param Parser               $parser  the parser that serves as context
22
     * @param TokensList           $list    the list of tokens that are being parsed
23
     * @param array<string, mixed> $options parameters for parsing
24
     *
25
     * @return IndexHint[]
26
     */
27 14
    public static function parse(Parser $parser, TokensList $list, array $options = []): array
28
    {
29 14
        $ret = [];
30 14
        $expr = new IndexHint();
31 14
        $expr->type = $options['type'] ?? null;
32
        /**
33
         * The state of the parser.
34
         *
35
         * Below are the states of the parser.
36
         *      0 ----------------- [ USE/IGNORE/FORCE ]-----------------> 1
37
         *      1 -------------------- [ INDEX/KEY ] --------------------> 2
38
         *      2 ----------------------- [ FOR ] -----------------------> 3
39
         *      2 -------------------- [ expr_list ] --------------------> 0
40
         *      3 -------------- [ JOIN/GROUP BY/ORDER BY ] -------------> 4
41
         *      4 -------------------- [ expr_list ] --------------------> 0
42
         */
43 14
        $state = 0;
44
45
        // By design, the parser will parse first token after the keyword. So, the keyword
46
        // must be analyzed too, in order to determine the type of this index hint.
47 14
        if ($list->idx > 0) {
48 14
            --$list->idx;
49
        }
50
51 14
        for (; $list->idx < $list->count; ++$list->idx) {
52
            /**
53
             * Token parsed at this moment.
54
             */
55 14
            $token = $list->tokens[$list->idx];
56
57
            // End of statement.
58 14
            if ($token->type === TokenType::Delimiter) {
59 8
                break;
60
            }
61
62
            // Skipping whitespaces and comments.
63 14
            if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
64 14
                continue;
65
            }
66
67
            switch ($state) {
68 14
                case 0:
69 14
                    if ($token->type === TokenType::Keyword) {
70 14
                        if ($token->keyword !== 'USE' && $token->keyword !== 'IGNORE' && $token->keyword !== 'FORCE') {
71 6
                            break 2;
72
                        }
73
74 14
                        $expr->type = $token->keyword;
75 14
                        $state = 1;
76
                    }
77
78 14
                    break;
79 14
                case 1:
80 14
                    if ($token->type === TokenType::Keyword) {
81 12
                        if ($token->keyword === 'INDEX' || $token->keyword === 'KEY') {
82 10
                            $expr->indexOrKey = $token->keyword;
83
                        } else {
84 2
                            $parser->error('Unexpected keyword.', $token);
85
                        }
86
87 12
                        $state = 2;
88
                    } else {
89
                        // we expect the token to be a keyword
90 2
                        $parser->error('Unexpected token.', $token);
91
                    }
92
93 14
                    break;
94 12
                case 2:
95 12
                    if ($token->type === TokenType::Keyword && $token->keyword === 'FOR') {
96 10
                        $state = 3;
97
                    } else {
98 8
                        $expr->indexes = ExpressionArray::parse($parser, $list);
99 8
                        $state = 0;
100 8
                        $ret[] = $expr;
101 8
                        $expr = new IndexHint();
102
                    }
103
104 12
                    break;
105 10
                case 3:
106 10
                    if ($token->type === TokenType::Keyword) {
107
                        if (
108 8
                            $token->keyword === 'JOIN'
109 8
                            || $token->keyword === 'GROUP BY'
110 8
                            || $token->keyword === 'ORDER BY'
111
                        ) {
112 6
                            $expr->for = $token->keyword;
113
                        } else {
114 2
                            $parser->error('Unexpected keyword.', $token);
115
                        }
116
117 8
                        $state = 4;
118
                    } else {
119
                        // we expect the token to be a keyword
120 2
                        $parser->error('Unexpected token.', $token);
121
                    }
122
123 10
                    break;
124 8
                case 4:
125 8
                    $expr->indexes = ExpressionArray::parse($parser, $list);
126 8
                    $state = 0;
127 8
                    $ret[] = $expr;
128 8
                    $expr = new IndexHint();
129 8
                    break;
130
            }
131
        }
132
133 14
        --$list->idx;
134
135 14
        return $ret;
136
    }
137
138
    /** @param IndexHint[] $component the component to be built */
139 2
    public static function buildAll(array $component): string
140
    {
141 2
        return implode(' ', $component);
142
    }
143
}
144