xref: /vim-8.2.3635/src/testdir/test_tagjump.vim (revision ed37d9b3)
1" Tests for tagjump (tags and special searches)
2
3source check.vim
4source screendump.vim
5
6" SEGV occurs in older versions.  (At least 7.4.1748 or older)
7func Test_ptag_with_notagstack()
8  CheckFeature quickfix
9
10  set notagstack
11  call assert_fails('ptag does_not_exist_tag_name', 'E426')
12  set tagstack&vim
13endfunc
14
15func Test_cancel_ptjump()
16  CheckFeature quickfix
17
18  set tags=Xtags
19  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
20        \ "word\tfile1\tcmd1",
21        \ "word\tfile2\tcmd2"],
22        \ 'Xtags')
23
24  only!
25  call feedkeys(":ptjump word\<CR>\<CR>", "xt")
26  help
27  call assert_equal(2, winnr('$'))
28
29  call delete('Xtags')
30  set tags&
31  quit
32endfunc
33
34func Test_static_tagjump()
35  set tags=Xtags
36  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
37        \ "one\tXfile1\t/^one/;\"\tf\tfile:\tsignature:(void)",
38        \ "word\tXfile2\tcmd2"],
39        \ 'Xtags')
40  new Xfile1
41  call setline(1, ['empty', 'one()', 'empty'])
42  write
43  tag one
44  call assert_equal(2, line('.'))
45
46  bwipe!
47  set tags&
48  call delete('Xtags')
49  call delete('Xfile1')
50endfunc
51
52func Test_duplicate_tagjump()
53  set tags=Xtags
54  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
55        \ "thesame\tXfile1\t1;\"\td\tfile:",
56        \ "thesame\tXfile1\t2;\"\td\tfile:",
57        \ "thesame\tXfile1\t3;\"\td\tfile:",
58        \ ],
59        \ 'Xtags')
60  new Xfile1
61  call setline(1, ['thesame one', 'thesame two', 'thesame three'])
62  write
63  tag thesame
64  call assert_equal(1, line('.'))
65  tnext
66  call assert_equal(2, line('.'))
67  tnext
68  call assert_equal(3, line('.'))
69
70  bwipe!
71  set tags&
72  call delete('Xtags')
73  call delete('Xfile1')
74endfunc
75
76func Test_tagjump_switchbuf()
77  CheckFeature quickfix
78
79  set tags=Xtags
80  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
81        \ "second\tXfile1\t2",
82        \ "third\tXfile1\t3",],
83        \ 'Xtags')
84  call writefile(['first', 'second', 'third'], 'Xfile1')
85
86  enew | only
87  set switchbuf=
88  stag second
89  call assert_equal(2, winnr('$'))
90  call assert_equal(2, line('.'))
91  stag third
92  call assert_equal(3, winnr('$'))
93  call assert_equal(3, line('.'))
94
95  enew | only
96  set switchbuf=useopen
97  stag second
98  call assert_equal(2, winnr('$'))
99  call assert_equal(2, line('.'))
100  stag third
101  call assert_equal(2, winnr('$'))
102  call assert_equal(3, line('.'))
103
104  enew | only
105  set switchbuf=usetab
106  tab stag second
107  call assert_equal(2, tabpagenr('$'))
108  call assert_equal(2, line('.'))
109  1tabnext | stag third
110  call assert_equal(2, tabpagenr('$'))
111  call assert_equal(3, line('.'))
112
113  tabclose!
114  enew | only
115  call delete('Xfile1')
116  call delete('Xtags')
117  set tags&
118  set switchbuf&vim
119endfunc
120
121" Tests for [ CTRL-I and CTRL-W CTRL-I commands
122function Test_keyword_jump()
123  call writefile(["#include Xinclude", "",
124	      \ "",
125	      \ "/* test text test tex start here",
126	      \ "		some text",
127	      \ "		test text",
128	      \ "		start OK if found this line",
129	      \ "	start found wrong line",
130	      \ "test text"], 'Xtestfile')
131  call writefile(["/* test text test tex start here",
132	      \ "		some text",
133	      \ "		test text",
134	      \ "		start OK if found this line",
135	      \ "	start found wrong line",
136	      \ "test text"], 'Xinclude')
137  new Xtestfile
138  call cursor(1,1)
139  call search("start")
140  exe "normal! 5[\<C-I>"
141  call assert_equal("		start OK if found this line", getline('.'))
142  call cursor(1,1)
143  call search("start")
144  exe "normal! 5\<C-W>\<C-I>"
145  call assert_equal("		start OK if found this line", getline('.'))
146  enew! | only
147  call delete('Xtestfile')
148  call delete('Xinclude')
149endfunction
150
151" Test for jumping to a tag with 'hidden' set, with symbolic link in path of
152" tag.  This only works for Unix, because of the symbolic link.
153func Test_tag_symbolic()
154  if !has('unix')
155    return
156  endif
157  set hidden
158  call delete("Xtest.dir", "rf")
159  call system("ln -s . Xtest.dir")
160  " Create a tags file with the current directory name inserted.
161  call writefile([
162        \ "SECTION_OFF	" . getcwd() . "/Xtest.dir/Xtest.c	/^#define  SECTION_OFF  3$/",
163        \ '',
164        \ ], 'Xtags')
165  call writefile(['#define  SECTION_OFF  3',
166        \ '#define  NUM_SECTIONS 3'], 'Xtest.c')
167
168  " Try jumping to a tag, but with a path that contains a symbolic link.  When
169  " wrong, this will give the ATTENTION message.  The next space will then be
170  " eaten by hit-return, instead of moving the cursor to 'd'.
171  set tags=Xtags
172  enew!
173  call append(0, 'SECTION_OFF')
174  call cursor(1,1)
175  exe "normal \<C-]> "
176  call assert_equal('Xtest.c', expand('%:t'))
177  call assert_equal(2, col('.'))
178
179  set hidden&
180  set tags&
181  enew!
182  call delete('Xtags')
183  call delete('Xtest.c')
184  call delete("Xtest.dir", "rf")
185  %bwipe!
186endfunc
187
188" Tests for tag search with !_TAG_FILE_ENCODING.
189" Depends on the test83-tags2 and test83-tags3 files.
190func Test_tag_file_encoding()
191  if has('vms')
192    return
193  endif
194
195  if !has('iconv') || iconv("\x82\x60", "cp932", "utf-8") != "\uff21"
196    return
197  endif
198
199  let save_enc = &encoding
200  set encoding=utf8
201
202  let content = ['text for tags1', 'abcdefghijklmnopqrs']
203  call writefile(content, 'Xtags1.txt')
204  let content = ['text for tags2', 'ABC']
205  call writefile(content, 'Xtags2.txt')
206  let content = ['text for tags3', 'ABC']
207  call writefile(content, 'Xtags3.txt')
208  let content = ['!_TAG_FILE_ENCODING	utf-8	//', 'abcdefghijklmnopqrs	Xtags1.txt	/abcdefghijklmnopqrs']
209  call writefile(content, 'Xtags1')
210
211  " case1:
212  new
213  set tags=Xtags1
214  tag abcdefghijklmnopqrs
215  call assert_equal('Xtags1.txt', expand('%:t'))
216  call assert_equal('abcdefghijklmnopqrs', getline('.'))
217  close
218
219  " case2:
220  new
221  set tags=test83-tags2
222  tag /.BC
223  call assert_equal('Xtags2.txt', expand('%:t'))
224  call assert_equal('ABC', getline('.'))
225  close
226
227  " case3:
228  new
229  set tags=test83-tags3
230  tag abc50
231  call assert_equal('Xtags3.txt', expand('%:t'))
232  call assert_equal('ABC', getline('.'))
233  close
234
235  set tags&
236  let &encoding = save_enc
237  call delete('Xtags1.txt')
238  call delete('Xtags2.txt')
239  call delete('Xtags3.txt')
240  call delete('Xtags1')
241endfunc
242
243func Test_tagjump_etags()
244  if !has('emacs_tags')
245    return
246  endif
247  call writefile([
248        \ "void foo() {}",
249        \ "int main(int argc, char **argv)",
250        \ "{",
251        \ "\tfoo();",
252        \ "\treturn 0;",
253        \ "}",
254        \ ], 'Xmain.c')
255
256  call writefile([
257	\ "\x0c",
258        \ "Xmain.c,64",
259        \ "void foo() {}\x7ffoo\x011,0",
260        \ "int main(int argc, char **argv)\x7fmain\x012,14",
261	\ ], 'Xtags')
262  set tags=Xtags
263  ta foo
264  call assert_equal('void foo() {}', getline('.'))
265
266  call delete('Xtags')
267  call delete('Xmain.c')
268  bwipe!
269endfunc
270
271" Test for getting and modifying the tag stack
272func Test_getsettagstack()
273  call writefile(['line1', 'line2', 'line3'], 'Xfile1')
274  call writefile(['line1', 'line2', 'line3'], 'Xfile2')
275  call writefile(['line1', 'line2', 'line3'], 'Xfile3')
276
277  enew | only
278  call settagstack(1, {'items' : []})
279  call assert_equal(0, gettagstack(1).length)
280  call assert_equal([], 1->gettagstack().items)
281  " Error cases
282  call assert_equal({}, gettagstack(100))
283  call assert_equal(-1, settagstack(100, {'items' : []}))
284  call assert_fails('call settagstack(1, [1, 10])', 'E715')
285  call assert_fails("call settagstack(1, {'items' : 10})", 'E714')
286  call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E928')
287  call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962')
288  call assert_equal(-1, settagstack(0, test_null_dict()))
289
290  set tags=Xtags
291  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
292        \ "one\tXfile1\t1",
293        \ "three\tXfile3\t3",
294        \ "two\tXfile2\t2"],
295        \ 'Xtags')
296
297  let stk = []
298  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'one',
299	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
300  tag one
301  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'two',
302	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
303  tag two
304  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'three',
305	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
306  tag three
307  call assert_equal(3, gettagstack(1).length)
308  call assert_equal(stk, gettagstack(1).items)
309  " Check for default - current window
310  call assert_equal(3, gettagstack().length)
311  call assert_equal(stk, gettagstack().items)
312
313  " Try to set current index to invalid values
314  call settagstack(1, {'curidx' : -1})
315  call assert_equal(1, gettagstack().curidx)
316  eval {'curidx' : 50}->settagstack(1)
317  call assert_equal(4, gettagstack().curidx)
318
319  " Try pushing invalid items onto the stack
320  call settagstack(1, {'items' : []})
321  call settagstack(1, {'items' : ["plate"]}, 'a')
322  call assert_equal(0, gettagstack().length)
323  call assert_equal([], gettagstack().items)
324  call settagstack(1, {'items' : [{"tagname" : "abc"}]}, 'a')
325  call assert_equal(0, gettagstack().length)
326  call assert_equal([], gettagstack().items)
327  call settagstack(1, {'items' : [{"from" : 100}]}, 'a')
328  call assert_equal(0, gettagstack().length)
329  call assert_equal([], gettagstack().items)
330  call settagstack(1, {'items' : [{"from" : [2, 1, 0, 0]}]}, 'a')
331  call assert_equal(0, gettagstack().length)
332  call assert_equal([], gettagstack().items)
333
334  " Push one item at a time to the stack
335  call settagstack(1, {'items' : []})
336  call settagstack(1, {'items' : [stk[0]]}, 'a')
337  call settagstack(1, {'items' : [stk[1]]}, 'a')
338  call settagstack(1, {'items' : [stk[2]]}, 'a')
339  call settagstack(1, {'curidx' : 4})
340  call assert_equal({'length' : 3, 'curidx' : 4, 'items' : stk},
341        \ gettagstack(1))
342
343  " Try pushing items onto a full stack
344  for i in range(7)
345    call settagstack(1, {'items' : stk}, 'a')
346  endfor
347  call assert_equal(20, gettagstack().length)
348  call settagstack(1,
349        \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 'a')
350  call assert_equal('abc', gettagstack().items[19].tagname)
351
352  " truncate the tag stack
353  call settagstack(1,
354        \ {'curidx' : 9,
355        \  'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
356  let t = gettagstack()
357  call assert_equal(9, t.length)
358  call assert_equal(10, t.curidx)
359
360  " truncate the tag stack without pushing any new items
361  call settagstack(1, {'curidx' : 5}, 't')
362  let t = gettagstack()
363  call assert_equal(4, t.length)
364  call assert_equal(5, t.curidx)
365
366  " truncate an empty tag stack and push new items
367  call settagstack(1, {'items' : []})
368  call settagstack(1,
369        \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
370  let t = gettagstack()
371  call assert_equal(1, t.length)
372  call assert_equal(2, t.curidx)
373
374  " Tag with multiple matches
375  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
376        \ "two\tXfile1\t1",
377        \ "two\tXfile2\t3",
378        \ "two\tXfile3\t2"],
379        \ 'Xtags')
380  call settagstack(1, {'items' : []})
381  tag two
382  tnext
383  tnext
384  call assert_equal(1, gettagstack().length)
385  call assert_equal(3, gettagstack().items[0].matchnr)
386
387  " Memory allocation failures
388  call test_alloc_fail(GetAllocId('tagstack_items'), 0, 0)
389  call assert_fails('call gettagstack()', 'E342:')
390  call test_alloc_fail(GetAllocId('tagstack_from'), 0, 0)
391  call assert_fails('call gettagstack()', 'E342:')
392  call test_alloc_fail(GetAllocId('tagstack_details'), 0, 0)
393  call assert_fails('call gettagstack()', 'E342:')
394
395  call settagstack(1, {'items' : []})
396  call delete('Xfile1')
397  call delete('Xfile2')
398  call delete('Xfile3')
399  call delete('Xtags')
400  set tags&
401endfunc
402
403func Test_tag_with_count()
404  call writefile([
405	\ 'test	Xtest.h	/^void test();$/;"	p	typeref:typename:void	signature:()',
406	\ ], 'Xtags')
407  call writefile([
408	\ 'main	Xtest.c	/^int main()$/;"	f	typeref:typename:int	signature:()',
409	\ 'test	Xtest.c	/^void test()$/;"	f	typeref:typename:void	signature:()',
410	\ ], 'Ytags')
411  cal writefile([
412	\ 'int main()',
413	\ 'void test()',
414	\ ], 'Xtest.c')
415  cal writefile([
416	\ 'void test();',
417	\ ], 'Xtest.h')
418  set tags=Xtags,Ytags
419
420  new Xtest.c
421  let tl = taglist('test', 'Xtest.c')
422  call assert_equal(tl[0].filename, 'Xtest.c')
423  call assert_equal(tl[1].filename, 'Xtest.h')
424
425  tag test
426  call assert_equal(bufname('%'), 'Xtest.c')
427  1tag test
428  call assert_equal(bufname('%'), 'Xtest.c')
429  2tag test
430  call assert_equal(bufname('%'), 'Xtest.h')
431
432  set tags&
433  call delete('Xtags')
434  call delete('Ytags')
435  bwipe Xtest.h
436  bwipe Xtest.c
437  call delete('Xtest.h')
438  call delete('Xtest.c')
439endfunc
440
441func Test_tagnr_recall()
442  call writefile([
443	\ 'test	Xtest.h	/^void test();$/;"	p',
444	\ 'main	Xtest.c	/^int main()$/;"	f',
445	\ 'test	Xtest.c	/^void test()$/;"	f',
446	\ ], 'Xtags')
447  cal writefile([
448	\ 'int main()',
449	\ 'void test()',
450	\ ], 'Xtest.c')
451  cal writefile([
452	\ 'void test();',
453	\ ], 'Xtest.h')
454  set tags=Xtags
455
456  new Xtest.c
457  let tl = taglist('test', 'Xtest.c')
458  call assert_equal(tl[0].filename, 'Xtest.c')
459  call assert_equal(tl[1].filename, 'Xtest.h')
460
461  2tag test
462  call assert_equal(bufname('%'), 'Xtest.h')
463  pop
464  call assert_equal(bufname('%'), 'Xtest.c')
465  tag
466  call assert_equal(bufname('%'), 'Xtest.h')
467
468  set tags&
469  call delete('Xtags')
470  bwipe Xtest.h
471  bwipe Xtest.c
472  call delete('Xtest.h')
473  call delete('Xtest.c')
474endfunc
475
476func Test_tag_line_toolong()
477  call writefile([
478	\ '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678	django/contrib/admin/templates/admin/edit_inline/stacked.html	16;"	j	line:16	language:HTML'
479	\ ], 'Xtags')
480  set tags=Xtags
481  let old_vbs = &verbose
482  set verbose=5
483  " ":tjump" should give "tag not found" not "Format error in tags file"
484  call assert_fails('tj /foo', 'E426')
485  try
486    tj /foo
487  catch /^Vim\%((\a\+)\)\=:E431/
488    call assert_report(v:exception)
489  catch /.*/
490  endtry
491  call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1])
492
493  call writefile([
494	\ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567	django/contrib/admin/templates/admin/edit_inline/stacked.html	16;"	j	line:16	language:HTML'
495	\ ], 'Xtags')
496  call assert_fails('tj /foo', 'E426')
497  try
498    tj /foo
499  catch /^Vim\%((\a\+)\)\=:E431/
500    call assert_report(v:exception)
501  catch /.*/
502  endtry
503  call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1])
504
505  " binary search works in file with long line
506  call writefile([
507        \ 'asdfasfd	nowhere	16',
508	\ 'foobar	Xsomewhere	3; " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567',
509        \ 'zasdfasfd	nowhere	16',
510	\ ], 'Xtags')
511  call writefile([
512        \ 'one',
513        \ 'two',
514        \ 'trhee',
515        \ 'four',
516        \ ], 'Xsomewhere')
517  tag foobar
518  call assert_equal('Xsomewhere', expand('%'))
519  call assert_equal(3, getcurpos()[1])
520
521  call delete('Xtags')
522  call delete('Xsomewhere')
523  set tags&
524  let &verbose = old_vbs
525endfunc
526
527" Check that using :tselect does not run into the hit-enter prompt.
528" Requires a terminal to trigger that prompt.
529func Test_tselect()
530  CheckScreendump
531
532  call writefile([
533	\ 'main	Xtest.h	/^void test();$/;"	f',
534	\ 'main	Xtest.c	/^int main()$/;"	f',
535	\ 'main	Xtest.x	/^void test()$/;"	f',
536	\ ], 'Xtags')
537  cal writefile([
538	\ 'int main()',
539	\ 'void test()',
540	\ ], 'Xtest.c')
541
542  let lines =<< trim [SCRIPT]
543    set tags=Xtags
544  [SCRIPT]
545  call writefile(lines, 'XTest_tselect')
546  let buf = RunVimInTerminal('-S XTest_tselect', {'rows': 10, 'cols': 50})
547
548  call TermWait(buf, 50)
549  call term_sendkeys(buf, ":tselect main\<CR>2\<CR>")
550  call VerifyScreenDump(buf, 'Test_tselect_1', {})
551
552  call StopVimInTerminal(buf)
553  call delete('Xtags')
554  call delete('Xtest.c')
555  call delete('XTest_tselect')
556endfunc
557
558func Test_tagline()
559  call writefile([
560	\ 'provision	Xtest.py	/^    def provision(self, **kwargs):$/;"	m	line:1	language:Python class:Foo',
561	\ 'provision	Xtest.py	/^    def provision(self, **kwargs):$/;"	m	line:3	language:Python class:Bar',
562	\], 'Xtags')
563  call writefile([
564	\ '    def provision(self, **kwargs):',
565	\ '        pass',
566	\ '    def provision(self, **kwargs):',
567	\ '        pass',
568	\], 'Xtest.py')
569
570  set tags=Xtags
571
572  1tag provision
573  call assert_equal(line('.'), 1)
574  2tag provision
575  call assert_equal(line('.'), 3)
576
577  call delete('Xtags')
578  call delete('Xtest.py')
579  set tags&
580endfunc
581
582" Test for expanding environment variable in a tag file name
583func Test_tag_envvar()
584  call writefile(["Func1\t$FOO\t/^Func1/"], 'Xtags')
585  set tags=Xtags
586
587  let $FOO='TagTestEnv'
588
589  let caught_exception = v:false
590  try
591    tag Func1
592  catch /E429:/
593    call assert_match('E429:.*"TagTestEnv".*', v:exception)
594    let caught_exception = v:true
595  endtry
596  call assert_true(caught_exception)
597
598  set tags&
599  call delete('Xtags')
600  unlet $FOO
601endfunc
602
603" Test for :ptag
604func Test_tag_preview()
605  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
606        \ "second\tXfile1\t2",
607        \ "third\tXfile1\t3",],
608        \ 'Xtags')
609  set tags=Xtags
610  call writefile(['first', 'second', 'third'], 'Xfile1')
611
612  enew | only
613  ptag third
614  call assert_equal(2, winnr())
615  call assert_equal(2, winnr('$'))
616  call assert_equal(1, getwinvar(1, '&previewwindow'))
617  call assert_equal(0, getwinvar(2, '&previewwindow'))
618  wincmd P
619  call assert_equal(3, line('.'))
620
621  " jump to the tag again
622  wincmd w
623  ptag third
624  wincmd P
625  call assert_equal(3, line('.'))
626
627  " jump to the newer tag
628  wincmd w
629  ptag
630  wincmd P
631  call assert_equal(3, line('.'))
632
633  " close the preview window
634  pclose
635  call assert_equal(1, winnr('$'))
636
637  call delete('Xfile1')
638  call delete('Xtags')
639  set tags&
640endfunc
641
642" Tests for guessing the tag location
643func Test_tag_guess()
644  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
645        \ "func1\tXfoo\t/^int func1(int x)/",
646        \ "func2\tXfoo\t/^int func2(int y)/",
647        \ "func3\tXfoo\t/^func3/",
648        \ "func4\tXfoo\t/^func4/"],
649        \ 'Xtags')
650  set tags=Xtags
651  let code =<< trim [CODE]
652
653    int FUNC1  (int x) { }
654    int
655    func2   (int y) { }
656    int * func3 () { }
657
658  [CODE]
659  call writefile(code, 'Xfoo')
660
661  let v:statusmsg = ''
662  ta func1
663  call assert_match('E435:', v:statusmsg)
664  call assert_equal(2, line('.'))
665  let v:statusmsg = ''
666  ta func2
667  call assert_match('E435:', v:statusmsg)
668  call assert_equal(4, line('.'))
669  let v:statusmsg = ''
670  ta func3
671  call assert_match('E435:', v:statusmsg)
672  call assert_equal(5, line('.'))
673  call assert_fails('ta func4', 'E434:')
674
675  call delete('Xtags')
676  call delete('Xfoo')
677  set tags&
678endfunc
679
680" Test for an unsorted tags file
681func Test_tag_sort()
682  call writefile([
683        \ "first\tXfoo\t1",
684        \ "ten\tXfoo\t3",
685        \ "six\tXfoo\t2"],
686        \ 'Xtags')
687  set tags=Xtags
688  let code =<< trim [CODE]
689    int first() {}
690    int six() {}
691    int ten() {}
692  [CODE]
693  call writefile(code, 'Xfoo')
694
695  call assert_fails('tag first', 'E432:')
696
697  call delete('Xtags')
698  call delete('Xfoo')
699  set tags&
700  %bwipe
701endfunc
702
703" Test for an unsorted tags file
704func Test_tag_fold()
705  call writefile([
706        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
707        \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/",
708        \ "first\tXfoo\t1",
709        \ "second\tXfoo\t2",
710        \ "third\tXfoo\t3"],
711        \ 'Xtags')
712  set tags=Xtags
713  let code =<< trim [CODE]
714    int first() {}
715    int second() {}
716    int third() {}
717  [CODE]
718  call writefile(code, 'Xfoo')
719
720  enew
721  tag second
722  call assert_equal('Xfoo', bufname(''))
723  call assert_equal(2, line('.'))
724
725  call delete('Xtags')
726  call delete('Xfoo')
727  set tags&
728  %bwipe
729endfunc
730
731" Test for the :ltag command
732func Test_ltag()
733  call writefile([
734        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
735        \ "first\tXfoo\t1",
736        \ "second\tXfoo\t/^int second() {}$/",
737        \ "third\tXfoo\t3"],
738        \ 'Xtags')
739  set tags=Xtags
740  let code =<< trim [CODE]
741    int first() {}
742    int second() {}
743    int third() {}
744  [CODE]
745  call writefile(code, 'Xfoo')
746
747  enew
748  call setloclist(0, [], 'f')
749  ltag third
750  call assert_equal('Xfoo', bufname(''))
751  call assert_equal(3, line('.'))
752  call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0,
753        \ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '',
754        \ 'module': '', 'text': 'third'}], getloclist(0))
755
756  ltag second
757  call assert_equal(2, line('.'))
758  call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0,
759        \ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0,
760        \ 'type': '', 'module': '', 'text': 'second'}], getloclist(0))
761
762  call delete('Xtags')
763  call delete('Xfoo')
764  set tags&
765  %bwipe
766endfunc
767
768" Test for setting the last search pattern to the tag search pattern
769" when cpoptions has 't'
770func Test_tag_last_search_pat()
771  call writefile([
772        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
773        \ "first\tXfoo\t/^int first() {}/",
774        \ "second\tXfoo\t/^int second() {}/",
775        \ "third\tXfoo\t/^int third() {}/"],
776        \ 'Xtags')
777  set tags=Xtags
778  let code =<< trim [CODE]
779    int first() {}
780    int second() {}
781    int third() {}
782  [CODE]
783  call writefile(code, 'Xfoo')
784
785  enew
786  let save_cpo = &cpo
787  set cpo+=t
788  let @/ = ''
789  tag second
790  call assert_equal('^int second() {}', @/)
791  let &cpo = save_cpo
792
793  call delete('Xtags')
794  call delete('Xfoo')
795  set tags&
796  %bwipe
797endfunc
798
799" Tag stack tests
800func Test_tag_stack()
801  let l = []
802  for i in range(10, 31)
803    let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"]
804  endfor
805  call writefile(l, 'Xtags')
806  set tags=Xtags
807
808  let l = []
809  for i in range(10, 31)
810    let l += ["int var" .. i .. ";"]
811  endfor
812  call writefile(l, 'Xfoo')
813
814  " Jump to a tag when the tag stack is full. Oldest entry should be removed.
815  enew
816  for i in range(10, 30)
817    exe "tag var" .. i
818  endfor
819  let l = gettagstack()
820  call assert_equal(20, l.length)
821  call assert_equal('var11', l.items[0].tagname)
822  tag var31
823  let l = gettagstack()
824  call assert_equal('var12', l.items[0].tagname)
825  call assert_equal('var31', l.items[19].tagname)
826
827  " Use tnext with a single match
828  call assert_fails('tnext', 'E427:')
829
830  " Jump to newest entry from the top of the stack
831  call assert_fails('tag', 'E556:')
832
833  " Pop with zero count from the top of the stack
834  call assert_fails('0pop', 'E556:')
835
836  " Pop from an unsaved buffer
837  enew!
838  call append(1, "sample text")
839  call assert_fails('pop', 'E37:')
840  call assert_equal(21, gettagstack().curidx)
841  enew!
842
843  " Pop all the entries in the tag stack
844  call assert_fails('30pop', 'E555:')
845
846  " Pop with a count when already at the bottom of the stack
847  call assert_fails('exe "normal 4\<C-T>"', 'E555:')
848  call assert_equal(1, gettagstack().curidx)
849
850  " Jump to newest entry from the bottom of the stack with zero count
851  call assert_fails('0tag', 'E555:')
852
853  " Pop the tag stack when it is empty
854  call settagstack(1, {'items' : []})
855  call assert_fails('pop', 'E73:')
856
857  call delete('Xtags')
858  call delete('Xfoo')
859  set tags&
860  %bwipe
861endfunc
862
863" Test for browsing multiple matching tags
864func Test_tag_multimatch()
865  call writefile([
866        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
867        \ "first\tXfoo\t1",
868        \ "first\tXfoo\t2",
869        \ "first\tXfoo\t3"],
870        \ 'Xtags')
871  set tags=Xtags
872  let code =<< trim [CODE]
873    int first() {}
874    int first() {}
875    int first() {}
876  [CODE]
877  call writefile(code, 'Xfoo')
878
879  call settagstack(1, {'items' : []})
880  tag first
881  tlast
882  call assert_equal(3, line('.'))
883  call assert_fails('tnext', 'E428:')
884  tfirst
885  call assert_equal(1, line('.'))
886  call assert_fails('tprev', 'E425:')
887
888  tlast
889  call feedkeys("5\<CR>", 't')
890  tselect first
891  call assert_equal(2, gettagstack().curidx)
892
893  set ignorecase
894  tag FIRST
895  tnext
896  call assert_equal(2, line('.'))
897  tlast
898  tprev
899  call assert_equal(2, line('.'))
900  tNext
901  call assert_equal(1, line('.'))
902  set ignorecase&
903
904  call delete('Xtags')
905  call delete('Xfoo')
906  set tags&
907  %bwipe
908endfunc
909
910" Test for previewing multiple matching tags
911func Test_preview_tag_multimatch()
912  call writefile([
913        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
914        \ "first\tXfoo\t1",
915        \ "first\tXfoo\t2",
916        \ "first\tXfoo\t3"],
917        \ 'Xtags')
918  set tags=Xtags
919  let code =<< trim [CODE]
920    int first() {}
921    int first() {}
922    int first() {}
923  [CODE]
924  call writefile(code, 'Xfoo')
925
926  enew | only
927  ptag first
928  ptlast
929  wincmd P
930  call assert_equal(3, line('.'))
931  wincmd w
932  call assert_fails('ptnext', 'E428:')
933  ptprev
934  wincmd P
935  call assert_equal(2, line('.'))
936  wincmd w
937  ptfirst
938  wincmd P
939  call assert_equal(1, line('.'))
940  wincmd w
941  call assert_fails('ptprev', 'E425:')
942  ptnext
943  wincmd P
944  call assert_equal(2, line('.'))
945  wincmd w
946  ptlast
947  call feedkeys("5\<CR>", 't')
948  ptselect first
949  wincmd P
950  call assert_equal(3, line('.'))
951
952  pclose
953
954  call delete('Xtags')
955  call delete('Xfoo')
956  set tags&
957  %bwipe
958endfunc
959
960" Test for jumping to multiple matching tags across multiple :tags commands
961func Test_tnext_multimatch()
962  call writefile([
963        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
964        \ "first\tXfoo1\t1",
965        \ "first\tXfoo2\t1",
966        \ "first\tXfoo3\t1"],
967        \ 'Xtags')
968  set tags=Xtags
969  let code =<< trim [CODE]
970    int first() {}
971  [CODE]
972  call writefile(code, 'Xfoo1')
973  call writefile(code, 'Xfoo2')
974  call writefile(code, 'Xfoo3')
975
976  tag first
977  tag first
978  pop
979  tnext
980  tnext
981  call assert_fails('tnext', 'E428:')
982
983  call delete('Xtags')
984  call delete('Xfoo1')
985  call delete('Xfoo2')
986  call delete('Xfoo3')
987  set tags&
988  %bwipe
989endfunc
990
991" Test for jumping to multiple matching tags in non-existing files
992func Test_multimatch_non_existing_files()
993  call writefile([
994        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
995        \ "first\tXfoo1\t1",
996        \ "first\tXfoo2\t1",
997        \ "first\tXfoo3\t1"],
998        \ 'Xtags')
999  set tags=Xtags
1000
1001  call settagstack(1, {'items' : []})
1002  call assert_fails('tag first', 'E429:')
1003  call assert_equal(3, gettagstack().items[0].matchnr)
1004
1005  call delete('Xtags')
1006  set tags&
1007  %bwipe
1008endfunc
1009
1010func Test_tselect_listing()
1011  call writefile([
1012        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
1013        \ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:",
1014        \ "first\tXfoo\t2" .. ';"' .. "\tv\ttyperef:typename:char\tfile:"],
1015        \ 'Xtags')
1016  set tags=Xtags
1017
1018  let code =<< trim [CODE]
1019    static int first;
1020    static char first;
1021  [CODE]
1022  call writefile(code, 'Xfoo')
1023
1024  call feedkeys("\<CR>", "t")
1025  let l = split(execute("tselect first"), "\n")
1026  let expected =<< [DATA]
1027  # pri kind tag               file
1028  1 FS  v    first             Xfoo
1029               typeref:typename:int
1030               1
1031  2 FS  v    first             Xfoo
1032               typeref:typename:char
1033               2
1034Type number and <Enter> (empty cancels):
1035[DATA]
1036  call assert_equal(expected, l)
1037
1038  call delete('Xtags')
1039  call delete('Xfoo')
1040  set tags&
1041  %bwipe
1042endfunc
1043
1044" Test for :isearch, :ilist, :ijump and :isplit commands
1045" Test for [i, ]i, [I, ]I, [ CTRL-I, ] CTRL-I and CTRL-W i commands
1046func Test_inc_search()
1047  new
1048  call setline(1, ['1:foo', '2:foo', 'foo', '3:foo', '4:foo'])
1049  call cursor(3, 1)
1050
1051  " Test for [i and ]i
1052  call assert_equal('1:foo', execute('normal [i'))
1053  call assert_equal('2:foo', execute('normal 2[i'))
1054  call assert_fails('normal 3[i', 'E387:')
1055  call assert_equal('3:foo', execute('normal ]i'))
1056  call assert_equal('4:foo', execute('normal 2]i'))
1057  call assert_fails('normal 3]i', 'E389:')
1058
1059  " Test for :isearch
1060  call assert_equal('1:foo', execute('isearch foo'))
1061  call assert_equal('3:foo', execute('isearch 4 /foo/'))
1062  call assert_fails('isearch 3 foo', 'E387:')
1063  call assert_equal('3:foo', execute('+1,$isearch foo'))
1064  call assert_fails('1,.-1isearch 3 foo', 'E389:')
1065  call assert_fails('isearch bar', 'E389:')
1066  call assert_fails('isearch /foo/3', 'E488:')
1067
1068  " Test for [I and ]I
1069  call assert_equal([
1070        \ '  1:    1 1:foo',
1071        \ '  2:    2 2:foo',
1072        \ '  3:    3 foo',
1073        \ '  4:    4 3:foo',
1074        \ '  5:    5 4:foo'], split(execute('normal [I'), "\n"))
1075  call assert_equal([
1076        \ '  1:    4 3:foo',
1077        \ '  2:    5 4:foo'], split(execute('normal ]I'), "\n"))
1078
1079  " Test for :ilist
1080  call assert_equal([
1081        \ '  1:    1 1:foo',
1082        \ '  2:    2 2:foo',
1083        \ '  3:    3 foo',
1084        \ '  4:    4 3:foo',
1085        \ '  5:    5 4:foo'], split(execute('ilist foo'), "\n"))
1086  call assert_equal([
1087        \ '  1:    4 3:foo',
1088        \ '  2:    5 4:foo'], split(execute('+1,$ilist /foo/'), "\n"))
1089  call assert_fails('ilist bar', 'E389:')
1090
1091  " Test for [ CTRL-I and ] CTRL-I
1092  exe "normal [\t"
1093  call assert_equal([1, 3], [line('.'), col('.')])
1094  exe "normal 2j4[\t"
1095  call assert_equal([4, 3], [line('.'), col('.')])
1096  call assert_fails("normal k3[\t", 'E387:')
1097  call assert_fails("normal 6[\t", 'E389:')
1098  exe "normal ]\t"
1099  call assert_equal([4, 3], [line('.'), col('.')])
1100  exe "normal k2]\t"
1101  call assert_equal([5, 3], [line('.'), col('.')])
1102  call assert_fails("normal 2k3]\t", 'E389:')
1103
1104  " Test for :ijump
1105  call cursor(3, 1)
1106  ijump foo
1107  call assert_equal([1, 3], [line('.'), col('.')])
1108  call cursor(3, 1)
1109  ijump 4 /foo/
1110  call assert_equal([4, 3], [line('.'), col('.')])
1111  call cursor(3, 1)
1112  call assert_fails('ijump 3 foo', 'E387:')
1113  +,$ijump 2 foo
1114  call assert_equal([5, 3], [line('.'), col('.')])
1115  call assert_fails('ijump bar', 'E389:')
1116
1117  " Test for CTRL-W i
1118  call cursor(3, 1)
1119  wincmd i
1120  call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')])
1121  close
1122  5wincmd i
1123  call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')])
1124  close
1125  call assert_fails('3wincmd i', 'E387:')
1126  call assert_fails('6wincmd i', 'E389:')
1127
1128  " Test for :isplit
1129  isplit foo
1130  call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')])
1131  close
1132  isplit 5 /foo/
1133  call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')])
1134  close
1135  call assert_fails('isplit 3 foo', 'E387:')
1136  call assert_fails('isplit 6 foo', 'E389:')
1137  call assert_fails('isplit bar', 'E389:')
1138
1139  close!
1140endfunc
1141
1142" Test for :dsearch, :dlist, :djump and :dsplit commands
1143" Test for [d, ]d, [D, ]D, [ CTRL-D, ] CTRL-D and CTRL-W d commands
1144func Test_macro_search()
1145  new
1146  call setline(1, ['#define FOO 1', '#define FOO 2', '#define FOO 3',
1147        \ '#define FOO 4', '#define FOO 5'])
1148  call cursor(3, 9)
1149
1150  " Test for [d and ]d
1151  call assert_equal('#define FOO 1', execute('normal [d'))
1152  call assert_equal('#define FOO 2', execute('normal 2[d'))
1153  call assert_fails('normal 3[d', 'E387:')
1154  call assert_equal('#define FOO 4', execute('normal ]d'))
1155  call assert_equal('#define FOO 5', execute('normal 2]d'))
1156  call assert_fails('normal 3]d', 'E388:')
1157
1158  " Test for :dsearch
1159  call assert_equal('#define FOO 1', execute('dsearch FOO'))
1160  call assert_equal('#define FOO 5', execute('dsearch 5 /FOO/'))
1161  call assert_fails('dsearch 3 FOO', 'E387:')
1162  call assert_equal('#define FOO 4', execute('+1,$dsearch FOO'))
1163  call assert_fails('1,.-1dsearch 3 FOO', 'E388:')
1164  call assert_fails('dsearch BAR', 'E388:')
1165
1166  " Test for [D and ]D
1167  call assert_equal([
1168        \ '  1:    1 #define FOO 1',
1169        \ '  2:    2 #define FOO 2',
1170        \ '  3:    3 #define FOO 3',
1171        \ '  4:    4 #define FOO 4',
1172        \ '  5:    5 #define FOO 5'], split(execute('normal [D'), "\n"))
1173  call assert_equal([
1174        \ '  1:    4 #define FOO 4',
1175        \ '  2:    5 #define FOO 5'], split(execute('normal ]D'), "\n"))
1176
1177  " Test for :dlist
1178  call assert_equal([
1179        \ '  1:    1 #define FOO 1',
1180        \ '  2:    2 #define FOO 2',
1181        \ '  3:    3 #define FOO 3',
1182        \ '  4:    4 #define FOO 4',
1183        \ '  5:    5 #define FOO 5'], split(execute('dlist FOO'), "\n"))
1184  call assert_equal([
1185        \ '  1:    4 #define FOO 4',
1186        \ '  2:    5 #define FOO 5'], split(execute('+1,$dlist /FOO/'), "\n"))
1187  call assert_fails('dlist BAR', 'E388:')
1188
1189  " Test for [ CTRL-D and ] CTRL-D
1190  exe "normal [\<C-D>"
1191  call assert_equal([1, 9], [line('.'), col('.')])
1192  exe "normal 2j4[\<C-D>"
1193  call assert_equal([4, 9], [line('.'), col('.')])
1194  call assert_fails("normal k3[\<C-D>", 'E387:')
1195  call assert_fails("normal 6[\<C-D>", 'E388:')
1196  exe "normal ]\<C-D>"
1197  call assert_equal([4, 9], [line('.'), col('.')])
1198  exe "normal k2]\<C-D>"
1199  call assert_equal([5, 9], [line('.'), col('.')])
1200  call assert_fails("normal 2k3]\<C-D>", 'E388:')
1201
1202  " Test for :djump
1203  call cursor(3, 9)
1204  djump FOO
1205  call assert_equal([1, 9], [line('.'), col('.')])
1206  call cursor(3, 9)
1207  djump 4 /FOO/
1208  call assert_equal([4, 9], [line('.'), col('.')])
1209  call cursor(3, 9)
1210  call assert_fails('djump 3 FOO', 'E387:')
1211  +,$djump 2 FOO
1212  call assert_equal([5, 9], [line('.'), col('.')])
1213  call assert_fails('djump BAR', 'E388:')
1214
1215  " Test for CTRL-W d
1216  call cursor(3, 9)
1217  wincmd d
1218  call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')])
1219  close
1220  5wincmd d
1221  call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')])
1222  close
1223  call assert_fails('3wincmd d', 'E387:')
1224  call assert_fails('6wincmd d', 'E388:')
1225
1226  " Test for :dsplit
1227  dsplit FOO
1228  call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')])
1229  close
1230  dsplit 5 /FOO/
1231  call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')])
1232  close
1233  call assert_fails('dsplit 3 FOO', 'E387:')
1234  call assert_fails('dsplit 6 FOO', 'E388:')
1235  call assert_fails('dsplit BAR', 'E388:')
1236
1237  close!
1238endfunc
1239
1240" Test for [*, [/, ]* and ]/
1241func Test_comment_search()
1242  new
1243  call setline(1, ['', '/*', ' *', ' *', ' */'])
1244  normal! 4gg[/
1245  call assert_equal([2, 1], [line('.'), col('.')])
1246  normal! 3gg[*
1247  call assert_equal([2, 1], [line('.'), col('.')])
1248  normal! 3gg]/
1249  call assert_equal([5, 3], [line('.'), col('.')])
1250  normal! 3gg]*
1251  call assert_equal([5, 3], [line('.'), col('.')])
1252  %d
1253  call setline(1, ['', '/*', ' *', ' *'])
1254  call assert_beeps('normal! 3gg]/')
1255  %d
1256  call setline(1, ['', ' *', ' *', ' */'])
1257  call assert_beeps('normal! 4gg[/')
1258  %d
1259  call setline(1, '        /* comment */')
1260  normal! 15|[/
1261  call assert_equal(9, col('.'))
1262  normal! 15|]/
1263  call assert_equal(21, col('.'))
1264  call setline(1, '         comment */')
1265  call assert_beeps('normal! 15|[/')
1266  call setline(1, '        /* comment')
1267  call assert_beeps('normal! 15|]/')
1268  close!
1269endfunc
1270
1271" vim: shiftwidth=2 sts=2 expandtab
1272