xref: /vim-8.2.3635/src/testdir/test_syntax.vim (revision 2387773d)
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:')
335endfunc
336
337func Test_syn_sync()
338  syntax region HereGroup start=/this/ end=/that/
339  syntax sync match SyncHere grouphere HereGroup "pattern"
340  call assert_match('SyncHere', execute('syntax sync'))
341  syn sync clear
342  call assert_notmatch('SyncHere', execute('syntax sync'))
343  syn clear
344endfunc
345
346func Test_syn_clear()
347  syntax keyword Foo foo
348  syntax keyword Bar tar
349  call assert_match('Foo', execute('syntax'))
350  call assert_match('Bar', execute('syntax'))
351  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
352  syn clear Foo
353  call assert_notmatch('Foo', execute('syntax'))
354  call assert_match('Bar', execute('syntax'))
355  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
356  syn clear Foo Bar
357  call assert_notmatch('Foo', execute('syntax'))
358  call assert_notmatch('Bar', execute('syntax'))
359  hi clear Foo
360  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
361  hi clear Bar
362endfunc
363
364func Test_invalid_name()
365  syn clear
366  syn keyword Nop yes
367  call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
368  syntax keyword @Wrong bar
369  call assert_match('W18:', execute('1messages'))
370  syn clear
371  hi clear Nop
372  hi clear @Wrong
373endfunc
374
375func Test_ownsyntax()
376  new Xfoo
377  call setline(1, '#define FOO')
378  syntax on
379  set filetype=c
380  ownsyntax perl
381  call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
382  call assert_equal('c',    b:current_syntax)
383  call assert_equal('perl', w:current_syntax)
384
385  " A new split window should have the original syntax.
386  split
387  call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
388  call assert_equal('c', b:current_syntax)
389  call assert_equal(0, exists('w:current_syntax'))
390
391  wincmd x
392  call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
393
394  syntax off
395  set filetype&
396  %bw!
397endfunc
398
399func Test_ownsyntax_completion()
400  call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
401  call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
402endfunc
403
404func Test_highlight_invalid_arg()
405  if has('gui_running')
406    call assert_fails('hi XXX guifg=xxx', 'E254:')
407  endif
408  call assert_fails('hi DoesNotExist', 'E411:')
409  call assert_fails('hi link', 'E412:')
410  call assert_fails('hi link a', 'E412:')
411  call assert_fails('hi link a b c', 'E413:')
412  call assert_fails('hi XXX =', 'E415:')
413  call assert_fails('hi XXX cterm', 'E416:')
414  call assert_fails('hi XXX cterm=', 'E417:')
415  call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
416  call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
417  call assert_fails('hi XXX xxx=White', 'E423:')
418endfunc
419
420func Test_bg_detection()
421  CheckNotGui
422
423  " auto-detection of &bg, make sure sure it isn't set anywhere before
424  " this test
425  hi Normal ctermbg=0
426  call assert_equal('dark', &bg)
427  hi Normal ctermbg=4
428  call assert_equal('dark', &bg)
429  hi Normal ctermbg=12
430  call assert_equal('light', &bg)
431  hi Normal ctermbg=15
432  call assert_equal('light', &bg)
433
434  " manually-set &bg takes precedence over auto-detection
435  set bg=light
436  hi Normal ctermbg=4
437  call assert_equal('light', &bg)
438  set bg=dark
439  hi Normal ctermbg=12
440  call assert_equal('dark', &bg)
441
442  hi Normal ctermbg=NONE
443endfunc
444
445func Test_syntax_hangs()
446  if !has('reltime') || !has('float') || !has('syntax')
447    return
448  endif
449
450  " This pattern takes a long time to match, it should timeout.
451  new
452  call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
453  let start = reltime()
454  set nolazyredraw redrawtime=101
455  syn match Error /\%#=1a*.*X\@<=b*/
456  redraw
457  let elapsed = reltimefloat(reltime(start))
458  call assert_true(elapsed > 0.1)
459  call assert_true(elapsed < 1.0)
460
461  " second time syntax HL is disabled
462  let start = reltime()
463  redraw
464  let elapsed = reltimefloat(reltime(start))
465  call assert_true(elapsed < 0.1)
466
467  " after CTRL-L the timeout flag is reset
468  let start = reltime()
469  exe "normal \<C-L>"
470  redraw
471  let elapsed = reltimefloat(reltime(start))
472  call assert_true(elapsed > 0.1)
473  call assert_true(elapsed < 1.0)
474
475  set redrawtime&
476  bwipe!
477endfunc
478
479func Test_conceal()
480  if !has('conceal')
481    return
482  endif
483
484  new
485  call setline(1, ['', '123456'])
486  syn match test23 "23" conceal cchar=X
487  syn match test45 "45" conceal
488
489  set conceallevel=0
490  call assert_equal('123456 ', ScreenLines(2, 7)[0])
491  call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
492
493  set conceallevel=1
494  call assert_equal('1X 6   ', ScreenLines(2, 7)[0])
495  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)'))
496
497  set conceallevel=1
498  set listchars=conceal:Y
499  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)'))
500  call assert_equal('1XY6   ', ScreenLines(2, 7)[0])
501
502  set conceallevel=2
503  call assert_match('1X6    ', ScreenLines(2, 7)[0])
504  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)'))
505
506  set conceallevel=3
507  call assert_match('16     ', ScreenLines(2, 7)[0])
508  call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
509
510  syn clear
511  set conceallevel&
512  bw!
513endfunc
514
515func Test_synstack_synIDtrans()
516  new
517  setfiletype c
518  syntax on
519  call setline(1, ' /* A comment with a TODO */')
520
521  call assert_equal([], synstack(1, 1))
522
523  norm f/
524  eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
525  eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
526
527  norm fA
528  call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
529  call assert_equal(['Comment'],  map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
530
531  norm fT
532  call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
533  call assert_equal(['Comment', 'Todo'],   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
534
535  syn clear
536  bw!
537endfunc
538
539" Check highlighting for a small piece of C code with a screen dump.
540func Test_syntax_c()
541  if !CanRunVimInTerminal()
542    throw 'Skipped: cannot make screendumps'
543  endif
544  call writefile([
545	\ '/* comment line at the top */',
546	\ 'int main(int argc, char **argv) { // another comment',
547	\ '#if 0',
548	\ '   int   not_used;',
549	\ '#else',
550	\ '   int   used;',
551	\ '#endif',
552	\ '   printf("Just an example piece of C code\n");',
553	\ '   return 0x0ff;',
554	\ '}',
555	\ "\t\t ",
556	\ '   static void',
557	\ 'myFunction(const double count, struct nothing, long there) {',
558	\ "\t// 123: nothing to endif here",
559	\ "\tfor (int i = 0; i < count; ++i) {",
560	\ "\t   break;",
561	\ "\t}",
562	\ "\tNote: asdf",
563	\ '}',
564	\ ], 'Xtest.c')
565
566  " This makes the default for 'background' use "dark", check that the
567  " response to t_RB corrects it to "light".
568  let $COLORFGBG = '15;0'
569
570  let buf = RunVimInTerminal('Xtest.c', {})
571  call term_sendkeys(buf, ":syn keyword Search Note\r")
572  call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
573  call term_sendkeys(buf, ":set hlsearch\r")
574  call term_sendkeys(buf, "/endif\r")
575  call term_sendkeys(buf, "vjfC")
576  call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
577
578  call term_sendkeys(buf, "\<Esc>")
579  call StopVimInTerminal(buf)
580
581  let $COLORFGBG = ''
582  call delete('Xtest.c')
583endfun
584
585" Using \z() in a region with NFA failing should not crash.
586func Test_syn_wrong_z_one()
587  new
588  call setline(1, ['just some text', 'with foo and bar to match with'])
589  syn region FooBar start="foo\z(.*\)bar" end="\z1"
590  call test_override("nfa_fail", 1)
591  redraw!
592  redraw!
593  call test_override("ALL", 0)
594  bwipe!
595endfunc
596
597func Test_syntax_after_bufdo()
598  call writefile(['/* aaa comment */'], 'Xaaa.c')
599  call writefile(['/* bbb comment */'], 'Xbbb.c')
600  call writefile(['/* ccc comment */'], 'Xccc.c')
601  call writefile(['/* ddd comment */'], 'Xddd.c')
602
603  let bnr = bufnr('%')
604  new Xaaa.c
605  badd Xbbb.c
606  badd Xccc.c
607  badd Xddd.c
608  exe "bwipe " . bnr
609  let l = []
610  bufdo call add(l, bufnr('%'))
611  call assert_equal(4, len(l))
612
613  syntax on
614
615  " This used to only enable syntax HL in the last buffer.
616  bufdo tab split
617  tabrewind
618  for tab in range(1, 4)
619    norm fm
620    call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
621    tabnext
622  endfor
623
624  bwipe! Xaaa.c
625  bwipe! Xbbb.c
626  bwipe! Xccc.c
627  bwipe! Xddd.c
628  syntax off
629  call delete('Xaaa.c')
630  call delete('Xbbb.c')
631  call delete('Xccc.c')
632  call delete('Xddd.c')
633endfunc
634