【问题标题】:vim and ctags, multiple definitions with same signature not foundvim 和 ctags,未找到具有相同签名的多个定义
【发布时间】:2019-09-05 11:37:37
【问题描述】:

我有一个像这样的简单 c++ 文件:

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

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

如果我使用ctags -R * 生成一个 ctags 文件,我得到:

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:

如您所见,SomeMethod 定义的条目没有区别,因为在 vim 中 tftn 始终显示文件中的第一个定义。

我也可以用ctags --fields=+n *添加行号 这导致:

...
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:

但如果我使用ta SomeMethodtn,vim 也总是跳转到SomeMethod 的第一个定义

我在这个版本中使用 ctags:

Universal Ctags 0.0.0(2614dbe1),版权所有 (C) 2015 Universal Ctags Team Universal Ctags 源自 Exuberant Ctags。 Exuberant Ctags 5.8,版权所有 (C) 1996-2009 Darren Hiebert 编译:2019 年 9 月 5 日,13:10:38 网址:https://ctags.io/ 可选编译特性:+wildcards、+regex、+iconv、+option-directory、+xpath、+yaml、+packcc

而vim是:

VIM - Vi 改进的 8.1 补丁 1-1713

【问题讨论】:

    标签: c++ vim ctags


    【解决方案1】:

    试试--excmd=combine。它将行号添加到模式中。

    $ 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:
    

    【讨论】:

      【解决方案2】:

      我自己找到了一个简单的解决方案:

      ctags --excmd=number *
      

      完成了任务。

      在标签文件的第三列中,我们找到了 vim 用来在文件中查找位置的 excmd。

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

      变成

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

      现在 vim 没有搜索标签文件中重复的表达式,而是直接转到 excmd 中的行。

      【讨论】:

      • 这有问题,如果你在文件中添加行,行号会改变。
      • @geza 很清楚!拥有过时的标签文件可能会导致错误的发现。在默认情况下,更改函数签名将导致无法找到行。一个完美的解决方案将类似于“找到第 n 行正则表达式”。但这只有在我们不能像 cmets 一样在文件的其他地方有相同的正则表达式时才有效。简单的解决方案:错误发现:再次生成标签文件。即使对于大型项目,它也只需要几秒钟。没问题!
      【解决方案3】:

      您需要:

      • 将正确的号码传递给:tag & co,
      • 或使用:tselect
      • 或使用有助于区分/选择您感兴趣的重载的插件(例如我的旧 lh-tags 插件)
      • 或更现代的解决方案,如 LSP 服务器:最近我发现 coc+ccls 非常好,因为它会从上下文中知道光标下的确切过载,而基于标签的解决方案是不可能的。

      【讨论】:

      • 您没有抓住重点:我遍历标签列表并始终在文件中找到相同的行。我知道使用tftn 导航,正如我的问题中已经写的那样。但这一切都在源代码的同一行结束。正如您在标签文件中看到的,这两行是相同的! vim 忽略添加行号!
      • @Klaus 语言服务器应该可以解决这个问题,我建议你看看它作为使用 ctags 的替代方法。
      • @克劳斯。我的错误,我误读了你的问题。看起来像一个错误,请在 github 上的 vim 存储库上打开错误报告/问题。
      • 似乎不是一个错误。我的理解是:标签文件在标签文件的第三列中显示了一个excmd。如果该行完全相同,vim 就没有机会找到正确的行。但是 ctags 除外另一个 excmd,只是“转到行”。请参阅我自己的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多