xref: /vim-8.2.3635/src/testdir/test_syntax.vim (revision 5f1920ad)
1" Test for syntax and syntax iskeyword option
2
3source check.vim
4CheckFeature syntax
5
6source view_util.vim
7source screendump.vim
8
9func GetSyntaxItem(pat)
10  let c = ''
11  let a = ['a', getreg('a'), getregtype('a')]
12  0
13  redraw!
14  call search(a:pat, 'W')
15  let synid = synID(line('.'), col('.'), 1)
16  while synid == synID(line('.'), col('.'), 1)
17    norm! v"ay
18    " stop at whitespace
19    if @a =~# '\s'
20      break
21    endif
22    let c .= @a
23    norm! l
24  endw
25  call call('setreg', a)
26  0
27  return c
28endfunc
29
30func Test_syn_iskeyword()
31  new
32  call setline(1, [
33	\ 'CREATE TABLE FOOBAR(',
34	\ '    DLTD_BY VARCHAR2(100)',
35	\ ');',
36	\ ''])
37
38  syntax on
39  set ft=sql
40  syn match SYN /C\k\+\>/
41  hi link SYN ErrorMsg
42  call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
43  /\<D\k\+\>/:norm! ygn
44  call assert_equal('DLTD_BY', @0)
45  redir @c
46  syn iskeyword
47  redir END
48  call assert_equal("\nsyntax iskeyword not set", @c)
49
50  syn iskeyword @,48-57,_,192-255
51  redir @c
52  syn iskeyword
53  redir END
54  call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c)
55
56  setlocal isk-=_
57  call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
58  /\<D\k\+\>/:norm! ygn
59  let b2 = @0
60  call assert_equal('DLTD', @0)
61
62  syn iskeyword clear
63  redir @c
64  syn iskeyword
65  redir END
66  call assert_equal("\nsyntax iskeyword not set", @c)
67
68  quit!
69endfunc
70
71func Test_syntax_after_reload()
72  split Xsomefile
73  call setline(1, ['hello', 'there'])
74  w!
75  only!
76  setl filetype=hello
77  au FileType hello let g:gotit = 1
78  call assert_false(exists('g:gotit'))
79  edit other
80  buf Xsomefile
81  call assert_equal('hello', &filetype)
82  call assert_true(exists('g:gotit'))
83  call delete('Xsomefile')
84endfunc
85
86func Test_syntime()
87  if !has('profile')
88    return
89  endif
90
91  syntax on
92  syntime on
93  let a = execute('syntime report')
94  call assert_equal("\nNo Syntax items defined for this buffer", a)
95
96  view ../memfile_test.c
97  setfiletype cpp
98  redraw
99  let a = execute('syntime report')
100  call assert_match('^  TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
101  call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
102  call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
103
104  syntime off
105  syntime clear
106  let a = execute('syntime report')
107  call assert_match('^  TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
108  call assert_notmatch('.* cppRawString *', a)
109  call assert_notmatch('.* cppNumber*', a)
110  call assert_notmatch('[1-9]', a)
111
112  call assert_fails('syntime abc', 'E475')
113
114  syntax clear
115  let a = execute('syntime report')
116  call assert_equal("\nNo Syntax items defined for this buffer", a)
117
118  bd
119endfunc
120
121func Test_syntime_completion()
122  if !has('profile')
123    return
124  endif
125
126  call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
127  call assert_equal('"syntime clear off on report', @:)
128endfunc
129
130func Test_syntax_list()
131  syntax on
132  let a = execute('syntax list')
133  call assert_equal("\nNo Syntax items defined for this buffer", a)
134
135  view ../memfile_test.c
136  setfiletype c
137
138  let a = execute('syntax list')
139  call assert_match('cInclude*', a)
140  call assert_match('cDefine', a)
141
142  let a = execute('syntax list cDefine')
143  call assert_notmatch('cInclude*', a)
144  call assert_match('cDefine', a)
145  call assert_match(' links to Macro$', a)
146
147  call assert_fails('syntax list ABCD', 'E28:')
148  call assert_fails('syntax list @ABCD', 'E392:')
149
150  syntax clear
151  let a = execute('syntax list')
152  call assert_equal("\nNo Syntax items defined for this buffer", a)
153
154  bd
155endfunc
156
157func Test_syntax_completion()
158  call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
159  call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:)
160
161  call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
162  call assert_equal('"syn case ignore match', @:)
163
164  call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
165  call assert_equal('"syn spell default notoplevel toplevel', @:)
166
167  call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
168  call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
169
170  " Check that clearing "Aap" avoids it showing up before Boolean.
171  hi Aap ctermfg=blue
172  call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
173  call assert_match('^"syn list Aap Boolean Character ', @:)
174  hi clear Aap
175
176  call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
177  call assert_match('^"syn list Boolean Character ', @:)
178
179  call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
180  call assert_match('^"syn match Boolean Character ', @:)
181endfunc
182
183func Test_syntax_arg_skipped()
184  syn clear
185  syntax case ignore
186  if 0
187    syntax case match
188  endif
189  call assert_match('case ignore', execute('syntax case'))
190
191  syn keyword Foo foo
192  call assert_match('Foo', execute('syntax'))
193  syn clear
194  call assert_match('case match', execute('syntax case'))
195  call assert_notmatch('Foo', execute('syntax'))
196
197  if has('conceal')
198    syn clear
199    syntax conceal on
200    if 0
201      syntax conceal off
202    endif
203    call assert_match('conceal on', execute('syntax conceal'))
204    syn clear
205    call assert_match('conceal off', execute('syntax conceal'))
206
207    syntax conceal on
208    syntax conceal off
209    call assert_match('conceal off', execute('syntax conceal'))
210  endif
211
212  syntax region Bar start=/</ end=/>/
213  if 0
214    syntax region NotTest start=/</ end=/>/ contains=@Spell
215  endif
216  call assert_match('Bar', execute('syntax'))
217  call assert_notmatch('NotTest', execute('syntax'))
218  call assert_notmatch('Spell', execute('syntax'))
219
220  hi Foo ctermfg=blue
221  let a = execute('hi Foo')
222  if 0
223    syntax rest
224  endif
225  call assert_equal(a, execute('hi Foo'))
226  hi clear Bar
227  hi clear Foo
228
229  set ft=tags
230  syn off
231  if 0
232    syntax enable
233  endif
234  call assert_match('No Syntax items defined', execute('syntax'))
235  syntax enable
236  call assert_match('tagComment', execute('syntax'))
237  set ft=
238
239  syn clear
240  if 0
241    syntax include @Spell nothing
242  endif
243  call assert_notmatch('Spell', execute('syntax'))
244
245  syn clear
246  syn iskeyword 48-57,$,_
247  call assert_match('48-57,$,_', execute('syntax iskeyword'))
248  if 0
249    syn clear
250    syn iskeyword clear
251  endif
252  call assert_match('48-57,$,_', execute('syntax iskeyword'))
253  syn iskeyword clear
254  call assert_match('not set', execute('syntax iskeyword'))
255  syn iskeyword 48-57,$,_
256  syn clear
257  call assert_match('not set', execute('syntax iskeyword'))
258
259  syn clear
260  syn keyword Foo foo
261  if 0
262    syn keyword NotAdded bar
263  endif
264  call assert_match('Foo', execute('syntax'))
265  call assert_notmatch('NotAdded', execute('highlight'))
266
267  syn clear
268  syn keyword Foo foo
269  call assert_match('Foo', execute('syntax'))
270  call assert_match('Foo', execute('syntax list'))
271  call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
272  call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
273
274  syn clear
275  syn match Fopi /asdf/
276  if 0
277    syn match Fopx /asdf/
278  endif
279  call assert_match('Fopi', execute('syntax'))
280  call assert_notmatch('Fopx', execute('syntax'))
281
282  syn clear
283  syn spell toplevel
284  call assert_match('spell toplevel', execute('syntax spell'))
285  if 0
286    syn spell notoplevel
287  endif
288  call assert_match('spell toplevel', execute('syntax spell'))
289  syn spell notoplevel
290  call assert_match('spell notoplevel', execute('syntax spell'))
291  syn spell default
292  call assert_match('spell default', execute('syntax spell'))
293
294  syn clear
295  if 0
296    syntax cluster Spell
297  endif
298  call assert_notmatch('Spell', execute('syntax'))
299
300  syn clear
301  syn keyword Foo foo
302  syn sync ccomment
303  syn sync maxlines=5
304  if 0
305    syn sync maxlines=11
306  endif
307  call assert_match('on C-style comments', execute('syntax sync'))
308  call assert_match('maximal 5 lines', execute('syntax sync'))
309  syn sync clear
310  if 0
311    syn sync ccomment
312  endif
313  call assert_notmatch('on C-style comments', execute('syntax sync'))
314
315  syn clear
316endfunc
317
318func Test_syntax_invalid_arg()
319  call assert_fails('syntax case asdf', 'E390:')
320  if has('conceal')
321    call assert_fails('syntax conceal asdf', 'E390:')
322  endif
323  call assert_fails('syntax spell asdf', 'E390:')
324  call assert_fails('syntax clear @ABCD', 'E391:')
325  call assert_fails('syntax include @Xxx', 'E397:')
326  call assert_fails('syntax region X start="{"', 'E399:')
327  call assert_fails('syntax sync x', 'E404:')
328  call assert_fails('syntax keyword Abc a[', 'E789:')
329  call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
330endfunc
331
332func Test_syn_sync()
333  syntax region HereGroup start=/this/ end=/that/
334  syntax sync match SyncHere grouphere HereGroup "pattern"
335  call assert_match('SyncHere', execute('syntax sync'))
336  syn sync clear
337  call assert_notmatch('SyncHere', execute('syntax sync'))
338  syn clear
339endfunc
340
341func Test_syn_clear()
342  syntax keyword Foo foo
343  syntax keyword Bar tar
344  call assert_match('Foo', execute('syntax'))
345  call assert_match('Bar', execute('syntax'))
346  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
347  syn clear Foo
348  call assert_notmatch('Foo', execute('syntax'))
349  call assert_match('Bar', execute('syntax'))
350  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
351  syn clear Foo Bar
352  call assert_notmatch('Foo', execute('syntax'))
353  call assert_notmatch('Bar', execute('syntax'))
354  hi clear Foo
355  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
356  hi clear Bar
357endfunc
358
359func Test_invalid_name()
360  syn clear
361  syn keyword Nop yes
362  call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
363  syntax keyword @Wrong bar
364  call assert_match('W18:', execute('1messages'))
365  syn clear
366  hi clear Nop
367  hi clear @Wrong
368endfunc
369
370func Test_ownsyntax()
371  new Xfoo
372  call setline(1, '#define FOO')
373  syntax on
374  set filetype=c
375  ownsyntax perl
376  call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
377  call assert_equal('c',    b:current_syntax)
378  call assert_equal('perl', w:current_syntax)
379
380  " A new split window should have the original syntax.
381  split
382  call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
383  call assert_equal('c', b:current_syntax)
384  call assert_equal(0, exists('w:current_syntax'))
385
386  wincmd x
387  call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
388
389  syntax off
390  set filetype&
391  %bw!
392endfunc
393
394func Test_ownsyntax_completion()
395  call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
396  call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
397endfunc
398
399func Test_highlight_invalid_arg()
400  if has('gui_running')
401    call assert_fails('hi XXX guifg=xxx', 'E254:')
402  endif
403  call assert_fails('hi DoesNotExist', 'E411:')
404  call assert_fails('hi link', 'E412:')
405  call assert_fails('hi link a', 'E412:')
406  call assert_fails('hi link a b c', 'E413:')
407  call assert_fails('hi XXX =', 'E415:')
408  call assert_fails('hi XXX cterm', 'E416:')
409  call assert_fails('hi XXX cterm=', 'E417:')
410  call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
411  call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
412  call assert_fails('hi XXX xxx=White', 'E423:')
413endfunc
414
415func Test_bg_detection()
416  CheckNotGui
417
418  " auto-detection of &bg, make sure sure it isn't set anywhere before
419  " this test
420  hi Normal ctermbg=0
421  call assert_equal('dark', &bg)
422  hi Normal ctermbg=4
423  call assert_equal('dark', &bg)
424  hi Normal ctermbg=12
425  call assert_equal('light', &bg)
426  hi Normal ctermbg=15
427  call assert_equal('light', &bg)
428
429  " manually-set &bg takes precedence over auto-detection
430  set bg=light
431  hi Normal ctermbg=4
432  call assert_equal('light', &bg)
433  set bg=dark
434  hi Normal ctermbg=12
435  call assert_equal('dark', &bg)
436
437  hi Normal ctermbg=NONE
438endfunc
439
440func Test_syntax_hangs()
441  if !has('reltime') || !has('float') || !has('syntax')
442    return
443  endif
444
445  " This pattern takes a long time to match, it should timeout.
446  new
447  call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
448  let start = reltime()
449  set nolazyredraw redrawtime=101
450  syn match Error /\%#=1a*.*X\@<=b*/
451  redraw
452  let elapsed = reltimefloat(reltime(start))
453  call assert_true(elapsed > 0.1)
454  call assert_true(elapsed < 1.0)
455
456  " second time syntax HL is disabled
457  let start = reltime()
458  redraw
459  let elapsed = reltimefloat(reltime(start))
460  call assert_true(elapsed < 0.1)
461
462  " after CTRL-L the timeout flag is reset
463  let start = reltime()
464  exe "normal \<C-L>"
465  redraw
466  let elapsed = reltimefloat(reltime(start))
467  call assert_true(elapsed > 0.1)
468  call assert_true(elapsed < 1.0)
469
470  set redrawtime&
471  bwipe!
472endfunc
473
474func Test_conceal()
475  if !has('conceal')
476    return
477  endif
478
479  new
480  call setline(1, ['', '123456'])
481  syn match test23 "23" conceal cchar=X
482  syn match test45 "45" conceal
483
484  set conceallevel=0
485  call assert_equal('123456 ', ScreenLines(2, 7)[0])
486  call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
487
488  set conceallevel=1
489  call assert_equal('1X 6   ', ScreenLines(2, 7)[0])
490  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, ' ', 2], [1, ' ', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
491
492  set conceallevel=1
493  set listchars=conceal:Y
494  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, 'Y', 2], [1, 'Y', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
495  call assert_equal('1XY6   ', ScreenLines(2, 7)[0])
496
497  set conceallevel=2
498  call assert_match('1X6    ', ScreenLines(2, 7)[0])
499  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
500
501  set conceallevel=3
502  call assert_match('16     ', ScreenLines(2, 7)[0])
503  call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
504
505  syn clear
506  set conceallevel&
507  bw!
508endfunc
509
510func Test_synstack_synIDtrans()
511  new
512  setfiletype c
513  syntax on
514  call setline(1, ' /* A comment with a TODO */')
515
516  call assert_equal([], synstack(1, 1))
517
518  norm f/
519  eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
520  eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
521
522  norm fA
523  call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
524  call assert_equal(['Comment'],  map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
525
526  norm fT
527  call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
528  call assert_equal(['Comment', 'Todo'],   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
529
530  syn clear
531  bw!
532endfunc
533
534" Check highlighting for a small piece of C code with a screen dump.
535func Test_syntax_c()
536  if !CanRunVimInTerminal()
537    throw 'Skipped: cannot make screendumps'
538  endif
539  call writefile([
540	\ '/* comment line at the top */',
541	\ 'int main(int argc, char **argv) { // another comment',
542	\ '#if 0',
543	\ '   int   not_used;',
544	\ '#else',
545	\ '   int   used;',
546	\ '#endif',
547	\ '   printf("Just an example piece of C code\n");',
548	\ '   return 0x0ff;',
549	\ '}',
550	\ "\t\t ",
551	\ '   static void',
552	\ 'myFunction(const double count, struct nothing, long there) {',
553	\ "\t// 123: nothing to endif here",
554	\ "\tfor (int i = 0; i < count; ++i) {",
555	\ "\t   break;",
556	\ "\t}",
557	\ "\tNote: asdf",
558	\ '}',
559	\ ], 'Xtest.c')
560
561  " This makes the default for 'background' use "dark", check that the
562  " response to t_RB corrects it to "light".
563  let $COLORFGBG = '15;0'
564
565  let buf = RunVimInTerminal('Xtest.c', {})
566  call term_sendkeys(buf, ":syn keyword Search Note\r")
567  call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
568  call term_sendkeys(buf, ":set hlsearch\r")
569  call term_sendkeys(buf, "/endif\r")
570  call term_sendkeys(buf, "vjfC")
571  call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
572
573  call term_sendkeys(buf, "\<Esc>")
574  call StopVimInTerminal(buf)
575
576  let $COLORFGBG = ''
577  call delete('Xtest.c')
578endfun
579
580" Using \z() in a region with NFA failing should not crash.
581func Test_syn_wrong_z_one()
582  new
583  call setline(1, ['just some text', 'with foo and bar to match with'])
584  syn region FooBar start="foo\z(.*\)bar" end="\z1"
585  call test_override("nfa_fail", 1)
586  redraw!
587  redraw!
588  call test_override("ALL", 0)
589  bwipe!
590endfunc
591
592func Test_syntax_after_bufdo()
593  call writefile(['/* aaa comment */'], 'Xaaa.c')
594  call writefile(['/* bbb comment */'], 'Xbbb.c')
595  call writefile(['/* ccc comment */'], 'Xccc.c')
596  call writefile(['/* ddd comment */'], 'Xddd.c')
597
598  let bnr = bufnr('%')
599  new Xaaa.c
600  badd Xbbb.c
601  badd Xccc.c
602  badd Xddd.c
603  exe "bwipe " . bnr
604  let l = []
605  bufdo call add(l, bufnr('%'))
606  call assert_equal(4, len(l))
607
608  syntax on
609
610  " This used to only enable syntax HL in the last buffer.
611  bufdo tab split
612  tabrewind
613  for tab in range(1, 4)
614    norm fm
615    call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
616    tabnext
617  endfor
618
619  bwipe! Xaaa.c
620  bwipe! Xbbb.c
621  bwipe! Xccc.c
622  bwipe! Xddd.c
623  syntax off
624  call delete('Xaaa.c')
625  call delete('Xbbb.c')
626  call delete('Xccc.c')
627  call delete('Xddd.c')
628endfunc
629