Skip to content

Commit

Permalink
Hook up mapped code edits experiment for TS
Browse files Browse the repository at this point in the history
  • Loading branch information
mjbvz committed Nov 16, 2023
1 parent 678f6a5 commit 2b761cb
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 0 deletions.
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"
]
}

0 comments on commit 2b761cb

Please sign in to comment.