Commit 87d79390645951be0174699d130e566e5ffa169c

Michael Schmidt 2021-05-17T16:28:00

PHP: Fixed functions with namespaces (#2889)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
diff --git a/components/prism-php.js b/components/prism-php.js
index 970db8f..02abdc8 100644
--- a/components/prism-php.js
+++ b/components/prism-php.js
@@ -219,7 +219,13 @@
 			}
 		],
 		'constant': constant,
-		'function': /\b\w+(?=\s*\()/,
+		'function': {
+			pattern: /(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,
+			lookbehind: true,
+			inside: {
+				'punctuation': /\\/
+			}
+		},
 		'property': {
 			pattern: /(->\s*)\w+/,
 			lookbehind: true
diff --git a/components/prism-php.min.js b/components/prism-php.min.js
index 9733bd4..906401a 100644
--- a/components/prism-php.min.js
+++ b/components/prism-php.min.js
@@ -1 +1 @@
-!function(a){var e=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;a.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:e,variable:/\$+(?:\w+\b|(?={))/i,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*[a-z0-9_|]\|\s*)(?:null|false)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?[a-z0-9_|]\|\s*)(?:null|false)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:null|false)\b/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:/\b\w+(?=\s*\()/,property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:a.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];a.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=]$)/,lookbehind:!0,inside:{comment:e,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|]$/,alias:"punctuation"}}}}),a.hooks.add("before-tokenize",function(e){if(/<\?/.test(e.code)){a.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/gi)}}),a.hooks.add("after-tokenize",function(e){a.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism);
\ No newline at end of file
+!function(a){var e=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;a.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:e,variable:/\$+(?:\w+\b|(?={))/i,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*[a-z0-9_|]\|\s*)(?:null|false)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?[a-z0-9_|]\|\s*)(?:null|false)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:null|false)\b/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:a.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];a.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=]$)/,lookbehind:!0,inside:{comment:e,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|]$/,alias:"punctuation"}}}}),a.hooks.add("before-tokenize",function(e){if(/<\?/.test(e.code)){a.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/gi)}}),a.hooks.add("after-tokenize",function(e){a.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism);
\ No newline at end of file
diff --git a/tests/languages/latte/delimiter_feature.test b/tests/languages/latte/delimiter_feature.test
index 23d0bac..4116230 100644
--- a/tests/languages/latte/delimiter_feature.test
+++ b/tests/languages/latte/delimiter_feature.test
@@ -14,17 +14,102 @@ line}
 ----------------------------------------------------
 
 [
-	["latte", [["ld", [["punctuation", "{"], ["tag", "aa"]]], ["rd", [["punctuation", "}"]]]]],
-	["latte", [["ld", [["punctuation", "{/"], ["tag", "aa"]]], ["rd", [["punctuation", "}"]]]]],
-	["latte", [["ld", [["punctuation", "{"]]], ["php", [["operator", "/"]]], ["rd", [["punctuation", "}"]]]]],
+	["latte", [
+		["ld", [
+			["punctuation", "{"],
+			["tag", "aa"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
+	["latte", [
+		["ld", [
+			["punctuation", "{/"],
+			["tag", "aa"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
+	["latte", [
+		["ld", [
+			["punctuation", "{"]
+		]],
+		["php", [
+			["operator", "/"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
 	"\r\n{",
-		["latte", [["ld", [["punctuation", "{"], ["tag", "aa"]]], ["rd", [["punctuation", "}"]]]]],
+	["latte", [
+		["ld", [
+			["punctuation", "{"],
+			["tag", "aa"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
 	"}\r\n",
-	["latte", [["ld", [["punctuation", "{"]]], ["php", [["number", "10"]]], ["rd", [["punctuation", "}"]]]]],
-	["latte", [["ld", [["punctuation", "{"], ["tag", "="]]], ["php", [["number", "10"]]], ["rd", [["punctuation", "}"]]]]],
-	["latte", [["ld", [["punctuation", "{"]]], ["php", [["function", "test"], ["punctuation", "("], ["punctuation", ")"]]], ["rd", [["punctuation", "}"]]]]],
+
+	["latte", [
+		["ld", [
+			["punctuation", "{"]
+		]],
+		["php", [
+			["number", "10"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
+	["latte", [
+		["ld", [
+			["punctuation", "{"],
+			["tag", "="]
+		]],
+		["php", [
+			["number", "10"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
+	["latte", [
+		["ld", [
+			["punctuation", "{"]
+		]],
+		["php", [
+			["function", ["test"]],
+			["punctuation", "("],
+			["punctuation", ")"]
+		]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]],
+
 	"\r\n{'no'}\r\n{\"no\"}\r\n{ no }\r\n",
-	["latte", [["ld", [["punctuation", "{"], ["tag", "multi"]]], ["php", ["line"]], ["rd", [["punctuation", "}"]]]]]
+
+	["latte", [
+		["ld", [
+			["punctuation", "{"],
+			["tag", "multi"]
+		]],
+
+		["php", ["line"]],
+		["rd", [
+			["punctuation", "}"]
+		]]
+	]]
 ]
 
 ----------------------------------------------------
diff --git a/tests/languages/php!+css-extras/issue2008.test b/tests/languages/php!+css-extras/issue2008.test
index ca5b7cf..34c084f 100644
--- a/tests/languages/php!+css-extras/issue2008.test
+++ b/tests/languages/php!+css-extras/issue2008.test
@@ -1,43 +1,43 @@
-<img style="width:<?php echo (80 / count($images)) ?>%"/>
-
-----------------------------------------------------
-
-[
-	["tag", [
-		["tag", [
-			["punctuation", "<"],
-			"img"
-		]],
-		["special-attr", [
-			["attr-name", "style"],
-			["attr-value", [
-				["punctuation", "="],
-				["punctuation", "\""],
-				["value", [
-					["property", "width"],
-					["punctuation", ":"],
-					["php", [
-						["delimiter", "<?php"],
-						["keyword", "echo"],
-						["punctuation", "("],
-						["number", "80"],
-						["operator", "/"],
-						["function", "count"],
-						["punctuation", "("],
-						["variable", "$images"],
-						["punctuation", ")"],
-						["punctuation", ")"],
-						["delimiter", "?>"]
-					]],
-					"%"
-				]],
-				["punctuation", "\""]
-			]]
-		]],
-		["punctuation", "/>"]
-	]]
-]
-
-----------------------------------------------------
-
-Checks for #2008 where a part of markup templating's placeholder was tokenized as `number` by CSS Extras.
+<img style="width:<?php echo (80 / count($images)) ?>%"/>
+
+----------------------------------------------------
+
+[
+	["tag", [
+		["tag", [
+			["punctuation", "<"],
+			"img"
+		]],
+		["special-attr", [
+			["attr-name", "style"],
+			["attr-value", [
+				["punctuation", "="],
+				["punctuation", "\""],
+				["value", [
+					["property", "width"],
+					["punctuation", ":"],
+					["php", [
+						["delimiter", "<?php"],
+						["keyword", "echo"],
+						["punctuation", "("],
+						["number", "80"],
+						["operator", "/"],
+						["function", ["count"]],
+						["punctuation", "("],
+						["variable", "$images"],
+						["punctuation", ")"],
+						["punctuation", ")"],
+						["delimiter", "?>"]
+					]],
+					"%"
+				]],
+				["punctuation", "\""]
+			]]
+		]],
+		["punctuation", "/>"]
+	]]
+]
+
+----------------------------------------------------
+
+Checks for #2008 where a part of markup templating's placeholder was tokenized as `number` by CSS Extras.
diff --git a/tests/languages/php!+php-extras/scope_feature.test b/tests/languages/php!+php-extras/scope_feature.test
index bd96168..313a554 100644
--- a/tests/languages/php!+php-extras/scope_feature.test
+++ b/tests/languages/php!+php-extras/scope_feature.test
@@ -9,19 +9,27 @@ parent::baz()
 		["keyword", "static"],
 		["punctuation", "::"]
 	]],
-	["function", "foo"], ["punctuation", "("], ["punctuation", ")"],
+	["function", ["foo"]],
+	["punctuation", "("],
+	["punctuation", ")"],
+
 	["scope", [
 		["keyword", "self"],
 		["punctuation", "::"]
 	]],
-	["function", "bar"], ["punctuation", "("], ["punctuation", ")"],
+	["function", ["bar"]],
+	["punctuation", "("],
+	["punctuation", ")"],
+
 	["scope", [
 		["keyword", "parent"],
 		["punctuation", "::"]
 	]],
-	["function", "baz"], ["punctuation", "("], ["punctuation", ")"]
+	["function", ["baz"]],
+	["punctuation", "("],
+	["punctuation", ")"]
 ]
 
 ----------------------------------------------------
 
-Checks for scopes.
\ No newline at end of file
+Checks for scopes.
diff --git a/tests/languages/php/argument-name_feature.test b/tests/languages/php/argument-name_feature.test
index 8abbca1..5d61d2f 100644
--- a/tests/languages/php/argument-name_feature.test
+++ b/tests/languages/php/argument-name_feature.test
@@ -6,19 +6,22 @@ foo(
 ----------------------------------------------------
 
 [
-	["function", "foo"],
+	["function", ["foo"]],
 	["punctuation", "("],
+
 	["argument-name", "a"],
 	["punctuation", ":"],
 	["string", "'bar'"],
 	["punctuation", ","],
+
 	["argument-name", "qux"],
 	["punctuation", ":"],
 	["string", "'baz'"],
+
 	["punctuation", ")"],
 	["punctuation", ";"]
 ]
 
 ----------------------------------------------------
 
-Checks for named arguments.
\ No newline at end of file
+Checks for named arguments.
diff --git a/tests/languages/php/class-name_feature.test b/tests/languages/php/class-name_feature.test
index 09f5432..cda1575 100644
--- a/tests/languages/php/class-name_feature.test
+++ b/tests/languages/php/class-name_feature.test
@@ -32,7 +32,7 @@ class Foo extends \Package\Bar implements App\Baz {}
 
 	["class-name", "Foo"],
 	["operator", "::"],
-	["function", "bar"],
+	["function", ["bar"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -42,7 +42,7 @@ class Foo extends \Package\Bar implements App\Baz {}
 		"Foo"
 	]],
 	["operator", "::"],
-	["function", "bar"],
+	["function", ["bar"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -54,7 +54,7 @@ class Foo extends \Package\Bar implements App\Baz {}
 		"Foo"
 	]],
 	["operator", "::"],
-	["function", "bar"],
+	["function", ["bar"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
diff --git a/tests/languages/php/function_feature.test b/tests/languages/php/function_feature.test
index d04d07d..290a76a 100644
--- a/tests/languages/php/function_feature.test
+++ b/tests/languages/php/function_feature.test
@@ -23,6 +23,10 @@ Test::method();  // this is "method" static method
 $variable->class(); // this "class" should be interpreted as "keyword"
 Test::class; // This "class" should still be a keyword
 
+mb_string(); // call to a global function
+\mb_string(); // namespace \ is global
+\a\b\c\mb_string(); // function in \a\b\c namespace
+
 ----------------------------------------------------
 
 [
@@ -49,7 +53,7 @@ Test::class; // This "class" should still be a keyword
 
 	["variable", "$a"],
 	["operator", "->"],
-	["function", "if"],
+	["function", ["if"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -71,7 +75,7 @@ Test::class; // This "class" should still be a keyword
 
 	["variable", "$variable"],
 	["operator", "->"],
-	["function", "foreach"],
+	["function", ["foreach"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -79,7 +83,7 @@ Test::class; // This "class" should still be a keyword
 
 	["variable", "$variable"],
 	["operator", "->"],
-	["function", "method"],
+	["function", ["method"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -87,7 +91,7 @@ Test::class; // This "class" should still be a keyword
 
 	["variable", "$var"],
 	["operator", "->"],
-	["function", "match"],
+	["function", ["match"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 
@@ -104,7 +108,7 @@ Test::class; // This "class" should still be a keyword
 
 	["class-name", "Test"],
 	["operator", "::"],
-	["function", "foreach"],
+	["function", ["foreach"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -112,7 +116,7 @@ Test::class; // This "class" should still be a keyword
 
 	["class-name", "Test"],
 	["operator", "::"],
-	["function", "method"],
+	["function", ["method"]],
 	["punctuation", "("],
 	["punctuation", ")"],
 	["punctuation", ";"],
@@ -132,5 +136,35 @@ Test::class; // This "class" should still be a keyword
 	["operator", "::"],
 	["keyword", "class"],
 	["punctuation", ";"],
-	["comment", "// This \"class\" should still be a keyword"]
-]
\ No newline at end of file
+	["comment", "// This \"class\" should still be a keyword"],
+
+	["function", ["mb_string"]],
+	["punctuation", "("],
+	["punctuation", ")"],
+	["punctuation", ";"],
+	["comment", "// call to a global function"],
+
+	["function", [
+		["punctuation", "\\"],
+		"mb_string"
+	]],
+	["punctuation", "("],
+	["punctuation", ")"],
+	["punctuation", ";"],
+	["comment", "// namespace \\ is global"],
+
+	["function", [
+		["punctuation", "\\"],
+		"a",
+		["punctuation", "\\"],
+		"b",
+		["punctuation", "\\"],
+		"c",
+		["punctuation", "\\"],
+		"mb_string"
+	]],
+	["punctuation", "("],
+	["punctuation", ")"],
+	["punctuation", ";"],
+	["comment", "// function in \\a\\b\\c namespace"]
+]
diff --git a/tests/languages/php/string-interpolation_feature.test b/tests/languages/php/string-interpolation_feature.test
index 3f86ef5..d870eb4 100644
--- a/tests/languages/php/string-interpolation_feature.test
+++ b/tests/languages/php/string-interpolation_feature.test
@@ -118,7 +118,7 @@ $value = "$foo[0][1]";
 			["punctuation", "{"],
 			["variable", "$"],
 			["punctuation", "{"],
-			["function", "getName"],
+			["function", ["getName"]],
 			["punctuation", "("],
 			["punctuation", ")"],
 			["punctuation", "}"],
@@ -135,7 +135,7 @@ $value = "$foo[0][1]";
 			["punctuation", "{"],
 			["variable", "$object"],
 			["operator", "->"],
-			["function", "getName"],
+			["function", ["getName"]],
 			["punctuation", "("],
 			["punctuation", ")"],
 			["punctuation", "}"],
@@ -187,7 +187,7 @@ $value = "$foo[0][1]";
 			["punctuation", "{"],
 			["variable", "$string"],
 			["operator", "->"],
-			["function", "interpolation"],
+			["function", ["interpolation"]],
 			["punctuation", "("],
 			["punctuation", ")"],
 			["punctuation", "}"],