Add PasteEditProvider (#107283)

For #30066

This adds a new `documentPaste` api proposal that lets extensions hook into copy and paste.

This can be used to do things such as:

- Create link when pasting an image
- Bring along imports when copy and pasting code
This commit is contained in:
Matt Bierner
2022-05-25 03:27:58 -07:00
committed by GitHub
parent a6724dcc10
commit e4f7f6a9da
21 changed files with 512 additions and 51 deletions
@@ -5,6 +5,7 @@
import { VSBuffer } from 'vs/base/common/buffer';
import { CancellationToken } from 'vs/base/common/cancellation';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { CancellationError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@@ -23,14 +24,13 @@ import { ITextModel } from 'vs/editor/common/model';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { decodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { DataTransferCache } from 'vs/workbench/api/common/shared/dataTransferCache';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import * as search from 'vs/workbench/contrib/search/common/search';
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceEditDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures extends Disposable implements MainThreadLanguageFeaturesShape {
@@ -366,6 +366,47 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
this._registrations.set(handle, this._languageFeaturesService.codeActionProvider.register(selector, provider));
}
// --- copy paste action provider
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean): void {
const provider: languages.DocumentPasteEditProvider = {
prepareDocumentPaste: supportsCopy
? async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<VSDataTransfer | undefined> => {
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
if (token.isCancellationRequested) {
return undefined;
}
const result = await this._proxy.$prepareDocumentPaste(handle, model.uri, selection, dataTransferDto, token);
if (!result) {
return undefined;
}
const dataTransferOut = new VSDataTransfer();
result.items.forEach(([type, item]) => {
dataTransferOut.setString(type, item.asString);
});
return dataTransferOut;
}
: undefined,
provideDocumentPasteEdits: async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken) => {
const d = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
const result = await this._proxy.$providePasteEdits(handle, model.uri, selection, d, token);
if (!result) {
return;
} else if ((result as IWorkspaceEditDto).edits) {
return reviveWorkspaceEditDto(result as IWorkspaceEditDto);
} else {
return result as languages.SnippetTextEdit;
}
}
};
this._registrations.set(handle, this._languageFeaturesService.documentPasteEditProvider.register(selector, provider));
}
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void {