跳到内容
新问题

对这个项目有疑问吗?注册一个免费的GitHub帐户以打开一个问题,并联系其维护者和社区。

单击“注册GitHub”,表示您同意我们的服务条款隐私声明。我们偶尔会向您发送与帐户相关的电子邮件。

已经在GitHub上了?登录到您的帐户

使用uctags中的cxx解析器 #3032

已合并
将10个提交合并到
2021年12月19日
已合并

对话

技术人员
复制链接
成员

@技术人员 技术人员 评论2021年11月28日

这个pull请求将我们切换到新的C和C++cxx解析器。

除了
更改匿名标记在新解析器中的调用方式。
我们有一个旧的解析器,例如。

非结构_1匿名2匿名类型定义3

现在被称为just

__匿名1__匿名2__匿名3

问题是我们应该对此做些什么,还是保持这种方式(应该可以重命名代码中的标记,唯一的问题是我们必须遍历所有标记,除了标记名之外,还需要更新作用域名称)。

修复 #2349,修复 #1314,修复 #1249,修复 #1944,修复 #2916

这是为了避免与新cxx解析器使用的cpreprocessor.ch发生冲突。将lcpp.c/h与cpreprocessor.c/h合并将很困难(至少对于现在)因为c.c中的差异,所以暂时将它们分开。
因此,当我们复制新的cxx解析器时这些符号来自两个不同的解析器。
此修补程序仅使解析器编译,不启用现在还没有。
为此需要做几件事:1.必须将新的预处理器定义为一个单独的解析器。2.来自新c/c++解析器和预处理器解析器的标记必须映射到Geany类型。我们仍然需要保留旧的映射,因为一些解析器(如Ferite或GLSL)仍然使用旧的C解析器。3.匿名标签具有不同的名称,因此我们必须在中反映这一点tm_tag_is_ann()。
主要变化如下:1.函数参数列表中的空格(int var1,int var2,…)-之前(int var1,int var2,…)-现在2.匿名标签非结构_1匿名联合2匿名类型定义3__匿名1__匿名2__匿名33.改进了新解析器的解析
@技术人员
复制链接
成员 作者

刚刚重申,一个单元测试有问题。

@elextr公司
复制链接
成员

哇,77个文件变了,虽然有些是测试。

@技术人员
复制链接
成员 作者

哇,77个文件变了,虽然有些是测试。

是的,这加上由大约30个文件组成的新cxx解析器。

@elextr公司
复制链接
成员

嗯,好吧,我看不出和旧的有什么区别,你确定它正在被使用吗?

没有任何功能在这里看起来很管用,也许格尼需要更多的支持?

@elextr公司
复制链接
成员

elextr公司 评论2021年11月28日

端子上还输出了以下错误:

(geany:100237):Tagmanager-WARNING**:00:10:04.254:生成了refonly kind(using)的定义标记:设置

我明天会去找它,试着做一个MRE。

[编辑:我想这证明它被使用了:)]

@技术人员
复制链接
成员 作者

嗯,好吧,我看不出和旧的有什么区别,你确定它正在被使用吗?
这里的功能似乎都不起作用,也许Geany需要更多的支持?

这些标记类型目前没有映射到Geany中的任何内容,但更好的方法是在添加更多内容之前确保解析器正常工作(我也对其他解析器进行了相同的操作):

{'h',tm_tag_undef_t}\{'l',tm_tag_undef_t}\{'z',tm_tag_undef_t}\{'L',tm_tag_undef_t}\{'D',tm_tag_undef_t},{'A',tm_tag_undef_t},{'N',tm_tag_undef_t},{'U',tm_tag_undef_t},{'Z',tm_tag_undef_t},

在使用新解析器之前,您尝试过一些产生错误输出的棘手文件吗?

(geany:100237):Tagmanager-WARNING**:00:10:04.254:创建了refonly kind(using)的定义标记:设置

我会看看这个。

@技术人员
复制链接
成员 作者

我在这里创建了一个关于警告的错误报告:

通用ctags/ctags#3203

但它应该是无害的。

@马斯塔克
复制链接
贡献者

您可以使用标记外位标记()以ctags申报:主/入口。小时检测标记是否匿名。
作为额外的参数,使用XTAG_非对称在中声明主/入口。小时.

@技术人员
复制链接
成员 作者

您可以使用在ctags:main/entry.h中声明的isTagExtraBitMarked()来检测标记是否是匿名的。
作为额外的参数,使用在main/entry.h中声明的XTAG_ANONYMOUS。

是的,我知道这一点,我想在未来解决这个问题。问题是标签的内部表示TM标签

类型定义 结构 TM标签

不包含可以存储此信息的字段,添加更多字段是ABI的一项更改,因为插件可以访问此结构,所以最好避免这样做。但我认为我们可以使用指针顺序内部为整数TM标签这只是Geany和插件中任何东西都没有使用的一些遗留字段,并且可以将其转换为标记字段,在标记字段中可以存储关于标签是否匿名的信息。

@elextr公司
复制链接
成员

elextr公司 评论2021年11月28日

是ABI的一个变化,因为插件可以访问此结构,所以最好避免这种情况。

可以在ABI结构的末尾添加字段,只是不要更改任何现有字段的顺序。

@技术人员
复制链接
成员 作者

在ABI结构的末尾添加字段是可以的,只是不要改变任何现有字段的顺序。

如果只存储指向TMTag的指针,那也没关系。但如果你有这样的价值观

TMTag foo[10];

TMTag的大小随着一个新字段的增加而增加,并且出现了问题。

@技术人员
复制链接
成员 作者

我刚推送修复程序以获取来自

通用-ctags/ctags@fb305d8型

@elextr公司
复制链接
成员

TMTag foo[10];

我想你的意思是指向数组的指针是从TM传递给插件使用的,而不是插件分配的TM标签就是他们自己。

当非C语言需要额外数据时,这将是一个问题,唉,把它添加到TM仇恨列表中。因为它是从Anjuta偷来的,也许我们应该偷他们的Sqlite替代品:)

@埃克斯特
复制链接
成员

我刚推送修复程序以获取来自

无论如何,危机暂时避免了。

@技术人员
复制链接
成员 作者

我想您的意思是,指向数组的指针是从TM传递给插件使用的,而不是插件自己分配TMTag。

实际上,我指的是由插件分配的TMTag,例如在堆栈上,但我错了——在这种情况下,这不是问题,所以理论上添加更多字段应该不是问题。

因为它是从Anjuta偷来的,也许我们应该偷他们的Sqlite替代品:)

不可能,我认为我们的TM现在很好(我和Colomban重写/删除了许多部分),将标签存储到数据库对我们来说没有任何帮助。

@技术人员
复制链接
成员 作者

@马斯塔克也许有一个问题——目前我们在这里为各个语言提供了硬编码的范围分隔符:

常数 格查尔 *tm地址上下文分隔符(TMParser类型 )

有可能从ctags获得这些信息吗?

@elextr公司
复制链接
成员

我实际上是指由插件分配的TMTag

正是出于这个原因,哈金宣布这是违法的。

@技术人员
复制链接
成员 作者

@马斯塔克也许有一个问题——目前我们在这里为各个语言提供了硬编码的范围分隔符:
有可能从ctags获得这些信息吗?

在看了几个解析器之后回答我自己:不,在许多情况下,这些解析器本身是硬编码的。也许对于使用ATTACH_SEPARATORS()的人来说是可能的,但这只是一些解析器。

@马斯塔克
复制链接
贡献者

马斯塔克 评论2021年11月30日

对不起,迟到了。
正如您所发现的,我介绍了“ATTACH_SEARTORS”,这是定义分隔符的更系统的方法。
然而,只有一些解析器使用它。主要是因为没有强烈的需求:-)。

在标记输出中,您可以看到分隔符定义:

[yamato@dev64]~/var/ctags-withub%/ctags--伪标记=TAG_KIND_SEPARATOR--额外标记=+'{pseudo}'-o-/tmp/input.php!_标签KIND_SEARATOR!PHP::/*a/!_标签KIND_SEARATOR!PHP::/*c/!_标签KIND_SEARATOR!PHP::/*d/!_标签KIND_SEARATOR!PHP::/*f/_标签KIND_SEARATOR!PHP::/*i/!_标签KIND_SEARATOR!PHP::/*l/!_标签KIND_SEARATOR!PHP::/*n/!_标签_分类_分隔符!菲律宾比索::/*t/!_标签KIND_SEARATOR!PHP::/*v/!_标签KIND_SEARATOR!PHP \\/na/!_标签KIND_SEARATOR!PHP \\/nc/!_标签KIND_SEARATOR!PHP \\/nd/!_标签_分类_分隔符!PHP \\/nf/!_标签KIND_SEARATOR!PHP \\/ni/!_标签KIND_SEARATOR!PHP \\/nl/!_标签KIND_SEARATOR!菲律宾比索\\/nn/!_标签KIND_SEARATOR!PHP\\/nt语言/!_标签KIND_SEARATOR!菲律宾\\/nv/

如果您在这方面需要改进,请在u-ctags上提出问题。

@马斯塔克
复制链接
贡献者

马斯塔克 评论2021年11月30日

我在读迷你们蛋糕。
它可以访问种类定义。因此,可以从geany访问附加到它的分隔符定义。
参见u-ctags的main/kind.h中的scopeSeparator。

然而,无法访问定义了默认范围分隔符的“parserDefinition”。
只有在未定义每种scopeSeparator时,才使用默认范围分隔符。
Geany现在没有默认范围分隔符的访问器。
scopeSeparatorFor()很适合作为导出到Geany的API的一部分。
如果你要求,我会检查更多。


以下界面如何:

diff—git a/main/cond.h b/main/cind.h索引5a9b243a。。4d27a3fc 100644号---a/主要/种类.h+++b/main/种类.h@@-104,5+104,7@@结构类定义{*/extern const char*scopeSeparatorFor(langType lang,int kindIndex,int parentKindIndex);+extern const char*scopeRootSeparatorFor(langType语言);+extern const char*scopeDefaultSeparatorFor(langType语言);#endif/*CTAGS_MAIN_KIND_H*/

当然,解析器显式地定义分隔符。但这是一个有点不同的主题。

@技术人员
复制链接
成员 作者

@马斯塔克谢谢你的详细解释。我认为我们真的不需要任何特殊的API来实现这一点,我只是想问问,以防我们做了一些不必要的蠢事:-)

然而,PHP中的那些多范围分隔符非常令人不快——我们的代码目前假设每种语言只有一种类型的范围分隔符。我想对我们来说最简单的方法是重写从ctags收到的标记,使其具有单一类型的范围分隔符。有没有其他语言使用多种类型的范围分隔符?

(我不确定多种类型的范围分隔符是否是一个好主意,即使给定的语言对某些类型使用这些分隔符-我认为处理ctags文件的工具不会很乐意处理这个问题。)

我还开始意识到,我们必须考虑到我们目前忽略的“角色”——例如,在go编译器中,角色用于区分文件包和导入的包,这是两种不同的东西,会混淆我们的代码:

静态角色定义GoPackageRoles[]={{true,“导入”,“导入包”},};{true,'p',“package”,“packets”,.referenceOnly=false,ATTACH_ROLES(GoPackageRoles)},

我这样假设对吗角色比特类型角色比特里面sTagEntryInfo(标签条目信息)定义一种类型是否具有特定作用?例如,对于某些角色定义,如

静态角色定义SomeRoles[]={{true,“foo”,“”},{true,“bar”,“}”,{true,“baz”,“”},};

5(即。101二进制)表示类型具有foo公司巴兹角色?

@技术人员
复制链接
成员 作者

@马斯塔克考虑了一会儿之后,使用go中的角色(可能还有其他一些语言)区分导入和包定义实际上是一个好主意吗?我理解角色语义的方式是,它们进一步区分了单一类型的性质,但如果忽略了这些额外的信息,就不会发生什么坏事。例如,在Python中,我认为以下内容没问题,因为它只是区分不同类型的导入

/*与“导入”相关的角色* ==========================*import X X=(种类:模块,角色:已导入)**将X导入为Y X=(种类:模块,角色:间接导入),*Y=(kind:namespace,nameref:module:X)*                       ------------------------------------------------*不要混淆Y的类型和模块类型的名称空间角色。**从X导入*X=(种类:模块,角色:命名空间)**从X导入Y X=(种类:模块,角色:命名空间),*Y=(种类:未知,角色:已导入,范围:模块:X)**从X导入Y作为Z X=(种类:模块,角色:命名空间),*Y=(种类:未知,角色:间接导入,范围:模块:X)*Z=(种类:未知,名称参考:未知:Y)*/

但包装定义和其他包装的进口是两个根本不同的东西,IMO应该有两种不同的定义。

注意:请将上述内容作为一个记录,记录下那些懒于在Geany做额外工作的人,可能只是想找出如何将一些工作委派给其他人:-)。我在上面写的东西在我(非常有偏见)的大脑中是有意义的,但无论实现什么,对ctags来说都应该是一件好事。

@技术人员
复制链接
成员 作者

可以理解。然而,我想让ctags将提取的信息传递给包括Geany在内的客户端工具。
我认为ctags不应该做得太聪明。减少信息可以在客户端工具中完成。在ctags级别,仅仅传递过多的信息比减少信息要好。即使目标语言出错,ctags也不会尝试修复它。这个基本规则使开发ctags变得更容易。

ctags可以做的是为以下方面提供更多API:
(1) 获取分隔符,以及
(2) 在制作标记时,根据客户端工具的需要调整分隔符。

好的,明白了,我认为不需要API,我只是转换了\::对于Geany中的PHP,没有真正的问题。

你似乎误解了角色的含义。

的确,我误解了角色,但问题仍然存在-我刚刚在这里针对ctags创建了一个新问题通用ctags/ctags#3211所以我们不会污染这个线程。

@技术人员
复制链接
成员 作者

@elextr公司新解析器缺少哪些标记?是局部变量吗?这是一种“l”类型,您可以将其映射到tm_tag_variable_t,然后解析所有局部变量(一切正常-侧栏,转到标记定义/声明,范围完成等)。我只是觉得在侧栏中显示局部变量可能有点冗长。

我认为我们应该改进侧边栏的标记映射功能,并通过将映射从

转换(英尺id)

tmctags.c位于ctags映射旁边,因此它们是并排的,更容易管理。还应该允许禁用某些类型的侧边栏,同时保留它们用于我们使用标记的其他内容,如标记定义、声明等。一个示例可能是局部变量(但我自己不太使用侧边栏并且可能需要它们)但也可以获取函数参数的标记&虽然这些标记有助于自动完成或跳转代码,但我们不想在侧栏中单独显示它们,因为它们已经是函数原型的一部分。

#定义映射_CPP映射_C
#定义COMMON_C_NEW_PARSER\
{'h',tm_tag_undef_t}\
{'l',tm_tag_undef_t}\
复制链接
成员 作者

选择隐藏此评论的原因

将显示原因,以便向其他人描述此评论。了解更多信息.

@elextr公司如果您想进行实验,请将此处的“l”类型映射到tm_tag_variable_t,这样可以解析所有局部变量。

该语法与前面的语法略有不同描述如下:https://docs.ctags.io/en/latest/parser-cxx.html基本用法应该相同,ductags不支持Geany的通配符会忽略类似G_GNUC_*的内容。另一方面,新的解析器是对宏的适应性更强,所以不应该有太多需求手动忽略。对于仍然使用旧的预处理器。
@技术人员
复制链接
成员 作者

我刚刚添加了一个补丁以通过我们的忽略的.tags文件到新的cxx解析器。新语法与以前略有不同,因此我们可能还应该更新文档。

@技术人员
复制链接
成员 作者

刚刚浏览了各种问题报告,这个请求应该(至少)修复了以下问题。

修复#2349,#1314,#1249,#1944,#2916

@elextr公司
复制链接
成员

@技术人员我想冲突来自合并#2991

#冲突:#ctags/Makefile.am
@技术人员
复制链接
成员 作者

我刚刚解决了这个拉请求的冲突(只有Makefile.am),#3031#3035。从我的角度来看,所有3个pull请求或多或少都已准备好合并。

对于这里的cxx解析器,我只需要指出两件事来决定:

  • 是否__阿诺标记可以用于匿名声明的侧栏
  • ignored.tags文件的不同语法和功能是否正常(但恐怕我们在这里无能为力)。如果是这样,我将更新文档。

@elextr公司
复制链接
成员

即将测试(ish)。

ignored.tags文件的不同语法和功能是否正常(但恐怕我们在这里无能为力)

这是紧跟上游的不利因素之一,正如你所说,我们无能为力

我会更新文档。

拜托。

@elextr公司
复制链接
成员

似乎有效。

__anon标记是否适用于匿名声明的侧栏

嗯,我明白你的意思了,看看tm_parser.c开头的typedef,结构如下所示__阿诺typedef随后显示,但它们之间没有链接。所以AFAICT使用typedef找不到自动完成的成员?

我按照你的建议启用了局部变量(为什么我要编辑tm_parser。c(c)同上),是的,它们被发现了:-)。

但并非所有(参见下面的示例):-(。

函数参数如何?

这两个将有助于处理许多简单的案例,以显示以下选项本地变量。参数->,至少在C语言中是如此,对于Geany开发来说也是如此。

但这提出了一个问题,即我们应该努力走多远?

没有项目组织者或者类似于获取项目中的所有符号,以及C++STL,或者(例如)Geany的libc、GTK和Glib,除了非常简单的情况外,我们不会有太多进展。但是,随着所有符号的收集,由于出现了太多无用的选项,当前的无范围自动完成方法变得不可用。因此,需要进行适当的范围跟踪。但范围界定还意味着遵循include,这一点目前尚未完成,根据@b4n型可能性很小。

但即使有了所有这些,推断类型的趋势也将是一个很大的限制(好的,不是对C,而是对C++和其他推断类型的语言)。

例如(显示STL包含、范围和推断的示例):

#包括 <效用>#包括 <一串>
使用 命名空间 标准::字符串;
(f)(){//makepair返回的类型根据其参数推断为std::pair<int,std::string>
    //i和s的类型是通过分解返回类型推断出来的
    汽车【i,s】=标准::make_pair(1,"美国广播公司"s) ;//如上所述,但分配未分解的对
    汽车第页=标准::make_pair(1,"美国广播公司"s) ;第条。????第页。东南方????}

如果我在????处按ctrl+space????s应该自动完成显示什么(回答“大小”和“秒”)。

但事实上,i和s目前并没有被解析为局部变量,所以“si”为我提供了大量的Linux信号符号,尽管p被解析了,因为它是推断出来的,所以ctags没有为它提供类型和范围自动补全,所以它从C!!中获得了混杂的“se”符号!!!。

仍然能够获得显式声明的局部变量和参数将对Geany有很大帮助😄
特别是如果我们可以修复那些typedefed __anno结构。
但除此之外,还有一些事情要留给大男孩,让他们对中等能力的IMO感到满意。

@技术人员
复制链接
成员 作者

嗯,我明白你的意思了,看看tm_parser.c开头的typedef,结构显示为__anon,typedef随后显示,但它们之间没有链接。所以AFAICT使用typedef无法找到自动完成的成员?

typedef和例如匿名枚举之间的断开不是什么新鲜事,它已经存在于旧的解析器中。这里的新情况是名称缺少关于它是哪种匿名类型的信息匿名_编号_1,非结构-2现在你只需要__匿名1__匿名2Scope自动补全应该仍然有效,它应该正确解析typedef,它只是侧边栏中的显示。

如果没有问题,我会为此打开一个单独的pull请求-这不仅仅是简单的标记名重命名,问题是这些匿名标记可能会作为其他标记的父标记出现在作用域中,然后我们也必须更新作用域信息。此外,我们应该开始使用来自ctags的信息来检测标签是否匿名,而不仅仅依赖于基于标签名称的检测。

但这提出了一个问题,即我们应该努力走多远?

我们的范围完成以及跳转到标记定义/声明还没有准备好启用局部变量-将有太多误报。正如你所说,我们不能完全依赖范围信息,因为我们不知道要解析哪些文件,我认为我们必须找到一种混合方法,在某些情况下使用范围信息,而在其他情况下则不使用。

函数参数如何?

它们最终也应该启用,但我们还没有做好准备。我们主要需要提高自己的能力,以便能够决定在符号树中显示什么以及如何显示。例如,虽然我们希望参数由ctags解析,但我们不希望在侧边栏的函数名下面看到它们——这些参数会与局部变量混淆。

一旦合并了所有当前挂起的解析器pull请求,我想将树映射从symbols.c移动到tm_parsers,提高它们的灵活性,并简化维护和添加新解析器。例如,对于makefiles,其定义如下:

/*除了我们在这里已经拥有的之外,我们还可以在这里指定符号树的图标*/静态TMParserMapEntry映射_MAKEFILE[]={{'m',tm_tag_macro_t,ICON_macro},{not',tm_tag_function_t,ICON_METHOD},{'I',tm_tag_undef_t,ICON_NONE},};/*这将定义符号树中的根、用于它们的图标以及放置的标记在根下面。请注意,tm_tag_macro_t是一个位掩码,因此如果我们想在下面添加几种类型对于同一根,我们只需在最后一个元素中对其进行xor运算*/静态TMParserMapGroup组_MAKEFILE[]={{_(“目标”),ICON_METHOD,tm_tag_macro_t},{_(“宏”),ICON_MACRO,tm_tag_function_t},};

@elextr公司
复制链接
成员

范围自动完成应该仍然有效,它应该正确解析typedef,它只是侧边栏中的显示。

好的,我关闭了“自动补全符号”,看起来ctrl+space不会影响自动补全,只是命名为autocomplete,我没有意识到这一点。作用域和名称都适用于它。

范围自动完成也适用于本地人👍 (例如在tmparser.c:674上键入map->)但正如您所指出的,它也可以在本地范围之外工作😞

我们不想在侧栏中的函数名下面看到它们,因为它们会与局部变量混淆。

从技术上讲,参数比局部变量更准确,因为它们对整个函数都可见,而局部变量只在声明到范围结束时可见。

Vscode和Eclipse都没有在函数的符号中显示局部变量或参数,这有点道理,您不能指定它们的范围(即不能执行funct_name::local_name或funct_name::param_name),但两者都在悬停时在工具提示中显示了它们的声明(我对此仍有歧义,这可能很烦人)。局部和参数名称的风格不同,但这不是我们能做的,因为闪烁体。

无论如何,这只是一个试验,而不是这个PR的一部分,到目前为止似乎是可行的,我很高兴它能被合并,以便得到更多的测试。

@技术人员
复制链接
成员 作者

Vscode和Eclipse都没有在函数的符号中显示局部变量或参数

是的,这两个都应该在侧边栏中禁用。

我很乐意将其合并,以便进行更多测试。

👍

@elextr公司
复制链接
成员

文档LGTM

@elextr公司
复制链接
成员

如果没有人提出问题或击败我,那么“很快”就会挤掉并合并

@技术人员
复制链接
成员 作者

“很快”

是的:-)。无论如何,我真的认为所有的解析器pull请求应该很快合并(注意——没有撇号),以便进行一些测试。如果有问题,我们可以向上游报告并获得固定版本,或者只返回到旧的解析器—这应该是最简单的。

我首先想了解的唯一解析器是#3034并在Raspberry Pi上测试它,看看它在较慢的硬件上是如何工作的。

@技术人员
复制链接
成员 作者

@elextr公司还有一件事:一旦合并了这个pull请求,就可以使用上游ASM解析器,该解析器依赖于该pull请求添加的新cxx预处理器(否则,如果不存在这种依赖关系,解析器就会包含在“具有大更改的解析器”pull请求中)。我应该为此创建单独的拉取请求,还是将其添加到#3035?

@elextr公司
复制链接
成员

“很快”

只是周末,以防万一有人有问题,真的,真的。。。😄

我应该创建单独的拉取请求吗

我会的,小就是好,尤其是在拉取请求中。

@技术人员
复制链接
成员 作者

只是周末,以防万一有人有问题,真的,真的。。。😄

只是一个温和的提醒——周末结束了,又一个周末即将到来:-)。

@elextr公司
复制链接
成员

只是一个温和的提醒——周末结束了,又一个周末即将到来:-)。

我没说哪一个我周末去了吗??😀

只是时间不够了,希望很快。

@elextr公司 elextr公司合并提交5ea3e3e进入之内 杰尼:主人 2021年12月19日
@elextr公司
复制链接
成员

好了,只是偏执地重新检查它对我来说仍然有效。😄

免费注册 在GitHub上加入此对话.已经有帐户了吗?登录以发表评论