xref: /vim-8.2.3635/src/testdir/test_tagjump.vim (revision 1a928c20)
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
289  set tags=Xtags
290  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
291        \ "one\tXfile1\t1",
292        \ "three\tXfile3\t3",
293        \ "two\tXfile2\t2"],
294        \ 'Xtags')
295
296  let stk = []
297  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'one',
298	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
299  tag one
300  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'two',
301	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
302  tag two
303  call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'three',
304	\ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1})
305  tag three
306  call assert_equal(3, gettagstack(1).length)
307  call assert_equal(stk, gettagstack(1).items)
308  " Check for default - current window
309  call assert_equal(3, gettagstack().length)
310  call assert_equal(stk, gettagstack().items)
311
312  " Try to set current index to invalid values
313  call settagstack(1, {'curidx' : -1})
314  call assert_equal(1, gettagstack().curidx)
315  eval {'curidx' : 50}->settagstack(1)
316  call assert_equal(4, gettagstack().curidx)
317
318  " Try pushing invalid items onto the stack
319  call settagstack(1, {'items' : []})
320  call settagstack(1, {'items' : ["plate"]}, 'a')
321  call assert_equal(0, gettagstack().length)
322  call assert_equal([], gettagstack().items)
323  call settagstack(1, {'items' : [{"tagname" : "abc"}]}, 'a')
324  call assert_equal(0, gettagstack().length)
325  call assert_equal([], gettagstack().items)
326  call settagstack(1, {'items' : [{"from" : 100}]}, 'a')
327  call assert_equal(0, gettagstack().length)
328  call assert_equal([], gettagstack().items)
329  call settagstack(1, {'items' : [{"from" : [2, 1, 0, 0]}]}, 'a')
330  call assert_equal(0, gettagstack().length)
331  call assert_equal([], gettagstack().items)
332
333  " Push one item at a time to the stack
334  call settagstack(1, {'items' : []})
335  call settagstack(1, {'items' : [stk[0]]}, 'a')
336  call settagstack(1, {'items' : [stk[1]]}, 'a')
337  call settagstack(1, {'items' : [stk[2]]}, 'a')
338  call settagstack(1, {'curidx' : 4})
339  call assert_equal({'length' : 3, 'curidx' : 4, 'items' : stk},
340        \ gettagstack(1))
341
342  " Try pushing items onto a full stack
343  for i in range(7)
344    call settagstack(1, {'items' : stk}, 'a')
345  endfor
346  call assert_equal(20, gettagstack().length)
347  call settagstack(1,
348        \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 'a')
349  call assert_equal('abc', gettagstack().items[19].tagname)
350
351  " truncate the tag stack
352  call settagstack(1,
353        \ {'curidx' : 9,
354        \  'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
355  let t = gettagstack()
356  call assert_equal(9, t.length)
357  call assert_equal(10, t.curidx)
358
359  " truncate the tag stack without pushing any new items
360  call settagstack(1, {'curidx' : 5}, 't')
361  let t = gettagstack()
362  call assert_equal(4, t.length)
363  call assert_equal(5, t.curidx)
364
365  " truncate an empty tag stack and push new items
366  call settagstack(1, {'items' : []})
367  call settagstack(1,
368        \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
369  let t = gettagstack()
370  call assert_equal(1, t.length)
371  call assert_equal(2, t.curidx)
372
373  " Tag with multiple matches
374  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
375        \ "two\tXfile1\t1",
376        \ "two\tXfile2\t3",
377        \ "two\tXfile3\t2"],
378        \ 'Xtags')
379  call settagstack(1, {'items' : []})
380  tag two
381  tnext
382  tnext
383  call assert_equal(1, gettagstack().length)
384  call assert_equal(3, gettagstack().items[0].matchnr)
385
386  " Memory allocation failures
387  call test_alloc_fail(GetAllocId('tagstack_items'), 0, 0)
388  call assert_fails('call gettagstack()', 'E342:')
389  call test_alloc_fail(GetAllocId('tagstack_from'), 0, 0)
390  call assert_fails('call gettagstack()', 'E342:')
391  call test_alloc_fail(GetAllocId('tagstack_details'), 0, 0)
392  call assert_fails('call gettagstack()', 'E342:')
393
394  call settagstack(1, {'items' : []})
395  call delete('Xfile1')
396  call delete('Xfile2')
397  call delete('Xfile3')
398  call delete('Xtags')
399  set tags&
400endfunc
401
402func Test_tag_with_count()
403  call writefile([
404	\ 'test	Xtest.h	/^void test();$/;"	p	typeref:typename:void	signature:()',
405	\ ], 'Xtags')
406  call writefile([
407	\ 'main	Xtest.c	/^int main()$/;"	f	typeref:typename:int	signature:()',
408	\ 'test	Xtest.c	/^void test()$/;"	f	typeref:typename:void	signature:()',
409	\ ], 'Ytags')
410  cal writefile([
411	\ 'int main()',
412	\ 'void test()',
413	\ ], 'Xtest.c')
414  cal writefile([
415	\ 'void test();',
416	\ ], 'Xtest.h')
417  set tags=Xtags,Ytags
418
419  new Xtest.c
420  let tl = taglist('test', 'Xtest.c')
421  call assert_equal(tl[0].filename, 'Xtest.c')
422  call assert_equal(tl[1].filename, 'Xtest.h')
423
424  tag test
425  call assert_equal(bufname('%'), 'Xtest.c')
426  1tag test
427  call assert_equal(bufname('%'), 'Xtest.c')
428  2tag test
429  call assert_equal(bufname('%'), 'Xtest.h')
430
431  set tags&
432  call delete('Xtags')
433  call delete('Ytags')
434  bwipe Xtest.h
435  bwipe Xtest.c
436  call delete('Xtest.h')
437  call delete('Xtest.c')
438endfunc
439
440func Test_tagnr_recall()
441  call writefile([
442	\ 'test	Xtest.h	/^void test();$/;"	p',
443	\ 'main	Xtest.c	/^int main()$/;"	f',
444	\ 'test	Xtest.c	/^void test()$/;"	f',
445	\ ], 'Xtags')
446  cal writefile([
447	\ 'int main()',
448	\ 'void test()',
449	\ ], 'Xtest.c')
450  cal writefile([
451	\ 'void test();',
452	\ ], 'Xtest.h')
453  set tags=Xtags
454
455  new Xtest.c
456  let tl = taglist('test', 'Xtest.c')
457  call assert_equal(tl[0].filename, 'Xtest.c')
458  call assert_equal(tl[1].filename, 'Xtest.h')
459
460  2tag test
461  call assert_equal(bufname('%'), 'Xtest.h')
462  pop
463  call assert_equal(bufname('%'), 'Xtest.c')
464  tag
465  call assert_equal(bufname('%'), 'Xtest.h')
466
467  set tags&
468  call delete('Xtags')
469  bwipe Xtest.h
470  bwipe Xtest.c
471  call delete('Xtest.h')
472  call delete('Xtest.c')
473endfunc
474
475func Test_tag_line_toolong()
476  call writefile([
477	\ '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678	django/contrib/admin/templates/admin/edit_inline/stacked.html	16;"	j	line:16	language:HTML'
478	\ ], 'Xtags')
479  set tags=Xtags
480  let old_vbs = &verbose
481  set verbose=5
482  " ":tjump" should give "tag not found" not "Format error in tags file"
483  call assert_fails('tj /foo', 'E426')
484  try
485    tj /foo
486  catch /^Vim\%((\a\+)\)\=:E431/
487    call assert_report(v:exception)
488  catch /.*/
489  endtry
490  call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1])
491
492  call writefile([
493	\ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567	django/contrib/admin/templates/admin/edit_inline/stacked.html	16;"	j	line:16	language:HTML'
494	\ ], 'Xtags')
495  call assert_fails('tj /foo', 'E426')
496  try
497    tj /foo
498  catch /^Vim\%((\a\+)\)\=:E431/
499    call assert_report(v:exception)
500  catch /.*/
501  endtry
502  call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1])
503
504  " binary search works in file with long line
505  call writefile([
506        \ 'asdfasfd	nowhere	16',
507	\ 'foobar	Xsomewhere	3; " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567',
508        \ 'zasdfasfd	nowhere	16',
509	\ ], 'Xtags')
510  call writefile([
511        \ 'one',
512        \ 'two',
513        \ 'trhee',
514        \ 'four',
515        \ ], 'Xsomewhere')
516  tag foobar
517  call assert_equal('Xsomewhere', expand('%'))
518  call assert_equal(3, getcurpos()[1])
519
520  call delete('Xtags')
521  call delete('Xsomewhere')
522  set tags&
523  let &verbose = old_vbs
524endfunc
525
526" Check that using :tselect does not run into the hit-enter prompt.
527" Requires a terminal to trigger that prompt.
528func Test_tselect()
529  CheckScreendump
530
531  call writefile([
532	\ 'main	Xtest.h	/^void test();$/;"	f',
533	\ 'main	Xtest.c	/^int main()$/;"	f',
534	\ 'main	Xtest.x	/^void test()$/;"	f',
535	\ ], 'Xtags')
536  cal writefile([
537	\ 'int main()',
538	\ 'void test()',
539	\ ], 'Xtest.c')
540
541  let lines =<< trim [SCRIPT]
542    set tags=Xtags
543  [SCRIPT]
544  call writefile(lines, 'XTest_tselect')
545  let buf = RunVimInTerminal('-S XTest_tselect', {'rows': 10, 'cols': 50})
546
547  call term_wait(buf, 100)
548  call term_sendkeys(buf, ":tselect main\<CR>2\<CR>")
549  call VerifyScreenDump(buf, 'Test_tselect_1', {})
550
551  call StopVimInTerminal(buf)
552  call delete('Xtags')
553  call delete('Xtest.c')
554  call delete('XTest_tselect')
555endfunc
556
557func Test_tagline()
558  call writefile([
559	\ 'provision	Xtest.py	/^    def provision(self, **kwargs):$/;"	m	line:1	language:Python class:Foo',
560	\ 'provision	Xtest.py	/^    def provision(self, **kwargs):$/;"	m	line:3	language:Python class:Bar',
561	\], 'Xtags')
562  call writefile([
563	\ '    def provision(self, **kwargs):',
564	\ '        pass',
565	\ '    def provision(self, **kwargs):',
566	\ '        pass',
567	\], 'Xtest.py')
568
569  set tags=Xtags
570
571  1tag provision
572  call assert_equal(line('.'), 1)
573  2tag provision
574  call assert_equal(line('.'), 3)
575
576  call delete('Xtags')
577  call delete('Xtest.py')
578  set tags&
579endfunc
580
581" Test for expanding environment variable in a tag file name
582func Test_tag_envvar()
583  call writefile(["Func1\t$FOO\t/^Func1/"], 'Xtags')
584  set tags=Xtags
585
586  let $FOO='TagTestEnv'
587
588  let caught_exception = v:false
589  try
590    tag Func1
591  catch /E429:/
592    call assert_match('E429:.*"TagTestEnv".*', v:exception)
593    let caught_exception = v:true
594  endtry
595  call assert_true(caught_exception)
596
597  set tags&
598  call delete('Xtags')
599  unlet $FOO
600endfunc
601
602" Test for :ptag
603func Test_tag_preview()
604  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
605        \ "second\tXfile1\t2",
606        \ "third\tXfile1\t3",],
607        \ 'Xtags')
608  set tags=Xtags
609  call writefile(['first', 'second', 'third'], 'Xfile1')
610
611  enew | only
612  ptag third
613  call assert_equal(2, winnr())
614  call assert_equal(2, winnr('$'))
615  call assert_equal(1, getwinvar(1, '&previewwindow'))
616  call assert_equal(0, getwinvar(2, '&previewwindow'))
617  wincmd P
618  call assert_equal(3, line('.'))
619
620  " jump to the tag again
621  wincmd w
622  ptag third
623  wincmd P
624  call assert_equal(3, line('.'))
625
626  " jump to the newer tag
627  wincmd w
628  ptag
629  wincmd P
630  call assert_equal(3, line('.'))
631
632  " close the preview window
633  pclose
634  call assert_equal(1, winnr('$'))
635
636  call delete('Xfile1')
637  call delete('Xtags')
638  set tags&
639endfunc
640
641" Tests for guessing the tag location
642func Test_tag_guess()
643  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
644        \ "func1\tXfoo\t/^int func1(int x)/",
645        \ "func2\tXfoo\t/^int func2(int y)/",
646        \ "func3\tXfoo\t/^func3/",
647        \ "func4\tXfoo\t/^func4/"],
648        \ 'Xtags')
649  set tags=Xtags
650  let code =<< trim [CODE]
651
652    int FUNC1  (int x) { }
653    int
654    func2   (int y) { }
655    int * func3 () { }
656
657  [CODE]
658  call writefile(code, 'Xfoo')
659
660  let v:statusmsg = ''
661  ta func1
662  call assert_match('E435:', v:statusmsg)
663  call assert_equal(2, line('.'))
664  let v:statusmsg = ''
665  ta func2
666  call assert_match('E435:', v:statusmsg)
667  call assert_equal(4, line('.'))
668  let v:statusmsg = ''
669  ta func3
670  call assert_match('E435:', v:statusmsg)
671  call assert_equal(5, line('.'))
672  call assert_fails('ta func4', 'E434:')
673
674  call delete('Xtags')
675  call delete('Xfoo')
676  set tags&
677endfunc
678
679" Test for an unsorted tags file
680func Test_tag_sort()
681  call writefile([
682        \ "first\tXfoo\t1",
683        \ "ten\tXfoo\t3",
684        \ "six\tXfoo\t2"],
685        \ 'Xtags')
686  set tags=Xtags
687  let code =<< trim [CODE]
688    int first() {}
689    int six() {}
690    int ten() {}
691  [CODE]
692  call writefile(code, 'Xfoo')
693
694  call assert_fails('tag first', 'E432:')
695
696  call delete('Xtags')
697  call delete('Xfoo')
698  set tags&
699  %bwipe
700endfunc
701
702" Test for an unsorted tags file
703func Test_tag_fold()
704  call writefile([
705        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
706        \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/",
707        \ "first\tXfoo\t1",
708        \ "second\tXfoo\t2",
709        \ "third\tXfoo\t3"],
710        \ 'Xtags')
711  set tags=Xtags
712  let code =<< trim [CODE]
713    int first() {}
714    int second() {}
715    int third() {}
716  [CODE]
717  call writefile(code, 'Xfoo')
718
719  enew
720  tag second
721  call assert_equal('Xfoo', bufname(''))
722  call assert_equal(2, line('.'))
723
724  call delete('Xtags')
725  call delete('Xfoo')
726  set tags&
727  %bwipe
728endfunc
729
730" Test for the :ltag command
731func Test_ltag()
732  call writefile([
733        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
734        \ "first\tXfoo\t1",
735        \ "second\tXfoo\t/^int second() {}$/",
736        \ "third\tXfoo\t3"],
737        \ 'Xtags')
738  set tags=Xtags
739  let code =<< trim [CODE]
740    int first() {}
741    int second() {}
742    int third() {}
743  [CODE]
744  call writefile(code, 'Xfoo')
745
746  enew
747  call setloclist(0, [], 'f')
748  ltag third
749  call assert_equal('Xfoo', bufname(''))
750  call assert_equal(3, line('.'))
751  call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0,
752        \ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '',
753        \ 'module': '', 'text': 'third'}], getloclist(0))
754
755  ltag second
756  call assert_equal(2, line('.'))
757  call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0,
758        \ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0,
759        \ 'type': '', 'module': '', 'text': 'second'}], getloclist(0))
760
761  call delete('Xtags')
762  call delete('Xfoo')
763  set tags&
764  %bwipe
765endfunc
766
767" Test for setting the last search pattern to the tag search pattern
768" when cpoptions has 't'
769func Test_tag_last_search_pat()
770  call writefile([
771        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
772        \ "first\tXfoo\t/^int first() {}/",
773        \ "second\tXfoo\t/^int second() {}/",
774        \ "third\tXfoo\t/^int third() {}/"],
775        \ 'Xtags')
776  set tags=Xtags
777  let code =<< trim [CODE]
778    int first() {}
779    int second() {}
780    int third() {}
781  [CODE]
782  call writefile(code, 'Xfoo')
783
784  enew
785  let save_cpo = &cpo
786  set cpo+=t
787  let @/ = ''
788  tag second
789  call assert_equal('^int second() {}', @/)
790  let &cpo = save_cpo
791
792  call delete('Xtags')
793  call delete('Xfoo')
794  set tags&
795  %bwipe
796endfunc
797
798" Tag stack tests
799func Test_tag_stack()
800  let l = []
801  for i in range(10, 31)
802    let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"]
803  endfor
804  call writefile(l, 'Xtags')
805  set tags=Xtags
806
807  let l = []
808  for i in range(10, 31)
809    let l += ["int var" .. i .. ";"]
810  endfor
811  call writefile(l, 'Xfoo')
812
813  " Jump to a tag when the tag stack is full. Oldest entry should be removed.
814  enew
815  for i in range(10, 30)
816    exe "tag var" .. i
817  endfor
818  let l = gettagstack()
819  call assert_equal(20, l.length)
820  call assert_equal('var11', l.items[0].tagname)
821  tag var31
822  let l = gettagstack()
823  call assert_equal('var12', l.items[0].tagname)
824  call assert_equal('var31', l.items[19].tagname)
825
826  " Use tnext with a single match
827  call assert_fails('tnext', 'E427:')
828
829  " Jump to newest entry from the top of the stack
830  call assert_fails('tag', 'E556:')
831
832  " Pop with zero count from the top of the stack
833  call assert_fails('0pop', 'E556:')
834
835  " Pop from an unsaved buffer
836  enew!
837  call append(1, "sample text")
838  call assert_fails('pop', 'E37:')
839  call assert_equal(21, gettagstack().curidx)
840  enew!
841
842  " Pop all the entries in the tag stack
843  call assert_fails('30pop', 'E555:')
844
845  " Pop with a count when already at the bottom of the stack
846  call assert_fails('exe "normal 4\<C-T>"', 'E555:')
847  call assert_equal(1, gettagstack().curidx)
848
849  " Jump to newest entry from the bottom of the stack with zero count
850  call assert_fails('0tag', 'E555:')
851
852  " Pop the tag stack when it is empty
853  call settagstack(1, {'items' : []})
854  call assert_fails('pop', 'E73:')
855
856  call delete('Xtags')
857  call delete('Xfoo')
858  set tags&
859  %bwipe
860endfunc
861
862" Test for browsing multiple matching tags
863func Test_tag_multimatch()
864  call writefile([
865        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
866        \ "first\tXfoo\t1",
867        \ "first\tXfoo\t2",
868        \ "first\tXfoo\t3"],
869        \ 'Xtags')
870  set tags=Xtags
871  let code =<< trim [CODE]
872    int first() {}
873    int first() {}
874    int first() {}
875  [CODE]
876  call writefile(code, 'Xfoo')
877
878  call settagstack(1, {'items' : []})
879  tag first
880  tlast
881  call assert_equal(3, line('.'))
882  call assert_fails('tnext', 'E428:')
883  tfirst
884  call assert_equal(1, line('.'))
885  call assert_fails('tprev', 'E425:')
886
887  tlast
888  call feedkeys("5\<CR>", 't')
889  tselect first
890  call assert_equal(2, gettagstack().curidx)
891
892  set ignorecase
893  tag FIRST
894  tnext
895  call assert_equal(2, line('.'))
896  set ignorecase&
897
898  call delete('Xtags')
899  call delete('Xfoo')
900  set tags&
901  %bwipe
902endfunc
903
904" Test for previewing multiple matching tags
905func Test_preview_tag_multimatch()
906  call writefile([
907        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
908        \ "first\tXfoo\t1",
909        \ "first\tXfoo\t2",
910        \ "first\tXfoo\t3"],
911        \ 'Xtags')
912  set tags=Xtags
913  let code =<< trim [CODE]
914    int first() {}
915    int first() {}
916    int first() {}
917  [CODE]
918  call writefile(code, 'Xfoo')
919
920  enew | only
921  ptag first
922  ptlast
923  wincmd P
924  call assert_equal(3, line('.'))
925  wincmd w
926  call assert_fails('ptnext', 'E428:')
927  ptprev
928  wincmd P
929  call assert_equal(2, line('.'))
930  wincmd w
931  ptfirst
932  wincmd P
933  call assert_equal(1, line('.'))
934  wincmd w
935  call assert_fails('ptprev', 'E425:')
936  ptnext
937  wincmd P
938  call assert_equal(2, line('.'))
939  wincmd w
940  ptlast
941  call feedkeys("5\<CR>", 't')
942  ptselect first
943  wincmd P
944  call assert_equal(3, line('.'))
945
946  pclose
947
948  call delete('Xtags')
949  call delete('Xfoo')
950  set tags&
951  %bwipe
952endfunc
953
954" Test for jumping to multiple matching tags across multiple :tags commands
955func Test_tnext_multimatch()
956  call writefile([
957        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
958        \ "first\tXfoo1\t1",
959        \ "first\tXfoo2\t1",
960        \ "first\tXfoo3\t1"],
961        \ 'Xtags')
962  set tags=Xtags
963  let code =<< trim [CODE]
964    int first() {}
965  [CODE]
966  call writefile(code, 'Xfoo1')
967  call writefile(code, 'Xfoo2')
968  call writefile(code, 'Xfoo3')
969
970  tag first
971  tag first
972  pop
973  tnext
974  tnext
975  call assert_fails('tnext', 'E428:')
976
977  call delete('Xtags')
978  call delete('Xfoo1')
979  call delete('Xfoo2')
980  call delete('Xfoo3')
981  set tags&
982  %bwipe
983endfunc
984
985" Test for jumping to multiple matching tags in non-existing files
986func Test_multimatch_non_existing_files()
987  call writefile([
988        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
989        \ "first\tXfoo1\t1",
990        \ "first\tXfoo2\t1",
991        \ "first\tXfoo3\t1"],
992        \ 'Xtags')
993  set tags=Xtags
994
995  call settagstack(1, {'items' : []})
996  call assert_fails('tag first', 'E429:')
997  call assert_equal(3, gettagstack().items[0].matchnr)
998
999  call delete('Xtags')
1000  set tags&
1001  %bwipe
1002endfunc
1003
1004func Test_tselect_listing()
1005  call writefile([
1006        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
1007        \ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:",
1008        \ "first\tXfoo\t2" .. ';"' .. "\tv\ttyperef:typename:char\tfile:"],
1009        \ 'Xtags')
1010  set tags=Xtags
1011
1012  let code =<< trim [CODE]
1013    static int first;
1014    static char first;
1015  [CODE]
1016  call writefile(code, 'Xfoo')
1017
1018  call feedkeys("\<CR>", "t")
1019  let l = split(execute("tselect first"), "\n")
1020  let expected =<< [DATA]
1021  # pri kind tag               file
1022  1 FS  v    first             Xfoo
1023               typeref:typename:int
1024               1
1025  2 FS  v    first             Xfoo
1026               typeref:typename:char
1027               2
1028Type number and <Enter> (empty cancels):
1029[DATA]
1030  call assert_equal(expected, l)
1031
1032  call delete('Xtags')
1033  call delete('Xfoo')
1034  set tags&
1035  %bwipe
1036endfunc
1037
1038" vim: shiftwidth=2 sts=2 expandtab
1039