vscode 如何实现插件化
内核代码本身也采用扩展机制: Contrib
可以看到 /src/vs/workbench/contrib 这个目录下存放着非常多的 VSCode 的小的功能单元:
├── backup
├── callHierarchy
├── cli
├── codeActions
├── codeEditor
├── comments
├── configExporter
├── customEditor
├── debug
├── emmet
├── watermark
├── webview
└── welcome
Contrib 有一些特点:
- Contrib 目录下的所有代码不允许依赖任何本文件夹之外的文件
- Contrib 主要是使用 Core 暴露的一些扩展点来做事情
- 每一个 Contrib 如果要对外暴露,将API 在一个出口文件里面导出 eg: contrib/search/common/search.ts
- 一个 Contrib 如果要和另一个 Contrib 发生调用,不允许使用除了出口 API 文件之外的其它文件
- 接上一条,即使 Contrib 事实上可以调用另一个 Contrib 的出口 API,也要审慎的考虑并尽量避免两个 Contrib 互相依赖
extension 每一个都是运行在归宿于自己的独立宿主进程,而 contrib 的功能基本是要运行在主进程的 extension 只能依附于 core 开放的扩展点而活,但是 contrib 可以通过依赖注入拿到所有 core 内部实现的 class
extension需要提供的接口有
- command注册 vscode.commands API
export namespace commands {}
- 配置化 Contribute configuration
getConfiguration
{
"contributes": {
"configuration": {}
}
}
- Keybinding(键盘事件) An extension can add custom keybindings.
{
"contributes": {
"keybindings": [
{
"command": "extension.sayHello",
"key": "ctrl+f1",
"mac": "cmd+f1",
"when": "editorTextFocus"
}
]
}
}
- 右键菜单(Context Menu)
{
"contributes": {
"menus": {
"editor/title": [
{
"when": "resourceLangId == markdown",
"command": "markdown.showPreview",
"alt": "markdown.showPreviewToSide",
"group": "navigation"
}
]
}
}
}
- Data Storage 数据存储 readonly globalStorageUri: Uri; ExtensionContext.storagePath
{
"contributes": {
"menus": {
"editor/title": [
{
"when": "resourceLangId == markdown",
"command": "markdown.showPreview",
"alt": "markdown.showPreviewToSide",
"group": "navigation"
}
]
}
}
}
- Display Notifications 告示
window.showInformationMessage();
- 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', {});
-
Programmatic Language Features (编程语言特性) Programmatic Language Features add rich programming language support such as Hovers, Go to Definition, diagnostic errors, IntelliSense and CodeLens.
-
插件激活事件 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"
],
- 插件的加载
注册插件的Action vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
electron版本中注册 插件 vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts install
elctron中通过IPC的形式注册到另外一个独立宿主进程中
其web版本并没有实现,所以其加载过程没有参考性。
- 插件的销毁
this.uninstallingExtensions.forEach(promise => promise.cancel());
现在sheet提供的插件功能:
- 插件懒加载
this.serviceCollection.createLoader();
- 调用插件destory方法
this.app.serviceCollection.destroyItializedService();