These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of PDepend. |
||
4 | * |
||
5 | * PHP Version 5 |
||
6 | * |
||
7 | * Copyright (c) 2008-2017 Manuel Pichler <[email protected]>. |
||
8 | * All rights reserved. |
||
9 | * |
||
10 | * Redistribution and use in source and binary forms, with or without |
||
11 | * modification, are permitted provided that the following conditions |
||
12 | * are met: |
||
13 | * |
||
14 | * * Redistributions of source code must retain the above copyright |
||
15 | * notice, this list of conditions and the following disclaimer. |
||
16 | * |
||
17 | * * Redistributions in binary form must reproduce the above copyright |
||
18 | * notice, this list of conditions and the following disclaimer in |
||
19 | * the documentation and/or other materials provided with the |
||
20 | * distribution. |
||
21 | * |
||
22 | * * Neither the name of Manuel Pichler nor the names of his |
||
23 | * contributors may be used to endorse or promote products derived |
||
24 | * from this software without specific prior written permission. |
||
25 | * |
||
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
27 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
28 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
29 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||
30 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
31 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||
32 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
33 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||
34 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||
36 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
37 | * POSSIBILITY OF SUCH DAMAGE. |
||
38 | * |
||
39 | * @copyright 2008-2017 Manuel Pichler. All rights reserved. |
||
40 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
||
41 | */ |
||
42 | |||
43 | namespace PDepend\Source\Language\PHP; |
||
44 | |||
45 | use PDepend\Source\AST\ASTCompilationUnit; |
||
46 | use PDepend\Source\Tokenizer\Token; |
||
47 | use PDepend\Source\Tokenizer\Tokenizer; |
||
48 | use PDepend\Source\Tokenizer\Tokens; |
||
49 | |||
50 | /** |
||
51 | * Define PHP 5.4 __TRAIT__ token constant. |
||
52 | */ |
||
53 | if (!defined('T_TRAIT_C')) { |
||
54 | define('T_TRAIT_C', 42000); |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * Define PHP 5.4 'trait' token constant. |
||
59 | */ |
||
60 | if (!defined('T_TRAIT')) { |
||
61 | define('T_TRAIT', 42001); |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * Define PHP 5.4 'insteadof' token constant. |
||
66 | */ |
||
67 | if (!defined('T_INSTEADOF')) { |
||
68 | define('T_INSTEADOF', 42002); |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Define PHP 5.3 __NAMESPACE__ token constant. |
||
73 | */ |
||
74 | if (!defined('T_NS_C')) { |
||
75 | define('T_NS_C', 42003); |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Define PHP 5.3 'use' token constant |
||
80 | */ |
||
81 | if (!defined('T_USE')) { |
||
82 | define('T_USE', 42004); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Define PHP 5.3 'namespace' token constant. |
||
87 | */ |
||
88 | if (!defined('T_NAMESPACE')) { |
||
89 | define('T_NAMESPACE', 42005); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Define PHP 5.6 '...' token constant |
||
94 | */ |
||
95 | if (!defined('T_ELLIPSIS')) { |
||
96 | define('T_ELLIPSIS', 42006); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Define PHP 5.3's '__DIR__' token constant. |
||
101 | */ |
||
102 | if (!defined('T_DIR')) { |
||
103 | define('T_DIR', 42006); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Define PHP 5.3's 'T_GOTO' token constant. |
||
108 | */ |
||
109 | if (!defined('T_GOTO')) { |
||
110 | define('T_GOTO', 42007); |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * Define PHP 5.4's 'T_CALLABLE' token constant |
||
115 | */ |
||
116 | if (!defined('T_CALLABLE')) { |
||
117 | define('T_CALLABLE', 42008); |
||
118 | } |
||
119 | |||
120 | /** |
||
121 | * Define PHP 5.5's 'T_YIELD' token constant |
||
122 | */ |
||
123 | if (!defined('T_YIELD')) { |
||
124 | define('T_YIELD', 42009); |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * Define PHP 5,5's 'T_FINALLY' token constant |
||
129 | */ |
||
130 | if (!defined('T_FINALLY')) { |
||
131 | define('T_FINALLY', 42010); |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Define character token that was removed in PHP 7 |
||
136 | */ |
||
137 | if (!defined('T_CHARACTER')) { |
||
138 | define('T_CHARACTER', 42011); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Define bad character token that was removed in PHP 7 |
||
143 | */ |
||
144 | if (!defined('T_BAD_CHARACTER')) { |
||
145 | define('T_BAD_CHARACTER', 42012); |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Define PHP 7's '<=>' token constant |
||
150 | */ |
||
151 | if (!defined('T_SPACESHIP')) { |
||
152 | define('T_SPACESHIP', 42013); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Define PHP 7's '??' token constant |
||
157 | */ |
||
158 | if (!defined('T_COALESCE')) { |
||
159 | define('T_COALESCE', 42014); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Define PHP 7's '**' token constant |
||
164 | */ |
||
165 | if (!defined('T_POW')) { |
||
166 | define('T_POW', 42015); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * This tokenizer uses the internal {@link token_get_all()} function as token stream |
||
171 | * generator. |
||
172 | * |
||
173 | * @copyright 2008-2017 Manuel Pichler. All rights reserved. |
||
174 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
||
175 | */ |
||
176 | class PHPTokenizerInternal implements Tokenizer |
||
177 | { |
||
178 | /** |
||
179 | * Mapping between php internal tokens and php depend tokens. |
||
180 | * |
||
181 | * @var array<integer, integer> |
||
182 | */ |
||
183 | protected static $tokenMap = array( |
||
184 | T_AS => Tokens::T_AS, |
||
185 | T_DO => Tokens::T_DO, |
||
186 | T_IF => Tokens::T_IF, |
||
187 | T_SL => Tokens::T_SL, |
||
188 | T_SR => Tokens::T_SR, |
||
189 | T_DEC => Tokens::T_DEC, |
||
190 | T_FOR => Tokens::T_FOR, |
||
191 | T_INC => Tokens::T_INC, |
||
192 | T_NEW => Tokens::T_NEW, |
||
193 | T_POW => Tokens::T_POW, |
||
194 | T_TRY => Tokens::T_TRY, |
||
195 | T_USE => Tokens::T_USE, |
||
196 | T_VAR => Tokens::T_VAR, |
||
197 | T_CASE => Tokens::T_CASE, |
||
198 | T_ECHO => Tokens::T_ECHO, |
||
199 | T_ELSE => Tokens::T_ELSE, |
||
200 | T_EVAL => Tokens::T_EVAL, |
||
201 | T_EXIT => Tokens::T_EXIT, |
||
202 | T_FILE => Tokens::T_FILE, |
||
203 | T_GOTO => Tokens::T_GOTO, |
||
204 | T_LINE => Tokens::T_LINE, |
||
205 | T_LIST => Tokens::T_LIST, |
||
206 | T_NS_C => Tokens::T_NS_C, |
||
207 | T_ARRAY => Tokens::T_ARRAY, |
||
208 | T_BREAK => Tokens::T_BREAK, |
||
209 | T_CLASS => Tokens::T_CLASS, |
||
210 | T_CATCH => Tokens::T_CATCH, |
||
211 | T_CLONE => Tokens::T_CLONE, |
||
212 | T_CONST => Tokens::T_CONST, |
||
213 | T_EMPTY => Tokens::T_EMPTY, |
||
214 | T_ENDIF => Tokens::T_ENDIF, |
||
215 | T_FINAL => Tokens::T_FINAL, |
||
216 | T_ISSET => Tokens::T_ISSET, |
||
217 | T_PRINT => Tokens::T_PRINT, |
||
218 | T_THROW => Tokens::T_THROW, |
||
219 | T_TRAIT => Tokens::T_TRAIT, |
||
220 | T_UNSET => Tokens::T_UNSET, |
||
221 | T_WHILE => Tokens::T_WHILE, |
||
222 | T_ENDFOR => Tokens::T_ENDFOR, |
||
223 | T_ELSEIF => Tokens::T_ELSEIF, |
||
224 | T_FUNC_C => Tokens::T_FUNC_C, |
||
225 | T_GLOBAL => Tokens::T_GLOBAL, |
||
226 | T_PUBLIC => Tokens::T_PUBLIC, |
||
227 | T_RETURN => Tokens::T_RETURN, |
||
228 | T_STATIC => Tokens::T_STATIC, |
||
229 | T_STRING => Tokens::T_STRING, |
||
230 | T_SWITCH => Tokens::T_SWITCH, |
||
231 | T_CLASS_C => Tokens::T_CLASS_C, |
||
232 | T_COMMENT => Tokens::T_COMMENT, |
||
233 | T_DECLARE => Tokens::T_DECLARE, |
||
234 | T_DEFAULT => Tokens::T_DEFAULT, |
||
235 | T_DNUMBER => Tokens::T_DNUMBER, |
||
236 | T_EXTENDS => Tokens::T_EXTENDS, |
||
237 | T_FOREACH => Tokens::T_FOREACH, |
||
238 | T_INCLUDE => Tokens::T_INCLUDE, |
||
239 | T_LNUMBER => Tokens::T_LNUMBER, |
||
240 | T_PRIVATE => Tokens::T_PRIVATE, |
||
241 | T_REQUIRE => Tokens::T_REQUIRE, |
||
242 | T_TRAIT_C => Tokens::T_TRAIT_C, |
||
243 | T_ABSTRACT => Tokens::T_ABSTRACT, |
||
244 | T_CALLABLE => Tokens::T_CALLABLE, |
||
245 | T_ENDWHILE => Tokens::T_ENDWHILE, |
||
246 | T_FUNCTION => Tokens::T_FUNCTION, |
||
247 | T_INT_CAST => Tokens::T_INT_CAST, |
||
248 | T_IS_EQUAL => Tokens::T_IS_EQUAL, |
||
249 | T_OR_EQUAL => Tokens::T_OR_EQUAL, |
||
250 | T_CONTINUE => Tokens::T_CONTINUE, |
||
251 | T_METHOD_C => Tokens::T_METHOD_C, |
||
252 | T_ELLIPSIS => Tokens::T_ELLIPSIS, |
||
253 | T_OPEN_TAG => Tokens::T_OPEN_TAG, |
||
254 | T_SL_EQUAL => Tokens::T_SL_EQUAL, |
||
255 | T_SR_EQUAL => Tokens::T_SR_EQUAL, |
||
256 | T_VARIABLE => Tokens::T_VARIABLE, |
||
257 | T_ENDSWITCH => Tokens::T_ENDSWITCH, |
||
258 | T_DIV_EQUAL => Tokens::T_DIV_EQUAL, |
||
259 | T_AND_EQUAL => Tokens::T_AND_EQUAL, |
||
260 | T_MOD_EQUAL => Tokens::T_MOD_EQUAL, |
||
261 | T_MUL_EQUAL => Tokens::T_MUL_EQUAL, |
||
262 | T_NAMESPACE => Tokens::T_NAMESPACE, |
||
263 | T_XOR_EQUAL => Tokens::T_XOR_EQUAL, |
||
264 | T_INTERFACE => Tokens::T_INTERFACE, |
||
265 | T_BOOL_CAST => Tokens::T_BOOL_CAST, |
||
266 | T_CHARACTER => Tokens::T_CHARACTER, |
||
267 | T_CLOSE_TAG => Tokens::T_CLOSE_TAG, |
||
268 | T_INSTEADOF => Tokens::T_INSTEADOF, |
||
269 | T_PROTECTED => Tokens::T_PROTECTED, |
||
270 | T_SPACESHIP => Tokens::T_SPACESHIP, |
||
271 | T_CURLY_OPEN => Tokens::T_CURLY_BRACE_OPEN, |
||
272 | T_ENDFOREACH => Tokens::T_ENDFOREACH, |
||
273 | T_ENDDECLARE => Tokens::T_ENDDECLARE, |
||
274 | T_IMPLEMENTS => Tokens::T_IMPLEMENTS, |
||
275 | T_NUM_STRING => Tokens::T_NUM_STRING, |
||
276 | T_PLUS_EQUAL => Tokens::T_PLUS_EQUAL, |
||
277 | T_ARRAY_CAST => Tokens::T_ARRAY_CAST, |
||
278 | T_BOOLEAN_OR => Tokens::T_BOOLEAN_OR, |
||
279 | T_INSTANCEOF => Tokens::T_INSTANCEOF, |
||
280 | T_LOGICAL_OR => Tokens::T_LOGICAL_OR, |
||
281 | T_UNSET_CAST => Tokens::T_UNSET_CAST, |
||
282 | T_DOC_COMMENT => Tokens::T_DOC_COMMENT, |
||
283 | T_END_HEREDOC => Tokens::T_END_HEREDOC, |
||
284 | T_MINUS_EQUAL => Tokens::T_MINUS_EQUAL, |
||
285 | T_BOOLEAN_AND => Tokens::T_BOOLEAN_AND, |
||
286 | T_DOUBLE_CAST => Tokens::T_DOUBLE_CAST, |
||
287 | T_INLINE_HTML => Tokens::T_INLINE_HTML, |
||
288 | T_LOGICAL_AND => Tokens::T_LOGICAL_AND, |
||
289 | T_LOGICAL_XOR => Tokens::T_LOGICAL_XOR, |
||
290 | T_OBJECT_CAST => Tokens::T_OBJECT_CAST, |
||
291 | T_STRING_CAST => Tokens::T_STRING_CAST, |
||
292 | T_DOUBLE_ARROW => Tokens::T_DOUBLE_ARROW, |
||
293 | T_INCLUDE_ONCE => Tokens::T_INCLUDE_ONCE, |
||
294 | T_IS_IDENTICAL => Tokens::T_IS_IDENTICAL, |
||
295 | T_DOUBLE_COLON => Tokens::T_DOUBLE_COLON, |
||
296 | T_CONCAT_EQUAL => Tokens::T_CONCAT_EQUAL, |
||
297 | T_IS_NOT_EQUAL => Tokens::T_IS_NOT_EQUAL, |
||
298 | T_REQUIRE_ONCE => Tokens::T_REQUIRE_ONCE, |
||
299 | T_BAD_CHARACTER => Tokens::T_BAD_CHARACTER, |
||
300 | T_HALT_COMPILER => Tokens::T_HALT_COMPILER, |
||
301 | T_START_HEREDOC => Tokens::T_START_HEREDOC, |
||
302 | T_STRING_VARNAME => Tokens::T_STRING_VARNAME, |
||
303 | T_OBJECT_OPERATOR => Tokens::T_OBJECT_OPERATOR, |
||
304 | T_IS_NOT_IDENTICAL => Tokens::T_IS_NOT_IDENTICAL, |
||
305 | T_OPEN_TAG_WITH_ECHO => Tokens::T_OPEN_TAG_WITH_ECHO, |
||
306 | T_IS_GREATER_OR_EQUAL => Tokens::T_IS_GREATER_OR_EQUAL, |
||
307 | T_IS_SMALLER_OR_EQUAL => Tokens::T_IS_SMALLER_OR_EQUAL, |
||
308 | //T_PAAMAYIM_NEKUDOTAYIM => Tokens::T_DOUBLE_COLON, |
||
309 | T_ENCAPSED_AND_WHITESPACE => Tokens::T_ENCAPSED_AND_WHITESPACE, |
||
310 | T_CONSTANT_ENCAPSED_STRING => Tokens::T_CONSTANT_ENCAPSED_STRING, |
||
311 | T_YIELD => Tokens::T_YIELD, |
||
312 | T_FINALLY => Tokens::T_FINALLY, |
||
313 | T_COALESCE => Tokens::T_COALESCE, |
||
314 | //T_DOLLAR_OPEN_CURLY_BRACES => Tokens::T_CURLY_BRACE_OPEN, |
||
315 | ); |
||
316 | |||
317 | /** |
||
318 | * Internally used transition token. |
||
319 | */ |
||
320 | const T_ELLIPSIS = 23006; |
||
321 | |||
322 | /** |
||
323 | * Mapping between php internal text tokens an php depend numeric tokens. |
||
324 | * |
||
325 | * @var array<string, integer> |
||
326 | */ |
||
327 | protected static $literalMap = array( |
||
328 | '@' => Tokens::T_AT, |
||
329 | '/' => Tokens::T_DIV, |
||
330 | '%' => Tokens::T_MOD, |
||
331 | '*' => Tokens::T_MUL, |
||
332 | '+' => Tokens::T_PLUS, |
||
333 | ':' => Tokens::T_COLON, |
||
334 | ',' => Tokens::T_COMMA, |
||
335 | '=' => Tokens::T_EQUAL, |
||
336 | '-' => Tokens::T_MINUS, |
||
337 | '.' => Tokens::T_CONCAT, |
||
338 | '$' => Tokens::T_DOLLAR, |
||
339 | '`' => Tokens::T_BACKTICK, |
||
340 | '\\' => Tokens::T_BACKSLASH, |
||
341 | ';' => Tokens::T_SEMICOLON, |
||
342 | '|' => Tokens::T_BITWISE_OR, |
||
343 | '&' => Tokens::T_BITWISE_AND, |
||
344 | '~' => Tokens::T_BITWISE_NOT, |
||
345 | '^' => Tokens::T_BITWISE_XOR, |
||
346 | '"' => Tokens::T_DOUBLE_QUOTE, |
||
347 | '?' => Tokens::T_QUESTION_MARK, |
||
348 | '!' => Tokens::T_EXCLAMATION_MARK, |
||
349 | '{' => Tokens::T_CURLY_BRACE_OPEN, |
||
350 | '}' => Tokens::T_CURLY_BRACE_CLOSE, |
||
351 | '(' => Tokens::T_PARENTHESIS_OPEN, |
||
352 | ')' => Tokens::T_PARENTHESIS_CLOSE, |
||
353 | '<' => Tokens::T_ANGLE_BRACKET_OPEN, |
||
354 | '>' => Tokens::T_ANGLE_BRACKET_CLOSE, |
||
355 | '[' => Tokens::T_SQUARED_BRACKET_OPEN, |
||
356 | ']' => Tokens::T_SQUARED_BRACKET_CLOSE, |
||
357 | 'use' => Tokens::T_USE, |
||
358 | 'goto' => Tokens::T_GOTO, |
||
359 | 'null' => Tokens::T_NULL, |
||
360 | 'self' => Tokens::T_SELF, |
||
361 | 'true' => Tokens::T_TRUE, |
||
362 | 'array' => Tokens::T_ARRAY, |
||
363 | 'false' => Tokens::T_FALSE, |
||
364 | 'trait' => Tokens::T_TRAIT, |
||
365 | 'yield' => Tokens::T_YIELD, |
||
366 | 'yield from' => Tokens::T_YIELD, |
||
367 | 'parent' => Tokens::T_PARENT, |
||
368 | 'finally' => Tokens::T_FINALLY, |
||
369 | 'callable' => Tokens::T_CALLABLE, |
||
370 | 'insteadof' => Tokens::T_INSTEADOF, |
||
371 | 'namespace' => Tokens::T_NAMESPACE, |
||
372 | '__dir__' => Tokens::T_DIR, |
||
373 | '__trait__' => Tokens::T_TRAIT_C, |
||
374 | '__namespace__' => Tokens::T_NS_C, |
||
375 | ); |
||
376 | |||
377 | /** |
||
378 | * |
||
379 | * @var array<mixed, array> |
||
380 | */ |
||
381 | protected static $substituteTokens = array( |
||
382 | T_DOLLAR_OPEN_CURLY_BRACES => array('$', '{'), |
||
383 | ); |
||
384 | |||
385 | /** |
||
386 | * BuilderContext sensitive alternative mappings. |
||
387 | * |
||
388 | * @var array<integer, array> |
||
389 | */ |
||
390 | protected static $alternativeMap = array( |
||
391 | Tokens::T_USE => array( |
||
392 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
393 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
394 | Tokens::T_CONST => Tokens::T_STRING, |
||
395 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
396 | ), |
||
397 | |||
398 | Tokens::T_GOTO => array( |
||
399 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
400 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
401 | Tokens::T_CONST => Tokens::T_STRING, |
||
402 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
403 | ), |
||
404 | |||
405 | Tokens::T_NULL => array( |
||
406 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
407 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
408 | Tokens::T_CONST => Tokens::T_STRING, |
||
409 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
410 | ), |
||
411 | |||
412 | Tokens::T_SELF => array( |
||
413 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
414 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
415 | Tokens::T_CONST => Tokens::T_STRING, |
||
416 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
417 | ), |
||
418 | |||
419 | Tokens::T_TRUE => array( |
||
420 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
421 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
422 | Tokens::T_NAMESPACE => Tokens::T_STRING, |
||
423 | Tokens::T_CONST => Tokens::T_STRING, |
||
424 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
425 | ), |
||
426 | |||
427 | Tokens::T_ARRAY => array( |
||
428 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
429 | ), |
||
430 | |||
431 | Tokens::T_FALSE => array( |
||
432 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
433 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
434 | Tokens::T_NAMESPACE => Tokens::T_STRING, |
||
435 | Tokens::T_CONST => Tokens::T_STRING, |
||
436 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
437 | ), |
||
438 | |||
439 | Tokens::T_NAMESPACE => array( |
||
440 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
441 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
442 | Tokens::T_CONST => Tokens::T_STRING, |
||
443 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
444 | ), |
||
445 | |||
446 | Tokens::T_DIR => array( |
||
447 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
448 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
449 | Tokens::T_CONST => Tokens::T_STRING, |
||
450 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
451 | ), |
||
452 | |||
453 | Tokens::T_NS_C => array( |
||
454 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
455 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
456 | Tokens::T_CONST => Tokens::T_STRING, |
||
457 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
458 | ), |
||
459 | |||
460 | Tokens::T_PARENT => array( |
||
461 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
462 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
463 | Tokens::T_CONST => Tokens::T_STRING, |
||
464 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
465 | ), |
||
466 | |||
467 | Tokens::T_FINALLY => array( |
||
468 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
469 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
470 | Tokens::T_CONST => Tokens::T_STRING, |
||
471 | Tokens::T_FUNCTION => Tokens::T_STRING, |
||
472 | ), |
||
473 | |||
474 | Tokens::T_CALLABLE => array( |
||
475 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
476 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
477 | ), |
||
478 | |||
479 | Tokens::T_LIST => array( |
||
480 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
481 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
482 | ), |
||
483 | |||
484 | Tokens::T_EMPTY => array( |
||
485 | Tokens::T_OBJECT_OPERATOR => Tokens::T_STRING, |
||
486 | Tokens::T_DOUBLE_COLON => Tokens::T_STRING, |
||
487 | ), |
||
488 | |||
489 | Tokens::T_CLASS => array( |
||
490 | Tokens::T_DOUBLE_COLON => Tokens::T_CLASS_FQN, |
||
491 | ), |
||
492 | ); |
||
493 | |||
494 | protected static $reductionMap = array( |
||
495 | Tokens::T_CONCAT => array( |
||
496 | Tokens::T_CONCAT => array( |
||
497 | 'type' => self::T_ELLIPSIS, |
||
498 | 'image' => '..', |
||
499 | ), |
||
500 | self::T_ELLIPSIS => array( |
||
501 | 'type' => Tokens::T_ELLIPSIS, |
||
502 | 'image' => '...', |
||
503 | ) |
||
504 | ), |
||
505 | |||
506 | Tokens::T_ANGLE_BRACKET_CLOSE => array( |
||
507 | Tokens::T_IS_SMALLER_OR_EQUAL => array( |
||
508 | 'type' => Tokens::T_SPACESHIP, |
||
509 | 'image' => '<=>', |
||
510 | ) |
||
511 | ), |
||
512 | |||
513 | Tokens::T_QUESTION_MARK => array( |
||
514 | Tokens::T_QUESTION_MARK => array( |
||
515 | 'type' => Tokens::T_COALESCE, |
||
516 | 'image' => '??', |
||
517 | ) |
||
518 | ), |
||
519 | |||
520 | Tokens::T_MUL => array( |
||
521 | Tokens::T_MUL => array( |
||
522 | 'type' => Tokens::T_POW, |
||
523 | 'image' => '**', |
||
524 | ) |
||
525 | ), |
||
526 | ); |
||
527 | |||
528 | /** |
||
529 | * The source file instance. |
||
530 | * |
||
531 | * @var \PDepend\Source\AST\ASTCompilationUnit |
||
532 | */ |
||
533 | protected $sourceFile = ''; |
||
534 | |||
535 | /** |
||
536 | * Count of all tokens. |
||
537 | * |
||
538 | * @var integer |
||
539 | */ |
||
540 | protected $count = 0; |
||
541 | |||
542 | /** |
||
543 | * Internal stream pointer index. |
||
544 | * |
||
545 | * @var integer |
||
546 | */ |
||
547 | protected $index = 0; |
||
548 | |||
549 | /** |
||
550 | * Prepared token list. |
||
551 | * |
||
552 | * @var Token[]|null |
||
553 | */ |
||
554 | protected $tokens = null; |
||
555 | |||
556 | /** |
||
557 | * The next free identifier for unknown string tokens. |
||
558 | * |
||
559 | * @var integer |
||
560 | */ |
||
561 | private $unknownTokenID = 1000; |
||
562 | |||
563 | /** |
||
564 | * Returns the name of the source file. |
||
565 | * |
||
566 | * @return \PDepend\Source\AST\ASTCompilationUnit |
||
567 | */ |
||
568 | public function getSourceFile() |
||
569 | { |
||
570 | return $this->sourceFile; |
||
571 | } |
||
572 | |||
573 | /** |
||
574 | * Sets a new php source file. |
||
575 | * |
||
576 | * @param string $sourceFile A php source file. |
||
577 | * |
||
578 | * @return void |
||
579 | */ |
||
580 | 28 | public function setSourceFile($sourceFile) |
|
581 | { |
||
582 | 28 | $this->tokens = null; |
|
583 | 28 | $this->sourceFile = new ASTCompilationUnit($sourceFile); |
|
584 | 28 | } |
|
585 | |||
586 | /** |
||
587 | * Returns the next token or {@link \PDepend\Source\Tokenizer\Tokenizer::T_EOF} if |
||
588 | * there is no next token. |
||
589 | * |
||
590 | * @return Token|integer |
||
591 | */ |
||
592 | 26 | View Code Duplication | public function next() |
593 | { |
||
594 | 26 | $this->tokenize(); |
|
595 | |||
596 | 26 | if ($this->index < $this->count) { |
|
597 | 26 | return $this->tokens[$this->index++]; |
|
598 | } |
||
599 | 26 | return self::T_EOF; |
|
600 | } |
||
601 | |||
602 | /** |
||
603 | * Returns the next token type or {@link \PDepend\Source\Tokenizer\Tokenizer::T_EOF} if |
||
604 | * there is no next token. |
||
605 | * |
||
606 | * @return integer |
||
607 | */ |
||
608 | View Code Duplication | public function peek() |
|
609 | { |
||
610 | $this->tokenize(); |
||
611 | |||
612 | if (isset($this->tokens[$this->index])) { |
||
613 | return $this->tokens[$this->index]->type; |
||
614 | } |
||
615 | return self::T_EOF; |
||
616 | } |
||
617 | |||
618 | /** |
||
619 | * Returns the type of next token, after the current token. This method |
||
620 | * ignores all comments between the current and the next token. |
||
621 | * |
||
622 | * @return integer |
||
623 | * @since 0.9.12 |
||
624 | */ |
||
625 | public function peekNext() |
||
626 | { |
||
627 | $this->tokenize(); |
||
628 | |||
629 | $offset = 0; |
||
630 | do { |
||
631 | $type = $this->tokens[$this->index + ++$offset]->type; |
||
632 | } while ($type == Tokens::T_COMMENT || $type == Tokens::T_DOC_COMMENT); |
||
633 | return $type; |
||
634 | } |
||
635 | |||
636 | /** |
||
637 | * Returns the previous token type or {@link \PDepend\Source\Tokenizer\Tokenizer::T_BOF} |
||
638 | * if there is no previous token. |
||
639 | * |
||
640 | * @return integer |
||
641 | */ |
||
642 | 2 | View Code Duplication | public function prev() |
643 | { |
||
644 | 2 | $this->tokenize(); |
|
645 | |||
646 | 2 | if ($this->index > 1) { |
|
647 | return $this->tokens[$this->index - 2]->type; |
||
648 | } |
||
649 | 2 | return self::T_BOF; |
|
650 | } |
||
651 | |||
652 | /** |
||
653 | * This method takes an array of tokens returned by <b>token_get_all()</b> |
||
654 | * and substitutes some of the tokens with those required by PDepend's |
||
655 | * parser implementation. |
||
656 | * |
||
657 | * @param array<array> $tokens Unprepared array of php tokens. |
||
658 | * |
||
659 | * @return array<array> |
||
660 | */ |
||
661 | 28 | private function substituteTokens(array $tokens) |
|
662 | { |
||
663 | 28 | $result = array(); |
|
664 | 28 | foreach ($tokens as $token) { |
|
665 | 28 | $temp = (array) $token; |
|
666 | 28 | $temp = $temp[0]; |
|
667 | 28 | if (isset(self::$substituteTokens[$temp])) { |
|
668 | foreach (self::$substituteTokens[$temp] as $token) { |
||
669 | $result[] = $token; |
||
670 | } |
||
671 | } else { |
||
672 | 28 | $result[] = $token; |
|
673 | } |
||
674 | 28 | } |
|
675 | 28 | return $result; |
|
676 | } |
||
677 | |||
678 | /** |
||
679 | * Tokenizes the content of the source file with {@link token_get_all()} and |
||
680 | * filters this token stream. |
||
681 | * |
||
682 | * @return void |
||
683 | */ |
||
684 | 28 | private function tokenize() |
|
685 | { |
||
686 | 28 | if ($this->tokens !== null) { |
|
687 | 26 | return; |
|
688 | } |
||
689 | |||
690 | 28 | $this->tokens = array(); |
|
691 | 28 | $this->index = 0; |
|
692 | 28 | $this->count = 0; |
|
693 | |||
694 | // Replace short open tags, short open tags will produce invalid results |
||
695 | // in all environments with disabled short open tags. |
||
696 | 28 | $source = $this->sourceFile->getSource(); |
|
697 | 28 | $source = preg_replace( |
|
698 | 28 | array('(<\?=)', '(<\?(\s))'), |
|
699 | 28 | array('<?php echo ', '<?php\1'), |
|
700 | $source |
||
701 | 28 | ); |
|
702 | |||
703 | 28 | if (version_compare(phpversion(), '5.3.0alpha3') < 0) { |
|
704 | $tokens = PHPTokenizerHelperVersion52::tokenize($source); |
||
705 | } else { |
||
706 | 28 | $tokens = token_get_all($source); |
|
707 | } |
||
708 | |||
709 | 28 | $tokens = $this->substituteTokens($tokens); |
|
710 | |||
711 | // Is the current token between an opening and a closing php tag? |
||
712 | 28 | $inTag = false; |
|
713 | |||
714 | // The current line number |
||
715 | 28 | $startLine = 1; |
|
716 | |||
717 | 28 | $startColumn = 1; |
|
718 | 28 | $endColumn = 1; |
|
719 | |||
720 | 28 | $literalMap = self::$literalMap; |
|
721 | 28 | $tokenMap = self::$tokenMap; |
|
722 | |||
723 | // Previous found type |
||
724 | 28 | $previousType = null; |
|
725 | 28 | $previousStartColumn = 0; |
|
726 | |||
727 | 28 | while ($token = current($tokens)) { |
|
728 | 28 | $type = null; |
|
729 | 28 | $image = null; |
|
730 | |||
731 | 28 | if (is_string($token)) { |
|
732 | 28 | $token = array(null, $token); |
|
733 | 28 | } |
|
734 | |||
735 | 28 | if ($token[0] === T_OPEN_TAG) { |
|
736 | 28 | $type = $tokenMap[$token[0]]; |
|
737 | 28 | $image = $token[1]; |
|
738 | 28 | $inTag = true; |
|
739 | 28 | } elseif ($token[0] === T_CLOSE_TAG) { |
|
740 | 12 | $type = $tokenMap[$token[0]]; |
|
741 | 12 | $image = $token[1]; |
|
742 | 12 | $inTag = false; |
|
743 | 28 | } elseif ($inTag === false) { |
|
744 | 6 | $type = Tokens::T_NO_PHP; |
|
745 | 6 | $image = $this->consumeNonePhpTokens($tokens); |
|
746 | 28 | } elseif ($token[0] === T_WHITESPACE) { |
|
747 | // Count newlines in token |
||
748 | 26 | $lines = substr_count($token[1], "\n"); |
|
749 | 26 | if ($lines === 0) { |
|
750 | 24 | $startColumn += strlen($token[1]); |
|
751 | 24 | } else { |
|
752 | 20 | $startColumn = strlen( |
|
753 | 20 | substr($token[1], strrpos($token[1], "\n") + 1) |
|
754 | 20 | ) + 1; |
|
755 | } |
||
756 | |||
757 | 26 | $startLine += $lines; |
|
758 | 26 | } else { |
|
759 | 28 | $value = strtolower($token[1]); |
|
760 | 28 | if (isset($literalMap[$value])) { |
|
761 | // Fetch literal type |
||
762 | 28 | $type = $literalMap[$value]; |
|
763 | 28 | $image = $token[1]; |
|
764 | |||
765 | // Check for a context sensitive alternative |
||
766 | 28 | View Code Duplication | if (isset(self::$alternativeMap[$type][$previousType])) { |
767 | $type = self::$alternativeMap[$type][$previousType]; |
||
768 | } |
||
769 | |||
770 | 28 | if (isset(self::$reductionMap[$type][$previousType])) { |
|
771 | $image = self::$reductionMap[$type][$previousType]['image']; |
||
772 | $type = self::$reductionMap[$type][$previousType]['type']; |
||
773 | |||
774 | $startColumn = $previousStartColumn; |
||
775 | |||
776 | array_pop($this->tokens); |
||
777 | } |
||
778 | 28 | } elseif (isset($tokenMap[$token[0]])) { |
|
779 | 28 | $type = $tokenMap[$token[0]]; |
|
780 | // Check for a context sensitive alternative |
||
781 | 28 | View Code Duplication | if (isset(self::$alternativeMap[$type][$previousType])) { |
782 | $type = self::$alternativeMap[$type][$previousType]; |
||
783 | } |
||
784 | |||
785 | 28 | $image = $token[1]; |
|
786 | 28 | } else { |
|
787 | // This should never happen |
||
788 | // @codeCoverageIgnoreStart |
||
789 | list($type, $image) = $this->generateUnknownToken($token[1]); |
||
790 | // @codeCoverageIgnoreEnd |
||
791 | } |
||
792 | } |
||
793 | |||
794 | 28 | if ($type) { |
|
795 | 28 | $rtrim = rtrim($image); |
|
796 | 28 | $lines = substr_count($rtrim, "\n"); |
|
797 | 28 | View Code Duplication | if ($lines === 0) { |
798 | 28 | $endColumn = $startColumn + strlen($rtrim) - 1; |
|
799 | 28 | } else { |
|
800 | 16 | $endColumn = strlen( |
|
801 | 16 | substr($rtrim, strrpos($rtrim, "\n") + 1) |
|
802 | 16 | ); |
|
803 | } |
||
804 | |||
805 | 28 | $endLine = $startLine + $lines; |
|
806 | |||
807 | 28 | $token = new Token($type, $rtrim, $startLine, $endLine, $startColumn, $endColumn); |
|
808 | |||
809 | // Store token in internal list |
||
810 | 28 | $this->tokens[] = $token; |
|
811 | |||
812 | // Store previous start column |
||
813 | 28 | $previousStartColumn = $startColumn; |
|
814 | |||
815 | // Count newlines in token |
||
816 | 28 | $lines = substr_count($image, "\n"); |
|
817 | 28 | View Code Duplication | if ($lines === 0) { |
818 | 28 | $startColumn += strlen($image); |
|
819 | 28 | } else { |
|
820 | 24 | $startColumn = strlen( |
|
821 | 24 | substr($image, strrpos($image, "\n") + 1) |
|
822 | 24 | ) + 1; |
|
823 | } |
||
824 | |||
825 | 28 | $startLine += $lines; |
|
826 | |||
827 | // Store current type |
||
828 | 28 | if ($type !== Tokens::T_COMMENT && $type !== Tokens::T_DOC_COMMENT) { |
|
829 | 28 | $previousType = $type; |
|
830 | 28 | } |
|
831 | 28 | } |
|
832 | |||
833 | 28 | next($tokens); |
|
834 | 28 | } |
|
835 | |||
836 | 28 | $this->count = count($this->tokens); |
|
837 | 28 | } |
|
838 | |||
839 | /** |
||
840 | * This method fetches all tokens until an opening php tag was found and it |
||
841 | * returns the collected content. The returned value will be null if there |
||
842 | * was no none php token. |
||
843 | * |
||
844 | * @param array $tokens Reference to the current token stream. |
||
845 | * |
||
846 | * @return string |
||
847 | */ |
||
848 | 6 | private function consumeNonePhpTokens(array &$tokens) |
|
849 | { |
||
850 | // The collected token content |
||
851 | 6 | $content = null; |
|
852 | |||
853 | // Fetch current token |
||
854 | 6 | $token = (array) current($tokens); |
|
855 | |||
856 | // Skipp all non open tags |
||
857 | 6 | while ($token[0] !== T_OPEN_TAG_WITH_ECHO && |
|
858 | 6 | $token[0] !== T_OPEN_TAG && |
|
859 | 6 | $token[0] !== false) { |
|
860 | 6 | $content .= (isset($token[1]) ? $token[1] : $token[0]); |
|
861 | |||
862 | 6 | $token = (array) next($tokens); |
|
863 | 6 | } |
|
864 | |||
865 | // Set internal pointer one back when there was at least one none php token |
||
866 | 6 | if ($token[0] !== false) { |
|
867 | 6 | prev($tokens); |
|
868 | 6 | } |
|
869 | |||
870 | 6 | return $content; |
|
871 | } |
||
872 | |||
873 | /** |
||
874 | * Generates a dummy/temp token for unknown string literals. |
||
875 | * |
||
876 | * @param string $token The unknown string token. |
||
877 | * |
||
878 | * @return array<integer, mixed> |
||
0 ignored issues
–
show
|
|||
879 | */ |
||
880 | private function generateUnknownToken($token) |
||
881 | { |
||
882 | return array($this->unknownTokenID++, $token); |
||
883 | } |
||
884 | } |
||
885 |
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.