Passed
Push — master ( 16d2f0...7c26e5 )
by William
06:07 queued 03:22
created

TokensList::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

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