@@ -245,6 +245,7 @@ public static function getLinesToBeIgnored($filename, $cacheTokens = TRUE)
245
245
* @param $filename string Filename to be checked
246
246
* @param $toplevel_funcs array List of function calls at top level that are allowed (e.g. array('define'))
247
247
* @param $classes array Classes that are present in file with respect of namespaces
248
+ * @param $errmsg string Error message will be written to this variable if false is returned
248
249
*
249
250
* @return bool
250
251
*/
@@ -260,131 +261,152 @@ public static function canIncludeFile($filename, array $toplevel_funcs, &$classe
260
261
$ state = "default " ;
261
262
$ depth = 0 ; // depth of "(" or "{"
262
263
$ line = 1 ;
263
- $ namespace = "" ;
264
+ $ namespace = "\\" ;
265
+ $ classname = "" ;
264
266
265
267
foreach ($ tokens as $ row ) {
266
- // printf("%-12s ", $state);
267
268
if (is_array ($ row )) {
268
269
list ($ token , $ text , $ line ) = $ row ;
269
270
$ text = str_replace ("\n" , '\\n ' , $ text );
270
- // echo token_name($token) . " '$text' on line $line\n";
271
- if ($ token === T_WHITESPACE || $ token === T_COMMENT || $ token === T_DOC_COMMENT ) continue ;
271
+ } else {
272
+ $ token = $ text = $ row ;
273
+ }
274
+
275
+ if ($ token === T_WHITESPACE || $ token === T_COMMENT || $ token === T_DOC_COMMENT ) continue ;
276
+
277
+ // printf("%-12s ", $state);
278
+
279
+ switch ($ state ) {
280
+ case "funccall " :
281
+ if ($ token === "( " ) $ depth ++;
282
+ else if ($ token === ") " ) $ depth --;
283
+ if ($ depth == 0 ) $ state = "funccall_end " ;
284
+ break ;
272
285
273
- switch ($ state ) {
274
- case "default " :
275
- if ($ token !== T_OPEN_TAG ) {
276
- $ errmsg = "Have something before <?php tag on line $ line " ;
286
+ case "default " :
287
+ if ($ token !== T_OPEN_TAG ) {
288
+ $ errmsg = "Have something before <?php tag on line $ line " ;
289
+ return false ;
290
+ }
291
+ $ state = "root " ;
292
+ break ;
293
+
294
+ case "root " :
295
+ if ($ token === T_STRING ) { // function call
296
+ if (!isset ($ toplevel_funcs [$ text ])) {
297
+ $ errmsg = "Forbidden top level function call: $ text(...) on line $ line " ;
277
298
return false ;
278
299
}
300
+ $ state = "funccall " ;
301
+ $ depth = 0 ;
302
+ } else if ($ token === T_ABSTRACT || $ token === T_FINAL ) {
303
+ continue ;
304
+ } else if ($ token === T_CLASS ) {
305
+ $ state = "classdef " ;
306
+ $ classname = "" ;
307
+ } else if ($ token === T_CLOSE_TAG ) {
308
+ $ state = "default " ;
309
+ } else if ($ token === T_NAMESPACE ) {
310
+ $ state = "namespace " ;
311
+ $ namespace = "" ;
312
+ } else if ($ token === T_USE ) {
313
+ $ state = "use " ;
314
+ } else if ($ token === T_FUNCTION ) {
315
+ $ state = "funcdef " ;
316
+ } else {
317
+ $ errmsg = "Disallowed top level token ' $ text' on line $ line " ;
318
+ return false ;
319
+ }
320
+ break ;
321
+
322
+ case "use " :
323
+ if ($ row === "; " ) $ state = "root " ;
324
+ break ;
325
+
326
+ case "namespace " :
327
+ if ($ token === "; " ) {
279
328
$ state = "root " ;
280
- break ;
281
- case "root " :
282
- if ($ token === T_STRING ) { // function call
283
- if (!isset ($ toplevel_funcs [$ text ])) {
284
- $ errmsg = "Forbidden top level function call: $ text(...) on line $ line " ;
285
- return false ;
286
- }
287
- $ state = "funccall " ;
288
- $ depth = 0 ;
289
- } else if ($ token === T_ABSTRACT || $ token === T_FINAL ) {
290
- continue ;
291
- } else if ($ token === T_CLASS ) {
292
- $ state = "classdef " ;
293
- } else if ($ token === T_CLOSE_TAG ) {
294
- $ state = "default " ;
295
- } else if ($ token === T_NAMESPACE ) {
296
- $ state = "namespace " ;
297
- $ namespace = "" ;
298
- } else if ($ token === T_USE ) {
299
- $ state = "use " ;
300
- } else if ($ token === T_FUNCTION ) {
301
- $ state = "funcdef " ;
302
- } else {
303
- $ errmsg = "Disallowed top level token " . token_name ($ token ) . " ( $ text) on line $ line " ;
329
+ } else if ($ token === T_NS_SEPARATOR || $ token === T_STRING ) {
330
+ $ namespace .= $ text ;
331
+ } else {
332
+ $ errmsg = "Unexpected token ' $ row' on line $ line (expected ';') " ;
333
+ return false ;
334
+ }
335
+ break ;
336
+
337
+ case "classdef " :
338
+ case "extends " :
339
+ case "implements " :
340
+ if ($ token === T_EXTENDS || $ token === T_IMPLEMENTS || $ token === "{ " ) {
341
+ if (!$ classname ) {
342
+ $ errmsg = "Empty classname on line $ line " ;
304
343
return false ;
305
344
}
306
- break ;
307
- case "namespace " :
308
- $ namespace .= $ text ;
309
- break ;
310
- case "classdef " :
311
- if ($ token === T_EXTENDS ) {
312
- $ state = "extends " ;
313
- } else if ($ token === T_IMPLEMENTS ) {
314
- $ state = "implements " ;
315
- } else if ($ token === T_STRING ) {
316
- $ classname = $ namespace . "\\" . $ text ;
345
+
346
+ if ($ classname [0 ] != '\\' ) {
347
+ $ classname = rtrim ($ namespace , "\\" ) . "\\" . $ classname ;
348
+ }
349
+
350
+ if ($ state == "classdef " ) {
317
351
if (class_exists ($ classname )) {
318
352
$ errmsg = "Class ' $ classname' already exists on line $ line " ;
319
353
return false ;
320
- } else {
321
- $ classes [] = $ classname ;
322
354
}
323
- } else {
324
- $ errmsg = "Unexpected token " . token_name ($ token ) . " ( $ text) on line $ line " ;
325
- return false ;
355
+ $ classes [] = $ classname ;
326
356
}
327
- break ;
328
- case "funccall_end " :
329
- $ errmsg = "Unexpected terminator for function call: " . token_name ($ token ) . " ( $ text) on line $ line " ;
330
- return false ;
331
- }
332
357
333
- } else {
334
- // echo "$row\n";
335
- switch ($ state ) {
336
- case "funccall " :
337
- if ($ row === "( " ) $ depth ++;
338
- else if ($ row === ") " ) $ depth --;
339
- if ($ depth == 0 ) $ state = "funccall_end " ;
340
- break ;
341
- case "funccall_end " :
342
- if ($ row !== "; " ) {
343
- $ errmsg = "Unexpected terminator for function call: ' $ row' on line $ line " ;
344
- return false ;
345
- }
346
- $ state = "root " ;
347
- break ;
348
- case "namespace " :
349
- if ($ row === "; " ) {
350
- $ state = "root " ;
351
- } else {
352
- $ errmsg = "Unexpected token ' $ row' on line $ line (expected ';') " ;
353
- return false ;
358
+ if ($ state != "classdef " ) {
359
+ $ func = ($ state == "extends " ? "class_exists " : "interface_exists " );
360
+ if (!$ func ($ classname , true )) {
361
+ $ errmsg = "Class ' $ classname' does not exist on line $ line " ;
362
+ return false ;
363
+ }
354
364
}
355
- break ;
356
- case "use " :
357
- if ($ row === "; " ) $ state = "root " ;
358
- break ;
359
- case "classdef " :
360
- case "extends " :
361
- case "implements " :
362
- if ($ row === "{ " ) {
365
+
366
+ if ($ token === "{ " ) {
363
367
$ state = "class " ;
364
368
$ depth = 1 ;
365
369
} else {
366
- $ errmsg = "Unexpected token ' $ row' on line $ line (expected '{') " ;
367
- return false ;
368
- }
369
- break ;
370
- case "funcdef " :
371
- if ($ row === "{ " ) {
372
- $ state = "function " ;
373
- $ depth = 1 ;
370
+ $ state = ($ token == T_EXTENDS ? "extends " : "implements " );
371
+ $ classname = "" ;
374
372
}
375
- break ;
376
- case "function " :
377
- if ($ row === "{ " ) $ depth ++;
378
- else if ($ row === "} " ) $ depth --;
379
- if ($ depth == 0 ) $ state = "root " ;
380
- break ;
381
- case "class " :
382
- if ($ row === "{ " ) $ depth ++;
383
- else if ($ row === "} " ) $ depth --;
384
- if ($ depth == 0 ) $ state = "root " ;
385
- break ;
386
- }
373
+ } else if ($ token === T_STRING || $ token == T_NS_SEPARATOR ) {
374
+ $ classname .= $ text ;
375
+ } else {
376
+ $ errmsg = "Unexpected token ' $ text' on line $ line (expected '{') " ;
377
+ return false ;
378
+ }
379
+ break ;
380
+
381
+ case "funccall_end " :
382
+ if ($ token !== "; " ) {
383
+ $ errmsg = "Unexpected terminator for function call: ' $ text' on line $ line " ;
384
+ return false ;
385
+ }
386
+ $ state = "root " ;
387
+ break ;
388
+
389
+ case "funcdef " :
390
+ if ($ row === "{ " ) {
391
+ $ state = "function " ;
392
+ $ depth = 1 ;
393
+ }
394
+ break ;
395
+
396
+ case "function " :
397
+ if ($ token === "{ " ) $ depth ++;
398
+ else if ($ token === "} " ) $ depth --;
399
+ if ($ depth == 0 ) $ state = "root " ;
400
+ break ;
401
+
402
+ case "class " :
403
+ if ($ token === "{ " ) $ depth ++;
404
+ else if ($ token === "} " ) $ depth --;
405
+ if ($ depth == 0 ) $ state = "root " ;
406
+ break ;
387
407
}
408
+
409
+ // printf(" => %-15s %-30s %-50s line %d\n", $state, is_int($token) ? token_name($token) : $text, $text, $line);
388
410
}
389
411
390
412
return true ;
0 commit comments