5

正如你们中的一些人所知,我正在开发自己的 IDE。你可能会想“哦不,再来一个?!” - 别担心,没有人强迫你使用它,我怀疑它无论如何都会被认真发布。

所以,继续讨论主要问题。我正在尝试实现一个自动完成系统。确切的用户界面不是问题。但是,以灵活的方式存储语言/库标记是我的主要问题。

假设我们向用户建议 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

所以每个令牌都有一个命名空间,这样我们就可以在令牌之间进行跟踪。与 BNF 类似,一些标记值由子标记组成,例如边框和颜色的大小写。

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

所以,总而言之,这里的事情非常复杂,老实说,我想不出一种方法来获得一个通用和灵活的解决方案。请记住,IDE 应该适合任何类型的语言,这使得这变得更加复杂。

我不确定这个问题是否更适合程序员,所以我会留给模组来决定。

4

4 回答 4

8

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

我认为您无法以通用方式正确解决自动完成问题。大多数 IDE 通过为每种语言提供一个插件来支持各种语言,并且完全由插件根据文档中光标的当前位置来确定完成列表的外观。

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

getAutocompletionList(editor) {
  plugin = editor.languagePlugin;
  plugin.getAutocompletionList(editor.cursorPosition, editor.parsedDocument);
}

ACSSLanguagePlugin然后PHPLanguagePlugin会有完全独立的实现getAutocompletionList- 一个在编辑 CSS 时使用,另一个在编辑 PHP 时使用。

正如其他人指出的那样,光标周围的上下文很重要。例如,在编辑以下 CSS 时:

h1 {
    text-align: <cursor>

上下文将是:

[cssTopLevelContext] {
    [cssPropertyContext]: [cssPropertyValueContext]
}

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'];
}

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

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

  • 通用令牌
  • 当前项目导入的代币
  • 当前项目本身中的代币

在 SharpDevelop 中,没有“通用标记”部分,因为任何项目都会导入标准库,因此在打开项目时分析所有导入的库就足够了。

在 PHP 中你可以做同样的事情,你可以为已经看到的库缓存令牌数据库。

现在我们来看看存储格式。要在 PHP 中提供自动完成功能,您需要知道当前类、它的基类和接口层次结构、所有基类和接口中的方法及其可见性、当前上下文中可见的变量及其类型(在 PHP 中并不总是可能)和很快。

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

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

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


作为结束说明,为 CSS 实现良好的自动完成应该不难。对于 PHP,这将更加困难,您可以从简单的事情开始 - 提供标准库中的 8000 个令牌,并提供用户在项目其他地方键入的单词。这种方法被 Sublime Text 之类的编辑器使用,并且效果出奇的好。

于 2012-06-16T20:41:47.493 回答
3

经过一些人的仔细考虑和建议,数据库是存储自动完成信息的唯一合乎逻辑的解决方案。

在这个练习中,我编写了几个脚本来解析代码/规范以生成自动完成代码。

在这里我意识到,例如,PHP 至少有超过 8000 个函数(=> 自动完成项)。

因此,将这些信息存储在 PHP 文件中并在 IDE 启动时加载是很糟糕的。相反,我的数据库将存储这些信息。

任何特定于项目的自动完成都将存储在单独的数据库表中,有助于避免堵塞主文档表。

于 2012-06-13T14:54:23.830 回答
1

一般来说,困难的部分是收集要提供的标记并将它们与正确的输入上下文匹配。(在部分键入的行的哪个字符中键入以使用什么来激活,以及在语言类型系统中键入。)相比之下,表示和查询选项列表很容易并且无关紧要。天真的方法非常好。

现有 IDE 所做的一件事是,它们会定期获取您的代码并在后台线程中编译它,使用编译器的特殊版本或模式来生成程序中存在的函数/变量/等的列表。该列表交替地称为“标签文件”、“浏览信息”或“程序数据库”。它存储项目中每个函数的名称、路径、类型,有时还存储一些自动提取的文档;并且为了性能,它需要以增量方式工作,也就是说,避免重新编译没有改变的东西,至少在单个文件的粒度上。它还需要比真正的编译器更能容忍错误,因为它对部分类型的代码进行操作。

然后,当您键入时,编译器会知道自动完成程序应该出现的一些上下文:在您键入“。”之后 对于函数,当您键入 CSS 属性名称的一部分时等。这些取决于模式匹配部分键入的代码。这些没有统一的原则;这只是一堆特殊情况,因语言而异。例如,当您在“case SomeEnum.Foo:”中键入空格时,某些 IDE 会找到封闭的 switch 语句,推断其类型,找到该枚举类型的定义,并将其值作为选项提供。

所有这一切的实际后果是,您永远无法获得自动完成器可以提供的东西的统一表示;相反,您混合了特定于语言的上下文识别技巧、各种上下文的列表以及通过解析提取的更多列表。许多上下文会将几个列表合并在一起;例如,CSS 选择器可以具有任何 HTML 标记名称,或提取类名称/ID,并且在键入 HTML 时也使用 HTML 标记名称列表。

于 2012-06-16T02:55:39.590 回答
1

在我以前的工作中,我们在糟糕的网站上出售制成品(我是一名工程师,所以我发誓这种可怕的事情不是我的错)。有一天,上级决定在我们所有的产品上都需要一个“推荐物品”框。

对此的常识性方法是在每个产品与所有其他产品之间建立一个非常酷且有趣的关系,然后为客户提供有关实际相关产品的相关当前信息。不幸的是,我工作中没有人知道如何让我们的预建网站做到这一点。

相反,他们为每个产品附加了一组五个产品 ID。这些产品 ID 是根据经验丰富的销售人员的推荐和常识进行硬编码的,没有花哨的算法。

这个故事的寓意是,您可能希望专注于您的 IDE 的最终用户只会看到大约十个推荐的事实,所以也许您应该想出一些导致“相当不错”的规则十大潜在变量列表:采用一些基本的语法规则,然后根据代码中的接近度、每个变量的频率等等进行预测。然后你可以把它放在床上,专注于你的 IDE 中更重要的部分。

于 2012-06-15T21:16:17.353 回答