问题描述
||
我正在为sha0ѭ生成一个函数,以为csharp-mode.el索引源代码模块
它可以工作,但是却提供了完全不可接受的性能。有解决此问题的技巧吗?
的背景
我查看了js.el,这是从v23.2开始包含在emacs中的经过重新标记的“ espresso”。它很好地索引了Javascript文件,并很好地处理了匿名函数以及各种常用的编码样式和模式。例如,在javascript中可以执行以下操作:
(function() {
var x = ... ;
function foo() {
if (x == 1) ...
}
})();
...定义一个范围,其中x
是\“ private \”或无法从其他代码访问。 js.el使用正则表达式对它进行了很好的索引,并且还对该范围内的内部函数(无论是否匿名)进行了索引。它运作迅速。一个大模块可以在不到一秒钟的时间内建立索引。
我尝试在csharp-mode中遵循类似的方法,但是要复杂得多。在Js中,所有被索引的都是函数。因此,开始的正则表达式是\“ function \”,两端都有详细说明。一旦发现出现function
关键字,则通过looking-at
会尝试其他4-8个正则表达式-该数目取决于设置。关于js模式的一件好事是,您可以为各种编码样式打开或关闭正则表达式,以加快执行速度。默认的“样式”适用于我尝试的大多数代码。
这在csharp模式下不起作用。它可以工作,但是性能很差,无法使用。我认为原因是
C#中没有单个标记关键字,因为function
在javascript中表现良好。在C#中,我需要查找名称空间,类,结构,接口,枚举等。
定义csharp构造有很大的灵活性。作为一个示例,一个类可以定义基类以及已实现的接口。另一个例子:方法的返回类型不是一个像单词一样简单的字符串,而可能像Dictionary<String,List<String>>
那样混乱。索引例程需要处理所有这些情况,并捕获匹配项。这使得它运行得很慢。
我用了很多七英镑。我在当前方法中使用的标记是大括号。一旦找到其中之一,便使用looking-back
来确定curl是否是类,接口,枚举,方法等。我不清楚它比4英镑慢多少。
一旦找到一对开闭的冰壶,我就叫ѭ11,以索引里面的东西。不知道这是否会降低性能。我怀疑这不是主要的罪魁祸首,因为我看到的性能问题发生在具有一个名称空间和2或3个类的模块中,这意味着狭窄的总数被称为3或4倍。
问题是什么?
我的问题是:您是否有一些技巧来加快C#缓冲区中类似imenu的索引编制?
我正在考虑:
避免looking-back
。我不确切地知道该怎么做,因为当re-search-forward
找到关键字class
时,光标已经在类声明的中间了。 looking-back
似乎很重要。
而不是使用open-curly作为标记,而使用诸如enum,interface,namespace,class之类的关键字
避免narrow-to-region
有什么好建议吗?进一步的建议?
我尝试过的一些事情,但我并不真正热衷于重新访问:为C#构建一个基于wisent的解析器,并依靠语义进行索引。我发现语义非常难以使用,难以发现且存在问题。我在语义上工作了一段时间,但后来升级到v23.2,但它崩溃了,我再也无法使其正常工作了。简单的事情-例如为命名空间关键字编制索引-需要花费很长时间解决。我对此非常不满意,也不想重试。
解决方法
我不是很了解C#语法,而且不看您的书本就很难给出答案,但是无论如何,这还是可行的。
looking-back
可能非常慢。这是我要尝试的第一件事。有用的一件事是使用limit
arg,例如,将搜索限制在当前行的开头。另一种方法是,当您按打开的卷曲时,先按backward-char
,然后按backward-sexp
(或其他任何方式)到达上一个单词的开头,然后使用looking-at
。
使用关键字搜索而不是打开卷曲可能是我会做的。也许像(re-search-forward \"\\\\(enum\\\\|interface\\\\|namespace\\\\|class\\\\)[ \\t\\n]*{\" nil t)
,然后在第一个捕获组上使用match-string-no-properties
来查看找到了哪个关键字。这也可能有助于解决“ 7”问题。
我不知道ѭ11expensive有多昂贵,但是当您找到一个开放的curly26forward-sexp
并保留point
作为您(我假设是递归)搜索的当前迭代的限制时,可以避免这种情况。