diff --git a/extensions/ipynb/package.json b/extensions/ipynb/package.json index f29ed650162..d923904ef9d 100644 --- a/extensions/ipynb/package.json +++ b/extensions/ipynb/package.json @@ -11,8 +11,7 @@ }, "enabledApiProposals": [ "documentPaste", - "diffContentOptions", - "dropMetadata" + "diffContentOptions" ], "activationEvents": [ "onNotebook:jupyter-notebook", diff --git a/extensions/ipynb/src/notebookImagePaste.ts b/extensions/ipynb/src/notebookImagePaste.ts index 7ea63e7026a..5e188dd554a 100644 --- a/extensions/ipynb/src/notebookImagePaste.ts +++ b/extensions/ipynb/src/notebookImagePaste.ts @@ -48,7 +48,7 @@ function getImageMimeType(uri: vscode.Uri): string | undefined { class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscode.DocumentDropEditProvider { - public static readonly kind = vscode.DocumentPasteEditKind.Empty.append('markdown', 'image', 'attachment'); + public static readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'image', 'attachment'); async provideDocumentPasteEdits( document: vscode.TextDocument, @@ -68,7 +68,7 @@ class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscod } const pasteEdit = new vscode.DocumentPasteEdit(insert.insertText, vscode.l10n.t('Insert Image as Attachment'), DropOrPasteEditProvider.kind); - pasteEdit.yieldTo = [vscode.DocumentPasteEditKind.Empty.append('text')]; + pasteEdit.yieldTo = [vscode.DocumentDropOrPasteEditKind.Empty.append('text')]; pasteEdit.additionalEdit = insert.additionalEdit; return [pasteEdit]; } @@ -85,7 +85,7 @@ class DropOrPasteEditProvider implements vscode.DocumentPasteEditProvider, vscod } const dropEdit = new vscode.DocumentDropEdit(insert.insertText); - dropEdit.yieldTo = [vscode.DocumentPasteEditKind.Empty.append('text')]; + dropEdit.yieldTo = [vscode.DocumentDropOrPasteEditKind.Empty.append('text')]; dropEdit.additionalEdit = insert.additionalEdit; dropEdit.title = vscode.l10n.t('Insert Image as Attachment'); return dropEdit; diff --git a/extensions/ipynb/tsconfig.json b/extensions/ipynb/tsconfig.json index 189a4848f56..2a6cc47eeeb 100644 --- a/extensions/ipynb/tsconfig.json +++ b/extensions/ipynb/tsconfig.json @@ -7,8 +7,6 @@ "include": [ "src/**/*", "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts", - "../../src/vscode-dts/vscode.proposed.dropMetadata.d.ts" - + "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts" ] } diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index c9e2e23d4e8..dffe3cc7533 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -16,8 +16,7 @@ "Programming Languages" ], "enabledApiProposals": [ - "documentPaste", - "dropMetadata" + "documentPaste" ], "activationEvents": [ "onLanguage:markdown", diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts index ef5310013b8..9fd3e4f388d 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/dropOrPasteResource.ts @@ -30,7 +30,7 @@ enum CopyFilesSettings { */ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, vscode.DocumentDropEditProvider { - public static readonly kind = vscode.DocumentPasteEditKind.Empty.append('markdown', 'link'); + public static readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'link'); public static readonly mimeTypes = [ Mime.textUriList, @@ -39,8 +39,8 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v ]; private readonly _yieldTo = [ - vscode.DocumentPasteEditKind.Empty.append('text'), - vscode.DocumentPasteEditKind.Empty.append('markdown', 'image', 'attachment'), + vscode.DocumentDropOrPasteEditKind.Empty.append('text'), + vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'image', 'attachment'), ]; constructor( @@ -133,7 +133,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v } if (!(await shouldInsertMarkdownLinkByDefault(this._parser, document, settings.insert, ranges, token))) { - edit.yieldTo.push(vscode.DocumentPasteEditKind.Empty.append('uri')); + edit.yieldTo.push(vscode.DocumentDropOrPasteEditKind.Empty.append('uri')); } return edit; diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts index 7fcff576a3d..661b0bfd05f 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts @@ -17,7 +17,7 @@ import { UriList } from '../../util/uriList'; */ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { - public static readonly kind = vscode.DocumentPasteEditKind.Empty.append('markdown', 'link'); + public static readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'link'); public static readonly pasteMimeTypes = [Mime.textPlain]; @@ -61,8 +61,8 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { if (!(await shouldInsertMarkdownLinkByDefault(this._parser, document, pasteUrlSetting, ranges, token))) { pasteEdit.yieldTo = [ - vscode.DocumentPasteEditKind.Empty.append('text'), - vscode.DocumentPasteEditKind.Empty.append('uri') + vscode.DocumentDropOrPasteEditKind.Empty.append('text'), + vscode.DocumentDropOrPasteEditKind.Empty.append('uri') ]; } diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts index 87e2a0eaeb5..fc232bfeecb 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts @@ -265,5 +265,5 @@ export interface DropOrPasteEdit { readonly snippet: vscode.SnippetString; readonly label: string; readonly additionalEdits: vscode.WorkspaceEdit; - readonly yieldTo: vscode.DocumentPasteEditKind[]; + readonly yieldTo: vscode.DocumentDropOrPasteEditKind[]; } diff --git a/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts b/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts index dd244cac76b..36b6eacfcfd 100644 --- a/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts +++ b/extensions/markdown-language-features/src/languageFeatures/updateLinksOnPaste.ts @@ -9,7 +9,7 @@ import { Mime } from '../util/mimes'; class UpdatePastedLinksEditProvider implements vscode.DocumentPasteEditProvider { - public static readonly kind = vscode.DocumentPasteEditKind.Empty.append('text', 'markdown', 'updateLinks'); + public static readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('text', 'markdown', 'updateLinks'); public static readonly metadataMime = 'vnd.vscode.markdown.updateLinksMetadata'; diff --git a/extensions/markdown-language-features/tsconfig.json b/extensions/markdown-language-features/tsconfig.json index 6bbe1c80767..75edc8fdacf 100644 --- a/extensions/markdown-language-features/tsconfig.json +++ b/extensions/markdown-language-features/tsconfig.json @@ -6,7 +6,6 @@ "include": [ "src/**/*", "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts", - "../../src/vscode-dts/vscode.proposed.dropMetadata.d.ts" + "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts" ] } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts index e2145d4ee28..b4212bb6103 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts @@ -37,7 +37,7 @@ suite.skip('vscode API - Copy Paste', function () { dataTransfer.set(textPlain, new vscode.DataTransferItem(reversed)); } } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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')); } } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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(' ')}`)); } } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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(); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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')); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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(); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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 { @@ -172,7 +172,7 @@ suite.skip('vscode API - Copy Paste', function () { const str = await entry!.asString(); dataTransfer.set(textPlain, new vscode.DataTransferItem(reverseString(str))); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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 { dataTransfer.set(textPlain, new vscode.DataTransferItem('xyz')); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('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 { throw new Error('Expected testing error from bad provider'); } - }, { providedPasteEditKinds: [vscode.DocumentPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); + }, { providedPasteEditKinds: [vscode.DocumentDropOrPasteEditKind.Empty.append('test')], copyMimeTypes: [textPlain] })); await vscode.commands.executeCommand('editor.action.clipboardCopyAction'); const newDocContent = getNextDocumentText(testDisposables, doc); diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 2c3925b4d45..6a86d6c91da 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -2146,7 +2146,7 @@ export type DropYieldTo = { readonly kind: HierarchicalKind } | { readonly mimeT /** * @internal */ -export interface DocumentOnDropEdit { +export interface DocumentDropEdit { readonly title: string; readonly kind: HierarchicalKind | undefined; readonly handledMimeType?: string; @@ -2158,11 +2158,12 @@ export interface DocumentOnDropEdit { /** * @internal */ -export interface DocumentOnDropEditProvider { +export interface DocumentDropEditProvider { readonly id?: string; readonly dropMimeTypes?: readonly string[]; - provideDocumentOnDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): ProviderResult; + provideDocumentDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): ProviderResult; + resolveDocumentDropEdit?(edit: DocumentDropEdit, token: CancellationToken): Promise; } export interface DocumentContextItem { diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index 72889bd0b7e..205d1b86f10 100644 --- a/src/vs/editor/common/services/languageFeatures.ts +++ b/src/vs/editor/common/services/languageFeatures.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LanguageFeatureRegistry, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, MappedEditsProvider, MultiDocumentHighlightProvider, NewSymbolNamesProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, InlineEditProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, MappedEditsProvider, MultiDocumentHighlightProvider, NewSymbolNamesProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, InlineEditProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService'); @@ -75,7 +75,7 @@ export interface ILanguageFeaturesService { readonly evaluatableExpressionProvider: LanguageFeatureRegistry; - readonly documentOnDropEditProvider: LanguageFeatureRegistry; + readonly documentDropEditProvider: LanguageFeatureRegistry; readonly mappedEditsProvider: LanguageFeatureRegistry; diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index 920a78d7402..2b1384ba099 100644 --- a/src/vs/editor/common/services/languageFeaturesService.ts +++ b/src/vs/editor/common/services/languageFeaturesService.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, MultiDocumentHighlightProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, MappedEditsProvider, NewSymbolNamesProvider, InlineEditProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, MultiDocumentHighlightProvider, DocumentHighlightProvider, DocumentDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, MappedEditsProvider, NewSymbolNamesProvider, InlineEditProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -43,7 +43,7 @@ export class LanguageFeaturesService implements ILanguageFeaturesService { readonly evaluatableExpressionProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly documentRangeSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly documentSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this)); - readonly documentOnDropEditProvider = new LanguageFeatureRegistry(this._score.bind(this)); + readonly documentDropEditProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly documentPasteEditProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly mappedEditsProvider: LanguageFeatureRegistry = new LanguageFeatureRegistry(this._score.bind(this)); diff --git a/src/vs/editor/contrib/dropOrPasteInto/browser/defaultProviders.ts b/src/vs/editor/contrib/dropOrPasteInto/browser/defaultProviders.ts index 88ffc64d4bd..006713618a6 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/browser/defaultProviders.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/browser/defaultProviders.ts @@ -14,14 +14,14 @@ import { relativePath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange } from 'vs/editor/common/core/range'; -import { DocumentOnDropEdit, DocumentOnDropEditProvider, DocumentPasteContext, DocumentPasteEdit, DocumentPasteEditProvider, DocumentPasteEditsSession, DocumentPasteTriggerKind } from 'vs/editor/common/languages'; +import { DocumentDropEdit, DocumentDropEditProvider, DocumentPasteContext, DocumentPasteEdit, DocumentPasteEditProvider, DocumentPasteEditsSession, DocumentPasteTriggerKind } from 'vs/editor/common/languages'; import { ITextModel } from 'vs/editor/common/model'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { localize } from 'vs/nls'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -abstract class SimplePasteAndDropProvider implements DocumentOnDropEditProvider, DocumentPasteEditProvider { +abstract class SimplePasteAndDropProvider implements DocumentDropEditProvider, DocumentPasteEditProvider { abstract readonly kind: HierarchicalKind; abstract readonly dropMimeTypes: readonly string[] | undefined; @@ -39,7 +39,7 @@ abstract class SimplePasteAndDropProvider implements DocumentOnDropEditProvider, }; } - async provideDocumentOnDropEdits(_model: ITextModel, _position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise { + async provideDocumentDropEdits(_model: ITextModel, _position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise { const edit = await this.getEdit(dataTransfer, token); return edit ? [{ insertText: edit.insertText, title: edit.title, kind: edit.kind, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo }] : undefined; } @@ -219,9 +219,9 @@ export class DefaultDropProvidersFeature extends Disposable { ) { super(); - this._register(languageFeaturesService.documentOnDropEditProvider.register('*', new DefaultTextPasteOrDropEditProvider())); - this._register(languageFeaturesService.documentOnDropEditProvider.register('*', new PathProvider())); - this._register(languageFeaturesService.documentOnDropEditProvider.register('*', new RelativePathProvider(workspaceContextService))); + this._register(languageFeaturesService.documentDropEditProvider.register('*', new DefaultTextPasteOrDropEditProvider())); + this._register(languageFeaturesService.documentDropEditProvider.register('*', new PathProvider())); + this._register(languageFeaturesService.documentDropEditProvider.register('*', new RelativePathProvider(workspaceContextService))); } } diff --git a/src/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.ts b/src/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.ts index 32e64cff650..20adc65da11 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.ts @@ -14,7 +14,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; -import { DocumentOnDropEdit, DocumentOnDropEditProvider } from 'vs/editor/common/languages'; +import { DocumentDropEdit, DocumentDropEditProvider } from 'vs/editor/common/languages'; import { ITextModel } from 'vs/editor/common/model'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { DraggedTreeItemsIdentifier } from 'vs/editor/common/services/treeViewsDnd'; @@ -46,7 +46,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr private _currentOperation?: CancelablePromise; private readonly _dropProgressManager: InlineProgressManager; - private readonly _postDropWidgetManager: PostEditWidgetManager; + private readonly _postDropWidgetManager: PostEditWidgetManager; private readonly treeItemsTransfer = LocalSelectionTransfer.getInstance(); @@ -97,7 +97,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr return; } - const providers = this._languageFeaturesService.documentOnDropEditProvider + const providers = this._languageFeaturesService.documentDropEditProvider .ordered(model) .filter(provider => { if (!provider.dropMimeTypes) { @@ -130,10 +130,10 @@ export class DropIntoEditorController extends Disposable implements IEditorContr this._currentOperation = p; } - private async getDropEdits(providers: readonly DocumentOnDropEditProvider[], model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, tokenSource: EditorStateCancellationTokenSource) { + private async getDropEdits(providers: readonly DocumentDropEditProvider[], model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, tokenSource: EditorStateCancellationTokenSource) { const results = await raceCancellation(Promise.all(providers.map(async provider => { try { - const edits = await provider.provideDocumentOnDropEdits(model, position, dataTransfer, tokenSource.token); + const edits = await provider.provideDocumentDropEdits(model, position, dataTransfer, tokenSource.token); return edits?.map(edit => ({ ...edit, providerId: provider.id })); } catch (err) { console.error(err); @@ -145,7 +145,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr return sortEditsByYieldTo(edits); } - private getInitialActiveEditIndex(model: ITextModel, edits: ReadonlyArray) { + private getInitialActiveEditIndex(model: ITextModel, edits: ReadonlyArray) { const preferredProviders = this._configService.getValue>(defaultProviderConfig, { resource: model.uri }); for (const [configMime, desiredKindStr] of Object.entries(preferredProviders)) { const desiredKind = new HierarchicalKind(desiredKindStr); diff --git a/src/vs/editor/contrib/dropOrPasteInto/browser/edit.ts b/src/vs/editor/contrib/dropOrPasteInto/browser/edit.ts index 81cc89436cf..e612cfc0bfc 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/browser/edit.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/browser/edit.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; -import { DocumentOnDropEdit, DocumentPasteEdit, DropYieldTo, WorkspaceEdit } from 'vs/editor/common/languages'; +import { DocumentDropEdit, DocumentPasteEdit, DropYieldTo, WorkspaceEdit } from 'vs/editor/common/languages'; import { Range } from 'vs/editor/common/core/range'; import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser'; import { HierarchicalKind } from 'vs/base/common/hierarchicalKind'; @@ -14,7 +14,7 @@ import { HierarchicalKind } from 'vs/base/common/hierarchicalKind'; * Given a {@link DropOrPasteEdit} and set of ranges, creates a {@link WorkspaceEdit} that applies the insert text from * the {@link DropOrPasteEdit} at each range plus any additional edits. */ -export function createCombinedWorkspaceEdit(uri: URI, ranges: readonly Range[], edit: DocumentPasteEdit | DocumentOnDropEdit): WorkspaceEdit { +export function createCombinedWorkspaceEdit(uri: URI, ranges: readonly Range[], edit: DocumentPasteEdit | DocumentDropEdit): WorkspaceEdit { // If the edit insert text is empty, skip applying at each range if (typeof edit.insertText === 'string' ? edit.insertText === '' : edit.insertText.snippet === '') { return { diff --git a/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts b/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts index e584c56b0b5..7415060262a 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts @@ -13,7 +13,7 @@ import 'vs/css!./postEditWidget'; import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; import { IBulkEditResult, IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { Range } from 'vs/editor/common/core/range'; -import { DocumentOnDropEdit, DocumentPasteEdit } from 'vs/editor/common/languages'; +import { DocumentDropEdit, DocumentPasteEdit } from 'vs/editor/common/languages'; import { TrackedRangeStickiness } from 'vs/editor/common/model'; import { createCombinedWorkspaceEdit } from 'vs/editor/contrib/dropOrPasteInto/browser/edit'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -22,7 +22,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -interface EditSet { +interface EditSet { readonly activeEditIndex: number; readonly allEdits: ReadonlyArray; } @@ -32,7 +32,7 @@ interface ShowCommand { readonly label: string; } -class PostEditWidget extends Disposable implements IContentWidget { +class PostEditWidget extends Disposable implements IContentWidget { private static readonly baseId = 'editor.widget.postEditWidget'; readonly allowEditorOverflow = true; @@ -132,7 +132,7 @@ class PostEditWidget extends D } } -export class PostEditWidgetManager extends Disposable { +export class PostEditWidgetManager extends Disposable { private readonly _currentWidget = this._register(new MutableDisposable>()); diff --git a/src/vs/editor/contrib/dropOrPasteInto/test/browser/editSort.test.ts b/src/vs/editor/contrib/dropOrPasteInto/test/browser/editSort.test.ts index 3013bcde756..ee0b8e56b61 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/test/browser/editSort.test.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/test/browser/editSort.test.ts @@ -5,11 +5,11 @@ import * as assert from 'assert'; import { HierarchicalKind } from 'vs/base/common/hierarchicalKind'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; -import { DocumentOnDropEdit } from 'vs/editor/common/languages'; +import { DocumentDropEdit } from 'vs/editor/common/languages'; import { sortEditsByYieldTo } from 'vs/editor/contrib/dropOrPasteInto/browser/edit'; -function createTestEdit(kind: string, args?: Partial): DocumentOnDropEdit { +function createTestEdit(kind: string, args?: Partial): DocumentDropEdit { return { title: '', insertText: '', @@ -21,13 +21,13 @@ function createTestEdit(kind: string, args?: Partial): Docum suite('sortEditsByYieldTo', () => { test('Should noop for empty edits', () => { - const edits: DocumentOnDropEdit[] = []; + const edits: DocumentDropEdit[] = []; assert.deepStrictEqual(sortEditsByYieldTo(edits), []); }); test('Yielded to edit should get sorted after target', () => { - const edits: DocumentOnDropEdit[] = [ + const edits: DocumentDropEdit[] = [ createTestEdit('a', { yieldTo: [{ kind: new HierarchicalKind('b') }] }), createTestEdit('b'), ]; @@ -36,7 +36,7 @@ suite('sortEditsByYieldTo', () => { test('Should handle chain of yield to', () => { { - const edits: DocumentOnDropEdit[] = [ + const edits: DocumentDropEdit[] = [ createTestEdit('c', { yieldTo: [{ kind: new HierarchicalKind('a') }] }), createTestEdit('a', { yieldTo: [{ kind: new HierarchicalKind('b') }] }), createTestEdit('b'), @@ -45,7 +45,7 @@ suite('sortEditsByYieldTo', () => { assert.deepStrictEqual(sortEditsByYieldTo(edits).map(x => x.kind?.value), ['b', 'a', 'c']); } { - const edits: DocumentOnDropEdit[] = [ + const edits: DocumentDropEdit[] = [ createTestEdit('a', { yieldTo: [{ kind: new HierarchicalKind('b') }] }), createTestEdit('c', { yieldTo: [{ kind: new HierarchicalKind('a') }] }), createTestEdit('b'), @@ -56,7 +56,7 @@ suite('sortEditsByYieldTo', () => { }); test(`Should not reorder when yield to isn't used`, () => { - const edits: DocumentOnDropEdit[] = [ + const edits: DocumentDropEdit[] = [ createTestEdit('c', { yieldTo: [{ kind: new HierarchicalKind('x') }] }), createTestEdit('a', { yieldTo: [{ kind: new HierarchicalKind('y') }] }), createTestEdit('b'), diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index d89eecf9a3f..9c13506c29a 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -32,7 +32,7 @@ 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, IdentifiableInlineEdit, IDocumentDropEditProviderMetadata, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IPasteEditDto, IPasteEditProviderMetadataDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape } from '../common/extHost.protocol'; +import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IdentifiableInlineEdit, IDocumentDropEditDto, IDocumentDropEditProviderMetadata, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IPasteEditDto, IPasteEditProviderMetadataDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape } from '../common/extHost.protocol'; import { ResourceMap } from 'vs/base/common/map'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { HierarchicalKind } from 'vs/base/common/hierarchicalKind'; @@ -968,7 +968,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread const provider = new MainThreadDocumentOnDropEditProvider(handle, this._proxy, metadata, this._uriIdentService); this._documentOnDropEditProviders.set(handle, provider); this._registrations.set(handle, combinedDisposable( - this._languageFeaturesService.documentOnDropEditProvider.register(selector, provider), + this._languageFeaturesService.documentDropEditProvider.register(selector, provider), toDisposable(() => this._documentOnDropEditProviders.delete(handle)), )); } @@ -1082,12 +1082,14 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider } } -class MainThreadDocumentOnDropEditProvider implements languages.DocumentOnDropEditProvider { +class MainThreadDocumentOnDropEditProvider implements languages.DocumentDropEditProvider { private readonly dataTransfers = new DataTransferFileCache(); readonly dropMimeTypes?: readonly string[]; + readonly resolveDocumentDropEdit?: languages.DocumentDropEditProvider['resolveDocumentDropEdit']; + constructor( private readonly _handle: number, private readonly _proxy: ExtHostLanguageFeaturesShape, @@ -1095,9 +1097,19 @@ class MainThreadDocumentOnDropEditProvider implements languages.DocumentOnDropEd @IUriIdentityService private readonly _uriIdentService: IUriIdentityService ) { this.dropMimeTypes = metadata?.dropMimeTypes ?? ['*/*']; + + if (metadata?.supportsResolve) { + this.resolveDocumentDropEdit = async (edit, token) => { + const resolved = await this._proxy.$resolvePasteEdit(this._handle, (edit)._cacheId!, token); + if (resolved.additionalEdit) { + edit.additionalEdit = reviveWorkspaceEditDto(resolved.additionalEdit, this._uriIdentService); + } + return edit; + }; + } } - async provideDocumentOnDropEdits(model: ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise { + async provideDocumentDropEdits(model: ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise { const request = this.dataTransfers.add(dataTransfer); try { const dataTransferDto = await typeConvert.DataTransfer.from(dataTransfer); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 86fbf665c2d..5211bd91579 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -665,7 +665,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostLanguages.createLanguageStatusItem(extension, id, selector); }, registerDocumentDropEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentDropEditProvider, metadata?: vscode.DocumentDropEditProviderMetadata): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentOnDropEditProvider(extension, selector, provider, isProposedApiEnabled(extension, 'dropMetadata') ? metadata : undefined); + return extHostLanguageFeatures.registerDocumentOnDropEditProvider(extension, selector, provider, isProposedApiEnabled(extension, 'documentPaste') ? metadata : undefined); } }; @@ -1624,7 +1624,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I // proposed api types DocumentPasteTriggerKind: extHostTypes.DocumentPasteTriggerKind, DocumentDropEdit: extHostTypes.DocumentDropEdit, - DocumentPasteEditKind: extHostTypes.DocumentPasteEditKind, + DocumentDropOrPasteEditKind: extHostTypes.DocumentDropOrPasteEditKind, DocumentPasteEdit: extHostTypes.DocumentPasteEdit, InlayHint: extHostTypes.InlayHint, InlayHintLabelPart: extHostTypes.InlayHintLabelPart, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index a2ec2e84c91..ca40d5c6e87 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -2082,7 +2082,6 @@ export interface IPasteEditProviderMetadataDto { export interface IDocumentPasteContextDto { readonly only: string | undefined; readonly triggerKind: languages.DocumentPasteTriggerKind; - } export interface IPasteEditDto { @@ -2095,10 +2094,13 @@ export interface IPasteEditDto { } export interface IDocumentDropEditProviderMetadata { + readonly supportsResolve: boolean; + dropMimeTypes: readonly string[]; } -export interface IDocumentOnDropEditDto { +export interface IDocumentDropEditDto { + _cacheId?: ChainedCacheId; title: string; kind: string | undefined; insertText: string | { snippet: string }; @@ -2170,7 +2172,7 @@ export interface ExtHostLanguageFeaturesShape { $provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise; $provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise; $releaseTypeHierarchy(handle: number, sessionId: string): void; - $provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: DataTransferDTO, token: CancellationToken): Promise; + $provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: DataTransferDTO, token: CancellationToken): Promise; $provideMappedEdits(handle: number, document: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise; $provideInlineEdit(handle: number, document: UriComponents, context: languages.IInlineEditContext, token: CancellationToken): Promise; $freeInlineEdit(handle: number, pid: number): void; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index fe84fef3af9..3b05c263ca5 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -32,7 +32,7 @@ import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; import { ExtHostTelemetry, IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters'; -import { CodeActionKind, CompletionList, Disposable, DocumentPasteEditKind, DocumentSymbol, InlineCompletionTriggerKind, InlineEditTriggerKind, InternalDataTransferItem, Location, Range, SemanticTokens, SemanticTokensEdit, SemanticTokensEdits, SnippetString, SymbolInformation, SyntaxTokenType } from 'vs/workbench/api/common/extHostTypes'; +import { CodeActionKind, CompletionList, Disposable, DocumentDropOrPasteEditKind, DocumentSymbol, InlineCompletionTriggerKind, InlineEditTriggerKind, InternalDataTransferItem, Location, Range, SemanticTokens, SemanticTokensEdit, SemanticTokensEdits, SnippetString, SymbolInformation, SyntaxTokenType } from 'vs/workbench/api/common/extHostTypes'; import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import type * as vscode from 'vscode'; import { Cache } from './cache'; @@ -581,7 +581,7 @@ class DocumentPasteEditProvider { }); const edits = await this._provider.provideDocumentPasteEdits(doc, vscodeRanges, dataTransfer, { - only: context.only ? new DocumentPasteEditKind(context.only) : undefined, + only: context.only ? new DocumentDropOrPasteEditKind(context.only) : undefined, triggerKind: context.triggerKind, }, token); if (!edits || token.isCancellationRequested) { @@ -1956,7 +1956,9 @@ class TypeHierarchyAdapter { } } -class DocumentOnDropEditAdapter { +class DocumentDropEditAdapter { + + private readonly _cache = new Cache('DocumentDropEdit'); constructor( private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape, @@ -1966,7 +1968,7 @@ class DocumentOnDropEditAdapter { private readonly _extension: IExtensionDescription, ) { } - async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise { + async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise { const doc = this._documents.getDocument(uri); const pos = typeConvert.Position.to(position); const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (id) => { @@ -1978,7 +1980,11 @@ class DocumentOnDropEditAdapter { return undefined; } - return asArray(edits).map((edit): extHostProtocol.IDocumentOnDropEditDto => ({ + const editsArray = asArray(edits); + const cacheId = this._cache.add(editsArray); + + return editsArray.map((edit, i): extHostProtocol.IDocumentDropEditDto => ({ + _cacheId: [cacheId, i], title: edit.title ?? localize('defaultDropLabel', "Drop using '{0}' extension", this._extension.displayName || this._extension.name), kind: edit.kind?.value, yieldTo: edit.yieldTo?.map(x => x.value), @@ -1986,6 +1992,22 @@ class DocumentOnDropEditAdapter { additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined, })); } + + async resolveDropEdit(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> { + const [sessionId, itemId] = id; + const item = this._cache.get(sessionId, itemId); + if (!item || !this._provider.resolveDocumentDropEdit) { + return {}; // this should not happen... + } + + const resolvedItem = (await this._provider.resolveDocumentDropEdit(item, token)) ?? item; + const additionalEdit = resolvedItem.additionalEdit ? typeConvert.WorkspaceEdit.from(resolvedItem.additionalEdit, undefined) : undefined; + return { additionalEdit }; + } + + releaseDropEdits(id: number): any { + this._cache.delete(id); + } } class MappedEditsAdapter { @@ -2036,7 +2058,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter | InlineValuesAdapter | LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter - | DocumentOnDropEditAdapter | MappedEditsAdapter | NewSymbolNamesAdapter | InlineEditAdapter; + | DocumentDropEditAdapter | MappedEditsAdapter | NewSymbolNamesAdapter | InlineEditAdapter; class AdapterData { constructor( @@ -2704,18 +2726,29 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF registerDocumentOnDropEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentDropEditProvider, metadata?: vscode.DocumentDropEditProviderMetadata) { const handle = this._nextHandle(); - this._adapter.set(handle, new AdapterData(new DocumentOnDropEditAdapter(this._proxy, this._documents, provider, handle, extension), extension)); + this._adapter.set(handle, new AdapterData(new DocumentDropEditAdapter(this._proxy, this._documents, provider, handle, extension), extension)); - this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), isProposedApiEnabled(extension, 'dropMetadata') ? metadata : undefined); + this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), isProposedApiEnabled(extension, 'documentPaste') && metadata ? { + supportsResolve: !!provider.resolveDocumentDropEdit, + dropMimeTypes: metadata.dropMimeTypes, + } : undefined); return this._createDisposable(handle); } - $provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise { - return this._withAdapter(handle, DocumentOnDropEditAdapter, adapter => + $provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise { + return this._withAdapter(handle, DocumentDropEditAdapter, adapter => Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined); } + $resolveDropEdit(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> { + return this._withAdapter(handle, DocumentDropEditAdapter, adapter => adapter.resolveDropEdit(id, token), {}, undefined); + } + + $releaseDropEdits(handle: number, cacheId: number): void { + this._withAdapter(handle, DocumentDropEditAdapter, adapter => Promise.resolve(adapter.releaseDropEdits(cacheId)), undefined, undefined); + } + // --- mapped edits registerMappedEditsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider): vscode.Disposable { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index addaa76b683..d177924bb00 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2794,9 +2794,9 @@ export class DocumentDropEdit { additionalEdit?: WorkspaceEdit; - kind?: DocumentPasteEditKind; + kind?: DocumentDropOrPasteEditKind; - constructor(insertText: string | SnippetString, title?: string, kind?: DocumentPasteEditKind) { + constructor(insertText: string | SnippetString, title?: string, kind?: DocumentDropOrPasteEditKind) { this.insertText = insertText; this.title = title; this.kind = kind; @@ -2808,8 +2808,8 @@ export enum DocumentPasteTriggerKind { PasteAs = 1, } -export class DocumentPasteEditKind { - static Empty: DocumentPasteEditKind; +export class DocumentDropOrPasteEditKind { + static Empty: DocumentDropOrPasteEditKind; private static sep = '.'; @@ -2817,29 +2817,28 @@ export class DocumentPasteEditKind { public readonly value: string ) { } - public append(...parts: string[]): DocumentPasteEditKind { - return new DocumentPasteEditKind((this.value ? [this.value, ...parts] : parts).join(DocumentPasteEditKind.sep)); + public append(...parts: string[]): DocumentDropOrPasteEditKind { + return new DocumentDropOrPasteEditKind((this.value ? [this.value, ...parts] : parts).join(DocumentDropOrPasteEditKind.sep)); } - public intersects(other: DocumentPasteEditKind): boolean { + public intersects(other: DocumentDropOrPasteEditKind): boolean { return this.contains(other) || other.contains(this); } - public contains(other: DocumentPasteEditKind): boolean { - return this.value === other.value || other.value.startsWith(this.value + DocumentPasteEditKind.sep); + public contains(other: DocumentDropOrPasteEditKind): boolean { + return this.value === other.value || other.value.startsWith(this.value + DocumentDropOrPasteEditKind.sep); } } -DocumentPasteEditKind.Empty = new DocumentPasteEditKind(''); +DocumentDropOrPasteEditKind.Empty = new DocumentDropOrPasteEditKind(''); -@es5ClassCompat export class DocumentPasteEdit { title: string; insertText: string | SnippetString; additionalEdit?: WorkspaceEdit; - kind: DocumentPasteEditKind; + kind: DocumentDropOrPasteEditKind; - constructor(insertText: string | SnippetString, title: string, kind: DocumentPasteEditKind) { + constructor(insertText: string | SnippetString, title: string, kind: DocumentDropOrPasteEditKind) { this.title = title; this.insertText = insertText; this.kind = kind; diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index d9ce6e42ddf..cfe1ad95f04 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -56,7 +56,6 @@ export const allApiProposals = Object.freeze({ diffContentOptions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.diffContentOptions.d.ts', documentFiltersExclusive: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.documentFiltersExclusive.d.ts', documentPaste: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.documentPaste.d.ts', - dropMetadata: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.dropMetadata.d.ts', editSessionIdentityProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts', editorInsets: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorInsets.d.ts', extensionRuntime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionRuntime.d.ts', diff --git a/src/vscode-dts/vscode.proposed.documentPaste.d.ts b/src/vscode-dts/vscode.proposed.documentPaste.d.ts index 627c8dcc1cb..227ae50fdd7 100644 --- a/src/vscode-dts/vscode.proposed.documentPaste.d.ts +++ b/src/vscode-dts/vscode.proposed.documentPaste.d.ts @@ -7,6 +7,41 @@ declare module 'vscode' { // https://github.com/microsoft/vscode/issues/30066/ + /** + * Identifies a {@linkcode DocumentDropEdit} or {@linkcode DocumentPasteEdit} + */ + class DocumentDropOrPasteEditKind { + static readonly Empty: DocumentDropOrPasteEditKind; + + private constructor(value: string); + + /** + * The raw of the kind. + */ + readonly value: string; + + /** + * Create a new kind by appending a more specific selector to the current kind. + * + * Does not modify the current kind. + */ + append(...parts: string[]): DocumentDropOrPasteEditKind; + + /** + * Checks if this code action kind intersects `other`. + * + * @param other Kind to check. + */ + intersects(other: DocumentDropOrPasteEditKind): boolean; + + /** + * Checks if `other` is a sub-kind of this `DocumentDropOrPasteEditKind`. + * + * @param other Kind to check. + */ + contains(other: DocumentDropOrPasteEditKind): boolean; + } + /** * The reason why paste edits were requested. */ @@ -30,7 +65,7 @@ declare module 'vscode' { /** * Requested kind of paste edits to return. */ - readonly only: DocumentPasteEditKind | undefined; + readonly only: DocumentDropOrPasteEditKind | undefined; /** * The reason why paste edits were requested. @@ -103,11 +138,11 @@ declare module 'vscode' { title: string; /** - * {@link DocumentPasteEditKind Kind} of the edit. + * {@link DocumentDropOrPasteEditKind Kind} of the edit. * * Used to identify specific types of edits. */ - kind: DocumentPasteEditKind; + kind: DocumentDropOrPasteEditKind; /** * The text or snippet to insert at the pasted locations. @@ -124,43 +159,28 @@ declare module 'vscode' { * * If this edit yields to another, it will be shown lower in the list of paste edit. */ - yieldTo?: readonly DocumentPasteEditKind[]; + yieldTo?: readonly DocumentDropOrPasteEditKind[]; /** * 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. + * @param kind {@link DocumentDropOrPasteEditKind Kind} of the edit. */ - constructor(insertText: string | SnippetString, title: string, kind: DocumentPasteEditKind); + constructor(insertText: string | SnippetString, title: string, kind: DocumentDropOrPasteEditKind); } - /** - * TODO: Share with code action kind? + * Provides additional metadata about how a {@linkcode DocumentPasteEditProvider} works. */ - 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 { /** - * List of {@link DocumentPasteEditKind kinds} that the provider may return in {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits}. + * List of {@link DocumentDropOrPasteEditKind kinds} that the provider may return in {@linkcode DocumentPasteEditProvider.provideDocumentPasteEdits provideDocumentPasteEdits}. * - * The provider will only be invoked when one of these kinds is being requested. For normal pasting, all providers will be invoked. + * This is used to filter out providers when a specific kind of edit is requested. */ - readonly providedPasteEditKinds: readonly DocumentPasteEditKind[]; + readonly providedPasteEditKinds: readonly DocumentDropOrPasteEditKind[]; /** * Mime types that {@linkcode DocumentPasteEditProvider.prepareDocumentPaste prepareDocumentPaste} may add on copy. @@ -181,6 +201,74 @@ declare module 'vscode' { readonly pasteMimeTypes?: readonly string[]; } + /** + * TODO on finalization: + * - Add ctor(insertText: string | SnippetString, title?: string, kind?: DocumentDropOrPasteEditKind); Can't be done as this is an extension to an existing class + */ + + export interface DocumentDropEdit { + /** + * Human readable label that describes the edit. + */ + title?: string; + + /** + * {@link DocumentDropOrPasteEditKind Kind} of the edit. + * + * Used to identify specific types of edits. + */ + kind: DocumentDropOrPasteEditKind; + + /** + * Controls the ordering or multiple edits. If this provider yield to edits, it will be shown lower in the list. + */ + yieldTo?: readonly DocumentDropOrPasteEditKind[]; + } + + export interface DocumentDropEditProvider { + // Overload that allows returning multiple edits + provideDocumentDropEdits(document: TextDocument, position: Position, dataTransfer: DataTransfer, token: CancellationToken): ProviderResult; + + /** + * Optional method which fills in the {@linkcode DocumentDropEdit.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 DocumentDropEdit.additionalEdit}. + * + * @param pasteEdit The {@linkcode DocumentDropEdit} to resolve. + * @param token A cancellation token. + * + * @returns The resolved edit or a thenable that resolves to such. It is OK to return the given + * `edit`. If no result is returned, the given `edit` is used. + */ + resolveDocumentDropEdit?(edit: T, token: CancellationToken): ProviderResult; + } + + /** + * Provides additional metadata about how a {@linkcode DocumentDropEditProvider} works. + */ + export interface DocumentDropEditProviderMetadata { + /** + * List of {@link DocumentDropOrPasteEditKind kinds} that the provider may return in {@linkcode DocumentDropEditProvider.provideDocumentDropEdits provideDocumentDropEdits}. + * + * This is used to filter out providers when a specific kind of edit is requested. + */ + readonly providedDropEditKinds?: readonly DocumentDropOrPasteEditKind[]; + + /** + * 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/*`. + * + * 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 + * from the operating system. + */ + readonly dropMimeTypes: readonly string[]; + } + namespace languages { /** * Registers a new {@linkcode DocumentPasteEditProvider}. @@ -192,5 +280,10 @@ declare module 'vscode' { * @returns A {@link Disposable} that unregisters this provider when disposed of. */ export function registerDocumentPasteEditProvider(selector: DocumentSelector, provider: DocumentPasteEditProvider, metadata: DocumentPasteProviderMetadata): Disposable; + + /** + * Overload which adds extra metadata + */ + export function registerDocumentDropEditProvider(selector: DocumentSelector, provider: DocumentDropEditProvider, metadata?: DocumentDropEditProviderMetadata): Disposable; } } diff --git a/src/vscode-dts/vscode.proposed.dropMetadata.d.ts b/src/vscode-dts/vscode.proposed.dropMetadata.d.ts deleted file mode 100644 index 63631c4ac7b..00000000000 --- a/src/vscode-dts/vscode.proposed.dropMetadata.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'vscode' { - - // https://github.com/microsoft/vscode/issues/179430 - - - /** - * TODO: - * - Add ctor(insertText: string | SnippetString, title?: string, kind?: DocumentPasteEditKind); Can't be done as this is an extension to an existing class - * - Update provider to return multiple edits - */ - - export interface DocumentDropEdit { - /** - * Human readable label that describes the edit. - */ - 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. - * - * TODO: Should this be taken from `dropMimeTypes` instead? - */ - handledMimeType?: string; - - /** - * Controls the ordering or multiple paste edits. If this provider yield to edits, it will be shown lower in the list. - */ - yieldTo?: ReadonlyArray; - } - - export interface DocumentDropEditProviderMetadata { - readonly providedDropEditKinds?: readonly DocumentPasteEditKind[]; - - /** - * 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/*`. - * - * 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 - * from the operating system. - */ - readonly dropMimeTypes: readonly string[]; - } - - export namespace languages { - export function registerDocumentDropEditProvider(selector: DocumentSelector, provider: DocumentDropEditProvider, metadata?: DocumentDropEditProviderMetadata): Disposable; - } -}