Passed
Pull Request — master (#504)
by
unknown
02:50
created

TokensList::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser;
6
7
use ArrayAccess;
8
9
use function count;
10
use function in_array;
11
use function is_array;
12
13
/**
14
 * Defines an array of tokens and utility functions to iterate through it.
15
 *
16
 * A structure representing a list of tokens.
17
 *
18
 * @implements ArrayAccess<int, Token>
19
 */
20
class TokensList implements ArrayAccess
21
{
22
    /**
23
     * The count of tokens.
24
     *
25
     * @var int
26
     */
27
    public $count = 0;
28
29
    /**
30
     * The index of the next token to be returned.
31
     *
32
     * @var int
33
     */
34
    public $idx = 0;
35
36
    /**
37
     * @param Token[] $tokens The array of tokens.
38
     */
39 1448
    public function __construct(public array $tokens = [])
40
    {
41 1448
        $this->count = count($tokens);
42
    }
43
44
    /**
45
     * Builds an array of tokens by merging their raw value.
46
     */
47 2
    public function build(): string
48
    {
49 2
        return static::buildFromArray($this->tokens);
50
    }
51
52
    /**
53
     * Builds an array of tokens by merging their raw value.
54
     *
55
     * @param Token[] $list the tokens to be built
56
     */
57 40
    public static function buildFromArray(array $list): string
58
    {
59 40
        $ret = '';
60 40
        foreach ($list as $token) {
61 24
            $ret .= $token->token;
62
        }
63
64 40
        return $ret;
65
    }
66
67
    /**
68
     * Adds a new token.
69
     *
70
     * @param Token $token token to be added in list
71
     */
72 2
    public function add(Token $token): void
73
    {
74 2
        $this->tokens[$this->count++] = $token;
75
    }
76
77
    /**
78
     * Gets the next token. Skips any irrelevant token (whitespaces and
79
     * comments).
80
     */
81 508
    public function getNext(): Token|null
82
    {
83 508
        for (; $this->idx < $this->count; ++$this->idx) {
84
            if (
85 508
                ($this->tokens[$this->idx]->type !== Token::TYPE_WHITESPACE)
86 508
                && ($this->tokens[$this->idx]->type !== Token::TYPE_COMMENT)
87
            ) {
88 508
                return $this->tokens[$this->idx++];
89
            }
90
        }
91
92 2
        return null;
93
    }
94
95
    /**
96
     * Gets the previous token. Skips any irrelevant token (whitespaces and
97
     * comments).
98
     */
99 500
    public function getPrevious(): Token|null
100
    {
101 500
        for (; $this->idx >= 0; --$this->idx) {
102
            if (
103 500
                ($this->tokens[$this->idx]->type !== Token::TYPE_WHITESPACE)
104 500
                && ($this->tokens[$this->idx]->type !== Token::TYPE_COMMENT)
105
            ) {
106 500
                return $this->tokens[$this->idx--];
107
            }
108
        }
109
110 14
        return null;
111
    }
112
113
    /**
114
     * Gets the previous token.
115
     *
116
     * @param int|int[] $type the type
117
     */
118 2
    public function getPreviousOfType($type): Token|null
119
    {
120 2
        if (! is_array($type)) {
121 2
            $type = [$type];
122
        }
123
124 2
        for (; $this->idx >= 0; --$this->idx) {
125 2
            if (in_array($this->tokens[$this->idx]->type, $type, true)) {
126 2
                return $this->tokens[$this->idx--];
127
            }
128
        }
129
130 2
        return null;
131
    }
132
133
    /**
134
     * Gets the next token.
135
     *
136
     * @param int|int[] $type the type
137
     */
138 184
    public function getNextOfType($type): Token|null
139
    {
140 184
        if (! is_array($type)) {
141 184
            $type = [$type];
142
        }
143
144 184
        for (; $this->idx < $this->count; ++$this->idx) {
145 184
            if (in_array($this->tokens[$this->idx]->type, $type, true)) {
146 166
                return $this->tokens[$this->idx++];
147
            }
148
        }
149
150 30
        return null;
151
    }
152
153
    /**
154
     * Gets the next token.
155
     *
156
     * @param int    $type  the type of the token
157
     * @param string $value the value of the token
158
     */
159 1428
    public function getNextOfTypeAndValue($type, $value): Token|null
160
    {
161 1428
        for (; $this->idx < $this->count; ++$this->idx) {
162 1428
            if (($this->tokens[$this->idx]->type === $type) && ($this->tokens[$this->idx]->value === $value)) {
163 242
                return $this->tokens[$this->idx++];
164
            }
165
        }
166
167 1428
        return null;
168
    }
169
170
    /**
171
     * Gets the next token.
172
     *
173
     * @param int $type the type of the token
174
     * @param int $flag the flag of the token
175
     */
176 1428
    public function getNextOfTypeAndFlag(int $type, int $flag): Token|null
177
    {
178 1428
        for (; $this->idx < $this->count; ++$this->idx) {
179 1428
            if (($this->tokens[$this->idx]->type === $type) && ($this->tokens[$this->idx]->flags === $flag)) {
180 216
                return $this->tokens[$this->idx++];
181
            }
182
        }
183
184 1428
        return null;
185
    }
186
187
    /**
188
     * Sets an value inside the container.
189
     *
190
     * @param int|null $offset the offset to be set
191
     * @param Token    $value  the token to be saved
192
     */
193 2
    public function offsetSet($offset, $value): void
194
    {
195 2
        if ($offset === null) {
196 2
            $this->tokens[$this->count++] = $value;
197
        } else {
198 2
            $this->tokens[$offset] = $value;
199
        }
200
    }
201
202
    /**
203
     * Gets a value from the container.
204
     *
205
     * @param int $offset the offset to be returned
206
     */
207 2
    public function offsetGet($offset): Token|null
208
    {
209 2
        return $offset < $this->count ? $this->tokens[$offset] : null;
210
    }
211
212
    /**
213
     * Checks if an offset was previously set.
214
     *
215
     * @param int $offset the offset to be checked
216
     */
217 2
    public function offsetExists($offset): bool
218
    {
219 2
        return $offset < $this->count;
220
    }
221
222
    /**
223
     * Unsets the value of an offset.
224
     *
225
     * @param int $offset the offset to be unset
226
     */
227 2
    public function offsetUnset($offset): void
228
    {
229 2
        unset($this->tokens[$offset]);
230 2
        --$this->count;
231 2
        for ($i = $offset; $i < $this->count; ++$i) {
232 2
            $this->tokens[$i] = $this->tokens[$i + 1];
233
        }
234
235 2
        unset($this->tokens[$this->count]);
236
    }
237
}
238