test_quickfix.vim (203884B)
1 " Test for the quickfix feature. 2 3 source check.vim 4 source vim9.vim 5 CheckFeature quickfix 6 7 source screendump.vim 8 9 set encoding=utf-8 10 11 func s:setup_commands(cchar) 12 if a:cchar == 'c' 13 command! -nargs=* -bang Xlist <mods>clist<bang> <args> 14 command! -nargs=* Xgetexpr <mods>cgetexpr <args> 15 command! -nargs=* Xaddexpr <mods>caddexpr <args> 16 command! -nargs=* -count Xolder <mods><count>colder <args> 17 command! -nargs=* Xnewer <mods>cnewer <args> 18 command! -nargs=* Xopen <mods> copen <args> 19 command! -nargs=* Xwindow <mods>cwindow <args> 20 command! -nargs=* Xbottom <mods>cbottom <args> 21 command! -nargs=* Xclose <mods>cclose <args> 22 command! -nargs=* -bang Xfile <mods>cfile<bang> <args> 23 command! -nargs=* Xgetfile <mods>cgetfile <args> 24 command! -nargs=* Xaddfile <mods>caddfile <args> 25 command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args> 26 command! -nargs=* Xgetbuffer <mods>cgetbuffer <args> 27 command! -nargs=* Xaddbuffer <mods>caddbuffer <args> 28 command! -nargs=* Xrewind <mods>crewind <args> 29 command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args> 30 command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args> 31 command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args> 32 command! -nargs=* -bang Xlast <mods>clast<bang> <args> 33 command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args> 34 command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args> 35 command! -nargs=* Xexpr <mods>cexpr <args> 36 command! -count=999 -nargs=* Xvimgrep <mods> <count>vimgrep <args> 37 command! -nargs=* Xvimgrepadd <mods> vimgrepadd <args> 38 command! -nargs=* Xgrep <mods> grep <args> 39 command! -nargs=* Xgrepadd <mods> grepadd <args> 40 command! -nargs=* Xhelpgrep helpgrep <args> 41 command! -nargs=0 -count Xcc <count>cc 42 command! -count=1 -nargs=0 Xbelow <mods><count>cbelow 43 command! -count=1 -nargs=0 Xabove <mods><count>cabove 44 command! -count=1 -nargs=0 Xbefore <mods><count>cbefore 45 command! -count=1 -nargs=0 Xafter <mods><count>cafter 46 command! -nargs=1 Xsethist <mods>set chistory=<args> 47 command! -nargs=0 Xsethistdefault <mods>set chistory& 48 let g:Xgetlist = function('getqflist') 49 let g:Xsetlist = function('setqflist') 50 call setqflist([], 'f') 51 else 52 command! -nargs=* -bang Xlist <mods>llist<bang> <args> 53 command! -nargs=* Xgetexpr <mods>lgetexpr <args> 54 command! -nargs=* Xaddexpr <mods>laddexpr <args> 55 command! -nargs=* -count Xolder <mods><count>lolder <args> 56 command! -nargs=* Xnewer <mods>lnewer <args> 57 command! -nargs=* Xopen <mods> lopen <args> 58 command! -nargs=* Xwindow <mods>lwindow <args> 59 command! -nargs=* Xbottom <mods>lbottom <args> 60 command! -nargs=* Xclose <mods>lclose <args> 61 command! -nargs=* -bang Xfile <mods>lfile<bang> <args> 62 command! -nargs=* Xgetfile <mods>lgetfile <args> 63 command! -nargs=* Xaddfile <mods>laddfile <args> 64 command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args> 65 command! -nargs=* Xgetbuffer <mods>lgetbuffer <args> 66 command! -nargs=* Xaddbuffer <mods>laddbuffer <args> 67 command! -nargs=* Xrewind <mods>lrewind <args> 68 command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args> 69 command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args> 70 command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args> 71 command! -nargs=* -bang Xlast <mods>llast<bang> <args> 72 command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args> 73 command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args> 74 command! -nargs=* Xexpr <mods>lexpr <args> 75 command! -count=999 -nargs=* Xvimgrep <mods> <count>lvimgrep <args> 76 command! -nargs=* Xvimgrepadd <mods> lvimgrepadd <args> 77 command! -nargs=* Xgrep <mods> lgrep <args> 78 command! -nargs=* Xgrepadd <mods> lgrepadd <args> 79 command! -nargs=* Xhelpgrep lhelpgrep <args> 80 command! -nargs=0 -count Xcc <count>ll 81 command! -count=1 -nargs=0 Xbelow <mods><count>lbelow 82 command! -count=1 -nargs=0 Xabove <mods><count>labove 83 command! -count=1 -nargs=0 Xbefore <mods><count>lbefore 84 command! -count=1 -nargs=0 Xafter <mods><count>lafter 85 command! -nargs=1 Xsethist <mods>set lhistory=<args> 86 command! -nargs=1 Xsetlocalhist <mods>setlocal lhistory=<args> 87 command! -nargs=0 Xsethistdefault <mods>set lhistory& 88 let g:Xgetlist = function('getloclist', [0]) 89 let g:Xsetlist = function('setloclist', [0]) 90 call setloclist(0, [], 'f') 91 endif 92 endfunc 93 94 " This must be run before any error lists are created. 95 func Test_AA_cc_no_errors() 96 call assert_fails('cc', 'E42:') 97 call assert_fails('ll', 'E42:') 98 endfunc 99 100 " Tests for the :clist and :llist commands 101 func XlistTests(cchar) 102 call s:setup_commands(a:cchar) 103 104 if a:cchar == 'l' 105 call assert_fails('llist', 'E776:') 106 endif 107 " With an empty list, command should return error 108 Xgetexpr [] 109 silent! Xlist 110 call assert_true(v:errmsg ==# 'E42: No Errors') 111 112 " Populate the list and then try 113 let lines =<< trim END 114 non-error 1 115 Xtestfile1:1:3:Line1 116 non-error 2 117 Xtestfile2:2:2:Line2 118 non-error| 3 119 Xtestfile3:3:1:Line3 120 END 121 Xgetexpr lines 122 123 " List only valid entries 124 let l = split(execute('Xlist', ''), "\n") 125 call assert_equal([' 2 Xtestfile1:1 col 3: Line1', 126 \ ' 4 Xtestfile2:2 col 2: Line2', 127 \ ' 6 Xtestfile3:3 col 1: Line3'], l) 128 129 " List all the entries 130 let l = split(execute('Xlist!', ''), "\n") 131 call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', 132 \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2', 133 \ ' 5: non-error| 3', ' 6 Xtestfile3:3 col 1: Line3'], l) 134 135 " List a range of errors 136 let l = split(execute('Xlist 3,6', ''), "\n") 137 call assert_equal([' 4 Xtestfile2:2 col 2: Line2', 138 \ ' 6 Xtestfile3:3 col 1: Line3'], l) 139 140 let l = split(execute('Xlist! 3,4', ''), "\n") 141 call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) 142 143 let l = split(execute('Xlist -6,-4', ''), "\n") 144 call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) 145 146 let l = split(execute('Xlist! -5,-3', ''), "\n") 147 call assert_equal([' 2 Xtestfile1:1 col 3: Line1', 148 \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) 149 150 " Test for '+' 151 let l = split(execute('Xlist! +2', ''), "\n") 152 call assert_equal([' 2 Xtestfile1:1 col 3: Line1', 153 \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) 154 155 " Ranged entries 156 call g:Xsetlist([{'lnum':10,'text':'Line1'}, 157 \ {'lnum':20,'col':10,'text':'Line2'}, 158 \ {'lnum':30,'col':15,'end_col':20,'text':'Line3'}, 159 \ {'lnum':40,'end_lnum':45,'text':'Line4'}, 160 \ {'lnum':50,'end_lnum':55,'col':15,'text':'Line5'}, 161 \ {'lnum':60,'end_lnum':65,'col':25,'end_col':35,'text':'Line6'}]) 162 let l = split(execute('Xlist', ""), "\n") 163 call assert_equal([' 1:10: Line1', 164 \ ' 2:20 col 10: Line2', 165 \ ' 3:30 col 15-20: Line3', 166 \ ' 4:40-45: Line4', 167 \ ' 5:50-55 col 15: Line5', 168 \ ' 6:60-65 col 25-35: Line6'], l) 169 170 " Different types of errors 171 call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11}, 172 \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22}, 173 \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33}, 174 \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44}, 175 \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}, 176 \ {'lnum':0,'type':'e','text':'Check type field is output even when lnum==0. ("error" was not output by v9.0.0736.)','nr':66}]) 177 let l = split(execute('Xlist', ""), "\n") 178 call assert_equal([' 1:10 col 5 warning 11: Warning', 179 \ ' 2:20 col 10 error 22: Error', 180 \ ' 3:30 col 15 info 33: Info', 181 \ ' 4:40 col 20 x 44: Other', 182 \ ' 5:50 col 25 55: one', 183 \ ' 6 error 66: Check type field is output even when lnum==0. ("error" was not output by v9.0.0736.)'], l) 184 185 " Test for module names, one needs to explicitly set `'valid':v:true` so 186 call g:Xsetlist([ 187 \ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true}, 188 \ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true}, 189 \ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}]) 190 let l = split(execute('Xlist', ""), "\n") 191 call assert_equal([' 1 Data.Text:10 col 5 warning 11: ModuleWarning', 192 \ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning', 193 \ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l) 194 195 " Very long line should be displayed. 196 let text = 'Line' .. repeat('1234567890', 130) 197 let lines = ['Xtestfile9:2:9:' .. text] 198 Xgetexpr lines 199 200 let l = split(execute('Xlist', ''), "\n") 201 call assert_equal([' 1 Xtestfile9:2 col 9: ' .. text] , l) 202 203 " For help entries in the quickfix list, only the filename without directory 204 " should be displayed 205 Xhelpgrep setqflist() 206 let l = split(execute('Xlist 1', ''), "\n") 207 call assert_match('^ 1 [^\\/]\{-}:', l[0]) 208 209 " Error cases 210 call assert_fails('Xlist abc', 'E488:') 211 endfunc 212 213 func Test_clist() 214 call XlistTests('c') 215 call XlistTests('l') 216 endfunc 217 218 " Tests for the :colder, :cnewer, :lolder and :lnewer commands 219 " Note that this test assumes that a quickfix/location list is 220 " already set by the caller. 221 func XageTests(cchar) 222 call s:setup_commands(a:cchar) 223 224 if a:cchar == 'l' 225 " No location list for the current window 226 call assert_fails('lolder', 'E776:') 227 call assert_fails('lnewer', 'E776:') 228 endif 229 230 let list = [{'bufnr': bufnr('%'), 'lnum': 1}] 231 call g:Xsetlist(list) 232 233 " Jumping to a non existent list should return error 234 silent! Xolder 99 235 call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') 236 237 silent! Xnewer 99 238 call assert_true(v:errmsg ==# 'E381: At top of quickfix stack') 239 240 " Add three quickfix/location lists 241 Xgetexpr ['Xtestfile1:1:3:Line1'] 242 Xgetexpr ['Xtestfile2:2:2:Line2'] 243 Xgetexpr ['Xtestfile3:3:1:Line3'] 244 245 " Go back two lists 246 Xolder 247 let l = g:Xgetlist() 248 call assert_equal('Line2', l[0].text) 249 250 " Go forward two lists 251 Xnewer 252 let l = g:Xgetlist() 253 call assert_equal('Line3', l[0].text) 254 255 " Test for the optional count argument 256 Xolder 2 257 let l = g:Xgetlist() 258 call assert_equal('Line1', l[0].text) 259 260 Xnewer 2 261 let l = g:Xgetlist() 262 call assert_equal('Line3', l[0].text) 263 endfunc 264 265 func Test_cage() 266 call XageTests('c') 267 call XageTests('l') 268 endfunc 269 270 " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen 271 " commands 272 func XwindowTests(cchar) 273 call s:setup_commands(a:cchar) 274 275 " Opening the location list window without any errors should fail 276 if a:cchar == 'l' 277 call assert_fails('lopen', 'E776:') 278 call assert_fails('lwindow', 'E776:') 279 endif 280 281 " Create a list with no valid entries 282 Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3'] 283 284 " Quickfix/Location window should not open with no valid errors 285 Xwindow 286 call assert_true(winnr('$') == 1) 287 288 " Create a list with valid entries 289 let lines =<< trim END 290 Xtestfile1:1:3:Line1 291 Xtestfile2:2:2:Line2 292 Xtestfile3:3:1:Line3 293 END 294 Xgetexpr lines 295 296 " Open the window 297 Xwindow 298 call assert_true(winnr('$') == 2 && winnr() == 2 && 299 \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') 300 redraw! 301 302 " Close the window 303 Xclose 304 call assert_true(winnr('$') == 1) 305 306 " Create a list with no valid entries 307 Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3'] 308 309 " Open the window 310 Xopen 5 311 call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1' 312 \ && winheight(0) == 5) 313 314 " Opening the window again, should move the cursor to that window 315 wincmd t 316 Xopen 7 317 call assert_true(winnr('$') == 2 && winnr() == 2 && 318 \ winheight(0) == 7 && 319 \ getline('.') ==# '|| non-error 1') 320 321 " :cnext in quickfix window should move to the next entry 322 Xnext 323 call assert_equal(2, g:Xgetlist({'idx' : 0}).idx) 324 325 " Calling cwindow should close the quickfix window with no valid errors 326 Xwindow 327 call assert_true(winnr('$') == 1) 328 329 " Specifying the width should adjust the width for a vertically split 330 " quickfix window. 331 vert Xopen 332 call assert_equal(10, winwidth(0)) 333 vert Xopen 12 334 call assert_equal(12, winwidth(0)) 335 Xclose 336 337 " Horizontally or vertically splitting the quickfix window should create a 338 " normal window/buffer 339 Xopen 340 wincmd s 341 call assert_equal(0, getwininfo(win_getid())[0].quickfix) 342 call assert_equal(0, getwininfo(win_getid())[0].loclist) 343 call assert_notequal('quickfix', &buftype) 344 close 345 Xopen 346 wincmd v 347 call assert_equal(0, getwininfo(win_getid())[0].quickfix) 348 call assert_equal(0, getwininfo(win_getid())[0].loclist) 349 call assert_notequal('quickfix', &buftype) 350 close 351 Xopen 352 Xclose 353 354 if a:cchar == 'c' 355 " Opening the quickfix window in multiple tab pages should reuse the 356 " quickfix buffer 357 let lines =<< trim END 358 Xtestfile1:1:3:Line1 359 Xtestfile2:2:2:Line2 360 Xtestfile3:3:1:Line3 361 END 362 Xgetexpr lines 363 Xopen 364 let qfbufnum = bufnr('%') 365 tabnew 366 Xopen 367 call assert_equal(qfbufnum, bufnr('%')) 368 new | only | tabonly 369 endif 370 endfunc 371 372 func Test_cwindow() 373 call XwindowTests('c') 374 call XwindowTests('l') 375 endfunc 376 377 func Test_copenHeight() 378 copen 379 wincmd H 380 let height = winheight(0) 381 copen 10 382 call assert_equal(height, winheight(0)) 383 quit 384 endfunc 385 386 func Test_copenHeight_tabline() 387 set tabline=foo showtabline=2 388 copen 389 wincmd H 390 let height = winheight(0) 391 copen 10 392 call assert_equal(height, winheight(0)) 393 quit 394 set tabline& showtabline& 395 endfunc 396 397 " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile 398 " commands. 399 func XfileTests(cchar) 400 call s:setup_commands(a:cchar) 401 402 let lines =<< trim END 403 Xtestfile1:700:10:Line 700 404 Xtestfile2:800:15:Line 800 405 END 406 call writefile(lines, 'Xqftestfile1') 407 408 enew! 409 Xfile Xqftestfile1 410 let l = g:Xgetlist() 411 call assert_true(len(l) == 2 && 412 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && 413 \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') 414 415 " Test with a non existent file 416 call assert_fails('Xfile non_existent_file', 'E40') 417 418 " Run cfile/lfile from a modified buffer 419 enew! 420 silent! put ='Quickfix' 421 silent! Xfile Xqftestfile1 422 call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)') 423 424 call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') 425 Xaddfile Xqftestfile1 426 let l = g:Xgetlist() 427 call assert_true(len(l) == 3 && 428 \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') 429 430 let lines =<< trim END 431 Xtestfile1:222:77:Line 222 432 Xtestfile2:333:88:Line 333 433 END 434 call writefile(lines, 'Xqftestfile1') 435 436 enew! 437 Xgetfile Xqftestfile1 438 let l = g:Xgetlist() 439 call assert_true(len(l) == 2 && 440 \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && 441 \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') 442 443 " Test for a file with a long line and without a newline at the end 444 let text = repeat('x', 1024) 445 let t = 'a.txt:18:' . text 446 call writefile([t], 'Xqftestfile1', 'b') 447 silent! Xfile Xqftestfile1 448 call assert_equal(text, g:Xgetlist()[0].text) 449 450 call delete('Xqftestfile1') 451 endfunc 452 453 func Test_cfile() 454 call XfileTests('c') 455 call XfileTests('l') 456 endfunc 457 458 " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and 459 " :lgetbuffer commands. 460 func XbufferTests(cchar) 461 call s:setup_commands(a:cchar) 462 463 enew! 464 let lines =<< trim END 465 Xtestfile7:700:10:Line 700 466 Xtestfile8:800:15:Line 800 467 END 468 silent! call setline(1, lines) 469 Xbuffer! 470 let l = g:Xgetlist() 471 call assert_true(len(l) == 2 && 472 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && 473 \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') 474 475 enew! 476 let lines =<< trim END 477 Xtestfile9:900:55:Line 900 478 Xtestfile10:950:66:Line 950 479 END 480 silent! call setline(1, lines) 481 Xgetbuffer 482 let l = g:Xgetlist() 483 call assert_true(len(l) == 2 && 484 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && 485 \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') 486 487 enew! 488 let lines =<< trim END 489 Xtestfile11:700:20:Line 700 490 Xtestfile12:750:25:Line 750 491 END 492 silent! call setline(1, lines) 493 Xaddbuffer 494 let l = g:Xgetlist() 495 call assert_true(len(l) == 4 && 496 \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && 497 \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && 498 \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') 499 enew! 500 501 " Check for invalid buffer 502 call assert_fails('Xbuffer 199', 'E474:') 503 504 " Check for unloaded buffer 505 edit Xtestfile1 506 let bnr = bufnr('%') 507 enew! 508 call assert_fails('Xbuffer ' . bnr, 'E681:') 509 510 " Check for invalid range 511 " Using Xbuffer will not run the range check in the cbuffer/lbuffer 512 " commands. So directly call the commands. 513 if (a:cchar == 'c') 514 call assert_fails('900,999cbuffer', 'E16:') 515 else 516 call assert_fails('900,999lbuffer', 'E16:') 517 endif 518 endfunc 519 520 func Test_cbuffer() 521 call XbufferTests('c') 522 call XbufferTests('l') 523 endfunc 524 525 func XexprTests(cchar) 526 call s:setup_commands(a:cchar) 527 528 call assert_fails('Xexpr 10', 'E777:') 529 endfunc 530 531 func Test_cexpr() 532 call XexprTests('c') 533 call XexprTests('l') 534 endfunc 535 536 " Tests for :cnext, :cprev, :cfirst, :clast commands 537 func Xtest_browse(cchar) 538 call s:setup_commands(a:cchar) 539 540 call g:Xsetlist([], 'f') 541 " Jumping to first or next location list entry without any error should 542 " result in failure 543 if a:cchar == 'c' 544 let err = 'E42:' 545 let cmd = '$cc' 546 else 547 let err = 'E776:' 548 let cmd = '$ll' 549 endif 550 call assert_fails('Xnext', err) 551 call assert_fails('Xprev', err) 552 call assert_fails('Xnfile', err) 553 call assert_fails('Xpfile', err) 554 call assert_fails(cmd, err) 555 556 Xexpr '' 557 call assert_fails(cmd, 'E42:') 558 559 call s:create_test_file('Xqftestfile1') 560 call s:create_test_file('Xqftestfile2') 561 562 let lines =<< trim END 563 Xqftestfile1:5:Line5 564 Xqftestfile1:6:Line6 565 Xqftestfile2:10:Line10 566 Xqftestfile2:11:Line11 567 RegularLine1 568 RegularLine2 569 END 570 Xgetexpr lines 571 572 Xfirst 573 call assert_fails('-5Xcc', 'E16:') 574 call assert_fails('Xprev', 'E553') 575 call assert_fails('Xpfile', 'E553') 576 Xnfile 577 call assert_equal('Xqftestfile2', @%) 578 call assert_equal(10, line('.')) 579 Xpfile 580 call assert_equal('Xqftestfile1', @%) 581 call assert_equal(6, line('.')) 582 5Xcc 583 call assert_equal(5, g:Xgetlist({'idx':0}).idx) 584 2Xcc 585 call assert_equal(2, g:Xgetlist({'idx':0}).idx) 586 if a:cchar == 'c' 587 cc 588 else 589 ll 590 endif 591 call assert_equal(2, g:Xgetlist({'idx':0}).idx) 592 10Xcc 593 call assert_equal(6, g:Xgetlist({'idx':0}).idx) 594 Xlast 595 Xprev 596 call assert_equal('Xqftestfile2', @%) 597 call assert_equal(11, line('.')) 598 call assert_fails('Xnext', 'E553') 599 call assert_fails('Xnfile', 'E553') 600 " To process the range using quickfix list entries, directly use the 601 " quickfix commands (don't use the user defined commands) 602 if a:cchar == 'c' 603 $cc 604 else 605 $ll 606 endif 607 call assert_equal(6, g:Xgetlist({'idx':0}).idx) 608 Xrewind 609 call assert_equal('Xqftestfile1', @%) 610 call assert_equal(5, line('.')) 611 612 10Xnext 613 call assert_equal('Xqftestfile2', @%) 614 call assert_equal(11, line('.')) 615 10Xprev 616 call assert_equal('Xqftestfile1', @%) 617 call assert_equal(5, line('.')) 618 619 " Jumping to an error from the error window using cc command 620 let lines =<< trim END 621 Xqftestfile1:5:Line5 622 Xqftestfile1:6:Line6 623 Xqftestfile2:10:Line10 624 Xqftestfile2:11:Line11 625 END 626 Xgetexpr lines 627 Xopen 628 10Xcc 629 call assert_equal(11, line('.')) 630 call assert_equal('Xqftestfile2', @%) 631 Xopen 632 call cursor(2, 1) 633 if a:cchar == 'c' 634 .cc 635 else 636 .ll 637 endif 638 call assert_equal(6, line('.')) 639 call assert_equal('Xqftestfile1', @%) 640 641 " Jumping to an error from the error window (when only the error window is 642 " present) 643 Xopen | only 644 Xlast 1 645 call assert_equal(5, line('.')) 646 call assert_equal('Xqftestfile1', @%) 647 648 Xexpr "" 649 call assert_fails('Xnext', 'E42:') 650 651 call delete('Xqftestfile1') 652 call delete('Xqftestfile2') 653 654 " Should be able to use next/prev with invalid entries 655 Xexpr "" 656 call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) 657 call assert_equal(0, g:Xgetlist({'size' : 0}).size) 658 Xaddexpr ['foo', 'bar', 'baz', 'quux', 'sh|moo'] 659 call assert_equal(5, g:Xgetlist({'size' : 0}).size) 660 Xlast 661 call assert_equal(5, g:Xgetlist({'idx' : 0}).idx) 662 Xfirst 663 call assert_equal(1, g:Xgetlist({'idx' : 0}).idx) 664 2Xnext 665 call assert_equal(3, g:Xgetlist({'idx' : 0}).idx) 666 endfunc 667 668 func Test_browse() 669 call Xtest_browse('c') 670 call Xtest_browse('l') 671 endfunc 672 673 " Test for memory allocation failures 674 func Xnomem_tests(cchar) 675 call s:setup_commands(a:cchar) 676 677 call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0) 678 call assert_fails('Xvimgrep vim runtest.vim', 'E342:') 679 680 call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0) 681 call assert_fails('Xvimgrep vim runtest.vim', 'E342:') 682 683 call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0) 684 call assert_fails('Xfile runtest.vim', 'E342:') 685 686 call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0) 687 call assert_fails('Xfile runtest.vim', 'E342:') 688 689 call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0) 690 call assert_fails('Xfile runtest.vim', 'E342:') 691 692 call test_alloc_fail(GetAllocId('qf_efm_fmtstr'), 0, 0) 693 set efm=%f 694 call assert_fails('Xexpr ["Xfile1"]', 'E342:') 695 set efm& 696 697 call test_alloc_fail(GetAllocId('qf_efm_fmtpart'), 0, 0) 698 set efm=%f:%l:%m,%f-%l-%m 699 call assert_fails('Xaddexpr ["Xfile2", "Xfile3"]', 'E342:') 700 set efm& 701 702 call test_alloc_fail(GetAllocId('qf_title'), 0, 0) 703 call assert_fails('Xexpr ""', 'E342:') 704 call assert_equal('', g:Xgetlist({'all': 1}).title) 705 706 call test_alloc_fail(GetAllocId('qf_mef_name'), 0, 0) 707 set makeef=Xtmp##.err 708 call assert_fails('Xgrep needle haystack', 'E342:') 709 set makeef& 710 711 call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0) 712 call assert_fails('Xexpr "Xfile1:10:Line10"', 'E342:') 713 714 if a:cchar == 'l' 715 for id in ['qf_qfline', 'qf_qfinfo'] 716 lgetexpr ["Xfile1:10:L10", "Xfile2:20:L20"] 717 call test_alloc_fail(GetAllocId(id), 0, 0) 718 call assert_fails('new', 'E342:') 719 call assert_equal(2, winnr('$')) 720 call assert_equal([], getloclist(0)) 721 %bw! 722 endfor 723 endif 724 725 call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0) 726 try 727 call assert_fails('Xvimgrep vim runtest.vim', 'E342:') 728 catch /^Vim:Interrupt$/ 729 endtry 730 731 call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0) 732 try 733 call assert_fails('Xvimgrep /vim/f runtest.vim', 'E342:') 734 catch /^Vim:Interrupt$/ 735 endtry 736 737 let l = getqflist({"lines": ["Xfile1:10:L10"]}) 738 call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0) 739 call assert_fails('call g:Xsetlist(l.items)', 'E342:') 740 741 call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0) 742 try 743 call assert_fails('Xhelpgrep quickfix', 'E342:') 744 catch /^Vim:Interrupt$/ 745 endtry 746 747 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 748 call assert_fails('let l = g:Xgetlist({"lines": ["Xfile1:10:L10"]})', 'E342:') 749 call assert_equal(#{items: []}, l) 750 751 if a:cchar == 'l' 752 call setqflist([], 'f') 753 call setloclist(0, [], 'f') 754 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 755 call assert_fails('lhelpgrep quickfix', 'E342:') 756 call assert_equal([], getloclist(0)) 757 758 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 759 call assert_fails('lvimgrep vim runtest.vim', 'E342:') 760 761 let l = getqflist({"lines": ["Xfile1:10:L10"]}) 762 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 763 call assert_fails('call setloclist(0, l.items)', 'E342:') 764 765 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 766 call assert_fails('lbuffer', 'E342:') 767 768 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 769 call assert_fails('lexpr ["Xfile1:10:L10", "Xfile2:20:L20"]', 'E342:') 770 771 call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0) 772 call assert_fails('lfile runtest.vim', 'E342:') 773 endif 774 775 call test_alloc_fail(GetAllocId('qf_dirstack'), 0, 0) 776 set efm=%DEntering\ dir\ %f,%f:%l:%m 777 call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E342:') 778 set efm& 779 780 call test_alloc_fail(GetAllocId('qf_dirstack'), 0, 0) 781 set efm=%+P[%f],(%l)%m 782 call assert_fails('Xexpr ["[runtest.vim]", "(1)Hello"]', 'E342:') 783 set efm& 784 785 call test_alloc_fail(GetAllocId('qf_multiline_pfx'), 0, 0) 786 set efm=%EError,%Cline\ %l,%Z%m 787 call assert_fails('Xexpr ["Error", "line 1", "msg"]', 'E342:') 788 set efm& 789 790 call test_alloc_fail(GetAllocId('qf_makecmd'), 0, 0) 791 call assert_fails('Xgrep vim runtest.vim', 'E342:') 792 793 call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0) 794 call assert_fails('Xexpr repeat("a", 8192)', 'E342:') 795 796 call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0) 797 call assert_fails('Xexpr [repeat("a", 8192)]', 'E342:') 798 799 new 800 call setline(1, repeat('a', 8192)) 801 call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0) 802 call assert_fails('Xbuffer', 'E342:') 803 %bw! 804 805 call writefile([repeat('a', 8192)], 'Xtest') 806 call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0) 807 call assert_fails('Xfile Xtest', 'E342:') 808 call delete('Xtest') 809 endfunc 810 811 func Test_nomem() 812 throw 'Skipped: Nvim does not support test_alloc_fail()' 813 call Xnomem_tests('c') 814 call Xnomem_tests('l') 815 endfunc 816 817 func s:test_xhelpgrep(cchar) 818 call s:setup_commands(a:cchar) 819 Xhelpgrep quickfix 820 Xopen 821 if a:cchar == 'c' 822 let title_text = ':helpgrep quickfix' 823 else 824 let title_text = ':lhelpgrep quickfix' 825 endif 826 call assert_true(w:quickfix_title =~ title_text, w:quickfix_title) 827 828 " Jumping to a help topic should open the help window 829 only 830 Xnext 831 call assert_true(&buftype == 'help') 832 call assert_true(winnr('$') == 2) 833 " Jumping to the next match should reuse the help window 834 Xnext 835 call assert_true(&buftype == 'help') 836 call assert_true(winnr() == 1) 837 call assert_true(winnr('$') == 2) 838 " Jumping to the next match from the quickfix window should reuse the help 839 " window 840 Xopen 841 Xnext 842 call assert_true(&buftype == 'help') 843 call assert_true(winnr() == 1) 844 call assert_true(winnr('$') == 2) 845 call assert_match('|\d\+ col \d\+-\d\+|', getbufline(winbufnr(2), 1)[0]) 846 847 " This wipes out the buffer, make sure that doesn't cause trouble. 848 Xclose 849 850 " When the current window is vertically split, jumping to a help match 851 " should open the help window at the top. 852 only | enew 853 let w1 = win_getid() 854 vert new 855 let w2 = win_getid() 856 Xnext 857 let w3 = win_getid() 858 call assert_true(&buftype == 'help') 859 call assert_true(winnr() == 1) 860 " See jump_to_help_window() for details 861 let w2_width = winwidth(w2) 862 if w2_width != &columns && w2_width < 80 863 call assert_equal(['col', [['leaf', w3], 864 \ ['row', [['leaf', w2], ['leaf', w1]]]]], winlayout()) 865 else 866 call assert_equal(['row', [['col', [['leaf', w3], ['leaf', w2]]], 867 \ ['leaf', w1]]] , winlayout()) 868 endif 869 870 new | only 871 set buftype=help 872 set modified 873 call assert_fails('Xnext', 'E37:') 874 set nomodified 875 new | only 876 877 if a:cchar == 'l' 878 " When a help window is present, running :lhelpgrep should reuse the 879 " help window and not the current window 880 new | only 881 call g:Xsetlist([], 'f') 882 help index.txt 883 wincmd w 884 lhelpgrep quickfix 885 call assert_equal(1, winnr()) 886 call assert_notequal([], getloclist(1)) 887 call assert_equal([], getloclist(2)) 888 endif 889 890 new | only 891 892 " Search for non existing help string 893 call assert_fails('Xhelpgrep a1b2c3', 'E480:') 894 " Invalid regular expression 895 call assert_fails('Xhelpgrep \@<!', 'E866:') 896 endfunc 897 898 func Test_helpgrep() 899 call s:test_xhelpgrep('c') 900 helpclose 901 call s:test_xhelpgrep('l') 902 endfunc 903 904 " When running the :helpgrep command, if an autocmd modifies the 'cpoptions' 905 " value, then Vim crashes. (issue fixed by 7.2b-004 and 8.2.4453) 906 func Test_helpgrep_restore_cpo_aucmd() 907 let save_cpo = &cpo 908 augroup QF_Test 909 au! 910 autocmd BufNew * set cpo=acd 911 augroup END 912 913 helpgrep quickfix 914 call assert_equal('acd', &cpo) 915 %bw! 916 917 set cpo&vim 918 augroup QF_Test 919 au! 920 autocmd BufReadPost * set cpo= 921 augroup END 922 923 helpgrep buffer 924 call assert_equal('', &cpo) 925 926 augroup QF_Test 927 au! 928 augroup END 929 %bw! 930 let &cpo = save_cpo 931 endfunc 932 933 func Test_errortitle() 934 augroup QfBufWinEnter 935 au! 936 au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE') 937 augroup END 938 copen 939 let a=[{'lnum': 308, 'bufnr': bufnr(''), 'col': 58, 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'pattern': '', 'text': ' au BufWinEnter * :let g:a=get(w:, ''quickfix_title'', ''NONE'')'}] 940 call setqflist(a) 941 call assert_equal(':setqflist()', g:a) 942 augroup QfBufWinEnter 943 au! 944 augroup END 945 augroup! QfBufWinEnter 946 endfunc 947 948 func Test_vimgreptitle() 949 augroup QfBufWinEnter 950 au! 951 au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE') 952 augroup END 953 try 954 vimgrep /pattern/j file 955 catch /E480/ 956 endtry 957 copen 958 call assert_equal(': vimgrep /pattern/j file', g:a) 959 augroup QfBufWinEnter 960 au! 961 augroup END 962 augroup! QfBufWinEnter 963 endfunc 964 965 func Test_bufwinenter_once() 966 augroup QfBufWinEnter 967 au! 968 au BufWinEnter * let g:got_afile ..= 'got ' .. expand('<afile>') 969 augroup END 970 let g:got_afile = '' 971 copen 972 call assert_equal('got quickfix', g:got_afile) 973 974 cclose 975 unlet g:got_afile 976 augroup QfBufWinEnter 977 au! 978 augroup END 979 augroup! QfBufWinEnter 980 endfunc 981 982 func XqfTitleTests(cchar) 983 call s:setup_commands(a:cchar) 984 985 Xgetexpr ['file:1:1:message'] 986 let l = g:Xgetlist() 987 if a:cchar == 'c' 988 call setqflist(l, 'r') 989 else 990 call setloclist(0, l, 'r') 991 endif 992 993 Xopen 994 if a:cchar == 'c' 995 let title = ':setqflist()' 996 else 997 let title = ':setloclist()' 998 endif 999 call assert_equal(title, w:quickfix_title) 1000 Xclose 1001 endfunc 1002 1003 " Tests for quickfix window's title 1004 func Test_qf_title() 1005 call XqfTitleTests('c') 1006 call XqfTitleTests('l') 1007 endfunc 1008 1009 " Tests for 'errorformat' 1010 func Test_efm() 1011 let save_efm = &efm 1012 set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%# 1013 cgetexpr ['WWWW', 'EEEE', 'CCCC'] 1014 let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) 1015 call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l) 1016 cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC'] 1017 let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) 1018 call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l) 1019 cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY'] 1020 let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) 1021 call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l) 1022 let &efm = save_efm 1023 endfunc 1024 1025 " This will test for problems in quickfix: 1026 " A. incorrectly copying location lists which caused the location list to show 1027 " a different name than the file that was actually being displayed. 1028 " B. not reusing the window for which the location list window is opened but 1029 " instead creating new windows. 1030 " C. make sure that the location list window is not reused instead of the 1031 " window it belongs to. 1032 " 1033 " Set up the test environment: 1034 func ReadTestProtocol(name) 1035 let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') 1036 let word = substitute(base, '\v(.*)\..*', '\1', '') 1037 1038 setl modifiable 1039 setl noreadonly 1040 setl noswapfile 1041 setl bufhidden=delete 1042 %del _ 1043 " For problem 2: 1044 " 'buftype' has to be set to reproduce the constant opening of new windows 1045 setl buftype=nofile 1046 1047 call setline(1, word) 1048 1049 setl nomodified 1050 setl nomodifiable 1051 setl readonly 1052 exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '') 1053 endfunc 1054 1055 func Test_locationlist() 1056 enew 1057 1058 augroup testgroup 1059 au! 1060 autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>")) 1061 augroup END 1062 1063 let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ] 1064 1065 let qflist = [] 1066 for word in words 1067 call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', }) 1068 " NOTE: problem 1: 1069 " intentionally not setting 'lnum' so that the quickfix entries are not 1070 " valid 1071 eval qflist->setloclist(0, ' ') 1072 endfor 1073 1074 " Test A 1075 lrewind 1076 enew 1077 lopen 1078 4lnext 1079 vert split 1080 wincmd L 1081 lopen 1082 wincmd p 1083 lnext 1084 let fileName = expand("%") 1085 wincmd p 1086 let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '') 1087 let fileName = substitute(fileName, '\\', '/', 'g') 1088 let locationListFileName = substitute(locationListFileName, '\\', '/', 'g') 1089 call assert_equal("test://bar.txt", fileName) 1090 call assert_equal("test://bar.txt", locationListFileName) 1091 1092 wincmd n | only 1093 1094 " Test B: 1095 lrewind 1096 lopen 1097 2 1098 exe "normal \<CR>" 1099 wincmd p 1100 3 1101 exe "normal \<CR>" 1102 wincmd p 1103 4 1104 exe "normal \<CR>" 1105 call assert_equal(2, winnr('$')) 1106 wincmd n | only 1107 1108 " Test C: 1109 lrewind 1110 lopen 1111 " Let's move the location list window to the top to check whether it (the 1112 " first window found) will be reused when we try to open new windows: 1113 wincmd K 1114 2 1115 exe "normal \<CR>" 1116 wincmd p 1117 3 1118 exe "normal \<CR>" 1119 wincmd p 1120 4 1121 exe "normal \<CR>" 1122 1wincmd w 1123 call assert_equal('quickfix', &buftype) 1124 2wincmd w 1125 let bufferName = expand("%") 1126 let bufferName = substitute(bufferName, '\\', '/', 'g') 1127 call assert_equal('test://quux.txt', bufferName) 1128 1129 wincmd n | only 1130 1131 augroup! testgroup 1132 endfunc 1133 1134 func Test_locationlist_curwin_was_closed() 1135 augroup testgroup 1136 au! 1137 autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>")) 1138 augroup END 1139 1140 func! R(n) 1141 quit 1142 endfunc 1143 1144 new 1145 let q = [] 1146 call add(q, {'filename': 'test_curwin.txt' }) 1147 call setloclist(0, q) 1148 call assert_fails('lrewind', 'E924:') 1149 1150 augroup! testgroup 1151 delfunc R 1152 endfunc 1153 1154 func Test_locationlist_cross_tab_jump() 1155 call writefile(['loclistfoo'], 'loclistfoo') 1156 call writefile(['loclistbar'], 'loclistbar') 1157 set switchbuf=usetab 1158 1159 edit loclistfoo 1160 tabedit loclistbar 1161 silent lgrep loclistfoo loclist* 1162 call assert_equal(1, tabpagenr()) 1163 1164 enew | only | tabonly 1165 set switchbuf&vim 1166 call delete('loclistfoo') 1167 call delete('loclistbar') 1168 endfunc 1169 1170 " More tests for 'errorformat' 1171 func Test_efm1() 1172 " The 'errorformat' setting is different on non-Unix systems. 1173 " This test works only on Unix-like systems. 1174 CheckUnix 1175 1176 let l =<< trim [DATA] 1177 "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. 1178 "Xtestfile", line 6 col 19; this is an error 1179 gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c 1180 Xtestfile:9: parse error before `asd' 1181 make: *** [src/vim/testdir/Makefile:100: test_quickfix] Error 1 1182 in file "Xtestfile" linenr 10: there is an error 1183 1184 2 returned 1185 "Xtestfile", line 11 col 1; this is an error 1186 "Xtestfile", line 12 col 2; this is another error 1187 "Xtestfile", line 14:10; this is an error in column 10 1188 =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time 1189 "Xtestfile", linenr 16: yet another problem 1190 Error in "Xtestfile" at line 17: 1191 x should be a dot 1192 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 1193 ^ 1194 Error in "Xtestfile" at line 18: 1195 x should be a dot 1196 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 1197 .............^ 1198 Error in "Xtestfile" at line 19: 1199 x should be a dot 1200 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 1201 --------------^ 1202 Error in "Xtestfile" at line 20: 1203 x should be a dot 1204 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 1205 ^ 1206 1207 Does anyone know what is the problem and how to correction it? 1208 "Xtestfile", line 21 col 9: What is the title of the quickfix window? 1209 "Xtestfile", line 22 col 9: What is the title of the quickfix window? 1210 [DATA] 1211 1212 call writefile(l, 'Xerrorfile1') 1213 call writefile(l[:-2], 'Xerrorfile2') 1214 1215 let m =<< [DATA] 1216 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 1217 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 1218 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 1219 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 1220 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 1221 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 1222 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 1223 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 1224 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 1225 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 1226 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 1227 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 1228 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 1229 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 1230 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 1231 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 1232 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 1233 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 1234 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 1235 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 1236 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 1237 [DATA] 1238 call writefile(m, 'Xtestfile') 1239 1240 let save_efm = &efm 1241 set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m 1242 set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m 1243 1244 exe 'cf Xerrorfile2' 1245 clast 1246 copen 1247 call assert_equal(':cf Xerrorfile2', w:quickfix_title) 1248 wincmd p 1249 1250 exe 'cf Xerrorfile1' 1251 call assert_equal([4, 12], [line('.'), col('.')]) 1252 cn 1253 call assert_equal([6, 19], [line('.'), col('.')]) 1254 cn 1255 call assert_equal([9, 2], [line('.'), col('.')]) 1256 cn 1257 call assert_equal([10, 2], [line('.'), col('.')]) 1258 cn 1259 call assert_equal([11, 1], [line('.'), col('.')]) 1260 cn 1261 call assert_equal([12, 2], [line('.'), col('.')]) 1262 cn 1263 call assert_equal([14, 10], [line('.'), col('.')]) 1264 cn 1265 call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')]) 1266 cn 1267 call assert_equal([16, 2], [line('.'), col('.')]) 1268 cn 1269 call assert_equal([17, 6], [line('.'), col('.')]) 1270 cn 1271 call assert_equal([18, 7], [line('.'), col('.')]) 1272 cn 1273 call assert_equal([19, 8], [line('.'), col('.')]) 1274 cn 1275 call assert_equal([20, 9], [line('.'), col('.')]) 1276 clast 1277 cprev 1278 cprev 1279 wincmd w 1280 call assert_equal(':cf Xerrorfile1', w:quickfix_title) 1281 wincmd p 1282 1283 let &efm = save_efm 1284 call delete('Xerrorfile1') 1285 call delete('Xerrorfile2') 1286 call delete('Xtestfile') 1287 endfunc 1288 1289 " Test for quickfix directory stack support 1290 func s:dir_stack_tests(cchar) 1291 call s:setup_commands(a:cchar) 1292 1293 let save_efm=&efm 1294 set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' 1295 1296 let lines =<< trim END 1297 Entering dir 'dir1/a' 1298 habits2.txt:1:Nine Healthy Habits 1299 Entering dir 'b' 1300 habits3.txt:2:0 Hours of television 1301 habits2.txt:7:5 Small meals 1302 Entering dir 'dir1/c' 1303 habits4.txt:3:1 Hour of exercise 1304 Leaving dir 'dir1/c' 1305 Leaving dir 'dir1/a' 1306 habits1.txt:4:2 Liters of water 1307 Entering dir 'dir2' 1308 habits5.txt:5:3 Cups of hot green tea 1309 Leaving dir 'dir2' 1310 END 1311 1312 Xexpr "" 1313 for l in lines 1314 Xaddexpr l 1315 endfor 1316 1317 let qf = g:Xgetlist() 1318 1319 call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr)) 1320 call assert_equal(1, qf[1].lnum) 1321 call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr)) 1322 call assert_equal(2, qf[3].lnum) 1323 call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr)) 1324 call assert_equal(7, qf[4].lnum) 1325 call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr)) 1326 call assert_equal(3, qf[6].lnum) 1327 call assert_equal('habits1.txt', bufname(qf[9].bufnr)) 1328 call assert_equal(4, qf[9].lnum) 1329 call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr)) 1330 call assert_equal(5, qf[11].lnum) 1331 1332 let &efm=save_efm 1333 endfunc 1334 1335 " Tests for %D and %X errorformat options 1336 func Test_efm_dirstack() 1337 " Create the directory stack and files 1338 call mkdir('dir1') 1339 call mkdir('dir1/a') 1340 call mkdir('dir1/a/b') 1341 call mkdir('dir1/c') 1342 call mkdir('dir2') 1343 1344 let lines =<< trim END 1345 Nine Healthy Habits 1346 0 Hours of television 1347 1 Hour of exercise 1348 2 Liters of water 1349 3 Cups of hot green tea 1350 4 Short mental breaks 1351 5 Small meals 1352 6 AM wake up time 1353 7 Minutes of laughter 1354 8 Hours of sleep (at least) 1355 9 PM end of the day and off to bed 1356 END 1357 call writefile(lines, 'habits1.txt') 1358 call writefile(lines, 'dir1/a/habits2.txt') 1359 call writefile(lines, 'dir1/a/b/habits3.txt') 1360 call writefile(lines, 'dir1/c/habits4.txt') 1361 call writefile(lines, 'dir2/habits5.txt') 1362 1363 call s:dir_stack_tests('c') 1364 call s:dir_stack_tests('l') 1365 1366 call delete('dir1', 'rf') 1367 call delete('dir2', 'rf') 1368 call delete('habits1.txt') 1369 endfunc 1370 1371 " Test for resync after continuing an ignored message 1372 func Xefm_ignore_continuations(cchar) 1373 call s:setup_commands(a:cchar) 1374 1375 let save_efm = &efm 1376 1377 let &efm = 1378 \ '%Eerror %m %l,' . 1379 \ '%-Wignored %m %l,' . 1380 \ '%+Cmore ignored %m %l,' . 1381 \ '%Zignored end' 1382 let lines =<< trim END 1383 ignored warning 1 1384 more ignored continuation 2 1385 ignored end 1386 error resync 4 1387 END 1388 Xgetexpr lines 1389 let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]') 1390 call assert_equal([['resync', 1, 4, 'E']], l) 1391 1392 let &efm = save_efm 1393 endfunc 1394 1395 func Test_efm_ignore_continuations() 1396 call Xefm_ignore_continuations('c') 1397 call Xefm_ignore_continuations('l') 1398 endfunc 1399 1400 " Tests for invalid error format specifies 1401 func Xinvalid_efm_Tests(cchar) 1402 call s:setup_commands(a:cchar) 1403 1404 let save_efm = &efm 1405 1406 set efm=%f:%l:%m,%f:%f:%l:%m 1407 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:') 1408 1409 set efm=%f:%l:%m,%f:%l:%r:%m 1410 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:') 1411 1412 set efm=%f:%l:%m,%O:%f:%l:%m 1413 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:') 1414 1415 set efm=%f:%l:%m,%f:%l:%*[^a-z 1416 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:') 1417 1418 set efm=%f:%l:%m,%f:%l:%*c 1419 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:') 1420 1421 set efm=%f:%l:%m,%L%M%N 1422 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:') 1423 1424 set efm=%f:%l:%m,%f:%l:%m:%R 1425 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:') 1426 1427 " Invalid regular expression 1428 set efm=%\\%%k 1429 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E867:') 1430 1431 set efm= 1432 call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:') 1433 1434 " Empty directory name. When there is an error in parsing new entries, make 1435 " sure the previous quickfix list is made the current list. 1436 set efm& 1437 cexpr ["one", "two"] 1438 let qf_id = getqflist(#{id: 0}).id 1439 set efm=%DEntering\ dir\ abc,%f:%l:%m 1440 call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:') 1441 call assert_equal(qf_id, getqflist(#{id: 0}).id) 1442 1443 let &efm = save_efm 1444 endfunc 1445 1446 func Test_invalid_efm() 1447 call Xinvalid_efm_Tests('c') 1448 call Xinvalid_efm_Tests('l') 1449 endfunc 1450 1451 " TODO: 1452 " Add tests for the following formats in 'errorformat' 1453 " %r %O 1454 func Test_efm2() 1455 let save_efm = &efm 1456 1457 " Test for %s format in efm 1458 set efm=%f:%s 1459 cexpr 'Xtestfile:Line search text' 1460 let l = getqflist() 1461 call assert_equal('^\VLine search text\$', l[0].pattern) 1462 call assert_equal(0, l[0].lnum) 1463 1464 let l = split(execute('clist', ''), "\n") 1465 call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l) 1466 1467 " Test for a long line 1468 cexpr 'Xtestfile:' . repeat('a', 1026) 1469 let l = getqflist() 1470 call assert_equal('^\V' . repeat('a', 1019) . '\$', l[0].pattern) 1471 1472 " Test for %P, %Q and %t format specifiers 1473 let lines =<< trim [DATA] 1474 [Xtestfile1] 1475 (1,17) error: ';' missing 1476 (21,2) warning: variable 'z' not defined 1477 (67,3) error: end of file found before string ended 1478 -- 1479 1480 [Xtestfile2] 1481 -- 1482 1483 [Xtestfile3] 1484 NEW compiler v1.1 1485 (2,2) warning: variable 'x' not defined 1486 (67,3) warning: 's' already defined 1487 -- 1488 [DATA] 1489 1490 set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r 1491 " To exercise the push/pop file functionality in quickfix, the test files 1492 " need to be created. 1493 call writefile(['Line1'], 'Xtestfile1') 1494 call writefile(['Line2'], 'Xtestfile2') 1495 call writefile(['Line3'], 'Xtestfile3') 1496 cexpr "" 1497 for l in lines 1498 caddexpr l 1499 endfor 1500 let l = getqflist() 1501 call assert_equal(12, len(l)) 1502 call assert_equal(21, l[2].lnum) 1503 call assert_equal(2, l[2].col) 1504 call assert_equal('w', l[2].type) 1505 call assert_equal('e', l[3].type) 1506 call delete('Xtestfile1') 1507 call delete('Xtestfile2') 1508 call delete('Xtestfile3') 1509 1510 " Test for %P, %Q with non-existing files 1511 cexpr lines 1512 let l = getqflist() 1513 call assert_equal(14, len(l)) 1514 call assert_equal('[Xtestfile1]', l[0].text) 1515 call assert_equal('[Xtestfile2]', l[6].text) 1516 call assert_equal('[Xtestfile3]', l[9].text) 1517 1518 " Tests for %E, %C and %Z format specifiers 1519 let lines =<< trim [DATA] 1520 Error 275 1521 line 42 1522 column 3 1523 ' ' expected after '--' 1524 [DATA] 1525 1526 set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m 1527 cgetexpr lines 1528 let l = getqflist() 1529 call assert_equal(275, l[0].nr) 1530 call assert_equal(42, l[0].lnum) 1531 call assert_equal(3, l[0].col) 1532 call assert_equal('E', l[0].type) 1533 call assert_equal("\n' ' expected after '--'", l[0].text) 1534 1535 " Test for %> 1536 let lines =<< trim [DATA] 1537 Error in line 147 of foo.c: 1538 unknown variable 'i' 1539 [DATA] 1540 1541 set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m 1542 cgetexpr lines 1543 let l = getqflist() 1544 call assert_equal(147, l[0].lnum) 1545 call assert_equal('E', l[0].type) 1546 call assert_equal("\nunknown variable 'i'", l[0].text) 1547 1548 " Test for %A, %C and other formats 1549 let lines =<< trim [DATA] 1550 ============================================================== 1551 FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest) 1552 -------------------------------------------------------------- 1553 Traceback (most recent call last): 1554 File "unittests/dbfacadeTest.py", line 89, in testFoo 1555 self.assertEquals(34, dtid) 1556 File "/usr/lib/python2.2/unittest.py", line 286, in 1557 failUnlessEqual 1558 raise self.failureException, \\ 1559 W:AssertionError: 34 != 33 1560 1561 -------------------------------------------------------------- 1562 Ran 27 tests in 0.063s 1563 [DATA] 1564 1565 set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%t:%m 1566 cgetexpr lines 1567 let l = getqflist() 1568 call assert_equal(8, len(l)) 1569 call assert_equal(89, l[4].lnum) 1570 call assert_equal(1, l[4].valid) 1571 call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) 1572 call assert_equal('W', l[4].type) 1573 1574 " Test for %o 1575 set efm=%f(%o):%l\ %m 1576 cgetexpr ['Xotestfile(Language.PureScript.Types):20 Error'] 1577 call writefile(['Line1'], 'Xotestfile') 1578 let l = getqflist() 1579 call assert_equal(1, len(l), string(l)) 1580 call assert_equal('Language.PureScript.Types', l[0].module) 1581 copen 1582 call assert_equal('Language.PureScript.Types|20| Error', getline(1)) 1583 call feedkeys("\<CR>", 'xn') 1584 call assert_equal('Xotestfile', expand('%:t')) 1585 cclose 1586 bd 1587 call delete("Xotestfile") 1588 1589 " Test for a long module name 1590 cexpr 'Xtest(' . repeat('m', 1026) . '):15 message' 1591 let l = getqflist() 1592 " call assert_equal(repeat('m', 1024), l[0].module) 1593 call assert_equal(repeat('m', 1023), l[0].module) 1594 call assert_equal(15, l[0].lnum) 1595 call assert_equal('message', l[0].text) 1596 1597 " The following sequence of commands used to crash Vim 1598 set efm=%W%m 1599 cgetexpr ['msg1'] 1600 let l = getqflist() 1601 call assert_equal(1, len(l), string(l)) 1602 call assert_equal('msg1', l[0].text) 1603 set efm=%C%m 1604 lexpr 'msg2' 1605 let l = getloclist(0) 1606 call assert_equal(1, len(l), string(l)) 1607 call assert_equal('msg2', l[0].text) 1608 lopen 1609 call setqflist([], 'r') 1610 caddbuf 1611 let l = getqflist() 1612 call assert_equal(1, len(l), string(l)) 1613 call assert_equal('|| msg2', l[0].text) 1614 1615 " When matching error lines, case should be ignored. Test for this. 1616 set noignorecase 1617 let l=getqflist({'lines' : ['Xtest:FOO10:Line 20'], 'efm':'%f:foo%l:%m'}) 1618 call assert_equal(10, l.items[0].lnum) 1619 call assert_equal('Line 20', l.items[0].text) 1620 set ignorecase& 1621 1622 new | only 1623 let &efm = save_efm 1624 endfunc 1625 1626 " Test for '%t' (error type) field in 'efm' 1627 func Test_efm_error_type() 1628 let save_efm = &efm 1629 1630 " error type 1631 set efm=%f:%l:%t:%m 1632 let lines =<< trim END 1633 Xfile1:10:E:msg1 1634 Xfile1:20:W:msg2 1635 Xfile1:30:I:msg3 1636 Xfile1:40:N:msg4 1637 Xfile1:50:R:msg5 1638 END 1639 cexpr lines 1640 let output = split(execute('clist'), "\n") 1641 call assert_equal([ 1642 \ ' 1 Xfile1:10 error: msg1', 1643 \ ' 2 Xfile1:20 warning: msg2', 1644 \ ' 3 Xfile1:30 info: msg3', 1645 \ ' 4 Xfile1:40 note: msg4', 1646 \ ' 5 Xfile1:50 R: msg5'], output) 1647 1648 " error type and a error number 1649 set efm=%f:%l:%t:%n:%m 1650 let lines =<< trim END 1651 Xfile1:10:E:2:msg1 1652 Xfile1:20:W:4:msg2 1653 Xfile1:30:I:6:msg3 1654 Xfile1:40:N:8:msg4 1655 Xfile1:50:R:3:msg5 1656 END 1657 cexpr lines 1658 let output = split(execute('clist'), "\n") 1659 call assert_equal([ 1660 \ ' 1 Xfile1:10 error 2: msg1', 1661 \ ' 2 Xfile1:20 warning 4: msg2', 1662 \ ' 3 Xfile1:30 info 6: msg3', 1663 \ ' 4 Xfile1:40 note 8: msg4', 1664 \ ' 5 Xfile1:50 R 3: msg5'], output) 1665 let &efm = save_efm 1666 endfunc 1667 1668 " Test for end_lnum ('%e') and end_col ('%k') fields in 'efm' 1669 func Test_efm_end_lnum_col() 1670 let save_efm = &efm 1671 1672 " single line 1673 set efm=%f:%l-%e:%c-%k:%t:%m 1674 cexpr ["Xfile1:10-20:1-2:E:msg1", "Xfile1:20-30:2-3:W:msg2",] 1675 let output = split(execute('clist'), "\n") 1676 call assert_equal([ 1677 \ ' 1 Xfile1:10-20 col 1-2 error: msg1', 1678 \ ' 2 Xfile1:20-30 col 2-3 warning: msg2'], output) 1679 1680 " multiple lines 1681 set efm=%A%n)%m,%Z%f:%l-%e:%c-%k 1682 let lines =<< trim END 1683 1)msg1 1684 Xfile1:14-24:1-2 1685 2)msg2 1686 Xfile1:24-34:3-4 1687 END 1688 cexpr lines 1689 let output = split(execute('clist'), "\n") 1690 call assert_equal([ 1691 \ ' 1 Xfile1:14-24 col 1-2 error 1: msg1', 1692 \ ' 2 Xfile1:24-34 col 3-4 error 2: msg2'], output) 1693 let &efm = save_efm 1694 endfunc 1695 1696 func XquickfixChangedByAutocmd(cchar) 1697 call s:setup_commands(a:cchar) 1698 if a:cchar == 'c' 1699 let ErrorNr = 'E925' 1700 func! ReadFunc() 1701 colder 1702 cgetexpr [] 1703 endfunc 1704 else 1705 let ErrorNr = 'E926' 1706 func! ReadFunc() 1707 lolder 1708 lgetexpr [] 1709 endfunc 1710 endif 1711 1712 augroup QF_Test 1713 au! 1714 autocmd BufReadCmd test_changed.txt call ReadFunc() 1715 augroup END 1716 1717 new | only 1718 let words = [ "a", "b" ] 1719 let qflist = [] 1720 for word in words 1721 call add(qflist, {'filename': 'test_changed.txt'}) 1722 call g:Xsetlist(qflist, ' ') 1723 endfor 1724 call assert_fails('Xrewind', ErrorNr . ':') 1725 1726 augroup QF_Test 1727 au! 1728 augroup END 1729 1730 if a:cchar == 'c' 1731 cexpr ["Xtest1:1:Line"] 1732 cwindow 1733 only 1734 augroup QF_Test 1735 au! 1736 autocmd WinEnter * call setqflist([], 'f') 1737 augroup END 1738 call assert_fails('exe "normal \<CR>"', 'E925:') 1739 augroup QF_Test 1740 au! 1741 augroup END 1742 endif 1743 %bw! 1744 endfunc 1745 1746 func Test_quickfix_was_changed_by_autocmd() 1747 call XquickfixChangedByAutocmd('c') 1748 call XquickfixChangedByAutocmd('l') 1749 endfunc 1750 1751 func Test_setloclist_in_autocommand() 1752 call writefile(['test1', 'test2'], 'Xfile') 1753 edit Xfile 1754 let s:bufnr = bufnr() 1755 call setloclist(1, 1756 \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'}, 1757 \ {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}]) 1758 1759 augroup Test_LocList 1760 au! 1761 autocmd BufEnter * call setloclist(1, 1762 \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'}, 1763 \ {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}], 'r') 1764 augroup END 1765 1766 lopen 1767 call assert_fails('exe "normal j\<CR>"', 'E926:') 1768 1769 augroup Test_LocList 1770 au! 1771 augroup END 1772 call delete('Xfile') 1773 endfunc 1774 1775 func Test_caddbuffer_to_empty() 1776 helpgr quickfix 1777 call setqflist([], 'r') 1778 cad 1779 try 1780 cn 1781 catch 1782 " number of matches is unknown 1783 call assert_true(v:exception =~ 'E553:') 1784 endtry 1785 quit! 1786 endfunc 1787 1788 func Test_cgetexpr_works() 1789 " this must not crash Vim 1790 cgetexpr [$x] 1791 lgetexpr [$x] 1792 endfunc 1793 1794 " Tests for the setqflist() and setloclist() functions 1795 func SetXlistTests(cchar, bnum) 1796 call s:setup_commands(a:cchar) 1797 1798 call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, 1799 \ {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5, 'user_data': {'6': [7, 8]}}]) 1800 let l = g:Xgetlist() 1801 call assert_equal(2, len(l)) 1802 call assert_equal(2, l[1].lnum) 1803 call assert_equal(3, l[1].end_lnum) 1804 call assert_equal(4, l[1].col) 1805 call assert_equal(5, l[1].end_col) 1806 call assert_equal({'6': [7, 8]}, l[1].user_data) 1807 1808 " Test that user_data is garbage collected 1809 call g:Xsetlist([{'user_data': ['high', 5]}, 1810 \ {'user_data': {'this': [7, 'eight'], 'is': ['a', 'dictionary']}}]) 1811 call test_garbagecollect_now() 1812 let l = g:Xgetlist() 1813 call assert_equal(2, len(l)) 1814 call assert_equal(['high', 5], l[0].user_data) 1815 call assert_equal({'this': [7, 'eight'], 'is': ['a', 'dictionary']}, l[1].user_data) 1816 1817 Xnext 1818 call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a') 1819 let l = g:Xgetlist() 1820 call assert_equal(3, len(l)) 1821 Xnext 1822 call assert_equal(3, line('.')) 1823 1824 " Appending entries to the list should not change the cursor position 1825 " in the quickfix window 1826 Xwindow 1827 1 1828 call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4}, 1829 \ {'bufnr': a:bnum, 'lnum': 5}], 'a') 1830 call assert_equal(1, line('.')) 1831 close 1832 1833 call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, 1834 \ {'bufnr': a:bnum, 'lnum': 4}, 1835 \ {'bufnr': a:bnum, 'lnum': 5}], 'r') 1836 let l = g:Xgetlist() 1837 call assert_equal(3, len(l)) 1838 call assert_equal(5, l[2].lnum) 1839 1840 call g:Xsetlist([]) 1841 let l = g:Xgetlist() 1842 call assert_equal(0, len(l)) 1843 1844 " Tests for setting the 'valid' flag 1845 call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}]) 1846 Xwindow 1847 call assert_equal(1, winnr('$')) 1848 let l = g:Xgetlist() 1849 call g:Xsetlist(l) 1850 call assert_equal(0, g:Xgetlist()[0].valid) 1851 " Adding a non-valid entry should not mark the list as having valid entries 1852 call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a') 1853 Xwindow 1854 call assert_equal(1, winnr('$')) 1855 1856 " :cnext/:cprev should still work even with invalid entries in the list 1857 let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0}, 1858 \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}] 1859 call g:Xsetlist(l) 1860 Xnext 1861 call assert_equal(2, g:Xgetlist({'idx' : 0}).idx) 1862 Xprev 1863 call assert_equal(1, g:Xgetlist({'idx' : 0}).idx) 1864 " :cnext/:cprev should still work after appending invalid entries to an 1865 " empty list 1866 call g:Xsetlist([]) 1867 call g:Xsetlist(l, 'a') 1868 Xnext 1869 call assert_equal(2, g:Xgetlist({'idx' : 0}).idx) 1870 Xprev 1871 call assert_equal(1, g:Xgetlist({'idx' : 0}).idx) 1872 1873 call g:Xsetlist([{'text':'Text1', 'valid':1}]) 1874 Xwindow 1875 call assert_equal(2, winnr('$')) 1876 Xclose 1877 let save_efm = &efm 1878 set efm=%m 1879 Xgetexpr 'TestMessage' 1880 let l = g:Xgetlist() 1881 call g:Xsetlist(l) 1882 call assert_equal(1, g:Xgetlist()[0].valid) 1883 let &efm = save_efm 1884 1885 " Error cases: 1886 " Refer to a non-existing buffer and pass a non-dictionary type 1887 call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," . 1888 \ " {'bufnr':999, 'lnum':5}])", 'E92:') 1889 call g:Xsetlist([[1, 2,3]]) 1890 call assert_equal(0, len(g:Xgetlist())) 1891 call assert_fails('call g:Xsetlist([], [])', 'E928:') 1892 call g:Xsetlist([v:_null_dict]) 1893 call assert_equal([], g:Xgetlist()) 1894 endfunc 1895 1896 func Test_setqflist() 1897 new Xtestfile | only 1898 let bnum = bufnr('%') 1899 call setline(1, range(1,5)) 1900 1901 call SetXlistTests('c', bnum) 1902 call SetXlistTests('l', bnum) 1903 1904 enew! 1905 call delete('Xtestfile') 1906 endfunc 1907 1908 func Xlist_empty_middle(cchar) 1909 call s:setup_commands(a:cchar) 1910 1911 " create three quickfix lists 1912 let @/ = 'Test_' 1913 Xvimgrep // test_quickfix.vim 1914 let testlen = len(g:Xgetlist()) 1915 call assert_true(testlen > 0) 1916 Xvimgrep empty test_quickfix.vim 1917 call assert_true(len(g:Xgetlist()) > 0) 1918 Xvimgrep matches test_quickfix.vim 1919 let matchlen = len(g:Xgetlist()) 1920 call assert_true(matchlen > 0) 1921 Xolder 1922 " make the middle list empty 1923 call g:Xsetlist([], 'r') 1924 call assert_true(len(g:Xgetlist()) == 0) 1925 Xolder 1926 call assert_equal(testlen, len(g:Xgetlist())) 1927 Xnewer 1928 Xnewer 1929 call assert_equal(matchlen, len(g:Xgetlist())) 1930 endfunc 1931 1932 func Test_setqflist_empty_middle() 1933 call Xlist_empty_middle('c') 1934 call Xlist_empty_middle('l') 1935 endfunc 1936 1937 func Xlist_empty_older(cchar) 1938 call s:setup_commands(a:cchar) 1939 1940 " create three quickfix lists 1941 Xvimgrep one test_quickfix.vim 1942 let onelen = len(g:Xgetlist()) 1943 call assert_true(onelen > 0) 1944 Xvimgrep two test_quickfix.vim 1945 let twolen = len(g:Xgetlist()) 1946 call assert_true(twolen > 0) 1947 Xvimgrep three test_quickfix.vim 1948 let threelen = len(g:Xgetlist()) 1949 call assert_true(threelen > 0) 1950 Xolder 2 1951 " make the first list empty, check the others didn't change 1952 call g:Xsetlist([], 'r') 1953 call assert_true(len(g:Xgetlist()) == 0) 1954 Xnewer 1955 call assert_equal(twolen, len(g:Xgetlist())) 1956 Xnewer 1957 call assert_equal(threelen, len(g:Xgetlist())) 1958 endfunc 1959 1960 func Test_setqflist_empty_older() 1961 call Xlist_empty_older('c') 1962 call Xlist_empty_older('l') 1963 endfunc 1964 1965 func XquickfixSetListWithAct(cchar) 1966 call s:setup_commands(a:cchar) 1967 1968 let list1 = [{'filename': 'fnameA', 'text': 'A'}, 1969 \ {'filename': 'fnameB', 'text': 'B'}] 1970 let list2 = [{'filename': 'fnameC', 'text': 'C'}, 1971 \ {'filename': 'fnameD', 'text': 'D'}, 1972 \ {'filename': 'fnameE', 'text': 'E'}] 1973 1974 " {action} is unspecified. Same as specifying ' '. 1975 new | only 1976 silent! Xnewer 99 1977 call g:Xsetlist(list1) 1978 call g:Xsetlist(list2) 1979 let li = g:Xgetlist() 1980 call assert_equal(3, len(li)) 1981 call assert_equal('C', li[0]['text']) 1982 call assert_equal('D', li[1]['text']) 1983 call assert_equal('E', li[2]['text']) 1984 silent! Xolder 1985 let li = g:Xgetlist() 1986 call assert_equal(2, len(li)) 1987 call assert_equal('A', li[0]['text']) 1988 call assert_equal('B', li[1]['text']) 1989 1990 " {action} is specified ' '. 1991 new | only 1992 silent! Xnewer 99 1993 call g:Xsetlist(list1) 1994 call g:Xsetlist(list2, ' ') 1995 let li = g:Xgetlist() 1996 call assert_equal(3, len(li)) 1997 call assert_equal('C', li[0]['text']) 1998 call assert_equal('D', li[1]['text']) 1999 call assert_equal('E', li[2]['text']) 2000 silent! Xolder 2001 let li = g:Xgetlist() 2002 call assert_equal(2, len(li)) 2003 call assert_equal('A', li[0]['text']) 2004 call assert_equal('B', li[1]['text']) 2005 2006 " {action} is specified 'a'. 2007 new | only 2008 silent! Xnewer 99 2009 call g:Xsetlist(list1) 2010 call g:Xsetlist(list2, 'a') 2011 let li = g:Xgetlist() 2012 call assert_equal(5, len(li)) 2013 call assert_equal('A', li[0]['text']) 2014 call assert_equal('B', li[1]['text']) 2015 call assert_equal('C', li[2]['text']) 2016 call assert_equal('D', li[3]['text']) 2017 call assert_equal('E', li[4]['text']) 2018 2019 " {action} is specified 'r'. 2020 new | only 2021 silent! Xnewer 99 2022 call g:Xsetlist(list1) 2023 call g:Xsetlist(list2, 'r') 2024 let li = g:Xgetlist() 2025 call assert_equal(3, len(li)) 2026 call assert_equal('C', li[0]['text']) 2027 call assert_equal('D', li[1]['text']) 2028 call assert_equal('E', li[2]['text']) 2029 2030 " Test for wrong value. 2031 new | only 2032 call assert_fails("call g:Xsetlist(0)", 'E714:') 2033 call assert_fails("call g:Xsetlist(list1, '')", 'E927:') 2034 call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:') 2035 call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:') 2036 call assert_fails("call g:Xsetlist(list1, 0)", 'E928:') 2037 endfunc 2038 2039 func Test_setqflist_invalid_nr() 2040 " The following command used to crash Vim 2041 eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST}) 2042 endfunc 2043 2044 func Test_setqflist_user_sets_buftype() 2045 call setqflist([{'text': 'foo'}, {'text': 'bar'}]) 2046 set buftype=quickfix 2047 call setqflist([], 'a') 2048 enew 2049 endfunc 2050 2051 func Test_quickfix_set_list_with_act() 2052 call XquickfixSetListWithAct('c') 2053 call XquickfixSetListWithAct('l') 2054 endfunc 2055 2056 func XLongLinesTests(cchar) 2057 let l = g:Xgetlist() 2058 2059 call assert_equal(4, len(l)) 2060 call assert_equal(1, l[0].lnum) 2061 call assert_equal(1, l[0].col) 2062 call assert_equal(1975, len(l[0].text)) 2063 call assert_equal(2, l[1].lnum) 2064 call assert_equal(1, l[1].col) 2065 call assert_equal(4070, len(l[1].text)) 2066 call assert_equal(3, l[2].lnum) 2067 call assert_equal(1, l[2].col) 2068 call assert_equal(4070, len(l[2].text)) 2069 call assert_equal(4, l[3].lnum) 2070 call assert_equal(1, l[3].col) 2071 call assert_equal(10, len(l[3].text)) 2072 2073 call g:Xsetlist([], 'r') 2074 endfunc 2075 2076 func s:long_lines_tests(cchar) 2077 call s:setup_commands(a:cchar) 2078 2079 let testfile = 'samples/quickfix.txt' 2080 2081 " file 2082 exe 'Xgetfile' testfile 2083 call XLongLinesTests(a:cchar) 2084 2085 " list 2086 Xexpr readfile(testfile) 2087 call XLongLinesTests(a:cchar) 2088 2089 " string 2090 Xexpr join(readfile(testfile), "\n") 2091 call XLongLinesTests(a:cchar) 2092 2093 " buffer 2094 exe 'edit' testfile 2095 exe 'Xbuffer' bufnr('%') 2096 call XLongLinesTests(a:cchar) 2097 endfunc 2098 2099 func Test_long_lines() 2100 call s:long_lines_tests('c') 2101 call s:long_lines_tests('l') 2102 endfunc 2103 2104 func Test_cgetfile_on_long_lines() 2105 " Problematic values if the line is longer than 4096 bytes. Then 1024 bytes 2106 " are read at a time. 2107 for len in [4078, 4079, 4080, 5102, 5103, 5104, 6126, 6127, 6128, 7150, 7151, 7152] 2108 let lines =<< trim END 2109 /tmp/file1:1:1:aaa 2110 /tmp/file2:1:1:%s 2111 /tmp/file3:1:1:bbb 2112 /tmp/file4:1:1:ccc 2113 END 2114 let lines[1] = substitute(lines[1], '%s', repeat('x', len), '') 2115 call writefile(lines, 'Xcqetfile.txt') 2116 cgetfile Xcqetfile.txt 2117 call assert_equal(4, getqflist(#{size: v:true}).size, 'with length ' .. len) 2118 endfor 2119 call delete('Xcqetfile.txt') 2120 endfunc 2121 2122 func s:create_test_file(filename) 2123 let l = [] 2124 for i in range(1, 20) 2125 call add(l, 'Line' . i) 2126 endfor 2127 call writefile(l, a:filename) 2128 endfunc 2129 2130 func Test_switchbuf() 2131 call s:create_test_file('Xqftestfile1') 2132 call s:create_test_file('Xqftestfile2') 2133 call s:create_test_file('Xqftestfile3') 2134 2135 new | only 2136 edit Xqftestfile1 2137 let file1_winid = win_getid() 2138 new Xqftestfile2 2139 let file2_winid = win_getid() 2140 let lines =<< trim END 2141 Xqftestfile1:5:Line5 2142 Xqftestfile1:6:Line6 2143 Xqftestfile2:10:Line10 2144 Xqftestfile2:11:Line11 2145 Xqftestfile3:15:Line15 2146 Xqftestfile3:16:Line16 2147 END 2148 cgetexpr lines 2149 2150 new 2151 let winid = win_getid() 2152 cfirst | cnext 2153 call assert_equal(winid, win_getid()) 2154 2cnext 2155 call assert_equal(winid, win_getid()) 2156 2cnext 2157 call assert_equal(winid, win_getid()) 2158 2159 " Test for 'switchbuf' set to search for files in windows in the current 2160 " tabpage and jump to an existing window (if present) 2161 set switchbuf=useopen 2162 enew 2163 cfirst | cnext 2164 call assert_equal(file1_winid, win_getid()) 2165 2cnext 2166 call assert_equal(file2_winid, win_getid()) 2167 2cnext 2168 call assert_equal(file2_winid, win_getid()) 2169 2170 " Test for 'switchbuf' set to search for files in tabpages and jump to an 2171 " existing tabpage (if present) 2172 enew | only 2173 set switchbuf=usetab 2174 tabedit Xqftestfile1 2175 tabedit Xqftestfile2 2176 tabedit Xqftestfile3 2177 tabfirst 2178 cfirst | cnext 2179 call assert_equal(2, tabpagenr()) 2180 2cnext 2181 call assert_equal(3, tabpagenr()) 2182 6cnext 2183 call assert_equal(4, tabpagenr()) 2184 2cpfile 2185 call assert_equal(2, tabpagenr()) 2186 2cnfile 2187 call assert_equal(4, tabpagenr()) 2188 tabfirst | tabonly | enew 2189 2190 " Test for 'switchbuf' set to open a new window for every file 2191 set switchbuf=split 2192 cfirst | cnext 2193 call assert_equal(1, winnr('$')) 2194 cnext | cnext 2195 call assert_equal(2, winnr('$')) 2196 cnext | cnext 2197 call assert_equal(3, winnr('$')) 2198 2199 " Test for 'switchbuf' set to open a new tabpage for every file 2200 set switchbuf=newtab 2201 enew | only 2202 cfirst | cnext 2203 call assert_equal(1, tabpagenr('$')) 2204 cnext | cnext 2205 call assert_equal(2, tabpagenr('$')) 2206 cnext | cnext 2207 call assert_equal(3, tabpagenr('$')) 2208 tabfirst | enew | tabonly | only 2209 2210 set switchbuf=uselast 2211 split 2212 let last_winid = win_getid() 2213 copen 2214 exe "normal 1G\<CR>" 2215 call assert_equal(last_winid, win_getid()) 2216 enew | only 2217 2218 " With an empty 'switchbuf', jumping to a quickfix entry should open the 2219 " file in an existing window (if present) 2220 set switchbuf= 2221 edit Xqftestfile1 2222 let file1_winid = win_getid() 2223 new Xqftestfile2 2224 let file2_winid = win_getid() 2225 copen 2226 exe "normal 1G\<CR>" 2227 call assert_equal(file1_winid, win_getid()) 2228 copen 2229 exe "normal 3G\<CR>" 2230 call assert_equal(file2_winid, win_getid()) 2231 copen | only 2232 exe "normal 5G\<CR>" 2233 call assert_equal(2, winnr('$')) 2234 call assert_equal(1, bufwinnr('Xqftestfile3')) 2235 2236 " If only quickfix window is open in the current tabpage, jumping to an 2237 " entry with 'switchbuf' set to 'usetab' should search in other tabpages. 2238 enew | only 2239 set switchbuf=usetab 2240 tabedit Xqftestfile1 2241 tabedit Xqftestfile2 2242 tabedit Xqftestfile3 2243 tabfirst 2244 copen | only 2245 clast 2246 call assert_equal(4, tabpagenr()) 2247 tabfirst | tabonly | enew | only 2248 2249 " Jumping to a file that is not present in any of the tabpages and the 2250 " current tabpage doesn't have any usable windows, should open it in a new 2251 " window in the current tabpage. 2252 copen | only 2253 cfirst 2254 call assert_equal(1, tabpagenr()) 2255 call assert_equal('Xqftestfile1', @%) 2256 2257 " If opening a file changes 'switchbuf', then the new value should be 2258 " retained. 2259 set modeline&vim 2260 call writefile(["vim: switchbuf=split"], 'Xqftestfile1') 2261 enew | only 2262 set switchbuf&vim 2263 cexpr "Xqftestfile1:1:10" 2264 call assert_equal('split', &switchbuf) 2265 call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1') 2266 enew | only 2267 set switchbuf=useopen 2268 cexpr "Xqftestfile1:1:10" 2269 call assert_equal('usetab', &switchbuf) 2270 call writefile(["vim: switchbuf&vim"], 'Xqftestfile1') 2271 enew | only 2272 set switchbuf=useopen 2273 cexpr "Xqftestfile1:1:10" 2274 call assert_equal('uselast', &switchbuf) 2275 2276 call delete('Xqftestfile1') 2277 call delete('Xqftestfile2') 2278 call delete('Xqftestfile3') 2279 set switchbuf&vim 2280 2281 enew | only 2282 endfunc 2283 2284 func Xadjust_qflnum(cchar) 2285 call s:setup_commands(a:cchar) 2286 2287 enew | only 2288 2289 let fname = 'Xqftestfile' . a:cchar 2290 call s:create_test_file(fname) 2291 exe 'edit ' . fname 2292 2293 Xgetexpr [fname . ':5:Line5', 2294 \ fname . ':10:Line10', 2295 \ fname . ':15:Line15', 2296 \ fname . ':20:Line20'] 2297 2298 6,14delete 2299 call append(6, ['Buffer', 'Window']) 2300 2301 let l = g:Xgetlist() 2302 call assert_equal(5, l[0].lnum) 2303 call assert_equal(6, l[2].lnum) 2304 call assert_equal(13, l[3].lnum) 2305 2306 " If a file doesn't have any quickfix entries, then deleting lines in the 2307 " file should not update the quickfix list 2308 call g:Xsetlist([], 'f') 2309 1,2delete 2310 call assert_equal([], g:Xgetlist()) 2311 2312 enew! 2313 call delete(fname) 2314 endfunc 2315 2316 func Test_adjust_lnum() 2317 call setloclist(0, []) 2318 call Xadjust_qflnum('c') 2319 call setqflist([]) 2320 call Xadjust_qflnum('l') 2321 endfunc 2322 2323 " Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands 2324 func s:test_xgrep(cchar) 2325 call s:setup_commands(a:cchar) 2326 2327 " The following lines are used for the grep test. Don't remove. 2328 " Grep_Test_Text: Match 1 2329 " Grep_Test_Text: Match 2 2330 " GrepAdd_Test_Text: Match 1 2331 " GrepAdd_Test_Text: Match 2 2332 enew! | only 2333 set makeef&vim 2334 silent Xgrep Grep_Test_Text: test_quickfix.vim 2335 call assert_true(len(g:Xgetlist()) == 5) 2336 Xopen 2337 call assert_true(w:quickfix_title =~ '^:grep') 2338 Xclose 2339 enew 2340 set makeef=Temp_File_## 2341 silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim 2342 call assert_true(len(g:Xgetlist()) == 9) 2343 2344 " Try with 'grepprg' set to 'internal' 2345 set grepprg=internal 2346 silent Xgrep Grep_Test_Text: test_quickfix.vim 2347 silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim 2348 call assert_true(len(g:Xgetlist()) == 9) 2349 set grepprg&vim 2350 2351 call writefile(['Vim'], 'XtestTempFile') 2352 set makeef=XtestTempFile 2353 silent Xgrep Grep_Test_Text: test_quickfix.vim 2354 call assert_equal(5, len(g:Xgetlist())) 2355 call assert_false(filereadable('XtestTempFile')) 2356 set makeef&vim 2357 endfunc 2358 2359 func Test_grep() 2360 " The grepprg may not be set on non-Unix systems 2361 CheckUnix 2362 2363 call s:test_xgrep('c') 2364 call s:test_xgrep('l') 2365 endfunc 2366 2367 func Test_local_grepformat() 2368 let save_grepformat = &grepformat 2369 set grepformat=%f:%l:%m 2370 " The following line are used for the local grep test. Don't remove. 2371 " UNIQUEPREFIX:2:3: Local grepformat test 2372 new 2373 setlocal grepformat=UNIQUEPREFIX:%c:%n:%m 2374 call assert_equal('UNIQUEPREFIX:%c:%n:%m', &l:grepformat) 2375 call assert_equal('%f:%l:%m', &g:grepformat) 2376 2377 set grepprg=internal 2378 silent grep "^[[:space:]]*\" UNIQUEPREFIX:" test_quickfix.vim 2379 call assert_equal(1, len(getqflist())) 2380 set grepprg&vim 2381 2382 bwipe! 2383 let &grepformat = save_grepformat 2384 endfunc 2385 2386 func Test_two_windows() 2387 " Use one 'errorformat' for two windows. Add an expression to each of them, 2388 " make sure they each keep their own state. 2389 set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' 2390 call mkdir('Xone/a', 'p') 2391 call mkdir('Xtwo/a', 'p') 2392 let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] 2393 call writefile(lines, 'Xone/a/one.txt') 2394 call writefile(lines, 'Xtwo/a/two.txt') 2395 2396 new one 2397 let one_id = win_getid() 2398 lexpr "" 2399 new two 2400 let two_id = win_getid() 2401 lexpr "" 2402 2403 laddexpr "Entering dir 'Xtwo/a'" 2404 call win_gotoid(one_id) 2405 laddexpr "Entering dir 'Xone/a'" 2406 call win_gotoid(two_id) 2407 laddexpr 'two.txt:5:two two two' 2408 call win_gotoid(one_id) 2409 laddexpr 'one.txt:3:one one one' 2410 2411 let loc_one = getloclist(one_id) 2412 call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) 2413 call assert_equal(3, loc_one[1].lnum) 2414 2415 let loc_two = getloclist(two_id) 2416 call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) 2417 call assert_equal(5, loc_two[1].lnum) 2418 2419 call win_gotoid(one_id) 2420 bwipe! 2421 call win_gotoid(two_id) 2422 bwipe! 2423 call delete('Xone', 'rf') 2424 call delete('Xtwo', 'rf') 2425 endfunc 2426 2427 func XbottomTests(cchar) 2428 call s:setup_commands(a:cchar) 2429 2430 " Calling lbottom without any errors should fail 2431 if a:cchar == 'l' 2432 call assert_fails('lbottom', 'E776:') 2433 endif 2434 2435 call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) 2436 Xopen 2437 let wid = win_getid() 2438 call assert_equal(1, line('.')) 2439 wincmd w 2440 call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a') 2441 Xbottom 2442 call win_gotoid(wid) 2443 call assert_equal(2, line('.')) 2444 Xclose 2445 endfunc 2446 2447 " Tests for the :cbottom and :lbottom commands 2448 func Test_cbottom() 2449 call XbottomTests('c') 2450 call XbottomTests('l') 2451 endfunc 2452 2453 func HistoryTest(cchar) 2454 call s:setup_commands(a:cchar) 2455 2456 " clear all lists after the first one, then replace the first one. 2457 call g:Xsetlist([]) 2458 call assert_fails('Xolder 99', 'E380:') 2459 let entry = {'filename': 'foo', 'lnum': 42} 2460 call g:Xsetlist([entry], 'r') 2461 call g:Xsetlist([entry, entry]) 2462 call g:Xsetlist([entry, entry, entry]) 2463 let res = split(execute(a:cchar . 'hist'), "\n") 2464 call assert_equal(3, len(res)) 2465 let common = 'errors :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()' 2466 call assert_equal(' error list 1 of 3; 1 ' . common, res[0]) 2467 call assert_equal(' error list 2 of 3; 2 ' . common, res[1]) 2468 call assert_equal('> error list 3 of 3; 3 ' . common, res[2]) 2469 2470 " Test for changing the quickfix lists 2471 call assert_equal(3, g:Xgetlist({'nr' : 0}).nr) 2472 exe '1' . a:cchar . 'hist' 2473 call assert_equal(1, g:Xgetlist({'nr' : 0}).nr) 2474 exe '3' . a:cchar . 'hist' 2475 call assert_equal(3, g:Xgetlist({'nr' : 0}).nr) 2476 call assert_fails('-2' . a:cchar . 'hist', 'E16:') 2477 call assert_fails('4' . a:cchar . 'hist', 'E16:') 2478 2479 call g:Xsetlist([], 'f') 2480 let l = split(execute(a:cchar . 'hist'), "\n") 2481 call assert_equal('No entries', l[0]) 2482 if a:cchar == 'c' 2483 call assert_fails('4chist', 'E16:') 2484 else 2485 call assert_fails('4lhist', 'E776:') 2486 endif 2487 2488 " An empty list should still show the stack history 2489 call g:Xsetlist([]) 2490 let res = split(execute(a:cchar . 'hist'), "\n") 2491 call assert_equal('> error list 1 of 1; 0 ' . common, res[0]) 2492 2493 call g:Xsetlist([], 'f') 2494 endfunc 2495 2496 func Test_history() 2497 call HistoryTest('c') 2498 call HistoryTest('l') 2499 endfunc 2500 2501 func Test_duplicate_buf() 2502 " make sure we can get the highest buffer number 2503 edit DoesNotExist 2504 edit DoesNotExist2 2505 let last_buffer = bufnr("$") 2506 2507 " make sure only one buffer is created 2508 call writefile(['this one', 'that one'], 'Xgrepthis') 2509 vimgrep one Xgrepthis 2510 vimgrep one Xgrepthis 2511 call assert_equal(last_buffer + 1, bufnr("$")) 2512 2513 call delete('Xgrepthis') 2514 endfunc 2515 2516 " Quickfix/Location list set/get properties tests 2517 func Xproperty_tests(cchar) 2518 call s:setup_commands(a:cchar) 2519 2520 " Error cases 2521 call assert_fails('call g:Xgetlist(99)', 'E715:') 2522 call assert_fails('call g:Xsetlist(99)', 'E714:') 2523 call assert_fails('call g:Xsetlist([], "a", [])', 'E715:') 2524 2525 " Set and get the title 2526 call g:Xsetlist([]) 2527 Xopen 2528 wincmd p 2529 call g:Xsetlist([{'filename':'foo', 'lnum':27}]) 2530 let s = g:Xsetlist([], 'a', {'title' : 'Sample'}) 2531 call assert_equal(0, s) 2532 let d = g:Xgetlist({"title":1}) 2533 call assert_equal('Sample', d.title) 2534 " Try setting title to a non-string value 2535 call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']})) 2536 call assert_equal('Sample', g:Xgetlist({"title":1}).title) 2537 2538 Xopen 2539 call assert_equal('Sample', w:quickfix_title) 2540 Xclose 2541 2542 " Tests for action argument 2543 silent! Xolder 999 2544 let qfnr = g:Xgetlist({'all':1}).nr 2545 call g:Xsetlist([], 'r', {'title' : 'N1'}) 2546 call assert_equal('N1', g:Xgetlist({'all':1}).title) 2547 call g:Xsetlist([], ' ', {'title' : 'N2'}) 2548 call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr) 2549 2550 let res = g:Xgetlist({'nr': 0}) 2551 call assert_equal(qfnr + 1, res.nr) 2552 call assert_equal(['nr'], keys(res)) 2553 2554 call g:Xsetlist([], ' ', {'title' : 'N3'}) 2555 call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) 2556 2557 " Changing the title of an earlier quickfix list 2558 call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2}) 2559 call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title) 2560 2561 " Changing the title of an invalid quickfix list 2562 call assert_equal(-1, g:Xsetlist([], ' ', 2563 \ {'title' : 'SomeTitle', 'nr' : 99})) 2564 call assert_equal(-1, g:Xsetlist([], ' ', 2565 \ {'title' : 'SomeTitle', 'nr' : 'abc'})) 2566 2567 if a:cchar == 'c' 2568 copen 2569 call assert_equal({'winid':win_getid()}, getqflist({'winid':1})) 2570 cclose 2571 endif 2572 2573 " Invalid arguments 2574 call assert_fails('call g:Xgetlist([])', 'E715') 2575 call assert_fails('call g:Xsetlist([], "a", [])', 'E715') 2576 let s = g:Xsetlist([], 'a', {'abc':1}) 2577 call assert_equal(-1, s) 2578 2579 call assert_equal({}, g:Xgetlist({'abc':1})) 2580 call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title) 2581 call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title) 2582 2583 if a:cchar == 'l' 2584 call assert_equal({}, getloclist(99, {'title': 1})) 2585 endif 2586 2587 " Context related tests 2588 let s = g:Xsetlist([], 'a', {'context':[1,2,3]}) 2589 call assert_equal(0, s) 2590 call test_garbagecollect_now() 2591 let d = g:Xgetlist({'context':1}) 2592 call assert_equal([1,2,3], d.context) 2593 call g:Xsetlist([], 'a', {'context':{'color':'green'}}) 2594 let d = g:Xgetlist({'context':1}) 2595 call assert_equal({'color':'green'}, d.context) 2596 call g:Xsetlist([], 'a', {'context':"Context info"}) 2597 let d = g:Xgetlist({'context':1}) 2598 call assert_equal("Context info", d.context) 2599 call g:Xsetlist([], 'a', {'context':246}) 2600 let d = g:Xgetlist({'context':1}) 2601 call assert_equal(246, d.context) 2602 " set other Vim data types as context 2603 call g:Xsetlist([], 'a', {'context' : v:_null_blob}) 2604 if has('channel') 2605 call g:Xsetlist([], 'a', {'context' : test_null_channel()}) 2606 endif 2607 if has('job') 2608 call g:Xsetlist([], 'a', {'context' : test_null_job()}) 2609 endif 2610 " Nvim doesn't have null functions 2611 " call g:Xsetlist([], 'a', {'context' : test_null_function()}) 2612 " Nvim doesn't have null partials 2613 " call g:Xsetlist([], 'a', {'context' : test_null_partial()}) 2614 call g:Xsetlist([], 'a', {'context' : ''}) 2615 call test_garbagecollect_now() 2616 if a:cchar == 'l' 2617 " Test for copying context across two different location lists 2618 new | only 2619 let w1_id = win_getid() 2620 let l = [1] 2621 call setloclist(0, [], 'a', {'context':l}) 2622 new 2623 let w2_id = win_getid() 2624 call add(l, 2) 2625 call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context) 2626 call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) 2627 unlet! l 2628 call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) 2629 only 2630 call setloclist(0, [], 'f') 2631 call assert_equal('', getloclist(0, {'context':1}).context) 2632 endif 2633 2634 " Test for changing the context of previous quickfix lists 2635 call g:Xsetlist([], 'f') 2636 Xexpr "One" 2637 Xexpr "Two" 2638 Xexpr "Three" 2639 call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1}) 2640 call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2}) 2641 " Also, check for setting the context using quickfix list number zero. 2642 call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0}) 2643 call test_garbagecollect_now() 2644 let l = g:Xgetlist({'nr' : 1, 'context' : 1}) 2645 call assert_equal([1], l.context) 2646 let l = g:Xgetlist({'nr' : 2, 'context' : 1}) 2647 call assert_equal([2], l.context) 2648 let l = g:Xgetlist({'nr' : 3, 'context' : 1}) 2649 call assert_equal([3], l.context) 2650 2651 " Test for changing the context through reference and for garbage 2652 " collection of quickfix context 2653 let l = ["red"] 2654 call g:Xsetlist([], ' ', {'context' : l}) 2655 call add(l, "blue") 2656 let x = g:Xgetlist({'context' : 1}) 2657 call add(x.context, "green") 2658 call assert_equal(["red", "blue", "green"], l) 2659 call assert_equal(["red", "blue", "green"], x.context) 2660 unlet l 2661 call test_garbagecollect_now() 2662 let m = g:Xgetlist({'context' : 1}) 2663 call assert_equal(["red", "blue", "green"], m.context) 2664 2665 " Test for setting/getting items 2666 Xexpr "" 2667 let qfprev = g:Xgetlist({'nr':0}) 2668 let s = g:Xsetlist([], ' ', {'title':'Green', 2669 \ 'items' : [{'filename':'F1', 'lnum':10}]}) 2670 call assert_equal(0, s) 2671 let qfcur = g:Xgetlist({'nr':0}) 2672 call assert_true(qfcur.nr == qfprev.nr + 1) 2673 let l = g:Xgetlist({'items':1}) 2674 call assert_equal('F1', bufname(l.items[0].bufnr)) 2675 call assert_equal(10, l.items[0].lnum) 2676 call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20}, 2677 \ {'filename':'F2', 'lnum':30}]}) 2678 let l = g:Xgetlist({'items':1}) 2679 call assert_equal('F2', bufname(l.items[2].bufnr)) 2680 call assert_equal(30, l.items[2].lnum) 2681 call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]}) 2682 let l = g:Xgetlist({'items':1}) 2683 call assert_equal('F3', bufname(l.items[0].bufnr)) 2684 call assert_equal(40, l.items[0].lnum) 2685 call g:Xsetlist([], 'r', {'items' : []}) 2686 let l = g:Xgetlist({'items':1}) 2687 call assert_equal(0, len(l.items)) 2688 2689 call g:Xsetlist([], 'r', {'title' : 'TestTitle'}) 2690 call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]}) 2691 call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]}) 2692 call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title) 2693 2694 " Test for getting id of window associated with a location list window 2695 if a:cchar == 'l' 2696 only 2697 call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid) 2698 let wid = win_getid() 2699 Xopen 2700 call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid) 2701 wincmd w 2702 call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid) 2703 only 2704 endif 2705 2706 " The following used to crash Vim with address sanitizer 2707 call g:Xsetlist([], 'f') 2708 call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]}) 2709 call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum) 2710 2711 " Try setting the items using a string 2712 call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'})) 2713 2714 " Save and restore the quickfix stack 2715 call g:Xsetlist([], 'f') 2716 call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) 2717 Xexpr "File1:10:Line1" 2718 Xexpr "File2:20:Line2" 2719 Xexpr "File3:30:Line3" 2720 let last_qf = g:Xgetlist({'nr':'$'}).nr 2721 call assert_equal(3, last_qf) 2722 let qstack = [] 2723 for i in range(1, last_qf) 2724 let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1})) 2725 endfor 2726 call g:Xsetlist([], 'f') 2727 for i in range(len(qstack)) 2728 call g:Xsetlist([], ' ', qstack[i]) 2729 endfor 2730 call assert_equal(3, g:Xgetlist({'nr':'$'}).nr) 2731 call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum) 2732 call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum) 2733 call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum) 2734 call g:Xsetlist([], 'f') 2735 2736 " Swap two quickfix lists 2737 Xexpr "File1:10:Line10" 2738 Xexpr "File2:20:Line20" 2739 Xexpr "File3:30:Line30" 2740 call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']}) 2741 call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']}) 2742 let l1=g:Xgetlist({'nr':1,'all':1}) 2743 let l2=g:Xgetlist({'nr':2,'all':1}) 2744 let save_id = l1.id 2745 let l1.id=l2.id 2746 let l2.id=save_id 2747 call g:Xsetlist([], 'r', l1) 2748 call g:Xsetlist([], 'r', l2) 2749 let newl1=g:Xgetlist({'nr':1,'all':1}) 2750 let newl2=g:Xgetlist({'nr':2,'all':1}) 2751 call assert_equal('Fruits', newl1.title) 2752 call assert_equal(['Fruits'], newl1.context) 2753 call assert_equal('Line20', newl1.items[0].text) 2754 call assert_equal('Colors', newl2.title) 2755 call assert_equal(['Colors'], newl2.context) 2756 call assert_equal('Line10', newl2.items[0].text) 2757 call g:Xsetlist([], 'f') 2758 2759 " Cannot specify both a non-empty list argument and a dict argument 2760 call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:') 2761 endfunc 2762 2763 func Test_qf_property() 2764 call Xproperty_tests('c') 2765 call Xproperty_tests('l') 2766 endfunc 2767 2768 " Test for setting the current index in the location/quickfix list 2769 func Xtest_setqfidx(cchar) 2770 call s:setup_commands(a:cchar) 2771 2772 Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3" 2773 Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3" 2774 Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3" 2775 2776 call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2}) 2777 call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2}) 2778 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3}) 2779 Xolder 2 2780 Xopen 2781 call assert_equal(3, line('.')) 2782 Xnewer 2783 call assert_equal(2, line('.')) 2784 Xnewer 2785 call assert_equal(2, line('.')) 2786 " Update the current index with the quickfix window open 2787 wincmd w 2788 call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3}) 2789 Xopen 2790 call assert_equal(3, line('.')) 2791 Xclose 2792 2793 " Set the current index to the last entry 2794 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'}) 2795 call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) 2796 " A large value should set the index to the last index 2797 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1}) 2798 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999}) 2799 call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) 2800 " Invalid index values 2801 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1}) 2802 call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) 2803 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0}) 2804 call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) 2805 call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'}) 2806 call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) 2807 call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:') 2808 2809 call g:Xsetlist([], 'f') 2810 new | only 2811 endfunc 2812 2813 func Test_setqfidx() 2814 call Xtest_setqfidx('c') 2815 call Xtest_setqfidx('l') 2816 endfunc 2817 2818 " Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands 2819 func QfAutoCmdHandler(loc, cmd) 2820 call add(g:acmds, a:loc . a:cmd) 2821 endfunc 2822 2823 func Test_Autocmd() 2824 autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>')) 2825 autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>')) 2826 2827 let g:acmds = [] 2828 cexpr "F1:10:Line 10" 2829 caddexpr "F1:20:Line 20" 2830 cgetexpr "F1:30:Line 30" 2831 cexpr "" 2832 caddexpr "" 2833 cgetexpr "" 2834 silent! cexpr non_existing_func() 2835 silent! caddexpr non_existing_func() 2836 silent! cgetexpr non_existing_func() 2837 let l =<< trim END 2838 precexpr 2839 postcexpr 2840 precaddexpr 2841 postcaddexpr 2842 precgetexpr 2843 postcgetexpr 2844 precexpr 2845 postcexpr 2846 precaddexpr 2847 postcaddexpr 2848 precgetexpr 2849 postcgetexpr 2850 precexpr 2851 precaddexpr 2852 precgetexpr 2853 END 2854 call assert_equal(l, g:acmds) 2855 2856 let g:acmds = [] 2857 enew! | call append(0, "F2:10:Line 10") 2858 cbuffer! 2859 enew! | call append(0, "F2:20:Line 20") 2860 cgetbuffer 2861 enew! | call append(0, "F2:30:Line 30") 2862 caddbuffer 2863 new 2864 let bnum = bufnr('%') 2865 bunload 2866 exe 'silent! cbuffer! ' . bnum 2867 exe 'silent! cgetbuffer ' . bnum 2868 exe 'silent! caddbuffer ' . bnum 2869 enew! 2870 let l =<< trim END 2871 precbuffer 2872 postcbuffer 2873 precgetbuffer 2874 postcgetbuffer 2875 precaddbuffer 2876 postcaddbuffer 2877 precbuffer 2878 precgetbuffer 2879 precaddbuffer 2880 END 2881 call assert_equal(l, g:acmds) 2882 2883 call writefile(['Xtest:1:Line1'], 'Xtest') 2884 call writefile([], 'Xempty') 2885 let g:acmds = [] 2886 cfile Xtest 2887 caddfile Xtest 2888 cgetfile Xtest 2889 cfile Xempty 2890 caddfile Xempty 2891 cgetfile Xempty 2892 silent! cfile do_not_exist 2893 silent! caddfile do_not_exist 2894 silent! cgetfile do_not_exist 2895 let l =<< trim END 2896 precfile 2897 postcfile 2898 precaddfile 2899 postcaddfile 2900 precgetfile 2901 postcgetfile 2902 precfile 2903 postcfile 2904 precaddfile 2905 postcaddfile 2906 precgetfile 2907 postcgetfile 2908 precfile 2909 postcfile 2910 precaddfile 2911 postcaddfile 2912 precgetfile 2913 postcgetfile 2914 END 2915 call assert_equal(l, g:acmds) 2916 2917 let g:acmds = [] 2918 helpgrep quickfix 2919 silent! helpgrep non_existing_help_topic 2920 vimgrep test Xtest 2921 vimgrepadd test Xtest 2922 silent! vimgrep non_existing_test Xtest 2923 silent! vimgrepadd non_existing_test Xtest 2924 set makeprg= 2925 silent! make 2926 set makeprg& 2927 let l =<< trim END 2928 prehelpgrep 2929 posthelpgrep 2930 prehelpgrep 2931 posthelpgrep 2932 previmgrep 2933 postvimgrep 2934 previmgrepadd 2935 postvimgrepadd 2936 previmgrep 2937 postvimgrep 2938 previmgrepadd 2939 postvimgrepadd 2940 premake 2941 postmake 2942 END 2943 call assert_equal(l, g:acmds) 2944 2945 if has('unix') 2946 " Run this test only on Unix-like systems. The grepprg may not be set on 2947 " non-Unix systems. 2948 " The following lines are used for the grep test. Don't remove. 2949 " Grep_Autocmd_Text: Match 1 2950 " GrepAdd_Autocmd_Text: Match 2 2951 let g:acmds = [] 2952 silent grep Grep_Autocmd_Text test_quickfix.vim 2953 silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim 2954 silent grep abc123def Xtest 2955 silent grepadd abc123def Xtest 2956 set grepprg=internal 2957 silent grep Grep_Autocmd_Text test_quickfix.vim 2958 silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim 2959 silent lgrep Grep_Autocmd_Text test_quickfix.vim 2960 silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim 2961 set grepprg&vim 2962 let l =<< trim END 2963 pregrep 2964 postgrep 2965 pregrepadd 2966 postgrepadd 2967 pregrep 2968 postgrep 2969 pregrepadd 2970 postgrepadd 2971 pregrep 2972 postgrep 2973 pregrepadd 2974 postgrepadd 2975 prelgrep 2976 postlgrep 2977 prelgrepadd 2978 postlgrepadd 2979 END 2980 call assert_equal(l, g:acmds) 2981 endif 2982 2983 call delete('Xtest') 2984 call delete('Xempty') 2985 au! QuickFixCmdPre 2986 au! QuickFixCmdPost 2987 endfunc 2988 2989 func Test_Autocmd_Exception() 2990 set efm=%m 2991 lgetexpr '?' 2992 2993 try 2994 call DoesNotExit() 2995 catch 2996 lgetexpr '1' 2997 finally 2998 lgetexpr '1' 2999 endtry 3000 3001 call assert_equal('1', getloclist(0)[0].text) 3002 3003 set efm&vim 3004 endfunc 3005 3006 func Test_caddbuffer_wrong() 3007 " This used to cause a memory access in freed memory. 3008 let save_efm = &efm 3009 set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.# 3010 cgetexpr ['WWWW', 'EEEE', 'CCCC'] 3011 let &efm = save_efm 3012 caddbuffer 3013 bwipe! 3014 endfunc 3015 3016 func Test_caddexpr_wrong() 3017 " This used to cause a memory access in freed memory. 3018 cbuffer 3019 cbuffer 3020 copen 3021 let save_efm = &efm 3022 set efm=% 3023 call assert_fails('caddexpr ""', 'E376:') 3024 let &efm = save_efm 3025 endfunc 3026 3027 func Test_dirstack_cleanup() 3028 " This used to cause a memory access in freed memory. 3029 let save_efm = &efm 3030 lexpr '0' 3031 lopen 3032 fun X(c) 3033 let save_efm=&efm 3034 set efm=%D%f 3035 if a:c == 'c' 3036 caddexpr '::' 3037 else 3038 laddexpr ':0:0' 3039 endif 3040 let &efm=save_efm 3041 endfun 3042 call X('c') 3043 call X('l') 3044 call setqflist([], 'r') 3045 caddbuffer 3046 let &efm = save_efm 3047 endfunc 3048 3049 " Tests for jumping to entries from the location list window and quickfix 3050 " window 3051 func Test_cwindow_jump() 3052 set efm=%f%%%l%%%m 3053 lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] 3054 lopen | only 3055 lfirst 3056 call assert_true(winnr('$') == 2) 3057 call assert_true(winnr() == 1) 3058 " Location list for the new window should be set 3059 call assert_true(getloclist(0)[2].text == 'Line 30') 3060 3061 " Open a scratch buffer 3062 " Open a new window and create a location list 3063 " Open the location list window and close the other window 3064 " Jump to an entry. 3065 " Should create a new window and jump to the entry. The scratch buffer 3066 " should not be used. 3067 enew | only 3068 set buftype=nofile 3069 below new 3070 lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] 3071 lopen 3072 2wincmd c 3073 lnext 3074 call assert_true(winnr('$') == 3) 3075 call assert_true(winnr() == 2) 3076 3077 " Open two windows with two different location lists 3078 " Open the location list window and close the previous window 3079 " Jump to an entry in the location list window 3080 " Should open the file in the first window and not set the location list. 3081 enew | only 3082 lgetexpr ["F1%5%Line 5"] 3083 below new 3084 lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] 3085 lopen 3086 2wincmd c 3087 lnext 3088 call assert_true(winnr() == 1) 3089 call assert_true(getloclist(0)[0].text == 'Line 5') 3090 3091 enew | only 3092 cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] 3093 copen 3094 cnext 3095 call assert_true(winnr('$') == 2) 3096 call assert_true(winnr() == 1) 3097 3098 " open the quickfix buffer in two windows and jump to an entry. Should open 3099 " the file in the first quickfix window. 3100 enew | only 3101 copen 3102 let bnum = bufnr('') 3103 exe 'sbuffer ' . bnum 3104 wincmd b 3105 cfirst 3106 call assert_equal(2, winnr()) 3107 call assert_equal('F1', @%) 3108 enew | only 3109 exe 'sb' bnum 3110 exe 'botright sb' bnum 3111 wincmd t 3112 clast 3113 call assert_equal(2, winnr()) 3114 call assert_equal('quickfix', getwinvar(1, '&buftype')) 3115 call assert_equal('quickfix', getwinvar(3, '&buftype')) 3116 3117 " Jumping to a file from the location list window should find a usable 3118 " window by wrapping around the window list. 3119 enew | only 3120 call setloclist(0, [], 'f') 3121 new | new 3122 lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] 3123 lopen 3124 1close 3125 call assert_equal(0, getloclist(3, {'id' : 0}).id) 3126 lnext 3127 call assert_equal(3, winnr()) 3128 call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id) 3129 3130 enew | only 3131 set efm&vim 3132 endfunc 3133 3134 func Test_cwindow_highlight() 3135 CheckScreendump 3136 3137 let lines =<< trim END 3138 call setline(1, ['some', 'text', 'with', 'matches']) 3139 write XCwindow 3140 vimgrep e XCwindow 3141 redraw 3142 cwindow 4 3143 END 3144 call writefile(lines, 'XtestCwindow') 3145 let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12}) 3146 call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {}) 3147 3148 call term_sendkeys(buf, ":cnext\<CR>") 3149 call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {}) 3150 3151 " clean up 3152 call StopVimInTerminal(buf) 3153 call delete('XtestCwindow') 3154 call delete('XCwindow') 3155 endfunc 3156 3157 func XvimgrepTests(cchar) 3158 call s:setup_commands(a:cchar) 3159 3160 let lines =<< trim END 3161 Editor:VIM vim 3162 Editor:Emacs EmAcS 3163 Editor:Notepad NOTEPAD 3164 END 3165 call writefile(lines, 'Xtestfile1') 3166 call writefile(['Linux', 'macOS', 'MS-Windows'], 'Xtestfile2') 3167 3168 " Error cases 3169 call assert_fails('Xvimgrep /abc *', 'E682:') 3170 3171 let @/='' 3172 call assert_fails('Xvimgrep // *', 'E35:') 3173 3174 call assert_fails('Xvimgrep abc', 'E683:') 3175 call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:') 3176 call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:') 3177 3178 Xexpr "" 3179 Xvimgrepadd Notepad Xtestfile1 3180 Xvimgrepadd macOS Xtestfile2 3181 let l = g:Xgetlist() 3182 call assert_equal(2, len(l)) 3183 call assert_equal('Editor:Notepad NOTEPAD', l[0].text) 3184 3185 10Xvimgrep #\cvim#g Xtestfile? 3186 let l = g:Xgetlist() 3187 call assert_equal(2, len(l)) 3188 call assert_equal(8, l[0].col) 3189 call assert_equal(11, l[0].end_col) 3190 call assert_equal(12, l[1].col) 3191 call assert_equal(15, l[1].end_col) 3192 3193 1Xvimgrep ?Editor? Xtestfile* 3194 let l = g:Xgetlist() 3195 call assert_equal(1, len(l)) 3196 call assert_equal('Editor:VIM vim', l[0].text) 3197 3198 edit +3 Xtestfile2 3199 Xvimgrep +\cemacs+j Xtestfile1 3200 let l = g:Xgetlist() 3201 call assert_equal('Xtestfile2', @%) 3202 call assert_equal('Editor:Emacs EmAcS', l[0].text) 3203 3204 " Test for unloading a buffer after vimgrep searched the buffer 3205 %bwipe 3206 Xvimgrep /Editor/j Xtestfile* 3207 call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded) 3208 call assert_equal([], getbufinfo('Xtestfile2')) 3209 3210 " Test for opening the dummy buffer used by vimgrep in a window. The new 3211 " window should be closed 3212 %bw! 3213 augroup QF_Test 3214 au! 3215 autocmd BufReadPre * exe "sb " .. expand("<abuf>") 3216 augroup END 3217 call assert_fails("Xvimgrep /sublime/ Xtestfile1", 'E480:') 3218 call assert_equal(1, winnr('$')) 3219 augroup QF_Test 3220 au! 3221 augroup END 3222 3223 call delete('Xtestfile1') 3224 call delete('Xtestfile2') 3225 endfunc 3226 3227 " Tests for the :vimgrep command 3228 func Test_vimgrep() 3229 call XvimgrepTests('c') 3230 call XvimgrepTests('l') 3231 endfunc 3232 3233 func Test_vimgrep_wildcards_expanded_once() 3234 new X[id-01] file.txt 3235 call setline(1, 'some text to search for') 3236 vimgrep text % 3237 bwipe! 3238 endfunc 3239 3240 " Test for incsearch highlighting of the :vimgrep pattern 3241 " This test used to cause "E315: ml_get: invalid lnum" errors. 3242 func Test_vimgrep_incsearch() 3243 enew 3244 set incsearch 3245 call Ntest_override("char_avail", 1) 3246 3247 call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx") 3248 let l = getqflist() 3249 call assert_equal(2, len(l)) 3250 3251 call Ntest_override("ALL", 0) 3252 set noincsearch 3253 endfunc 3254 3255 " Test vimgrep with the last search pattern not set 3256 func Test_vimgrep_with_no_last_search_pat() 3257 let lines =<< trim [SCRIPT] 3258 call assert_fails('vimgrep // *', 'E35:') 3259 call writefile(v:errors, 'Xresult') 3260 qall! 3261 [SCRIPT] 3262 call writefile(lines, 'Xscript') 3263 if RunVim([], [], '--clean -S Xscript') 3264 call assert_equal([], readfile('Xresult')) 3265 endif 3266 call delete('Xscript') 3267 call delete('Xresult') 3268 endfunc 3269 3270 " Test vimgrep without swap file 3271 func Test_vimgrep_without_swap_file() 3272 let lines =<< trim [SCRIPT] 3273 vimgrep grep test_c* 3274 call writefile(['done'], 'Xresult') 3275 qall! 3276 [SCRIPT] 3277 call writefile(lines, 'Xscript') 3278 if RunVim([], [], '--clean -n -S Xscript Xscript') 3279 call assert_equal(['done'], readfile('Xresult')) 3280 endif 3281 call delete('Xscript') 3282 call delete('Xresult') 3283 endfunc 3284 3285 func Test_vimgrep_existing_swapfile() 3286 call writefile(['match apple with apple'], 'Xapple') 3287 call writefile(['swapfile'], '.Xapple.swp') 3288 let g:foundSwap = 0 3289 let g:ignoreSwapExists = 1 3290 augroup grep 3291 au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e' 3292 augroup END 3293 vimgrep apple Xapple 3294 call assert_equal(1, g:foundSwap) 3295 call assert_match('.Xapple.swo', swapname('')) 3296 3297 call delete('Xapple') 3298 call delete('.Xapple.swp') 3299 augroup grep 3300 au! SwapExists 3301 augroup END 3302 unlet g:ignoreSwapExists 3303 endfunc 3304 3305 func XfreeTests(cchar) 3306 call s:setup_commands(a:cchar) 3307 3308 enew | only 3309 3310 " Deleting the quickfix stack should work even When the current list is 3311 " somewhere in the middle of the stack 3312 Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] 3313 Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] 3314 Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] 3315 Xolder 3316 call g:Xsetlist([], 'f') 3317 call assert_equal(0, len(g:Xgetlist())) 3318 3319 " After deleting the stack, adding a new list should create a stack with a 3320 " single list. 3321 Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] 3322 call assert_equal(1, g:Xgetlist({'all':1}).nr) 3323 3324 " Deleting the stack from a quickfix window should update/clear the 3325 " quickfix/location list window. 3326 Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] 3327 Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] 3328 Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] 3329 Xolder 3330 Xwindow 3331 call g:Xsetlist([], 'f') 3332 call assert_equal(2, winnr('$')) 3333 call assert_equal(1, line('$')) 3334 Xclose 3335 3336 " Deleting the stack from a non-quickfix window should update/clear the 3337 " quickfix/location list window. 3338 Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] 3339 Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] 3340 Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] 3341 Xolder 3342 Xwindow 3343 wincmd p 3344 call g:Xsetlist([], 'f') 3345 call assert_equal(0, len(g:Xgetlist())) 3346 wincmd p 3347 call assert_equal(2, winnr('$')) 3348 call assert_equal(1, line('$')) 3349 3350 " After deleting the location list stack, if the location list window is 3351 " opened, then a new location list should be created. So opening the 3352 " location list window again should not create a new window. 3353 if a:cchar == 'l' 3354 lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] 3355 wincmd p 3356 lopen 3357 call assert_equal(2, winnr('$')) 3358 endif 3359 Xclose 3360 endfunc 3361 3362 " Tests for the quickfix free functionality 3363 func Test_qf_free() 3364 call XfreeTests('c') 3365 call XfreeTests('l') 3366 endfunc 3367 3368 " Test for buffer overflow when parsing lines and adding new entries to 3369 " the quickfix list. 3370 func Test_bufoverflow() 3371 set efm=%f:%l:%m 3372 cgetexpr ['File1:100:' . repeat('x', 1025)] 3373 3374 set efm=%+GCompiler:\ %.%#,%f:%l:%m 3375 cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World'] 3376 3377 set efm=%DEntering\ directory\ %f,%f:%l:%m 3378 let lines =<< trim eval END 3379 Entering directory $"{repeat('a', 1006)}" 3380 File1:10:Hello World 3381 END 3382 cgetexpr lines 3383 set efm&vim 3384 endfunc 3385 3386 " Tests for getting the quickfix stack size 3387 func XsizeTests(cchar) 3388 call s:setup_commands(a:cchar) 3389 3390 call g:Xsetlist([], 'f') 3391 call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) 3392 call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title) 3393 call assert_equal(0, g:Xgetlist({'nr':0}).nr) 3394 3395 Xexpr "File1:10:Line1" 3396 Xexpr "File2:20:Line2" 3397 Xexpr "File3:30:Line3" 3398 Xolder | Xolder 3399 call assert_equal(3, g:Xgetlist({'nr':'$'}).nr) 3400 call g:Xsetlist([], 'f') 3401 3402 Xexpr "File1:10:Line1" 3403 Xexpr "File2:20:Line2" 3404 Xexpr "File3:30:Line3" 3405 Xolder | Xolder 3406 call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'}) 3407 call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title) 3408 endfunc 3409 3410 func Test_Qf_Size() 3411 call XsizeTests('c') 3412 call XsizeTests('l') 3413 endfunc 3414 3415 func Test_cclose_from_copen() 3416 augroup QF_Test 3417 au! 3418 au FileType qf :call assert_fails(':cclose', 'E788') 3419 augroup END 3420 copen 3421 augroup QF_Test 3422 au! 3423 augroup END 3424 augroup! QF_Test 3425 endfunc 3426 3427 func Test_cclose_in_autocmd() 3428 " Problem is only triggered if "starting" is zero, so that the OptionSet 3429 " event will be triggered. 3430 call Ntest_override('starting', 1) 3431 augroup QF_Test 3432 au! 3433 au FileType qf :call assert_fails(':cclose', 'E788') 3434 augroup END 3435 copen 3436 augroup QF_Test 3437 au! 3438 augroup END 3439 augroup! QF_Test 3440 call Ntest_override('starting', 0) 3441 endfunc 3442 3443 " Check that ":file" without an argument is possible even when "curbuf->b_ro_locked" 3444 " is set. 3445 func Test_file_from_copen() 3446 " Works without argument. 3447 augroup QF_Test 3448 au! 3449 au FileType qf file 3450 augroup END 3451 copen 3452 3453 augroup QF_Test 3454 au! 3455 augroup END 3456 cclose 3457 3458 " Fails with argument. 3459 augroup QF_Test 3460 au! 3461 au FileType qf call assert_fails(':file foo', 'E788') 3462 augroup END 3463 copen 3464 augroup QF_Test 3465 au! 3466 augroup END 3467 cclose 3468 3469 augroup! QF_Test 3470 endfunc 3471 3472 func Test_resize_from_copen() 3473 augroup QF_Test 3474 au! 3475 au FileType qf resize 5 3476 augroup END 3477 try 3478 " This should succeed without any exception. No other buffers are 3479 " involved in the autocmd. 3480 copen 3481 finally 3482 augroup QF_Test 3483 au! 3484 augroup END 3485 augroup! QF_Test 3486 endtry 3487 endfunc 3488 3489 func Test_filetype_autocmd() 3490 " this changes the location list while it is in use to fill a buffer 3491 lexpr '' 3492 lopen 3493 augroup FT_loclist 3494 au FileType * call setloclist(0, [], 'f') 3495 augroup END 3496 silent! lolder 3497 lexpr '' 3498 3499 augroup FT_loclist 3500 au! FileType 3501 augroup END 3502 endfunc 3503 3504 func Test_vimgrep_with_textlock() 3505 new 3506 3507 " Simple way to execute something with "textlock" set. 3508 " Check that vimgrep without jumping can be executed. 3509 au InsertCharPre * vimgrep /RunTheTest/j runtest.vim 3510 normal ax 3511 let qflist = getqflist() 3512 call assert_true(len(qflist) > 0) 3513 call assert_match('RunTheTest', qflist[0].text) 3514 call setqflist([], 'r') 3515 au! InsertCharPre 3516 3517 " Check that vimgrepadd without jumping can be executed. 3518 au InsertCharPre * vimgrepadd /RunTheTest/j runtest.vim 3519 normal ax 3520 let qflist = getqflist() 3521 call assert_true(len(qflist) > 0) 3522 call assert_match('RunTheTest', qflist[0].text) 3523 call setqflist([], 'r') 3524 au! InsertCharPre 3525 3526 " Check that lvimgrep without jumping can be executed. 3527 au InsertCharPre * lvimgrep /RunTheTest/j runtest.vim 3528 normal ax 3529 let qflist = getloclist(0) 3530 call assert_true(len(qflist) > 0) 3531 call assert_match('RunTheTest', qflist[0].text) 3532 call setloclist(0, [], 'r') 3533 au! InsertCharPre 3534 3535 " Check that lvimgrepadd without jumping can be executed. 3536 au InsertCharPre * lvimgrepadd /RunTheTest/j runtest.vim 3537 normal ax 3538 let qflist = getloclist(0) 3539 call assert_true(len(qflist) > 0) 3540 call assert_match('RunTheTest', qflist[0].text) 3541 call setloclist(0, [], 'r') 3542 au! InsertCharPre 3543 3544 " trying to jump will give an error 3545 au InsertCharPre * vimgrep /RunTheTest/ runtest.vim 3546 call assert_fails('normal ax', 'E565:') 3547 au! InsertCharPre 3548 3549 au InsertCharPre * vimgrepadd /RunTheTest/ runtest.vim 3550 call assert_fails('normal ax', 'E565:') 3551 au! InsertCharPre 3552 3553 au InsertCharPre * lvimgrep /RunTheTest/ runtest.vim 3554 call assert_fails('normal ax', 'E565:') 3555 au! InsertCharPre 3556 3557 au InsertCharPre * lvimgrepadd /RunTheTest/ runtest.vim 3558 call assert_fails('normal ax', 'E565:') 3559 au! InsertCharPre 3560 3561 bwipe! 3562 endfunc 3563 3564 " Tests for the quickfix buffer b:changedtick variable 3565 func Xchangedtick_tests(cchar) 3566 call s:setup_commands(a:cchar) 3567 3568 new | only 3569 3570 Xexpr "" | Xexpr "" | Xexpr "" 3571 3572 Xopen 3573 Xolder 3574 Xolder 3575 Xaddexpr "F1:10:Line10" 3576 Xaddexpr "F2:20:Line20" 3577 call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a') 3578 call g:Xsetlist([], 'f') 3579 call assert_equal(8, getbufvar('%', 'changedtick')) 3580 Xclose 3581 endfunc 3582 3583 func Test_changedtick() 3584 call Xchangedtick_tests('c') 3585 call Xchangedtick_tests('l') 3586 endfunc 3587 3588 " Tests for parsing an expression using setqflist() 3589 func Xsetexpr_tests(cchar) 3590 call s:setup_commands(a:cchar) 3591 3592 let t = ["File1:10:Line10", "File1:20:Line20"] 3593 call g:Xsetlist([], ' ', {'lines' : t}) 3594 call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]}) 3595 3596 let l = g:Xgetlist() 3597 call assert_equal(3, len(l)) 3598 call assert_equal(20, l[1].lnum) 3599 call assert_equal('Line30', l[2].text) 3600 call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]}) 3601 let l = g:Xgetlist() 3602 call assert_equal(1, len(l)) 3603 call assert_equal('Line5', l[0].text) 3604 call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10})) 3605 call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"})) 3606 3607 call g:Xsetlist([], 'f') 3608 " Add entries to multiple lists 3609 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]}) 3610 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]}) 3611 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]}) 3612 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]}) 3613 call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text) 3614 call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text) 3615 3616 " Adding entries using a custom efm 3617 set efm& 3618 call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m', 3619 \ 'lines' : ["F1#10#L10", "F2#20#L20"]}) 3620 call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum) 3621 call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]}) 3622 call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text) 3623 call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum) 3624 call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [], 3625 \ 'lines' : ['F1:10:L10']})) 3626 endfunc 3627 3628 func Test_setexpr() 3629 call Xsetexpr_tests('c') 3630 call Xsetexpr_tests('l') 3631 endfunc 3632 3633 " Tests for per quickfix/location list directory stack 3634 func Xmultidirstack_tests(cchar) 3635 call s:setup_commands(a:cchar) 3636 3637 call g:Xsetlist([], 'f') 3638 Xexpr "" | Xexpr "" 3639 3640 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]}) 3641 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]}) 3642 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]}) 3643 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]}) 3644 3645 let l1 = g:Xgetlist({'nr':1, 'items':1}) 3646 let l2 = g:Xgetlist({'nr':2, 'items':1}) 3647 call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr)) 3648 call assert_equal(3, l1.items[1].lnum) 3649 call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr)) 3650 call assert_equal(5, l2.items[1].lnum) 3651 endfunc 3652 3653 func Test_multidirstack() 3654 call mkdir('Xone/a', 'p') 3655 call mkdir('Xtwo/a', 'p') 3656 let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] 3657 call writefile(lines, 'Xone/a/one.txt') 3658 call writefile(lines, 'Xtwo/a/two.txt') 3659 let save_efm = &efm 3660 set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' 3661 3662 call Xmultidirstack_tests('c') 3663 call Xmultidirstack_tests('l') 3664 3665 let &efm = save_efm 3666 call delete('Xone', 'rf') 3667 call delete('Xtwo', 'rf') 3668 endfunc 3669 3670 " Tests for per quickfix/location list file stack 3671 func Xmultifilestack_tests(cchar) 3672 call s:setup_commands(a:cchar) 3673 3674 call g:Xsetlist([], 'f') 3675 Xexpr "" | Xexpr "" 3676 3677 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]}) 3678 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]}) 3679 call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]}) 3680 call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]}) 3681 3682 let l1 = g:Xgetlist({'nr':1, 'items':1}) 3683 let l2 = g:Xgetlist({'nr':2, 'items':1}) 3684 call assert_equal('one.txt', bufname(l1.items[1].bufnr)) 3685 call assert_equal(3, l1.items[1].lnum) 3686 call assert_equal('two.txt', bufname(l2.items[1].bufnr)) 3687 call assert_equal(5, l2.items[1].lnum) 3688 3689 " Test for start of a new error line in the same line where a previous 3690 " error line ends with a file stack. 3691 let efm_val = 'Error\ l%l\ in\ %f,' 3692 let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r' 3693 let lines =<< trim END 3694 (one.txt 3695 Error l4 in one.txt 3696 ) (two.txt 3697 Error l6 in two.txt 3698 ) 3699 Error l8 in one.txt 3700 END 3701 let l = g:Xgetlist({'lines': lines, 'efm' : efm_val}) 3702 call assert_equal(3, len(l.items)) 3703 call assert_equal('one.txt', bufname(l.items[0].bufnr)) 3704 call assert_equal(4, l.items[0].lnum) 3705 call assert_equal('one.txt', l.items[0].text) 3706 call assert_equal('two.txt', bufname(l.items[1].bufnr)) 3707 call assert_equal(6, l.items[1].lnum) 3708 call assert_equal('two.txt', l.items[1].text) 3709 call assert_equal('one.txt', bufname(l.items[2].bufnr)) 3710 call assert_equal(8, l.items[2].lnum) 3711 call assert_equal('', l.items[2].text) 3712 endfunc 3713 3714 func Test_multifilestack() 3715 let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] 3716 call writefile(lines, 'one.txt') 3717 call writefile(lines, 'two.txt') 3718 let save_efm = &efm 3719 set efm=%+P[%f],(%l\\,%c)\ %m,%-Q 3720 3721 call Xmultifilestack_tests('c') 3722 call Xmultifilestack_tests('l') 3723 3724 let &efm = save_efm 3725 call delete('one.txt') 3726 call delete('two.txt') 3727 endfunc 3728 3729 " Tests for per buffer 'efm' setting 3730 func Test_perbuf_efm() 3731 call writefile(["File1-10-Line10"], 'one.txt') 3732 call writefile(["File2#20#Line20"], 'two.txt') 3733 set efm=%f#%l#%m 3734 new | only 3735 new 3736 setlocal efm=%f-%l-%m 3737 cfile one.txt 3738 wincmd w 3739 caddfile two.txt 3740 3741 let l = getqflist() 3742 call assert_equal(10, l[0].lnum) 3743 call assert_equal('Line20', l[1].text) 3744 3745 set efm& 3746 new | only 3747 call delete('one.txt') 3748 call delete('two.txt') 3749 endfunc 3750 3751 " Open multiple help windows using ":lhelpgrep 3752 " This test used to crash Vim 3753 func Test_Multi_LL_Help() 3754 new | only 3755 lhelpgrep window 3756 lopen 3757 e# 3758 lhelpgrep buffer 3759 call assert_equal(3, winnr('$')) 3760 call assert_true(len(getloclist(1)) != 0) 3761 call assert_true(len(getloclist(2)) != 0) 3762 new | only 3763 endfunc 3764 3765 " Tests for adding new quickfix lists using setqflist() 3766 func XaddQf_tests(cchar) 3767 call s:setup_commands(a:cchar) 3768 3769 " Create a new list using ' ' for action 3770 call g:Xsetlist([], 'f') 3771 call g:Xsetlist([], ' ', {'title' : 'Test1'}) 3772 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3773 call assert_equal(1, l.nr) 3774 call assert_equal('Test1', l.title) 3775 3776 " Create a new list using ' ' for action and '$' for 'nr' 3777 call g:Xsetlist([], 'f') 3778 call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'}) 3779 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3780 call assert_equal(1, l.nr) 3781 call assert_equal('Test2', l.title) 3782 3783 " Create a new list using 'a' for action 3784 call g:Xsetlist([], 'f') 3785 call g:Xsetlist([], 'a', {'title' : 'Test3'}) 3786 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3787 call assert_equal(1, l.nr) 3788 call assert_equal('Test3', l.title) 3789 3790 " Create a new list using 'a' for action and '$' for 'nr' 3791 call g:Xsetlist([], 'f') 3792 call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'}) 3793 call g:Xsetlist([], 'a', {'title' : 'Test4'}) 3794 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3795 call assert_equal(1, l.nr) 3796 call assert_equal('Test4', l.title) 3797 3798 " Adding a quickfix list should remove all the lists following the current 3799 " list. 3800 Xexpr "" | Xexpr "" | Xexpr "" 3801 silent! 10Xolder 3802 call g:Xsetlist([], ' ', {'title' : 'Test5'}) 3803 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3804 call assert_equal(2, l.nr) 3805 call assert_equal('Test5', l.title) 3806 3807 " Add a quickfix list using '$' as the list number. 3808 let lastqf = g:Xgetlist({'nr':'$'}).nr 3809 silent! 99Xolder 3810 call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'}) 3811 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3812 call assert_equal(lastqf + 1, l.nr) 3813 call assert_equal('Test6', l.title) 3814 3815 " Add a quickfix list using 'nr' set to one more than the quickfix 3816 " list size. 3817 let lastqf = g:Xgetlist({'nr':'$'}).nr 3818 silent! 99Xolder 3819 call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'}) 3820 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3821 call assert_equal(lastqf + 1, l.nr) 3822 call assert_equal('Test7', l.title) 3823 3824 " Add a quickfix list to a stack with 10 lists using 'nr' set to '$' 3825 exe repeat('Xexpr "" |', 9) . 'Xexpr ""' 3826 silent! 99Xolder 3827 call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'}) 3828 let l = g:Xgetlist({'nr' : '$', 'all' : 1}) 3829 call assert_equal(10, l.nr) 3830 call assert_equal('Test8', l.title) 3831 3832 " Add a quickfix list using 'nr' set to a value greater than 10 3833 call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'})) 3834 3835 " Try adding a quickfix list with 'nr' set to a value greater than the 3836 " quickfix list size but less than 10. 3837 call g:Xsetlist([], 'f') 3838 Xexpr "" | Xexpr "" | Xexpr "" 3839 silent! 99Xolder 3840 call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'})) 3841 3842 " Add a quickfix list using 'nr' set to a some string or list 3843 call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'})) 3844 endfunc 3845 3846 func Test_add_qf() 3847 call XaddQf_tests('c') 3848 call XaddQf_tests('l') 3849 endfunc 3850 3851 " Test for getting the quickfix list items from some text without modifying 3852 " the quickfix stack 3853 func XgetListFromLines(cchar) 3854 call s:setup_commands(a:cchar) 3855 call g:Xsetlist([], 'f') 3856 3857 let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items 3858 call assert_equal(2, len(l)) 3859 call assert_equal(30, l[1].lnum) 3860 3861 call assert_equal({}, g:Xgetlist({'lines' : 10})) 3862 call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'})) 3863 call assert_equal([], g:Xgetlist({'lines' : []}).items) 3864 call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items) 3865 3866 " Parse text using a custom efm 3867 set efm& 3868 let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items 3869 call assert_equal('Line30', l[0].text) 3870 let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items 3871 call assert_equal('File3:30:Line30', l[0].text) 3872 let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]}) 3873 call assert_equal({}, l) 3874 call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:') 3875 call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:') 3876 3877 " Make sure that the quickfix stack is not modified 3878 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 3879 endfunc 3880 3881 func Test_get_list_from_lines() 3882 call XgetListFromLines('c') 3883 call XgetListFromLines('l') 3884 endfunc 3885 3886 " Tests for the quickfix list id 3887 func Xqfid_tests(cchar) 3888 call s:setup_commands(a:cchar) 3889 3890 call g:Xsetlist([], 'f') 3891 call assert_equal(0, g:Xgetlist({'id':0}).id) 3892 Xexpr '' 3893 let start_id = g:Xgetlist({'id' : 0}).id 3894 Xexpr '' | Xexpr '' 3895 Xolder 3896 call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id) 3897 call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id) 3898 call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id) 3899 call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id) 3900 call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr) 3901 call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id) 3902 call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id) 3903 3904 call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) 3905 call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) 3906 call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']}) 3907 call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text) 3908 call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'})) 3909 call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'})) 3910 3911 let qfid = g:Xgetlist({'id':0, 'nr':0}) 3912 call g:Xsetlist([], 'f') 3913 call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id) 3914 endfunc 3915 3916 func Test_qf_id() 3917 call Xqfid_tests('c') 3918 call Xqfid_tests('l') 3919 endfunc 3920 3921 func Xqfjump_tests(cchar) 3922 call s:setup_commands(a:cchar) 3923 3924 call writefile(["Line1\tFoo", "Line2"], 'F1') 3925 call writefile(["Line1\tBar", "Line2"], 'F2') 3926 call writefile(["Line1\tBaz", "Line2"], 'F3') 3927 3928 call g:Xsetlist([], 'f') 3929 3930 " Tests for 3931 " Jumping to a line using a pattern 3932 " Jumping to a column greater than the last column in a line 3933 " Jumping to a line greater than the last line in the file 3934 let l = [] 3935 for i in range(1, 7) 3936 call add(l, {}) 3937 endfor 3938 let l[0].filename='F1' 3939 let l[0].pattern='Line1' 3940 let l[1].filename='F2' 3941 let l[1].pattern='Line1' 3942 let l[2].filename='F3' 3943 let l[2].pattern='Line1' 3944 let l[3].filename='F3' 3945 let l[3].lnum=1 3946 let l[3].col=9 3947 let l[3].vcol=1 3948 let l[4].filename='F3' 3949 let l[4].lnum=99 3950 let l[5].filename='F3' 3951 let l[5].lnum=1 3952 let l[5].col=99 3953 let l[5].vcol=1 3954 let l[6].filename='F3' 3955 let l[6].pattern='abcxyz' 3956 3957 call g:Xsetlist([], ' ', {'items' : l}) 3958 Xopen | only 3959 2Xnext 3960 call assert_equal(3, g:Xgetlist({'idx' : 0}).idx) 3961 call assert_equal('F3', @%) 3962 Xnext 3963 call assert_equal(7, col('.')) 3964 Xnext 3965 call assert_equal(2, line('.')) 3966 Xnext 3967 call assert_equal(9, col('.')) 3968 2 3969 Xnext 3970 call assert_equal(2, line('.')) 3971 3972 if a:cchar == 'l' 3973 " When jumping to a location list entry in the location list window and 3974 " no usable windows are available, then a new window should be opened. 3975 enew! | new | only 3976 call g:Xsetlist([], 'f') 3977 setlocal buftype=nofile 3978 new 3979 let lines =<< trim END 3980 F1:1:1:Line1 3981 F1:2:2:Line2 3982 F2:1:1:Line1 3983 F2:2:2:Line2 3984 F3:1:1:Line1 3985 F3:2:2:Line2 3986 END 3987 call g:Xsetlist([], ' ', {'lines': lines}) 3988 Xopen 3989 let winid = win_getid() 3990 wincmd p 3991 close 3992 call win_gotoid(winid) 3993 Xnext 3994 call assert_equal(3, winnr('$')) 3995 call assert_equal(1, winnr()) 3996 call assert_equal(2, line('.')) 3997 3998 " When jumping to an entry in the location list window and the window 3999 " associated with the location list is not present and a window containing 4000 " the file is already present, then that window should be used. 4001 close 4002 belowright new 4003 call g:Xsetlist([], 'f') 4004 edit F3 4005 call win_gotoid(winid) 4006 Xlast 4007 call assert_equal(3, winnr()) 4008 call assert_equal(6, g:Xgetlist({'size' : 1}).size) 4009 call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid) 4010 endif 4011 4012 " Cleanup 4013 enew! 4014 new | only 4015 4016 call delete('F1') 4017 call delete('F2') 4018 call delete('F3') 4019 endfunc 4020 4021 func Test_qfjump() 4022 call Xqfjump_tests('c') 4023 call Xqfjump_tests('l') 4024 endfunc 4025 4026 " Tests for the getqflist() and getloclist() functions when the list is not 4027 " present or is empty 4028 func Xgetlist_empty_tests(cchar) 4029 call s:setup_commands(a:cchar) 4030 4031 " Empty quickfix stack 4032 call g:Xsetlist([], 'f') 4033 call assert_equal('', g:Xgetlist({'context' : 0}).context) 4034 call assert_equal(0, g:Xgetlist({'id' : 0}).id) 4035 call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) 4036 call assert_equal([], g:Xgetlist({'items' : 0}).items) 4037 call assert_equal(0, g:Xgetlist({'nr' : 0}).nr) 4038 call assert_equal(0, g:Xgetlist({'size' : 0}).size) 4039 call assert_equal('', g:Xgetlist({'title' : 0}).title) 4040 call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) 4041 call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick) 4042 if a:cchar == 'c' 4043 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 4044 \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0, 4045 \ 'title' : '', 'winid' : 0, 'changedtick': 0, 4046 \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0})) 4047 else 4048 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 4049 \ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 4050 \ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0, 4051 \ 'qfbufnr' : 0, 'quickfixtextfunc' : ''}, 4052 \ g:Xgetlist({'all' : 0})) 4053 endif 4054 4055 " Quickfix window with empty stack 4056 silent! Xopen 4057 let qfwinid = (a:cchar == 'c') ? win_getid() : 0 4058 let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0 4059 call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid) 4060 Xclose 4061 4062 " Empty quickfix list 4063 Xexpr "" 4064 call assert_equal('', g:Xgetlist({'context' : 0}).context) 4065 call assert_notequal(0, g:Xgetlist({'id' : 0}).id) 4066 call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) 4067 call assert_equal([], g:Xgetlist({'items' : 0}).items) 4068 call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr) 4069 call assert_equal(0, g:Xgetlist({'size' : 0}).size) 4070 call assert_notequal('', g:Xgetlist({'title' : 0}).title) 4071 call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) 4072 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 4073 4074 let qfid = g:Xgetlist({'id' : 0}).id 4075 call g:Xsetlist([], 'f') 4076 4077 " Non-existing quickfix identifier 4078 call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context) 4079 call assert_equal(0, g:Xgetlist({'id' : qfid}).id) 4080 call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx) 4081 call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items) 4082 call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr) 4083 call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size) 4084 call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title) 4085 call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid) 4086 call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick) 4087 if a:cchar == 'c' 4088 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 4089 \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 4090 \ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '', 4091 \ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0})) 4092 else 4093 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 4094 \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 4095 \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0, 4096 \ 'quickfixtextfunc' : ''}, 4097 \ g:Xgetlist({'id' : qfid, 'all' : 0})) 4098 endif 4099 4100 " Non-existing quickfix list number 4101 call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context) 4102 call assert_equal(0, g:Xgetlist({'nr' : 5}).nr) 4103 call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx) 4104 call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items) 4105 call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id) 4106 call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size) 4107 call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title) 4108 call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid) 4109 call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick) 4110 if a:cchar == 'c' 4111 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 4112 \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 4113 \ 'changedtick' : 0, 'qfbufnr' : qfbufnr, 4114 \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0})) 4115 else 4116 call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 4117 \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 4118 \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0, 4119 \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0})) 4120 endif 4121 endfunc 4122 4123 func Test_empty_list_quickfixtextfunc() 4124 " This was crashing. Can only reproduce by running it in a separate Vim 4125 " instance. 4126 let lines =<< trim END 4127 func s:Func(o) 4128 cgetexpr '0' 4129 endfunc 4130 cope 4131 let &quickfixtextfunc = 's:Func' 4132 cgetfile [ex 4133 END 4134 call writefile(lines, 'Xquickfixtextfunc') 4135 call RunVim([], [], '-e -s -S Xquickfixtextfunc -c qa') 4136 call delete('Xquickfixtextfunc') 4137 endfunc 4138 4139 func Test_getqflist() 4140 call Xgetlist_empty_tests('c') 4141 call Xgetlist_empty_tests('l') 4142 endfunc 4143 4144 func Test_getqflist_invalid_nr() 4145 " The following commands used to crash Vim 4146 cexpr "" 4147 call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX}) 4148 4149 " Cleanup 4150 call setqflist([], 'r') 4151 endfunc 4152 4153 " Tests for the quickfix/location list changedtick 4154 func Xqftick_tests(cchar) 4155 call s:setup_commands(a:cchar) 4156 4157 call g:Xsetlist([], 'f') 4158 4159 Xexpr "F1:10:Line10" 4160 let qfid = g:Xgetlist({'id' : 0}).id 4161 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 4162 Xaddexpr "F2:20:Line20\nF2:21:Line21" 4163 call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) 4164 call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]}) 4165 call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick) 4166 call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]}) 4167 call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick) 4168 call g:Xsetlist([], 'a', {'title' : 'New Title'}) 4169 call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick) 4170 4171 enew! 4172 call append(0, ["F5:50:L50", "F6:60:L60"]) 4173 Xaddbuffer 4174 call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick) 4175 enew! 4176 4177 call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}}) 4178 call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick) 4179 call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'}, 4180 \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a') 4181 call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick) 4182 call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'}, 4183 \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ') 4184 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 4185 call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'}, 4186 \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r') 4187 call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) 4188 4189 if isdirectory("Xone") 4190 call delete("Xone", 'rf') 4191 endif 4192 call writefile(["F8:80:L80", "F8:81:L81"], "Xone") 4193 Xfile Xone 4194 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 4195 Xaddfile Xone 4196 call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) 4197 4198 " Test case for updating a non-current quickfix list 4199 call g:Xsetlist([], 'f') 4200 Xexpr "F1:1:L1" 4201 Xexpr "F2:2:L2" 4202 call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]}) 4203 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 4204 call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick) 4205 4206 call delete("Xone") 4207 endfunc 4208 4209 func Test_qf_tick() 4210 call Xqftick_tests('c') 4211 call Xqftick_tests('l') 4212 endfunc 4213 4214 " Test helpgrep with lang specifier 4215 func Xtest_helpgrep_with_lang_specifier(cchar) 4216 call s:setup_commands(a:cchar) 4217 Xhelpgrep Vim@en 4218 call assert_equal('help', &filetype) 4219 call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr) 4220 new | only 4221 endfunc 4222 4223 func Test_helpgrep_with_lang_specifier() 4224 call Xtest_helpgrep_with_lang_specifier('c') 4225 call Xtest_helpgrep_with_lang_specifier('l') 4226 endfunc 4227 4228 " The following test used to crash Vim. 4229 " Open the location list window and close the regular window associated with 4230 " the location list. When the garbage collection runs now, it incorrectly 4231 " marks the location list context as not in use and frees the context. 4232 func Test_ll_window_ctx() 4233 call setloclist(0, [], 'f') 4234 call setloclist(0, [], 'a', {'context' : []}) 4235 lopen | only 4236 call test_garbagecollect_now() 4237 echo getloclist(0, {'context' : 1}).context 4238 enew | only 4239 endfunc 4240 4241 " Similar to the problem above, but for user data. 4242 func Test_ll_window_user_data() 4243 call setloclist(0, [#{bufnr: bufnr(), user_data: {}}]) 4244 lopen 4245 wincmd t 4246 close 4247 call test_garbagecollect_now() 4248 call feedkeys("\<CR>", 'tx') 4249 call test_garbagecollect_now() 4250 %bwipe! 4251 endfunc 4252 4253 " The following test used to crash vim 4254 func Test_lfile_crash() 4255 sp Xtest 4256 au QuickFixCmdPre * bw 4257 call assert_fails('lfile', 'E40:') 4258 au! QuickFixCmdPre 4259 endfunc 4260 4261 " The following test used to crash vim 4262 func Test_lbuffer_crash() 4263 sv Xtest 4264 augroup QF_Test 4265 au! 4266 au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bw 4267 augroup END 4268 lbuffer 4269 augroup QF_Test 4270 au! 4271 augroup END 4272 endfunc 4273 4274 " The following test used to crash vim 4275 func Test_lexpr_crash() 4276 augroup QF_Test 4277 au! 4278 au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f') 4279 augroup END 4280 lexpr "" 4281 augroup QF_Test 4282 au! 4283 augroup END 4284 4285 enew | only 4286 augroup QF_Test 4287 au! 4288 au BufNew * call setloclist(0, [], 'f') 4289 augroup END 4290 lexpr 'x:1:x' 4291 augroup QF_Test 4292 au! 4293 augroup END 4294 4295 enew | only 4296 lexpr '' 4297 lopen 4298 augroup QF_Test 4299 au! 4300 au FileType * call setloclist(0, [], 'f') 4301 augroup END 4302 lexpr '' 4303 augroup QF_Test 4304 au! 4305 augroup END 4306 endfunc 4307 4308 " The following test used to crash Vim 4309 func Test_lvimgrep_crash() 4310 " this leaves a swapfile .test_quickfix.vim.swp around, why? 4311 sv Xtest 4312 augroup QF_Test 4313 au! 4314 au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f') 4315 augroup END 4316 lvimgrep quickfix test_quickfix.vim 4317 augroup QF_Test 4318 au! 4319 augroup END 4320 4321 new | only 4322 augroup QF_Test 4323 au! 4324 au BufEnter * call setloclist(0, [], 'r') 4325 augroup END 4326 call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:') 4327 augroup QF_Test 4328 au! 4329 augroup END 4330 4331 enew | only 4332 endfunc 4333 4334 func Test_lvimgrep_crash2() 4335 au BufNewFile x sfind 4336 call assert_fails('lvimgrep x x', 'E471:') 4337 call assert_fails('lvimgrep x x x', 'E471:') 4338 4339 au! BufNewFile 4340 endfunc 4341 4342 " Test for the position of the quickfix and location list window 4343 func Test_qfwin_pos() 4344 " Open two windows 4345 new | only 4346 new 4347 cexpr ['F1:10:L10'] 4348 copen 4349 " Quickfix window should be the bottom most window 4350 call assert_equal(3, winnr()) 4351 close 4352 " Open at the very top 4353 wincmd t 4354 topleft copen 4355 call assert_equal(1, winnr()) 4356 close 4357 " open left of the current window 4358 wincmd t 4359 below new 4360 leftabove copen 4361 call assert_equal(2, winnr()) 4362 close 4363 " open right of the current window 4364 rightbelow copen 4365 call assert_equal(3, winnr()) 4366 close 4367 endfunc 4368 4369 " Tests for quickfix/location lists changed by autocommands when 4370 " :vimgrep/:lvimgrep commands are running. 4371 func Test_vimgrep_autocmd() 4372 call setqflist([], 'f') 4373 call writefile(['stars'], 'Xtest1.txt', 'D') 4374 call writefile(['stars'], 'Xtest2.txt', 'D') 4375 4376 " Test 1: 4377 " When searching for a pattern using :vimgrep, if the quickfix list is 4378 " changed by an autocmd, the results should be added to the correct quickfix 4379 " list. 4380 autocmd BufRead Xtest2.txt cexpr '' | cexpr '' 4381 silent vimgrep stars Xtest*.txt 4382 call assert_equal(1, getqflist({'nr' : 0}).nr) 4383 call assert_equal(3, getqflist({'nr' : '$'}).nr) 4384 call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr)) 4385 au! BufRead Xtest2.txt 4386 4387 " Test 2: 4388 " When searching for a pattern using :vimgrep, if the quickfix list is 4389 " freed, then a error should be given. 4390 silent! %bwipe! 4391 call setqflist([], 'f') 4392 autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor 4393 call assert_fails('vimgrep stars Xtest*.txt', 'E925:') 4394 au! BufRead Xtest2.txt 4395 4396 " Test 3: 4397 " When searching for a pattern using :lvimgrep, if the location list is 4398 " freed, then the command should error out. 4399 silent! %bwipe! 4400 let g:save_winid = win_getid() 4401 autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f') 4402 call assert_fails('lvimgrep stars Xtest*.txt', 'E926:') 4403 au! BufRead Xtest2.txt 4404 " cleanup the swap files 4405 bw! Xtest2.txt Xtest1.txt 4406 4407 call setqflist([], 'f') 4408 endfunc 4409 4410 " Test for an autocmd changing the current directory when running vimgrep 4411 func Xvimgrep_autocmd_cd(cchar) 4412 call s:setup_commands(a:cchar) 4413 4414 %bwipe 4415 let save_cwd = getcwd() 4416 4417 augroup QF_Test 4418 au! 4419 autocmd BufRead * silent cd %:p:h 4420 augroup END 4421 4422 10Xvimgrep /vim/ Xdir/** 4423 let l = g:Xgetlist() 4424 call assert_equal('f1.txt', bufname(l[0].bufnr)) 4425 call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t')) 4426 4427 augroup QF_Test 4428 au! 4429 augroup END 4430 4431 exe 'cd ' . save_cwd 4432 endfunc 4433 4434 func Test_vimgrep_autocmd_cd() 4435 call mkdir('Xdir/a', 'p') 4436 call mkdir('Xdir/b', 'p') 4437 call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt') 4438 call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt') 4439 call Xvimgrep_autocmd_cd('c') 4440 call Xvimgrep_autocmd_cd('l') 4441 %bwipe 4442 call delete('Xdir', 'rf') 4443 endfunc 4444 4445 " The following test used to crash Vim 4446 func Test_lhelpgrep_autocmd() 4447 lhelpgrep quickfix 4448 augroup QF_Test 4449 au! 4450 autocmd QuickFixCmdPost * call setloclist(0, [], 'f') 4451 augroup END 4452 lhelpgrep buffer 4453 call assert_equal('help', &filetype) 4454 call assert_equal(0, getloclist(0, {'nr' : '$'}).nr) 4455 lhelpgrep tabpage 4456 call assert_equal('help', &filetype) 4457 call assert_equal(1, getloclist(0, {'nr' : '$'}).nr) 4458 augroup QF_Test 4459 au! 4460 augroup END 4461 4462 new | only 4463 augroup QF_Test 4464 au! 4465 au BufEnter * call setqflist([], 'f') 4466 augroup END 4467 call assert_fails('helpgrep quickfix', 'E925:') 4468 " run the test with a help window already open 4469 help 4470 wincmd w 4471 call assert_fails('helpgrep quickfix', 'E925:') 4472 augroup QF_Test 4473 au! 4474 augroup END 4475 4476 new | only 4477 augroup QF_Test 4478 au! 4479 au BufEnter * call setqflist([], 'r') 4480 augroup END 4481 call assert_fails('helpgrep quickfix', 'E925:') 4482 augroup QF_Test 4483 au! 4484 augroup END 4485 4486 new | only 4487 augroup QF_Test 4488 au! 4489 au BufEnter * call setloclist(0, [], 'r') 4490 augroup END 4491 call assert_fails('lhelpgrep quickfix', 'E926:') 4492 augroup QF_Test 4493 au! 4494 augroup END 4495 4496 " Replace the contents of a help window location list when it is still in 4497 " use. 4498 new | only 4499 lhelpgrep quickfix 4500 wincmd w 4501 augroup QF_Test 4502 au! 4503 autocmd WinEnter * call setloclist(0, [], 'r') 4504 augroup END 4505 call assert_fails('lhelpgrep win_getid', 'E926:') 4506 augroup QF_Test 4507 au! 4508 augroup END 4509 4510 %bw! 4511 endfunc 4512 4513 " The following test used to crash Vim 4514 func Test_lhelpgrep_autocmd_free_loclist() 4515 %bw! 4516 lhelpgrep quickfix 4517 wincmd w 4518 augroup QF_Test 4519 au! 4520 autocmd WinEnter * call setloclist(0, [], 'f') 4521 augroup END 4522 lhelpgrep win_getid 4523 wincmd w 4524 wincmd w 4525 wincmd w 4526 augroup QF_Test 4527 au! 4528 augroup END 4529 %bw! 4530 endfunc 4531 4532 " Test for shortening/simplifying the file name when opening the 4533 " quickfix window or when displaying the quickfix list 4534 func Test_shorten_fname() 4535 CheckUnix 4536 %bwipe 4537 " Create a quickfix list with an absolute path filename 4538 let fname = getcwd() . '/test_quickfix.vim' 4539 call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'}) 4540 call assert_equal(fname, bufname('test_quickfix.vim')) 4541 " Opening the quickfix window should simplify the file path 4542 cwindow 4543 call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim')) 4544 cclose 4545 %bwipe 4546 " Create a quickfix list with an absolute path filename 4547 call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'}) 4548 call assert_equal(fname, bufname('test_quickfix.vim')) 4549 " Displaying the quickfix list should simplify the file path 4550 silent! clist 4551 call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim')) 4552 " Add a few entries for the same file with different paths and check whether 4553 " the buffer name is shortened 4554 %bwipe 4555 call setqflist([], 'f') 4556 call setqflist([{'filename' : 'test_quickfix.vim', 'lnum' : 10}, 4557 \ {'filename' : '../testdir/test_quickfix.vim', 'lnum' : 20}, 4558 \ {'filename' : fname, 'lnum' : 30}], ' ') 4559 copen 4560 call assert_equal(['test_quickfix.vim|10| ', 4561 \ 'test_quickfix.vim|20| ', 4562 \ 'test_quickfix.vim|30| '], getline(1, '$')) 4563 cclose 4564 endfunc 4565 4566 " Quickfix title tests 4567 " In the below tests, 'exe "cmd"' is used to invoke the quickfix commands. 4568 " Otherwise due to indentation, the title is set with spaces at the beginning 4569 " of the command. 4570 func Test_qftitle() 4571 call writefile(["F1:1:Line1"], 'Xerr') 4572 4573 " :cexpr 4574 exe "cexpr readfile('Xerr')" 4575 call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title) 4576 4577 " :cgetexpr 4578 exe "cgetexpr readfile('Xerr')" 4579 call assert_equal(":cgetexpr readfile('Xerr')", 4580 \ getqflist({'title' : 1}).title) 4581 4582 " :caddexpr 4583 call setqflist([], 'f') 4584 exe "caddexpr readfile('Xerr')" 4585 call assert_equal(":caddexpr readfile('Xerr')", 4586 \ getqflist({'title' : 1}).title) 4587 4588 " :cbuffer 4589 new Xerr 4590 exe "cbuffer" 4591 call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title) 4592 4593 " :cgetbuffer 4594 edit Xerr 4595 exe "cgetbuffer" 4596 call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title) 4597 4598 " :caddbuffer 4599 call setqflist([], 'f') 4600 edit Xerr 4601 exe "caddbuffer" 4602 call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title) 4603 4604 " :cfile 4605 exe "cfile Xerr" 4606 call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title) 4607 4608 " :cgetfile 4609 exe "cgetfile Xerr" 4610 call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title) 4611 4612 " :caddfile 4613 call setqflist([], 'f') 4614 exe "caddfile Xerr" 4615 call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title) 4616 4617 " :grep 4618 set grepprg=internal 4619 exe "grep F1 Xerr" 4620 call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title) 4621 4622 " :grepadd 4623 call setqflist([], 'f') 4624 exe "grepadd F1 Xerr" 4625 call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title) 4626 set grepprg&vim 4627 4628 " :vimgrep 4629 exe "vimgrep F1 Xerr" 4630 call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title) 4631 4632 " :vimgrepadd 4633 call setqflist([], 'f') 4634 exe "vimgrepadd F1 Xerr" 4635 call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title) 4636 4637 call setqflist(['F1:10:L10'], ' ') 4638 call assert_equal(':setqflist()', getqflist({'title' : 1}).title) 4639 4640 call setqflist([], 'f') 4641 call setqflist(['F1:10:L10'], 'a') 4642 call assert_equal(':setqflist()', getqflist({'title' : 1}).title) 4643 4644 call setqflist([], 'f') 4645 call setqflist(['F1:10:L10'], 'r') 4646 call assert_equal(':setqflist()', getqflist({'title' : 1}).title) 4647 4648 close 4649 call delete('Xerr') 4650 4651 call setqflist([], ' ', {'title' : 'Errors'}) 4652 copen 4653 call assert_equal('Errors', w:quickfix_title) 4654 call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]}) 4655 call assert_equal('Errors', w:quickfix_title) 4656 cclose 4657 4658 " Switching to another quickfix list in one tab page should update the 4659 " quickfix window title and statusline in all the other tab pages also 4660 call setqflist([], 'f') 4661 %bw! 4662 cgetexpr ['file_one:1:1: error in the first quickfix list'] 4663 call setqflist([], 'a', {'title': 'first quickfix list'}) 4664 cgetexpr ['file_two:2:1: error in the second quickfix list'] 4665 call setqflist([], 'a', {'title': 'second quickfix list'}) 4666 copen 4667 wincmd t 4668 tabnew two 4669 copen 4670 wincmd t 4671 colder 4672 call assert_equal('first quickfix list', gettabwinvar(1, 2, 'quickfix_title')) 4673 call assert_equal('first quickfix list', gettabwinvar(2, 2, 'quickfix_title')) 4674 call assert_equal(1, tabpagewinnr(1)) 4675 call assert_equal(1, tabpagewinnr(2)) 4676 tabnew 4677 call setqflist([], 'a', {'title': 'new quickfix title'}) 4678 call assert_equal('new quickfix title', gettabwinvar(1, 2, 'quickfix_title')) 4679 call assert_equal('new quickfix title', gettabwinvar(2, 2, 'quickfix_title')) 4680 %bw! 4681 endfunc 4682 4683 func Test_lbuffer_with_bwipe() 4684 new 4685 new 4686 augroup nasty 4687 au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bwipe 4688 augroup END 4689 lbuffer 4690 augroup nasty 4691 au! 4692 augroup END 4693 endfunc 4694 4695 " Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is 4696 " running 4697 func Xexpr_acmd_freelist(cchar) 4698 call s:setup_commands(a:cchar) 4699 4700 " This was using freed memory (but with what events?) 4701 augroup nasty 4702 au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call g:Xsetlist([], 'f') 4703 augroup END 4704 Xexpr "x" 4705 augroup nasty 4706 au! 4707 augroup END 4708 endfunc 4709 4710 func Test_cexpr_acmd_freelist() 4711 call Xexpr_acmd_freelist('c') 4712 call Xexpr_acmd_freelist('l') 4713 endfunc 4714 4715 " Test for commands that create a new quickfix/location list and jump to the 4716 " first error automatically. 4717 func Xjumpto_first_error_test(cchar) 4718 call s:setup_commands(a:cchar) 4719 4720 call s:create_test_file('Xtestfile1') 4721 call s:create_test_file('Xtestfile2') 4722 let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4'] 4723 4724 " Test for cexpr/lexpr 4725 enew 4726 Xexpr l 4727 call assert_equal('Xtestfile1', @%) 4728 call assert_equal(2, line('.')) 4729 4730 " Test for cfile/lfile 4731 enew 4732 call writefile(l, 'Xerr') 4733 Xfile Xerr 4734 call assert_equal('Xtestfile1', @%) 4735 call assert_equal(2, line('.')) 4736 4737 " Test for cbuffer/lbuffer 4738 edit Xerr 4739 Xbuffer 4740 call assert_equal('Xtestfile1', @%) 4741 call assert_equal(2, line('.')) 4742 4743 call delete('Xerr') 4744 call delete('Xtestfile1') 4745 call delete('Xtestfile2') 4746 endfunc 4747 4748 func Test_jumpto_first_error() 4749 call Xjumpto_first_error_test('c') 4750 call Xjumpto_first_error_test('l') 4751 endfunc 4752 4753 " Test for a quickfix autocmd changing the quickfix/location list before 4754 " jumping to the first error in the new list. 4755 func Xautocmd_changelist(cchar) 4756 call s:setup_commands(a:cchar) 4757 4758 " Test for cfile/lfile 4759 call s:create_test_file('Xtestfile1') 4760 call s:create_test_file('Xtestfile2') 4761 Xexpr 'Xtestfile1:2:Line2' 4762 autocmd QuickFixCmdPost * Xolder 4763 call writefile(['Xtestfile2:4:Line4'], 'Xerr') 4764 Xfile Xerr 4765 call assert_equal('Xtestfile2', @%) 4766 call assert_equal(4, line('.')) 4767 autocmd! QuickFixCmdPost 4768 4769 " Test for cbuffer/lbuffer 4770 call g:Xsetlist([], 'f') 4771 Xexpr 'Xtestfile1:2:Line2' 4772 autocmd QuickFixCmdPost * Xolder 4773 call writefile(['Xtestfile2:4:Line4'], 'Xerr') 4774 edit Xerr 4775 Xbuffer 4776 call assert_equal('Xtestfile2', @%) 4777 call assert_equal(4, line('.')) 4778 autocmd! QuickFixCmdPost 4779 4780 " Test for cexpr/lexpr 4781 call g:Xsetlist([], 'f') 4782 Xexpr 'Xtestfile1:2:Line2' 4783 autocmd QuickFixCmdPost * Xolder 4784 Xexpr 'Xtestfile2:4:Line4' 4785 call assert_equal('Xtestfile2', @%) 4786 call assert_equal(4, line('.')) 4787 autocmd! QuickFixCmdPost 4788 4789 " The grepprg may not be set on non-Unix systems 4790 if has('unix') 4791 " Test for grep/lgrep 4792 call g:Xsetlist([], 'f') 4793 Xexpr 'Xtestfile1:2:Line2' 4794 autocmd QuickFixCmdPost * Xolder 4795 silent Xgrep Line5 Xtestfile2 4796 call assert_equal('Xtestfile2', @%) 4797 call assert_equal(5, line('.')) 4798 autocmd! QuickFixCmdPost 4799 endif 4800 4801 " Test for vimgrep/lvimgrep 4802 call g:Xsetlist([], 'f') 4803 Xexpr 'Xtestfile1:2:Line2' 4804 autocmd QuickFixCmdPost * Xolder 4805 silent Xvimgrep Line5 Xtestfile2 4806 call assert_equal('Xtestfile2', @%) 4807 call assert_equal(5, line('.')) 4808 autocmd! QuickFixCmdPost 4809 4810 " Test for autocommands clearing the quickfix list before jumping to the 4811 " first error. This should not result in an error 4812 autocmd QuickFixCmdPost * call g:Xsetlist([], 'r') 4813 let v:errmsg = '' 4814 " Test for cfile/lfile 4815 Xfile Xerr 4816 call assert_true(v:errmsg !~# 'E42:') 4817 " Test for cbuffer/lbuffer 4818 edit Xerr 4819 Xbuffer 4820 call assert_true(v:errmsg !~# 'E42:') 4821 " Test for cexpr/lexpr 4822 Xexpr 'Xtestfile2:4:Line4' 4823 call assert_true(v:errmsg !~# 'E42:') 4824 " Test for grep/lgrep 4825 " The grepprg may not be set on non-Unix systems 4826 if has('unix') 4827 silent Xgrep Line5 Xtestfile2 4828 call assert_true(v:errmsg !~# 'E42:') 4829 endif 4830 " Test for vimgrep/lvimgrep 4831 call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:') 4832 autocmd! QuickFixCmdPost 4833 4834 call delete('Xerr') 4835 call delete('Xtestfile1') 4836 call delete('Xtestfile2') 4837 endfunc 4838 4839 func Test_autocmd_changelist() 4840 call Xautocmd_changelist('c') 4841 call Xautocmd_changelist('l') 4842 endfunc 4843 4844 " Tests for the ':filter /pat/ clist' command 4845 func Test_filter_clist() 4846 cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15'] 4847 call assert_equal([' 2 Xfile2:15 col 15: Line 15'], 4848 \ split(execute('filter /Line 15/ clist'), "\n")) 4849 call assert_equal([' 1 Xfile1:10 col 10: Line 10'], 4850 \ split(execute('filter /Xfile1/ clist'), "\n")) 4851 call assert_equal([], split(execute('filter /abc/ clist'), "\n")) 4852 4853 call setqflist([{'module' : 'abc', 'pattern' : 'pat1'}, 4854 \ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ') 4855 call assert_equal([' 2 pqr:pat2: '], 4856 \ split(execute('filter /pqr/ clist'), "\n")) 4857 call assert_equal([' 1 abc:pat1: '], 4858 \ split(execute('filter /pat1/ clist'), "\n")) 4859 endfunc 4860 4861 " Tests for the "CTRL-W <CR>" command. 4862 func Xview_result_split_tests(cchar) 4863 call s:setup_commands(a:cchar) 4864 4865 " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list. 4866 call g:Xsetlist([]) 4867 Xopen 4868 let l:win_count = winnr('$') 4869 call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42') 4870 call assert_equal(l:win_count, winnr('$')) 4871 Xclose 4872 endfunc 4873 4874 func Test_view_result_split() 4875 call Xview_result_split_tests('c') 4876 call Xview_result_split_tests('l') 4877 endfunc 4878 4879 " Test that :cc sets curswant 4880 func Test_curswant() 4881 helpgrep quickfix 4882 normal! llll 4883 1cc 4884 call assert_equal(getcurpos()[4], virtcol('.')) 4885 cclose | helpclose 4886 endfunc 4887 4888 " Test for opening a file from the quickfix window using CTRL-W <Enter> 4889 " doesn't leave an empty buffer around. 4890 func Test_splitview() 4891 call s:create_test_file('Xtestfile1') 4892 call s:create_test_file('Xtestfile2') 4893 new | only 4894 let last_bufnr = bufnr('Test_sv_1', 1) 4895 let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4'] 4896 cgetexpr l 4897 copen 4898 let numbufs = len(getbufinfo()) 4899 exe "normal \<C-W>\<CR>" 4900 copen 4901 exe "normal j\<C-W>\<CR>" 4902 " Make sure new empty buffers are not created 4903 call assert_equal(numbufs, len(getbufinfo())) 4904 " Creating a new buffer should use the next available buffer number 4905 call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1)) 4906 bwipe Test_sv_1 4907 bwipe Test_sv_2 4908 new | only 4909 4910 " When split opening files from location list window, make sure that two 4911 " windows doesn't refer to the same location list 4912 lgetexpr l 4913 let locid = getloclist(0, {'id' : 0}).id 4914 lopen 4915 exe "normal \<C-W>\<CR>" 4916 call assert_notequal(locid, getloclist(0, {'id' : 0}).id) 4917 call assert_equal(0, getloclist(0, {'winid' : 0}).winid) 4918 new | only 4919 4920 " When split opening files from a helpgrep location list window, a new help 4921 " window should be opened with a copy of the location list. 4922 lhelpgrep window 4923 let locid = getloclist(0, {'id' : 0}).id 4924 lwindow 4925 exe "normal j\<C-W>\<CR>" 4926 call assert_notequal(locid, getloclist(0, {'id' : 0}).id) 4927 call assert_equal(0, getloclist(0, {'winid' : 0}).winid) 4928 new | only 4929 4930 " Using :split or :vsplit from a quickfix window should behave like a :new 4931 " or a :vnew command 4932 copen 4933 split 4934 call assert_equal(3, winnr('$')) 4935 let l = getwininfo() 4936 call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix]) 4937 close 4938 copen 4939 vsplit 4940 let l = getwininfo() 4941 call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix]) 4942 new | only 4943 4944 call delete('Xtestfile1') 4945 call delete('Xtestfile2') 4946 endfunc 4947 4948 " Test for parsing entries using visual screen column 4949 func Test_viscol() 4950 enew 4951 call writefile(["Col1\tCol2\tCol3"], 'Xfile1') 4952 edit Xfile1 4953 4954 " Use byte offset for column number 4955 set efm& 4956 cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ" 4957 call assert_equal([5, 8], [col('.'), virtcol('.')]) 4958 cnext 4959 call assert_equal([9, 12], [col('.'), virtcol('.')]) 4960 cnext 4961 call assert_equal([14, 20], [col('.'), virtcol('.')]) 4962 4963 " Use screen column offset for column number 4964 set efm=%f:%l:%v:%m 4965 cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ" 4966 call assert_equal([5, 8], [col('.'), virtcol('.')]) 4967 cnext 4968 call assert_equal([9, 12], [col('.'), virtcol('.')]) 4969 cnext 4970 call assert_equal([14, 20], [col('.'), virtcol('.')]) 4971 cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ" 4972 call assert_equal([5, 8], [col('.'), virtcol('.')]) 4973 cnext 4974 call assert_equal([10, 16], [col('.'), virtcol('.')]) 4975 cnext 4976 call assert_equal([14, 20], [col('.'), virtcol('.')]) 4977 4978 enew 4979 call writefile(["Col1\täü\töß\tCol4"], 'Xfile1') 4980 4981 " Use byte offset for column number 4982 set efm& 4983 cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ" 4984 call assert_equal([8, 10], [col('.'), virtcol('.')]) 4985 cnext 4986 call assert_equal([11, 17], [col('.'), virtcol('.')]) 4987 cnext 4988 call assert_equal([16, 25], [col('.'), virtcol('.')]) 4989 4990 " Use screen column offset for column number 4991 set efm=%f:%l:%v:%m 4992 cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ" 4993 call assert_equal([8, 10], [col('.'), virtcol('.')]) 4994 cnext 4995 call assert_equal([11, 17], [col('.'), virtcol('.')]) 4996 cnext 4997 call assert_equal([16, 25], [col('.'), virtcol('.')]) 4998 4999 " Use screen column number with a multi-line error message 5000 enew 5001 call writefile(["à test"], 'Xfile1') 5002 set efm=%E===\ %f\ ===,%C%l:%v,%Z%m 5003 cexpr ["=== Xfile1 ===", "1:3", "errormsg"] 5004 call assert_equal('Xfile1', @%) 5005 call assert_equal([0, 1, 4, 0], getpos('.')) 5006 5007 " Repeat previous test with byte offset %c: ensure that fix to issue #7145 5008 " does not break this 5009 set efm=%E===\ %f\ ===,%C%l:%c,%Z%m 5010 cexpr ["=== Xfile1 ===", "1:3", "errormsg"] 5011 call assert_equal('Xfile1', @%) 5012 call assert_equal([0, 1, 3, 0], getpos('.')) 5013 5014 enew | only 5015 set efm& 5016 call delete('Xfile1') 5017 endfunc 5018 5019 " Test for the quickfix window buffer 5020 func Xqfbuf_test(cchar) 5021 call s:setup_commands(a:cchar) 5022 5023 " Quickfix buffer should be reused across closing and opening a quickfix 5024 " window 5025 Xexpr "F1:10:Line10" 5026 Xopen 5027 let qfbnum = bufnr('') 5028 Xclose 5029 " Even after the quickfix window is closed, the buffer should be loaded 5030 call assert_true(bufloaded(qfbnum)) 5031 call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr) 5032 Xopen 5033 " Buffer should be reused when opening the window again 5034 call assert_equal(qfbnum, bufnr('')) 5035 Xclose 5036 5037 " When quickfix buffer is wiped out, getqflist() should return 0 5038 %bw! 5039 Xexpr "" 5040 Xopen 5041 bw! 5042 call assert_equal(0, g:Xgetlist({'qfbufnr': 0}).qfbufnr) 5043 5044 if a:cchar == 'l' 5045 %bwipe 5046 " For a location list, when both the file window and the location list 5047 " window for the list are closed, then the buffer should be freed. 5048 new | only 5049 lexpr "F1:10:Line10" 5050 let wid = win_getid() 5051 lopen 5052 let qfbnum = bufnr('') 5053 call assert_match(qfbnum . ' %a- "\[Location List]"', execute('ls')) 5054 close 5055 " When the location list window is closed, the buffer name should not 5056 " change to 'Quickfix List' 5057 call assert_match(qfbnum . 'u h- "\[Location List]"', execute('ls!')) 5058 call assert_true(bufloaded(qfbnum)) 5059 5060 " After deleting a location list buffer using ":bdelete", opening the 5061 " location list window should mark the buffer as a location list buffer. 5062 exe "bdelete " . qfbnum 5063 lopen 5064 call assert_equal("quickfix", &buftype) 5065 call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist) 5066 call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid) 5067 call assert_false(&swapfile) 5068 lclose 5069 5070 " When the location list is cleared for the window, the buffer should be 5071 " removed 5072 call setloclist(0, [], 'f') 5073 call assert_false(bufexists(qfbnum)) 5074 call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr) 5075 5076 " When the location list is freed with the location list window open, the 5077 " location list buffer should not be lost. It should be reused when the 5078 " location list is again populated. 5079 lexpr "F1:10:Line10" 5080 lopen 5081 let wid = win_getid() 5082 let qfbnum = bufnr('') 5083 wincmd p 5084 call setloclist(0, [], 'f') 5085 lexpr "F1:10:Line10" 5086 lopen 5087 call assert_equal(wid, win_getid()) 5088 call assert_equal(qfbnum, bufnr('')) 5089 lclose 5090 5091 " When the window with the location list is closed, the buffer should be 5092 " removed 5093 new | only 5094 call assert_false(bufexists(qfbnum)) 5095 endif 5096 endfunc 5097 5098 func Test_qfbuf() 5099 call Xqfbuf_test('c') 5100 call Xqfbuf_test('l') 5101 endfunc 5102 5103 " If there is an autocmd to use only one window, then opening the location 5104 " list window used to crash Vim. 5105 func Test_winonly_autocmd() 5106 call s:create_test_file('Xtest1') 5107 " Autocmd to show only one Vim window at a time 5108 autocmd WinEnter * only 5109 new 5110 " Load the location list 5111 lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15" 5112 let loclistid = getloclist(0, {'id' : 0}).id 5113 " Open the location list window. Only this window will be shown and the file 5114 " window is closed. 5115 lopen 5116 call assert_equal(loclistid, getloclist(0, {'id' : 0}).id) 5117 " Jump to an entry in the location list and make sure that the cursor is 5118 " positioned correctly. 5119 ll 3 5120 call assert_equal(loclistid, getloclist(0, {'id' : 0}).id) 5121 call assert_equal('Xtest1', @%) 5122 call assert_equal(15, line('.')) 5123 " Cleanup 5124 autocmd! WinEnter 5125 new | only 5126 call delete('Xtest1') 5127 endfunc 5128 5129 " Test to make sure that an empty quickfix buffer is not reused for loading 5130 " a normal buffer. 5131 func Test_empty_qfbuf() 5132 enew | only 5133 call writefile(["Test"], 'Xfile1') 5134 call setqflist([], 'f') 5135 copen | only 5136 let qfbuf = bufnr('') 5137 edit Xfile1 5138 call assert_notequal(qfbuf, bufnr('')) 5139 enew 5140 call delete('Xfile1') 5141 endfunc 5142 5143 " Test for the :cbelow, :cabove, :lbelow and :labove commands. 5144 " And for the :cafter, :cbefore, :lafter and :lbefore commands. 5145 func Xtest_below(cchar) 5146 call s:setup_commands(a:cchar) 5147 5148 " No quickfix/location list 5149 call assert_fails('Xbelow', 'E42:') 5150 call assert_fails('Xabove', 'E42:') 5151 call assert_fails('Xbefore', 'E42:') 5152 call assert_fails('Xafter', 'E42:') 5153 5154 " Empty quickfix/location list 5155 call g:Xsetlist([]) 5156 call assert_fails('Xbelow', 'E42:') 5157 call assert_fails('Xabove', 'E42:') 5158 call assert_fails('Xbefore', 'E42:') 5159 call assert_fails('Xafter', 'E42:') 5160 5161 call s:create_test_file('X1') 5162 call s:create_test_file('X2') 5163 call s:create_test_file('X3') 5164 call s:create_test_file('X4') 5165 5166 " Invalid entries 5167 edit X1 5168 call g:Xsetlist(["E1", "E2"]) 5169 call assert_fails('Xbelow', 'E42:') 5170 call assert_fails('Xabove', 'E42:') 5171 call assert_fails('3Xbelow', 'E42:') 5172 call assert_fails('4Xabove', 'E42:') 5173 call assert_fails('Xbefore', 'E42:') 5174 call assert_fails('Xafter', 'E42:') 5175 call assert_fails('3Xbefore', 'E42:') 5176 call assert_fails('4Xafter', 'E42:') 5177 5178 " Test the commands with various arguments 5179 Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"] 5180 edit +7 X2 5181 Xabove 5182 call assert_equal(['X2', 5], [@%, line('.')]) 5183 call assert_fails('Xabove', 'E553:') 5184 normal 7G 5185 Xbefore 5186 call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')]) 5187 call assert_fails('Xbefore', 'E553:') 5188 5189 normal 2j 5190 Xbelow 5191 call assert_equal(['X2', 10], [@%, line('.')]) 5192 normal 7G 5193 Xafter 5194 call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')]) 5195 5196 " Last error in this file 5197 Xbelow 99 5198 call assert_equal(['X2', 15], [@%, line('.')]) 5199 call assert_fails('Xbelow', 'E553:') 5200 normal gg 5201 Xafter 99 5202 call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')]) 5203 call assert_fails('Xafter', 'E553:') 5204 5205 " First error in this file 5206 Xabove 99 5207 call assert_equal(['X2', 5], [@%, line('.')]) 5208 call assert_fails('Xabove', 'E553:') 5209 normal G 5210 Xbefore 99 5211 call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')]) 5212 call assert_fails('Xbefore', 'E553:') 5213 5214 normal gg 5215 Xbelow 2 5216 call assert_equal(['X2', 10], [@%, line('.')]) 5217 normal gg 5218 Xafter 2 5219 call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')]) 5220 5221 normal G 5222 Xabove 2 5223 call assert_equal(['X2', 10], [@%, line('.')]) 5224 normal G 5225 Xbefore 2 5226 call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')]) 5227 5228 edit X4 5229 call assert_fails('Xabove', 'E42:') 5230 call assert_fails('Xbelow', 'E42:') 5231 call assert_fails('Xbefore', 'E42:') 5232 call assert_fails('Xafter', 'E42:') 5233 if a:cchar == 'l' 5234 " If a buffer has location list entries from some other window but not 5235 " from the current window, then the commands should fail. 5236 edit X1 | split | call setloclist(0, [], 'f') 5237 call assert_fails('Xabove', 'E776:') 5238 call assert_fails('Xbelow', 'E776:') 5239 call assert_fails('Xbefore', 'E776:') 5240 call assert_fails('Xafter', 'E776:') 5241 close 5242 endif 5243 5244 " Test for lines with multiple quickfix entries 5245 let lines =<< trim END 5246 X1:5:L5 5247 X2:5:1:L5_1 5248 X2:5:2:L5_2 5249 X2:5:3:L5_3 5250 X2:10:1:L10_1 5251 X2:10:2:L10_2 5252 X2:10:3:L10_3 5253 X2:15:1:L15_1 5254 X2:15:2:L15_2 5255 X2:15:3:L15_3 5256 X3:3:L3 5257 END 5258 Xexpr lines 5259 edit +1 X2 5260 Xbelow 2 5261 call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')]) 5262 normal 1G 5263 Xafter 2 5264 call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')]) 5265 5266 normal gg 5267 Xbelow 99 5268 call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')]) 5269 normal gg 5270 Xafter 99 5271 call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')]) 5272 5273 normal G 5274 Xabove 2 5275 call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')]) 5276 normal G 5277 Xbefore 2 5278 call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')]) 5279 5280 normal G 5281 Xabove 99 5282 call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')]) 5283 normal G 5284 Xbefore 99 5285 call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')]) 5286 5287 normal 10G 5288 Xabove 5289 call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')]) 5290 normal 10G$ 5291 2Xbefore 5292 call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')]) 5293 5294 normal 10G 5295 Xbelow 5296 call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')]) 5297 normal 9G 5298 5Xafter 5299 call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')]) 5300 5301 " Invalid range 5302 if a:cchar == 'c' 5303 call assert_fails('-2cbelow', 'E16:') 5304 call assert_fails('-2cafter', 'E16:') 5305 else 5306 call assert_fails('-2lbelow', 'E16:') 5307 call assert_fails('-2lafter', 'E16:') 5308 endif 5309 5310 call delete('X1') 5311 call delete('X2') 5312 call delete('X3') 5313 call delete('X4') 5314 endfunc 5315 5316 func Test_cbelow() 5317 call Xtest_below('c') 5318 call Xtest_below('l') 5319 endfunc 5320 5321 func Test_quickfix_count() 5322 let commands =<< trim END 5323 cNext 5324 cNfile 5325 cabove 5326 cbelow 5327 cfirst 5328 clast 5329 cnewer 5330 cnext 5331 cnfile 5332 colder 5333 cprevious 5334 crewind 5335 lNext 5336 lNfile 5337 labove 5338 lbelow 5339 lfirst 5340 llast 5341 lnewer 5342 lnext 5343 lnfile 5344 lolder 5345 lprevious 5346 lrewind 5347 END 5348 for cmd in commands 5349 call assert_fails('-1' .. cmd, 'E16:') 5350 call assert_fails('.' .. cmd, 'E16:') 5351 call assert_fails('%' .. cmd, 'E16:') 5352 call assert_fails('$' .. cmd, 'E16:') 5353 endfor 5354 endfunc 5355 5356 " Test for aborting quickfix commands using QuickFixCmdPre 5357 func Xtest_qfcmd_abort(cchar) 5358 call s:setup_commands(a:cchar) 5359 5360 call g:Xsetlist([], 'f') 5361 5362 " cexpr/lexpr 5363 let e = '' 5364 try 5365 Xexpr ["F1:10:Line10", "F2:20:Line20"] 5366 catch /.*/ 5367 let e = v:exception 5368 endtry 5369 call assert_equal('AbortCmd', e) 5370 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5371 5372 " cfile/lfile 5373 call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1') 5374 let e = '' 5375 try 5376 Xfile Xfile1 5377 catch /.*/ 5378 let e = v:exception 5379 endtry 5380 call assert_equal('AbortCmd', e) 5381 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5382 call delete('Xfile1') 5383 5384 " cgetbuffer/lgetbuffer 5385 enew! 5386 call append(0, ["F1:10:Line10", "F2:20:Line20"]) 5387 let e = '' 5388 try 5389 Xgetbuffer 5390 catch /.*/ 5391 let e = v:exception 5392 endtry 5393 call assert_equal('AbortCmd', e) 5394 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5395 enew! 5396 5397 " vimgrep/lvimgrep 5398 let e = '' 5399 try 5400 Xvimgrep /func/ test_quickfix.vim 5401 catch /.*/ 5402 let e = v:exception 5403 endtry 5404 call assert_equal('AbortCmd', e) 5405 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5406 5407 " helpgrep/lhelpgrep 5408 let e = '' 5409 try 5410 Xhelpgrep quickfix 5411 catch /.*/ 5412 let e = v:exception 5413 endtry 5414 call assert_equal('AbortCmd', e) 5415 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5416 5417 " grep/lgrep 5418 if has('unix') 5419 let e = '' 5420 try 5421 silent Xgrep func test_quickfix.vim 5422 catch /.*/ 5423 let e = v:exception 5424 endtry 5425 call assert_equal('AbortCmd', e) 5426 call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) 5427 endif 5428 endfunc 5429 5430 func Test_qfcmd_abort() 5431 augroup QF_Test 5432 au! 5433 autocmd QuickFixCmdPre * throw "AbortCmd" 5434 augroup END 5435 5436 call Xtest_qfcmd_abort('c') 5437 call Xtest_qfcmd_abort('l') 5438 5439 augroup QF_Test 5440 au! 5441 augroup END 5442 endfunc 5443 5444 " Test for using a file in one of the parent directories. 5445 func Test_search_in_dirstack() 5446 call mkdir('Xtestdir/a/b/c', 'p') 5447 let save_cwd = getcwd() 5448 call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1') 5449 call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2') 5450 call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3') 5451 call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4') 5452 5453 let lines = "Entering dir Xtestdir\n" . 5454 \ "Entering dir a\n" . 5455 \ "Entering dir b\n" . 5456 \ "Xfile2:2:X2_L2\n" . 5457 \ "Leaving dir a\n" . 5458 \ "Xfile1:2:X1_L2\n" . 5459 \ "Xfile3:1:X3_L1\n" . 5460 \ "Entering dir c\n" . 5461 \ "Xfile4:2:X4_L2\n" . 5462 \ "Leaving dir c\n" 5463 set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m 5464 cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1 5465 call assert_equal(11, getqflist({'size' : 0}).size) 5466 call assert_equal(4, getqflist({'idx' : 0}).idx) 5467 call assert_equal('X2_L2', getline('.')) 5468 call assert_equal(1, next) 5469 cnext 5470 call assert_equal(6, getqflist({'idx' : 0}).idx) 5471 call assert_equal('X1_L2', getline('.')) 5472 cnext 5473 call assert_equal(7, getqflist({'idx' : 0}).idx) 5474 call assert_equal(1, line('$')) 5475 call assert_equal('', getline(1)) 5476 cnext 5477 call assert_equal(9, getqflist({'idx' : 0}).idx) 5478 call assert_equal(1, line('$')) 5479 call assert_equal('', getline(1)) 5480 5481 set efm& 5482 exe 'cd ' . save_cwd 5483 call delete('Xtestdir', 'rf') 5484 endfunc 5485 5486 " Test for :cquit 5487 func Test_cquit() 5488 " Exit Vim with a non-zero value 5489 if RunVim([], ["cquit 7"], '') 5490 call assert_equal(7, v:shell_error) 5491 endif 5492 5493 if RunVim([], ["50cquit"], '') 5494 call assert_equal(50, v:shell_error) 5495 endif 5496 5497 " Exit Vim with default value 5498 if RunVim([], ["cquit"], '') 5499 call assert_equal(1, v:shell_error) 5500 endif 5501 5502 " Exit Vim with zero value 5503 if RunVim([], ["cquit 0"], '') 5504 call assert_equal(0, v:shell_error) 5505 endif 5506 5507 " Exit Vim with negative value 5508 call assert_fails('-3cquit', 'E16:') 5509 endfunc 5510 5511 " Test for getting a specific item from a quickfix list 5512 func Xtest_getqflist_by_idx(cchar) 5513 call s:setup_commands(a:cchar) 5514 " Empty list 5515 call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items) 5516 Xexpr ['F1:10:L10', 'F1:20:L20'] 5517 let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items 5518 call assert_equal(bufnr('F1'), l[0].bufnr) 5519 call assert_equal(20, l[0].lnum) 5520 call assert_equal('L20', l[0].text) 5521 call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items) 5522 call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items) 5523 call assert_equal({}, g:Xgetlist(#{idx: "abc"})) 5524 %bwipe! 5525 endfunc 5526 5527 func Test_getqflist_by_idx() 5528 call Xtest_getqflist_by_idx('c') 5529 call Xtest_getqflist_by_idx('l') 5530 endfunc 5531 5532 " Test for the 'quickfixtextfunc' setting 5533 func Tqfexpr(info) 5534 if a:info.quickfix 5535 let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items 5536 else 5537 let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items 5538 endif 5539 5540 let l = [] 5541 for idx in range(a:info.start_idx - 1, a:info.end_idx - 1) 5542 let e = qfl[idx] 5543 let s = '' 5544 if e.bufnr != 0 5545 let bname = bufname(e.bufnr) 5546 let s ..= fnamemodify(bname, ':.') 5547 endif 5548 let s ..= '-' 5549 let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-' 5550 let s ..= e.text 5551 call add(l, s) 5552 endfor 5553 5554 return l 5555 endfunc 5556 5557 func Xtest_qftextfunc(cchar) 5558 call s:setup_commands(a:cchar) 5559 5560 set efm=%f:%l:%c:%m 5561 set quickfixtextfunc=Tqfexpr 5562 call assert_equal('Tqfexpr', &quickfixtextfunc) 5563 call assert_equal('', 5564 \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) 5565 call g:Xsetlist([ 5566 \ { 'filename': 'F1', 'lnum': 10, 'col': 2, 5567 \ 'end_col': 7, 'text': 'green'}, 5568 \ { 'filename': 'F1', 'lnum': 20, 'end_lnum': 25, 'col': 4, 5569 \ 'end_col': 8, 'text': 'blue'}, 5570 \ ]) 5571 5572 Xwindow 5573 call assert_equal('F1-L10C2-green', getline(1)) 5574 call assert_equal('F1-L20C4-blue', getline(2)) 5575 Xclose 5576 set quickfixtextfunc&vim 5577 Xwindow 5578 call assert_equal('F1|10 col 2-7| green', getline(1)) 5579 call assert_equal('F1|20-25 col 4-8| blue', getline(2)) 5580 Xclose 5581 5582 set efm=%f:%l:%c:%m 5583 set quickfixtextfunc=Tqfexpr 5584 " Update the list with only the cwindow 5585 Xwindow 5586 only 5587 call g:Xsetlist([ 5588 \ { 'filename': 'F2', 'lnum': 20, 'col': 2, 5589 \ 'end_col': 7, 'text': 'red'} 5590 \ ]) 5591 call assert_equal(['F2-L20C2-red'], getline(1, '$')) 5592 new 5593 Xclose 5594 set efm& 5595 set quickfixtextfunc& 5596 5597 " Test for per list 'quickfixtextfunc' setting 5598 func PerQfText(info) 5599 if a:info.quickfix 5600 let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items 5601 else 5602 let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items 5603 endif 5604 if empty(qfl) 5605 return [] 5606 endif 5607 let l = [] 5608 for idx in range(a:info.start_idx - 1, a:info.end_idx - 1) 5609 call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col) 5610 endfor 5611 return l 5612 endfunc 5613 set quickfixtextfunc=Tqfexpr 5614 call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"}) 5615 Xaddexpr ['F1:10:2:green', 'F1:20:4:blue'] 5616 Xwindow 5617 call assert_equal('Line 10, Col 2', getline(1)) 5618 call assert_equal('Line 20, Col 4', getline(2)) 5619 Xclose 5620 call assert_equal(function('PerQfText'), 5621 \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) 5622 " Add entries to the list when the quickfix buffer is hidden 5623 Xaddexpr ['F1:30:6:red'] 5624 Xwindow 5625 call assert_equal('Line 30, Col 6', getline(3)) 5626 Xclose 5627 call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''}) 5628 call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) 5629 set quickfixtextfunc& 5630 delfunc PerQfText 5631 5632 " Non-existing function 5633 set quickfixtextfunc=Tabc 5634 call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:') 5635 call assert_fails("Xwindow", 'E117:') 5636 Xclose 5637 set quickfixtextfunc& 5638 5639 " set option to a non-function 5640 set quickfixtextfunc=[10,\ 20] 5641 call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:') 5642 call assert_fails("Xwindow", 'E117:') 5643 Xclose 5644 set quickfixtextfunc& 5645 5646 " set option to a function with different set of arguments 5647 func Xqftext(a, b, c) 5648 return a:a .. a:b .. a:c 5649 endfunc 5650 set quickfixtextfunc=Xqftext 5651 call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:') 5652 call assert_fails("Xwindow", 'E119:') 5653 Xclose 5654 5655 " set option to a function that returns a list with non-strings 5656 func Xqftext2(d) 5657 return ['one', [], 'two'] 5658 endfunc 5659 set quickfixtextfunc=Xqftext2 5660 call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']", 5661 \ 'E730:') 5662 call assert_fails('Xwindow', 'E730:') 5663 call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'], 5664 \ getline(1, '$')) 5665 Xclose 5666 5667 set quickfixtextfunc& 5668 delfunc Xqftext 5669 delfunc Xqftext2 5670 5671 " set the global option to a lambda function 5672 set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')} 5673 Xexpr ['F1:10:2:green', 'F1:20:4:blue'] 5674 Xwindow 5675 call assert_equal(['green', 'blue'], getline(1, '$')) 5676 Xclose 5677 call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc) 5678 set quickfixtextfunc& 5679 5680 " use a lambda function that returns an empty list 5681 set quickfixtextfunc={d\ ->\ []} 5682 Xexpr ['F1:10:2:green', 'F1:20:4:blue'] 5683 Xwindow 5684 call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'], 5685 \ getline(1, '$')) 5686 Xclose 5687 set quickfixtextfunc& 5688 5689 " use a lambda function that returns a list with empty strings 5690 set quickfixtextfunc={d\ ->\ ['',\ '']} 5691 Xexpr ['F1:10:2:green', 'F1:20:4:blue'] 5692 Xwindow 5693 call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'], 5694 \ getline(1, '$')) 5695 Xclose 5696 set quickfixtextfunc& 5697 5698 " set the per-quickfix list text function to a lambda function 5699 call g:Xsetlist([], ' ', 5700 \ {'quickfixtextfunc' : 5701 \ {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 5702 \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}}) 5703 Xaddexpr ['F1:10:2:green', 'F1:20:4:blue'] 5704 Xwindow 5705 call assert_equal('Line 10, Col 2', getline(1)) 5706 call assert_equal('Line 20, Col 4', getline(2)) 5707 Xclose 5708 call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)) 5709 call g:Xsetlist([], 'f') 5710 endfunc 5711 5712 func Test_qftextfunc() 5713 call Xtest_qftextfunc('c') 5714 call Xtest_qftextfunc('l') 5715 endfunc 5716 5717 func Test_qftextfunc_callback() 5718 let lines =<< trim END 5719 set efm=%f:%l:%c:%m 5720 5721 #" Test for using a function name 5722 LET &qftf = 'g:Tqfexpr' 5723 cexpr "F0:0:0:L0" 5724 copen 5725 call assert_equal('F0-L0C0-L0', getline(1)) 5726 cclose 5727 5728 #" Test for using a function() 5729 set qftf=function('g:Tqfexpr') 5730 cexpr "F1:1:1:L1" 5731 copen 5732 call assert_equal('F1-L1C1-L1', getline(1)) 5733 cclose 5734 5735 #" Using a funcref variable to set 'quickfixtextfunc' 5736 VAR Fn = function('g:Tqfexpr') 5737 LET &qftf = Fn 5738 cexpr "F2:2:2:L2" 5739 copen 5740 call assert_equal('F2-L2C2-L2', getline(1)) 5741 cclose 5742 5743 #" Using string(funcref_variable) to set 'quickfixtextfunc' 5744 LET Fn = function('g:Tqfexpr') 5745 LET &qftf = string(Fn) 5746 cexpr "F3:3:3:L3" 5747 copen 5748 call assert_equal('F3-L3C3-L3', getline(1)) 5749 cclose 5750 5751 #" Test for using a funcref() 5752 set qftf=funcref('g:Tqfexpr') 5753 cexpr "F4:4:4:L4" 5754 copen 5755 call assert_equal('F4-L4C4-L4', getline(1)) 5756 cclose 5757 5758 #" Using a funcref variable to set 'quickfixtextfunc' 5759 LET Fn = funcref('g:Tqfexpr') 5760 LET &qftf = Fn 5761 cexpr "F5:5:5:L5" 5762 copen 5763 call assert_equal('F5-L5C5-L5', getline(1)) 5764 cclose 5765 5766 #" Using a string(funcref_variable) to set 'quickfixtextfunc' 5767 LET Fn = funcref('g:Tqfexpr') 5768 LET &qftf = string(Fn) 5769 cexpr "F5:5:5:L5" 5770 copen 5771 call assert_equal('F5-L5C5-L5', getline(1)) 5772 cclose 5773 5774 #" Test for using a lambda function with set 5775 VAR optval = "LSTART a LMIDDLE Tqfexpr(a) LEND" 5776 LET optval = substitute(optval, ' ', '\\ ', 'g') 5777 exe "set qftf=" .. optval 5778 cexpr "F6:6:6:L6" 5779 copen 5780 call assert_equal('F6-L6C6-L6', getline(1)) 5781 cclose 5782 5783 #" Set 'quickfixtextfunc' to a lambda expression 5784 LET &qftf = LSTART a LMIDDLE Tqfexpr(a) LEND 5785 cexpr "F7:7:7:L7" 5786 copen 5787 call assert_equal('F7-L7C7-L7', getline(1)) 5788 cclose 5789 5790 #" Set 'quickfixtextfunc' to string(lambda_expression) 5791 LET &qftf = "LSTART a LMIDDLE Tqfexpr(a) LEND" 5792 cexpr "F8:8:8:L8" 5793 copen 5794 call assert_equal('F8-L8C8-L8', getline(1)) 5795 cclose 5796 5797 #" Set 'quickfixtextfunc' to a variable with a lambda expression 5798 VAR Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND 5799 LET &qftf = Lambda 5800 cexpr "F9:9:9:L9" 5801 copen 5802 call assert_equal('F9-L9C9-L9', getline(1)) 5803 cclose 5804 5805 #" Set 'quickfixtextfunc' to a string(variable with a lambda expression) 5806 LET Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND 5807 LET &qftf = string(Lambda) 5808 cexpr "F9:9:9:L9" 5809 copen 5810 call assert_equal('F9-L9C9-L9', getline(1)) 5811 cclose 5812 END 5813 call CheckLegacyAndVim9Success(lines) 5814 5815 " Test for using a script-local function name 5816 func s:TqfFunc2(info) 5817 let g:TqfFunc2Args = [a:info.start_idx, a:info.end_idx] 5818 return '' 5819 endfunc 5820 let g:TqfFunc2Args = [] 5821 set quickfixtextfunc=s:TqfFunc2 5822 cexpr "F10:10:10:L10" 5823 cclose 5824 call assert_equal([1, 1], g:TqfFunc2Args) 5825 5826 let &quickfixtextfunc = 's:TqfFunc2' 5827 cexpr "F11:11:11:L11" 5828 cclose 5829 call assert_equal([1, 1], g:TqfFunc2Args) 5830 delfunc s:TqfFunc2 5831 5832 " set 'quickfixtextfunc' to a partial with dict. This used to cause a crash. 5833 func SetQftfFunc() 5834 let params = {'qftf': function('g:DictQftfFunc')} 5835 let &quickfixtextfunc = params.qftf 5836 endfunc 5837 func g:DictQftfFunc(_) dict 5838 endfunc 5839 call SetQftfFunc() 5840 new 5841 call SetQftfFunc() 5842 bw 5843 call test_garbagecollect_now() 5844 new 5845 set qftf= 5846 wincmd w 5847 set qftf= 5848 :%bw! 5849 5850 " set per-quickfix list 'quickfixtextfunc' to a partial with dict. This used 5851 " to cause a crash. 5852 let &qftf = '' 5853 func SetLocalQftfFunc() 5854 let params = {'qftf': function('g:DictQftfFunc')} 5855 call setqflist([], 'a', {'quickfixtextfunc' : params.qftf}) 5856 endfunc 5857 call SetLocalQftfFunc() 5858 call test_garbagecollect_now() 5859 call setqflist([], 'a', {'quickfixtextfunc' : ''}) 5860 delfunc g:DictQftfFunc 5861 delfunc SetQftfFunc 5862 delfunc SetLocalQftfFunc 5863 set efm& 5864 endfunc 5865 5866 " Test for updating a location list for some other window and check that 5867 " 'qftextfunc' uses the correct location list. 5868 func Test_qftextfunc_other_loclist() 5869 %bw! 5870 call setloclist(0, [], 'f') 5871 5872 " create a window and a location list for it and open the location list 5873 " window 5874 lexpr ['F1:10:12:one', 'F1:20:14:two'] 5875 let w1_id = win_getid() 5876 call setloclist(0, [], ' ', 5877 \ {'lines': ['F1:10:12:one', 'F1:20:14:two'], 5878 \ 'quickfixtextfunc': 5879 \ {d -> map(getloclist(d.winid, {'id' : d.id, 5880 \ 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 5881 \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}}) 5882 lwindow 5883 let w2_id = win_getid() 5884 5885 " create another window and a location list for it and open the location 5886 " list window 5887 topleft new 5888 let w3_id = win_getid() 5889 call setloclist(0, [], ' ', 5890 \ {'lines': ['F2:30:32:eleven', 'F2:40:34:twelve'], 5891 \ 'quickfixtextfunc': 5892 \ {d -> map(getloclist(d.winid, {'id' : d.id, 5893 \ 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 5894 \ "'Ligne ' .. v:val.lnum .. ', Colonne ' .. v:val.col")}}) 5895 lwindow 5896 let w4_id = win_getid() 5897 5898 topleft new 5899 lexpr ['F3:50:52:green', 'F3:60:54:blue'] 5900 let w5_id = win_getid() 5901 5902 " change the location list for some other window 5903 call setloclist(0, [], 'r', {'lines': ['F3:55:56:aaa', 'F3:57:58:bbb']}) 5904 call setloclist(w1_id, [], 'r', {'lines': ['F1:62:63:bbb', 'F1:64:65:ccc']}) 5905 call setloclist(w3_id, [], 'r', {'lines': ['F2:76:77:ddd', 'F2:78:79:eee']}) 5906 call assert_equal(['Line 62, Col 63', 'Line 64, Col 65'], 5907 \ getbufline(winbufnr(w2_id), 1, '$')) 5908 call assert_equal(['Ligne 76, Colonne 77', 'Ligne 78, Colonne 79'], 5909 \ getbufline(winbufnr(w4_id), 1, '$')) 5910 call setloclist(w2_id, [], 'r', {'lines': ['F1:32:33:fff', 'F1:34:35:ggg']}) 5911 call setloclist(w4_id, [], 'r', {'lines': ['F2:46:47:hhh', 'F2:48:49:jjj']}) 5912 call assert_equal(['Line 32, Col 33', 'Line 34, Col 35'], 5913 \ getbufline(winbufnr(w2_id), 1, '$')) 5914 call assert_equal(['Ligne 46, Colonne 47', 'Ligne 48, Colonne 49'], 5915 \ getbufline(winbufnr(w4_id), 1, '$')) 5916 5917 call win_gotoid(w5_id) 5918 lwindow 5919 call assert_equal(['F3|55 col 56| aaa', 'F3|57 col 58| bbb'], 5920 \ getline(1, '$')) 5921 %bw! 5922 endfunc 5923 5924 " Running :lhelpgrep command more than once in a help window, doesn't jump to 5925 " the help topic 5926 func Test_lhelpgrep_from_help_window() 5927 call mkdir('Xtestdir/doc', 'p') 5928 call writefile(['window'], 'Xtestdir/doc/a.txt') 5929 call writefile(['buffer'], 'Xtestdir/doc/b.txt') 5930 let save_rtp = &rtp 5931 let &rtp = 'Xtestdir' 5932 lhelpgrep window 5933 lhelpgrep buffer 5934 call assert_equal('b.txt', fnamemodify(@%, ":p:t")) 5935 lhelpgrep window 5936 call assert_equal('a.txt', fnamemodify(@%, ":p:t")) 5937 let &rtp = save_rtp 5938 call delete('Xtestdir', 'rf') 5939 new | only! 5940 endfunc 5941 5942 " Test for the crash fixed by 7.3.715 5943 func Test_setloclist_crash() 5944 %bw! 5945 let g:BufNum = bufnr() 5946 augroup QF_Test 5947 au! 5948 au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}]) 5949 augroup END 5950 5951 try 5952 lvimgrep /.*/ *.mak 5953 catch /E926:/ 5954 endtry 5955 call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text) 5956 call assert_equal(1, getloclist(0, {'size' : 0}).size) 5957 5958 augroup QF_Test 5959 au! 5960 augroup END 5961 unlet g:BufNum 5962 %bw! 5963 endfunc 5964 5965 " Test for adding an invalid entry with the quickfix window open and making 5966 " sure that the window contents are not changed 5967 func Test_add_invalid_entry_with_qf_window() 5968 call setqflist([], 'f') 5969 cexpr "Xfile1:10:aa" 5970 copen 5971 call setqflist(['bb'], 'a') 5972 call assert_equal(1, line('$')) 5973 call assert_equal(['Xfile1|10| aa'], getline(1, '$')) 5974 call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 5975 5976 call setqflist([{'lnum': 10 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 5977 call assert_equal(1 , line('$')) 5978 call assert_equal(['Xfile1|10| aa'] , getline(1 , '$')) 5979 call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 5980 5981 call setqflist([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 5982 call assert_equal(1 , line('$')) 5983 call assert_equal(['Xfile1|10| aa'] , getline(1 , '$')) 5984 call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 5985 5986 call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 5987 call assert_equal(1 , line('$')) 5988 call assert_equal(['Xfile1|10| aa'] , getline(1 , '$')) 5989 call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 5990 5991 call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 5992 call assert_equal(1 , line('$')) 5993 call assert_equal(['Xfile1|10 col 666| aa'] , getline(1 , '$')) 5994 call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 5995 5996 call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 5997 call assert_equal(1 , line('$')) 5998 call assert_equal(['Xfile1|10 col 666| aa'] , getline(1 , '$')) 5999 call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 6000 6001 call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 6002 call assert_equal(1 , line('$')) 6003 call assert_equal(['Xfile1|10 col 666-222| aa'] , getline(1 , '$')) 6004 call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 6005 6006 call setqflist([{'lnum': 10 , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r') 6007 call assert_equal(1 , line('$')) 6008 call assert_equal(['Xfile1|10-6 col 666-222| aa'] , getline(1 , '$')) 6009 call assert_equal([{'lnum': 10 , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist()) 6010 cclose 6011 endfunc 6012 6013 " Test for very weird problem: autocommand causes a failure, resulting opening 6014 " the quickfix window to fail. This still splits the window, but otherwise 6015 " should not mess up buffers. 6016 func Test_quickfix_window_fails_to_open() 6017 CheckScreendump 6018 6019 let lines =<< trim END 6020 anything 6021 try 6022 anything 6023 endtry 6024 END 6025 call writefile(lines, 'XquickfixFails') 6026 6027 let lines =<< trim END 6028 split XquickfixFails 6029 silent vimgrep anything % 6030 normal o 6031 au BufLeave * ++once source XquickfixFails 6032 " This will trigger the autocommand, which causes an error, what follows 6033 " is aborted but the window was already split. 6034 silent! cwindow 6035 END 6036 call writefile(lines, 'XtestWinFails') 6037 let buf = RunVimInTerminal('-S XtestWinFails', #{rows: 13}) 6038 call VerifyScreenDump(buf, 'Test_quickfix_window_fails', {}) 6039 6040 " clean up 6041 call term_sendkeys(buf, ":bwipe!\<CR>") 6042 call term_wait(buf) 6043 call StopVimInTerminal(buf) 6044 call delete('XtestWinFails') 6045 call delete('XquickfixFails') 6046 endfunc 6047 6048 " Test for updating the quickfix buffer whenever the associated quickfix list 6049 " is changed. 6050 func Xqfbuf_update(cchar) 6051 call s:setup_commands(a:cchar) 6052 6053 Xexpr "F1:1:line1" 6054 Xopen 6055 call assert_equal(['F1|1| line1'], getline(1, '$')) 6056 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 6057 6058 " Test setqflist() using the 'lines' key in 'what' 6059 " add a new entry 6060 call g:Xsetlist([], 'a', {'lines' : ['F2:2: line2']}) 6061 call assert_equal(['F1|1| line1', 'F2|2| line2'], getline(1, '$')) 6062 call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) 6063 " replace all the entries with a single entry 6064 call g:Xsetlist([], 'r', {'lines' : ['F3:3: line3']}) 6065 call assert_equal(['F3|3| line3'], getline(1, '$')) 6066 call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick) 6067 " remove all the entries 6068 call g:Xsetlist([], 'r', {'lines' : []}) 6069 call assert_equal([''], getline(1, '$')) 6070 call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick) 6071 " add a new list 6072 call g:Xsetlist([], ' ', {'lines' : ['F4:4: line4']}) 6073 call assert_equal(['F4|4| line4'], getline(1, '$')) 6074 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 6075 6076 " Test setqflist() using the 'items' key in 'what' 6077 " add a new entry 6078 call g:Xsetlist([], 'a', {'items' : [{'filename' : 'F5', 'lnum' : 5, 'text' : 'line5'}]}) 6079 call assert_equal(['F4|4| line4', 'F5|5| line5'], getline(1, '$')) 6080 call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) 6081 " replace all the entries with a single entry 6082 call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F6', 'lnum' : 6, 'text' : 'line6'}]}) 6083 call assert_equal(['F6|6| line6'], getline(1, '$')) 6084 call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick) 6085 " remove all the entries 6086 call g:Xsetlist([], 'r', {'items' : []}) 6087 call assert_equal([''], getline(1, '$')) 6088 call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick) 6089 " add a new list 6090 call g:Xsetlist([], ' ', {'items' : [{'filename' : 'F7', 'lnum' : 7, 'text' : 'line7'}]}) 6091 call assert_equal(['F7|7| line7'], getline(1, '$')) 6092 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 6093 6094 call g:Xsetlist([], ' ', {}) 6095 call assert_equal([''], getline(1, '$')) 6096 call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) 6097 6098 Xclose 6099 endfunc 6100 6101 func Test_qfbuf_update() 6102 call Xqfbuf_update('c') 6103 call Xqfbuf_update('l') 6104 endfunc 6105 6106 func Test_vimgrep_noswapfile() 6107 set noswapfile 6108 call writefile(['one', 'two', 'three'], 'Xgreppie') 6109 vimgrep two Xgreppie 6110 call assert_equal('two', getline('.')) 6111 6112 call delete('Xgreppie') 6113 set swapfile 6114 endfunc 6115 6116 " Test for the :vimgrep 'f' flag (fuzzy match) 6117 func Xvimgrep_fuzzy_match(cchar) 6118 call s:setup_commands(a:cchar) 6119 6120 Xvimgrep /three one/f Xfile* 6121 let l = g:Xgetlist() 6122 call assert_equal(2, len(l)) 6123 call assert_equal(['Xfile1', 1, 9, 'one two three'], 6124 \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text]) 6125 call assert_equal(['Xfile2', 2, 1, 'three one two'], 6126 \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text]) 6127 6128 Xvimgrep /the/f Xfile* 6129 let l = g:Xgetlist() 6130 call assert_equal(3, len(l)) 6131 call assert_equal(['Xfile1', 1, 9, 'one two three'], 6132 \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text]) 6133 call assert_equal(['Xfile2', 2, 1, 'three one two'], 6134 \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text]) 6135 call assert_equal(['Xfile2', 4, 4, 'aaathreeaaa'], 6136 \ [bufname(l[2].bufnr), l[2].lnum, l[2].col, l[2].text]) 6137 6138 Xvimgrep /aaa/fg Xfile* 6139 let l = g:Xgetlist() 6140 call assert_equal(4, len(l)) 6141 call assert_equal(['Xfile1', 2, 1, 'aaaaaa'], 6142 \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text]) 6143 call assert_equal(['Xfile1', 2, 4, 'aaaaaa'], 6144 \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text]) 6145 call assert_equal(['Xfile2', 4, 1, 'aaathreeaaa'], 6146 \ [bufname(l[2].bufnr), l[2].lnum, l[2].col, l[2].text]) 6147 call assert_equal(['Xfile2', 4, 9, 'aaathreeaaa'], 6148 \ [bufname(l[3].bufnr), l[3].lnum, l[3].col, l[3].text]) 6149 6150 call assert_fails('Xvimgrep /xyz/fg Xfile*', 'E480:') 6151 endfunc 6152 6153 func Test_vimgrep_fuzzy_match() 6154 call writefile(['one two three', 'aaaaaa'], 'Xfile1') 6155 call writefile(['one', 'three one two', 'two', 'aaathreeaaa'], 'Xfile2') 6156 call Xvimgrep_fuzzy_match('c') 6157 call Xvimgrep_fuzzy_match('l') 6158 call delete('Xfile1') 6159 call delete('Xfile2') 6160 endfunc 6161 6162 func Test_locationlist_open_in_newtab() 6163 call s:create_test_file('Xqftestfile1') 6164 call s:create_test_file('Xqftestfile2') 6165 call s:create_test_file('Xqftestfile3') 6166 6167 %bwipe! 6168 6169 let lines =<< trim END 6170 Xqftestfile1:5:Line5 6171 Xqftestfile2:10:Line10 6172 Xqftestfile3:16:Line16 6173 END 6174 lgetexpr lines 6175 6176 silent! llast 6177 call assert_equal(1, tabpagenr('$')) 6178 call assert_equal('Xqftestfile3', bufname()) 6179 6180 set switchbuf=newtab 6181 6182 silent! lfirst 6183 call assert_equal(2, tabpagenr('$')) 6184 call assert_equal('Xqftestfile1', bufname()) 6185 6186 silent! lnext 6187 call assert_equal(3, tabpagenr('$')) 6188 call assert_equal('Xqftestfile2', bufname()) 6189 6190 call delete('Xqftestfile1') 6191 call delete('Xqftestfile2') 6192 call delete('Xqftestfile3') 6193 set switchbuf&vim 6194 6195 %bwipe! 6196 endfunc 6197 6198 " Test for win_gettype() in quickfix and location list windows 6199 func Test_win_gettype() 6200 copen 6201 call assert_equal("quickfix", win_gettype()) 6202 let wid = win_getid() 6203 wincmd p 6204 call assert_equal("quickfix", win_gettype(wid)) 6205 cclose 6206 lexpr '' 6207 lopen 6208 call assert_equal("loclist", win_gettype()) 6209 let wid = win_getid() 6210 wincmd p 6211 call assert_equal("loclist", win_gettype(wid)) 6212 lclose 6213 endfunc 6214 6215 fun Test_vimgrep_nomatch() 6216 call XexprTests('c') 6217 call g:Xsetlist([{'lnum':10,'text':'Line1'}]) 6218 copen 6219 if has("win32") 6220 call assert_fails('vimgrep foo *.zzz', 'E479:') 6221 let expected = [{'lnum': 10, 'bufnr': 0, 'end_lnum': 0, 'pattern': '', 'valid': 0, 'vcol': 0, 'nr': 0, 'module': '', 'type': '', 'end_col': 0, 'col': 0, 'text': 'Line1'}] 6222 else 6223 call assert_fails('vimgrep foo *.zzz', 'E480:') 6224 let expected = [] 6225 endif 6226 call assert_equal(expected, getqflist()) 6227 cclose 6228 endfunc 6229 6230 " Test for opening the quickfix window in two tab pages and then closing one 6231 " of the quickfix windows. This should not make the quickfix buffer unlisted. 6232 " (github issue #9300). 6233 func Test_two_qf_windows() 6234 cexpr "F1:1:line1" 6235 copen 6236 tabnew 6237 copen 6238 call assert_true(&buflisted) 6239 cclose 6240 tabfirst 6241 call assert_true(&buflisted) 6242 let bnum = bufnr() 6243 cclose 6244 " if all the quickfix windows are closed, then buffer should be unlisted. 6245 call assert_false(buflisted(bnum)) 6246 %bw! 6247 6248 " Repeat the test for a location list 6249 lexpr "F2:2:line2" 6250 lopen 6251 let bnum = bufnr() 6252 tabnew 6253 exe "buffer" bnum 6254 tabfirst 6255 lclose 6256 tablast 6257 call assert_true(buflisted(bnum)) 6258 tabclose 6259 lopen 6260 call assert_true(buflisted(bnum)) 6261 lclose 6262 call assert_false(buflisted(bnum)) 6263 %bw! 6264 endfunc 6265 6266 " Weird sequence of commands that caused entering a wiped-out buffer 6267 func Test_lopen_bwipe() 6268 func R() 6269 silent! tab lopen 6270 e x 6271 silent! lfile 6272 endfunc 6273 6274 cal R() 6275 cal R() 6276 cal R() 6277 bw! 6278 delfunc R 6279 endfunc 6280 6281 " Another sequence of commands that caused all buffers to be wiped out 6282 func Test_lopen_bwipe_all() 6283 let lines =<< trim END 6284 func R() 6285 silent! tab lopen 6286 e foo 6287 silent! lfile 6288 endfunc 6289 cal R() 6290 exe "norm \<C-W>\<C-V>0" 6291 cal R() 6292 bwipe 6293 6294 call writefile(['done'], 'Xresult') 6295 qall! 6296 END 6297 call writefile(lines, 'Xscript') 6298 if RunVim([], [], '-u NONE -n -X -Z -e -m -s -S Xscript') 6299 call assert_equal(['done'], readfile('Xresult')) 6300 endif 6301 6302 call delete('Xscript') 6303 call delete('Xresult') 6304 endfunc 6305 6306 " Test for calling setqflist() function recursively 6307 func Test_recursive_setqflist() 6308 augroup QF_Test 6309 au! 6310 autocmd BufWinEnter quickfix call setqflist([], 'r') 6311 augroup END 6312 6313 copen 6314 call assert_fails("call setqflist([], 'a')", 'E952:') 6315 6316 augroup QF_Test 6317 au! 6318 augroup END 6319 %bw! 6320 endfunc 6321 6322 " Test for failure to create a new window when selecting a file from the 6323 " quickfix window 6324 func Test_cwindow_newwin_fails() 6325 cgetexpr ["Xfile1:10:L10", "Xfile1:20:L20"] 6326 cwindow 6327 only 6328 let qf_wid = win_getid() 6329 " create the maximum number of scratch windows 6330 let hor_win_count = (&lines - 1)/2 6331 let hor_split_count = hor_win_count - 1 6332 for s in range(1, hor_split_count) | new | set buftype=nofile | endfor 6333 call win_gotoid(qf_wid) 6334 call assert_fails('exe "normal \<CR>"', 'E36:') 6335 %bw! 6336 endfunc 6337 6338 " Test for updating the location list when only the location list window is 6339 " present and the corresponding file window is closed. 6340 func Test_loclist_update_with_llwin_only() 6341 %bw! 6342 new 6343 wincmd w 6344 lexpr ["Xfile1:1:Line1"] 6345 lopen 6346 wincmd p 6347 close 6348 call setloclist(2, [], 'r', {'lines': ["Xtest2:2:Line2"]}) 6349 call assert_equal(['Xtest2|2| Line2'], getbufline(winbufnr(2), 1, '$')) 6350 %bw! 6351 endfunc 6352 6353 " Test for getting the quickfix list after a buffer with an error is wiped out 6354 func Test_getqflist_wiped_out_buffer() 6355 %bw! 6356 cexpr ["Xtest1:34:Wiped out"] 6357 let bnum = bufnr('Xtest1') 6358 call assert_equal(bnum, getqflist()[0].bufnr) 6359 bw Xtest1 6360 call assert_equal(0, getqflist()[0].bufnr) 6361 %bw! 6362 endfunc 6363 6364 " Test for the status message that is displayed when opening a new quickfix 6365 " list 6366 func Test_qflist_statusmsg() 6367 cexpr "1\n2" 6368 cexpr "1\n2\n3\ntest_quickfix.vim:1:msg" 6369 call assert_equal('(4 of 4): msg', v:statusmsg) 6370 call setqflist([], 'f') 6371 %bw! 6372 6373 " When creating a new quickfix list, if an autocmd changes the quickfix list 6374 " in the stack, then an error message should be displayed. 6375 augroup QF_Test 6376 au! 6377 au BufEnter test_quickfix.vim colder 6378 augroup END 6379 cexpr "1\n2" 6380 call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:') 6381 call setqflist([], 'f') 6382 augroup QF_Test 6383 au! 6384 augroup END 6385 %bw! 6386 6387 augroup QF_Test 6388 au! 6389 au BufEnter test_quickfix.vim caddexpr "4" 6390 augroup END 6391 call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:') 6392 call setqflist([], 'f') 6393 augroup QF_Test 6394 au! 6395 augroup END 6396 %bw! 6397 endfunc 6398 6399 func Test_quickfixtextfunc_recursive() 6400 func s:QFTfunc(o) 6401 cgete '0' 6402 endfunc 6403 copen 6404 let &quickfixtextfunc = 's:QFTfunc' 6405 cex "" 6406 6407 let &quickfixtextfunc = '' 6408 cclose 6409 endfunc 6410 6411 " Test for replacing the location list from an autocmd. This used to cause a 6412 " read from freed memory. 6413 func Test_loclist_replace_autocmd() 6414 %bw! 6415 call setloclist(0, [], 'f') 6416 let s:bufnr = bufnr() 6417 cal setloclist(0, [{'0': 0, '': ''}]) 6418 au BufEnter * cal setloclist(1, [{'t': ''}, {'bufnr': s:bufnr}], 'r') 6419 lopen 6420 try 6421 exe "norm j\<CR>" 6422 catch 6423 endtry 6424 lnext 6425 %bw! 6426 call setloclist(0, [], 'f') 6427 endfunc 6428 6429 " Test for a very long error line and a very long information line 6430 func Test_very_long_error_line() 6431 let msg = repeat('abcdefghijklmn', 146) 6432 let emsg = 'Xlonglines.c:1:' . msg 6433 call writefile([msg, emsg], 'Xerror', 'D') 6434 cfile Xerror 6435 cwindow 6436 call assert_equal($'|| {msg}', getline(1)) 6437 call assert_equal($'Xlonglines.c|1| {msg}', getline(2)) 6438 cclose 6439 6440 let l = execute('clist!')->split("\n") 6441 call assert_equal([$' 1: {msg}', $' 2 Xlonglines.c:1: {msg}'], l) 6442 6443 let l = execute('cc')->split("\n") 6444 call assert_equal([$'(2 of 2): {msg}'], l) 6445 6446 call setqflist([], 'f') 6447 endfunc 6448 6449 " In the quickfix window, spaces at the beginning of an informational line 6450 " should not be removed but should be removed from an error line. 6451 func Test_info_line_with_space() 6452 cexpr ["a.c:20:12: error: expected ';' before ':' token", 6453 \ ' 20 | Afunc():', '', ' | ^'] 6454 copen 6455 call assert_equal(["a.c|20 col 12| error: expected ';' before ':' token", 6456 \ '|| 20 | Afunc():', '|| ', 6457 \ '|| | ^'], getline(1, '$')) 6458 cclose 6459 6460 let l = execute('clist!')->split("\n") 6461 call assert_equal([" 1 a.c:20 col 12: error: expected ';' before ':' token", 6462 \ ' 2: 20 | Afunc():', ' 3: ', ' 4: | ^'], l) 6463 6464 call setqflist([], 'f') 6465 endfunc 6466 6467 func s:QfTf(_) 6468 endfunc 6469 6470 func Test_setqflist_cb_arg() 6471 " This was changing the callback name in the dictionary. 6472 let d = #{quickfixtextfunc: 's:QfTf'} 6473 call setqflist([], 'a', d) 6474 call assert_equal('s:QfTf', d.quickfixtextfunc) 6475 6476 call setqflist([], 'f') 6477 endfunc 6478 6479 " Test that setqflist() should not prevent :stopinsert from working 6480 func Test_setqflist_stopinsert() 6481 new 6482 call setqflist([], 'f') 6483 copen 6484 cclose 6485 func StopInsert() 6486 stopinsert 6487 call setqflist([{'text': 'foo'}]) 6488 return '' 6489 endfunc 6490 6491 call setline(1, 'abc') 6492 call cursor(1, 1) 6493 call feedkeys("i\<C-R>=StopInsert()\<CR>$", 'tnix') 6494 call assert_equal('foo', getqflist()[0].text) 6495 call assert_equal([0, 1, 3, 0, v:maxcol], getcurpos()) 6496 call assert_equal(['abc'], getline(1, '$')) 6497 6498 delfunc StopInsert 6499 call setqflist([], 'f') 6500 bwipe! 6501 endfunc 6502 6503 func Test_quickfix_buffer_contents() 6504 call setqflist([{'filename':'filename', 'pattern':'pattern', 'text':'text'}]) 6505 copen 6506 call assert_equal(['filename|pattern| text'], getline(1, '$')) " The assert failed with Vim v9.0.0736; '| text' did not appear after the pattern. 6507 call setqflist([], 'f') 6508 endfunc 6509 6510 func XquickfixUpdateTests(cchar) 6511 call s:setup_commands(a:cchar) 6512 6513 " Setup: populate a couple buffers 6514 new 6515 call setline(1, range(1, 5)) 6516 let b1 = bufnr() 6517 new 6518 call setline(1, range(1, 3)) 6519 let b2 = bufnr() 6520 " Setup: set a quickfix list. 6521 let items = [{'bufnr': b1, 'lnum': 1}, {'bufnr': b1, 'lnum': 2}, {'bufnr': b2, 'lnum': 1}, {'bufnr': b2, 'lnum': 2}] 6522 call g:Xsetlist(items) 6523 6524 " Open the quickfix list, select the third entry. 6525 Xopen 6526 exe "normal jj\<CR>" 6527 call assert_equal(3, g:Xgetlist({'idx' : 0}).idx) 6528 6529 " Update the quickfix list. Make sure the third entry is still selected. 6530 call g:Xsetlist([], 'u', { 'items': items }) 6531 call assert_equal(3, g:Xgetlist({'idx' : 0}).idx) 6532 6533 " Update the quickfix list again, but this time with missing line number 6534 " information. Confirm that we keep the current buffer selected. 6535 call g:Xsetlist([{'bufnr': b1}, {'bufnr': b2}], 'u') 6536 call assert_equal(2, g:Xgetlist({'idx' : 0}).idx) 6537 6538 Xclose 6539 6540 " Cleanup the buffers we allocated during this test. 6541 %bwipe! 6542 endfunc 6543 6544 " Test for updating a quickfix list using the "u" flag in setqflist() 6545 func Test_quickfix_update() 6546 call XquickfixUpdateTests('c') 6547 call XquickfixUpdateTests('l') 6548 endfunc 6549 6550 func Test_quickfix_update_with_missing_coordinate_info() 6551 new 6552 call setline(1, range(1, 5)) 6553 let b1 = bufnr() 6554 6555 new 6556 call setline(1, range(1, 3)) 6557 let b2 = bufnr() 6558 6559 new 6560 call setline(1, range(1, 2)) 6561 let b3 = bufnr() 6562 6563 " Setup: set a quickfix list with no coordinate information at all. 6564 call setqflist([{}, {}]) 6565 6566 " Open the quickfix list, select the second entry. 6567 copen 6568 exe "normal j\<CR>" 6569 call assert_equal(2, getqflist({'idx' : 0}).idx) 6570 6571 " Update the quickfix list. As the previously selected entry has no 6572 " coordinate information, we expect the first entry to now be selected. 6573 call setqflist([{'bufnr': b1}, {'bufnr': b2}, {'bufnr': b3}], 'u') 6574 call assert_equal(1, getqflist({'idx' : 0}).idx) 6575 6576 " Select the second entry in the quickfix list. 6577 copen 6578 exe "normal j\<CR>" 6579 call assert_equal(2, getqflist({'idx' : 0}).idx) 6580 6581 " Update the quickfix list again. The currently selected entry does not have 6582 " a line number, but we should keep the file selected. 6583 call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 3}, {'bufnr': b3}], 'u') 6584 call assert_equal(2, getqflist({'idx' : 0}).idx) 6585 6586 " Update the quickfix list again. The currently selected entry (bufnr=b2, lnum=3) 6587 " is no longer present. We should pick the nearest entry. 6588 call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 1}, {'bufnr': b2, 'lnum': 4}], 'u') 6589 call assert_equal(3, getqflist({'idx' : 0}).idx) 6590 6591 " Set the quickfix list again, with a specific column number. The currently selected entry doesn't have a 6592 " column number, but they share a line number. 6593 call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 4, 'col': 5}, {'bufnr': b2, 'lnum': 4, 'col': 6}], 'u') 6594 call assert_equal(2, getqflist({'idx' : 0}).idx) 6595 6596 " Set the quickfix list again. The currently selected column number (6) is 6597 " no longer present. We should select the nearest column number. 6598 call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 4, 'col': 2}, {'bufnr': b2, 'lnum': 4, 'col': 4}], 'u') 6599 call assert_equal(3, getqflist({'idx' : 0}).idx) 6600 6601 " Now set the quickfix list, but without columns. We should still pick the 6602 " same line. 6603 call setqflist([{'bufnr': b2, 'lnum': 3}, {'bufnr': b2, 'lnum': 4}, {'bufnr': b2, 'lnum': 4}], 'u') 6604 call assert_equal(2, getqflist({'idx' : 0}).idx) 6605 6606 " Cleanup the buffers we allocated during this test. 6607 %bwipe! 6608 endfunc 6609 6610 " Test for "%b" in "errorformat" 6611 func Test_efm_format_b() 6612 call setqflist([], 'f') 6613 new 6614 call setline(1, ['1: abc', '1: def', '1: ghi']) 6615 let b1 = bufnr() 6616 new 6617 call setline(1, ['2: abc', '2: def', '2: ghi']) 6618 let b2 = bufnr() 6619 new 6620 call setline(1, ['3: abc', '3: def', '3: ghi']) 6621 let b3 = bufnr() 6622 new 6623 let lines =<< trim eval END 6624 {b1}:1:1 6625 {b2}:2:2 6626 {b3}:3:3 6627 END 6628 call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c'}) 6629 cfirst 6630 call assert_equal([b1, 1, 1], [bufnr(), line('.'), col('.')]) 6631 cnext 6632 call assert_equal([b2, 2, 2], [bufnr(), line('.'), col('.')]) 6633 cnext 6634 call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')]) 6635 enew! 6636 6637 " Use a non-existing buffer 6638 let lines =<< trim eval END 6639 9991:1:1:m1 6640 9992:2:2:m2 6641 {b3}:3:3:m3 6642 END 6643 call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c:%m'}) 6644 cfirst | cnext 6645 call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')]) 6646 " Lines with non-existing buffer numbers should be used as non-error lines 6647 call assert_equal([ 6648 \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1, 6649 \ module: '', type: '', end_col: 0, col: 0, text: '9991:1:1:m1'}, 6650 \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1, 6651 \ module: '', type: '', end_col: 0, col: 0, text: '9992:2:2:m2'}, 6652 \ #{lnum: 3, bufnr: b3, end_lnum: 0, pattern: '', valid: 1, vcol: 0, 6653 \ nr: -1, module: '', type: '', end_col: 0, col: 3, text: 'm3'}], 6654 \ getqflist()) 6655 %bw! 6656 call setqflist([], 'f') 6657 endfunc 6658 6659 func XbufferTests_range(cchar) 6660 call s:setup_commands(a:cchar) 6661 6662 enew! 6663 let lines =<< trim END 6664 Xtestfile7:700:10:Line 700 6665 Xtestfile8:800:15:Line 800 6666 END 6667 silent! call setline(1, lines) 6668 norm! Vy 6669 " Note: We cannot use :Xbuffer here, 6670 " it doesn't properly fail, so we need to 6671 " test using the raw c/l commands. 6672 " (also further down) 6673 if (a:cchar == 'c') 6674 exe "'<,'>cbuffer!" 6675 else 6676 exe "'<,'>lbuffer!" 6677 endif 6678 let l = g:Xgetlist() 6679 call assert_true(len(l) == 1 && 6680 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700') 6681 6682 enew! 6683 let lines =<< trim END 6684 Xtestfile9:900:55:Line 900 6685 Xtestfile10:950:66:Line 950 6686 END 6687 silent! call setline(1, lines) 6688 if (a:cchar == 'c') 6689 1cgetbuffer 6690 else 6691 1lgetbuffer 6692 endif 6693 let l = g:Xgetlist() 6694 call assert_true(len(l) == 1 && 6695 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900') 6696 6697 enew! 6698 let lines =<< trim END 6699 Xtestfile11:700:20:Line 700 6700 Xtestfile12:750:25:Line 750 6701 END 6702 silent! call setline(1, lines) 6703 if (a:cchar == 'c') 6704 1,1caddbuffer 6705 else 6706 1,1laddbuffer 6707 endif 6708 let l = g:Xgetlist() 6709 call assert_true(len(l) == 2 && 6710 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && 6711 \ l[1].lnum == 700 && l[1].col == 20 && l[1].text ==# 'Line 700') 6712 enew! 6713 6714 " Check for invalid range 6715 " Using Xbuffer will not run the range check in the cbuffer/lbuffer 6716 " commands. So directly call the commands. 6717 if (a:cchar == 'c') 6718 call assert_fails('900,999caddbuffer', 'E16:') 6719 else 6720 call assert_fails('900,999laddbuffer', 'E16:') 6721 endif 6722 endfunc 6723 6724 func Test_cbuffer_range() 6725 call XbufferTests_range('c') 6726 call XbufferTests_range('l') 6727 endfunc 6728 6729 " Test for displaying fname passed from setqflist() when the names include 6730 " hard links to prevent seemingly duplicate entries. 6731 func Xtest_hardlink_fname(cchar) 6732 call s:setup_commands(a:cchar) 6733 %bwipe 6734 " Create a sample source file 6735 let lines =<< trim END 6736 void sample() {} 6737 int main() { sample(); return 0; } 6738 END 6739 call writefile(lines, 'test_qf_hardlink1.c', 'D') 6740 defer delete('test_qf_hardlink1.c') 6741 defer delete('test_qf_hardlink2.c') 6742 call system('ln test_qf_hardlink1.c test_qf_hardlink2.c') 6743 if v:shell_error 6744 throw 'Skipped: ln throws error on this platform' 6745 endif 6746 call g:Xsetlist([], 'f') 6747 " Make a qflist that contains the file and it's hard link 6748 " like how LSP plugins set response into qflist 6749 call g:Xsetlist([{'filename' : 'test_qf_hardlink1.c', 'lnum' : 1}, 6750 \ {'filename' : 'test_qf_hardlink2.c', 'lnum' : 1}], ' ') 6751 Xopen 6752 " Ensure that two entries are displayed with different name 6753 " so that they aren't seen as duplication. 6754 call assert_equal(['test_qf_hardlink1.c|1| ', 6755 \ 'test_qf_hardlink2.c|1| '], getline(1, '$')) 6756 Xclose 6757 endfunc 6758 6759 func Test_hardlink_fname() 6760 CheckUnix 6761 CheckExecutable ln 6762 call Xtest_hardlink_fname('c') 6763 call Xtest_hardlink_fname('l') 6764 endfunc 6765 6766 " Test for checking if correct number of tests are deleted 6767 " and current list stays the same after setting Xhistory 6768 " to a smaller number. Do roughly the same for growing the stack. 6769 func Xtest_resize_list_stack(cchar) 6770 call s:setup_commands(a:cchar) 6771 Xsethist 100 6772 6773 for i in range(1, 100) 6774 Xexpr string(i) 6775 endfor 6776 Xopen 6777 call assert_equal(g:Xgetlist({'nr': '$'}).nr, 100) 6778 call assert_equal("|| 100", getline(1)) 6779 Xsethist 8 6780 call assert_equal("|| 100", getline(1)) 6781 Xolder 5 6782 call assert_equal("|| 95", getline(1)) 6783 Xsethist 6 6784 call assert_equal("|| 95", getline(1)) 6785 Xsethist 1 6786 call assert_equal("|| 100", getline(1)) 6787 6788 " grow array again 6789 Xsethist 100 6790 for i in range(1, 99) 6791 Xexpr string(i) 6792 endfor 6793 call assert_equal("|| 99", getline(1)) 6794 Xolder 99 6795 call assert_equal("|| 100", getline(1)) 6796 6797 Xsethistdefault 6798 endfunc 6799 6800 func Test_resize_list_stack() 6801 call Xtest_resize_list_stack('c') 6802 call Xtest_resize_list_stack('l') 6803 endfunc 6804 6805 " Test to check if order of lists is from 6806 " oldest at the bottom to newest at the top 6807 func Xtest_Xhistory_check_order(cchar) 6808 6809 Xsethist 100 6810 6811 for i in range(1, 100) 6812 Xexpr string(i) 6813 endfor 6814 6815 Xopen 6816 for i in range(100, 1, -1) 6817 let l:ret = assert_equal("|| " .. i, getline(1)) 6818 6819 if ret == 1 || i == 1 6820 break 6821 endif 6822 Xolder 6823 endfor 6824 6825 for i in range(1, 50) 6826 Xexpr string(i) 6827 endfor 6828 6829 for i in range(50, 1, -1) 6830 let l:ret = assert_equal("|| " .. i, getline(1)) 6831 6832 if ret == 1 || i == 50 6833 break 6834 endif 6835 Xolder 6836 endfor 6837 6838 for i in range(50, 1, -1) 6839 let l:ret = assert_equal("|| " .. i, getline(1)) 6840 6841 if ret == 1 || i == 50 6842 break 6843 endif 6844 Xolder 6845 endfor 6846 6847 Xsethistdefault 6848 endfunc 6849 6850 func Test_set_history_to_check_order() 6851 call Xtest_Xhistory_check_order('c') 6852 call Xtest_Xhistory_check_order('l') 6853 endfunc 6854 6855 " Check if 'lhistory' is the same between the location list window 6856 " and associated normal window 6857 func Test_win_and_loc_synced() 6858 new 6859 set lhistory=2 6860 lexpr "Text" 6861 lopen 6862 6863 " check if lhistory is synced when modified inside the 6864 " location list window 6865 setlocal lhistory=1 6866 wincmd k 6867 call assert_equal(&lhistory, 1) 6868 6869 " check if lhistory is synced when modified inside the 6870 " normal window 6871 setlocal lhistory=10 6872 lopen 6873 call assert_equal(&lhistory, 10) 6874 6875 wincmd k 6876 lclose 6877 wincmd q 6878 6879 set lhistory& 6880 endfunc 6881 6882 " Test if setting the lhistory of one window doesn't affect the other 6883 func Test_two_win_are_independent_of_history() 6884 setlocal lhistory=10 6885 new 6886 setlocal lhistory=20 6887 wincmd w 6888 call assert_equal(&lhistory, 10) 6889 wincmd w 6890 wincmd q 6891 6892 set lhistory& 6893 endfunc 6894 6895 " Test if lhistory is copied over to a new window 6896 func Test_lhistory_copied_over() 6897 setlocal lhistory=3 6898 split 6899 call assert_equal(&lhistory, 3) 6900 wincmd q 6901 6902 set lhistory& 6903 endfunc 6904 6905 " Test if error occurs when given invalid history number 6906 func Xtest_invalid_history_num(cchar) 6907 call s:setup_commands(a:cchar) 6908 6909 call assert_fails('Xsethist -10000', "E1542:") 6910 call assert_fails('Xsethist 10000', "E1543:") 6911 Xsethistdefault 6912 endfunc 6913 6914 func Test_invalid_history_num() 6915 call Xtest_invalid_history_num('c') 6916 call Xtest_invalid_history_num('l') 6917 endfunc 6918 6919 " Test if chistory and lhistory don't affect each other 6920 func Test_chi_and_lhi_are_independent() 6921 set chistory=100 6922 set lhistory=100 6923 6924 set chistory=10 6925 call assert_equal(&lhistory, 100) 6926 6927 set lhistory=1 6928 call assert_equal(&chistory, 10) 6929 6930 set chistory& 6931 set lhistory& 6932 endfunc 6933 6934 func Test_quickfix_close_buffer_crash() 6935 new 6936 lexpr 'test' | lopen 6937 wincmd k 6938 lclose 6939 wincmd q 6940 endfunc 6941 6942 func Test_vimgrep_dummy_buffer_crash() 6943 augroup DummyCrash 6944 autocmd! 6945 " Make the dummy buffer non-current, but still open in a window. 6946 autocmd BufReadCmd * ++once let s:dummy_buf = bufnr() 6947 \| split | wincmd p | enew 6948 6949 " Autocmds from cleaning up the dummy buffer in this case should be blocked. 6950 autocmd BufWipeout * 6951 \ call assert_notequal(s:dummy_buf, str2nr(expand('<abuf>'))) 6952 augroup END 6953 6954 silent! vimgrep /./ . 6955 redraw! " Window to freed dummy buffer used to remain; heap UAF. 6956 call assert_equal([], win_findbuf(s:dummy_buf)) 6957 call assert_equal(0, bufexists(s:dummy_buf)) 6958 6959 unlet! s:dummy_buf 6960 autocmd! DummyCrash 6961 %bw! 6962 endfunc 6963 6964 func Test_vimgrep_dummy_buffer_keep() 6965 augroup DummyKeep 6966 autocmd! 6967 " Trigger a wipe of the dummy buffer by aborting script processing. Prevent 6968 " wiping it by splitting it from the autocmd window into an only window. 6969 autocmd BufReadCmd * ++once let s:dummy_buf = bufnr() 6970 \| tab split | call interrupt() 6971 augroup END 6972 6973 call assert_fails('vimgrep /./ .') 6974 call assert_equal(1, bufexists(s:dummy_buf)) 6975 " Ensure it's no longer considered a dummy; should be able to switch to it. 6976 execute s:dummy_buf 'sbuffer' 6977 6978 unlet! s:dummy_buf 6979 autocmd! DummyKeep 6980 %bw! 6981 endfunc 6982 6983 func Test_quickfix_restore_current_win() 6984 let curwin = win_getid() 6985 vsplit Xb 6986 wincmd p 6987 botright copen 6988 cclose 6989 6990 call assert_equal(curwin, win_getid()) 6991 bw! Xb 6992 endfunc 6993 6994 func Test_quickfixtextfunc_wipes_buffer() 6995 let g:crash="" 6996 new 6997 fu QFexpr(dummy) 6998 bw 6999 endfu 7000 try 7001 set quickfixtextfunc=QFexpr 7002 lad "['0:4:e']" 7003 lw 7004 catch /^Vim\%((\S\+)\)\=:E565:/ 7005 let g:crash='caught' 7006 endtry 7007 " close location list window 7008 bw 7009 delfunc QFexpr 7010 set quickfixtextfunc= 7011 call assert_equal('caught', g:crash) 7012 unlet g:crash 7013 " close the newly opened window 7014 bw 7015 endfunc 7016 7017 " vim: shiftwidth=2 sts=2 expandtab