test_syntax.vim (29109B)
1 " Test for syntax and syntax iskeyword option 2 3 source check.vim 4 CheckFeature syntax 5 6 source view_util.vim 7 source screendump.vim 8 9 func 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 28 endfunc 29 30 func AssertHighlightGroups(lnum, startcol, expected, trans = 1, msg = "") 31 " Assert that the characters starting at a given (line, col) 32 " sequentially match the expected highlight groups. 33 " If groups are provided as a string, each character is assumed to be a 34 " group and spaces represent no group, useful for visually describing tests. 35 let l:expectedGroups = type(a:expected) == v:t_string 36 \ ? a:expected->split('\zs')->map({_, v -> trim(v)}) 37 \ : a:expected 38 let l:errors = 0 39 let l:msg = (a:msg->empty() ? "" : a:msg .. ": ") 40 \ .. "Wrong highlight group at " .. a:lnum .. "," 41 42 for l:i in range(a:startcol, a:startcol + l:expectedGroups->len() - 1) 43 let l:errors += synID(a:lnum, l:i, a:trans) 44 \ ->synIDattr("name") 45 \ ->assert_equal(l:expectedGroups[l:i - 1], 46 \ l:msg .. l:i) 47 endfor 48 endfunc 49 50 func Test_syn_iskeyword() 51 new 52 call setline(1, [ 53 \ 'CREATE TABLE FOOBAR(', 54 \ ' DLTD_BY VARCHAR2(100)', 55 \ ');', 56 \ '']) 57 58 syntax on 59 set ft=sql 60 syn match SYN /C\k\+\>/ 61 hi link SYN ErrorMsg 62 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 63 /\<D\k\+\>/:norm! ygn 64 call assert_equal('DLTD_BY', @0) 65 redir @c 66 syn iskeyword 67 redir END 68 call assert_equal("\nsyntax iskeyword not set", @c) 69 70 syn iskeyword @,48-57,_,192-255 71 redir @c 72 syn iskeyword 73 redir END 74 call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c) 75 76 setlocal isk-=_ 77 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 78 /\<D\k\+\>/:norm! ygn 79 let b2 = @0 80 call assert_equal('DLTD', @0) 81 82 syn iskeyword clear 83 redir @c 84 syn iskeyword 85 redir END 86 call assert_equal("\nsyntax iskeyword not set", @c) 87 88 quit! 89 endfunc 90 91 func Test_syntax_after_reload() 92 split Xsomefile 93 call setline(1, ['hello', 'there']) 94 w! 95 only! 96 setl filetype=hello 97 au FileType hello let g:gotit = 1 98 call assert_false(exists('g:gotit')) 99 edit other 100 buf Xsomefile 101 call assert_equal('hello', &filetype) 102 call assert_true(exists('g:gotit')) 103 call delete('Xsomefile') 104 endfunc 105 106 func Test_syntime() 107 if !has('profile') 108 return 109 endif 110 111 syntax on 112 syntime on 113 let a = execute('syntime report') 114 call assert_equal("\nNo Syntax items defined for this buffer", a) 115 116 let a = execute('syntime clear') 117 call assert_equal("\nNo Syntax items defined for this buffer", a) 118 119 view ../memfile_test.c 120 setfiletype cpp 121 redraw 122 let a = execute('syntime report') 123 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 124 call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a) 125 call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a) 126 127 syntime off 128 syntime clear 129 let a = execute('syntime report') 130 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 131 call assert_notmatch('.* cppRawString *', a) 132 call assert_notmatch('.* cppNumber*', a) 133 call assert_notmatch('[1-9]', a) 134 135 call assert_fails('syntime abc', 'E475') 136 137 syntax clear 138 let a = execute('syntime report') 139 call assert_equal("\nNo Syntax items defined for this buffer", a) 140 141 bd 142 endfunc 143 144 func Test_syntime_completion() 145 if !has('profile') 146 return 147 endif 148 149 call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx') 150 call assert_equal('"syntime clear off on report', @:) 151 endfunc 152 153 func Test_syntax_list() 154 syntax on 155 let a = execute('syntax list') 156 call assert_equal("\nNo Syntax items defined for this buffer", a) 157 158 view ../memfile_test.c 159 setfiletype c 160 161 let a = execute('syntax list') 162 call assert_match('cInclude*', a) 163 call assert_match('cDefine', a) 164 165 let a = execute('syntax list cDefine') 166 call assert_notmatch('cInclude*', a) 167 call assert_match('cDefine', a) 168 call assert_match(' links to Macro$', a) 169 170 call assert_fails('syntax list ABCD', 'E28:') 171 call assert_fails('syntax list @ABCD', 'E392:') 172 173 syntax clear 174 let a = execute('syntax list') 175 call assert_equal("\nNo Syntax items defined for this buffer", a) 176 177 syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc 178 let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int" 179 call assert_equal(exp, split(execute("syntax list"), "\n")[1]) 180 181 bd 182 endfunc 183 184 func Test_syntax_completion() 185 call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') 186 call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:) 187 188 call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') 189 call assert_equal('"syn case ignore match', @:) 190 191 call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx') 192 call assert_equal('"syn spell default notoplevel toplevel', @:) 193 194 call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx') 195 call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:) 196 197 " Check that clearing "Aap" avoids it showing up before Boolean. 198 hi @Aap ctermfg=blue 199 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 200 call assert_match('^"syn list @Aap @attribute @attribute.builtin @boolean @character ', @:) 201 hi clear @Aap 202 203 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 204 call assert_match('^"syn list @attribute @attribute.builtin @boolean @character ', @:) 205 206 call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx') 207 call assert_match('^"syn match @attribute @attribute.builtin @boolean @character ', @:) 208 209 syn cluster Aax contains=Aap 210 call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx') 211 call assert_match('^"syn list @Aax', @:) 212 endfunc 213 214 func Test_echohl_completion() 215 call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx') 216 " call assert_equal('"echohl NonText Normal none', @:) 217 call assert_equal('"echohl NonText Normal NormalFloat NormalNC none', @:) 218 endfunc 219 220 func Test_syntax_arg_skipped() 221 syn clear 222 syntax case ignore 223 if 0 224 syntax case match 225 endif 226 call assert_match('case ignore', execute('syntax case')) 227 228 syn keyword Foo foo 229 call assert_match('Foo', execute('syntax')) 230 syn clear 231 call assert_match('case match', execute('syntax case')) 232 call assert_notmatch('Foo', execute('syntax')) 233 234 if has('conceal') 235 syn clear 236 syntax conceal on 237 if 0 238 syntax conceal off 239 endif 240 call assert_match('conceal on', execute('syntax conceal')) 241 syn clear 242 call assert_match('conceal off', execute('syntax conceal')) 243 endif 244 245 syntax conceal on 246 syntax conceal off 247 call assert_match('conceal off', execute('syntax conceal')) 248 249 syntax region Bar start=/</ end=/>/ 250 if 0 251 syntax region NotTest start=/</ end=/>/ contains=@Spell 252 endif 253 call assert_match('Bar', execute('syntax')) 254 call assert_notmatch('NotTest', execute('syntax')) 255 call assert_notmatch('Spell', execute('syntax')) 256 257 hi Foo ctermfg=blue 258 let a = execute('hi Foo') 259 if 0 260 syntax rest 261 endif 262 call assert_equal(a, execute('hi Foo')) 263 hi clear Bar 264 hi clear Foo 265 266 set ft=tags 267 syn off 268 if 0 269 syntax enable 270 endif 271 call assert_match('No Syntax items defined', execute('syntax')) 272 syntax enable 273 call assert_match('tagComment', execute('syntax')) 274 set ft= 275 276 syn clear 277 if 0 278 syntax include @Spell nothing 279 endif 280 call assert_notmatch('Spell', execute('syntax')) 281 282 syn clear 283 syn iskeyword 48-57,$,_ 284 call assert_match('48-57,$,_', execute('syntax iskeyword')) 285 if 0 286 syn clear 287 syn iskeyword clear 288 endif 289 call assert_match('48-57,$,_', execute('syntax iskeyword')) 290 syn iskeyword clear 291 call assert_match('not set', execute('syntax iskeyword')) 292 syn iskeyword 48-57,$,_ 293 syn clear 294 call assert_match('not set', execute('syntax iskeyword')) 295 296 syn clear 297 syn keyword Foo foo 298 if 0 299 syn keyword NotAdded bar 300 endif 301 call assert_match('Foo', execute('syntax')) 302 call assert_notmatch('NotAdded', execute('highlight')) 303 304 syn clear 305 syn keyword Foo foo 306 call assert_match('Foo', execute('syntax')) 307 call assert_match('Foo', execute('syntax list')) 308 call assert_notmatch('Foo', execute('if 0 | syntax | endif')) 309 call assert_notmatch('Foo', execute('if 0 | syntax list | endif')) 310 311 syn clear 312 syn match Fopi /asdf/ 313 if 0 314 syn match Fopx /asdf/ 315 endif 316 call assert_match('Fopi', execute('syntax')) 317 call assert_notmatch('Fopx', execute('syntax')) 318 319 syn clear 320 syn spell toplevel 321 call assert_match('spell toplevel', execute('syntax spell')) 322 if 0 323 syn spell notoplevel 324 endif 325 call assert_match('spell toplevel', execute('syntax spell')) 326 syn spell notoplevel 327 call assert_match('spell notoplevel', execute('syntax spell')) 328 syn spell default 329 call assert_match('spell default', execute('syntax spell')) 330 331 syn clear 332 if 0 333 syntax cluster Spell 334 endif 335 call assert_notmatch('Spell', execute('syntax')) 336 337 syn clear 338 syn keyword Foo foo 339 syn sync ccomment 340 syn sync maxlines=5 341 if 0 342 syn sync maxlines=11 343 endif 344 call assert_match('on C-style comments', execute('syntax sync')) 345 call assert_match('maximal 5 lines', execute('syntax sync')) 346 syn sync clear 347 if 0 348 syn sync ccomment 349 endif 350 call assert_notmatch('on C-style comments', execute('syntax sync')) 351 syn sync fromstart 352 call assert_match('syncing starts at the first line', execute('syntax sync')) 353 354 syn clear 355 endfunc 356 357 " Check for an error. Used when multiple errors are thrown and we are checking 358 " for an earliest error. 359 func AssertFails(cmd, errcode) 360 let save_exception = '' 361 try 362 exe a:cmd 363 catch 364 let save_exception = v:exception 365 endtry 366 call assert_match(a:errcode, save_exception) 367 endfunc 368 369 func Test_syntax_invalid_arg() 370 call assert_fails('syntax case asdf', 'E390:') 371 if has('conceal') 372 call assert_fails('syntax conceal asdf', 'E390:') 373 endif 374 call assert_fails('syntax spell asdf', 'E390:') 375 call assert_fails('syntax clear @ABCD', 'E391:') 376 call assert_fails('syntax include random_file', 'E484:') 377 call assert_fails('syntax include <afile>', 'E495:') 378 call assert_fails('syntax sync x', 'E404:') 379 call assert_fails('syntax keyword Abc a[', 'E789:') 380 call assert_fails('syntax keyword Abc a[bc]d', 'E890:') 381 call assert_fails('syntax cluster Abc add=A add=', 'E406:') 382 383 " Test for too many \z\( and unmatched \z\( 384 " Not able to use assert_fails() here because both E50:/E879: and E475: 385 " messages are emitted. 386 set regexpengine=1 387 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:') 388 389 let cmd = "syntax region MyRegion start='" 390 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" 391 call AssertFails(cmd, 'E50:') 392 393 set regexpengine=2 394 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:') 395 396 let cmd = "syntax region MyRegion start='" 397 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" 398 call AssertFails(cmd, 'E879:') 399 set regexpengine& 400 401 call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:') 402 call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:') 403 call AssertFails('syn keyword Type contains int', 'E395:') 404 call assert_fails('syntax include @Xxx', 'E397:') 405 call AssertFails('syntax region X start', 'E398:') 406 call assert_fails('syntax region X start="{"', 'E399:') 407 call AssertFails('syntax cluster contains=Abc', 'E400:') 408 call AssertFails("syntax match Character /'.'", 'E401:') 409 call AssertFails("syntax match Character /'.'/a", 'E402:') 410 call assert_fails('syntax sync linecont /\%(/', 'E53:') 411 call assert_fails('syntax sync linecont /pat', 'E404:') 412 call assert_fails('syntax sync linecont', 'E404:') 413 call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:') 414 call assert_fails('syntax sync minlines=a', 'E404:') 415 call AssertFails('syntax match ABC /x/ contains=', 'E406:') 416 call AssertFails("syntax match Character contains /'.'/", 'E405:') 417 call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:') 418 call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:') 419 call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:') 420 call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:') 421 endfunc 422 423 func Test_syn_sync() 424 syntax region HereGroup start=/this/ end=/that/ 425 syntax sync match SyncHere grouphere HereGroup "pattern" 426 call assert_match('SyncHere', execute('syntax sync')) 427 syn sync clear 428 call assert_notmatch('SyncHere', execute('syntax sync')) 429 syn clear 430 endfunc 431 432 func Test_syn_clear() 433 syntax keyword Foo foo 434 syntax keyword Bar tar 435 call assert_match('Foo', execute('syntax')) 436 call assert_match('Bar', execute('syntax')) 437 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 438 syn clear Foo 439 call assert_notmatch('Foo', execute('syntax')) 440 call assert_match('Bar', execute('syntax')) 441 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 442 syn clear Foo Bar 443 call assert_notmatch('Foo', execute('syntax')) 444 call assert_notmatch('Bar', execute('syntax')) 445 hi clear Foo 446 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 447 hi clear Bar 448 call assert_fails('syntax clear invalid_syngroup', 'E28:') 449 endfunc 450 451 func Test_invalid_name() 452 syn clear 453 syn keyword Nop yes 454 call assert_fails("syntax keyword Wr\x17ong bar", 'E669:') 455 syntax keyword @Wrong bar 456 call assert_fails("syntax keyword @#Wrong bar", 'E5248:') 457 syn clear 458 hi clear Nop 459 hi clear @Wrong 460 endfunc 461 462 func Test_ownsyntax() 463 new XfooOwnSyntax 464 call setline(1, '#define FOO') 465 syntax on 466 set filetype=c 467 468 ownsyntax perl 469 " this should not crash 470 set 471 472 call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name')) 473 call assert_equal('c', b:current_syntax) 474 call assert_equal('perl', w:current_syntax) 475 476 " A new split window should have the original syntax. 477 split 478 call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name')) 479 call assert_equal('c', b:current_syntax) 480 call assert_equal(0, exists('w:current_syntax')) 481 482 wincmd x 483 call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name")) 484 485 syntax off 486 set filetype& 487 %bw! 488 endfunc 489 490 func Test_ownsyntax_completion() 491 call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx') 492 call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:) 493 endfunc 494 495 func Test_highlight_invalid_arg() 496 if has('gui_running') 497 call assert_fails('hi XXX guifg=xxx', 'E254:') 498 endif 499 call assert_fails('hi DoesNotExist', 'E411:') 500 call assert_fails('hi link', 'E412:') 501 call assert_fails('hi link a', 'E412:') 502 call assert_fails('hi link a b c', 'E413:') 503 call assert_fails('hi XXX =', 'E415:') 504 call assert_fails('hi XXX cterm', 'E416:') 505 call assert_fails('hi XXX cterm=', 'E417:') 506 call assert_fails('hi XXX cterm=DoesNotExist', 'E418:') 507 call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:') 508 call assert_fails('hi XXX xxx=White', 'E423:') 509 endfunc 510 511 func Test_conceal() 512 if !has('conceal') 513 return 514 endif 515 516 new 517 call setline(1, ['', '123456']) 518 syn match test23 "23" conceal cchar=X 519 syn match test45 "45" conceal 520 521 set conceallevel=0 522 call assert_equal('123456 ', ScreenLines(2, 7)[0]) 523 call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 524 525 set conceallevel=1 526 call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) 527 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)')) 528 529 set conceallevel=1 530 set listchars=conceal:Y 531 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)')) 532 call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) 533 534 set conceallevel=2 535 call assert_match('1X6 ', ScreenLines(2, 7)[0]) 536 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)')) 537 538 set conceallevel=3 539 call assert_match('16 ', ScreenLines(2, 7)[0]) 540 call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 541 542 call AssertFails("syntax match Entity '&' conceal cchar=\<Tab>", 'E844:') 543 544 syn clear 545 set conceallevel& 546 bw! 547 endfunc 548 549 func Test_bg_detection() 550 CheckNotGui 551 552 " auto-detection of &bg, make sure it isn't set anywhere before this test 553 hi Normal ctermbg=0 554 call assert_equal('dark', &bg) 555 hi Normal ctermbg=4 556 call assert_equal('dark', &bg) 557 hi Normal ctermbg=12 558 call assert_equal('light', &bg) 559 hi Normal ctermbg=15 560 call assert_equal('light', &bg) 561 562 " manually-set &bg takes precedence over auto-detection 563 set bg=light 564 hi Normal ctermbg=4 565 call assert_equal('light', &bg) 566 set bg=dark 567 hi Normal ctermbg=12 568 call assert_equal('dark', &bg) 569 570 hi Normal ctermbg=NONE 571 endfunc 572 573 func Test_syntax_hangs() 574 if !has('reltime') || !has('float') || !has('syntax') 575 return 576 endif 577 578 " This pattern takes a long time to match, it should timeout. 579 new 580 call setline(1, ['aaa', repeat('abc ', 1000), 'ccc']) 581 let start = reltime() 582 set nolazyredraw redrawtime=101 583 syn match Error /\%#=1a*.*X\@<=b*/ 584 redraw 585 let elapsed = reltimefloat(reltime(start)) 586 call assert_true(elapsed > 0.1) 587 call assert_true(elapsed < 1.0) 588 589 " second time syntax HL is disabled 590 let start = reltime() 591 redraw 592 let elapsed = reltimefloat(reltime(start)) 593 call assert_true(elapsed < 0.1) 594 595 " after CTRL-L the timeout flag is reset 596 let start = reltime() 597 exe "normal \<C-L>" 598 redraw 599 let elapsed = reltimefloat(reltime(start)) 600 call assert_true(elapsed > 0.1) 601 call assert_true(elapsed < 1.0) 602 603 set redrawtime& 604 bwipe! 605 endfunc 606 607 func Test_synstack_synIDtrans() 608 new 609 setfiletype c 610 syntax on 611 call setline(1, ' /* A comment with a TODO */') 612 613 call assert_equal([], synstack(1, 1)) 614 615 norm f/ 616 eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart']) 617 eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment']) 618 619 norm fA 620 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 621 call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 622 623 norm fT 624 call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 625 call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 626 627 call assert_fails("let n=synIDtrans([])", 'E745:') 628 629 syn clear 630 bw! 631 endfunc 632 633 " Check highlighting for a small piece of C code with a screen dump. 634 func Test_syntax_c() 635 CheckScreendump 636 CheckRunVimInTerminal 637 call writefile([ 638 \ '/* comment line at the top */', 639 \ 'int main(int argc, char **argv) { // another comment', 640 \ '#if 0', 641 \ ' int not_used;', 642 \ '#else', 643 \ ' int used;', 644 \ '#endif', 645 \ ' printf("Just an example piece of C code\n");', 646 \ ' return 0x0ff;', 647 \ '}', 648 \ "\t\t ", 649 \ ' static void', 650 \ 'myFunction(const double count, struct nothing, long there) {', 651 \ "\t// 123: nothing to endif here", 652 \ "\tfor (int i = 0; i < count; ++i) {", 653 \ "\t break;", 654 \ "\t}", 655 \ "\tNote: asdf", 656 \ '}', 657 \ ], 'Xtest.c', 'D') 658 659 " This makes the default for 'background' use "dark", check that the 660 " response to t_RB corrects it to "light". 661 let $COLORFGBG = '15;0' 662 663 let buf = RunVimInTerminal('Xtest.c', {}) 664 call term_sendkeys(buf, ":syn keyword Search Note\r") 665 call VerifyScreenDump(buf, 'Test_syntax_c_01', {}) 666 call StopVimInTerminal(buf) 667 668 let $COLORFGBG = '' 669 endfun 670 671 " Test \z(...) along with \z1 672 func Test_syn_zsub() 673 new 674 syntax on 675 call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx') 676 let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ' 677 678 for l:re in [0, 1, 2] 679 " Example taken from :help :syn-ext-match 680 syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1" 681 eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re) 682 syntax clear Z 683 endfor 684 685 set re& 686 bw! 687 endfunc 688 689 " Using \z() in a region with NFA failing should not crash. 690 func Test_syn_wrong_z_one() 691 new 692 call setline(1, ['just some text', 'with foo and bar to match with']) 693 syn region FooBar start="foo\z(.*\)bar" end="\z1" 694 " call test_override("nfa_fail", 1) 695 redraw! 696 redraw! 697 " call test_override("ALL", 0) 698 bwipe! 699 endfunc 700 701 func Test_syntax_after_bufdo() 702 call writefile(['/* aaa comment */'], 'Xaaa.c', 'D') 703 call writefile(['/* bbb comment */'], 'Xbbb.c', 'D') 704 call writefile(['/* ccc comment */'], 'Xccc.c', 'D') 705 call writefile(['/* ddd comment */'], 'Xddd.c', 'D') 706 707 let bnr = bufnr('%') 708 new Xaaa.c 709 badd Xbbb.c 710 badd Xccc.c 711 badd Xddd.c 712 exe "bwipe " . bnr 713 let l = [] 714 bufdo call add(l, bufnr('%')) 715 call assert_equal(4, len(l)) 716 717 syntax on 718 719 " This used to only enable syntax HL in the last buffer. 720 bufdo tab split 721 tabrewind 722 for tab in range(1, 4) 723 norm fm 724 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 725 tabnext 726 endfor 727 728 bwipe! Xaaa.c 729 bwipe! Xbbb.c 730 bwipe! Xccc.c 731 bwipe! Xddd.c 732 syntax off 733 endfunc 734 735 func Test_syntax_foldlevel() 736 new 737 call setline(1, [ 738 \ 'void f(int a)', 739 \ '{', 740 \ ' if (a == 1) {', 741 \ ' a = 0;', 742 \ ' } else if (a == 2) {', 743 \ ' a = 1;', 744 \ ' } else {', 745 \ ' a = 2;', 746 \ ' }', 747 \ ' if (a > 0) {', 748 \ ' if (a == 1) {', 749 \ ' a = 0;', 750 \ ' } /* missing newline */ } /* end of outer if */ else {', 751 \ ' a = 1;', 752 \ ' }', 753 \ ' if (a == 1)', 754 \ ' {', 755 \ ' a = 0;', 756 \ ' }', 757 \ ' else if (a == 2)', 758 \ ' {', 759 \ ' a = 1;', 760 \ ' }', 761 \ ' else', 762 \ ' {', 763 \ ' a = 2;', 764 \ ' }', 765 \ '}', 766 \ ]) 767 setfiletype c 768 syntax on 769 set foldmethod=syntax 770 771 call assert_fails('syn foldlevel start start', 'E390') 772 call assert_fails('syn foldlevel not_an_option', 'E390') 773 774 set foldlevel=1 775 776 syn foldlevel start 777 redir @c 778 syn foldlevel 779 redir END 780 call assert_equal("\nsyntax foldlevel start", @c) 781 syn sync fromstart 782 call assert_match('from the first line$', execute('syn sync')) 783 let a = map(range(3,9), 'foldclosed(v:val)') 784 call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together 785 let a = map(range(10,15), 'foldclosed(v:val)') 786 call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden 787 let a = map(range(16,27), 'foldclosed(v:val)') 788 let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25] 789 call assert_equal(unattached_results, a) " unattached cascade folds separately 790 791 syn foldlevel minimum 792 redir @c 793 syn foldlevel 794 redir END 795 call assert_equal("\nsyntax foldlevel minimum", @c) 796 syn sync fromstart 797 let a = map(range(3,9), 'foldclosed(v:val)') 798 call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately 799 let a = map(range(10,15), 'foldclosed(v:val)') 800 call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible 801 let a = map(range(16,27), 'foldclosed(v:val)') 802 call assert_equal(unattached_results, a) " unattached cascade folds separately 803 804 set foldlevel=2 805 806 syn foldlevel start 807 syn sync fromstart 808 let a = map(range(11,14), 'foldclosed(v:val)') 809 call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden 810 811 syn foldlevel minimum 812 syn sync fromstart 813 let a = map(range(11,14), 'foldclosed(v:val)') 814 call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible 815 816 quit! 817 endfunc 818 819 func Test_search_syntax_skip() 820 new 821 let lines =<< trim END 822 823 /* This is VIM */ 824 Another Text for VIM 825 let a = "VIM" 826 END 827 call setline(1, lines) 828 syntax on 829 syntax match Comment "^/\*.*\*/" 830 syntax match String '".*"' 831 832 " Skip argument using string evaluation. 833 1 834 call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"') 835 call assert_equal('Another Text for VIM', getline('.')) 836 837 1 838 call search('VIM', 'cw', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"') 839 call assert_equal(' let a = "VIM"', getline('.')) 840 841 " Skip argument using Lambda. 842 1 843 call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"}) 844 call assert_equal('Another Text for VIM', getline('.')) 845 846 1 847 call search('VIM', 'cw', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"}) 848 call assert_equal(' let a = "VIM"', getline('.')) 849 850 " Skip argument using funcref. 851 func InComment() 852 return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment" 853 endfunc 854 func NotInString() 855 return synIDattr(synID(line("."), col("."), 1), "name") !~? "string" 856 endfunc 857 858 1 859 call search('VIM', 'w', '', 0, function('InComment')) 860 call assert_equal('Another Text for VIM', getline('.')) 861 862 1 863 call search('VIM', 'cw', '', 0, function('NotInString')) 864 call assert_equal(' let a = "VIM"', getline('.')) 865 866 delfunc InComment 867 delfunc NotInString 868 bwipe! 869 endfunc 870 871 func Test_syn_contained_transparent() 872 " Comments starting with "Regression:" show the result when the highlighting 873 " span of the containing item is assigned to the contained region. 874 syntax on 875 876 let l:case = "Transparent region contained in region" 877 new 878 syntax region X start=/\[/ end=/\]/ contained transparent 879 syntax region Y start=/(/ end=/)/ contains=X 880 881 call setline(1, "==(--[~~]--)==") 882 let l:expected = " YYYYYYYYYY " 883 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 884 syntax clear Y X 885 bw! 886 887 let l:case = "Transparent region extends region" 888 new 889 syntax region X start=/\[/ end=/\]/ contained transparent 890 syntax region Y start=/(/ end=/)/ end=/e/ contains=X 891 892 call setline(1, "==(--[~~e~~]--)==") 893 let l:expected = " YYYYYYYYYYYYY " 894 " Regression: " YYYYYYY YYY " 895 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 896 syntax clear Y X 897 bw! 898 899 let l:case = "Nested transparent regions extend region" 900 new 901 syntax region X start=/\[/ end=/\]/ contained transparent 902 syntax region Y start=/(/ end=/)/ end=/e/ contains=X 903 904 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") 905 let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY " 906 " Regression: " YYYYYYY YYYYYYYYY " 907 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 908 syntax clear Y X 909 bw! 910 911 let l:case = "Transparent region contained in match" 912 new 913 syntax region X start=/\[/ end=/\]/ contained transparent 914 syntax match Y /(.\{-})/ contains=X 915 916 call setline(1, "==(--[~~]--)==") 917 let l:expected = " YYYYYYYYYY " 918 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 919 syntax clear Y X 920 bw! 921 922 let l:case = "Transparent region extends match" 923 new 924 syntax region X start=/\[/ end=/\]/ contained transparent 925 syntax match Y /(.\{-}[e)]/ contains=X 926 927 call setline(1, "==(--[~~e~~]--)==") 928 let l:expected = " YYYYYYYYYY " 929 " Regression: " YYYYYYY " 930 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 931 syntax clear Y X 932 bw! 933 934 let l:case = "Nested transparent regions extend match" 935 new 936 syntax region X start=/\[/ end=/\]/ contained transparent 937 syntax match Y /(.\{-}[e)]/ contains=X 938 939 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") 940 let l:expected = " YYYYYYYYYYYYYYYYYYYYYY " 941 " Regression: " YYYYYYY YYYYYY " 942 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 943 syntax clear Y X 944 bw! 945 endfunc 946 947 func Test_syn_include_contains_TOP() 948 let l:case = "TOP in included syntax refers to top level of that included syntax" 949 new 950 syntax include @INCLUDED syntax/c.vim 951 syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED 952 953 call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ]) 954 let l:expected = ["cCppOutIf2"] 955 eval AssertHighlightGroups(3, 1, l:expected, 1) 956 " cCppOutElse has contains=TOP 957 let l:expected = ["cType"] 958 eval AssertHighlightGroups(5, 1, l:expected, 1, l:case) 959 syntax clear 960 bw! 961 endfunc 962 963 func Test_syn_include_contains_TOP_excluding() 964 new 965 syntax include @INCLUDED syntax/c.vim 966 syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED 967 968 call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#if', '#endif', '```' ]) 969 let l:expected = ["cCppOutElse", "cConditional"] 970 eval AssertHighlightGroups(6, 1, l:expected, 1) 971 syntax clear 972 bw! 973 endfunc 974 975 " This was using freed memory 976 func Test_WinEnter_synstack_synID() 977 autocmd WinEnter * call synstack(line("."), col(".")) 978 autocmd WinEnter * call synID(line('.'), col('.') - 1, 1) 979 call setline(1, 'aaaaa') 980 normal! $ 981 new 982 close 983 984 au! WinEnter 985 bw! 986 endfunc 987 988 989 " vim: shiftwidth=2 sts=2 expandtab