:::info 🦊 这篇文档记录了 @Arno(surfacew) 研究 VSCodeExtension 的学习历程和一些技术思考。 :::

VSCode 的插件系统是我所见过的 IDE 里面生态最繁荣的了。VSCode 的作者是当年 Eclipse 的架构师,其功底绝对不浅,所以可以从 VSCode 的产品层设计到技术层设计进行学习和剖析,找到有趣的点记录在这里。

学习一个技术产品,最好的方式是先用起来,之前个人写过一个 VSCode 插件用来解决内部产品的研发体验,如今再来尝试实现一个好玩的功能包,便于给日常开发注入灵魂。便自己给自己提需求吧,Here we go ~

需求

内置支持各种花式插入「好(hua)玩(li)有(hu)趣(shao)」的代码注释,比如:

  • D1:最大分割符号(参考 Angular)
  • D2:中等分割符号
  • D3:小型分割符号
  • H1:佛祖保佑
  • H2:草泥马
  • H3:ASCII 划线图
  • H4:ASCII 表格
  • WARNING
  • TODO
  • FIXME
  • ATTENTION

CodeCommenter 需求池

实现

该项目存储在 Github 上:https://github.com/SurfaceW/arno-vscode-vcomments-ext

工程初始化

  • 仅仅几个命令非常快

    1. npm install -g yo generator-code
    2. yo code
    3. code ./helloworld
    4. npm run start
  • 随后就直接在 VSCode 里面运行起来了,很舒服。

截屏2021-09-26 下午11.18.58.png

增加 snippets

将这些 Comments 作为 Snippets 添加到 VSCode 中是第一步。根据 SnippetsGuide 文档的指引,我们编写一个 template.js 里面将常用的好玩有用的注释写入其中,然后设定分割规则,并写一个简单的解析函数,将之切割为 snippet.json ,具体请参考代码仓库里面的具体实现。最终实现下面的效果:

2021-09-27 23.35.16.gif

发布插件

  • 完善 ExtensionManifest 所依赖的发布字段。
  • 使用 Microsoft VSCE 命令行发布插件。

截屏2021-10-11 下午8.41.47.png

  • 微软开发者社区,提供了 Marketplace 来管理插件相关的生命周期,整体和 Azure 开发者连接到了一起,说白了有点牵动 MS 开发者生态的味道。

image.png
https://marketplace.visualstudio.com/items?itemName=surfacew.arno-commenter,发布之后的效果 🎉

质量提升

  • VSCode 插件给出了 AzurePipeline 以及 TravisCI 的配置,给出了 CI 的解决方案
  • VSCode 官方文档也完备地给出了 VSCode 扩展的 Test 机制,可以直接在 VSCode 内调试测试代码 👍

VSCodeExt 的设计思考

VSCode Guideline 给出了 VSCode 做扩展的最佳实践。这里面 VSCode 就常见的扩展实现类型做了一个推荐,告知用户哪些设计是推荐的,哪些设计是不符合实践的。整体来说图文并茂,DO 以及 DO NOT 界线颇为清晰。

image.png

以 👆 这张图为例,就将 VSCode 「约定俗成」的命名一次性给到了开发者,「瞬间有了体感」。又比如 Notification 的流程图整体也比较干净:

image.png

:::info ℹ️ 对于文档而言,我们必须非常用心地设计,要想发设法,图文并茂地向开发者呈递我们的设计思考。比如 DO 和 DO NOT 在设计 Guide 的时候的确广泛使用。
截屏2021-10-11 下午7.25.43.png :::

开放结构的设计

截屏2021-09-26 下午11.28.09.png
文档:这里

  • ActivationEventsActivationEvents 事件系统,激活事件的注册,用于声明当前插件需要依赖的系统事件,以便于系统做定向广播。
  • ContributionPointsContributionPoints 的设计整体类似于扩展点注册的 Manifest.json 文件。这块是 VSCode 对外抛出的核心「可扩展」、「可配置」的扩展接口,每一项配置都可以等价为一个扩展点的描述。VSCode 将可枚举的模块功能都抽离出「扩展点」并支持插件在 package.json 中显式声明关联,是典型的扩展方式。
  • VSCodeAPI:开发者可以使用的 VSCode 暴露出来的功能 API,各个模块精要抽象了核心 API,供扩展层使用。其 vscode.d.ts 颇有灵魂。

整体设计还是比较干净的,自然,易理解,符合开发的思维模式。

VSCode 主要的可扩展点

思维导图简单绘制一番:

来实现一个有灵魂的 VSCode 插件 - 图9

一些琐碎的 Tips

  • Starter 的 Doc 可以学习 VSCode 的写法,「简单干净」。
  • 大量 Provider 的模式,用于扩展 👇 VSCode 代码层 API 注册扩展实现的方式有 registerXXXProvider() 的命名规约,这种注册机制在 VSCode API 中大量使用,用于数据、服务、UI 等注入

image.png

  • VSCode 发明了一个简单的 WhenClause DSL 用于处理简单的条件表达,覆盖常规的条件判断操作,比如:

    "when": "resourceFilename =~ /docker/"
    
  • 大量的 SampleCode 提供给开发者参考,大量的开源项目亦如此:

    • 比如:vscode-search-node-modules:支持搜索本地的 node_modules
    • 比如:官方 SampleLib

VSCode 源代码的实现

源代码实现浅析:

VSCode 源代码分析 & 研究

源代码关注点:

  • VSCodeExtension Launcher 时序?看 VSCode 是如何完成扩展插件启动的?
  • WhenClause 语法是如何解析 & 如何运行的?
  • VSCode core 开放 API 是如何组织 & 管理的?
  • VSCode 整体 Event 机制?其事件的注册、广播和管理机制如何实现?
  • VSCode 有 ExtensionHost 的概念,支持 Server 和 Client 多平台模式,其代码是如何隔离实现的?
  • VSCode Language Server 是如何实现的?LanguagePack 里面最有灵魂的部分?尝试写一个简单的编程语言和编程语言背后的 LanguageServer 来玩一玩也挺有意思的 😁(比如一个批处理的 DSL,或者把 VSCode 的条件 ConditionCaluse 写出来)

小结

VSCode 的插件系统是值得单体应用做大规模扩展的时候深度借鉴的。后续个人在设计软件系统的开放扩展的时候需要更进一步,学其精粹。

参考