From 413ad7aabf44eda23f0dfb607f088bbc270ebb08 Mon Sep 17 00:00:00 2001 From: Pine Date: Wed, 8 Apr 2020 13:57:53 -0700 Subject: [PATCH] VS Code 1.44.0 Extension API (#43745) * VS Code 1.44.0 Extension API * Update tslint Co-authored-by: VSCode --- types/vscode/index.d.ts | 361 +++++++++++++++++++++++++++++++++++++-- types/vscode/tslint.json | 1 + 2 files changed, 350 insertions(+), 12 deletions(-) diff --git a/types/vscode/index.d.ts b/types/vscode/index.d.ts index b9001feb44..c325dc7469 100644 --- a/types/vscode/index.d.ts +++ b/types/vscode/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Visual Studio Code 1.43 +// Type definitions for Visual Studio Code 1.44 // Project: https://github.com/microsoft/vscode // Definitions by: Visual Studio Code Team, Microsoft // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -10,7 +10,7 @@ *--------------------------------------------------------------------------------------------*/ /** - * Type Definition for Visual Studio Code 1.43 Extension API + * Type Definition for Visual Studio Code 1.44 Extension API * See https://code.visualstudio.com/api for more information */ @@ -2127,6 +2127,9 @@ declare module 'vscode' { /** * A [command](#Command) this code action executes. + * + * If this command throws an exception, VS Code displays the exception message to users in the editor at the + * current cursor position. */ command?: Command; @@ -2156,8 +2159,8 @@ declare module 'vscode' { * of code action, such as refactorings. * * - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) - * that auto applies a code action and only a disabled code actions are returned, VS Code will show the user a - * message with `reason` in the editor. + * that auto applies a code action and only a disabled code actions are returned, VS Code will show the user an + * error message with `reason` in the editor. */ disabled?: { /** @@ -3158,6 +3161,233 @@ declare module 'vscode' { prepareRename?(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; } + /** + * A semantic tokens legend contains the needed information to decipher + * the integer encoded representation of semantic tokens. + */ + export class SemanticTokensLegend { + /** + * The possible token types. + */ + public readonly tokenTypes: string[]; + /** + * The possible token modifiers. + */ + public readonly tokenModifiers: string[]; + + constructor(tokenTypes: string[], tokenModifiers?: string[]); + } + + /** + * A semantic tokens builder can help with creating a `SemanticTokens` instance + * which contains delta encoded semantic tokens. + */ + export class SemanticTokensBuilder { + + constructor(legend?: SemanticTokensLegend); + + /** + * Add another token. + * + * @param line The token start line number (absolute value). + * @param char The token start character (absolute value). + * @param length The token length in characters. + * @param tokenType The encoded token type. + * @param tokenModifiers The encoded token modifiers. + */ + push(line: number, char: number, length: number, tokenType: number, tokenModifiers?: number): void; + + /** + * Add another token. Use only when providing a legend. + * + * @param range The range of the token. Must be single-line. + * @param tokenType The token type. + * @param tokenModifiers The token modifiers. + */ + push(range: Range, tokenType: string, tokenModifiers?: string[]): void; + + /** + * Finish and create a `SemanticTokens` instance. + */ + build(resultId?: string): SemanticTokens; + } + + /** + * Represents semantic tokens, either in a range or in an entire document. + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to create an instance. + */ + export class SemanticTokens { + /** + * The result id of the tokens. + * + * This is the id that will be passed to `DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits` (if implemented). + */ + readonly resultId?: string; + /** + * The actual tokens data. + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. + */ + readonly data: Uint32Array; + + constructor(data: Uint32Array, resultId?: string); + } + + /** + * Represents edits to semantic tokens. + * @see [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. + */ + export class SemanticTokensEdits { + /** + * The result id of the tokens. + * + * This is the id that will be passed to `DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits` (if implemented). + */ + readonly resultId?: string; + /** + * The edits to the tokens data. + * All edits refer to the initial data state. + */ + readonly edits: SemanticTokensEdit[]; + + constructor(edits: SemanticTokensEdit[], resultId?: string); + } + + /** + * Represents an edit to semantic tokens. + * @see [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. + */ + export class SemanticTokensEdit { + /** + * The start offset of the edit. + */ + readonly start: number; + /** + * The count of elements to remove. + */ + readonly deleteCount: number; + /** + * The elements to insert. + */ + readonly data?: Uint32Array; + + constructor(start: number, deleteCount: number, data?: Uint32Array); + } + + /** + * The document semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ + export interface DocumentSemanticTokensProvider { + /** + * An optional event to signal that the semantic tokens from this provider have changed. + */ + onDidChangeSemanticTokens?: Event; + + /** + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. + * + * --- + * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: + * - at index `5*i` - `deltaLine`: token line number, relative to the previous token + * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line) + * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline. + * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536. + * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + * + * --- + * ### How to encode tokens + * + * Here is an example for encoding a file with 3 tokens in a uint32 array: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, + * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, + * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } + * ``` + * + * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types. + * For this example, we will choose the following legend which must be passed in when registering the provider: + * ``` + * tokenTypes: ['property', 'type', 'class'], + * tokenModifiers: ['private', 'static'] + * ``` + * + * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked + * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, + * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because + * bits 0 and 1 are set. Using this legend, the tokens now are: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token + * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` + * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the + * `startChar` of the third token will not be altered: + * ``` + * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to encode tokens as integers. + * *NOTE*: When doing edits, it is possible that multiple edits occur until VS Code decides to invoke the semantic tokens provider. + * *NOTE*: If the provider cannot temporarily compute semantic tokens, it can indicate this by throwing an error with the message 'Busy'. + */ + provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): ProviderResult; + + /** + * Instead of always returning all the tokens in a file, it is possible for a `DocumentSemanticTokensProvider` to implement + * this method (`provideDocumentSemanticTokensEdits`) and then return incremental updates to the previously provided semantic tokens. + * + * --- + * ### How tokens change when the document changes + * + * Suppose that `provideDocumentSemanticTokens` has previously returned the following semantic tokens: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * + * Also suppose that after some edits, the new semantic tokens in a file are: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + * It is possible to express these new tokens in terms of an edit applied to the previous tokens: + * ``` + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // old tokens + * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // new tokens + * + * edit: { start: 0, deleteCount: 1, data: [3] } // replace integer at offset 0 with 3 + * ``` + * + * *NOTE*: If the provider cannot compute `SemanticTokensEdits`, it can "give up" and return all the tokens in the document again. + * *NOTE*: All edits in `SemanticTokensEdits` contain indices in the old integers array, so they all refer to the previous result state. + */ + provideDocumentSemanticTokensEdits?(document: TextDocument, previousResultId: string, token: CancellationToken): ProviderResult; + } + + /** + * The document range semantic tokens provider interface defines the contract between extensions and + * semantic tokens. + */ + export interface DocumentRangeSemanticTokensProvider { + /** + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens). + */ + provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): ProviderResult; + } + /** * Value-object describing what options formatting should use. */ @@ -4986,10 +5216,14 @@ declare module 'vscode' { color: string | ThemeColor | undefined; /** - * The identifier of a command to run on click. The command must be - * [known](#commands.getCommands). + * [`Command`](#Command) or identifier of a command to run on click. + * + * The command must be [known](#commands.getCommands). + * + * Note that if this is a [`Command`](#Command) object, only the [`command`](#Command.command) and [`arguments`](#Command.arguments) + * are used by VS Code. */ - command: string | undefined; + command: string | Command | undefined; /** * Shows the entry in the status bar. @@ -6027,6 +6261,14 @@ declare module 'vscode' { * @param messageOrUri Message or uri. */ constructor(messageOrUri?: string | Uri); + + /** + * A code that identifies this error. + * + * Possible values are names of errors, like [`FileNotFound`](#FileSystemError.FileNotFound), + * or `Unknown` for unspecified errors. + */ + readonly code: string; } /** @@ -6335,7 +6577,7 @@ declare module 'vscode' { } /** - * A webview displays html content, like an iframe. + * Displays html content, similarly to an iframe. */ export interface Webview { /** @@ -6344,9 +6586,29 @@ declare module 'vscode' { options: WebviewOptions; /** - * Contents of the webview. + * HTML contents of the webview. * - * Should be a complete html document. + * This should be a complete, valid html document. Changing this property causes the webview to be reloaded. + * + * Webviews are sandboxed from normal extension process, so all communication with the webview must use + * message passing. To send a message from the extension to the webview, use [`postMessage`](#Webview.postMessage). + * To send message from the webview back to an extension, use the `acquireVsCodeApi` function inside the webview + * to get a handle to VS Code's api and then call `.postMessage()`: + * + * ```html + * + * ``` + * + * To load a resources from the workspace inside a webview, use the `[asWebviewUri](#Webview.asWebviewUri)` method + * and ensure the resource's directory is listed in [`WebviewOptions.localResourceRoots`](#WebviewOptions.localResourceRoots). + * + * Keep in mind that even though webviews are sandboxed, they still allow running scripts and loading arbitrary content, + * so extensions must follow all standard web security best practices when working with webviews. This includes + * properly sanitizing all untrusted input (including content from the workspace) and + * setting a [content security policy](https://aka.ms/vscode-api-webview-csp). */ html: string; @@ -6444,7 +6706,7 @@ declare module 'vscode' { iconPath?: Uri | { light: Uri; dark: Uri }; /** - * Webview belonging to the panel. + * [`Webview`](#Webview) belonging to the panel. */ readonly webview: Webview; @@ -6561,6 +6823,34 @@ declare module 'vscode' { deserializeWebviewPanel(webviewPanel: WebviewPanel, state: any): Thenable; } + /** + * Provider for text based custom editors. + * + * Text based custom editors use a [`TextDocument`](#TextDocument) as their data model. This considerably simplifies + * implementing a custom editor as it allows VS Code to handle many common operations such as + * undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`. + */ + export interface CustomTextEditorProvider { + + /** + * Resolve a custom editor for a given text resource. + * + * This is called when a user first opens a resource for a `CustomTextEditorProvider`, or if they reopen an + * existing editor using this `CustomTextEditorProvider`. + * + * To resolve a custom editor, the provider must fill in its initial html content and hook up all + * the event listeners it is interested it. The provider can also hold onto the `WebviewPanel` to use later, + * for example in a command. See [`WebviewPanel`](#WebviewPanel) for additional details. + * + * @param document Document for the resource to resolve. + * @param webviewPanel Webview to resolve. + * @param token A cancellation token that indicates the result is no longer needed. + * + * @return Thenable indicating that the custom editor has been resolved. + */ + resolveCustomTextEditor(document: TextDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable | void; + } + /** * The clipboard provides read and write access to the system's clipboard. */ @@ -7397,6 +7687,21 @@ declare module 'vscode' { * @param serializer Webview serializer. */ export function registerWebviewPanelSerializer(viewType: string, serializer: WebviewPanelSerializer): Disposable; + + /** + * Register a provider for custom editors for the `viewType` contributed by the `customEditors` extension point. + * + * When a custom editor is opened, VS Code fires an `onCustomEditor:viewType` activation event. Your extension + * must register a [`CustomTextEditorProvider`](#CustomTextEditorProvider) for `viewType` as part of activation. + * + * @param viewType Unique identifier for the custom editor provider. This should match the `viewType` from the + * `customEditors` contribution point. + * @param provider Provider that resolves custom editors. + * @param options Options for the provider. + * + * @return Disposable that unregisters the provider. + */ + export function registerCustomEditorProvider(viewType: string, provider: CustomTextEditorProvider, options?: { readonly webviewOptions?: WebviewPanelOptions; }): Disposable; } /** @@ -7919,7 +8224,7 @@ declare module 'vscode' { /** * The location at which progress should show. */ - location: ProgressLocation; + location: ProgressLocation | { viewId: string }; /** * A human-readable string which will be used to describe the @@ -9270,6 +9575,38 @@ declare module 'vscode' { */ export function registerRenameProvider(selector: DocumentSelector, provider: RenameProvider): Disposable; + /** + * Register a semantic tokens provider for a whole document. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document semantic tokens provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentSemanticTokensProvider(selector: DocumentSelector, provider: DocumentSemanticTokensProvider, legend: SemanticTokensLegend): Disposable; + + /** + * Register a semantic tokens provider for a document range. + * + * *Note:* If a document has both a `DocumentSemanticTokensProvider` and a `DocumentRangeSemanticTokensProvider`, + * the range provider will be invoked only initially, for the time in which the full document provider takes + * to resolve the first request. Once the full document provider resolves the first request, the semantic tokens + * provided via the range provider will be discarded and from that point forward, only the document provider + * will be used. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider A document range semantic tokens provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerDocumentRangeSemanticTokensProvider(selector: DocumentSelector, provider: DocumentRangeSemanticTokensProvider, legend: SemanticTokensLegend): Disposable; + /** * Register a formatting provider for a document. * diff --git a/types/vscode/tslint.json b/types/vscode/tslint.json index a57ee44e5c..9c956fb3c4 100644 --- a/types/vscode/tslint.json +++ b/types/vscode/tslint.json @@ -17,6 +17,7 @@ "no-single-declare-module": false, "no-unnecessary-class": false, "no-unnecessary-generics": false, + "member-access": false, "npm-naming": false, "prefer-method-signature": false, "strict-export-declare-modifiers": false,