Detailed plug-in mechanism _VSCode plug-in development notes 1

1. Expandability
VS Code plug-in is not suitable for UI customization, such as Atom's tool-bar is difficult to implement in VS Code:

Detailed plug-in mechanism _VSCode plug-in development notes 1

Provides a rich extensibility model, but does not allow plugins to directly access the underlying UI DOM (that is, it is difficult for plugins to change the appearance of the IDE, and UI customization is limited). This is for the convenience of continuous optimization at the bottom:


With VS Code, we’re continually trying to optimize use of the underlying web technologies to deliver an always available, highly responsive editor and we will continue to tune our use of the DOM as these technologies and our product evolve.

The UI DOM layer may change frequently with optimization. VS Code does not want these optimization items to be limited by plug-in dependencies, so simply limit the UI customization capabilities

In addition to UI customization, IDE-related functional features support extensions, such as basic syntax highlighting/API prompt, reference jump (go to definition)/file search, theme customization, advanced debug protocol, etc.

PS In fact, there is a way to extend the UI (to escape the plug-in runtime environment, but it takes a lot of effort), see access electron API from vscode extension for details, follow-up notes will introduce in detail

2. Operating environment
For performance and compatibility, the plug-in runs in a separate process (called the extension host process) and does not allow direct access to the DOM, so it provides a set of built-in UI components, such as IntelliSense

Therefore, the plug-in crash or unresponsiveness does not affect the normal operation of the IDE, for example:


// ref: my-extension/src/extension.ts
export function activate(context: vscode.ExtensionContext) {
  // hang up
  while (true);
}

The infinite loop of a plug-in does not affect the normal use of the IDE and the loading/activation of other plug-ins, but in the process list, you can see that the CPU occupancy of Code Helper is close to 100%. The process-level sandbox ensures the stability of the plug-in mechanism

3. The
stability of the core concept : plug-in isolation
plug-ins may affect the startup performance and the stability of the IDE itself, so this problem is solved through process isolation. The plug-ins run in independent processes and do not affect the IDE and its startup time.

This is considered from the user’s point of view, and it is hoped that the user has complete control over the IDE. No matter what the plug-in is doing, it will not affect the normal use of the basic functions of the IDE.

PSextension host process is a special Node process that can access the VS Code extension API. VS Code also provides debug support for this process

Performance: Plug-in activation
Plug-ins are lazy loading (as late as possible), only loaded/activated in specific scenes, so it does not consume memory and other resources before then

The implementation is that the plug-in registers specific activation events (activation events), which are triggered by the IDE. For example, the markdown plug-in only needs to be activated when the user opens the md file.


There are 6 activation methods for the plugin:

onLanguage:${language} Open documents in a specific language
onCommand:${command} Execute specific commands through Command Palette
onDebug enter debugging mode
workspaceContains:${toplevelfilename} The opened folder contains specific files
onView:${viewId} Expand the specified view

  • Open the IDE to activate,
    except for "activationEvents": ["*"]. All are conditional activations. Plug-ins are loaded/activated only in specific scenarios or when certain conditions are met.

Plug-in manifest file The
manifest file is used to describe the meta information of the plug-in. It directly uses package.json as the manifest file and adds some unique fields, such as activation events that trigger the plug-in loading, and the extension points that the plug-in wants to enhance (contribution). points)

The IDE scans the plug-in manifest file during the startup process. If the UI is related, the UI is extended, and if the UI is not relevant, the extension point is associated with the plug-in function.

In addition, since the execution environment of the plugin is the Node process, the npm package is available, and the dependent modules are also declared in package.json. Note that the user will not automatically npm install when installing the plug-in, so the dependent modules need to be packaged before the plug-in is released, see Installation and Packaging for details

The PS extension point is similar to the Join point in AOP, that is "allowed to extend/enhance here". For example, adding a custom command is an enhancement to the commands extension point


manifest
// package.json
{
  // 插件名称
  "name": "my-extension",
  // 显示名称
  "displayName": "MyExtension",
  // 描述信息
  "description": "An awesome vscode  extension",
  // 版本号 semver格式
  "version": "0.0.1",
  // 在插件市场展示的图标
  "icon": "img/icon.png",
  // 发布者名字
  "publisher": "ayqy",
  // vscode版本要求
  "engines": {
    "vscode": "^1.19.0"
  },
  // 所属分类,可选Languages, Snippets, Linters, Themes等等
  "categories": ["Other"],
  // 加载/激活方式
  "activationEvents": ["onLanguage:javascript"],
  // 入口文件路径
  "main": "./out/extension",
  // 注册扩展点关联
  "contributes": {
    "languages": [
      {
        "id": "javascript",
        "aliases": ["JavaScript", "javascript"],
        "extensions": [".js"]
      }
    ]
  }
}

For the complete PS, see Extension Manifest File – package.json

extension.ts/activate is triggered only once, and is triggered according to the activationEvents declared in package.json. The trigger condition can be to open a file in a specific language or execute a specific command. After activation, extension.ts/deactivate will not be triggered until the IDE is closed/crashed, so the general usage is:

activate: The plug-in is activated, and the function module singleton is initialized (executed only once)

deactivate: IDE is about to close, clean up the scene, but it is not suitable to do too time-consuming operations, because it is said that only wait for 10s at most

Extension points
are the supported extension types, which are declared under package.json/contributes, including:

configuration plug-in configuration items, users can set
configurationDefaults plug-in configuration item default values through Settings
commands add commands, users can enter specific commands through the Command Palette to activate the plug-in function
menus add menu items associated with commands, the user clicks on the menu item to execute the corresponding command
keybindings add The shortcut key associated with the command. When the user presses a specific shortcut key, the corresponding command
languages are executed to associate with the file type or expand a new language. When the user opens a specific file type (which meets certain requirements), the corresponding command is executed.
debuggers Add debugger, through VS Code debug protocol and IDE communication
breakpoints Cooperate with debuggers, declare that the debugger supports (programming) language type
grammars Add TextMate syntax description, syntax highlighting
themes Add custom theme
snippets Add code snippet
jsonValidation Add json format verification
views Add left file Viewer view and debug view are divided into
problemMatchers to add error matching, and
errorPatterns such as error and warning are parsed from lint results. With problemMatchers, defining the matching mode
menus is the only official way to extend the UI. The menus that support extensions are as follows:

Command Palette search box bottom menu commandPalette
file viewer right-click menu explorer/context
editor
right-click menu editor/context
title bar menu editor/title
title bar right-click menu editor/title/context
debug view
call stack right-click menu debug/callstack/context
SCM ( Source code management) view
title bar menu scm/title
file grouping menu scm/resourceGroup/context
file status menu scm/resource/context
file change menu scm/change/title
left view
file viewer sub-column view/title
debugging view sub-column view /item/context
P.S. are all inconspicuous locations, drastic UI customization is not supported, for example, it is impossible to add an Icon to the left sidebar (Activity Bar)

The menu extension on the title bar supports custom icons, but the definition is strange, for example:


"commands": [{
  "command": "markdown.showPreviewToSide",
  "title": "%markdown.previewSide.title%",
  "category": "Markdown",
  "icon": {
    "light": "./media/PreviewOnRightPane_16x.svg",
    "dark": "./media/PreviewOnRightPane_16x_dark.svg"
  }
}],
"menus": {
        "editor/title": [
            {
                "command": "markdown.showPreviewToSide",
                "when": "editorLangId == markdown",
                "alt": "markdown.showPreview",
                "group": "navigation"
            }
  ]
}

Define the icon for the command, the menu is associated with the command, and then the menu displays the corresponding icon


Isolation of the extended API environment makes it much easier to strictly restrict the APIs available to plugins. Plug-ins can only access the extensible APIs provided by the IDE and cannot mess around (such as modifying the UI DOM and style, except for the officially supported theme customization items)

API design principles
plug-in API follows some principles:

Based on Promise: Asynchronous operations are all described by Promise

Cancellation token: Pass in CancellationToken as an additional parameter to check the cancellation status and receive cancellation notifications

Releasable resource management: All resources held need to be released manually, such as event monitoring, commands, UI interaction, etc.

Event API: call the subscription method (on[Will|Did]VerbNoun), pass in the listener (receive event parameters), and return Disposable

Strict null check: Strictly distinguish between undefined and null through TypeScript

PS For more information on "Disposable", please see Dispose pattern

API overview
API is organized by namespace, the global namespace is as follows:

commands Execution/registration commands, both IDE's own and other plug-in registration commands, such as executeCommand
debug debugging related APIs, such as startDebugging
env IDE related environment information, such as machineId, sessionId
extensions, cross-plugin API calls, extensionDependency declares that the plug-in depends on
languages ​​programming Language-related APIs, such as createDiagnosticCollection, registerDocumentFormattingEditProvider
scm, source code version control APIs, such as createSourceControl
window editor window-related APIs, such as onDidChangeTextEditorSelection, createTerminal, showTextDocument
workspace Workspace-level APIs (working space is available only when a folder is opened), such as findFiles, openTextDocument , saveAll, for
example, can implement Haste's global module reference jump support through workspace.findFiles + languages.registerDefinitionProvider

In addition, some APIs are provided in the form of commands (the "IDE's own" commands mentioned above), such as vscode.previewHtml, vscode.openFolder, editorScroll, etc.

The protocol-based extension
plug-in process communicates with the IDE through a specific protocol. The implementation is stdin/stdout in JSON format.

The more powerful point of this model is that the plug-in can be implemented in any language, as long as the agreed communication protocol is complied with.

4. Language-related extensions
support syntax highlighting, code snippets and smart bracket matching through configuration files, and more complex ones are done through extended API or language server

Configuration type extended
syntax highlighting: basic support for distinguishing grammatical roles such as strings, comments, keywords, and advanced support for semantic distinctions such as variable and function references

Code snippet: quick input of snippets, basic support for simple placeholders, advanced support for nested placeholders

Smart bracket matching: advanced support for automatically supplementing things that appear in pairs, such as brackets, quotation marks, cross-line comments, etc.

Note that the language extension VS Code supports the standard Text Mate Grammar (tmLanguage format). For example, the non-mainstream Monarch-style of Monaco Editor is much more friendly. See Colorization Clarification for details.

Programmatic extensions
that cannot be easily configured are achieved through extension APIs (write plug-ins). There are two ways:

Realize communication between language server protocol and IDE, completely independent

Register Provider to provide custom capabilities, similar to hooks

In use, the first is troublesome but more powerful and flexible, and the second is convenient and direct but not so flexible. The supported expansion capabilities are as follows:

Hover tips: basic support type, document and other information, advanced support method signature syntax highlighting

Completion tips: Advanced support displays additional information next to the completion tips

Check error: basic support for checking and reporting errors for the content of the opened file when saving, advanced support for checking and reporting errors for any resource in the opened file directory

Method signature: Basic support includes parameter description documents in the method signature

Jump to definition: Basic support shows when there are multiple definitions

Reference search: Basic support returns the specific location of all references

Select search highlight: Basic support returns all the same references in the current document

Method/variable declaration directory: Basic support returns all the identifiers declared in the document and their definition locations

Quick fix: Suggestions for Warning and Error, quick fix. Basic support for error correction actions, advanced support for modifying source code, such as repetitive code to propose functions

Contextual operation options: Allows to provide additional information and operational options based on the user's code context. Basic support display, advanced can add custom commands

Rename: Basic does not support renaming by reference, advanced support cross-file renaming in workspace

Code formatting: basic does not support code formatting, advanced support full text/selected/formatted in input

V. Development step
environment requirements
VS Code

Yeoman and Yo Code – Extension Generator: npm install -g yo generator-code to get it done in one step

Steps
to generate project templates through scaffolding:

The yo code
command interactively selects the plug-in type:


New Extension (TypeScript)
New Extension (JavaScript)
New Color Theme
New Language Support
New Code Snippets
New Extension Pack

TypeScript is recommended, the others are literal, among which Extension Pack (plug-in pack) is more interesting, that is, plug-ins assembled into plug-ins, similar to Nuclide of React Native

Enter the plug-in name and other meta information to get a plug-in project, and then use VS Code to open the project alone (the workspace cannot have other project directories), F5 starts debug to enter the plug-in debugging

The plug-in entry file is my-extension/src/extension.ts, the project structure specification can refer to the VS Code built-in plug-in:


// ref: https://github.com/Microsoft/vscode/tree/master/extensions/markdown
markdown/
  media/
    *.svg
    *.css
  snippets/
    markdown.json
  syntaxes/
    *.tmLanguage
  src/
    features/
      *Provider.ts
    typings/
      *.d.ts
    commandManager.ts
    commands.ts
    logger.ts
    markdownEngine.ts
    security.ts
    telemetryReporter.ts

Six. Package release
provides CLI tools, vsce:


Pack npm install -g vsce
into the plug-in directory and pack it into a .vsix file:


cd my-extension
vsce package

You will get a local package of my-extesion.vsix (including node_modules dependencies), and then if you don’t want to make it public, you can find a way to spread the installation yourself, because unlike the npm registry, you can manually deploy a copy and put private plugins in the intranet environment, Visual Studio Marketplace (VS Code plug-in market) There is no such open mind:


If you want to share your extension with others privately, you can send them your packaged extension .vsix file.

(见Sharing Privately with Others)

There is no way to deploy a set of Visual Studio Marketplace, so I can only find a way to manually solve the plug-in update problem, such as automatic download/prompt to install

Publish
To publish the plugin market, it needs to do several things:

Register a Visual Studio Team Services account

Go to the Security page to create a Personal Access Token

vsce create-publisher (publisher name) command to add publisher

vsce login (publisher name) command login

vsce publish -p <token> command to publish

See Publishing Extensions for details

Reference
Extending Visual Studio Code

Guess you like

Origin blog.51cto.com/15080030/2592713