summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-01-05 20:35:44 +0100
committerBram Moolenaar <Bram@vim.org>2020-01-05 20:35:44 +0100
commit830c1afc9d2cd5819a05c71d4e0b1f748a8c0519 (patch)
tree6ce97c03e711c4017898dd209e596cb04dc43795 /src
parent61d7c0d52ca40ab8488c36e619d1e46503affd0b (diff)
patch 8.2.0088: insufficient tests for tags; bug in using extra tag fieldv8.2.0088
Problem: Insufficient tests for tags; bug in using extra tag field when using an ex command to position the cursor. Solution: Fix the bug, add more tests. (Yegappan Lakshmanan, closes #5439)
Diffstat (limited to 'src')
-rw-r--r--src/tag.c4
-rw-r--r--src/testdir/test_ins_complete.vim28
-rw-r--r--src/testdir/test_tagfunc.vim24
-rw-r--r--src/testdir/test_tagjump.vim289
-rw-r--r--src/testdir/test_taglist.vim96
-rw-r--r--src/version.c2
6 files changed, 442 insertions, 1 deletions
diff --git a/src/tag.c b/src/tag.c
index 4f897fa607..aaf19c9738 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -3808,6 +3808,7 @@ test_for_current(
find_extra(char_u **pp)
{
char_u *str = *pp;
+ char_u first_char = **pp;
// Repeat for addresses separated with ';'
for (;;)
@@ -3817,7 +3818,7 @@ find_extra(char_u **pp)
else if (*str == '/' || *str == '?')
{
str = skip_regexp(str + 1, *str, FALSE, NULL);
- if (*str != **pp)
+ if (*str != first_char)
str = NULL;
else
++str;
@@ -3837,6 +3838,7 @@ find_extra(char_u **pp)
|| !(VIM_ISDIGIT(str[1]) || str[1] == '/' || str[1] == '?'))
break;
++str; // skip ';'
+ first_char = *str;
}
if (str != NULL && STRNCMP(str, ";\"", 2) == 0)
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index bec6ffc6f9..c9d93ceb1e 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -432,3 +432,31 @@ func Test_pum_with_preview_win()
call StopVimInTerminal(buf)
call delete('Xpreviewscript')
endfunc
+
+" Test for inserting the tag search pattern in insert mode
+func Test_ins_compl_tag_sft()
+ call writefile([
+ \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "first\tXfoo\t/^int first() {}$/",
+ \ "second\tXfoo\t/^int second() {}$/",
+ \ "third\tXfoo\t/^int third() {}$/"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int second() {}
+ int third() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ enew
+ set showfulltag
+ exe "normal isec\<C-X>\<C-]>\<C-N>\<CR>"
+ call assert_equal('int second() {}', getline(1))
+ set noshowfulltag
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe!
+endfunc
diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim
index 242aa3a235..97782ae21d 100644
--- a/src/testdir/test_tagfunc.vim
+++ b/src/testdir/test_tagfunc.vim
@@ -81,4 +81,28 @@ func Test_tagfunc()
call delete('Xfile1')
endfunc
+" Test for modifying the tag stack from a tag function and jumping to a tag
+" from a tag function
+func Test_tagfunc_settagstack()
+ func Mytagfunc1(pat, flags, info)
+ call settagstack(1, {'tagname' : 'mytag', 'from' : [0, 10, 1, 0]})
+ return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}]
+ endfunc
+ set tagfunc=Mytagfunc1
+ call writefile([''], 'Xtest')
+ call assert_fails('tag xyz', 'E986:')
+
+ func Mytagfunc2(pat, flags, info)
+ tag test_tag
+ return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}]
+ endfunc
+ set tagfunc=Mytagfunc2
+ call assert_fails('tag xyz', 'E986:')
+
+ call delete('Xtest')
+ set tagfunc&
+ delfunc Mytagfunc1
+ delfunc Mytagfunc2
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 8d32883da2..d7bc2992ee 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -578,4 +578,293 @@ func Test_tagline()
set tags&
endfunc
+" Test for expanding environment variable in a tag file name
+func Test_tag_envvar()
+ call writefile(["Func1\t$FOO\t/^Func1/"], 'Xtags')
+ set tags=Xtags
+
+ let $FOO='TagTestEnv'
+
+ let caught_exception = v:false
+ try
+ tag Func1
+ catch /E429:/
+ call assert_match('E429:.*"TagTestEnv".*', v:exception)
+ let caught_exception = v:true
+ endtry
+ call assert_true(caught_exception)
+
+ set tags&
+ call delete('Xtags')
+ unlet $FOO
+endfunc
+
+" Test for :ptag
+func Test_ptag()
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "second\tXfile1\t2",
+ \ "third\tXfile1\t3",],
+ \ 'Xtags')
+ set tags=Xtags
+ call writefile(['first', 'second', 'third'], 'Xfile1')
+
+ enew | only
+ ptag third
+ call assert_equal(2, winnr())
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, getwinvar(1, '&previewwindow'))
+ call assert_equal(0, getwinvar(2, '&previewwindow'))
+ wincmd w
+ call assert_equal(3, line('.'))
+
+ " jump to the tag again
+ ptag third
+ call assert_equal(3, line('.'))
+
+ " close the preview window
+ pclose
+ call assert_equal(1, winnr('$'))
+
+ call delete('Xfile1')
+ call delete('Xtags')
+ set tags&
+endfunc
+
+" Tests for guessing the tag location
+func Test_tag_guess()
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "func1\tXfoo\t/^int func1(int x)/",
+ \ "func2\tXfoo\t/^int func2(int y)/",
+ \ "func3\tXfoo\t/^func3/",
+ \ "func4\tXfoo\t/^func4/"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+
+ int FUNC1 (int x) { }
+ int
+ func2 (int y) { }
+ int * func3 () { }
+
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ let v:statusmsg = ''
+ ta func1
+ call assert_match('E435:', v:statusmsg)
+ call assert_equal(2, line('.'))
+ let v:statusmsg = ''
+ ta func2
+ call assert_match('E435:', v:statusmsg)
+ call assert_equal(4, line('.'))
+ let v:statusmsg = ''
+ ta func3
+ call assert_match('E435:', v:statusmsg)
+ call assert_equal(5, line('.'))
+ call assert_fails('ta func4', 'E434:')
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+endfunc
+
+" Test for an unsorted tags file
+func Test_tag_sort()
+ call writefile([
+ \ "first\tXfoo\t1",
+ \ "ten\tXfoo\t3",
+ \ "six\tXfoo\t2"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int six() {}
+ int ten() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ call assert_fails('tag first', 'E432:')
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
+" Test for an unsorted tags file
+func Test_tag_fold()
+ call writefile([
+ \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/",
+ \ "first\tXfoo\t1",
+ \ "second\tXfoo\t2",
+ \ "third\tXfoo\t3"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int second() {}
+ int third() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ enew
+ tag second
+ call assert_equal('Xfoo', bufname(''))
+ call assert_equal(2, line('.'))
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
+" Test for the :ltag command
+func Test_ltag()
+ call writefile([
+ \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "first\tXfoo\t1",
+ \ "second\tXfoo\t/^int second() {}$/",
+ \ "third\tXfoo\t3"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int second() {}
+ int third() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ enew
+ call setloclist(0, [], 'f')
+ ltag third
+ call assert_equal('Xfoo', bufname(''))
+ call assert_equal(3, line('.'))
+ call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0,
+ \ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '',
+ \ 'module': '', 'text': 'third'}], getloclist(0))
+
+ ltag second
+ call assert_equal(2, line('.'))
+ call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0,
+ \ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0,
+ \ 'type': '', 'module': '', 'text': 'second'}], getloclist(0))
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
+" Test for setting the last search pattern to the tag search pattern
+" when cpoptions has 't'
+func Test_tag_last_search_pat()
+ call writefile([
+ \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "first\tXfoo\t/^int first() {}/",
+ \ "second\tXfoo\t/^int second() {}/",
+ \ "third\tXfoo\t/^int third() {}/"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int second() {}
+ int third() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ enew
+ let save_cpo = &cpo
+ set cpo+=t
+ let @/ = ''
+ tag second
+ call assert_equal('^int second() {}', @/)
+ let &cpo = save_cpo
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
+" Test for jumping to a tag when the tag stack is full
+func Test_tag_stack_full()
+ let l = []
+ for i in range(10, 31)
+ let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"]
+ endfor
+ call writefile(l, 'Xtags')
+ set tags=Xtags
+
+ let l = []
+ for i in range(10, 31)
+ let l += ["int var" .. i .. ";"]
+ endfor
+ call writefile(l, 'Xfoo')
+
+ enew
+ for i in range(10, 30)
+ exe "tag var" .. i
+ endfor
+ let l = gettagstack()
+ call assert_equal(20, l.length)
+ call assert_equal('var11', l.items[0].tagname)
+ tag var31
+ let l = gettagstack()
+ call assert_equal('var12', l.items[0].tagname)
+ call assert_equal('var31', l.items[19].tagname)
+
+ " Jump from the top of the stack
+ call assert_fails('tag', 'E556:')
+
+ " Pop from an unsaved buffer
+ enew!
+ call append(1, "sample text")
+ call assert_fails('pop', 'E37:')
+ call assert_equal(21, gettagstack().curidx)
+ enew!
+
+ " Pop all the entries in the tag stack
+ call assert_fails('30pop', 'E555:')
+
+ " Pop the tag stack when it is empty
+ call settagstack(1, {'items' : []})
+ call assert_fails('pop', 'E73:')
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
+" Test for browsing multiple matching tags
+func Test_tag_multimatch()
+ call writefile([
+ \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "first\tXfoo\t1",
+ \ "first\tXfoo\t2",
+ \ "first\tXfoo\t3"],
+ \ 'Xtags')
+ set tags=Xtags
+ let code =<< trim [CODE]
+ int first() {}
+ int first() {}
+ int first() {}
+ [CODE]
+ call writefile(code, 'Xfoo')
+
+ tag first
+ tlast
+ call assert_equal(3, line('.'))
+ call assert_fails('tnext', 'E428:')
+ tfirst
+ call assert_equal(1, line('.'))
+ call assert_fails('tprev', 'E425:')
+
+ call delete('Xtags')
+ call delete('Xfoo')
+ set tags&
+ %bwipe
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_taglist.vim b/src/testdir/test_taglist.vim
index 824adc013b..0f2615d520 100644
--- a/src/testdir/test_taglist.vim
+++ b/src/testdir/test_taglist.vim
@@ -115,3 +115,99 @@ func Test_tagsfile_without_trailing_newline()
call delete('Xtags')
set tags&
endfunc
+
+" Test for ignoring comments in a tags file
+func Test_tagfile_ignore_comments()
+ call writefile([
+ \ "!_TAG_PROGRAM_NAME /Test tags generator/",
+ \ "FBar\tXfoo\t2" .. ';"' .. "\textrafield\tf",
+ \ "!_TAG_FILE_FORMAT 2 /extended format/",
+ \ ], 'Xtags')
+ set tags=Xtags
+
+ let l = taglist('.*')
+ call assert_equal(1, len(l))
+ call assert_equal('FBar', l[0].name)
+
+ set tags&
+ call delete('Xtags')
+endfunc
+
+" Test for using an excmd in a tags file to position the cursor (instead of a
+" search pattern or a line number)
+func Test_tagfile_excmd()
+ call writefile([
+ \ "vFoo\tXfoo\tcall cursor(3, 4)" .. '|;"' .. "\tv",
+ \ ], 'Xtags')
+ set tags=Xtags
+
+ let l = taglist('.*')
+ call assert_equal([{
+ \ 'cmd' : 'call cursor(3, 4)',
+ \ 'static' : 0,
+ \ 'name' : 'vFoo',
+ \ 'kind' : 'v',
+ \ 'filename' : 'Xfoo'}], l)
+
+ set tags&
+ call delete('Xtags')
+endfunc
+
+" Test for duplicate fields in a tag in a tags file
+func Test_duplicate_field()
+ call writefile([
+ \ "vFoo\tXfoo\t4" .. ';"' .. "\ttypename:int\ttypename:int\tv",
+ \ ], 'Xtags')
+ set tags=Xtags
+
+ let l = taglist('.*')
+ call assert_equal([{
+ \ 'cmd' : '4',
+ \ 'static' : 0,
+ \ 'name' : 'vFoo',
+ \ 'kind' : 'v',
+ \ 'typename' : 'int',
+ \ 'filename' : 'Xfoo'}], l)
+
+ set tags&
+ call delete('Xtags')
+endfunc
+
+" Test for tag address with ;
+func Test_tag_addr_with_semicolon()
+ call writefile([
+ \ "Func1\tXfoo\t6;/^Func1/" .. ';"' .. "\tf"
+ \ ], 'Xtags')
+ set tags=Xtags
+
+ let l = taglist('.*')
+ call assert_equal([{
+ \ 'cmd' : '6;/^Func1/',
+ \ 'static' : 0,
+ \ 'name' : 'Func1',
+ \ 'kind' : 'f',
+ \ 'filename' : 'Xfoo'}], l)
+
+ set tags&
+ call delete('Xtags')
+endfunc
+
+" Test for format error in a tags file
+func Test_format_error()
+ call writefile(['vFoo-Xfoo-4'], 'Xtags')
+ set tags=Xtags
+
+ let caught_exception = v:false
+ try
+ let l = taglist('.*')
+ catch /E431:/
+ " test succeeded
+ let caught_exception = v:true
+ catch
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+ call assert_true(caught_exception)
+
+ set tags&
+ call delete('Xtags')
+endfunc
diff --git a/src/version.c b/src/version.c
index dfa31a77e6..c34675f46c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 88,
+/**/
87,
/**/
86,