Algorithm 代码完成是如何工作的?
许多编辑器和IDE都有代码完成。他们中的一些人非常“聪明”,其他人则不是。我对更聪明的类型感兴趣。例如,我见过一些IDE,它们只在函数a)在当前范围内可用b)返回值有效时才提供函数。(例如,在“5+foo[tab]”之后,它只提供返回可以添加到正确类型的整数或变量名中的内容的函数。)我还看到,它们将更常用或最长的选项放在列表的前面 我意识到你需要解析代码。但通常,当编辑当前代码无效时,其中会有语法错误。当某个内容不完整且包含错误时,如何解析它 还有一个时间限制。如果需要几秒钟才能列出一个列表,那么完成是没有用的。有时,完成算法处理数千个类Algorithm 代码完成是如何工作的?,algorithm,autocomplete,code-completion,Algorithm,Autocomplete,Code Completion,许多编辑器和IDE都有代码完成。他们中的一些人非常“聪明”,其他人则不是。我对更聪明的类型感兴趣。例如,我见过一些IDE,它们只在函数a)在当前范围内可用b)返回值有效时才提供函数。(例如,在“5+foo[tab]”之后,它只提供返回可以添加到正确类型的整数或变量名中的内容的函数。)我还看到,它们将更常用或最长的选项放在列表的前面 我意识到你需要解析代码。但通常,当编辑当前代码无效时,其中会有语法错误。当某个内容不完整且包含错误时,如何解析它 还有一个时间限制。如果需要几秒钟才能列出一个列表,那
这方面有哪些好的算法和数据结构?我不能确切地说任何特定的实现使用了哪些算法,但我可以做出一些有根据的猜测。对于这个问题,A是一个非常有用的数据结构:IDE可以在项目中所有符号的内存中维护一个大的trie,每个节点上都有一些额外的元数据 键入字符时,它会沿着trie中的路径移动。特定trie节点的所有子代都是可能的补全。IDE然后只需要根据在当前上下文中有意义的内容过滤掉这些内容,但它只需要计算在tab completion弹出窗口中显示的尽可能多的内容 更高级的制表符完成需要更复杂的trie。例如,有一个功能,您只需要键入CamelCase符号的大写字母——例如,如果您键入SFN,它会在其选项卡完成窗口中显示符号
SomeFunctionName
计算trie(或其他数据结构)确实需要解析所有代码,以获得项目中所有符号的列表。VisualStudio将其存储在IntelliSense数据库中,该数据库是一个存储在项目旁边的.ncb
文件,因此它不必在每次关闭和重新打开项目时都重新分析所有内容。当您第一次打开一个大型项目(比如,您刚刚从源代码管理同步的项目)时,VS将花时间解析所有内容并生成数据库
我不知道它如何处理增量更改。正如您所说的,当您编写代码时,90%的时间都是无效的语法,并且每当您空闲时重新划分所有内容都会对您的CPU带来巨大的负担,但好处微乎其微,特别是当您修改大量源文件所包含的头文件时
我怀疑它要么(a)只在您实际构建项目时(或者可能在您关闭/打开项目时)重新解析,要么(b)它进行某种本地解析,只在您刚刚以某种有限的方式编辑的地方解析代码,只是为了获得相关符号的名称。因为C++有着非常复杂的语法,如果使用重模板元编程之类的话,它可能在黑暗的角落里表现得很奇怪。 < P>我的UnRealScript语言服务产品中的智能信息引擎很复杂,但我会尽我所能给出最好的概览。VS2008SP1中的C语言服务是我的性能目标(有充分的理由)。它还没有出现,但它足够快/准确,我可以在键入单个字符后安全地提供建议,而无需等待ctrl+space或用户键入
(点)。[从事语言服务的人]获得的关于这个主题的信息越多,我使用他们的产品所获得的最终用户体验就越好。有很多产品我都有过不幸的工作经历,它们没有对细节给予如此密切的关注,因此我与IDE的斗争超过了编码
在我的语言服务中,它的布局如下:
aa.bb.cc
,但也可以包含方法调用,如aa.bb(3+2).cc
IDeclarationProvider
,您可以在其中调用GetDeclarations()
,以获取范围中所有可见项的IEnumerable
。在我的例子中,这个列表包含局部变量/参数(如果在方法中)、成员(字段和方法,只有在实例方法中才是静态的,没有基类型的私有成员)、全局变量(我正在处理的语言的类型和常量)和关键字。此列表中的项目名称为aa
。作为评估#1中表达式的第一步,我们从上下文枚举中选择名为aa
的项,为下一步提供IDeclaration
aa
的IDeclaration
,以获得另一个IEnumerable
,其中包含aa
的“成员”(在某种意义上)。由于
运算符与->
运算符不同,因此我调用声明.GetMembers(“.”
并期望IDeclaration
对象正确应用列出的运算符cc
,其中声明列表可能包含也可能不包含名为cc
的对象。我相信您也知道,如果多个项目以cc
开头,它们也应该出现。我用羚羊来解决这个问题
class A
{
int x; // linked to A
void foo() // linked to A
{
int local; // linked to foo()
// foo() ends here because bar() is starting
void bar() // linked to A
{
int local2; // linked to bar()
}
int y; // linked again to A