VSCode插件开发指南

只是一篇干货满满的介绍vscode插件开发的文章,先收藏再观看效果更佳。
vscode 提供了哪些开放能力?
从 vscode 的官网中我们可以看到,vscode 主要提供了六类开放能力:通用能力、主题、声明类语言特性(我把它称为基础支持)、程序类语言特性(高级支持)、工作区UI扩展、调试。我们开发 vscode 插件,实际上就是在通过这些能力对 vscode 进行扩展。这六类能力具体包括的功能和使用场景可以看下图。
"1"

如何编写一个 vscode 插件呢?
vscode 插件的形态和一个 npm 包非常相似,需要在项目的根目录添加 package.json,并且在其中增加一些 vscode 独家的设置。其中最主要的设置是 Activation Events(插件的激活时机) 和 contribution points (插件的能力)。接下来我们主要看看这两个配置具体是什么意思。

声明插件的激活时机 Activation Events
我将 vscode 的生命周期简单描述为下图。下面会做进一步解释。

"2"

activate() 函数 & deactivate() 函数
可以看到生命周期中最终要的两个节点就是activate函数和deactivate函数。这两个函数需要在插件 npm 模块的入口文件 export 出去给 vscode 主动调用。
其中,activate 会在 vscode 认为合适的时机调用,并且在插件的运行周期内只调用一次。因此在 activate 函数中开始启动插件的逻辑,是一个非常合适的时机。
deactivate 函数会在插件卸载之前调用,如果你的卸载逻辑中存在异步操作,那么只需要在deactivate 函数中 retuen 一个 promise 对象,vscode 会在 promise resolve 时才正式将插件卸载掉。

onXxxx Activation Events
可以看到在activate函数之前,还有onLanguage等事件的描述,实际上这些就是声明在插件 package.json 文件中的 Activation Events。声明这些 Activation Events 后,vscode 就会在适当的时机回调插件中的 activate函数。vscode之所以这么设计,是为了节省资源开销,只在必要的时候才激活你的插件。当然,如果你的插件非常重要,不希望在某个事件之后才被激活,你可以声明Activation Events为*这样 vscode 就会在启动的时候就开始回调 activate 函数。

插件的具体逻辑插件中的具体逻辑 vscode 没有做任何限制,你可以通过调用vscdoe提供的各种 api 对其进行扩充。不过需要注意的是,出于性能和移植性考虑,vscode不允许开发者直接操作dom。关于 vscode 的 api 可以参考 https://code.visualstudio.com/api/references/vscode-api 这是微软根据 vscode 的 d.ts 文件生成的文档。

举个例子
接下来我们来看几个插件的 Activation Events 声明

  • 超越鼓励师 申明了 onCommand:ycy.showReminderView 和 * ,其实我们都知道只声明后一个就足够了
  • vuter 申明了 onLanguage:vue 所以他会在用户打开 vue 语言文件时被激活
  • vscode-icons 是一个纯主题插件,声明的是 *GitLens 需要覆盖所有的文件,并且在vscode启动时就需要激活,他的声明是 *

关于 Activation Events 的说明可以参考官方文档 https://code.visualstudio.com/api/references/activation-events

声明插件的贡献点 contribution points
需要在 package.json 中声明的另一个重要字段就是 contribution points。 contribution points描述了当前插件支持哪些能力,以及对应能力的配置。

由于 vscode 禁止直接操作dom,往 UI 中插入功能的正确方式是声明贡献点。下图列出了 vscode 支持的所有贡献点。

"3"

举个例子
接下来我们来看几个插件的 contribution points 声明

  • 超越鼓励师 支持通过 commands 触发杨超越的提醒,同时可以配置提醒出现的时机,因此包括 commands / configuration
  • vuter 主要为 vue 文件提供语言支持,可以看到他提供的 contribution points 比较广,包括 commands / breakpoints / languages / grammars / configuration
  • vscode-icons 已支持主题为主,他提供了 iconThemes / commands / configurationGitLens 是对vscode git 功能的增强,所以他的插入点集中在 UI 上的能力 configuration / commands / menus /resourceLabelFormatters / viewsContainers / views

关于 contribution points 的更多说明可以参考 https://code.visualstudio.com/api/references/contribution-points

编程语言支持
那么,要怎么给 vscode 增加一门新的编程语言支持呢?就像之前说的,vscode 主要支持两类编程语言支持: 声明类语言特性主要描述了代码高亮、代码片段等轻量级需要实时给出响应的语言特性支持;而程序类语言特性只要提供更加高级的跳到定义、查找引用、hover提示等对实时性要求不高,而且需要大量计算的语言能力。因此前者更加适合在 IDE 的主线程进行处理,而后者可以考虑拆分到其他线程甚至服务中进行计算。

声明类语言特性(基本支持)

下面主要以语法高亮为例子介绍声明式语言支持。

"4"

在最初,微软的工程师们为web开发中常见的开发语言都手写了 paser。这类 paser 执行效率很高,但对开发者的能力要求也比较高,不太适合未来的插件扩展。从 vscode 1.8 版本开始,微软引入了 TextMate 的高亮语法,并逐步将原有的手写 paser 切换到这种语法上。

"5"

TextMate 本身是 mac 下的一个文本编辑器,vscode 借用了他对语言高亮文本的定义方式。TextMate语法的本质是用一个 json 文件来描述语言中的 token 和结构,当然为了方便,也可以改用 YAML 并编译成json。

顺便一提,而 TextMate 语法使用的是 oniguruma 库来解析正则表达式,oniguruma 中支持一些 js 引擎目前还不支持的正则特性,因此在 vscode 中使用了一个 oniguruma 的 c++ 模块来加速正则表达式解析速度。

另外,为了方便开发者编写语法高亮插件,vscode还提供了一个 yomen 模板用于生成插件基本目录结构,以及一个名为 inspectTMScopes 的调试器查看词法分析的结果。

"6"
"7"

除了语法高亮外,vscode还支持这些特性:注释切换、括号定义、自动闭合、Auto surrounding、代码折叠、word Pattern、缩进规则等,详见 https://code.visualstudio.com/api/language-extensions/language-configuration-guide

程序类语言特性(高级能力)
对于高级的语言能力支持,vscode 提供了两种方式:
方案一:注册 vscode 提供的回调钩子
方案二:使用 language server

"8"

这两种方式提供的能力是完全相同的,而微软主推方案二,因此下面主要对方案二展开介绍。

language server protocol(LSP)

首先 language server 是一种跨编辑器的语言支持实现规范。它由微软提出,目前 vscode 、vim、atom 都已经支持了这个规范。

"9"

在过去,每个IDE遇到一门全新的语言,往往都需要重新实现一次基本功能,对于流行的语言来说还好,因为 IDE 厂商都有动力提供支持。然后对于一门全新的语言,往往需要语言的发明人自己实现各种 IDE 的语言支持。由于各个IDE的接口不同,需要将语言支持在各个IDE中重新移植一遍。

有了 LSP 规范后,语言支持插件开发者只需要编写一次,就可以很快地在 IDE 之间移植代码。

"10"

实现一个LSP,只需要在后台开启一个接受LSP请求的 server,并实现 LSP 规范中的接口(往往是通过 JSON RPC进行调用的)即可。
关于 LSP 可以从这两篇文档中找到更加详细的介绍

至此,我们对 vscode 插件中的主要知识点进行了学习,相信看到这里的小伙伴已经收获满满了吧

还不过瘾?
出门左转vscode插件开发官方文档吧~

https://code.visualstudio.com/api