Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/typescript-language-features/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"license": "MIT",
"aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255",
"enabledApiProposals": [
"mappedEditsProvider",
"workspaceTrust"
],
"capabilities": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* 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 { API } from '../tsServer/api';
import { FileSpan } from '../tsServer/protocol/protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import { conditionalRegistration, requireMinVersion } from './util/dependentRegistration';
import { Range, WorkspaceEdit } from '../typeConverters';
import { DocumentSelector } from '../configuration/documentSelector';

class TsMappedEditsProvider implements vscode.MappedEditsProvider {
constructor(
private readonly client: ITypeScriptServiceClient
) { }

async provideMappedEdits(document: vscode.TextDocument, codeBlocks: string[], context: vscode.MappedEditsContext, token: vscode.CancellationToken): Promise<vscode.WorkspaceEdit | undefined> {
if (!this.isEnabled()) {
return;
}

const file = this.client.toOpenTsFilePath(document);
if (!file) {
return;
}

const response = await this.client.execute('mapCode', {
mappings: [{
file,
contents: codeBlocks,
focusLocations: context.documents.map(documents => {
return documents.flatMap((contextItem): FileSpan[] => {
const file = this.client.toTsFilePath(contextItem.uri);
if (!file) {
return [];
}
return contextItem.ranges.map((range): FileSpan => ({ file, ...Range.toTextSpan(range) }));
});
}),
}],
}, token);
if (response.type !== 'response' || !response.body) {
return;
}

return WorkspaceEdit.fromFileCodeEdits(this.client, response.body);
}

private isEnabled(): boolean {
return vscode.workspace.getConfiguration('typescript').get<boolean>('experimental.mappedCodeEdits.enabled', false);
}
}

export function register(
selector: DocumentSelector,
client: ITypeScriptServiceClient,
) {
return conditionalRegistration([
requireMinVersion(client, API.v540)
], () => {
const provider = new TsMappedEditsProvider(client);
return vscode.chat.registerMappedEditsProvider(selector.semantic, provider);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default class LanguageProvider extends Disposable {
import('./languageFeatures/inlayHints').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager, this.telemetryReporter))),
import('./languageFeatures/jsDocCompletions').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager))),
import('./languageFeatures/linkedEditing').then(provider => this._register(provider.register(selector, this.client))),
import('./languageFeatures/mappedCodeEditProvider').then(provider => this._register(provider.register(selector, this.client))),
import('./languageFeatures/organizeImports').then(provider => this._register(provider.register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter))),
import('./languageFeatures/quickFix').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.client.diagnosticsManager, this.telemetryReporter))),
import('./languageFeatures/refactor').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager, this.commandManager, this.telemetryReporter))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class API {
public static readonly v500 = API.fromSimpleString('5.0.0');
public static readonly v510 = API.fromSimpleString('5.1.0');
public static readonly v520 = API.fromSimpleString('5.2.0');
public static readonly v540 = API.fromSimpleString('5.4.0');

public static fromVersionString(versionString: string): API {
let version = semver.valid(versionString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,43 @@ declare module 'typescript/lib/tsserverlibrary' {
interface Response {
readonly _serverType?: ServerType;
}

export interface MapCodeRequestArgs {
/// The files and changes to try and apply/map.
mappings: MapCodeRequestDocumentMapping[];

/// Edits to apply to the current workspace before performing the mapping.
updates?: FileCodeEdits[]
}

export interface MapCodeRequestDocumentMapping {
/// The file for the request (absolute pathname required). Null/undefined
/// if specific file is unknown.
file?: string;

/// Optional name of project that contains file
projectFileName?: string;

/// The specific code to map/insert/replace in the file.
contents: string[];

/// Areas of "focus" to inform the code mapper with. For example, cursor
/// location, current selection, viewport, etc. Nested arrays denote
/// priority: toplevel arrays are more important than inner arrays, and
/// inner array priorities are based on items within that array. Items
/// earlier in the arrays have higher priority.
focusLocations?: FileSpan[][];
}

export interface MapCodeRequest extends Request {
command: 'mapCode',
arguments: MapCodeRequestArgs;
}

export interface MapCodeResponse extends Response {
body: FileCodeEdits[]
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ interface StandardTsServerRequests {
'findSourceDefinition': [Proto.FileLocationRequestArgs, Proto.DefinitionResponse];
'getMoveToRefactoringFileSuggestions': [Proto.GetMoveToRefactoringFileSuggestionsRequestArgs, Proto.GetMoveToRefactoringFileSuggestions];
'linkedEditingRange': [Proto.FileLocationRequestArgs, Proto.LinkedEditingRangeResponse];
'mapCode': [Proto.MapCodeRequestArgs, Proto.MapCodeResponse];
}

interface NoResponseTsServerRequests {
Expand Down
1 change: 1 addition & 0 deletions extensions/typescript-language-features/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
"../../src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts",
"../../src/vscode-dts/vscode.proposed.workspaceTrust.d.ts"
]
}