xref: /vim-8.2.3635/src/testdir/test_syntax.vim (revision 81ea1dfb)
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_echohl_completion()
184  call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
185  call assert_equal('"echohl NonText Normal none', @:)
186endfunc
187
188func Test_syntax_arg_skipped()
189  syn clear
190  syntax case ignore
191  if 0
192    syntax case match
193  endif
194  call assert_match('case ignore', execute('syntax case'))
195
196  syn keyword Foo foo
197  call assert_match('Foo', execute('syntax'))
198  syn clear
199  call assert_match('case match', execute('syntax case'))
200  call assert_notmatch('Foo', execute('syntax'))
201
202  if has('conceal')
203    syn clear
204    syntax conceal on
205    if 0
206      syntax conceal off
207    endif
208    call assert_match('conceal on', execute('syntax conceal'))
209    syn clear
210    call assert_match('conceal off', execute('syntax conceal'))
211
212    syntax conceal on
213    syntax conceal off
214    call assert_match('conceal off', execute('syntax conceal'))
215  endif
216
217  syntax region Bar start=/</ end=/>/
218  if 0
219    syntax region NotTest start=/</ end=/>/ contains=@Spell
220  endif
221  call assert_match('Bar', execute('syntax'))
222  call assert_notmatch('NotTest', execute('syntax'))
223  call assert_notmatch('Spell', execute('syntax'))
224
225  hi Foo ctermfg=blue
226  let a = execute('hi Foo')
227  if 0
228    syntax rest
229  endif
230  call assert_equal(a, execute('hi Foo'))
231  hi clear Bar
232  hi clear Foo
233
234  set ft=tags
235  syn off
236  if 0
237    syntax enable
238  endif
239  call assert_match('No Syntax items defined', execute('syntax'))
240  syntax enable
241  call assert_match('tagComment', execute('syntax'))
242  set ft=
243
244  syn clear
245  if 0
246    syntax include @Spell nothing
247  endif
248  call assert_notmatch('Spell', execute('syntax'))
249
250  syn clear
251  syn iskeyword 48-57,$,_
252  call assert_match('48-57,$,_', execute('syntax iskeyword'))
253  if 0
254    syn clear
255    syn iskeyword clear
256  endif
257  call assert_match('48-57,$,_', execute('syntax iskeyword'))
258  syn iskeyword clear
259  call assert_match('not set', execute('syntax iskeyword'))
260  syn iskeyword 48-57,$,_
261  syn clear
262  call assert_match('not set', execute('syntax iskeyword'))
263
264  syn clear
265  syn keyword Foo foo
266  if 0
267    syn keyword NotAdded bar
268  endif
269  call assert_match('Foo', execute('syntax'))
270  call assert_notmatch('NotAdded', execute('highlight'))
271
272  syn clear
273  syn keyword Foo foo
274  call assert_match('Foo', execute('syntax'))
275  call assert_match('Foo', execute('syntax list'))
276  call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
277  call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
278
279  syn clear
280  syn match Fopi /asdf/
281  if 0
282    syn match Fopx /asdf/
283  endif
284  call assert_match('Fopi', execute('syntax'))
285  call assert_notmatch('Fopx', execute('syntax'))
286
287  syn clear
288  syn spell toplevel
289  call assert_match('spell toplevel', execute('syntax spell'))
290  if 0
291    syn spell notoplevel
292  endif
293  call assert_match('spell toplevel', execute('syntax spell'))
294  syn spell notoplevel
295  call assert_match('spell notoplevel', execute('syntax spell'))
296  syn spell default
297  call assert_match('spell default', execute('syntax spell'))
298
299  syn clear
300  if 0
301    syntax cluster Spell
302  endif
303  call assert_notmatch('Spell', execute('syntax'))
304
305  syn clear
306  syn keyword Foo foo
307  syn sync ccomment
308  syn sync maxlines=5
309  if 0
310    syn sync maxlines=11
311  endif
312  call assert_match('on C-style comments', execute('syntax sync'))
313  call assert_match('maximal 5 lines', execute('syntax sync'))
314  syn sync clear
315  if 0
316    syn sync ccomment
317  endif
318  call assert_notmatch('on C-style comments', execute('syntax sync'))
319
320  syn clear
321endfunc
322
323func Test_syntax_invalid_arg()
324  call assert_fails('syntax case asdf', 'E390:')
325  if has('conceal')
326    call assert_fails('syntax conceal asdf', 'E390:')
327  endif
328  call assert_fails('syntax spell asdf', 'E390:')
329  call assert_fails('syntax clear @ABCD', 'E391:')
330  call assert_fails('syntax include @Xxx', 'E397:')
331  call assert_fails('syntax region X start="{"', 'E399:')
332  call assert_fails('syntax sync x', 'E404:')
333  call assert_fails('syntax keyword Abc a[', 'E789:')
334  call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
335
336  let caught_393 = 0
337  try
338    syntax keyword cMyItem grouphere G1
339  catch /E393:/
340    let caught_393 = 1
341  endtry
342  call assert_equal(1, caught_393)
343
344  let caught_394 = 0
345  try
346    syntax sync match Abc grouphere MyItem "abc"'
347  catch /E394:/
348    let caught_394 = 1
349  endtry
350  call assert_equal(1, caught_394)
351
352  " Test for too many \z\( and unmatched \z\(
353  " Not able to use assert_fails() here because both E50:/E879: and E475:
354  " messages are emitted.
355  set regexpengine=1
356  let caught_52 = 0
357  try
358    syntax region MyRegion start='\z\(' end='\*/'
359  catch /E52:/
360    let caught_52 = 1
361  endtry
362  call assert_equal(1, caught_52)
363
364  let caught_50 = 0
365  try
366    let cmd = "syntax region MyRegion start='"
367    let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
368    exe cmd
369  catch /E50:/
370    let caught_50 = 1
371  endtry
372  call assert_equal(1, caught_50)
373
374  set regexpengine=2
375  let caught_54 = 0
376  try
377    syntax region MyRegion start='\z\(' end='\*/'
378  catch /E54:/
379    let caught_54 = 1
380  endtry
381  call assert_equal(1, caught_54)
382
383  let caught_879 = 0
384  try
385    let cmd = "syntax region MyRegion start='"
386    let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
387    exe cmd
388  catch /E879:/
389    let caught_879 = 1
390  endtry
391  call assert_equal(1, caught_879)
392  set regexpengine&
393endfunc
394
395func Test_syn_sync()
396  syntax region HereGroup start=/this/ end=/that/
397  syntax sync match SyncHere grouphere HereGroup "pattern"
398  call assert_match('SyncHere', execute('syntax sync'))
399  syn sync clear
400  call assert_notmatch('SyncHere', execute('syntax sync'))
401  syn clear
402endfunc
403
404func Test_syn_clear()
405  syntax keyword Foo foo
406  syntax keyword Bar tar
407  call assert_match('Foo', execute('syntax'))
408  call assert_match('Bar', execute('syntax'))
409  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
410  syn clear Foo
411  call assert_notmatch('Foo', execute('syntax'))
412  call assert_match('Bar', execute('syntax'))
413  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
414  syn clear Foo Bar
415  call assert_notmatch('Foo', execute('syntax'))
416  call assert_notmatch('Bar', execute('syntax'))
417  hi clear Foo
418  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
419  hi clear Bar
420endfunc
421
422func Test_invalid_name()
423  syn clear
424  syn keyword Nop yes
425  call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
426  syntax keyword @Wrong bar
427  call assert_match('W18:', execute('1messages'))
428  syn clear
429  hi clear Nop
430  hi clear @Wrong
431endfunc
432
433func Test_ownsyntax()
434  new Xfoo
435  call setline(1, '#define FOO')
436  syntax on
437  set filetype=c
438  ownsyntax perl
439  call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
440  call assert_equal('c',    b:current_syntax)
441  call assert_equal('perl', w:current_syntax)
442
443  " A new split window should have the original syntax.
444  split
445  call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
446  call assert_equal('c', b:current_syntax)
447  call assert_equal(0, exists('w:current_syntax'))
448
449  wincmd x
450  call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
451
452  syntax off
453  set filetype&
454  %bw!
455endfunc
456
457func Test_ownsyntax_completion()
458  call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
459  call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
460endfunc
461
462func Test_highlight_invalid_arg()
463  if has('gui_running')
464    call assert_fails('hi XXX guifg=xxx', 'E254:')
465  endif
466  call assert_fails('hi DoesNotExist', 'E411:')
467  call assert_fails('hi link', 'E412:')
468  call assert_fails('hi link a', 'E412:')
469  call assert_fails('hi link a b c', 'E413:')
470  call assert_fails('hi XXX =', 'E415:')
471  call assert_fails('hi XXX cterm', 'E416:')
472  call assert_fails('hi XXX cterm=', 'E417:')
473  call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
474  call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
475  call assert_fails('hi XXX xxx=White', 'E423:')
476endfunc
477
478func Test_bg_detection()
479  CheckNotGui
480
481  " auto-detection of &bg, make sure sure it isn't set anywhere before
482  " this test
483  hi Normal ctermbg=0
484  call assert_equal('dark', &bg)
485  hi Normal ctermbg=4
486  call assert_equal('dark', &bg)
487  hi Normal ctermbg=12
488  call assert_equal('light', &bg)
489  hi Normal ctermbg=15
490  call assert_equal('light', &bg)
491
492  " manually-set &bg takes precedence over auto-detection
493  set bg=light
494  hi Normal ctermbg=4
495  call assert_equal('light', &bg)
496  set bg=dark
497  hi Normal ctermbg=12
498  call assert_equal('dark', &bg)
499
500  hi Normal ctermbg=NONE
501endfunc
502
503func Test_syntax_hangs()
504  if !has('reltime') || !has('float') || !has('syntax')
505    return
506  endif
507
508  " This pattern takes a long time to match, it should timeout.
509  new
510  call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
511  let start = reltime()
512  set nolazyredraw redrawtime=101
513  syn match Error /\%#=1a*.*X\@<=b*/
514  redraw
515  let elapsed = reltimefloat(reltime(start))
516  call assert_true(elapsed > 0.1)
517  call assert_true(elapsed < 1.0)
518
519  " second time syntax HL is disabled
520  let start = reltime()
521  redraw
522  let elapsed = reltimefloat(reltime(start))
523  call assert_true(elapsed < 0.1)
524
525  " after CTRL-L the timeout flag is reset
526  let start = reltime()
527  exe "normal \<C-L>"
528  redraw
529  let elapsed = reltimefloat(reltime(start))
530  call assert_true(elapsed > 0.1)
531  call assert_true(elapsed < 1.0)
532
533  set redrawtime&
534  bwipe!
535endfunc
536
537func Test_conceal()
538  if !has('conceal')
539    return
540  endif
541
542  new
543  call setline(1, ['', '123456'])
544  syn match test23 "23" conceal cchar=X
545  syn match test45 "45" conceal
546
547  set conceallevel=0
548  call assert_equal('123456 ', ScreenLines(2, 7)[0])
549  call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
550
551  set conceallevel=1
552  call assert_equal('1X 6   ', ScreenLines(2, 7)[0])
553  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)'))
554
555  set conceallevel=1
556  set listchars=conceal:Y
557  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)'))
558  call assert_equal('1XY6   ', ScreenLines(2, 7)[0])
559
560  set conceallevel=2
561  call assert_match('1X6    ', ScreenLines(2, 7)[0])
562  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)'))
563
564  set conceallevel=3
565  call assert_match('16     ', ScreenLines(2, 7)[0])
566  call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
567
568  syn clear
569  set conceallevel&
570  bw!
571endfunc
572
573func Test_synstack_synIDtrans()
574  new
575  setfiletype c
576  syntax on
577  call setline(1, ' /* A comment with a TODO */')
578
579  call assert_equal([], synstack(1, 1))
580
581  norm f/
582  eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
583  eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
584
585  norm fA
586  call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
587  call assert_equal(['Comment'],  map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
588
589  norm fT
590  call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
591  call assert_equal(['Comment', 'Todo'],   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
592
593  call assert_fails("let n=synIDtrans([])", 'E745:')
594
595  syn clear
596  bw!
597endfunc
598
599" Check highlighting for a small piece of C code with a screen dump.
600func Test_syntax_c()
601  if !CanRunVimInTerminal()
602    throw 'Skipped: cannot make screendumps'
603  endif
604  call writefile([
605	\ '/* comment line at the top */',
606	\ 'int main(int argc, char **argv) { // another comment',
607	\ '#if 0',
608	\ '   int   not_used;',
609	\ '#else',
610	\ '   int   used;',
611	\ '#endif',
612	\ '   printf("Just an example piece of C code\n");',
613	\ '   return 0x0ff;',
614	\ '}',
615	\ "\t\t ",
616	\ '   static void',
617	\ 'myFunction(const double count, struct nothing, long there) {',
618	\ "\t// 123: nothing to endif here",
619	\ "\tfor (int i = 0; i < count; ++i) {",
620	\ "\t   break;",
621	\ "\t}",
622	\ "\tNote: asdf",
623	\ '}',
624	\ ], 'Xtest.c')
625
626  " This makes the default for 'background' use "dark", check that the
627  " response to t_RB corrects it to "light".
628  let $COLORFGBG = '15;0'
629
630  let buf = RunVimInTerminal('Xtest.c', {})
631  call term_sendkeys(buf, ":syn keyword Search Note\r")
632  call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
633  call term_sendkeys(buf, ":set hlsearch\r")
634  call term_sendkeys(buf, "/endif\r")
635  call term_sendkeys(buf, "vjfC")
636  call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
637
638  call term_sendkeys(buf, "\<Esc>")
639  call StopVimInTerminal(buf)
640
641  let $COLORFGBG = ''
642  call delete('Xtest.c')
643endfun
644
645" Using \z() in a region with NFA failing should not crash.
646func Test_syn_wrong_z_one()
647  new
648  call setline(1, ['just some text', 'with foo and bar to match with'])
649  syn region FooBar start="foo\z(.*\)bar" end="\z1"
650  call test_override("nfa_fail", 1)
651  redraw!
652  redraw!
653  call test_override("ALL", 0)
654  bwipe!
655endfunc
656
657func Test_syntax_after_bufdo()
658  call writefile(['/* aaa comment */'], 'Xaaa.c')
659  call writefile(['/* bbb comment */'], 'Xbbb.c')
660  call writefile(['/* ccc comment */'], 'Xccc.c')
661  call writefile(['/* ddd comment */'], 'Xddd.c')
662
663  let bnr = bufnr('%')
664  new Xaaa.c
665  badd Xbbb.c
666  badd Xccc.c
667  badd Xddd.c
668  exe "bwipe " . bnr
669  let l = []
670  bufdo call add(l, bufnr('%'))
671  call assert_equal(4, len(l))
672
673  syntax on
674
675  " This used to only enable syntax HL in the last buffer.
676  bufdo tab split
677  tabrewind
678  for tab in range(1, 4)
679    norm fm
680    call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
681    tabnext
682  endfor
683
684  bwipe! Xaaa.c
685  bwipe! Xbbb.c
686  bwipe! Xccc.c
687  bwipe! Xddd.c
688  syntax off
689  call delete('Xaaa.c')
690  call delete('Xbbb.c')
691  call delete('Xccc.c')
692  call delete('Xddd.c')
693endfunc
694
695" vim: shiftwidth=2 sts=2 expandtab
696