Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * Tokenizes PHP code.
|
Chris@0
|
4 *
|
Chris@0
|
5 * PHP version 5
|
Chris@0
|
6 *
|
Chris@0
|
7 * @category PHP
|
Chris@0
|
8 * @package PHP_CodeSniffer
|
Chris@0
|
9 * @author Greg Sherwood <gsherwood@squiz.net>
|
Chris@0
|
10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
|
Chris@0
|
11 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
|
Chris@0
|
12 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
13 */
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Tokenizes PHP code.
|
Chris@0
|
17 *
|
Chris@0
|
18 * @category PHP
|
Chris@0
|
19 * @package PHP_CodeSniffer
|
Chris@0
|
20 * @author Greg Sherwood <gsherwood@squiz.net>
|
Chris@0
|
21 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
|
Chris@0
|
22 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
|
Chris@0
|
23 * @version Release: @package_version@
|
Chris@0
|
24 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
25 */
|
Chris@0
|
26 class PHP_CodeSniffer_Tokenizers_PHP
|
Chris@0
|
27 {
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * If TRUE, files that appear to be minified will not be processed.
|
Chris@0
|
31 *
|
Chris@0
|
32 * @var boolean
|
Chris@0
|
33 */
|
Chris@0
|
34 public $skipMinified = false;
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * A list of tokens that are allowed to open a scope.
|
Chris@0
|
38 *
|
Chris@0
|
39 * This array also contains information about what kind of token the scope
|
Chris@0
|
40 * opener uses to open and close the scope, if the token strictly requires
|
Chris@0
|
41 * an opener, if the token can share a scope closer, and who it can be shared
|
Chris@0
|
42 * with. An example of a token that shares a scope closer is a CASE scope.
|
Chris@0
|
43 *
|
Chris@0
|
44 * @var array
|
Chris@0
|
45 */
|
Chris@0
|
46 public $scopeOpeners = array(
|
Chris@0
|
47 T_IF => array(
|
Chris@0
|
48 'start' => array(
|
Chris@0
|
49 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
50 T_COLON => T_COLON,
|
Chris@0
|
51 ),
|
Chris@0
|
52 'end' => array(
|
Chris@0
|
53 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
54 T_ENDIF => T_ENDIF,
|
Chris@0
|
55 T_ELSE => T_ELSE,
|
Chris@0
|
56 T_ELSEIF => T_ELSEIF,
|
Chris@0
|
57 ),
|
Chris@0
|
58 'strict' => false,
|
Chris@0
|
59 'shared' => false,
|
Chris@0
|
60 'with' => array(
|
Chris@0
|
61 T_ELSE => T_ELSE,
|
Chris@0
|
62 T_ELSEIF => T_ELSEIF,
|
Chris@0
|
63 ),
|
Chris@0
|
64 ),
|
Chris@0
|
65 T_TRY => array(
|
Chris@0
|
66 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
67 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
68 'strict' => true,
|
Chris@0
|
69 'shared' => false,
|
Chris@0
|
70 'with' => array(),
|
Chris@0
|
71 ),
|
Chris@0
|
72 T_CATCH => array(
|
Chris@0
|
73 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
74 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
75 'strict' => true,
|
Chris@0
|
76 'shared' => false,
|
Chris@0
|
77 'with' => array(),
|
Chris@0
|
78 ),
|
Chris@0
|
79 T_FINALLY => array(
|
Chris@0
|
80 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
81 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
82 'strict' => true,
|
Chris@0
|
83 'shared' => false,
|
Chris@0
|
84 'with' => array(),
|
Chris@0
|
85 ),
|
Chris@0
|
86 T_ELSE => array(
|
Chris@0
|
87 'start' => array(
|
Chris@0
|
88 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
89 T_COLON => T_COLON,
|
Chris@0
|
90 ),
|
Chris@0
|
91 'end' => array(
|
Chris@0
|
92 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
93 T_ENDIF => T_ENDIF,
|
Chris@0
|
94 ),
|
Chris@0
|
95 'strict' => false,
|
Chris@0
|
96 'shared' => false,
|
Chris@0
|
97 'with' => array(
|
Chris@0
|
98 T_IF => T_IF,
|
Chris@0
|
99 T_ELSEIF => T_ELSEIF,
|
Chris@0
|
100 ),
|
Chris@0
|
101 ),
|
Chris@0
|
102 T_ELSEIF => array(
|
Chris@0
|
103 'start' => array(
|
Chris@0
|
104 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
105 T_COLON => T_COLON,
|
Chris@0
|
106 ),
|
Chris@0
|
107 'end' => array(
|
Chris@0
|
108 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
109 T_ENDIF => T_ENDIF,
|
Chris@0
|
110 T_ELSE => T_ELSE,
|
Chris@0
|
111 T_ELSEIF => T_ELSEIF,
|
Chris@0
|
112 ),
|
Chris@0
|
113 'strict' => false,
|
Chris@0
|
114 'shared' => false,
|
Chris@0
|
115 'with' => array(
|
Chris@0
|
116 T_IF => T_IF,
|
Chris@0
|
117 T_ELSE => T_ELSE,
|
Chris@0
|
118 ),
|
Chris@0
|
119 ),
|
Chris@0
|
120 T_FOR => array(
|
Chris@0
|
121 'start' => array(
|
Chris@0
|
122 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
123 T_COLON => T_COLON,
|
Chris@0
|
124 ),
|
Chris@0
|
125 'end' => array(
|
Chris@0
|
126 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
127 T_ENDFOR => T_ENDFOR,
|
Chris@0
|
128 ),
|
Chris@0
|
129 'strict' => false,
|
Chris@0
|
130 'shared' => false,
|
Chris@0
|
131 'with' => array(),
|
Chris@0
|
132 ),
|
Chris@0
|
133 T_FOREACH => array(
|
Chris@0
|
134 'start' => array(
|
Chris@0
|
135 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
136 T_COLON => T_COLON,
|
Chris@0
|
137 ),
|
Chris@0
|
138 'end' => array(
|
Chris@0
|
139 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
140 T_ENDFOREACH => T_ENDFOREACH,
|
Chris@0
|
141 ),
|
Chris@0
|
142 'strict' => false,
|
Chris@0
|
143 'shared' => false,
|
Chris@0
|
144 'with' => array(),
|
Chris@0
|
145 ),
|
Chris@0
|
146 T_INTERFACE => array(
|
Chris@0
|
147 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
148 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
149 'strict' => true,
|
Chris@0
|
150 'shared' => false,
|
Chris@0
|
151 'with' => array(),
|
Chris@0
|
152 ),
|
Chris@0
|
153 T_FUNCTION => array(
|
Chris@0
|
154 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
155 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
156 'strict' => true,
|
Chris@0
|
157 'shared' => false,
|
Chris@0
|
158 'with' => array(),
|
Chris@0
|
159 ),
|
Chris@0
|
160 T_CLASS => array(
|
Chris@0
|
161 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
162 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
163 'strict' => true,
|
Chris@0
|
164 'shared' => false,
|
Chris@0
|
165 'with' => array(),
|
Chris@0
|
166 ),
|
Chris@0
|
167 T_TRAIT => array(
|
Chris@0
|
168 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
169 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
170 'strict' => true,
|
Chris@0
|
171 'shared' => false,
|
Chris@0
|
172 'with' => array(),
|
Chris@0
|
173 ),
|
Chris@0
|
174 T_USE => array(
|
Chris@0
|
175 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
176 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
177 'strict' => false,
|
Chris@0
|
178 'shared' => false,
|
Chris@0
|
179 'with' => array(),
|
Chris@0
|
180 ),
|
Chris@0
|
181 T_DECLARE => array(
|
Chris@0
|
182 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
183 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
184 'strict' => false,
|
Chris@0
|
185 'shared' => false,
|
Chris@0
|
186 'with' => array(),
|
Chris@0
|
187 ),
|
Chris@0
|
188 T_NAMESPACE => array(
|
Chris@0
|
189 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
190 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
191 'strict' => false,
|
Chris@0
|
192 'shared' => false,
|
Chris@0
|
193 'with' => array(),
|
Chris@0
|
194 ),
|
Chris@0
|
195 T_WHILE => array(
|
Chris@0
|
196 'start' => array(
|
Chris@0
|
197 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
198 T_COLON => T_COLON,
|
Chris@0
|
199 ),
|
Chris@0
|
200 'end' => array(
|
Chris@0
|
201 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
202 T_ENDWHILE => T_ENDWHILE,
|
Chris@0
|
203 ),
|
Chris@0
|
204 'strict' => false,
|
Chris@0
|
205 'shared' => false,
|
Chris@0
|
206 'with' => array(),
|
Chris@0
|
207 ),
|
Chris@0
|
208 T_DO => array(
|
Chris@0
|
209 'start' => array(T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET),
|
Chris@0
|
210 'end' => array(T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET),
|
Chris@0
|
211 'strict' => true,
|
Chris@0
|
212 'shared' => false,
|
Chris@0
|
213 'with' => array(),
|
Chris@0
|
214 ),
|
Chris@0
|
215 T_SWITCH => array(
|
Chris@0
|
216 'start' => array(
|
Chris@0
|
217 T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
218 T_COLON => T_COLON,
|
Chris@0
|
219 ),
|
Chris@0
|
220 'end' => array(
|
Chris@0
|
221 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
222 T_ENDSWITCH => T_ENDSWITCH,
|
Chris@0
|
223 ),
|
Chris@0
|
224 'strict' => true,
|
Chris@0
|
225 'shared' => false,
|
Chris@0
|
226 'with' => array(),
|
Chris@0
|
227 ),
|
Chris@0
|
228 T_CASE => array(
|
Chris@0
|
229 'start' => array(
|
Chris@0
|
230 T_COLON => T_COLON,
|
Chris@0
|
231 T_SEMICOLON => T_SEMICOLON,
|
Chris@0
|
232 ),
|
Chris@0
|
233 'end' => array(
|
Chris@0
|
234 T_BREAK => T_BREAK,
|
Chris@0
|
235 T_RETURN => T_RETURN,
|
Chris@0
|
236 T_CONTINUE => T_CONTINUE,
|
Chris@0
|
237 T_THROW => T_THROW,
|
Chris@0
|
238 T_EXIT => T_EXIT,
|
Chris@0
|
239 ),
|
Chris@0
|
240 'strict' => true,
|
Chris@0
|
241 'shared' => true,
|
Chris@0
|
242 'with' => array(
|
Chris@0
|
243 T_DEFAULT => T_DEFAULT,
|
Chris@0
|
244 T_CASE => T_CASE,
|
Chris@0
|
245 T_SWITCH => T_SWITCH,
|
Chris@0
|
246 ),
|
Chris@0
|
247 ),
|
Chris@0
|
248 T_DEFAULT => array(
|
Chris@0
|
249 'start' => array(
|
Chris@0
|
250 T_COLON => T_COLON,
|
Chris@0
|
251 T_SEMICOLON => T_SEMICOLON,
|
Chris@0
|
252 ),
|
Chris@0
|
253 'end' => array(
|
Chris@0
|
254 T_BREAK => T_BREAK,
|
Chris@0
|
255 T_RETURN => T_RETURN,
|
Chris@0
|
256 T_CONTINUE => T_CONTINUE,
|
Chris@0
|
257 T_THROW => T_THROW,
|
Chris@0
|
258 T_EXIT => T_EXIT,
|
Chris@0
|
259 ),
|
Chris@0
|
260 'strict' => true,
|
Chris@0
|
261 'shared' => true,
|
Chris@0
|
262 'with' => array(
|
Chris@0
|
263 T_CASE => T_CASE,
|
Chris@0
|
264 T_SWITCH => T_SWITCH,
|
Chris@0
|
265 ),
|
Chris@0
|
266 ),
|
Chris@0
|
267 T_START_HEREDOC => array(
|
Chris@0
|
268 'start' => array(T_START_HEREDOC => T_START_HEREDOC),
|
Chris@0
|
269 'end' => array(T_END_HEREDOC => T_END_HEREDOC),
|
Chris@0
|
270 'strict' => true,
|
Chris@0
|
271 'shared' => false,
|
Chris@0
|
272 'with' => array(),
|
Chris@0
|
273 ),
|
Chris@0
|
274 );
|
Chris@0
|
275
|
Chris@0
|
276 /**
|
Chris@0
|
277 * A list of tokens that end the scope.
|
Chris@0
|
278 *
|
Chris@0
|
279 * This array is just a unique collection of the end tokens
|
Chris@0
|
280 * from the _scopeOpeners array. The data is duplicated here to
|
Chris@0
|
281 * save time during parsing of the file.
|
Chris@0
|
282 *
|
Chris@0
|
283 * @var array
|
Chris@0
|
284 */
|
Chris@0
|
285 public $endScopeTokens = array(
|
Chris@0
|
286 T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
287 T_ENDIF => T_ENDIF,
|
Chris@0
|
288 T_ENDFOR => T_ENDFOR,
|
Chris@0
|
289 T_ENDFOREACH => T_ENDFOREACH,
|
Chris@0
|
290 T_ENDWHILE => T_ENDWHILE,
|
Chris@0
|
291 T_ENDSWITCH => T_ENDSWITCH,
|
Chris@0
|
292 T_BREAK => T_BREAK,
|
Chris@0
|
293 T_END_HEREDOC => T_END_HEREDOC,
|
Chris@0
|
294 );
|
Chris@0
|
295
|
Chris@0
|
296 /**
|
Chris@0
|
297 * A cache of different token types, resolved into arrays.
|
Chris@0
|
298 *
|
Chris@0
|
299 * @var array()
|
Chris@0
|
300 * @see standardiseToken()
|
Chris@0
|
301 */
|
Chris@0
|
302 private static $_resolveTokenCache = array();
|
Chris@0
|
303
|
Chris@0
|
304
|
Chris@0
|
305 /**
|
Chris@0
|
306 * Creates an array of tokens when given some PHP code.
|
Chris@0
|
307 *
|
Chris@0
|
308 * Starts by using token_get_all() but does a lot of extra processing
|
Chris@0
|
309 * to insert information about the context of the token.
|
Chris@0
|
310 *
|
Chris@0
|
311 * @param string $string The string to tokenize.
|
Chris@0
|
312 * @param string $eolChar The EOL character to use for splitting strings.
|
Chris@0
|
313 *
|
Chris@0
|
314 * @return array
|
Chris@0
|
315 */
|
Chris@0
|
316 public function tokenizeString($string, $eolChar='\n')
|
Chris@0
|
317 {
|
Chris@0
|
318 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
319 echo "\t*** START PHP TOKENIZING ***".PHP_EOL;
|
Chris@0
|
320 $isWin = false;
|
Chris@0
|
321 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
Chris@0
|
322 $isWin = true;
|
Chris@0
|
323 }
|
Chris@0
|
324 }
|
Chris@0
|
325
|
Chris@0
|
326 $tokens = @token_get_all($string);
|
Chris@0
|
327 $finalTokens = array();
|
Chris@0
|
328
|
Chris@0
|
329 $newStackPtr = 0;
|
Chris@0
|
330 $numTokens = count($tokens);
|
Chris@0
|
331 $lastNotEmptyToken = 0;
|
Chris@0
|
332
|
Chris@0
|
333 $insideInlineIf = array();
|
Chris@0
|
334 $insideUseGroup = false;
|
Chris@0
|
335
|
Chris@0
|
336 $commentTokenizer = new PHP_CodeSniffer_Tokenizers_Comment();
|
Chris@0
|
337
|
Chris@0
|
338 for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
|
Chris@0
|
339 $token = (array) $tokens[$stackPtr];
|
Chris@0
|
340 $tokenIsArray = isset($token[1]);
|
Chris@0
|
341
|
Chris@0
|
342 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
343 if ($tokenIsArray === true) {
|
Chris@0
|
344 $type = token_name($token[0]);
|
Chris@0
|
345 $content = PHP_CodeSniffer::prepareForOutput($token[1]);
|
Chris@0
|
346 } else {
|
Chris@0
|
347 $newToken = self::resolveSimpleToken($token[0]);
|
Chris@0
|
348 $type = $newToken['type'];
|
Chris@0
|
349 $content = PHP_CodeSniffer::prepareForOutput($token[0]);
|
Chris@0
|
350 }
|
Chris@0
|
351
|
Chris@0
|
352 echo "\tProcess token ";
|
Chris@0
|
353 if ($tokenIsArray === true) {
|
Chris@0
|
354 echo "[$stackPtr]";
|
Chris@0
|
355 } else {
|
Chris@0
|
356 echo " $stackPtr ";
|
Chris@0
|
357 }
|
Chris@0
|
358
|
Chris@0
|
359 echo ": $type => $content";
|
Chris@0
|
360 }//end if
|
Chris@0
|
361
|
Chris@0
|
362 if ($newStackPtr > 0 && $finalTokens[($newStackPtr - 1)]['code'] !== T_WHITESPACE) {
|
Chris@0
|
363 $lastNotEmptyToken = ($newStackPtr - 1);
|
Chris@0
|
364 }
|
Chris@0
|
365
|
Chris@0
|
366 /*
|
Chris@0
|
367 If we are using \r\n newline characters, the \r and \n are sometimes
|
Chris@0
|
368 split over two tokens. This normally occurs after comments. We need
|
Chris@0
|
369 to merge these two characters together so that our line endings are
|
Chris@0
|
370 consistent for all lines.
|
Chris@0
|
371 */
|
Chris@0
|
372
|
Chris@0
|
373 if ($tokenIsArray === true && substr($token[1], -1) === "\r") {
|
Chris@0
|
374 if (isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
375 && is_array($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
376 && $tokens[($stackPtr + 1)][1][0] === "\n"
|
Chris@0
|
377 ) {
|
Chris@0
|
378 $token[1] .= "\n";
|
Chris@0
|
379 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
380 if ($isWin === true) {
|
Chris@0
|
381 echo '\n';
|
Chris@0
|
382 } else {
|
Chris@0
|
383 echo "\033[30;1m\\n\033[0m";
|
Chris@0
|
384 }
|
Chris@0
|
385 }
|
Chris@0
|
386
|
Chris@0
|
387 if ($tokens[($stackPtr + 1)][1] === "\n") {
|
Chris@0
|
388 // This token's content has been merged into the previous,
|
Chris@0
|
389 // so we can skip it.
|
Chris@0
|
390 $tokens[($stackPtr + 1)] = '';
|
Chris@0
|
391 } else {
|
Chris@0
|
392 $tokens[($stackPtr + 1)][1] = substr($tokens[($stackPtr + 1)][1], 1);
|
Chris@0
|
393 }
|
Chris@0
|
394 }
|
Chris@0
|
395 }//end if
|
Chris@0
|
396
|
Chris@0
|
397 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
398 echo PHP_EOL;
|
Chris@0
|
399 }
|
Chris@0
|
400
|
Chris@0
|
401 /*
|
Chris@0
|
402 Parse doc blocks into something that can be easily iterated over.
|
Chris@0
|
403 */
|
Chris@0
|
404
|
Chris@0
|
405 if ($tokenIsArray === true && $token[0] === T_DOC_COMMENT) {
|
Chris@0
|
406 $commentTokens = $commentTokenizer->tokenizeString($token[1], $eolChar, $newStackPtr);
|
Chris@0
|
407 foreach ($commentTokens as $commentToken) {
|
Chris@0
|
408 $finalTokens[$newStackPtr] = $commentToken;
|
Chris@0
|
409 $newStackPtr++;
|
Chris@0
|
410 }
|
Chris@0
|
411
|
Chris@0
|
412 continue;
|
Chris@0
|
413 }
|
Chris@0
|
414
|
Chris@0
|
415 /*
|
Chris@0
|
416 If this is a double quoted string, PHP will tokenize the whole
|
Chris@0
|
417 thing which causes problems with the scope map when braces are
|
Chris@0
|
418 within the string. So we need to merge the tokens together to
|
Chris@0
|
419 provide a single string.
|
Chris@0
|
420 */
|
Chris@0
|
421
|
Chris@0
|
422 if ($tokenIsArray === false && ($token[0] === '"' || $token[0] === 'b"')) {
|
Chris@0
|
423 // Binary casts need a special token.
|
Chris@0
|
424 if ($token[0] === 'b"') {
|
Chris@0
|
425 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
426 'code' => T_BINARY_CAST,
|
Chris@0
|
427 'type' => 'T_BINARY_CAST',
|
Chris@0
|
428 'content' => 'b',
|
Chris@0
|
429 );
|
Chris@0
|
430 $newStackPtr++;
|
Chris@0
|
431 }
|
Chris@0
|
432
|
Chris@0
|
433 $tokenContent = '"';
|
Chris@0
|
434 $nestedVars = array();
|
Chris@0
|
435 for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
|
Chris@0
|
436 $subToken = (array) $tokens[$i];
|
Chris@0
|
437 $subTokenIsArray = isset($subToken[1]);
|
Chris@0
|
438
|
Chris@0
|
439 if ($subTokenIsArray === true) {
|
Chris@0
|
440 $tokenContent .= $subToken[1];
|
Chris@0
|
441 if ($subToken[1] === '{'
|
Chris@0
|
442 && $subToken[0] !== T_ENCAPSED_AND_WHITESPACE
|
Chris@0
|
443 ) {
|
Chris@0
|
444 $nestedVars[] = $i;
|
Chris@0
|
445 }
|
Chris@0
|
446 } else {
|
Chris@0
|
447 $tokenContent .= $subToken[0];
|
Chris@0
|
448 if ($subToken[0] === '}') {
|
Chris@0
|
449 array_pop($nestedVars);
|
Chris@0
|
450 }
|
Chris@0
|
451 }
|
Chris@0
|
452
|
Chris@0
|
453 if ($subTokenIsArray === false
|
Chris@0
|
454 && $subToken[0] === '"'
|
Chris@0
|
455 && empty($nestedVars) === true
|
Chris@0
|
456 ) {
|
Chris@0
|
457 // We found the other end of the double quoted string.
|
Chris@0
|
458 break;
|
Chris@0
|
459 }
|
Chris@0
|
460 }//end for
|
Chris@0
|
461
|
Chris@0
|
462 $stackPtr = $i;
|
Chris@0
|
463
|
Chris@0
|
464 // Convert each line within the double quoted string to a
|
Chris@0
|
465 // new token, so it conforms with other multiple line tokens.
|
Chris@0
|
466 $tokenLines = explode($eolChar, $tokenContent);
|
Chris@0
|
467 $numLines = count($tokenLines);
|
Chris@0
|
468 $newToken = array();
|
Chris@0
|
469
|
Chris@0
|
470 for ($j = 0; $j < $numLines; $j++) {
|
Chris@0
|
471 $newToken['content'] = $tokenLines[$j];
|
Chris@0
|
472 if ($j === ($numLines - 1)) {
|
Chris@0
|
473 if ($tokenLines[$j] === '') {
|
Chris@0
|
474 break;
|
Chris@0
|
475 }
|
Chris@0
|
476 } else {
|
Chris@0
|
477 $newToken['content'] .= $eolChar;
|
Chris@0
|
478 }
|
Chris@0
|
479
|
Chris@0
|
480 $newToken['code'] = T_DOUBLE_QUOTED_STRING;
|
Chris@0
|
481 $newToken['type'] = 'T_DOUBLE_QUOTED_STRING';
|
Chris@0
|
482 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
483 $newStackPtr++;
|
Chris@0
|
484 }
|
Chris@0
|
485
|
Chris@0
|
486 // Continue, as we're done with this token.
|
Chris@0
|
487 continue;
|
Chris@0
|
488 }//end if
|
Chris@0
|
489
|
Chris@0
|
490 /*
|
Chris@0
|
491 If this is a heredoc, PHP will tokenize the whole
|
Chris@0
|
492 thing which causes problems when heredocs don't
|
Chris@0
|
493 contain real PHP code, which is almost never.
|
Chris@0
|
494 We want to leave the start and end heredoc tokens
|
Chris@0
|
495 alone though.
|
Chris@0
|
496 */
|
Chris@0
|
497
|
Chris@0
|
498 if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) {
|
Chris@0
|
499 // Add the start heredoc token to the final array.
|
Chris@0
|
500 $finalTokens[$newStackPtr] = self::standardiseToken($token);
|
Chris@0
|
501
|
Chris@0
|
502 // Check if this is actually a nowdoc and use a different token
|
Chris@0
|
503 // to help the sniffs.
|
Chris@0
|
504 $nowdoc = false;
|
Chris@0
|
505 if ($token[1][3] === "'") {
|
Chris@0
|
506 $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC;
|
Chris@0
|
507 $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC';
|
Chris@0
|
508 $nowdoc = true;
|
Chris@0
|
509 }
|
Chris@0
|
510
|
Chris@0
|
511 $tokenContent = '';
|
Chris@0
|
512 for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
|
Chris@0
|
513 $subTokenIsArray = is_array($tokens[$i]);
|
Chris@0
|
514 if ($subTokenIsArray === true
|
Chris@0
|
515 && $tokens[$i][0] === T_END_HEREDOC
|
Chris@0
|
516 ) {
|
Chris@0
|
517 // We found the other end of the heredoc.
|
Chris@0
|
518 break;
|
Chris@0
|
519 }
|
Chris@0
|
520
|
Chris@0
|
521 if ($subTokenIsArray === true) {
|
Chris@0
|
522 $tokenContent .= $tokens[$i][1];
|
Chris@0
|
523 } else {
|
Chris@0
|
524 $tokenContent .= $tokens[$i];
|
Chris@0
|
525 }
|
Chris@0
|
526 }
|
Chris@0
|
527
|
Chris@0
|
528 if ($i === $numTokens) {
|
Chris@0
|
529 // We got to the end of the file and never
|
Chris@0
|
530 // found the closing token, so this probably wasn't
|
Chris@0
|
531 // a heredoc.
|
Chris@0
|
532 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
533 $type = $finalTokens[$newStackPtr]['type'];
|
Chris@0
|
534 echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL;
|
Chris@0
|
535 echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL;
|
Chris@0
|
536 }
|
Chris@0
|
537
|
Chris@0
|
538 $finalTokens[$newStackPtr]['code'] = T_STRING;
|
Chris@0
|
539 $finalTokens[$newStackPtr]['type'] = 'T_STRING';
|
Chris@0
|
540 $newStackPtr++;
|
Chris@0
|
541 continue;
|
Chris@0
|
542 }
|
Chris@0
|
543
|
Chris@0
|
544 $stackPtr = $i;
|
Chris@0
|
545 $newStackPtr++;
|
Chris@0
|
546
|
Chris@0
|
547 // Convert each line within the heredoc to a
|
Chris@0
|
548 // new token, so it conforms with other multiple line tokens.
|
Chris@0
|
549 $tokenLines = explode($eolChar, $tokenContent);
|
Chris@0
|
550 $numLines = count($tokenLines);
|
Chris@0
|
551 $newToken = array();
|
Chris@0
|
552
|
Chris@0
|
553 for ($j = 0; $j < $numLines; $j++) {
|
Chris@0
|
554 $newToken['content'] = $tokenLines[$j];
|
Chris@0
|
555 if ($j === ($numLines - 1)) {
|
Chris@0
|
556 if ($tokenLines[$j] === '') {
|
Chris@0
|
557 break;
|
Chris@0
|
558 }
|
Chris@0
|
559 } else {
|
Chris@0
|
560 $newToken['content'] .= $eolChar;
|
Chris@0
|
561 }
|
Chris@0
|
562
|
Chris@0
|
563 if ($nowdoc === true) {
|
Chris@0
|
564 $newToken['code'] = T_NOWDOC;
|
Chris@0
|
565 $newToken['type'] = 'T_NOWDOC';
|
Chris@0
|
566 } else {
|
Chris@0
|
567 $newToken['code'] = T_HEREDOC;
|
Chris@0
|
568 $newToken['type'] = 'T_HEREDOC';
|
Chris@0
|
569 }
|
Chris@0
|
570
|
Chris@0
|
571 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
572 $newStackPtr++;
|
Chris@0
|
573 }//end for
|
Chris@0
|
574
|
Chris@0
|
575 // Add the end heredoc token to the final array.
|
Chris@0
|
576 $finalTokens[$newStackPtr] = self::standardiseToken($tokens[$stackPtr]);
|
Chris@0
|
577
|
Chris@0
|
578 if ($nowdoc === true) {
|
Chris@0
|
579 $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC;
|
Chris@0
|
580 $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC';
|
Chris@0
|
581 $nowdoc = true;
|
Chris@0
|
582 }
|
Chris@0
|
583
|
Chris@0
|
584 $newStackPtr++;
|
Chris@0
|
585
|
Chris@0
|
586 // Continue, as we're done with this token.
|
Chris@0
|
587 continue;
|
Chris@0
|
588 }//end if
|
Chris@0
|
589
|
Chris@0
|
590 /*
|
Chris@0
|
591 Before PHP 5.6, the ... operator was tokenized as three
|
Chris@0
|
592 T_STRING_CONCAT tokens in a row. So look for and combine
|
Chris@0
|
593 these tokens in earlier versions.
|
Chris@0
|
594 */
|
Chris@0
|
595
|
Chris@0
|
596 if ($tokenIsArray === false
|
Chris@0
|
597 && $token[0] === '.'
|
Chris@0
|
598 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
599 && isset($tokens[($stackPtr + 2)]) === true
|
Chris@0
|
600 && $tokens[($stackPtr + 1)] === '.'
|
Chris@0
|
601 && $tokens[($stackPtr + 2)] === '.'
|
Chris@0
|
602 ) {
|
Chris@0
|
603 $newToken = array();
|
Chris@0
|
604 $newToken['code'] = T_ELLIPSIS;
|
Chris@0
|
605 $newToken['type'] = 'T_ELLIPSIS';
|
Chris@0
|
606 $newToken['content'] = '...';
|
Chris@0
|
607 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
608
|
Chris@0
|
609 $newStackPtr++;
|
Chris@0
|
610 $stackPtr += 2;
|
Chris@0
|
611 continue;
|
Chris@0
|
612 }
|
Chris@0
|
613
|
Chris@0
|
614 /*
|
Chris@0
|
615 Before PHP 5.6, the ** operator was tokenized as two
|
Chris@0
|
616 T_MULTIPLY tokens in a row. So look for and combine
|
Chris@0
|
617 these tokens in earlier versions.
|
Chris@0
|
618 */
|
Chris@0
|
619
|
Chris@0
|
620 if ($tokenIsArray === false
|
Chris@0
|
621 && $token[0] === '*'
|
Chris@0
|
622 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
623 && $tokens[($stackPtr + 1)] === '*'
|
Chris@0
|
624 ) {
|
Chris@0
|
625 $newToken = array();
|
Chris@0
|
626 $newToken['code'] = T_POW;
|
Chris@0
|
627 $newToken['type'] = 'T_POW';
|
Chris@0
|
628 $newToken['content'] = '**';
|
Chris@0
|
629 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
630
|
Chris@0
|
631 $newStackPtr++;
|
Chris@0
|
632 $stackPtr++;
|
Chris@0
|
633 continue;
|
Chris@0
|
634 }
|
Chris@0
|
635
|
Chris@0
|
636 /*
|
Chris@0
|
637 Before PHP 5.6, the **= operator was tokenized as
|
Chris@0
|
638 T_MULTIPLY followed by T_MUL_EQUAL. So look for and combine
|
Chris@0
|
639 these tokens in earlier versions.
|
Chris@0
|
640 */
|
Chris@0
|
641
|
Chris@0
|
642 if ($tokenIsArray === false
|
Chris@0
|
643 && $token[0] === '*'
|
Chris@0
|
644 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
645 && is_array($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
646 && $tokens[($stackPtr + 1)][1] === '*='
|
Chris@0
|
647 ) {
|
Chris@0
|
648 $newToken = array();
|
Chris@0
|
649 $newToken['code'] = T_POW_EQUAL;
|
Chris@0
|
650 $newToken['type'] = 'T_POW_EQUAL';
|
Chris@0
|
651 $newToken['content'] = '**=';
|
Chris@0
|
652 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
653
|
Chris@0
|
654 $newStackPtr++;
|
Chris@0
|
655 $stackPtr++;
|
Chris@0
|
656 continue;
|
Chris@0
|
657 }
|
Chris@0
|
658
|
Chris@0
|
659 /*
|
Chris@0
|
660 Before PHP 7, the ??= operator was tokenized as
|
Chris@0
|
661 T_INLINE_THEN, T_INLINE_THEN, T_EQUAL.
|
Chris@0
|
662 Between PHP 7.0 and 7.2, the ??= operator was tokenized as
|
Chris@0
|
663 T_COALESCE, T_EQUAL.
|
Chris@0
|
664 So look for and combine these tokens in earlier versions.
|
Chris@0
|
665 */
|
Chris@0
|
666
|
Chris@0
|
667 if (($tokenIsArray === false
|
Chris@0
|
668 && $token[0] === '?'
|
Chris@0
|
669 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
670 && $tokens[($stackPtr + 1)][0] === '?'
|
Chris@0
|
671 && isset($tokens[($stackPtr + 2)]) === true
|
Chris@0
|
672 && $tokens[($stackPtr + 2)][0] === '=')
|
Chris@0
|
673 || ($tokenIsArray === true
|
Chris@0
|
674 && $token[0] === T_COALESCE
|
Chris@0
|
675 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
676 && $tokens[($stackPtr + 1)][0] === '=')
|
Chris@0
|
677 ) {
|
Chris@0
|
678 $newToken = array();
|
Chris@0
|
679 $newToken['code'] = T_COALESCE_EQUAL;
|
Chris@0
|
680 $newToken['type'] = 'T_COALESCE_EQUAL';
|
Chris@0
|
681 $newToken['content'] = '??=';
|
Chris@0
|
682 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
683
|
Chris@0
|
684 $newStackPtr++;
|
Chris@0
|
685 $stackPtr++;
|
Chris@0
|
686
|
Chris@0
|
687 if ($tokenIsArray === false) {
|
Chris@0
|
688 // Pre PHP 7.
|
Chris@0
|
689 $stackPtr++;
|
Chris@0
|
690 }
|
Chris@0
|
691
|
Chris@0
|
692 continue;
|
Chris@0
|
693 }
|
Chris@0
|
694
|
Chris@0
|
695 /*
|
Chris@0
|
696 Before PHP 7, the ?? operator was tokenized as
|
Chris@0
|
697 T_INLINE_THEN followed by T_INLINE_THEN.
|
Chris@0
|
698 So look for and combine these tokens in earlier versions.
|
Chris@0
|
699 */
|
Chris@0
|
700
|
Chris@0
|
701 if ($tokenIsArray === false
|
Chris@0
|
702 && $token[0] === '?'
|
Chris@0
|
703 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
704 && $tokens[($stackPtr + 1)][0] === '?'
|
Chris@0
|
705 ) {
|
Chris@0
|
706 $newToken = array();
|
Chris@0
|
707 $newToken['code'] = T_COALESCE;
|
Chris@0
|
708 $newToken['type'] = 'T_COALESCE';
|
Chris@0
|
709 $newToken['content'] = '??';
|
Chris@0
|
710 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
711
|
Chris@0
|
712 $newStackPtr++;
|
Chris@0
|
713 $stackPtr++;
|
Chris@0
|
714 continue;
|
Chris@0
|
715 }
|
Chris@0
|
716
|
Chris@0
|
717 /*
|
Chris@0
|
718 Convert ? to T_NULLABLE OR T_INLINE_THEN
|
Chris@0
|
719 */
|
Chris@0
|
720
|
Chris@0
|
721 if ($tokenIsArray === false && $token[0] === '?') {
|
Chris@0
|
722 $newToken = array();
|
Chris@0
|
723 $newToken['content'] = '?';
|
Chris@0
|
724
|
Chris@0
|
725 for ($i = ($stackPtr - 1); $i >= 0; $i--) {
|
Chris@0
|
726 if (is_array($tokens[$i]) === true) {
|
Chris@0
|
727 $tokenType = $tokens[$i][0];
|
Chris@0
|
728 } else {
|
Chris@0
|
729 $tokenType = $tokens[$i];
|
Chris@0
|
730 }
|
Chris@0
|
731
|
Chris@0
|
732 if ($tokenType === T_FUNCTION) {
|
Chris@0
|
733 $newToken['code'] = T_NULLABLE;
|
Chris@0
|
734 $newToken['type'] = 'T_NULLABLE';
|
Chris@0
|
735 break;
|
Chris@0
|
736 } else if (in_array($tokenType, array(T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '{', ';')) === true) {
|
Chris@0
|
737 $newToken['code'] = T_INLINE_THEN;
|
Chris@0
|
738 $newToken['type'] = 'T_INLINE_THEN';
|
Chris@0
|
739
|
Chris@0
|
740 $insideInlineIf[] = $stackPtr;
|
Chris@0
|
741 break;
|
Chris@0
|
742 }
|
Chris@0
|
743 }
|
Chris@0
|
744
|
Chris@0
|
745 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
746 $newStackPtr++;
|
Chris@0
|
747 continue;
|
Chris@0
|
748 }//end if
|
Chris@0
|
749
|
Chris@0
|
750 /*
|
Chris@0
|
751 Tokens after a double colon may be look like scope openers,
|
Chris@0
|
752 such as when writing code like Foo::NAMESPACE, but they are
|
Chris@0
|
753 only ever variables or strings.
|
Chris@0
|
754 */
|
Chris@0
|
755
|
Chris@0
|
756 if ($stackPtr > 1
|
Chris@0
|
757 && (is_array($tokens[($stackPtr - 1)]) === true
|
Chris@0
|
758 && $tokens[($stackPtr - 1)][0] === T_PAAMAYIM_NEKUDOTAYIM)
|
Chris@0
|
759 && $tokenIsArray === true
|
Chris@0
|
760 && $token[0] !== T_STRING
|
Chris@0
|
761 && $token[0] !== T_VARIABLE
|
Chris@0
|
762 && $token[0] !== T_DOLLAR
|
Chris@0
|
763 && isset(PHP_CodeSniffer_Tokens::$emptyTokens[$token[0]]) === false
|
Chris@0
|
764 ) {
|
Chris@0
|
765 $newToken = array();
|
Chris@0
|
766 $newToken['code'] = T_STRING;
|
Chris@0
|
767 $newToken['type'] = 'T_STRING';
|
Chris@0
|
768 $newToken['content'] = $token[1];
|
Chris@0
|
769 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
770
|
Chris@0
|
771 $newStackPtr++;
|
Chris@0
|
772 continue;
|
Chris@0
|
773 }
|
Chris@0
|
774
|
Chris@0
|
775 /*
|
Chris@0
|
776 The string-like token after a function keyword should always be
|
Chris@0
|
777 tokenized as T_STRING even if it appears to be a different token,
|
Chris@0
|
778 such as when writing code like: function default(): foo
|
Chris@0
|
779 so go forward and change the token type before it is processed.
|
Chris@0
|
780 */
|
Chris@0
|
781
|
Chris@0
|
782 if ($tokenIsArray === true && $token[0] === T_FUNCTION) {
|
Chris@0
|
783 for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
|
Chris@0
|
784 if (is_array($tokens[$x]) === false
|
Chris@0
|
785 || isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x][0]]) === false
|
Chris@0
|
786 ) {
|
Chris@0
|
787 // Non-empty content.
|
Chris@0
|
788 break;
|
Chris@0
|
789 }
|
Chris@0
|
790 }
|
Chris@0
|
791
|
Chris@0
|
792 if ($x < $numTokens && is_array($tokens[$x]) === true) {
|
Chris@0
|
793 $tokens[$x][0] = T_STRING;
|
Chris@0
|
794 }
|
Chris@0
|
795 }
|
Chris@0
|
796
|
Chris@0
|
797 /*
|
Chris@0
|
798 Before PHP 7, the <=> operator was tokenized as
|
Chris@0
|
799 T_IS_SMALLER_OR_EQUAL followed by T_GREATER_THAN.
|
Chris@0
|
800 So look for and combine these tokens in earlier versions.
|
Chris@0
|
801 */
|
Chris@0
|
802
|
Chris@0
|
803 if ($tokenIsArray === true
|
Chris@0
|
804 && $token[0] === T_IS_SMALLER_OR_EQUAL
|
Chris@0
|
805 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
806 && $tokens[($stackPtr + 1)][0] === '>'
|
Chris@0
|
807 ) {
|
Chris@0
|
808 $newToken = array();
|
Chris@0
|
809 $newToken['code'] = T_SPACESHIP;
|
Chris@0
|
810 $newToken['type'] = 'T_SPACESHIP';
|
Chris@0
|
811 $newToken['content'] = '<=>';
|
Chris@0
|
812 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
813
|
Chris@0
|
814 $newStackPtr++;
|
Chris@0
|
815 $stackPtr++;
|
Chris@0
|
816 continue;
|
Chris@0
|
817 }
|
Chris@0
|
818
|
Chris@0
|
819 /*
|
Chris@0
|
820 Emulate traits in PHP versions less than 5.4.
|
Chris@0
|
821 */
|
Chris@0
|
822
|
Chris@0
|
823 if ($tokenIsArray === true
|
Chris@0
|
824 && $token[0] === T_STRING
|
Chris@0
|
825 && strtolower($token[1]) === 'trait'
|
Chris@0
|
826 && $tokens[($stackPtr - 1)][0] !== T_OBJECT_OPERATOR
|
Chris@0
|
827 && $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM
|
Chris@0
|
828 ) {
|
Chris@0
|
829 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
830 'content' => $token[1],
|
Chris@0
|
831 'code' => T_TRAIT,
|
Chris@0
|
832 'type' => 'T_TRAIT',
|
Chris@0
|
833 );
|
Chris@0
|
834
|
Chris@0
|
835 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
836 echo "\t\t* token $stackPtr changed from T_STRING to T_TRAIT".PHP_EOL;
|
Chris@0
|
837 }
|
Chris@0
|
838
|
Chris@0
|
839 $newStackPtr++;
|
Chris@0
|
840 continue;
|
Chris@0
|
841 }
|
Chris@0
|
842
|
Chris@0
|
843 /*
|
Chris@0
|
844 PHP doesn't assign a token to goto labels, so we have to.
|
Chris@0
|
845 These are just string tokens with a single colon after them. Double
|
Chris@0
|
846 colons are already tokenized and so don't interfere with this check.
|
Chris@0
|
847 But we do have to account for CASE statements, that look just like
|
Chris@0
|
848 goto labels.
|
Chris@0
|
849 */
|
Chris@0
|
850
|
Chris@0
|
851 if ($tokenIsArray === true
|
Chris@0
|
852 && $token[0] === T_STRING
|
Chris@0
|
853 && isset($tokens[($stackPtr + 1)]) === true
|
Chris@0
|
854 && $tokens[($stackPtr + 1)] === ':'
|
Chris@0
|
855 && $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM
|
Chris@0
|
856 ) {
|
Chris@0
|
857 $stopTokens = array(
|
Chris@0
|
858 T_CASE => true,
|
Chris@0
|
859 T_SEMICOLON => true,
|
Chris@0
|
860 T_OPEN_CURLY_BRACKET => true,
|
Chris@0
|
861 T_INLINE_THEN => true,
|
Chris@0
|
862 );
|
Chris@0
|
863
|
Chris@0
|
864 for ($x = ($newStackPtr - 1); $x > 0; $x--) {
|
Chris@0
|
865 if (isset($stopTokens[$finalTokens[$x]['code']]) === true) {
|
Chris@0
|
866 break;
|
Chris@0
|
867 }
|
Chris@0
|
868 }
|
Chris@0
|
869
|
Chris@0
|
870 if ($finalTokens[$x]['code'] !== T_CASE
|
Chris@0
|
871 && $finalTokens[$x]['code'] !== T_INLINE_THEN
|
Chris@0
|
872 ) {
|
Chris@0
|
873 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
874 'content' => $token[1].':',
|
Chris@0
|
875 'code' => T_GOTO_LABEL,
|
Chris@0
|
876 'type' => 'T_GOTO_LABEL',
|
Chris@0
|
877 );
|
Chris@0
|
878
|
Chris@0
|
879 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
880 echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL;
|
Chris@0
|
881 echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL;
|
Chris@0
|
882 }
|
Chris@0
|
883
|
Chris@0
|
884 $newStackPtr++;
|
Chris@0
|
885 $stackPtr++;
|
Chris@0
|
886 continue;
|
Chris@0
|
887 }
|
Chris@0
|
888 }//end if
|
Chris@0
|
889
|
Chris@0
|
890 /*
|
Chris@0
|
891 HHVM 3.5 tokenizes "else[\s]+if" as a T_ELSEIF token while PHP
|
Chris@0
|
892 proper only tokenizes "elseif" as a T_ELSEIF token. So split
|
Chris@0
|
893 up the HHVM token to make it looks like proper PHP.
|
Chris@0
|
894 */
|
Chris@0
|
895
|
Chris@0
|
896 if ($tokenIsArray === true
|
Chris@0
|
897 && $token[0] === T_ELSEIF
|
Chris@0
|
898 && strtolower($token[1]) !== 'elseif'
|
Chris@0
|
899 ) {
|
Chris@0
|
900 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
901 'content' => substr($token[1], 0, 4),
|
Chris@0
|
902 'code' => T_ELSE,
|
Chris@0
|
903 'type' => 'T_ELSE',
|
Chris@0
|
904 );
|
Chris@0
|
905
|
Chris@0
|
906 $newStackPtr++;
|
Chris@0
|
907 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
908 'content' => substr($token[1], 4, -2),
|
Chris@0
|
909 'code' => T_WHITESPACE,
|
Chris@0
|
910 'type' => 'T_WHITESPACE',
|
Chris@0
|
911 );
|
Chris@0
|
912
|
Chris@0
|
913 $newStackPtr++;
|
Chris@0
|
914 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
915 'content' => substr($token[1], -2),
|
Chris@0
|
916 'code' => T_IF,
|
Chris@0
|
917 'type' => 'T_IF',
|
Chris@0
|
918 );
|
Chris@0
|
919
|
Chris@0
|
920 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
921 echo "\t\t* token $stackPtr changed from T_ELSEIF to T_ELSE/T_WHITESPACE/T_IF".PHP_EOL;
|
Chris@0
|
922 }
|
Chris@0
|
923
|
Chris@0
|
924 $newStackPtr++;
|
Chris@0
|
925 continue;
|
Chris@0
|
926 }//end if
|
Chris@0
|
927
|
Chris@0
|
928 /*
|
Chris@0
|
929 HHVM 3.5 and 3.6 tokenizes a hashbang line such as #!/usr/bin/php
|
Chris@0
|
930 as T_HASHANG while PHP proper uses T_INLINE_HTML.
|
Chris@0
|
931 */
|
Chris@0
|
932
|
Chris@0
|
933 if ($tokenIsArray === true && token_name($token[0]) === 'T_HASHBANG') {
|
Chris@0
|
934 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
935 'content' => $token[1],
|
Chris@0
|
936 'code' => T_INLINE_HTML,
|
Chris@0
|
937 'type' => 'T_INLINE_HTML',
|
Chris@0
|
938 );
|
Chris@0
|
939
|
Chris@0
|
940 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
941 echo "\t\t* token $stackPtr changed from T_HASHBANG to T_INLINE_HTML".PHP_EOL;
|
Chris@0
|
942 }
|
Chris@0
|
943
|
Chris@0
|
944 $newStackPtr++;
|
Chris@0
|
945 continue;
|
Chris@0
|
946 }//end if
|
Chris@0
|
947
|
Chris@0
|
948 /*
|
Chris@0
|
949 If this token has newlines in its content, split each line up
|
Chris@0
|
950 and create a new token for each line. We do this so it's easier
|
Chris@0
|
951 to ascertain where errors occur on a line.
|
Chris@0
|
952 Note that $token[1] is the token's content.
|
Chris@0
|
953 */
|
Chris@0
|
954
|
Chris@0
|
955 if ($tokenIsArray === true && strpos($token[1], $eolChar) !== false) {
|
Chris@0
|
956 $tokenLines = explode($eolChar, $token[1]);
|
Chris@0
|
957 $numLines = count($tokenLines);
|
Chris@0
|
958 $newToken = array(
|
Chris@0
|
959 'type' => token_name($token[0]),
|
Chris@0
|
960 'code' => $token[0],
|
Chris@0
|
961 'content' => '',
|
Chris@0
|
962 );
|
Chris@0
|
963
|
Chris@0
|
964 for ($i = 0; $i < $numLines; $i++) {
|
Chris@0
|
965 $newToken['content'] = $tokenLines[$i];
|
Chris@0
|
966 if ($i === ($numLines - 1)) {
|
Chris@0
|
967 if ($tokenLines[$i] === '') {
|
Chris@0
|
968 break;
|
Chris@0
|
969 }
|
Chris@0
|
970 } else {
|
Chris@0
|
971 $newToken['content'] .= $eolChar;
|
Chris@0
|
972 }
|
Chris@0
|
973
|
Chris@0
|
974 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
975 $newStackPtr++;
|
Chris@0
|
976 }
|
Chris@0
|
977 } else {
|
Chris@0
|
978 if ($tokenIsArray === true && $token[0] === T_STRING) {
|
Chris@0
|
979 // Some T_STRING tokens should remain that way
|
Chris@0
|
980 // due to their context.
|
Chris@0
|
981 $context = array(
|
Chris@0
|
982 T_OBJECT_OPERATOR => true,
|
Chris@0
|
983 T_FUNCTION => true,
|
Chris@0
|
984 T_CLASS => true,
|
Chris@0
|
985 T_EXTENDS => true,
|
Chris@0
|
986 T_IMPLEMENTS => true,
|
Chris@0
|
987 T_NEW => true,
|
Chris@0
|
988 T_CONST => true,
|
Chris@0
|
989 T_NS_SEPARATOR => true,
|
Chris@0
|
990 T_USE => true,
|
Chris@0
|
991 T_NAMESPACE => true,
|
Chris@0
|
992 T_PAAMAYIM_NEKUDOTAYIM => true,
|
Chris@0
|
993 );
|
Chris@0
|
994 if (isset($context[$finalTokens[$lastNotEmptyToken]['code']]) === true) {
|
Chris@0
|
995 // Special case for syntax like: return new self
|
Chris@0
|
996 // where self should not be a string.
|
Chris@0
|
997 if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW
|
Chris@0
|
998 && strtolower($token[1]) === 'self'
|
Chris@0
|
999 ) {
|
Chris@0
|
1000 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
1001 'content' => $token[1],
|
Chris@0
|
1002 'code' => T_SELF,
|
Chris@0
|
1003 'type' => 'T_SELF',
|
Chris@0
|
1004 );
|
Chris@0
|
1005 } else {
|
Chris@0
|
1006 $finalTokens[$newStackPtr] = array(
|
Chris@0
|
1007 'content' => $token[1],
|
Chris@0
|
1008 'code' => T_STRING,
|
Chris@0
|
1009 'type' => 'T_STRING',
|
Chris@0
|
1010 );
|
Chris@0
|
1011 }
|
Chris@0
|
1012
|
Chris@0
|
1013 $newStackPtr++;
|
Chris@0
|
1014 continue;
|
Chris@0
|
1015 }//end if
|
Chris@0
|
1016 }//end if
|
Chris@0
|
1017
|
Chris@0
|
1018 $newToken = null;
|
Chris@0
|
1019 if ($tokenIsArray === false) {
|
Chris@0
|
1020 if (isset(self::$_resolveTokenCache[$token[0]]) === true) {
|
Chris@0
|
1021 $newToken = self::$_resolveTokenCache[$token[0]];
|
Chris@0
|
1022 }
|
Chris@0
|
1023 } else {
|
Chris@0
|
1024 $cacheKey = null;
|
Chris@0
|
1025 if ($token[0] === T_STRING) {
|
Chris@0
|
1026 $cacheKey = strtolower($token[1]);
|
Chris@0
|
1027 } else if ($token[0] !== T_CURLY_OPEN) {
|
Chris@0
|
1028 $cacheKey = $token[0];
|
Chris@0
|
1029 }
|
Chris@0
|
1030
|
Chris@0
|
1031 if ($cacheKey !== null && isset(self::$_resolveTokenCache[$cacheKey]) === true) {
|
Chris@0
|
1032 $newToken = self::$_resolveTokenCache[$cacheKey];
|
Chris@0
|
1033 $newToken['content'] = $token[1];
|
Chris@0
|
1034 }
|
Chris@0
|
1035 }
|
Chris@0
|
1036
|
Chris@0
|
1037 if ($newToken === null) {
|
Chris@0
|
1038 $newToken = self::standardiseToken($token);
|
Chris@0
|
1039 }
|
Chris@0
|
1040
|
Chris@0
|
1041 // Convert colons that are actually the ELSE component of an
|
Chris@0
|
1042 // inline IF statement.
|
Chris@0
|
1043 if (empty($insideInlineIf) === false && $newToken['code'] === T_COLON) {
|
Chris@0
|
1044 array_pop($insideInlineIf);
|
Chris@0
|
1045 $newToken['code'] = T_INLINE_ELSE;
|
Chris@0
|
1046 $newToken['type'] = 'T_INLINE_ELSE';
|
Chris@0
|
1047 }
|
Chris@0
|
1048
|
Chris@0
|
1049 // This is a special condition for T_ARRAY tokens used for
|
Chris@0
|
1050 // type hinting function arguments as being arrays. We want to keep
|
Chris@0
|
1051 // the parenthesis map clean, so let's tag these tokens as
|
Chris@0
|
1052 // T_ARRAY_HINT.
|
Chris@0
|
1053 if ($newToken['code'] === T_ARRAY) {
|
Chris@0
|
1054 for ($i = $stackPtr; $i < $numTokens; $i++) {
|
Chris@0
|
1055 if ($tokens[$i] === '(') {
|
Chris@0
|
1056 break;
|
Chris@0
|
1057 } else if ($tokens[$i][0] === T_VARIABLE) {
|
Chris@0
|
1058 $newToken['code'] = T_ARRAY_HINT;
|
Chris@0
|
1059 $newToken['type'] = 'T_ARRAY_HINT';
|
Chris@0
|
1060 break;
|
Chris@0
|
1061 }
|
Chris@0
|
1062 }
|
Chris@0
|
1063 }
|
Chris@0
|
1064
|
Chris@0
|
1065 // This is a special case when checking PHP 5.5+ code in PHP < 5.5
|
Chris@0
|
1066 // where "finally" should be T_FINALLY instead of T_STRING.
|
Chris@0
|
1067 if ($newToken['code'] === T_STRING
|
Chris@0
|
1068 && strtolower($newToken['content']) === 'finally'
|
Chris@0
|
1069 ) {
|
Chris@0
|
1070 $newToken['code'] = T_FINALLY;
|
Chris@0
|
1071 $newToken['type'] = 'T_FINALLY';
|
Chris@0
|
1072 }
|
Chris@0
|
1073
|
Chris@0
|
1074 // This is a special case for the PHP 5.5 classname::class syntax
|
Chris@0
|
1075 // where "class" should be T_STRING instead of T_CLASS.
|
Chris@0
|
1076 if (($newToken['code'] === T_CLASS
|
Chris@0
|
1077 || $newToken['code'] === T_FUNCTION)
|
Chris@0
|
1078 && $finalTokens[($newStackPtr - 1)]['code'] === T_DOUBLE_COLON
|
Chris@0
|
1079 ) {
|
Chris@0
|
1080 $newToken['code'] = T_STRING;
|
Chris@0
|
1081 $newToken['type'] = 'T_STRING';
|
Chris@0
|
1082 }
|
Chris@0
|
1083
|
Chris@0
|
1084 // This is a special case for PHP 5.6 use function and use const
|
Chris@0
|
1085 // where "function" and "const" should be T_STRING instead of T_FUNCTION
|
Chris@0
|
1086 // and T_CONST.
|
Chris@0
|
1087 if (($newToken['code'] === T_FUNCTION
|
Chris@0
|
1088 || $newToken['code'] === T_CONST)
|
Chris@0
|
1089 && $finalTokens[$lastNotEmptyToken]['code'] === T_USE
|
Chris@0
|
1090 ) {
|
Chris@0
|
1091 $newToken['code'] = T_STRING;
|
Chris@0
|
1092 $newToken['type'] = 'T_STRING';
|
Chris@0
|
1093 }
|
Chris@0
|
1094
|
Chris@0
|
1095 // This is a special case for use groups in PHP 7+ where leaving
|
Chris@0
|
1096 // the curly braces as their normal tokens would confuse
|
Chris@0
|
1097 // the scope map and sniffs.
|
Chris@0
|
1098 if ($newToken['code'] === T_OPEN_CURLY_BRACKET
|
Chris@0
|
1099 && $finalTokens[$lastNotEmptyToken]['code'] === T_NS_SEPARATOR
|
Chris@0
|
1100 ) {
|
Chris@0
|
1101 $newToken['code'] = T_OPEN_USE_GROUP;
|
Chris@0
|
1102 $newToken['type'] = 'T_OPEN_USE_GROUP';
|
Chris@0
|
1103 $insideUseGroup = true;
|
Chris@0
|
1104 }
|
Chris@0
|
1105
|
Chris@0
|
1106 if ($insideUseGroup === true && $newToken['code'] === T_CLOSE_CURLY_BRACKET) {
|
Chris@0
|
1107 $newToken['code'] = T_CLOSE_USE_GROUP;
|
Chris@0
|
1108 $newToken['type'] = 'T_CLOSE_USE_GROUP';
|
Chris@0
|
1109 $insideUseGroup = false;
|
Chris@0
|
1110 }
|
Chris@0
|
1111
|
Chris@0
|
1112 $finalTokens[$newStackPtr] = $newToken;
|
Chris@0
|
1113 $newStackPtr++;
|
Chris@0
|
1114 }//end if
|
Chris@0
|
1115 }//end for
|
Chris@0
|
1116
|
Chris@0
|
1117 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1118 echo "\t*** END PHP TOKENIZING ***".PHP_EOL;
|
Chris@0
|
1119 }
|
Chris@0
|
1120
|
Chris@0
|
1121 return $finalTokens;
|
Chris@0
|
1122
|
Chris@0
|
1123 }//end tokenizeString()
|
Chris@0
|
1124
|
Chris@0
|
1125
|
Chris@0
|
1126 /**
|
Chris@0
|
1127 * Performs additional processing after main tokenizing.
|
Chris@0
|
1128 *
|
Chris@0
|
1129 * This additional processing checks for CASE statements that are using curly
|
Chris@0
|
1130 * braces for scope openers and closers. It also turns some T_FUNCTION tokens
|
Chris@0
|
1131 * into T_CLOSURE when they are not standard function definitions. It also
|
Chris@0
|
1132 * detects short array syntax and converts those square brackets into new tokens.
|
Chris@0
|
1133 * It also corrects some usage of the static and class keywords. It also
|
Chris@0
|
1134 * assigns tokens to function return types.
|
Chris@0
|
1135 *
|
Chris@0
|
1136 * @param array $tokens The array of tokens to process.
|
Chris@0
|
1137 * @param string $eolChar The EOL character to use for splitting strings.
|
Chris@0
|
1138 *
|
Chris@0
|
1139 * @return void
|
Chris@0
|
1140 */
|
Chris@0
|
1141 public function processAdditional(&$tokens, $eolChar)
|
Chris@0
|
1142 {
|
Chris@0
|
1143 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1144 echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL;
|
Chris@0
|
1145 }
|
Chris@0
|
1146
|
Chris@0
|
1147 $numTokens = count($tokens);
|
Chris@0
|
1148 for ($i = ($numTokens - 1); $i >= 0; $i--) {
|
Chris@0
|
1149 // Check for any unset scope conditions due to alternate IF/ENDIF syntax.
|
Chris@0
|
1150 if (isset($tokens[$i]['scope_opener']) === true
|
Chris@0
|
1151 && isset($tokens[$i]['scope_condition']) === false
|
Chris@0
|
1152 ) {
|
Chris@0
|
1153 $tokens[$i]['scope_condition'] = $tokens[$tokens[$i]['scope_opener']]['scope_condition'];
|
Chris@0
|
1154 }
|
Chris@0
|
1155
|
Chris@0
|
1156 if ($tokens[$i]['code'] === T_FUNCTION) {
|
Chris@0
|
1157 /*
|
Chris@0
|
1158 Detect functions that are actually closures and
|
Chris@0
|
1159 assign them a different token.
|
Chris@0
|
1160 */
|
Chris@0
|
1161
|
Chris@0
|
1162 if (isset($tokens[$i]['scope_opener']) === true) {
|
Chris@0
|
1163 for ($x = ($i + 1); $x < $numTokens; $x++) {
|
Chris@0
|
1164 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false
|
Chris@0
|
1165 && $tokens[$x]['code'] !== T_BITWISE_AND
|
Chris@0
|
1166 ) {
|
Chris@0
|
1167 break;
|
Chris@0
|
1168 }
|
Chris@0
|
1169 }
|
Chris@0
|
1170
|
Chris@0
|
1171 if ($tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
|
Chris@0
|
1172 $tokens[$i]['code'] = T_CLOSURE;
|
Chris@0
|
1173 $tokens[$i]['type'] = 'T_CLOSURE';
|
Chris@0
|
1174 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1175 $line = $tokens[$i]['line'];
|
Chris@0
|
1176 echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL;
|
Chris@0
|
1177 }
|
Chris@0
|
1178
|
Chris@0
|
1179 for ($x = ($tokens[$i]['scope_opener'] + 1); $x < $tokens[$i]['scope_closer']; $x++) {
|
Chris@0
|
1180 if (isset($tokens[$x]['conditions'][$i]) === false) {
|
Chris@0
|
1181 continue;
|
Chris@0
|
1182 }
|
Chris@0
|
1183
|
Chris@0
|
1184 $tokens[$x]['conditions'][$i] = T_CLOSURE;
|
Chris@0
|
1185 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1186 $type = $tokens[$x]['type'];
|
Chris@0
|
1187 echo "\t\t* cleaned $x ($type) *".PHP_EOL;
|
Chris@0
|
1188 }
|
Chris@0
|
1189 }
|
Chris@0
|
1190 }
|
Chris@0
|
1191
|
Chris@0
|
1192 $tokenAfterReturnTypeHint = $tokens[$i]['scope_opener'];
|
Chris@0
|
1193 } else if (isset($tokens[$i]['parenthesis_closer']) === true) {
|
Chris@0
|
1194 $tokenAfterReturnTypeHint = null;
|
Chris@0
|
1195 for ($x = ($tokens[$i]['parenthesis_closer'] + 1); $x < $numTokens; $x++) {
|
Chris@0
|
1196 if ($tokens[$x]['code'] === T_SEMICOLON) {
|
Chris@0
|
1197 $tokenAfterReturnTypeHint = $x;
|
Chris@0
|
1198 break;
|
Chris@0
|
1199 }
|
Chris@0
|
1200 }
|
Chris@0
|
1201
|
Chris@0
|
1202 if ($tokenAfterReturnTypeHint === null) {
|
Chris@0
|
1203 // Probably a syntax error.
|
Chris@0
|
1204 continue;
|
Chris@0
|
1205 }
|
Chris@0
|
1206 } else {
|
Chris@0
|
1207 // Probably a syntax error.
|
Chris@0
|
1208 continue;
|
Chris@0
|
1209 }//end if
|
Chris@0
|
1210
|
Chris@0
|
1211 /*
|
Chris@0
|
1212 Detect function return values and assign them
|
Chris@0
|
1213 a special token, because PHP doesn't.
|
Chris@0
|
1214 */
|
Chris@0
|
1215
|
Chris@0
|
1216 for ($x = ($tokenAfterReturnTypeHint - 1); $x > $i; $x--) {
|
Chris@0
|
1217 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1218 if (in_array($tokens[$x]['code'], array(T_STRING, T_ARRAY, T_ARRAY_HINT, T_CALLABLE, T_SELF, T_PARENT), true) === true) {
|
Chris@0
|
1219 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1220 $line = $tokens[$x]['line'];
|
Chris@0
|
1221 $type = $tokens[$x]['type'];
|
Chris@0
|
1222 echo "\t* token $x on line $line changed from $type to T_RETURN_TYPE".PHP_EOL;
|
Chris@0
|
1223 }
|
Chris@0
|
1224
|
Chris@0
|
1225 $tokens[$x]['code'] = T_RETURN_TYPE;
|
Chris@0
|
1226 $tokens[$x]['type'] = 'T_RETURN_TYPE';
|
Chris@0
|
1227 }
|
Chris@0
|
1228
|
Chris@0
|
1229 break;
|
Chris@0
|
1230 }
|
Chris@0
|
1231 }
|
Chris@0
|
1232
|
Chris@0
|
1233 continue;
|
Chris@0
|
1234 } else if ($tokens[$i]['code'] === T_CLASS && isset($tokens[$i]['scope_opener']) === true) {
|
Chris@0
|
1235 /*
|
Chris@0
|
1236 Detect anonymous classes and assign them a different token.
|
Chris@0
|
1237 */
|
Chris@0
|
1238
|
Chris@0
|
1239 for ($x = ($i + 1); $x < $numTokens; $x++) {
|
Chris@0
|
1240 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1241 break;
|
Chris@0
|
1242 }
|
Chris@0
|
1243 }
|
Chris@0
|
1244
|
Chris@0
|
1245 if ($tokens[$x]['code'] === T_OPEN_PARENTHESIS
|
Chris@0
|
1246 || $tokens[$x]['code'] === T_OPEN_CURLY_BRACKET
|
Chris@0
|
1247 || $tokens[$x]['code'] === T_EXTENDS
|
Chris@0
|
1248 || $tokens[$x]['code'] === T_IMPLEMENTS
|
Chris@0
|
1249 ) {
|
Chris@0
|
1250 $tokens[$i]['code'] = T_ANON_CLASS;
|
Chris@0
|
1251 $tokens[$i]['type'] = 'T_ANON_CLASS';
|
Chris@0
|
1252 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1253 $line = $tokens[$i]['line'];
|
Chris@0
|
1254 echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL;
|
Chris@0
|
1255 }
|
Chris@0
|
1256
|
Chris@0
|
1257 for ($x = ($tokens[$i]['scope_opener'] + 1); $x < $tokens[$i]['scope_closer']; $x++) {
|
Chris@0
|
1258 if (isset($tokens[$x]['conditions'][$i]) === false) {
|
Chris@0
|
1259 continue;
|
Chris@0
|
1260 }
|
Chris@0
|
1261
|
Chris@0
|
1262 $tokens[$x]['conditions'][$i] = T_ANON_CLASS;
|
Chris@0
|
1263 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1264 $type = $tokens[$x]['type'];
|
Chris@0
|
1265 echo "\t\t* cleaned $x ($type) *".PHP_EOL;
|
Chris@0
|
1266 }
|
Chris@0
|
1267 }
|
Chris@0
|
1268 }
|
Chris@0
|
1269
|
Chris@0
|
1270 continue;
|
Chris@0
|
1271 } else if ($tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) {
|
Chris@0
|
1272 if (isset($tokens[$i]['bracket_closer']) === false) {
|
Chris@0
|
1273 continue;
|
Chris@0
|
1274 }
|
Chris@0
|
1275
|
Chris@0
|
1276 // Unless there is a variable or a bracket before this token,
|
Chris@0
|
1277 // it is the start of an array being defined using the short syntax.
|
Chris@0
|
1278 $isShortArray = false;
|
Chris@0
|
1279 $allowed = array(
|
Chris@0
|
1280 T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET,
|
Chris@0
|
1281 T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS,
|
Chris@0
|
1282 T_VARIABLE => T_VARIABLE,
|
Chris@0
|
1283 T_OBJECT_OPERATOR => T_OBJECT_OPERATOR,
|
Chris@0
|
1284 T_STRING => T_STRING,
|
Chris@0
|
1285 );
|
Chris@0
|
1286
|
Chris@0
|
1287 for ($x = ($i - 1); $x > 0; $x--) {
|
Chris@0
|
1288 // If we hit a scope opener, the statement has ended
|
Chris@0
|
1289 // without finding anything, so it's probably an array
|
Chris@0
|
1290 // using PHP 7.1 short list syntax.
|
Chris@0
|
1291 if (isset($tokens[$x]['scope_opener']) === true) {
|
Chris@0
|
1292 $isShortArray = true;
|
Chris@0
|
1293 break;
|
Chris@0
|
1294 }
|
Chris@0
|
1295
|
Chris@0
|
1296 if (isset($tokens[$x]['bracket_opener']) === true
|
Chris@0
|
1297 && $x > $tokens[$x]['bracket_opener']
|
Chris@0
|
1298 ) {
|
Chris@0
|
1299 $x = $tokens[$x]['bracket_opener'];
|
Chris@0
|
1300 continue;
|
Chris@0
|
1301 }
|
Chris@0
|
1302
|
Chris@0
|
1303 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1304 if (isset($allowed[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1305 $isShortArray = true;
|
Chris@0
|
1306 }
|
Chris@0
|
1307
|
Chris@0
|
1308 break;
|
Chris@0
|
1309 }
|
Chris@0
|
1310 }//end for
|
Chris@0
|
1311
|
Chris@0
|
1312 if ($isShortArray === true) {
|
Chris@0
|
1313 $tokens[$i]['code'] = T_OPEN_SHORT_ARRAY;
|
Chris@0
|
1314 $tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY';
|
Chris@0
|
1315
|
Chris@0
|
1316 $closer = $tokens[$i]['bracket_closer'];
|
Chris@0
|
1317 $tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY;
|
Chris@0
|
1318 $tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY';
|
Chris@0
|
1319 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1320 $line = $tokens[$i]['line'];
|
Chris@0
|
1321 echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL;
|
Chris@0
|
1322 $line = $tokens[$closer]['line'];
|
Chris@0
|
1323 echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL;
|
Chris@0
|
1324 }
|
Chris@0
|
1325 }
|
Chris@0
|
1326
|
Chris@0
|
1327 continue;
|
Chris@0
|
1328 } else if ($tokens[$i]['code'] === T_STATIC) {
|
Chris@0
|
1329 for ($x = ($i - 1); $x > 0; $x--) {
|
Chris@0
|
1330 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1331 break;
|
Chris@0
|
1332 }
|
Chris@0
|
1333 }
|
Chris@0
|
1334
|
Chris@0
|
1335 if ($tokens[$x]['code'] === T_INSTANCEOF) {
|
Chris@0
|
1336 $tokens[$i]['code'] = T_STRING;
|
Chris@0
|
1337 $tokens[$i]['type'] = 'T_STRING';
|
Chris@0
|
1338
|
Chris@0
|
1339 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1340 $line = $tokens[$i]['line'];
|
Chris@0
|
1341 echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL;
|
Chris@0
|
1342 }
|
Chris@0
|
1343 }
|
Chris@0
|
1344
|
Chris@0
|
1345 continue;
|
Chris@0
|
1346 } else if ($tokens[$i]['code'] === T_ECHO && $tokens[$i]['content'] === '<?=') {
|
Chris@0
|
1347 // HHVM tokenizes <?= as T_ECHO but it should be T_OPEN_TAG_WITH_ECHO.
|
Chris@0
|
1348 $tokens[$i]['code'] = T_OPEN_TAG_WITH_ECHO;
|
Chris@0
|
1349 $tokens[$i]['type'] = 'T_OPEN_TAG_WITH_ECHO';
|
Chris@0
|
1350
|
Chris@0
|
1351 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1352 $line = $tokens[$i]['line'];
|
Chris@0
|
1353 echo "\t* token $i on line $line changed from T_ECHO to T_OPEN_TAG_WITH_ECHO".PHP_EOL;
|
Chris@0
|
1354 }
|
Chris@0
|
1355 } else if ($tokens[$i]['code'] === T_TRUE
|
Chris@0
|
1356 || $tokens[$i]['code'] === T_FALSE
|
Chris@0
|
1357 || $tokens[$i]['code'] === T_NULL
|
Chris@0
|
1358 ) {
|
Chris@0
|
1359 for ($x = ($i + 1); $i < $numTokens; $x++) {
|
Chris@0
|
1360 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1361 // Non-whitespace content.
|
Chris@0
|
1362 break;
|
Chris@0
|
1363 }
|
Chris@0
|
1364 }
|
Chris@0
|
1365
|
Chris@0
|
1366 $context = array(
|
Chris@0
|
1367 T_OBJECT_OPERATOR => true,
|
Chris@0
|
1368 T_NS_SEPARATOR => true,
|
Chris@0
|
1369 T_PAAMAYIM_NEKUDOTAYIM => true,
|
Chris@0
|
1370 );
|
Chris@0
|
1371 if (isset($context[$tokens[$x]['code']]) === true) {
|
Chris@0
|
1372 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1373 $line = $tokens[$i]['line'];
|
Chris@0
|
1374 $type = $tokens[$i]['type'];
|
Chris@0
|
1375 echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL;
|
Chris@0
|
1376 }
|
Chris@0
|
1377
|
Chris@0
|
1378 $tokens[$i]['code'] = T_STRING;
|
Chris@0
|
1379 $tokens[$i]['type'] = 'T_STRING';
|
Chris@0
|
1380 }
|
Chris@0
|
1381 } else if ($tokens[$i]['code'] === T_CONST) {
|
Chris@0
|
1382 // Context sensitive keywords support.
|
Chris@0
|
1383 for ($x = ($i + 1); $i < $numTokens; $x++) {
|
Chris@0
|
1384 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1385 // Non-whitespace content.
|
Chris@0
|
1386 break;
|
Chris@0
|
1387 }
|
Chris@0
|
1388 }
|
Chris@0
|
1389
|
Chris@0
|
1390 if ($tokens[$x]['code'] !== T_STRING) {
|
Chris@0
|
1391 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1392 $line = $tokens[$x]['line'];
|
Chris@0
|
1393 $type = $tokens[$x]['type'];
|
Chris@0
|
1394 echo "\t* token $x on line $line changed from $type to T_STRING".PHP_EOL;
|
Chris@0
|
1395 }
|
Chris@0
|
1396
|
Chris@0
|
1397 $tokens[$x]['code'] = T_STRING;
|
Chris@0
|
1398 $tokens[$x]['type'] = 'T_STRING';
|
Chris@0
|
1399 }
|
Chris@0
|
1400 }//end if
|
Chris@0
|
1401
|
Chris@0
|
1402 if (($tokens[$i]['code'] !== T_CASE
|
Chris@0
|
1403 && $tokens[$i]['code'] !== T_DEFAULT)
|
Chris@0
|
1404 || isset($tokens[$i]['scope_opener']) === false
|
Chris@0
|
1405 ) {
|
Chris@0
|
1406 // Only interested in CASE and DEFAULT statements from here on in.
|
Chris@0
|
1407 continue;
|
Chris@0
|
1408 }
|
Chris@0
|
1409
|
Chris@0
|
1410 $scopeOpener = $tokens[$i]['scope_opener'];
|
Chris@0
|
1411 $scopeCloser = $tokens[$i]['scope_closer'];
|
Chris@0
|
1412
|
Chris@0
|
1413 // If the first char after the opener is a curly brace
|
Chris@0
|
1414 // and that brace has been ignored, it is actually
|
Chris@0
|
1415 // opening this case statement and the opener and closer are
|
Chris@0
|
1416 // probably set incorrectly.
|
Chris@0
|
1417 for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) {
|
Chris@0
|
1418 if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$tokens[$x]['code']]) === false) {
|
Chris@0
|
1419 // Non-whitespace content.
|
Chris@0
|
1420 break;
|
Chris@0
|
1421 }
|
Chris@0
|
1422 }
|
Chris@0
|
1423
|
Chris@0
|
1424 if ($tokens[$x]['code'] === T_CASE || $tokens[$x]['code'] === T_DEFAULT) {
|
Chris@0
|
1425 // Special case for multiple CASE statements that share the same
|
Chris@0
|
1426 // closer. Because we are going backwards through the file, this next
|
Chris@0
|
1427 // CASE/DEFAULT statement is already fixed, so just use its closer
|
Chris@0
|
1428 // and don't worry about fixing anything.
|
Chris@0
|
1429 $newCloser = $tokens[$x]['scope_closer'];
|
Chris@0
|
1430 $tokens[$i]['scope_closer'] = $newCloser;
|
Chris@0
|
1431 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1432 $oldType = $tokens[$scopeCloser]['type'];
|
Chris@0
|
1433 $newType = $tokens[$newCloser]['type'];
|
Chris@0
|
1434 $line = $tokens[$i]['line'];
|
Chris@0
|
1435 echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
|
Chris@0
|
1436 }
|
Chris@0
|
1437
|
Chris@0
|
1438 continue;
|
Chris@0
|
1439 }
|
Chris@0
|
1440
|
Chris@0
|
1441 if ($tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET
|
Chris@0
|
1442 || isset($tokens[$x]['scope_condition']) === true
|
Chris@0
|
1443 ) {
|
Chris@0
|
1444 // Not a CASE/DEFAULT with a curly brace opener.
|
Chris@0
|
1445 continue;
|
Chris@0
|
1446 }
|
Chris@0
|
1447
|
Chris@0
|
1448 // The closer for this CASE/DEFAULT should be the closing curly brace and
|
Chris@0
|
1449 // not whatever it already is. The opener needs to be the opening curly
|
Chris@0
|
1450 // brace so everything matches up.
|
Chris@0
|
1451 $newCloser = $tokens[$x]['bracket_closer'];
|
Chris@0
|
1452 foreach (array($i, $x, $newCloser) as $index) {
|
Chris@0
|
1453 $tokens[$index]['scope_condition'] = $i;
|
Chris@0
|
1454 $tokens[$index]['scope_opener'] = $x;
|
Chris@0
|
1455 $tokens[$index]['scope_closer'] = $newCloser;
|
Chris@0
|
1456 }
|
Chris@0
|
1457
|
Chris@0
|
1458 unset($tokens[$scopeOpener]['scope_condition']);
|
Chris@0
|
1459 unset($tokens[$scopeOpener]['scope_opener']);
|
Chris@0
|
1460 unset($tokens[$scopeOpener]['scope_closer']);
|
Chris@0
|
1461 unset($tokens[$scopeCloser]['scope_condition']);
|
Chris@0
|
1462 unset($tokens[$scopeCloser]['scope_opener']);
|
Chris@0
|
1463 unset($tokens[$scopeCloser]['scope_closer']);
|
Chris@0
|
1464 unset($tokens[$x]['bracket_opener']);
|
Chris@0
|
1465 unset($tokens[$x]['bracket_closer']);
|
Chris@0
|
1466 unset($tokens[$newCloser]['bracket_opener']);
|
Chris@0
|
1467 unset($tokens[$newCloser]['bracket_closer']);
|
Chris@0
|
1468 $tokens[$scopeCloser]['conditions'][] = $i;
|
Chris@0
|
1469
|
Chris@0
|
1470 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1471 $line = $tokens[$i]['line'];
|
Chris@0
|
1472 $tokenType = $tokens[$i]['type'];
|
Chris@0
|
1473
|
Chris@0
|
1474 $oldType = $tokens[$scopeOpener]['type'];
|
Chris@0
|
1475 $newType = $tokens[$x]['type'];
|
Chris@0
|
1476 echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL;
|
Chris@0
|
1477
|
Chris@0
|
1478 $oldType = $tokens[$scopeCloser]['type'];
|
Chris@0
|
1479 $newType = $tokens[$newCloser]['type'];
|
Chris@0
|
1480 echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
|
Chris@0
|
1481 }
|
Chris@0
|
1482
|
Chris@0
|
1483 // Now fix up all the tokens that think they are
|
Chris@0
|
1484 // inside the CASE/DEFAULT statement when they are really outside.
|
Chris@0
|
1485 for ($x = $newCloser; $x < $scopeCloser; $x++) {
|
Chris@0
|
1486 foreach ($tokens[$x]['conditions'] as $num => $oldCond) {
|
Chris@0
|
1487 if ($oldCond === $tokens[$i]['code']) {
|
Chris@0
|
1488 $oldConditions = $tokens[$x]['conditions'];
|
Chris@0
|
1489 unset($tokens[$x]['conditions'][$num]);
|
Chris@0
|
1490
|
Chris@0
|
1491 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1492 $type = $tokens[$x]['type'];
|
Chris@0
|
1493 $oldConds = '';
|
Chris@0
|
1494 foreach ($oldConditions as $condition) {
|
Chris@0
|
1495 $oldConds .= token_name($condition).',';
|
Chris@0
|
1496 }
|
Chris@0
|
1497
|
Chris@0
|
1498 $oldConds = rtrim($oldConds, ',');
|
Chris@0
|
1499
|
Chris@0
|
1500 $newConds = '';
|
Chris@0
|
1501 foreach ($tokens[$x]['conditions'] as $condition) {
|
Chris@0
|
1502 $newConds .= token_name($condition).',';
|
Chris@0
|
1503 }
|
Chris@0
|
1504
|
Chris@0
|
1505 $newConds = rtrim($newConds, ',');
|
Chris@0
|
1506
|
Chris@0
|
1507 echo "\t\t* cleaned $x ($type) *".PHP_EOL;
|
Chris@0
|
1508 echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL;
|
Chris@0
|
1509 }
|
Chris@0
|
1510
|
Chris@0
|
1511 break;
|
Chris@0
|
1512 }//end if
|
Chris@0
|
1513 }//end foreach
|
Chris@0
|
1514 }//end for
|
Chris@0
|
1515 }//end for
|
Chris@0
|
1516
|
Chris@0
|
1517 if (PHP_CODESNIFFER_VERBOSITY > 1) {
|
Chris@0
|
1518 echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL;
|
Chris@0
|
1519 }
|
Chris@0
|
1520
|
Chris@0
|
1521 }//end processAdditional()
|
Chris@0
|
1522
|
Chris@0
|
1523
|
Chris@0
|
1524 /**
|
Chris@0
|
1525 * Takes a token produced from <code>token_get_all()</code> and produces a
|
Chris@0
|
1526 * more uniform token.
|
Chris@0
|
1527 *
|
Chris@0
|
1528 * @param string|array $token The token to convert.
|
Chris@0
|
1529 *
|
Chris@0
|
1530 * @return array The new token.
|
Chris@0
|
1531 */
|
Chris@0
|
1532 public static function standardiseToken($token)
|
Chris@0
|
1533 {
|
Chris@0
|
1534 if (isset($token[1]) === false) {
|
Chris@0
|
1535 if (isset(self::$_resolveTokenCache[$token[0]]) === true) {
|
Chris@0
|
1536 return self::$_resolveTokenCache[$token[0]];
|
Chris@0
|
1537 }
|
Chris@0
|
1538 } else {
|
Chris@0
|
1539 $cacheKey = null;
|
Chris@0
|
1540 if ($token[0] === T_STRING) {
|
Chris@0
|
1541 $cacheKey = strtolower($token[1]);
|
Chris@0
|
1542 } else if ($token[0] !== T_CURLY_OPEN) {
|
Chris@0
|
1543 $cacheKey = $token[0];
|
Chris@0
|
1544 }
|
Chris@0
|
1545
|
Chris@0
|
1546 if ($cacheKey !== null && isset(self::$_resolveTokenCache[$cacheKey]) === true) {
|
Chris@0
|
1547 $newToken = self::$_resolveTokenCache[$cacheKey];
|
Chris@0
|
1548 $newToken['content'] = $token[1];
|
Chris@0
|
1549 return $newToken;
|
Chris@0
|
1550 }
|
Chris@0
|
1551 }
|
Chris@0
|
1552
|
Chris@0
|
1553 if (isset($token[1]) === false) {
|
Chris@0
|
1554 return self::resolveSimpleToken($token[0]);
|
Chris@0
|
1555 }
|
Chris@0
|
1556
|
Chris@0
|
1557 if ($token[0] === T_STRING) {
|
Chris@0
|
1558 switch ($cacheKey) {
|
Chris@0
|
1559 case 'false':
|
Chris@0
|
1560 $newToken['type'] = 'T_FALSE';
|
Chris@0
|
1561 break;
|
Chris@0
|
1562 case 'true':
|
Chris@0
|
1563 $newToken['type'] = 'T_TRUE';
|
Chris@0
|
1564 break;
|
Chris@0
|
1565 case 'null':
|
Chris@0
|
1566 $newToken['type'] = 'T_NULL';
|
Chris@0
|
1567 break;
|
Chris@0
|
1568 case 'self':
|
Chris@0
|
1569 $newToken['type'] = 'T_SELF';
|
Chris@0
|
1570 break;
|
Chris@0
|
1571 case 'parent':
|
Chris@0
|
1572 $newToken['type'] = 'T_PARENT';
|
Chris@0
|
1573 break;
|
Chris@0
|
1574 default:
|
Chris@0
|
1575 $newToken['type'] = 'T_STRING';
|
Chris@0
|
1576 break;
|
Chris@0
|
1577 }
|
Chris@0
|
1578
|
Chris@0
|
1579 $newToken['code'] = constant($newToken['type']);
|
Chris@0
|
1580
|
Chris@0
|
1581 self::$_resolveTokenCache[$cacheKey] = $newToken;
|
Chris@0
|
1582 } else if ($token[0] === T_CURLY_OPEN) {
|
Chris@0
|
1583 $newToken = array(
|
Chris@0
|
1584 'code' => T_OPEN_CURLY_BRACKET,
|
Chris@0
|
1585 'type' => 'T_OPEN_CURLY_BRACKET',
|
Chris@0
|
1586 );
|
Chris@0
|
1587 } else {
|
Chris@0
|
1588 $newToken = array(
|
Chris@0
|
1589 'code' => $token[0],
|
Chris@0
|
1590 'type' => token_name($token[0]),
|
Chris@0
|
1591 );
|
Chris@0
|
1592
|
Chris@0
|
1593 self::$_resolveTokenCache[$token[0]] = $newToken;
|
Chris@0
|
1594 }//end if
|
Chris@0
|
1595
|
Chris@0
|
1596 $newToken['content'] = $token[1];
|
Chris@0
|
1597 return $newToken;
|
Chris@0
|
1598
|
Chris@0
|
1599 }//end standardiseToken()
|
Chris@0
|
1600
|
Chris@0
|
1601
|
Chris@0
|
1602 /**
|
Chris@0
|
1603 * Converts simple tokens into a format that conforms to complex tokens
|
Chris@0
|
1604 * produced by token_get_all().
|
Chris@0
|
1605 *
|
Chris@0
|
1606 * Simple tokens are tokens that are not in array form when produced from
|
Chris@0
|
1607 * token_get_all().
|
Chris@0
|
1608 *
|
Chris@0
|
1609 * @param string $token The simple token to convert.
|
Chris@0
|
1610 *
|
Chris@0
|
1611 * @return array The new token in array format.
|
Chris@0
|
1612 */
|
Chris@0
|
1613 public static function resolveSimpleToken($token)
|
Chris@0
|
1614 {
|
Chris@0
|
1615 $newToken = array();
|
Chris@0
|
1616
|
Chris@0
|
1617 switch ($token) {
|
Chris@0
|
1618 case '{':
|
Chris@0
|
1619 $newToken['type'] = 'T_OPEN_CURLY_BRACKET';
|
Chris@0
|
1620 break;
|
Chris@0
|
1621 case '}':
|
Chris@0
|
1622 $newToken['type'] = 'T_CLOSE_CURLY_BRACKET';
|
Chris@0
|
1623 break;
|
Chris@0
|
1624 case '[':
|
Chris@0
|
1625 $newToken['type'] = 'T_OPEN_SQUARE_BRACKET';
|
Chris@0
|
1626 break;
|
Chris@0
|
1627 case ']':
|
Chris@0
|
1628 $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET';
|
Chris@0
|
1629 break;
|
Chris@0
|
1630 case '(':
|
Chris@0
|
1631 $newToken['type'] = 'T_OPEN_PARENTHESIS';
|
Chris@0
|
1632 break;
|
Chris@0
|
1633 case ')':
|
Chris@0
|
1634 $newToken['type'] = 'T_CLOSE_PARENTHESIS';
|
Chris@0
|
1635 break;
|
Chris@0
|
1636 case ':':
|
Chris@0
|
1637 $newToken['type'] = 'T_COLON';
|
Chris@0
|
1638 break;
|
Chris@0
|
1639 case '.':
|
Chris@0
|
1640 $newToken['type'] = 'T_STRING_CONCAT';
|
Chris@0
|
1641 break;
|
Chris@0
|
1642 case ';':
|
Chris@0
|
1643 $newToken['type'] = 'T_SEMICOLON';
|
Chris@0
|
1644 break;
|
Chris@0
|
1645 case '=':
|
Chris@0
|
1646 $newToken['type'] = 'T_EQUAL';
|
Chris@0
|
1647 break;
|
Chris@0
|
1648 case '*':
|
Chris@0
|
1649 $newToken['type'] = 'T_MULTIPLY';
|
Chris@0
|
1650 break;
|
Chris@0
|
1651 case '/':
|
Chris@0
|
1652 $newToken['type'] = 'T_DIVIDE';
|
Chris@0
|
1653 break;
|
Chris@0
|
1654 case '+':
|
Chris@0
|
1655 $newToken['type'] = 'T_PLUS';
|
Chris@0
|
1656 break;
|
Chris@0
|
1657 case '-':
|
Chris@0
|
1658 $newToken['type'] = 'T_MINUS';
|
Chris@0
|
1659 break;
|
Chris@0
|
1660 case '%':
|
Chris@0
|
1661 $newToken['type'] = 'T_MODULUS';
|
Chris@0
|
1662 break;
|
Chris@0
|
1663 case '^':
|
Chris@0
|
1664 $newToken['type'] = 'T_BITWISE_XOR';
|
Chris@0
|
1665 break;
|
Chris@0
|
1666 case '&':
|
Chris@0
|
1667 $newToken['type'] = 'T_BITWISE_AND';
|
Chris@0
|
1668 break;
|
Chris@0
|
1669 case '|':
|
Chris@0
|
1670 $newToken['type'] = 'T_BITWISE_OR';
|
Chris@0
|
1671 break;
|
Chris@0
|
1672 case '<':
|
Chris@0
|
1673 $newToken['type'] = 'T_LESS_THAN';
|
Chris@0
|
1674 break;
|
Chris@0
|
1675 case '>':
|
Chris@0
|
1676 $newToken['type'] = 'T_GREATER_THAN';
|
Chris@0
|
1677 break;
|
Chris@0
|
1678 case '!':
|
Chris@0
|
1679 $newToken['type'] = 'T_BOOLEAN_NOT';
|
Chris@0
|
1680 break;
|
Chris@0
|
1681 case ',':
|
Chris@0
|
1682 $newToken['type'] = 'T_COMMA';
|
Chris@0
|
1683 break;
|
Chris@0
|
1684 case '@':
|
Chris@0
|
1685 $newToken['type'] = 'T_ASPERAND';
|
Chris@0
|
1686 break;
|
Chris@0
|
1687 case '$':
|
Chris@0
|
1688 $newToken['type'] = 'T_DOLLAR';
|
Chris@0
|
1689 break;
|
Chris@0
|
1690 case '`':
|
Chris@0
|
1691 $newToken['type'] = 'T_BACKTICK';
|
Chris@0
|
1692 break;
|
Chris@0
|
1693 default:
|
Chris@0
|
1694 $newToken['type'] = 'T_NONE';
|
Chris@0
|
1695 break;
|
Chris@0
|
1696 }//end switch
|
Chris@0
|
1697
|
Chris@0
|
1698 $newToken['code'] = constant($newToken['type']);
|
Chris@0
|
1699 $newToken['content'] = $token;
|
Chris@0
|
1700
|
Chris@0
|
1701 self::$_resolveTokenCache[$token] = $newToken;
|
Chris@0
|
1702 return $newToken;
|
Chris@0
|
1703
|
Chris@0
|
1704 }//end resolveSimpleToken()
|
Chris@0
|
1705
|
Chris@0
|
1706
|
Chris@0
|
1707 }//end class
|