From c85c0ed3c7e4d2738af593a4ceec3a796c3c8421 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 7 Feb 2024 15:52:27 -0800 Subject: [PATCH 1/3] Hook up prototype paste with imports for JS/TS For https://github.com/microsoft/TypeScript/pull/57262 but with proposed changes to ts protocol --- .../typescript-language-features/package.json | 3 +- .../src/languageFeatures/copyPaste.ts | 111 ++++++++++++++++++ .../src/languageProvider.ts | 1 + .../src/tsServer/protocol/protocol.d.ts | 24 ++++ .../src/typescriptService.ts | 1 + .../tsconfig.json | 1 + 6 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 extensions/typescript-language-features/src/languageFeatures/copyPaste.ts diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 9a5f8ff1f86dc..13afae0e8871c 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -12,7 +12,8 @@ "multiDocumentHighlightProvider", "mappedEditsProvider", "codeActionAI", - "codeActionRanges" + "codeActionRanges", + "documentPaste" ], "capabilities": { "virtualWorkspaces": { diff --git a/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts new file mode 100644 index 0000000000000..617e0b7085a46 --- /dev/null +++ b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts @@ -0,0 +1,111 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { DocumentSelector } from '../configuration/documentSelector'; +import * as typeConverters from '../typeConverters'; +import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService'; +import { conditionalRegistration, requireSomeCapability } from './util/dependentRegistration'; + +class CopyMetadata { + constructor( + readonly resource: vscode.Uri, + readonly ranges: readonly vscode.Range[], + ) { } + + toJSON() { + return JSON.stringify({ + resource: this.resource.toJSON(), + ranges: this.ranges, + }); + } + + static fromJSON(str: string): CopyMetadata | undefined { + try { + const parsed = JSON.parse(str); + return new CopyMetadata( + vscode.Uri.from(parsed.resource), + parsed.ranges.map((r: any) => new vscode.Range(r[0].line, r[0].character, r[1].line, r[1].character))); + } catch { + // ignore + } + return undefined; + } +} + +class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { + + static readonly metadataMimeType = 'application/vnd.code.jsts.metadata'; + + constructor( + private readonly _client: ITypeScriptServiceClient, + ) { } + + prepareDocumentPaste(document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, _token: vscode.CancellationToken) { + dataTransfer.set(DocumentPasteProvider.metadataMimeType, + new vscode.DataTransferItem(new CopyMetadata(document.uri, ranges).toJSON())); + } + + async provideDocumentPasteEdits(document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise { + const file = this._client.toOpenTsFilePath(document); + if (!file) { + return; + } + + const text = await dataTransfer.get('text/plain')?.asString(); + if (!text || token.isCancellationRequested) { + return; + } + + // Get optional metadata + const metadata = await this.extractMetadata(dataTransfer, token); + if (token.isCancellationRequested) { + return; + } + + const copyRange = metadata?.ranges.at(0); + const copyFile = metadata ? this._client.toTsFilePath(metadata.resource) : undefined; + + const response = await this._client.execute('getPostPasteImportFixes', { + file, + pastes: ranges.map(range => ({ text, range: typeConverters.Range.toTextSpan(range) })), + copy: metadata && copyFile && copyRange + ? { file: copyFile, ...typeConverters.Range.toTextSpan(copyRange) } + : undefined, + }, token); + if (response.type !== 'response' || !response.body || token.isCancellationRequested) { + return; + } + + const edit = new vscode.DocumentPasteEdit('', vscode.l10n.t("Paste with imports")); + const additionalEdit = new vscode.WorkspaceEdit(); + for (const edit of response.body.edits) { + additionalEdit.set(this._client.toResource(edit.fileName), edit.textChanges.map(typeConverters.TextEdit.fromCodeEdit)); + } + edit.additionalEdit = additionalEdit; + return edit; + } + + private async extractMetadata(dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise { + const metadata = await dataTransfer.get(DocumentPasteProvider.metadataMimeType)?.asString(); + if (token.isCancellationRequested) { + return undefined; + } + + return metadata ? CopyMetadata.fromJSON(metadata) : undefined; + } +} + +export function register(selector: DocumentSelector, client: ITypeScriptServiceClient) { + return conditionalRegistration([ + requireSomeCapability(client, ClientCapability.Semantic), + ], () => { + return vscode.languages.registerDocumentPasteEditProvider(selector.semantic, new DocumentPasteProvider(client), { + id: 'jsts.pasteWithImports', + copyMimeTypes: [DocumentPasteProvider.metadataMimeType], + pasteMimeTypes: ['text/plain'], + }); + }); +} diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 6157c3b8cb4bd..5e901e758b280 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -64,6 +64,7 @@ export default class LanguageProvider extends Disposable { import('./languageFeatures/codeLens/implementationsCodeLens').then(provider => this._register(provider.register(selector, this.description, this.client, cachedNavTreeResponse))), import('./languageFeatures/codeLens/referencesCodeLens').then(provider => this._register(provider.register(selector, this.description, this.client, cachedNavTreeResponse))), import('./languageFeatures/completions').then(provider => this._register(provider.register(selector, this.description, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager, this.telemetryReporter, this.onCompletionAccepted))), + import('./languageFeatures/copyPaste').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/definitions').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/directiveCommentCompletions').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/documentHighlight').then(provider => this._register(provider.register(selector, this.client))), diff --git a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts index b8d863ebb1aba..412e6cf4cf8b9 100644 --- a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts +++ b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts @@ -20,6 +20,7 @@ declare module 'typescript/lib/tsserverlibrary' { readonly _serverType?: ServerType; } + //#region MapCode export interface MapCodeRequestArgs { /// The files and changes to try and apply/map. mappings: MapCodeRequestDocumentMapping[]; @@ -55,6 +56,29 @@ declare module 'typescript/lib/tsserverlibrary' { export interface MapCodeResponse extends Response { body: FileCodeEdits[] } + //#endregion + + //#region Paste + export interface GetPostPasteImportFixesRequest extends Request { + command: 'getPostPasteImportFixes'; + arguments: GetPostPasteImportFixesRequestArgs; + } + export type DocumentRange = FileRangeRequestArgs; + export type CopyRange = { + start: Location; + end: Location; + } + export type GetPostPasteImportFixesRequestArgs = FileRequestArgs & { + pastes: Array<{ text: string; range: TextSpan }>, + copy?: FileSpan; + } + export interface GetPostPasteImportFixesResponse extends Response { + body: PostPasteImportAction; + } + export interface PostPasteImportAction { + edits: FileCodeEdits[]; + } + //#endregion } } diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index 5823430c416fa..bcb5f59f3b325 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -77,6 +77,7 @@ interface StandardTsServerRequests { 'getMoveToRefactoringFileSuggestions': [Proto.GetMoveToRefactoringFileSuggestionsRequestArgs, Proto.GetMoveToRefactoringFileSuggestions]; 'linkedEditingRange': [Proto.FileLocationRequestArgs, Proto.LinkedEditingRangeResponse]; 'mapCode': [Proto.MapCodeRequestArgs, Proto.MapCodeResponse]; + 'getPostPasteImportFixes': [Proto.GetPostPasteImportFixesRequestArgs, Proto.GetPostPasteImportFixesResponse]; } interface NoResponseTsServerRequests { diff --git a/extensions/typescript-language-features/tsconfig.json b/extensions/typescript-language-features/tsconfig.json index d40c03a591db0..44097665a9c5c 100644 --- a/extensions/typescript-language-features/tsconfig.json +++ b/extensions/typescript-language-features/tsconfig.json @@ -16,5 +16,6 @@ "../../src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts", "../../src/vscode-dts/vscode.proposed.multiDocumentHighlightProvider.d.ts", "../../src/vscode-dts/vscode.proposed.workspaceTrust.d.ts", + "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts", ] } From e16523b3e845a4c30da9c797c2ab92fd2fcfc0e9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 Mar 2024 11:34:44 -0800 Subject: [PATCH 2/3] Support new api --- .../src/languageFeatures/copyPaste.ts | 11 ++++--- .../src/tsServer/protocol/protocol.d.ts | 31 ++++++++++--------- .../src/typescriptService.ts | 2 +- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts index 617e0b7085a46..57f1de9717efa 100644 --- a/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts +++ b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts @@ -68,12 +68,13 @@ class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { const copyRange = metadata?.ranges.at(0); const copyFile = metadata ? this._client.toTsFilePath(metadata.resource) : undefined; - const response = await this._client.execute('getPostPasteImportFixes', { + const response = await this._client.execute('GetPasteEdits', { file, - pastes: ranges.map(range => ({ text, range: typeConverters.Range.toTextSpan(range) })), - copy: metadata && copyFile && copyRange - ? { file: copyFile, ...typeConverters.Range.toTextSpan(copyRange) } - : undefined, + pastes: ranges.map(typeConverters.Range.toTextSpan), + copies: [{ + text, + range: metadata && copyFile && copyRange ? { file: copyFile, ...typeConverters.Range.toTextSpan(copyRange) } : undefined, + }] }, token); if (response.type !== 'response' || !response.body || token.isCancellationRequested) { return; diff --git a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts index 412e6cf4cf8b9..ea21fc5a8103d 100644 --- a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts +++ b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts @@ -59,23 +59,24 @@ declare module 'typescript/lib/tsserverlibrary' { //#endregion //#region Paste - export interface GetPostPasteImportFixesRequest extends Request { - command: 'getPostPasteImportFixes'; - arguments: GetPostPasteImportFixesRequestArgs; - } - export type DocumentRange = FileRangeRequestArgs; - export type CopyRange = { - start: Location; - end: Location; - } - export type GetPostPasteImportFixesRequestArgs = FileRequestArgs & { - pastes: Array<{ text: string; range: TextSpan }>, - copy?: FileSpan; + + + export interface GetPasteEditsRequest extends Request { + command: 'GetPasteEdits'; + arguments: GetPasteEditsRequestArgs; } - export interface GetPostPasteImportFixesResponse extends Response { - body: PostPasteImportAction; + + export type GetPasteEditsRequestArgs = FileRequestArgs & { + copies: { + text: string; + range?: FileSpan; + }[]; + pastes: TextSpan[]; + }; + export interface GetPasteEditsResponse extends Response { + body: PasteEditsAction; } - export interface PostPasteImportAction { + export interface PasteEditsAction { edits: FileCodeEdits[]; } //#endregion diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index bcb5f59f3b325..9e22fed7bbf37 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -77,7 +77,7 @@ interface StandardTsServerRequests { 'getMoveToRefactoringFileSuggestions': [Proto.GetMoveToRefactoringFileSuggestionsRequestArgs, Proto.GetMoveToRefactoringFileSuggestions]; 'linkedEditingRange': [Proto.FileLocationRequestArgs, Proto.LinkedEditingRangeResponse]; 'mapCode': [Proto.MapCodeRequestArgs, Proto.MapCodeResponse]; - 'getPostPasteImportFixes': [Proto.GetPostPasteImportFixesRequestArgs, Proto.GetPostPasteImportFixesResponse]; + 'GetPasteEdits': [Proto.GetPasteEditsRequestArgs, Proto.GetPasteEditsResponse]; } interface NoResponseTsServerRequests { From 39fab0208250669cbd12611afc2be57468867fae Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 8 May 2024 18:08:21 -0700 Subject: [PATCH 3/3] Update --- .../typescript-language-features/package.json | 14 +++++ .../package.nls.json | 1 + .../src/languageFeatures/copyPaste.ts | 55 ++++++++++++++----- .../src/languageProvider.ts | 2 +- .../src/tsServer/api.ts | 1 + .../src/tsServer/protocol/protocol.d.ts | 24 +++++--- .../src/typescriptService.ts | 2 +- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 2d12bf4680e50..e14c6f846dcd5 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -1314,6 +1314,20 @@ "default": true, "markdownDescription": "%typescript.workspaceSymbols.excludeLibrarySymbols%", "scope": "window" + }, + "javascript.experimental.updateImportsOnPaste": { + "scope": "resource", + "type": "boolean", + "default": false, + "description": "%configuration.updateImportsOnPaste%", + "tags": ["experimental"] + }, + "typescript.experimental.updateImportsOnPaste": { + "scope": "resource", + "type": "boolean", + "default": false, + "description": "%configuration.updateImportsOnPaste%", + "tags": ["experimental"] } } }, diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index e60451eaeb4a9..08b9d96fbd775 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -219,6 +219,7 @@ "configuration.tsserver.web.projectWideIntellisense.suppressSemanticErrors": "Suppresses semantic errors. This is needed when using external packages as these can't be included analyzed on web.", "configuration.tsserver.nodePath": "Run TS Server on a custom Node installation. This can be a path to a Node executable, or 'node' if you want VS Code to detect a Node installation.", "configuration.experimental.tsserver.web.typeAcquisition.enabled": "Enable/disable package acquisition on the web.", + "configuration.updateImportsOnPaste": "Automatically update imports when pasting code. Requires TypeScript 5.5+.", "walkthroughs.nodejsWelcome.title": "Get started with JavaScript and Node.js", "walkthroughs.nodejsWelcome.description": "Make the most of Visual Studio Code's first-class JavaScript experience.", "walkthroughs.nodejsWelcome.downloadNode.forMacOrWindows.title": "Install Node.js", diff --git a/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts index 57f1de9717efa..643c77ac35767 100644 --- a/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts +++ b/extensions/typescript-language-features/src/languageFeatures/copyPaste.ts @@ -7,7 +7,10 @@ import * as vscode from 'vscode'; import { DocumentSelector } from '../configuration/documentSelector'; import * as typeConverters from '../typeConverters'; import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService'; -import { conditionalRegistration, requireSomeCapability } from './util/dependentRegistration'; +import { conditionalRegistration, requireMinVersion, requireSomeCapability } from './util/dependentRegistration'; +import protocol from '../tsServer/protocol/protocol'; +import { API } from '../tsServer/api'; +import { LanguageDescription } from '../configuration/languageDescription'; class CopyMetadata { constructor( @@ -37,9 +40,11 @@ class CopyMetadata { class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { + static readonly kind = vscode.DocumentDropOrPasteEditKind.Empty.append('text', 'jsts', 'pasteWithImports'); static readonly metadataMimeType = 'application/vnd.code.jsts.metadata'; constructor( + private readonly _modeId: string, private readonly _client: ITypeScriptServiceClient, ) { } @@ -48,7 +53,18 @@ class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { new vscode.DataTransferItem(new CopyMetadata(document.uri, ranges).toJSON())); } - async provideDocumentPasteEdits(document: vscode.TextDocument, ranges: readonly vscode.Range[], dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise { + async provideDocumentPasteEdits( + document: vscode.TextDocument, + ranges: readonly vscode.Range[], + dataTransfer: vscode.DataTransfer, + _context: vscode.DocumentPasteEditContext, + token: vscode.CancellationToken, + ): Promise { + const config = vscode.workspace.getConfiguration(this._modeId, document.uri); + if (!config.get('experimental.updateImportsOnPaste')) { + return; + } + const file = this._client.toOpenTsFilePath(document); if (!file) { return; @@ -65,28 +81,36 @@ class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { return; } - const copyRange = metadata?.ranges.at(0); - const copyFile = metadata ? this._client.toTsFilePath(metadata.resource) : undefined; + let copiedFrom: { + file: string; + spans: protocol.TextSpan[]; + } | undefined; + if (metadata) { + const spans = metadata.ranges.map(typeConverters.Range.toTextSpan); + const copyFile = this._client.toTsFilePath(metadata.resource); + if (copyFile) { + copiedFrom = { file: copyFile, spans }; + } + } - const response = await this._client.execute('GetPasteEdits', { + const response = await this._client.execute('getPasteEdits', { file, - pastes: ranges.map(typeConverters.Range.toTextSpan), - copies: [{ - text, - range: metadata && copyFile && copyRange ? { file: copyFile, ...typeConverters.Range.toTextSpan(copyRange) } : undefined, - }] + // TODO: only supports a single paste for now + pastedText: [text], + pasteLocations: ranges.map(typeConverters.Range.toTextSpan), + copiedFrom }, token); if (response.type !== 'response' || !response.body || token.isCancellationRequested) { return; } - const edit = new vscode.DocumentPasteEdit('', vscode.l10n.t("Paste with imports")); + const edit = new vscode.DocumentPasteEdit('', vscode.l10n.t("Paste with imports"), DocumentPasteProvider.kind); const additionalEdit = new vscode.WorkspaceEdit(); for (const edit of response.body.edits) { additionalEdit.set(this._client.toResource(edit.fileName), edit.textChanges.map(typeConverters.TextEdit.fromCodeEdit)); } edit.additionalEdit = additionalEdit; - return edit; + return [edit]; } private async extractMetadata(dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise { @@ -99,12 +123,13 @@ class DocumentPasteProvider implements vscode.DocumentPasteEditProvider { } } -export function register(selector: DocumentSelector, client: ITypeScriptServiceClient) { +export function register(selector: DocumentSelector, language: LanguageDescription, client: ITypeScriptServiceClient) { return conditionalRegistration([ requireSomeCapability(client, ClientCapability.Semantic), + requireMinVersion(client, API.v550), ], () => { - return vscode.languages.registerDocumentPasteEditProvider(selector.semantic, new DocumentPasteProvider(client), { - id: 'jsts.pasteWithImports', + return vscode.languages.registerDocumentPasteEditProvider(selector.semantic, new DocumentPasteProvider(language.id, client), { + providedPasteEditKinds: [DocumentPasteProvider.kind], copyMimeTypes: [DocumentPasteProvider.metadataMimeType], pasteMimeTypes: ['text/plain'], }); diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 5e901e758b280..67c727cdefa05 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -64,7 +64,7 @@ export default class LanguageProvider extends Disposable { import('./languageFeatures/codeLens/implementationsCodeLens').then(provider => this._register(provider.register(selector, this.description, this.client, cachedNavTreeResponse))), import('./languageFeatures/codeLens/referencesCodeLens').then(provider => this._register(provider.register(selector, this.description, this.client, cachedNavTreeResponse))), import('./languageFeatures/completions').then(provider => this._register(provider.register(selector, this.description, this.client, this.typingsStatus, this.fileConfigurationManager, this.commandManager, this.telemetryReporter, this.onCompletionAccepted))), - import('./languageFeatures/copyPaste').then(provider => this._register(provider.register(selector, this.client))), + import('./languageFeatures/copyPaste').then(provider => this._register(provider.register(selector, this.description, this.client))), import('./languageFeatures/definitions').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/directiveCommentCompletions').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/documentHighlight').then(provider => this._register(provider.register(selector, this.client))), diff --git a/extensions/typescript-language-features/src/tsServer/api.ts b/extensions/typescript-language-features/src/tsServer/api.ts index 4a35ada0f24b4..0ff790b1dcb31 100644 --- a/extensions/typescript-language-features/src/tsServer/api.ts +++ b/extensions/typescript-language-features/src/tsServer/api.ts @@ -37,6 +37,7 @@ export class API { public static readonly v520 = API.fromSimpleString('5.2.0'); public static readonly v544 = API.fromSimpleString('5.4.4'); public static readonly v540 = API.fromSimpleString('5.4.0'); + public static readonly v550 = API.fromSimpleString('5.5.0'); public static fromVersionString(versionString: string): API { let version = semver.valid(versionString); diff --git a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts index 26a6441a1665d..d8b8baebe04f1 100644 --- a/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts +++ b/extensions/typescript-language-features/src/tsServer/protocol/protocol.d.ts @@ -62,22 +62,30 @@ declare module '../../../../node_modules/typescript/lib/typescript' { export interface GetPasteEditsRequest extends Request { - command: 'GetPasteEdits'; + command: 'getPasteEdits'; arguments: GetPasteEditsRequestArgs; } - export type GetPasteEditsRequestArgs = FileRequestArgs & { - copies: { - text: string; - range?: FileSpan; - }[]; - pastes: TextSpan[]; - }; + export interface GetPasteEditsRequestArgs extends FileRequestArgs { + /** The text that gets pasted in a file. */ + pastedText: string[]; + /** Locations of where the `pastedText` gets added in a file. If the length of the `pastedText` and `pastedLocations` are not the same, + * then the `pastedText` is combined into one and added at all the `pastedLocations`. + */ + pasteLocations: TextSpan[]; + /** The source location of each `pastedText`. If present, the length of `spans` must be equal to the length of `pastedText`. */ + copiedFrom?: { + file: string; + spans: TextSpan[]; + }; + } + export interface GetPasteEditsResponse extends Response { body: PasteEditsAction; } export interface PasteEditsAction { edits: FileCodeEdits[]; + fixId?: {}; } //#endregion } diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index 9dcd09c9bcf82..931b287df03e1 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -77,7 +77,7 @@ interface StandardTsServerRequests { 'getMoveToRefactoringFileSuggestions': [Proto.GetMoveToRefactoringFileSuggestionsRequestArgs, Proto.GetMoveToRefactoringFileSuggestions]; 'linkedEditingRange': [Proto.FileLocationRequestArgs, Proto.LinkedEditingRangeResponse]; 'mapCode': [Proto.MapCodeRequestArgs, Proto.MapCodeResponse]; - 'GetPasteEdits': [Proto.GetPasteEditsRequestArgs, Proto.GetPasteEditsResponse]; + 'getPasteEdits': [Proto.GetPasteEditsRequestArgs, Proto.GetPasteEditsResponse]; } interface NoResponseTsServerRequests {