Move drop/paste ids onto providers (#189961)

For #179430, #30066

This lets us call just the provider we are interested in
This commit is contained in:
Matt Bierner 2023-08-08 14:44:03 -07:00 committed by GitHub
parent 8f4385d10c
commit 8c7747252e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 113 additions and 105 deletions

View File

@ -48,7 +48,7 @@ function getImageMimeType(uri: vscode.Uri): string | undefined {
class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscode.DocumentDropEditProvider {
private readonly id = 'insertAttachment';
public readonly id = 'insertAttachment';
async provideDocumentPasteEdits(
document: vscode.TextDocument,
@ -66,7 +66,7 @@ class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscod
return;
}
const pasteEdit = new vscode.DocumentPasteEdit(insert.insertText, this.id, vscode.l10n.t('Insert Image as Attachment'));
const pasteEdit = new vscode.DocumentPasteEdit(insert.insertText, vscode.l10n.t('Insert Image as Attachment'));
pasteEdit.yieldTo = [{ mimeType: MimeType.plain }];
pasteEdit.additionalEdit = insert.additionalEdit;
return pasteEdit;
@ -84,7 +84,6 @@ class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscod
}
const dropEdit = new vscode.DocumentDropEdit(insert.insertText);
dropEdit.id = this.id;
dropEdit.yieldTo = [{ mimeType: MimeType.plain }];
dropEdit.additionalEdit = insert.additionalEdit;
dropEdit.label = vscode.l10n.t('Insert Image as Attachment');
@ -300,12 +299,14 @@ export function notebookImagePasteSetup(): vscode.Disposable {
const provider = new DropOrPasteEditProvider();
return vscode.Disposable.from(
vscode.languages.registerDocumentPasteEditProvider(JUPYTER_NOTEBOOK_MARKDOWN_SELECTOR, provider, {
id: provider.id,
pasteMimeTypes: [
MimeType.png,
MimeType.uriList,
],
}),
vscode.languages.registerDocumentDropEditProvider(JUPYTER_NOTEBOOK_MARKDOWN_SELECTOR, provider, {
id: provider.id,
dropMimeTypes: [
...Object.values(imageExtToMime),
MimeType.uriList,

View File

@ -9,11 +9,11 @@ import { createEditForMediaFiles, createEditAddingLinksForUriList, mediaMimes, g
class PasteEditProvider implements vscode.DocumentPasteEditProvider {
private readonly _id = 'insertLink';
public static readonly id = 'insertLink';
private readonly _yieldTo = [
{ mimeType: 'text/plain' },
{ extensionId: 'vscode.ipynb', editId: 'insertAttachment' },
{ extensionId: 'vscode.ipynb', providerId: 'insertAttachment' },
];
async provideDocumentPasteEdits(
@ -32,7 +32,7 @@ class PasteEditProvider implements vscode.DocumentPasteEditProvider {
return createEdit;
}
const uriEdit = new vscode.DocumentPasteEdit('', this._id, '');
const uriEdit = new vscode.DocumentPasteEdit('', '');
const urlList = await dataTransfer.get('text/uri-list')?.asString();
if (!urlList) {
return;
@ -65,7 +65,7 @@ class PasteEditProvider implements vscode.DocumentPasteEditProvider {
return;
}
const pasteEdit = new vscode.DocumentPasteEdit(edit.snippet, this._id, edit.label);
const pasteEdit = new vscode.DocumentPasteEdit(edit.snippet, edit.label);
pasteEdit.additionalEdit = edit.additionalEdits;
pasteEdit.yieldTo = this._yieldTo;
return pasteEdit;
@ -74,6 +74,7 @@ class PasteEditProvider implements vscode.DocumentPasteEditProvider {
export function registerPasteSupport(selector: vscode.DocumentSelector,) {
return vscode.languages.registerDocumentPasteEditProvider(selector, new PasteEditProvider(), {
id: PasteEditProvider.id,
pasteMimeTypes: [
'text/uri-list',
...mediaMimes,

View File

@ -10,7 +10,7 @@ const textPlainMime = 'text/plain';
class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
readonly id = 'insertMarkdownLink';
public static readonly id = 'insertMarkdownLink';
async provideDocumentPasteEdits(
document: vscode.TextDocument,
@ -34,7 +34,7 @@ class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
return;
}
const edit = new vscode.DocumentPasteEdit('', this.id, pasteEdit.label);
const edit = new vscode.DocumentPasteEdit('', pasteEdit.label);
edit.additionalEdit = pasteEdit.additionalEdits;
edit.yieldTo = pasteEdit.markdownLink ? undefined : [{ mimeType: textPlainMime }];
return edit;
@ -43,6 +43,7 @@ class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
export function registerLinkPasteSupport(selector: vscode.DocumentSelector,) {
return vscode.languages.registerDocumentPasteEditProvider(selector, new PasteLinkEditProvider(), {
id: PasteLinkEditProvider.id,
pasteMimeTypes: [textPlainMime]
});
}

View File

@ -10,11 +10,11 @@ import { Schemes } from '../../util/schemes';
class MarkdownImageDropProvider implements vscode.DocumentDropEditProvider {
private readonly _id = 'insertLink';
public static readonly id = 'insertLink';
private readonly _yieldTo = [
{ mimeType: 'text/plain' },
{ extensionId: 'vscode.ipynb', editId: 'insertAttachment' },
{ extensionId: 'vscode.ipynb', providerId: 'insertAttachment' },
];
async provideDocumentDropEdits(document: vscode.TextDocument, _position: vscode.Position, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.DocumentDropEdit | undefined> {
@ -46,7 +46,6 @@ class MarkdownImageDropProvider implements vscode.DocumentDropEditProvider {
}
const edit = new vscode.DocumentDropEdit(snippet.snippet);
edit.id = this._id;
edit.label = snippet.label;
edit.yieldTo = this._yieldTo;
return edit;
@ -68,7 +67,6 @@ class MarkdownImageDropProvider implements vscode.DocumentDropEditProvider {
}
const edit = new vscode.DocumentDropEdit(filesEdit.snippet);
edit.id = this._id;
edit.label = filesEdit.label;
edit.additionalEdit = filesEdit.additionalEdits;
edit.yieldTo = this._yieldTo;
@ -78,6 +76,7 @@ class MarkdownImageDropProvider implements vscode.DocumentDropEditProvider {
export function registerDropIntoEditorSupport(selector: vscode.DocumentSelector) {
return vscode.languages.registerDocumentDropEditProvider(selector, new MarkdownImageDropProvider(), {
id: MarkdownImageDropProvider.id,
dropMimeTypes: [
'text/uri-list',
...mediaMimes,

View File

@ -37,7 +37,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem(reversed));
}
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
const newDocContent = getNextDocumentText(testDisposables, doc);
@ -62,7 +62,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem(reversed + '\n'));
}
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
const newDocContent = getNextDocumentText(testDisposables, doc);
@ -88,7 +88,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem(`(${ranges.length})${selections.join(' ')}`));
}
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
editor.selections = [new vscode.Selection(0, 0, 0, 0)];
@ -118,7 +118,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem('a'));
providerAResolve();
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
// Later registered providers will be called first
testDisposables.push(vscode.languages.registerDocumentPasteEditProvider({ language: 'plaintext' }, new class implements vscode.DocumentPasteEditProvider {
@ -132,7 +132,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem('b'));
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
const newDocContent = getNextDocumentText(testDisposables, doc);
@ -159,7 +159,7 @@ suite.skip('vscode API - Copy Paste', function () {
dataTransfer.set(textPlain, new vscode.DataTransferItem('xyz'));
providerAResolve();
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
testDisposables.push(vscode.languages.registerDocumentPasteEditProvider({ language: 'plaintext' }, new class implements vscode.DocumentPasteEditProvider {
async prepareDocumentPaste(_document: vscode.TextDocument, _ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, _token: vscode.CancellationToken): Promise<void> {
@ -172,7 +172,7 @@ suite.skip('vscode API - Copy Paste', function () {
const str = await entry!.asString();
dataTransfer.set(textPlain, new vscode.DataTransferItem(reverseString(str)));
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
const newDocContent = getNextDocumentText(testDisposables, doc);
@ -192,13 +192,13 @@ suite.skip('vscode API - Copy Paste', function () {
async prepareDocumentPaste(_document: vscode.TextDocument, _ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, _token: vscode.CancellationToken): Promise<void> {
dataTransfer.set(textPlain, new vscode.DataTransferItem('xyz'));
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
testDisposables.push(vscode.languages.registerDocumentPasteEditProvider({ language: 'plaintext' }, new class implements vscode.DocumentPasteEditProvider {
async prepareDocumentPaste(_document: vscode.TextDocument, _ranges: readonly vscode.Range[], _dataTransfer: vscode.DataTransfer, _token: vscode.CancellationToken): Promise<void> {
throw new Error('Expected testing error from bad provider');
}
}, { copyMimeTypes: [textPlain] }));
}, { id: 'test', copyMimeTypes: [textPlain] }));
await vscode.commands.executeCommand('editor.action.clipboardCopyAction');
const newDocContent = getNextDocumentText(testDisposables, doc);

View File

@ -802,7 +802,6 @@ export interface CodeActionProvider {
* @internal
*/
export interface DocumentPasteEdit {
readonly id: string;
readonly label: string;
readonly detail: string;
readonly handledMimeType?: string;
@ -816,7 +815,7 @@ export interface DocumentPasteEdit {
*/
export interface DocumentPasteEditProvider {
readonly id?: string;
readonly id: string;
readonly copyMimeTypes?: readonly string[];
readonly pasteMimeTypes?: readonly string[];
@ -2012,13 +2011,12 @@ export enum ExternalUriOpenerPriority {
/**
* @internal
*/
export type DropYieldTo = { readonly editId: string } | { readonly mimeType: string };
export type DropYieldTo = { readonly providerId: string } | { readonly mimeType: string };
/**
* @internal
*/
export interface DocumentOnDropEdit {
readonly id: string;
readonly label: string;
readonly handledMimeType?: string;
readonly yieldTo?: readonly DropYieldTo[];
@ -2030,6 +2028,7 @@ export interface DocumentOnDropEdit {
* @internal
*/
export interface DocumentOnDropEditProvider {
readonly id?: string;
readonly dropMimeTypes?: readonly string[];
provideDocumentOnDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): ProviderResult<DocumentOnDropEdit>;

View File

@ -284,12 +284,6 @@ export class CopyPasteController extends Disposable implements IEditorContributi
return;
}
// If the only edit returned is a text edit, use the default paste handler
if (providerEdits.length === 1 && providerEdits[0].id === 'text') {
await this.applyDefaultPasteHandler(dataTransfer, metadata, tokenSource.token);
return;
}
if (providerEdits.length) {
const canShowWidget = editor.getOption(EditorOption.pasteAs).showPasteSelector === 'afterPaste';
return this._postPasteWidgetManager.applyEditAndShowIfNeeded(selections, { activeEditIndex: 0, allEdits: providerEdits }, canShowWidget, tokenSource.token);
@ -324,7 +318,11 @@ export class CopyPasteController extends Disposable implements IEditorContributi
}
// Filter out any providers the don't match the full data transfer we will send them.
const supportedProviders = allProviders.filter(provider => isSupportedPasteProvider(provider, dataTransfer));
let supportedProviders = allProviders.filter(provider => isSupportedPasteProvider(provider, dataTransfer));
if (preferredId) {
// We are looking for a specific edit
supportedProviders = supportedProviders.filter(edit => edit.id === preferredId);
}
const providerEdits = await this.getPasteEdits(supportedProviders, dataTransfer, model, selections, tokenSource.token);
if (tokenSource.token.isCancellationRequested) {
@ -336,14 +334,13 @@ export class CopyPasteController extends Disposable implements IEditorContributi
}
let pickedEdit: DocumentPasteEdit | undefined;
if (typeof preferredId === 'string') {
// We are looking for a specific edit
pickedEdit = providerEdits.find(edit => edit.id === preferredId);
if (preferredId) {
pickedEdit = providerEdits.at(0);
} else {
const selected = await this._quickInputService.pick(
providerEdits.map((edit): IQuickPickItem & { edit: DocumentPasteEdit } => ({
label: edit.label,
description: edit.id,
description: edit.providerId,
detail: edit.detail,
edit,
})), {
@ -431,15 +428,18 @@ export class CopyPasteController extends Disposable implements IEditorContributi
}
}
private async getPasteEdits(providers: readonly DocumentPasteEditProvider[], dataTransfer: VSDataTransfer, model: ITextModel, selections: readonly Selection[], token: CancellationToken): Promise<DocumentPasteEdit[]> {
private async getPasteEdits(providers: readonly DocumentPasteEditProvider[], dataTransfer: VSDataTransfer, model: ITextModel, selections: readonly Selection[], token: CancellationToken): Promise<Array<DocumentPasteEdit & { providerId: string }>> {
const results = await raceCancellation(
Promise.all(providers.map(provider => {
Promise.all(providers.map(async provider => {
try {
return provider.provideDocumentPasteEdits?.(model, selections, dataTransfer, token);
const edit = await provider.provideDocumentPasteEdits?.(model, selections, dataTransfer, token);
if (edit) {
return { ...edit, providerId: provider.id };
}
} catch (err) {
console.error(err);
return undefined;
}
return undefined;
})),
token);
const edits = coalesce(results ?? []);

View File

@ -29,12 +29,12 @@ abstract class SimplePasteAndDropProvider implements DocumentOnDropEditProvider,
async provideDocumentPasteEdits(_model: ITextModel, _ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
const edit = await this.getEdit(dataTransfer, token);
return edit ? { id: this.id, insertText: edit.insertText, label: edit.label, detail: edit.detail, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo } : undefined;
return edit ? { insertText: edit.insertText, label: edit.label, detail: edit.detail, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo } : undefined;
}
async provideDocumentOnDropEdits(_model: ITextModel, _position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentOnDropEdit | undefined> {
const edit = await this.getEdit(dataTransfer, token);
return edit ? { id: this.id, insertText: edit.insertText, label: edit.label, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo } : undefined;
return edit ? { insertText: edit.insertText, label: edit.label, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo } : undefined;
}
protected abstract getEdit(dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined>;
@ -60,7 +60,6 @@ class DefaultTextProvider extends SimplePasteAndDropProvider {
const insertText = await textEntry.asString();
return {
id: this.id,
handledMimeType: Mimes.text,
label: localize('text.label', "Insert Plain Text"),
detail: builtInLabel,
@ -107,7 +106,6 @@ class PathProvider extends SimplePasteAndDropProvider {
}
return {
id: this.id,
handledMimeType: Mimes.uriList,
insertText,
label,
@ -144,7 +142,6 @@ class RelativePathProvider extends SimplePasteAndDropProvider {
}
return {
id: this.id,
handledMimeType: Mimes.uriList,
insertText: relativeUris.join(' '),
label: entries.length > 1

View File

@ -125,8 +125,16 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
}
private async getDropEdits(providers: DocumentOnDropEditProvider[], model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, tokenSource: EditorStateCancellationTokenSource) {
const results = await raceCancellation(Promise.all(providers.map(provider => {
return provider.provideDocumentOnDropEdits(model, position, dataTransfer, tokenSource.token);
const results = await raceCancellation(Promise.all(providers.map(async provider => {
try {
const edit = await provider.provideDocumentOnDropEdits(model, position, dataTransfer, tokenSource.token);
if (edit) {
return { ...edit, providerId: provider.id };
}
} catch (err) {
console.error(err);
}
return undefined;
})), tokenSource.token);
const edits = coalesce(results ?? []);
sortEditsByYieldTo(edits);

View File

@ -29,12 +29,12 @@ export function createCombinedWorkspaceEdit(uri: URI, ranges: readonly Range[],
}
export function sortEditsByYieldTo<T extends {
readonly id: string;
readonly providerId: string | undefined;
readonly handledMimeType?: string;
readonly yieldTo?: readonly DropYieldTo[];
}>(edits: T[]): void {
function yieldsTo(yTo: DropYieldTo, other: T): boolean {
return ('editId' in yTo && yTo.editId === other.id)
return ('providerId' in yTo && yTo.providerId === other.providerId)
|| ('mimeType' in yTo && yTo.mimeType === other.handledMimeType);
}

View File

@ -372,8 +372,8 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
private readonly _pasteEditProviders = new Map<number, MainThreadPasteEditProvider>();
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], metadata: IPasteEditProviderMetadataDto): void {
const provider = new MainThreadPasteEditProvider(handle, this._proxy, metadata, this._uriIdentService);
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], id: string, metadata: IPasteEditProviderMetadataDto): void {
const provider = new MainThreadPasteEditProvider(handle, this._proxy, id, metadata, this._uriIdentService);
this._pasteEditProviders.set(handle, provider);
this._registrations.set(handle, combinedDisposable(
this._languageFeaturesService.documentPasteEditProvider.register(selector, provider),
@ -915,8 +915,8 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
private readonly _documentOnDropEditProviders = new Map<number, MainThreadDocumentOnDropEditProvider>();
$registerDocumentOnDropEditProvider(handle: number, selector: IDocumentFilterDto[], metadata: IDocumentDropEditProviderMetadata): void {
const provider = new MainThreadDocumentOnDropEditProvider(handle, metadata, this._proxy, this._uriIdentService);
$registerDocumentOnDropEditProvider(handle: number, selector: IDocumentFilterDto[], id: string | undefined, metadata: IDocumentDropEditProviderMetadata): void {
const provider = new MainThreadDocumentOnDropEditProvider(handle, this._proxy, id, metadata, this._uriIdentService);
this._documentOnDropEditProviders.set(handle, provider);
this._registrations.set(handle, combinedDisposable(
this._languageFeaturesService.documentOnDropEditProvider.register(selector, provider),
@ -937,6 +937,7 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider
private readonly dataTransfers = new DataTransferFileCache();
public readonly id: string;
public readonly copyMimeTypes?: readonly string[];
public readonly pasteMimeTypes?: readonly string[];
@ -944,11 +945,13 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider
readonly provideDocumentPasteEdits?: languages.DocumentPasteEditProvider['provideDocumentPasteEdits'];
constructor(
private readonly handle: number,
private readonly _handle: number,
private readonly _proxy: ExtHostLanguageFeaturesShape,
id: string,
metadata: IPasteEditProviderMetadataDto,
@IUriIdentityService private readonly _uriIdentService: IUriIdentityService
) {
this.id = id;
this.copyMimeTypes = metadata.copyMimeTypes;
this.pasteMimeTypes = metadata.pasteMimeTypes;
@ -959,7 +962,7 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider
return undefined;
}
const newDataTransfer = await this._proxy.$prepareDocumentPaste(handle, model.uri, selections, dataTransferDto, token);
const newDataTransfer = await this._proxy.$prepareDocumentPaste(_handle, model.uri, selections, dataTransferDto, token);
if (!newDataTransfer) {
return undefined;
}
@ -981,7 +984,7 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider
return;
}
const result = await this._proxy.$providePasteEdits(this.handle, request.id, model.uri, selections, dataTransferDto, token);
const result = await this._proxy.$providePasteEdits(this._handle, request.id, model.uri, selections, dataTransferDto, token);
if (!result) {
return;
}
@ -1006,14 +1009,17 @@ class MainThreadDocumentOnDropEditProvider implements languages.DocumentOnDropEd
private readonly dataTransfers = new DataTransferFileCache();
readonly id: string | undefined;
readonly dropMimeTypes?: readonly string[];
constructor(
private readonly handle: number,
metadata: IDocumentDropEditProviderMetadata | undefined,
private readonly _handle: number,
private readonly _proxy: ExtHostLanguageFeaturesShape,
id: string | undefined,
metadata: IDocumentDropEditProviderMetadata | undefined,
@IUriIdentityService private readonly _uriIdentService: IUriIdentityService
) {
this.id = id;
this.dropMimeTypes = metadata?.dropMimeTypes ?? ['*/*'];
}
@ -1025,7 +1031,7 @@ class MainThreadDocumentOnDropEditProvider implements languages.DocumentOnDropEd
return;
}
const edit = await this._proxy.$provideDocumentOnDropEdits(this.handle, request.id, model.uri, position, dataTransferDto, token);
const edit = await this._proxy.$provideDocumentOnDropEdits(this._handle, request.id, model.uri, position, dataTransferDto, token);
if (!edit) {
return;
}

View File

@ -402,7 +402,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void;
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], metadata: IPasteEditProviderMetadataDto): void;
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], id: string, metadata: IPasteEditProviderMetadataDto): void;
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string, supportRanges: boolean): void;
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
@ -423,7 +423,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerSelectionRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerTypeHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerDocumentOnDropEditProvider(handle: number, selector: IDocumentFilterDto[], metadata?: IDocumentDropEditProviderMetadata): void;
$registerDocumentOnDropEditProvider(handle: number, selector: IDocumentFilterDto[], id: string | undefined, metadata?: IDocumentDropEditProviderMetadata): void;
$resolvePasteFileData(handle: number, requestId: number, dataId: string): Promise<VSBuffer>;
$resolveDocumentOnDropFileData(handle: number, requestId: number, dataId: string): Promise<VSBuffer>;
$setLanguageConfiguration(handle: number, languageId: string, configuration: ILanguageConfigurationDto): void;
@ -1894,12 +1894,11 @@ export interface IPasteEditProviderMetadataDto {
}
export interface IPasteEditDto {
id: string;
label: string;
detail: string;
yieldTo?: readonly languages.DropYieldTo[];
insertText: string | { snippet: string };
additionalEdit?: IWorkspaceEditDto;
yieldTo?: readonly languages.DropYieldTo[];
}
export interface IDocumentDropEditProviderMetadata {
@ -1907,11 +1906,10 @@ export interface IDocumentDropEditProviderMetadata {
}
export interface IDocumentOnDropEditDto {
id: string;
label: string;
yieldTo?: readonly languages.DropYieldTo[];
insertText: string | { snippet: string };
additionalEdit?: IWorkspaceEditDto;
yieldTo?: readonly languages.DropYieldTo[];
}
export interface ExtHostLanguageFeaturesShape {

View File

@ -506,6 +506,10 @@ class CodeActionAdapter {
class DocumentPasteEditProvider {
public static toInternalProviderId(extId: string, editId: string): string {
return extId + '.' + editId;
}
constructor(
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,
private readonly _documents: ExtHostDocuments,
@ -553,20 +557,15 @@ class DocumentPasteEditProvider {
}
return {
id: edit.id ? this.toInternalId(this._extension.identifier.value, edit.id) : this._extension.identifier.value,
label: edit.label ?? localize('defaultPasteLabel', "Paste using '{0}' extension", this._extension.displayName || this._extension.name),
detail: this._extension.displayName || this._extension.name,
yieldTo: edit.yieldTo?.map(yTo => {
return 'mimeType' in yTo ? yTo : { editId: this.toInternalId(yTo.extensionId, yTo.editId) };
return 'mimeType' in yTo ? yTo : { providerId: DocumentPasteEditProvider.toInternalProviderId(yTo.extensionId, yTo.providerId) };
}),
insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },
additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,
};
}
private toInternalId(extId: string, editId: string): string {
return extId + '.' + editId;
}
}
class DocumentFormattingAdapter {
@ -1785,6 +1784,10 @@ class TypeHierarchyAdapter {
class DocumentOnDropEditAdapter {
public static toInternalProviderId(extId: string, editId: string): string {
return extId + '.' + editId;
}
constructor(
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,
private readonly _documents: ExtHostDocuments,
@ -1805,19 +1808,14 @@ class DocumentOnDropEditAdapter {
return undefined;
}
return {
id: edit.id ? this.toInternalId(this._extension.identifier.value, edit.id) : this._extension.identifier.value,
label: edit.label ?? localize('defaultDropLabel', "Drop using '{0}' extension", this._extension.displayName || this._extension.name),
yieldTo: edit.yieldTo?.map(yTo => {
return 'mimeType' in yTo ? yTo : { editId: this.toInternalId(yTo.extensionId, yTo.editId) };
return 'mimeType' in yTo ? yTo : { providerId: DocumentOnDropEditAdapter.toInternalProviderId(yTo.extensionId, yTo.providerId) };
}),
insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },
additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,
};
}
private toInternalId(extId: string, editId: string): string {
return extId + '.' + editId;
}
}
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
@ -2454,7 +2452,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
const handle = this._nextHandle();
this._adapter.set(handle, new AdapterData(new DocumentOnDropEditAdapter(this._proxy, this._documents, provider, handle, extension), extension));
this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), isProposedApiEnabled(extension, 'dropMetadata') ? metadata : undefined);
const id = isProposedApiEnabled(extension, 'dropMetadata') && metadata ? DocumentOnDropEditAdapter.toInternalProviderId(extension.identifier.value, metadata.id) : undefined;
this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), id, isProposedApiEnabled(extension, 'dropMetadata') ? metadata : undefined);
return this._createDisposable(handle);
}
@ -2469,7 +2468,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle, extension), extension));
this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector, extension), {
const internalId = DocumentPasteEditProvider.toInternalProviderId(extension.identifier.value, metadata.id);
this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector, extension), internalId, {
supportsCopy: !!provider.prepareDocumentPaste,
supportsPaste: !!provider.provideDocumentPasteEdits,
copyMimeTypes: metadata.copyMimeTypes,

View File

@ -2755,16 +2755,12 @@ export class DocumentDropEdit {
@es5ClassCompat
export class DocumentPasteEdit {
id: string;
label: string;
insertText: string | SnippetString;
additionalEdit?: WorkspaceEdit;
constructor(insertText: string | SnippetString, id: string, label: string) {
this.id = id;
constructor(insertText: string | SnippetString, label: string) {
this.label = label;
this.insertText = insertText;
}

View File

@ -44,12 +44,6 @@ declare module 'vscode' {
* An operation applied on paste
*/
class DocumentPasteEdit {
/**
* Identifies the type of edit.
*
* This id should be unique within the extension but does not need to be unique across extensions.
*/
id: string;
/**
* Human readable label that describes the edit.
@ -60,7 +54,7 @@ declare module 'vscode' {
* 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 editId: string }
| { readonly extensionId: string; readonly providerId: string }
| { readonly mimeType: string }
>;
@ -79,10 +73,19 @@ declare module 'vscode' {
*
* TODO: Reverse args, but this will break existing consumers :(
*/
constructor(insertText: string | SnippetString, id: string, label: string);
constructor(insertText: string | SnippetString, label: string);
}
interface DocumentPasteProviderMetadata {
/**
* Identifies the provider.
*
* This id is used when users configure the default provider for paste.
*
* This id should be unique within the extension but does not need to be unique across extensions.
*/
readonly id: string;
/**
* Mime types that {@link DocumentPasteEditProvider.prepareDocumentPaste provideDocumentPasteEdits} may add on copy.
*/

View File

@ -8,16 +8,6 @@ declare module 'vscode' {
// https://github.com/microsoft/vscode/issues/179430
export interface DocumentDropEdit {
/**
* Identifies the type of edit.
*
* This id should be unique within the extension but does not need to be unique across extensions.
*
* TODO: Should this live on the provider instead? That way we could call just the provider we want (however it would
* prevent extending providers in the future to allow returning multiple edits)
*/
id?: string;
/**
* Human readable label that describes the edit.
*/
@ -35,14 +25,23 @@ declare module 'vscode' {
*/
yieldTo?: ReadonlyArray<
// TODO: what about built-in providers?
| { readonly extensionId: string; readonly editId: string }
| { readonly extensionId: string; readonly providerId: string }
| { readonly mimeType: string }
>;
}
export interface DocumentDropEditProviderMetadata {
/**
* List of data transfer types that the provider supports.
* 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;
/**
* List of {@link DataTransfer} mime types that the provider can handle.
*
* This can either be an exact mime type such as `image/png`, or a wildcard pattern such as `image/*`.
*