Merge pull request #14178 from andymass/vim-8.2.0088

[RFC] vim-patch 8.2.0088: insufficient tests for tags...
This commit is contained in:
Jan Edmund Lazo
2021-03-22 20:35:24 -04:00
committed by GitHub
7 changed files with 451 additions and 13 deletions

View File

@@ -337,11 +337,11 @@ the same as above, with a "p" prepended.
A static tag is a tag that is defined for a specific file. In a C program
this could be a static function.
In Vi jumping to a tag sets the current search pattern. This means that
the "n" command after jumping to a tag does not search for the same pattern
that it did before jumping to the tag. Vim does not do this as we consider it
to be a bug. You can still find the tag search pattern in the search history.
If you really want the old Vi behavior, set the 't' flag in 'cpoptions'.
In Vi jumping to a tag sets the current search pattern. This means that the
"n" command after jumping to a tag does not search for the same pattern that
it did before jumping to the tag. Vim does not do this as we consider it to
be a bug. If you really want the old Vi behavior, set the 't' flag in
'cpoptions'.
*tag-binary-search*
Vim uses binary searching in the tags file to find the desired tag quickly
@@ -419,8 +419,7 @@ would otherwise go unnoticed. Example: >
In Vi the ":tag" command sets the last search pattern when the tag is searched
for. In Vim this is not done, the previous search pattern is still remembered,
unless the 't' flag is present in 'cpoptions'. The search pattern is always
put in the search history, so you can modify it if searching fails.
unless the 't' flag is present in 'cpoptions'.
*tags-option*
The 'tags' option is a list of file names. Each of these files is searched

View File

@@ -8809,8 +8809,6 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (set_tagstack(wp, d, action) == OK) {
rettv->vval.v_number = 0;
} else {
EMSG(_(e_listreq));
}
}

View File

@@ -908,7 +908,7 @@ add_llist_tags(
if (len > 128) {
len = 128;
}
xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len);
xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len + 1);
tag_name[len] = NUL;
// Save the tag file name
@@ -975,7 +975,8 @@ add_llist_tags(
if (cmd_len > (CMDBUFFSIZE - 5)) {
cmd_len = CMDBUFFSIZE - 5;
}
xstrlcat((char *)cmd, (char *)cmd_start, cmd_len);
snprintf((char *)cmd + len, CMDBUFFSIZE + 1 - len,
"%.*s", cmd_len, cmd_start);
len += cmd_len;
if (cmd[len - 1] == '$') {
@@ -3003,7 +3004,8 @@ static int test_for_current(char_u *fname, char_u *fname_end, char_u *tag_fname,
*/
static int find_extra(char_u **pp)
{
char_u *str = *pp;
char_u *str = *pp;
char_u first_char = **pp;
// Repeat for addresses separated with ';'
for (;; ) {
@@ -3011,7 +3013,7 @@ static int find_extra(char_u **pp)
str = skipdigits(str);
} else if (*str == '/' || *str == '?') {
str = skip_regexp(str + 1, *str, false, NULL);
if (*str != **pp) {
if (*str != first_char) {
str = NULL;
} else {
str++;
@@ -3029,6 +3031,7 @@ static int find_extra(char_u **pp)
break;
}
str++; // skip ';'
first_char = *str;
}
if (str != NULL && STRNCMP(str, ";\"", 2) == 0) {
@@ -3405,6 +3408,7 @@ int set_tagstack(win_T *wp, const dict_T *d, int action)
if ((di = tv_dict_find(d, "items", -1)) != NULL) {
if (di->di_tv.v_type != VAR_LIST) {
EMSG(_(e_listreq));
return FAIL;
}
l = di->di_tv.vval.v_list;

View File

@@ -469,6 +469,34 @@ func Test_pum_with_folds_two_tabs()
call delete('Xpumscript')
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
" Test to ensure 'Scanning...' messages are not recorded in messages history
func Test_z1_complete_no_history()
new

View File

@@ -93,4 +93,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

View File

@@ -609,6 +609,295 @@ 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
" Test for the 'taglength' option
func Test_tag_length()
set tags=Xtags

View File

@@ -126,3 +126,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