mirror of
https://github.com/neovim/neovim.git
synced 2025-10-08 19:06:31 +00:00
@@ -498,28 +498,21 @@ gnatxref For Ada. See http://www.gnuada.org/. gnatxref is
|
|||||||
part of the gnat package.
|
part of the gnat package.
|
||||||
|
|
||||||
|
|
||||||
The lines in the tags file must have one of these three formats:
|
The lines in the tags file must have one of these two formats:
|
||||||
|
|
||||||
1. {tagname} {TAB} {tagfile} {TAB} {tagaddress}
|
1. {tagname} {TAB} {tagfile} {TAB} {tagaddress}
|
||||||
2. {tagfile}:{tagname} {TAB} {tagfile} {TAB} {tagaddress}
|
2. {tagname} {TAB} {tagfile} {TAB} {tagaddress} {term} {field} ..
|
||||||
3. {tagname} {TAB} {tagfile} {TAB} {tagaddress} {term} {field} ..
|
|
||||||
|
|
||||||
The first is a normal tag, which is completely compatible with Vi. It is the
|
Previously an old format was supported, see |tag-old-static|.
|
||||||
only format produced by traditional ctags implementations. This is often used
|
|
||||||
for functions that are global, also referenced in other files.
|
The first format is a normal tag, which is completely compatible with Vi. It
|
||||||
|
is the only format produced by traditional ctags implementations. This is
|
||||||
|
often used for functions that are global, also referenced in other files.
|
||||||
|
|
||||||
The lines in the tags file can end in <LF> or <CR><LF>. On the Macintosh <CR>
|
The lines in the tags file can end in <LF> or <CR><LF>. On the Macintosh <CR>
|
||||||
also works. The <CR> and <NL> characters can never appear inside a line.
|
also works. The <CR> and <NL> characters can never appear inside a line.
|
||||||
|
|
||||||
*tag-old-static*
|
The second format is new. It includes additional information in optional
|
||||||
The second format is for a static tag only. It is obsolete now, replaced by
|
|
||||||
the third format. It is only supported by Elvis 1.x and Vim and a few
|
|
||||||
versions of ctags. A static tag is often used for functions that are local,
|
|
||||||
only referenced in the file {tagfile}. Note that for the static tag, the two
|
|
||||||
occurrences of {tagfile} must be exactly the same. Also see |tags-option|
|
|
||||||
below, for how static tags are used.
|
|
||||||
|
|
||||||
The third format is new. It includes additional information in optional
|
|
||||||
fields at the end of each line. It is backwards compatible with Vi. It is
|
fields at the end of each line. It is backwards compatible with Vi. It is
|
||||||
only supported by new versions of ctags (such as Exuberant ctags).
|
only supported by new versions of ctags (such as Exuberant ctags).
|
||||||
|
|
||||||
@@ -561,6 +554,7 @@ only supported by new versions of ctags (such as Exuberant ctags).
|
|||||||
The only other field currently recognized by Vim is "file:"
|
The only other field currently recognized by Vim is "file:"
|
||||||
(with an empty value). It is used for a static tag.
|
(with an empty value). It is used for a static tag.
|
||||||
|
|
||||||
|
|
||||||
The first lines in the tags file can contain lines that start with
|
The first lines in the tags file can contain lines that start with
|
||||||
!_TAG_
|
!_TAG_
|
||||||
These are sorted to the first lines, only rare tags that start with "!" can
|
These are sorted to the first lines, only rare tags that start with "!" can
|
||||||
@@ -613,6 +607,21 @@ If the command is a normal search command (it starts and ends with "/" or
|
|||||||
followed by white space and a '('. This will find macro names and function
|
followed by white space and a '('. This will find macro names and function
|
||||||
names with a type prepended.
|
names with a type prepended.
|
||||||
|
|
||||||
|
|
||||||
|
*tag-old-static*
|
||||||
|
Until March 2019 (patch 8.1.1092) an outdated format was supported:
|
||||||
|
{tagfile}:{tagname} {TAB} {tagfile} {TAB} {tagaddress}
|
||||||
|
|
||||||
|
This format is for a static tag only. It is obsolete now, replaced by
|
||||||
|
the second format. It is only supported by Elvis 1.x, older Vim versions and
|
||||||
|
a few versions of ctags. A static tag is often used for functions that are
|
||||||
|
local, only referenced in the file {tagfile}. Note that for the static tag,
|
||||||
|
the two occurrences of {tagfile} must be exactly the same. Also see
|
||||||
|
|tags-option| below, for how static tags are used.
|
||||||
|
|
||||||
|
The support was removed, since when you can update to the new Vim version you
|
||||||
|
should also be able to update ctags to one that supports the second format.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
6. Include file searches *include-search* *definition-search*
|
6. Include file searches *include-search* *definition-search*
|
||||||
*E387* *E388* *E389*
|
*E387* *E388* *E389*
|
||||||
|
116
src/nvim/tag.c
116
src/nvim/tag.c
@@ -1527,57 +1527,37 @@ line_read_in:
|
|||||||
}
|
}
|
||||||
|
|
||||||
parse_line:
|
parse_line:
|
||||||
/*
|
// When the line is too long the NUL will not be in the
|
||||||
* Figure out where the different strings are in this line.
|
// last-but-one byte (see vim_fgets()).
|
||||||
* For "normal" tags: Do a quick check if the tag matches.
|
// Has been reported for Mozilla JS with extremely long names.
|
||||||
* This speeds up tag searching a lot!
|
// In that case we can't parse it and we ignore the line.
|
||||||
*/
|
if (lbuf[LSIZE - 2] != NUL && !use_cscope) {
|
||||||
if (orgpat.headlen
|
if (p_verbose >= 5) {
|
||||||
) {
|
verbose_enter();
|
||||||
|
MSG(_("Ignoring long line in tags file"));
|
||||||
|
verbose_leave();
|
||||||
|
}
|
||||||
|
if (state != TS_LINEAR) {
|
||||||
|
// Avoid getting stuck.
|
||||||
|
linear = true;
|
||||||
|
state = TS_LINEAR;
|
||||||
|
vim_fseek(fp, search_info.low_offset, SEEK_SET);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out where the different strings are in this line.
|
||||||
|
// For "normal" tags: Do a quick check if the tag matches.
|
||||||
|
// This speeds up tag searching a lot!
|
||||||
|
if (orgpat.headlen) {
|
||||||
tagp.tagname = lbuf;
|
tagp.tagname = lbuf;
|
||||||
tagp.tagname_end = vim_strchr(lbuf, TAB);
|
tagp.tagname_end = vim_strchr(lbuf, TAB);
|
||||||
if (tagp.tagname_end == NULL)
|
if (tagp.tagname_end == NULL) {
|
||||||
{
|
// Corrupted tag line.
|
||||||
if (vim_strchr(lbuf, NL) == NULL) {
|
line_error = true;
|
||||||
/* Truncated line, ignore it. Has been reported for
|
|
||||||
* Mozilla JS with extremely long names. */
|
|
||||||
if (p_verbose >= 5) {
|
|
||||||
verbose_enter();
|
|
||||||
MSG(_("Ignoring long line in tags file"));
|
|
||||||
verbose_leave();
|
|
||||||
}
|
|
||||||
if (state != TS_LINEAR) {
|
|
||||||
/* Avoid getting stuck. */
|
|
||||||
linear = TRUE;
|
|
||||||
state = TS_LINEAR;
|
|
||||||
vim_fseek(fp, search_info.low_offset, SEEK_SET);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Corrupted tag line. */
|
|
||||||
line_error = TRUE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for old style static tag: "file:tag file .."
|
|
||||||
*/
|
|
||||||
tagp.fname = NULL;
|
|
||||||
for (p = lbuf; p < tagp.tagname_end; ++p) {
|
|
||||||
if (*p == ':') {
|
|
||||||
if (tagp.fname == NULL)
|
|
||||||
tagp.fname = tagp.tagname_end + 1;
|
|
||||||
if ( fnamencmp(lbuf, tagp.fname, p - lbuf) == 0
|
|
||||||
&& tagp.fname[p - lbuf] == TAB
|
|
||||||
) {
|
|
||||||
/* found one */
|
|
||||||
tagp.tagname = p + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip this line if the length of the tag is different and
|
* Skip this line if the length of the tag is different and
|
||||||
* there is no regexp, or the tag is too short.
|
* there is no regexp, or the tag is too short.
|
||||||
@@ -1677,11 +1657,8 @@ parse_line:
|
|||||||
if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0)
|
if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
// Can be a matching tag, isolate the file name and command.
|
||||||
* Can be a matching tag, isolate the file name and command.
|
tagp.fname = tagp.tagname_end + 1;
|
||||||
*/
|
|
||||||
if (tagp.fname == NULL)
|
|
||||||
tagp.fname = tagp.tagname_end + 1;
|
|
||||||
tagp.fname_end = vim_strchr(tagp.fname, TAB);
|
tagp.fname_end = vim_strchr(tagp.fname, TAB);
|
||||||
tagp.command = tagp.fname_end + 1;
|
tagp.command = tagp.fname_end + 1;
|
||||||
if (tagp.fname_end == NULL)
|
if (tagp.fname_end == NULL)
|
||||||
@@ -1748,19 +1725,12 @@ parse_line:
|
|||||||
/* Don't change the ordering, always use the same table. */
|
/* Don't change the ordering, always use the same table. */
|
||||||
mtt = MT_GL_OTH;
|
mtt = MT_GL_OTH;
|
||||||
} else {
|
} else {
|
||||||
/* Decide in which array to store this match. */
|
// Decide in which array to store this match.
|
||||||
is_current = test_for_current(
|
is_current = test_for_current(tagp.fname, tagp.fname_end, tag_fname,
|
||||||
tagp.fname, tagp.fname_end, tag_fname,
|
buf_ffname);
|
||||||
buf_ffname);
|
is_static = test_for_static(&tagp);
|
||||||
{
|
|
||||||
if (tagp.tagname != lbuf)
|
|
||||||
is_static = TRUE; /* detected static tag before */
|
|
||||||
else
|
|
||||||
is_static = test_for_static(&tagp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decide in which of the sixteen tables to store this
|
// Decide in which of the sixteen tables to store this match.
|
||||||
* match */
|
|
||||||
if (is_static) {
|
if (is_static) {
|
||||||
if (is_current)
|
if (is_current)
|
||||||
mtt = MT_ST_CUR;
|
mtt = MT_ST_CUR;
|
||||||
@@ -2192,25 +2162,9 @@ parse_tag_line (
|
|||||||
*/
|
*/
|
||||||
static bool test_for_static(tagptrs_T *tagp)
|
static bool test_for_static(tagptrs_T *tagp)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
|
||||||
int len;
|
// Check for new style static tag ":...<Tab>file:[<Tab>...]"
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for old style static tag: "file:tag file .."
|
|
||||||
*/
|
|
||||||
len = (int)(tagp->fname_end - tagp->fname);
|
|
||||||
p = tagp->tagname + len;
|
|
||||||
if ( p < tagp->tagname_end
|
|
||||||
&& *p == ':'
|
|
||||||
&& fnamencmp(tagp->tagname, tagp->fname, len) == 0) {
|
|
||||||
tagp->tagname = p + 1;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for new style static tag ":...<Tab>file:[<Tab>...]"
|
|
||||||
*/
|
|
||||||
p = tagp->command;
|
p = tagp->command;
|
||||||
while ((p = vim_strchr(p, '\t')) != NULL) {
|
while ((p = vim_strchr(p, '\t')) != NULL) {
|
||||||
++p;
|
++p;
|
||||||
|
@@ -331,4 +331,35 @@ func Test_tagnr_recall()
|
|||||||
call delete('Xtest.c')
|
call delete('Xtest.c')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_tag_line_toolong()
|
||||||
|
call writefile([
|
||||||
|
\ '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML'
|
||||||
|
\ ], 'Xtags')
|
||||||
|
set tags=Xtags
|
||||||
|
let old_vbs = &verbose
|
||||||
|
set verbose=5
|
||||||
|
" ":tjump" should give "tag not found" not "Format error in tags file"
|
||||||
|
call assert_fails('tj /foo', 'E426')
|
||||||
|
try
|
||||||
|
tj /foo
|
||||||
|
catch /^Vim\%((\a\+)\)\=:E431/
|
||||||
|
call assert_report(v:exception)
|
||||||
|
catch /.*/
|
||||||
|
endtry
|
||||||
|
call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1])
|
||||||
|
call writefile([
|
||||||
|
\ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML'
|
||||||
|
\ ], 'Xtags')
|
||||||
|
call assert_fails('tj /foo', 'E426')
|
||||||
|
try
|
||||||
|
tj /foo
|
||||||
|
catch /^Vim\%((\a\+)\)\=:E431/
|
||||||
|
call assert_report(v:exception)
|
||||||
|
catch /.*/
|
||||||
|
endtry
|
||||||
|
call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1])
|
||||||
|
call delete('Xtags')
|
||||||
|
let &verbose = old_vbs
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -61,3 +61,16 @@ func Test_tags_too_long()
|
|||||||
call assert_fails('tag ' . repeat('x', 1020), 'E426')
|
call assert_fails('tag ' . repeat('x', 1020), 'E426')
|
||||||
tags
|
tags
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" For historical reasons we support a tags file where the last line is missing
|
||||||
|
" the newline.
|
||||||
|
func Test_tagsfile_without_trailing_newline()
|
||||||
|
call writefile(["Foo\tfoo\t1"], 'Xtags', 'b')
|
||||||
|
set tags=Xtags
|
||||||
|
|
||||||
|
let tl = taglist('.*')
|
||||||
|
call assert_equal(1, len(tl))
|
||||||
|
call assert_equal('Foo', tl[0].name)
|
||||||
|
|
||||||
|
call delete('Xtags')
|
||||||
|
endfunc
|
||||||
|
Reference in New Issue
Block a user