扩展剖析(Extension Anatomy)
在上一个主题中,你已经可以让一个基本的扩展运行。它是如何在引擎下工作的呢?
Hello World
扩展有做了3 件事:
使用
onCommand
来注册 Activation Event(激活事件):onCommand:helloworld.helloWorld
因此当用户运行命令时,Hello World
扩展将被激活。使用
contributes.commands
Contribution Point(贡献点)使Hello World
命令在命令面板中可用,并将命令绑定到 IDhelloworld.helloWorld
上。使用
commands.registerCommand
VS Code API 将一个功能绑定到已注册的命令 IDhelloworld.helloWorld
上。
理解这三个概念对于在vscode 中编写扩展至关重要:
- Activation Event:使你的扩展变得活跃的事件。
- Contribution Points:你在扩展清单
package.json
中为扩展vscode而做出的静态声明。 - VS Code API:JavaScript API,你可以在你写的扩展代码中调用。
一般来说,您的扩展将使用Contribution Points和 vscode API 的组合来扩展 vscode的功能。扩展功能概述主题可帮助你找到正确的Contribution Point和 vscode API 。
让我们仔细查看 Hello World
样例的源代码,从中理解上述概念。
扩展文件结构
.
├── .vscode
│ ├── launch.json // Config for launching and debugging the extension
│ └── tasks.json // Config for build task that compiles TypeScript
├── .gitignore // Ignore build output and node_modules
├── README.md // Readable description of your extension's functionality
├── src
│ └── extension.ts // Extension source code
├── package.json // Extension manifest
├── tsconfig.json // TypeScript configuration
你可以阅读更多有关配置文件的资料:
然而,让我们专注于package.json
和extension.ts
这两个文件,这是理解 Hello World
扩展的关键!
(扩展清单)Extension Manifest
每个 vscode扩展都必须有一个 package.json
文件作为 扩展清单。package.json
文件中包含了一系列Node.js 中的字段,比如 scripts
和devDependencies
,也包含了vscode特有的字段,比如publisher
,activationEvents
和contributes
。您可以在扩展清单参考中找到所有有关vscode特定字段的描述。以下是一些最重要的字段:
name
和publisher
: vscode使用<publisher>.<name>
作为每个扩展的独一无二的ID。举个例子:Hello World
扩展有IDvscode-samples.helloworld-sample
。vscode使用ID来唯一识别你的插件。main
: 扩展的入口文件。activationEvents
和contributes
:激活事件和贡献点。engines.vscode
: 这指定了扩展所依赖的 vscode API 的最低版本。
{
"name": "helloworld-sample",
"displayName": "helloworld-sample",
"description": "HelloWorld example for VS Code",
"version": "0.0.1",
"publisher": "vscode-samples",
"repository": "https://github.com/microsoft/vscode-extension-samples/helloworld-sample",
"engines": {
"vscode": "^1.51.0"
},
"categories": ["Other"],
"activationEvents": ["onCommand:helloworld.helloWorld"],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "helloworld.helloWorld",
"title": "Hello World"
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./"
},
"devDependencies": {
"@types/node": "^8.10.25",
"@types/vscode": "^1.51.0",
"tslint": "^5.16.0",
"typescript": "^3.4.5"
}
}
扩展入口文件(Extension Entry File)
扩展入口文件会导出两个函数,activate
和deactivate
。 当你注册的Activation Event发生时会执行activate
。 deactivate
则让你在扩展停用之前,有机会进行一些清理工作。对于许多扩展,显式的清理工作不是必要的,因此,可以移除deactivate
这个函数。但是,如果扩展需要在vscode关闭,扩展被禁用或卸载执行操作,则这个方法会助你一臂之力。
vscode扩展 API 在@types/vscode类型定义中声明。vscode
类型定义的版本由package.json
中的字段exgines.vscode
的值来控制。vscode
类型为您提供了自动补全、查看定义以及其他TypeScript特色功能。
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "helloworld-sample" is now active!');
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World!');
});
context.subscriptions.push(disposable);
}
// this method is called when your extension is deactivated
export function deactivate() {}