Reputation: 101
The title states the problem, so here's the context. I have a tiny C++ file
void f(
int x
) { }
void f(
) { }
On which I run ctags.
ctags --recurse --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -f tags f.C
Examining the tags files shows two entries for f as expected, with correct signatures.
When I try to use this in Vim, Vim locates the function with ctrl-] but when I use :tnext and :tprev the message says tag 1 of 2
or tag 2 of 2
but the cursor doesn't move between them.
Upvotes: 5
Views: 1190
Reputation: 1
In my case, I also had a stale cscope database, and had cscopetag
turned on, so vim was jumping to the wrong tag based on the information in the cscope database. Deleting or updating the cscope db would solve it.
Upvotes: 0
Reputation: 17353
Based on Ingo Karkat's answer, here's a solution that may work for you. If you run ctags
(at least, Exuberant Ctags) with --excmd=number
, it will output line numbers instead of search commands for the tag location, which will then resolve the ambiguity.
ctags --recurse --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -f tags --excmd=number f.C
The downside to this is that once you start editing the file, the tags will be invalid until you run ctags again. Search patterns are less susceptible to this than line numbers would be.
There are some other answers (Vim auto-generate ctags is one) that cover automatically running ctags on changes; some combination of the two approaches may work for you.
Upvotes: 4
Reputation: 172788
If you look at :help tags-file-format
, Vim uses the third column (named {tagaddress}
) as a (search) command (:help tag-search
). In the generated tags file, it looks like this:
f foo.cpp /^void f($/;" f signature:( )
f foo.cpp /^void f($/;" f signature:( int x )
The search pattern for both overloads (/^void f($/
) are identical; that's why every tag jump will locate the first instance! In other words, though it's nice that the tags program added the signature, Vim unfortunately doesn't consider it.
With that, the obvious way to work around the problem would be to reformat the source code so that (parts of) the signature are included on the same line. Then, there will be different patterns:
b bar.cpp /^void b()$/;" f signature:()
b bar.cpp /^void b(int x)$/;" f signature:(int x)
A more correct (but also way more complex) route for solving this would be to extend the ctags
program to recognize these ambiguities, and then augment the pattern with positive lookahead to also consider the stuff in the following line.
f foo.cpp /^void f(\%(\n\s*int x\)\@=/;" f signature:( )
f foo.cpp /^void f(\n\s*)/;" f signature:( int x )
Unfortunately, Vim doesn't seem to understand this syntax (neither with nor without the lookahead); I just get E435: Couldn't find tag, just guessing!
.
Upvotes: 4