diff --git a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts index 38fb3fbffec78..4ae9532f404e9 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts @@ -18,7 +18,7 @@ import * as theia from '@theia/plugin'; import type * as monaco from '@theia/monaco-editor-core'; import { MarkdownString as MarkdownStringDTO } from '@theia/core/lib/common/markdown-rendering'; import { UriComponents } from './uri-components'; -import { CompletionItemTag, SnippetString } from '../plugin/types-impl'; +import { CompletionItemTag, DocumentPasteEditKind, SnippetString } from '../plugin/types-impl'; import { Event as TheiaEvent } from '@theia/core/lib/common/event'; import { URI } from '@theia/core/shared/vscode-uri'; import { SerializedRegExp } from './plugin-api-rpc'; @@ -330,7 +330,7 @@ export interface DocumentDropEdit { } export interface DocumentDropEditProviderMetadata { - readonly id: string; + readonly providedDropEditKinds?: readonly DocumentPasteEditKind[]; readonly dropMimeTypes: readonly string[]; } diff --git a/packages/plugin-ext/src/plugin/plugin-context.ts b/packages/plugin-ext/src/plugin/plugin-context.ts index 83c3f80a5c312..4a1f01b99aaa7 100644 --- a/packages/plugin-ext/src/plugin/plugin-context.ts +++ b/packages/plugin-ext/src/plugin/plugin-context.ts @@ -198,6 +198,8 @@ import { TextMergeTabInput, WebviewEditorTabInput, DocumentPasteEdit, + DocumentPasteEditKind, + DocumentPasteTriggerKind, ExternalUriOpenerPriority, EditSessionIdentityMatch, TerminalOutputAnchor, @@ -1398,6 +1400,8 @@ export function createAPIFactory( TerminalOutputAnchor, TerminalExitReason, DocumentPasteEdit, + DocumentPasteEditKind, + DocumentPasteTriggerKind, ExternalUriOpenerPriority, TerminalQuickFixTerminalCommand, TerminalQuickFixOpener, diff --git a/packages/plugin-ext/src/plugin/types-impl.ts b/packages/plugin-ext/src/plugin/types-impl.ts index 0a0e7c5611407..0f09cd572c62a 100644 --- a/packages/plugin-ext/src/plugin/types-impl.ts +++ b/packages/plugin-ext/src/plugin/types-impl.ts @@ -1643,15 +1643,11 @@ export class DocumentLink { @es5ClassCompat export class DocumentDropEdit { - - id?: string; - - priority?: number; - - label?: string; - + title?: string; + kind: DocumentPasteEditKind; + handledMimeType?: string; + yieldTo?: ReadonlyArray; insertText: string | SnippetString; - additionalEdit?: WorkspaceEdit; constructor(insertText: string | SnippetString) { @@ -3674,19 +3670,57 @@ export class InteractiveWindowInput { // #endregion // #region DocumentPaste +export class DocumentPasteEditKind { + static Empty: DocumentPasteEditKind; + + constructor(public readonly value: string) { } + + /** @stubbed */ + append(...parts: string[]): CodeActionKind { + return CodeActionKind.Empty; + }; + + /** @stubbed */ + intersects(other: CodeActionKind): boolean { + return false; + } + + /** @stubbed */ + contains(other: CodeActionKind): boolean { + return false; + } +} +DocumentPasteEditKind.Empty = new DocumentPasteEditKind(''); + @es5ClassCompat export class DocumentPasteEdit { - constructor(insertText: string | SnippetString, id: string, label: string) { + constructor(insertText: string | SnippetString, title: string, kind: DocumentPasteEditKind) { this.insertText = insertText; - this.id = id; - this.label = label; + this.title = title; + this.kind = kind; } + title: string; + kind: DocumentPasteEditKind; insertText: string | SnippetString; additionalEdit?: WorkspaceEdit; - id: string; - label: string; - priority?: number; + yieldTo?: readonly DocumentPasteEditKind[]; } + +/** + * The reason why paste edits were requested. + */ +export enum DocumentPasteTriggerKind { + /** + * Pasting was requested as part of a normal paste operation. + */ + Automatic = 0, + + /** + * Pasting was requested by the user with the `paste as` command. + */ + PasteAs = 1, +} + // #endregion // #region DocumentPaste diff --git a/packages/plugin/src/theia.proposed.documentPaste.d.ts b/packages/plugin/src/theia.proposed.documentPaste.d.ts index 2289ab1686f6a..42cd879080079 100644 --- a/packages/plugin/src/theia.proposed.documentPaste.d.ts +++ b/packages/plugin/src/theia.proposed.documentPaste.d.ts @@ -23,54 +23,107 @@ export module '@theia/plugin' { /** - * Provider invoked when the user copies and pastes code. + * The reason why paste edits were requested. */ - export interface DocumentPasteEditProvider { + export enum DocumentPasteTriggerKind { + /** + * Pasting was requested as part of a normal paste operation. + */ + Automatic = 0, + + /** + * Pasting was requested by the user with the `paste as` command. + */ + PasteAs = 1, + } + + /** + * Additional information about the paste operation. + */ + + export interface DocumentPasteEditContext { + /** + * Requested kind of paste edits to return. + */ + readonly only: DocumentPasteEditKind | undefined; + + /** + * The reason why paste edits were requested. + */ + readonly triggerKind: DocumentPasteTriggerKind; + } + + /** + * Provider invoked when the user copies or pastes in a {@linkcode TextDocument}. + */ + interface DocumentPasteEditProvider { /** * Optional method invoked after the user copies text in a file. * - * During {@link prepareDocumentPaste}, an extension can compute metadata that is attached to - * a {@link DataTransfer} and is passed back to the provider in {@link provideDocumentPasteEdits}. + * This allows the provider to attach copy metadata to the {@link DataTransfer} + * which is then passed back to providers in {@linkcode provideDocumentPasteEdits}. + * + * Note that currently any changes to the {@linkcode DataTransfer} are isolated to the current editor session. + * This means that added metadata cannot be seen by other applications. * * @param document Document where the copy took place. - * @param ranges Ranges being copied in the `document`. - * @param dataTransfer The data transfer associated with the copy. You can store additional values on this for later use in {@link provideDocumentPasteEdits}. + * @param ranges Ranges being copied in {@linkcode document}. + * @param dataTransfer The data transfer associated with the copy. You can store additional values on this for later use in {@linkcode provideDocumentPasteEdits}. + * This object is only valid for the duration of this method. * @param token A cancellation token. + * + * @return Optional thenable that resolves when all changes to the `dataTransfer` are complete. */ prepareDocumentPaste?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, token: CancellationToken): void | Thenable; /** * Invoked before the user pastes into a document. * - * In this method, extensions can return a workspace edit that replaces the standard pasting behavior. + * Returned edits can replace the standard pasting behavior. * * @param document Document being pasted into - * @param ranges Currently selected ranges in the document. - * @param dataTransfer The data transfer associated with the paste. + * @param ranges Range in the {@linkcode document} to paste into. + * @param dataTransfer The {@link DataTransfer data transfer} associated with the paste. This object is only valid for the duration of the paste operation. + * @param context Additional context for the paste. * @param token A cancellation token. * - * @return Optional workspace edit that applies the paste. Return undefined to use standard pasting. + * @return Set of potential {@link DocumentPasteEdit edits} that apply the paste. Return `undefined` to use standard pasting. */ - provideDocumentPasteEdits?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, token: CancellationToken): ProviderResult; + provideDocumentPasteEdits?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, context: DocumentPasteEditContext, + token: CancellationToken): ProviderResult; + + /** + * Optional method which fills in the {@linkcode DocumentPasteEdit.additionalEdit} before the edit is applied. + * + * This is called once per edit and should be used if generating the complete edit may take a long time. + * Resolve can only be used to change {@link DocumentPasteEdit.additionalEdit}. + * + * @param pasteEdit The {@linkcode DocumentPasteEdit} to resolve. + * @param token A cancellation token. + * + * @returns The resolved paste edit or a thenable that resolves to such. It is OK to return the given + * `pasteEdit`. If no result is returned, the given `pasteEdit` is used. + */ + resolveDocumentPasteEdit?(pasteEdit: T, token: CancellationToken): ProviderResult; } /** - * An operation applied on paste + * An edit applied on paste. */ class DocumentPasteEdit { + /** * Human readable label that describes the edit. */ - label: string; + title: string; /** - * Controls the ordering or multiple paste edits. If this provider yield to edits, it will be shown lower in the list. + * {@link DocumentPasteEditKind Kind} of the edit. + * + * Used to identify specific types of edits. */ - yieldTo?: ReadonlyArray< - | { readonly extensionId: string; readonly providerId: string } - | { readonly mimeType: string } - >; + kind: DocumentPasteEditKind; /** * The text or snippet to insert at the pasted locations. @@ -83,43 +136,77 @@ export module '@theia/plugin' { additionalEdit?: WorkspaceEdit; /** - * @param insertText The text or snippet to insert at the pasted locations. + * Controls the ordering of paste edits provided by multiple providers. * - * TODO: Reverse args, but this will break existing consumers :( + * If this edit yields to another, it will be shown lower in the list of paste edit. */ - constructor(insertText: string | SnippetString, id: string, label: string); + yieldTo?: readonly DocumentPasteEditKind[]; + + /** + * Create a new paste edit. + * + * @param insertText The text or snippet to insert at the pasted locations. + * @param title Human readable label that describes the edit. + * @param kind {@link DocumentPasteEditKind Kind} of the edit. + */ + constructor(insertText: string | SnippetString, title: string, kind: DocumentPasteEditKind); + } + + /** + * TODO: Share with code action kind? + */ + class DocumentPasteEditKind { + static readonly Empty: DocumentPasteEditKind; + + // TODO: Add `Text` any others? + + private constructor(value: string); + + readonly value: string; + + append(...parts: string[]): CodeActionKind; + intersects(other: CodeActionKind): boolean; + contains(other: CodeActionKind): boolean; } interface DocumentPasteProviderMetadata { /** - * Identifies the provider. - * - * This id is used when users configure the default provider for paste. + * List of {@link DocumentPasteEditKind kinds} that the provider may return in {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits}. * - * This id should be unique within the extension but does not need to be unique across extensions. + * The provider will only be invoked when one of these kinds is being requested. For normal pasting, all providers will be invoked. */ - readonly id: string; + readonly providedPasteEditKinds: readonly DocumentPasteEditKind[]; /** - * Mime types that {@link DocumentPasteEditProvider.prepareDocumentPaste provideDocumentPasteEdits} may add on copy. + * Mime types that {@linkcode DocumentPasteEditProvider.prepareDocumentPaste prepareDocumentPaste} may add on copy. */ readonly copyMimeTypes?: readonly string[]; /** - * Mime types that {@link DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits} should be invoked for. + * Mime types that {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits} should be invoked for. * * This can either be an exact mime type such as `image/png`, or a wildcard pattern such as `image/*`. * * Use `text/uri-list` for resources dropped from the explorer or other tree views in the workbench. * - * Use `files` to indicate that the provider should be invoked if any {@link DataTransferFile files} are present in the {@link DataTransfer}. - * Note that {@link DataTransferFile} entries are only created when dropping content from outside the editor, such as + * Use `files` to indicate that the provider should be invoked if any {@link DataTransferFile files} are present in the {@linkcode DataTransfer}. + * Note that {@linkcode DataTransferFile} entries are only created when dropping content from outside the editor, such as * from the operating system. */ readonly pasteMimeTypes?: readonly string[]; } namespace languages { + /** + * Registers a new {@linkcode DocumentPasteEditProvider}. + * + * @param selector A selector that defines the documents this provider applies to. + * @param provider A paste editor provider. + * @param metadata Additional metadata about the provider. + * + * @returns A {@link Disposable} that unregisters this provider when disposed of. + * @stubbed + */ export function registerDocumentPasteEditProvider(selector: DocumentSelector, provider: DocumentPasteEditProvider, metadata: DocumentPasteProviderMetadata): Disposable; } } diff --git a/packages/plugin/src/theia.proposed.dropMetadata.d.ts b/packages/plugin/src/theia.proposed.dropMetadata.d.ts index a8f58d436f2f3..073ddc63db270 100644 --- a/packages/plugin/src/theia.proposed.dropMetadata.d.ts +++ b/packages/plugin/src/theia.proposed.dropMetadata.d.ts @@ -29,7 +29,16 @@ export module '@theia/plugin' { /** * Human readable label that describes the edit. */ - label?: string; + title?: string; + + /** + * {@link DocumentPasteEditKind Kind} of the edit. + * + * Used to identify specific types of edits. + * + * TODO: use own type? + */ + kind: DocumentPasteEditKind; /** * The mime type from the {@link DataTransfer} that this edit applies. @@ -39,21 +48,11 @@ export module '@theia/plugin' { /** * Controls the ordering or multiple paste edits. If this provider yield to edits, it will be shown lower in the list. */ - yieldTo?: ReadonlyArray< - | { readonly extensionId: string; readonly providerId: string } - | { readonly mimeType: string } - >; + yieldTo?: ReadonlyArray; } export interface DocumentDropEditProviderMetadata { - /** - * Identifies the provider. - * - * This id is used when users configure the default provider for drop. - * - * This id should be unique within the extension but does not need to be unique across extensions. - */ - readonly id: string; + readonly providedDropEditKinds?: readonly DocumentPasteEditKind[]; /** * List of data transfer types that the provider supports.