Vetur 插件是如何做到自动补全的
Vetur 插件 是一个 VS Code 上的 Vue 插件,提供了代码补全、高亮等功能。今天看了一下代码,记录一下 Vetur 插件是如何做到 Script 部分自动补全的。
<!—- more —->
不同区域的处理
首先说一下 Vetur 是如何对 Vue 的每一部分进行高亮的。在 Vetur 的 Language Server 中,实现了一个 LanguageModes (server/src/embeddedSupport/languageModes.ts)类:
这个 LanguageModes 类中实现了 getModeAtPosition 方法,也就是根据文档当前所处的位置,返回不同的 mode。
mode 是用于处理不同语言的一系列工具方法:
他们是在 init 中进行初始化的。比如 vue-html 处理 template 部分,javascript、typescript 处理 script 部分。
这些 mode 的主要作用其实就是识别出语言,然后调用这些语言的方法来进行高亮、补全等操作。
可以看到 javascript、typescript、tsx 都使用的同一个 jsMode,他们的内部都是使用的 TypeScript 库来实现的。
jsMode定义在 server/src/modes/script/javascript.ts 中,它有这些方法:
从名字就可以看出大部分方法的功能,其中 doComplete 方法就是用于代码补全的。
这个方法的代码是这样的,其中 service.getCompletionsAtPosition 方法就是用于获取所有补全选项的,这个 service 其实就是 TypeScript 自身,getCompletionsAtPosition 是 TypeScript 的一个 API:https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API
所以我们可以看到,Vetur 中对于 script 部分的代码补全,是依赖 TypeScript 来实现的,依赖两个工作:
- 识别这部分是 js、ts
- 有 Vue 的类型信息
extend Vue 时
我们知道 .vue 文件中的 script 其实不只有一种写法,可以这么写:
也可以这么写:
第一种写法使用了 Vue.extend 方法,那么只需要标记出 script 使用 jsMode 来处理,TypeScript 就可以根据 Vue.extend 方法来获取到类型信息,进而给出代码补全。
但是在第二种写法中,单单凭借 script 中的代码,是不能推断出类型信息的,Vetur 是如何实现的呢?
直接 export default 时的实现
在这种情况下,Vetur 会讲 script 部分的代码进行预处理,预处理代码在:server/src/services/typescriptService/preprocess.ts
这里注释写的听清楚的,经过处理后,代码实际变成了这样:
vue-editor-bridge 是 Vetur 中实现的一个工具库,目的就是给 export default 出的对象增加类型信息。
这样通过 __vueEditorBridge 增加类型信息后,TypeScript 就可以正确返回代码补全内容了。