我无法确切地说出任何特定实现使用什么算法,但是我可以做出一些有根据的猜测。一个线索是这个问题的一个非常有用的数据结构:IDE可以保持在所有项目中的符号的一个大的内存线索,在每个节点的一些额外的元数据。
当您键入一个字符时,它将沿着特里里的路径走。特定特里节点的所有后代都是可能的完成。然后,IDE仅需要根据当前上下文中有意义的过滤器将它们过滤掉,但是它只需要计算尽可能多的选项卡完成弹出窗口中显示的内容即可。
更高级的制表符完成要求更复杂的尝试。例如,Visual Assist X具有一项功能,您只需键入CamelCase符号的大写字母-例如,如果键入SFN,它将SomeFunctionName
在其制表符完成窗口中显示该符号。
计算特里(或其他数据结构)确实需要解析所有代码以获取项目中所有符号的列表。Visual Studio将此.ncb
文件存储在其IntelliSense数据库中,该文件与项目一起存储,因此不必每次关闭并重新打开项目时都重新解析所有内容。第一次打开大型项目(例如,您刚刚同步了表单源控件的项目)时,VS将花时间分析所有内容并生成数据库。
我不知道它如何处理增量更改。正如您所说,在编写代码时,它有90%的时间是无效的语法,并且每当空闲时重新解析所有内容都会给CPU带来沉重的负担,而带来的好处却很小,尤其是在修改包含大量的源文件。
我怀疑它是(a)仅在您实际构建项目时才进行解析(或者可能在您关闭/打开它时),或者(b)在某种形式的本地解析中仅在您刚刚解析的地方解析代码以某种有限的方式进行编辑,只是为了获得相关符号的名称。由于C ++具有非常复杂的语法,因此如果您使用繁重的模板元编程等,它在黑暗的角落可能会表现出奇怪的表现。