vscode 如何实现插件化

58 阅读2分钟

vscode 如何实现插件化

内核代码本身也采用扩展机制: Contrib

可以看到 /src/vs/workbench/contrib 这个目录下存放着非常多的 VSCode 的小的功能单元:

├── backup
├── callHierarchy
├── cli
├── codeActions
├── codeEditor
├── comments
├── configExporter
├── customEditor
├── debug
├── emmet
├── watermark
├── webview
└── welcome

Contrib 有一些特点:
  1. Contrib 目录下的所有代码不允许依赖任何本文件夹之外的文件
  2. Contrib 主要是使用 Core 暴露的一些扩展点来做事情
  3. 每一个 Contrib 如果要对外暴露,将API 在一个出口文件里面导出 eg: contrib/search/common/search.ts
  4. 一个 Contrib 如果要和另一个 Contrib 发生调用,不允许使用除了出口 API 文件之外的其它文件
  5. 接上一条,即使 Contrib 事实上可以调用另一个 Contrib 的出口 API,也要审慎的考虑并尽量避免两个 Contrib 互相依赖

extension 每一个都是运行在归宿于自己的独立宿主进程,而 contrib 的功能基本是要运行在主进程的 extension 只能依附于 core 开放的扩展点而活,但是 contrib 可以通过依赖注入拿到所有 core 内部实现的 class

extension需要提供的接口有

  1. command注册 vscode.commands API
export namespace commands {}
  1. 配置化 Contribute configuration

getConfiguration

{
  "contributes": {
    "configuration": {}
  }
}
  1. Keybinding(键盘事件) An extension can add custom keybindings.
{
  "contributes": {
    "keybindings": [
      {
        "command": "extension.sayHello",
        "key": "ctrl+f1",
        "mac": "cmd+f1",
        "when": "editorTextFocus"
      }
    ]
  }
}
  1. 右键菜单(Context Menu)
{
  "contributes": {
    "menus": {
      "editor/title": [
        {
          "when": "resourceLangId == markdown",
          "command": "markdown.showPreview",
          "alt": "markdown.showPreviewToSide",
          "group": "navigation"
        }
      ]
    }
  }
}

  1. Data Storage 数据存储 readonly globalStorageUri: Uri; ExtensionContext.storagePath
{
  "contributes": {
    "menus": {
      "editor/title": [
        {
          "when": "resourceLangId == markdown",
          "command": "markdown.showPreview",
          "alt": "markdown.showPreviewToSide",
          "group": "navigation"
        }
      ]
    }
  }
}
  1. Display Notifications 告示
window.showInformationMessage();
  1. Declarative Language Features (通用语言方案) Declarative Language Features adds basic text editing support for a programming language such as bracket matching, auto-indentation and syntax highlighting. 可以支持自动换行,语法高亮,括号匹配。
languages.registerHoverProvider('javascript', {});

  1. Programmatic Language Features (编程语言特性) Programmatic Language Features add rich programming language support such as Hovers, Go to Definition, diagnostic errors, IntelliSense and CodeLens.

  2. 插件激活事件 Activation Events is a set of JSON declarations that you make in the activationEvents field of package.json Extension Manifest.

export function activate(context: vscode.ExtensionContext) {}
	"activationEvents": [
		"onCommand:helloworld.helloWorld"
	],
  1. 插件的加载

注册插件的Action vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts

electron版本中注册 插件 vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts install

elctron中通过IPC的形式注册到另外一个独立宿主进程中

其web版本并没有实现,所以其加载过程没有参考性。

  1. 插件的销毁
this.uninstallingExtensions.forEach(promise => promise.cancel());

现在sheet提供的插件功能:

  1. 插件懒加载
this.serviceCollection.createLoader();
  1. 调用插件destory方法
this.app.serviceCollection.destroyItializedService();