为自动完成方案表示语言标记的最佳方法

Chr*_*ian 5 language-agnostic autocomplete token

正如你们中的一些人所知,我正在开发自己的IDE.你可能会想"哦,不,另一个?!" - 别担心,没有人强迫你使用它,我怀疑它会被认真发表.

所以,从主要问题开始.我正在尝试实现自动完成系统.确切的UI不是问题.但是,以灵活的方式存储语言/库令牌是我的主要问题.

假设我们向用户建议CSS选择器或属性.我们有类似的东西:

- css/core
  - a                      // anchor tag
  - etc                    // all valid html tags
  - .stuff                 // class name parsed from user project
  - ?etc                   // more stuff parsed from user project (ids, classes...)
- css/properties
  - border                 // regular css properties - we also need to associate
                           // <border-style> and <color> value tokens
  - etc                    // the rest of them
- css/values/border-style  // property value tokens
  - solid
  - dotted
- css/values/color
  - red
  - green
  - fucshia
Run Code Online (Sandbox Code Playgroud)

因此每个令牌都有一个名称空间,因此我们可以在令牌之间进行跟踪 与BNF类似,一些标记值由字符组成,例如边框和颜色的情况.

1.不要忘记我们需要存储任何可能与具有异国语法的语言相关的内容.2.另外,需要注意的是,我需要以某种方式将上述信息与依赖于上下文的信息合并,例如从项目文件中收集的类名列表.这应该快速有效,不会造成任何重复的令牌等.

因此,总而言之,这里的事情非常复杂,我不能诚实地想到一种获得通用和灵活解决方案的方法.请记住,IDE应该适应任何类型的语言,这使得它更加复杂.

我不确定这个问题是否更适合于,例如,程序员,所以我将把它留给mods来决定.

Mar*_*cek 8

我在一个名为SharpDevelop的IDE上工作.在我讨论存储问题之前,让我先进行一般性的讨论.

我认为你不能以通用的方式正确解决自动填充问题.大多数IDE通过为每种语言提供插件来支持各种语言,完全取决于插件根据文档中光标的当前位置确定完成列表应该是什么样子.

IDE仅提供插件实现的简单接口.例如,显示自动完成的IDE中的代码可能如下所示:

getAutocompletionList(editor) {
  plugin = editor.languagePlugin;
  plugin.getAutocompletionList(editor.cursorPosition, editor.parsedDocument);
}
Run Code Online (Sandbox Code Playgroud)

CSSLanguagePluginPHPLanguagePlugin会则有完全不同的实现方式getAutocompletionList-编辑PHP时编辑CSS,另外当一个将被使用.

正如其他人所指出的,光标周围的上下文非常重要.例如,在编辑以下CSS时:

h1 {
    text-align: <cursor>
Run Code Online (Sandbox Code Playgroud)

上下文将是:

[cssTopLevelContext] {
    [cssPropertyContext]: [cssPropertyValueContext]
}
Run Code Online (Sandbox Code Playgroud)

然后,CSS插件的实现将执行以下操作:

// CSSLanguageBinding
getAutocompletionList(cursorPosition, document) {
    completionContext = this.getCompletionContext(cursorPosition, document);
    // completionContext is { 
    //     'name': 'cssPropertyValueContext', 
    //     'propertyName': 'text-align' 
    // }
    return this.completionDatabase.getCompletionList(completionContext);
    // returns ['left', 'center', 'right'];
}
Run Code Online (Sandbox Code Playgroud)

现在我们来看你的问题 - 完成数据库.同样,它可以(也可能应该)是不同语言插件的不同实现 - 在PHP中,您使用类,方法和变量,并且必须关注可见性(私有,公共,受保护).在CSS中,您使用标签,类和属性.

正如您正确指出的那样,完成数据库应包括:

  • 常见的令牌
  • 当前项目导入的令牌
  • 当前项目本身的令牌

在SharpDevelop中,"常用令牌"部分不存在,因为任何项目都会导入标准库,因此在打开项目时足以分析所有导入的库.

在PHP中,您可以执行相同的操作,并且可以为已经看过的库缓存令牌数据库.

现在我们进入存储格式.要在PHP中提供自动完成功能,您需要了解当前类,其基类和接口层次结构,所有基类和接口中的方法及其可见性,当前上下文中可见的变量及其类型(在PHP中并不总是可行)和等等.

出于这个原因,我认为关系数据库不是一个好的选择.您将如何在那里存储所有类,接口和方法并导航继承层次结构?SharpDevelop将所有这些作为对象模型存储在内存中(Class具有基本类型,接口列表,成员列表等).8000个项目不是一个非常大的数字,如果你在关系数据库中存储了8000个项目,它将会非常小,以至于数据库引擎无论如何都会将它全部保存在RAM中.

SharpDevelop将所有完成信息保存在内存中,当您在SharpDevelop中打开700K线项目时,内存消耗仍然很低.我建议您在打开项目时初始化自动完成数据结构并将它们保存在内存中.正如其他人所说,你必须在用户输入时在后台更新它们(引入新方法,重命名字段等).

这就是PHP.对于CSS,类似于您在问题中概述的数据结构似乎非常合理.您可以在IDE启动/打开项目/打开第一个CSS文件时从结构化文件将其加载到内存中.


作为结束语,为CSS实现良好的自动完成不应该那么难.对于PHP来说,它将变得更加困难,您可以从简单的东西开始 - 从标准库中提供8000个令牌,并提供用户在项目中的其他位置键入的单词.这种方法被Sublime Text等编辑使用,效果出奇的好.