Skip to content

Commit

Permalink
Prototype TS/JS Refactoring Provider
Browse files Browse the repository at this point in the history
Fixes microsoft#25739, from microsoft/TypeScript#15569

Prototype of refactoring support for ts 2.4
  • Loading branch information
mjbvz committed Jun 16, 2017
1 parent 73015a5 commit dfadffe
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
94 changes: 94 additions & 0 deletions extensions/typescript/src/features/refactorProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands, workspace, WorkspaceEdit } from 'vscode';

import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';


export default class TypeScriptRefactorProvider implements CodeActionProvider {
private commandId: string;

constructor(
private readonly client: ITypescriptServiceClient,
mode: string
) {
this.commandId = `_typescript.applyRefactoring.${mode}`;
commands.registerCommand(this.commandId, this.onCodeAction, this);
}

public async provideCodeActions(
document: TextDocument,
range: Range,
_context: CodeActionContext,
token: CancellationToken
): Promise<Command[]> {
if (!this.client.apiVersion.has240Features()) {
return [];
}

const file = this.client.normalizePath(document.uri);
if (!file) {
return [];
}

const args: Proto.GetApplicableRefactorsRequestArgs = {
file: file,
startLine: range.start.line + 1,
startOffset: range.start.character + 1,
endLine: range.end.line + 1,
endOffset: range.end.character + 1
};

const response = await this.client.execute('getApplicableRefactors', args, token);
if (!response || !response.body) {
return [];
}

return response.body.map(action => ({
title: action.description,
command: this.commandId,
arguments: [file, action.name, range]
}));
}

private actionsToEdit(actions: Proto.CodeAction[]): WorkspaceEdit {
const workspaceEdit = new WorkspaceEdit();
for (const action of actions) {
for (const change of action.changes) {
for (const textChange of change.textChanges) {
workspaceEdit.replace(this.client.asUrl(change.fileName),
new Range(
textChange.start.line - 1, textChange.start.offset - 1,
textChange.end.line - 1, textChange.end.offset - 1),
textChange.newText);
}
}
}
return workspaceEdit;
}

private async onCodeAction(file: string, refactorName: string, range: Range): Promise<boolean> {
const args: Proto.GetRefactorCodeActionsRequestArgs = {
file,
refactorName,
startLine: range.start.line + 1,
startOffset: range.start.character + 1,
endLine: range.end.line + 1,
endOffset: range.end.character + 1
};

const response = await this.client.execute('getRefactorCodeActions', args);
if (!response || !response.body || !response.body.actions.length) {
return false;
}

const edit = this.actionsToEdit(response.body.actions);
return workspace.applyEdit(edit);
}
}
3 changes: 3 additions & 0 deletions extensions/typescript/src/typescriptMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import BufferSyncSupport from './features/bufferSyncSupport';
import CompletionItemProvider from './features/completionItemProvider';
import WorkspaceSymbolProvider from './features/workspaceSymbolProvider';
import CodeActionProvider from './features/codeActionProvider';
import RefactorProvider from './features/refactorProvider';

import ReferenceCodeLensProvider from './features/referencesCodeLensProvider';
import { JsDocCompletionProvider, TryCompleteJsDocCommand } from './features/jsDocCompletionProvider';
import { DirectiveCommentCompletionProvider } from './features/directiveCommentCompletionProvider';
Expand Down Expand Up @@ -263,6 +265,7 @@ class LanguageProvider {
this.disposables.push(languages.registerRenameProvider(selector, new RenameProvider(client)));

this.disposables.push(languages.registerCodeActionsProvider(selector, new CodeActionProvider(client, this.description.id)));
this.disposables.push(languages.registerCodeActionsProvider(selector, new RefactorProvider(client, this.description.id)));

this.registerVersionDependentProviders();

Expand Down
5 changes: 5 additions & 0 deletions extensions/typescript/src/typescriptService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export class API {
public has234Features(): boolean {
return semver.gte(this._version, '2.3.4');
}
public has240Features(): boolean {
return semver.gte(this._version, '2.4.0');
}
}

export interface ITypescriptServiceClient {
Expand Down Expand Up @@ -115,6 +118,8 @@ export interface ITypescriptServiceClient {
execute(command: 'getCodeFixes', args: Proto.CodeFixRequestArgs, token?: CancellationToken): Promise<Proto.GetCodeFixesResponse>;
execute(command: 'getSupportedCodeFixes', args: null, token?: CancellationToken): Promise<Proto.GetSupportedCodeFixesResponse>;
execute(command: 'docCommentTemplate', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.DocCommandTemplateResponse>;
execute(command: 'getApplicableRefactors', args: Proto.GetApplicableRefactorsRequestArgs, token?: CancellationToken): Promise<Proto.GetApplicableRefactorsResponse>;
execute(command: 'getRefactorCodeActions', args: Proto.GetRefactorCodeActionsRequestArgs, token?: CancellationToken): Promise<Proto.GetRefactorCodeActionsResponse>;
// execute(command: 'compileOnSaveAffectedFileList', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise<Proto.CompileOnSaveAffectedFileListResponse>;
// execute(command: 'compileOnSaveEmitFile', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise<any>;
execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise<any>;
Expand Down

0 comments on commit dfadffe

Please sign in to comment.