解析插件结构

上一节中,你已经能够自己创建一个基础的插件了,但是在面纱之下,它究竟是怎么运作的呢?

Hello World插件包含了3个部分:

理解下面三个关键概念你才能作出一个基本的插件:

大体上,你的插件就是通过组合发布内容配置和VS Code API扩展VS Code的功能。你能在插件功能概述主题中找到合适你插件的配置点和VS Code API。

好了,现在让我们自己瞧一瞧Hello World示例的源码部分,以及我们上面提到的3个概念是如何应用其中的。

插件目录结构


  1. .
  2. ├── .vscode
  3. ├── launch.json // 插件加载和调试的配置
  4. └── tasks.json // 配置TypeScript编译任务
  5. ├── .gitignore // 忽略构建输出和node_modules文件
  6. ├── README.md // 一个友好的插件文档
  7. ├── src
  8. └── extension.ts // 插件源代码
  9. ├── package.json // 插件配置清单
  10. ├── tsconfig.json // TypeScript配置

下面的几个文件超出了本节讨论的范围,你可以自行前往相应的章节挖掘详细内容:

  • launch.json 用于配置VS Code 调试
  • tasks.json 用于定义VS Code 任务
  • tsconfig.json 参阅TypeScript Handbook

现在,让我们把精力集中在这个插件的关键部分——package.jsonextensions.ts

插件清单

每个VS Code插件都必须包含一个package.json,它就是插件的配置清单package.json混合了Node.js字段,如:scriptsdependencies,还加入了一些VS Code独有的字段,如:publisheractivationEventscontributes等。关于这些VS Code字段说明都在插件清单参考中可以找到。我们在本节介绍一些非常重要的字段:

  • namepublisher: VS Code 使用<publisher>.<name>作为一个插件的ID。你可以这么理解,Hello World 例子的 ID 就是vscode-samples.helloworld-sample。VS Code 使用 ID 来区分各个不同的插件。
  • main: 插件的主入口。
  • activationEventscontributes: 激活事件 and 发布内容配置
  • engines.vscode: 描述了这个插件依赖的最低VS Code API版本。
  • postinstall 脚本: 如果你的engines.vscode声明的是1.25版的VS Code API,那它就会按照这个声明去安装目标版本。一旦vscode.d.ts文件存在于node_modules/vscode/vscode.d.ts,IntelliSense就会开始运作,你就可以对所有VS Code API进行定义跳转或者语法检查了。
  1. {
  2. "name": "helloworld-sample",
  3. "displayName": "helloworld-sample",
  4. "description": "HelloWorld example for VS Code",
  5. "version": "0.0.1",
  6. "publisher": "vscode-samples",
  7. "repository": "https://github.com/Microsoft/vscode-extension-samples/helloworld-sample",
  8. "engines": {
  9. "vscode": "^1.25.0"
  10. },
  11. "categories": ["Other"],
  12. "activationEvents": ["onCommand:extension.helloWorld"],
  13. "main": "./out/extension.js",
  14. "contributes": {
  15. "commands": [
  16. {
  17. "command": "extension.helloWorld",
  18. "title": "Hello World"
  19. }
  20. ]
  21. },
  22. "scripts": {
  23. "vscode:prepublish": "npm run compile",
  24. "compile": "tsc -p ./",
  25. "watch": "tsc -watch -p ./",
  26. "postinstall": "node ./node_modules/vscode/bin/install"
  27. },
  28. "devDependencies": {
  29. "@types/node": "^8.10.25",
  30. "tslint": "^5.11.0",
  31. "typescript": "^2.6.1",
  32. "vscode": "^1.1.22"
  33. }
  34. }

插件入口文件


插件入口文件会导出两个函数,activatedeactivate,你注册的激活事件被触发之时执行activatedeactivate则提供了插件关闭前执行清理工作的机会。

vscode模块包含了一个位于node ./node_modules/vscode/bin/install的脚本,这个脚本会拉取package.jsonengines.vscode字段定义的VS Code API。这个脚本执行过后,你就得到了智能代码提示,定义跳转等TS特性了。

  1. // 'vscode'模块包含了VS Code extensibility API
  2. // 按下述方式导入这个模块
  3. import * as vscode from 'vscode';
  4. // 一旦你的插件激活,vscode会立刻调用下述方法
  5. export function activate(context: vscode.ExtensionContext) {
  6. // 用console输出诊断信息(console.log)和错误(console.error)
  7. // 下面的代码只会在你的插件激活时执行一次
  8. console.log('Congratulations, your extension "my-first-extension" is now active!');
  9. // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法
  10. // registerCommand中的参数必须与package.json中的command保持一致
  11. let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
  12. // 把你的代码写在这里,每次命令执行时都会调用这里的代码
  13. // ...
  14. // 给用户显示一个消息提示
  15. vscode.window.showInformationMessage('Hello World!');
  16. });
  17. context.subscriptions.push(disposable);
  18. }