879479119.github.io icon indicating copy to clipboard operation
879479119.github.io copied to clipboard

聊一聊代码的智能提示

Open 879479119 opened this issue 5 years ago • 1 comments

代码的智能提示其实是一个在开发中会比较少碰到的问题,更多的我们是在使用编辑器的时候很自然而然的就用上了这项功能,但是也没有仔细想过其中的原理到底是什么。

笔者之前做过补全的工作,但是受限于时间和能力,选择了将hue的自动补全功能迁移到其他平台的工作,完成相关工作之后看到 黄子毅的这篇文章,也是另辟蹊径,是另一种自己从头开始做的做法。今天简单的说下自己看到hue中的自动补全是如何完成的。


基本原理

大家可以先行阅读上面那篇文章,其实是有一个比较通用的点,就是把我们光标位置设计为一个特殊字符。其实如果要自己想出这个结论的话还是需要一些时间的。

这一点为什么重要?因为我们解析的时候是要构造一个树状的结构,所以不可能把前半部分和后半部分的文本分开进行构建,在lexer处理的时候都可能出现问题,就算能够成功的解析在后续构建语法树时也有极大可能会出现结构上的问题。

相较与黄同学的从底层的解析一层层做起,我们选择的方法是使用直接的jison方案进行解析。hue的jison文件

jison本身就是js版本的bison和flex的合集,他是其在js上的一层实现,我们可以用它完成编译器的前端工作(此前端非彼前端)。

他的语法这里就不赘述了,网上有很多教程,因为我们要做的是SQL的自动补全,整体的语法还是比较简单的,主要的也就create,insert,select这几种DML,DDL。

要写出整个解析语法的解析规则还是一个体力活。在书写的过程中也要对编译原理有足够的了解,不然会收到编译器的大量警告和报错。由于解析的过程会有很多递归的操作,所以写的时候要小心自己写下的的语法规则。如果有不确定的地方可以去看看一些开源的方案的代码或者antlr等。

不过上面说的是如何生成AST,如果我们的规则不符合标准的语法结构咋办呢,比如像自动补全的情况?这时候我们可以把光标当成一个特殊符号,在每一个结构中进行独立的补全处理配置。

上面这话啥意思,我们一般的解析规则是

select a from b;

jison会把这个SQL按照这种规则进行解析(简化),得到一个树状的结构

SelectStatement
 |             \
 SelectList   FromSource
 |                 |
 SelectItem    FromItem
 |                 |
 { value: 'a' }  { value: 'b' }

如果我们是在输入过程中,那么内容很有可能就变成了

select  from b;

这样的结构,我们不知道我们的指针在哪里,解析肯定是不能成功的,并且不符合我们预先定义的语法结构,我们就需要在其中加入我们的指针位置,让他和我们的内容一起解析,在指针的位置做特殊处理。

select | from b;	

现在我们就可以进行解析了,但是是通过专门的editing的规则进行匹配。

所谓的editing规则,其实就是在我们完整的语法解析结构中加入了光标的语句,代表了我们当前正在编辑这句话。~~不过这也引出了一个点,就是在多个指针同时操作文本时可能出现问题,这是在提示时需要注意的。~~

SelectStatement_Edit
 |                    \
 SelectList_Edit   FromSource
 |                      |
 ①SelectItem_Edit    FromItem
 |                      |
 { text: '' }     { value: 'b' }

由于我们在匹配到固定结构时是可以做一些js的操作的。比如在①的位置,我们就能拿到设置一条函数在匹配到这条规则时进行执行。构建语法树时对应的可能是些转化处理,并把子节点插到一个节点上再向上传递。

对应到智能补全的时候,我们要做的就是在这个函数中添加上我们需要的补全类型和当前字段的状态了。比如在①这里,我们可以简单的设计一个函数handleColumn,通过调用handleColumn(text, position),来注册一个固定的autocomplete的逻辑,也可以异步的做一些获取库表信息的操作了。对应到hue中的代码 就是这里

至此,解析器就能够简单的针对每个位置做到一个解析并提示了。


笔者的记录比较粗糙,只是提供一种思路,如果想要看具体的实现还是建议阅读hue或者其他有代码自动提示功能项目的源代码,由于hue项目的结构组织复杂,并且现在有多个版本,前端项目并不好直接在本地跑起来,可能开发上会有些问题,只建议了解一下相关思路,有任何问题欢迎在issue下面讨论。


引用

https://github.com/dt-fe/weekly/blob/master/85.%E7%B2%BE%E8%AF%BB%E3%80%8A%E6%89%8B%E5%86%99%20SQL%20%E7%BC%96%E8%AF%91%E5%99%A8%20-%20%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E3%80%8B.md https://github.com/cloudera/hue/blob/release-4.0.0/desktop/core/src/desktop/static/desktop/js

879479119 avatar Apr 22 '19 06:04 879479119

能加个联系方式聊一下吗?

wuhaohaoflake avatar Feb 28 '23 02:02 wuhaohaoflake