Klaus
Klaus

Reputation: 25613

vim and ctags, multiple definitions with same signature not found

I have a simple c++ file like this:

class SomeClass
{
    void SomeMethod() {};
};

class AnotherClass
{
    void SomeMethod() {};
};

If I generate a ctags file with ctags -R * I got:

AnotherClass    main.cpp    /^    class AnotherClass$/;"    c   file:
SomeClass   main.cpp    /^    class SomeClass$/;"   c   file:
SomeMethod  main.cpp    /^        void SomeMethod() {};$/;" f   class:AnotherClass  typeref:typename:void   file:
SomeMethod  main.cpp    /^        void SomeMethod() {};$/;" f   class:SomeClass typeref:typename:void   file:

As you can see, there is no difference in the entries for the definition of SomeMethod and as this in vim tf and tn shows always first definition in file.

I also can add a line number with ctags --fields=+n * which results in:

...
AnotherClass    main.cpp    /^    class AnotherClass$/;"    c   line:6  file:
SomeClass   main.cpp    /^    class SomeClass$/;"   c   line:1  file:
SomeMethod  main.cpp    /^        void SomeMethod() {};$/;" f   line:3  class:SomeClass typeref:typename:void   file:
SomeMethod  main.cpp    /^        void SomeMethod() {};$/;" f   line:8  class:AnotherClass  typeref:typename:void   file:

But vim also jumps always to the first definition of SomeMethod if I use ta SomeMethod and tn

I am using ctags in this version:

Universal Ctags 0.0.0(2614dbe1), Copyright (C) 2015 Universal Ctags Team Universal Ctags is derived from Exuberant Ctags. Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert Compiled: Sep 5 2019, 13:10:38 URL: https://ctags.io/ Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath, +yaml, +packcc

and vim is:

VIM - Vi IMproved 8.1 Patch 1-1713

Upvotes: 3

Views: 953

Answers (3)

Masatake YAMATO
Masatake YAMATO

Reputation: 1300

Try --excmd=combine. It prepends a line number to a pattern.

$ cat /tmp/main.cpp 
class SomeClass
{
    void SomeMethod() {};
};

class AnotherClass
{
    void SomeMethod() {};
};
$ ./ctags -o - --excmd=combine /tmp/main.cpp
AnotherClass    /tmp/main.cpp   5;/^class AnotherClass$/;"  c   file:
SomeClass   /tmp/main.cpp   0;/^class SomeClass$/;" c   file:
SomeMethod  /tmp/main.cpp   2;/^    void SomeMethod() {};$/;"   f   class:SomeClass typeref:typename:void   file:
SomeMethod  /tmp/main.cpp   7;/^    void SomeMethod() {};$/;"   f   class:AnotherClass  typeref:typename:void   file:
$ ./ctags -o - --excmd=combine -B /tmp/main.cpp
AnotherClass    /tmp/main.cpp   7;?^class AnotherClass$?;"  c   file:
SomeClass   /tmp/main.cpp   2;?^class SomeClass$?;" c   file:
SomeMethod  /tmp/main.cpp   4;?^    void SomeMethod() {};$?;"   f   class:SomeClass typeref:typename:void   file:
SomeMethod  /tmp/main.cpp   9;?^    void SomeMethod() {};$?;"   f   class:AnotherClass  typeref:typename:void   file:

Upvotes: 2

Klaus
Klaus

Reputation: 25613

I found a simple solution myself:

ctags --excmd=number *

did the job.

In the third column of the tags file we find the excmd which vim uses to find the place in the file.

SomeMethod  main.cpp    /^        void SomeMethod() {};$/;" f   line:8  class:AnotherClass  typeref:typename:void   file:

becomes

SomeMethod  main.cpp    8;" f   line:8  class:AnotherClass  typeref:typename    :void   file:

Now vim did not search for the expression which is duplicated in the tags file but simply goes to the line which is in the excmd.

Upvotes: 2

Luc Hermitte
Luc Hermitte

Reputation: 32956

You'll need either:

  • to pass the right number to :tag & co,
  • or to use :tselect
  • or to use a plugin that'll help distinguish/select the overload you're interested in (like my old lh-tags plugin)
  • or a more modern solution like a LSP server: lately I've found coc+ccls to be quite nice as it'll know from the context which is the exact overload under the cursor, which is impossible with tag based solutions.

Upvotes: 2

Related Questions