Skip to content

Commit

Permalink
Merge pull request #198775 from microsoft/aiday/typeScriptChanges
Browse files Browse the repository at this point in the history
Making TypeScript code actions `move to new file` and `move to` appear less often
  • Loading branch information
aiday-mar authored Nov 22, 2023
2 parents 823d54f + edf26e4 commit 5d9d066
Showing 1 changed file with 54 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { nulToken } from '../utils/cancellation';
import FormattingOptionsManager from './fileConfigurationManager';
import { conditionalRegistration, requireSomeCapability } from './util/dependentRegistration';
import { EditorChatFollowUp, EditorChatFollowUp_Args, CompositeCommand } from './util/copilot';
import * as PConst from '../tsServer/protocol/protocol.const';

function toWorkspaceEdit(client: ITypeScriptServiceClient, edits: readonly Proto.FileCodeEdits[]): vscode.WorkspaceEdit {
const workspaceEdit = new vscode.WorkspaceEdit();
Expand Down Expand Up @@ -435,6 +436,30 @@ class MoveToFileCodeAction extends vscode.CodeAction {
arguments: [<MoveToFileRefactorCommand.Args>{ action, document, range }]
};
}

private static readonly _declarationKinds = new Set([
PConst.Kind.module,
PConst.Kind.class,
PConst.Kind.interface
]);

static isOnDeclarationName(node: Proto.NavigationTree | undefined, range: vscode.Range) {
if (!node) {
return false;
}
const isRangeInSpan = (span: Proto.TextSpan) => typeConverters.Range.fromTextSpan(span).contains(range);
if (MoveToFileCodeAction._declarationKinds.has(node.kind) && node.nameSpan && isRangeInSpan(node.nameSpan)) {
return true;
}
if (node.childItems && node.spans.some(isRangeInSpan)) {
for (const child of node.childItems) {
if (MoveToFileCodeAction.isOnDeclarationName(child, range)) {
return true;
}
}
}
return false;
}
}

class SelectCodeAction extends vscode.CodeAction {
Expand Down Expand Up @@ -516,16 +541,24 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider<TsCodeActi
return undefined;
}

const actions = Array.from(this.convertApplicableRefactors(document, response.body, rangeOrSelection)).filter(action => {
const applicableRefactors = await this.convertApplicableRefactors(document, response.body, rangeOrSelection);
const actions = await Promise.all(applicableRefactors.map(async (action) => {
if (this.client.apiVersion.lt(API.v430)) {
// Don't show 'infer return type' refactoring unless it has been explicitly requested
// https://github.com/microsoft/TypeScript/issues/42993
if (!context.only && action.kind?.value === 'refactor.rewrite.function.returnType') {
return false;
}
}
if (action.kind?.value === Move_NewFile.kind.value) {
const navigationTree = await this.client.execute('navtree', { file: document.uri.path }, nulToken);
if (navigationTree.type !== 'response') {
return;
}
return MoveToFileCodeAction.isOnDeclarationName(navigationTree.body, rangeOrSelection);
}
return true;
});
})).then((mappedRefactors) => applicableRefactors.filter((_, index) => mappedRefactors[index]));

if (!context.only) {
return actions;
Expand All @@ -547,31 +580,44 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider<TsCodeActi
return context.triggerKind === vscode.CodeActionTriggerKind.Invoke ? 'invoked' : 'implicit';
}

private *convertApplicableRefactors(
private async convertApplicableRefactors(
document: vscode.TextDocument,
refactors: readonly Proto.ApplicableRefactorInfo[],
rangeOrSelection: vscode.Range | vscode.Selection
): Iterable<TsCodeAction> {
): Promise<Array<TsCodeAction>> {
const actions: Array<TsCodeAction> = [];
for (const refactor of refactors) {
if (refactor.inlineable === false) {
yield new SelectCodeAction(refactor, document, rangeOrSelection);
actions.push(new SelectCodeAction(refactor, document, rangeOrSelection));
} else {
for (const action of refactor.actions) {
yield this.refactorActionToCodeAction(document, refactor, action, rangeOrSelection, refactor.actions);
const refactorAction = await this.refactorActionToCodeAction(document, refactor, action, rangeOrSelection, refactor.actions);
if (refactorAction) {
actions.push(refactorAction);
}
}
}
}
return actions;
}

private refactorActionToCodeAction(
private async refactorActionToCodeAction(
document: vscode.TextDocument,
refactor: Proto.ApplicableRefactorInfo,
action: Proto.RefactorActionInfo,
rangeOrSelection: vscode.Range | vscode.Selection,
allActions: readonly Proto.RefactorActionInfo[],
): TsCodeAction {
): Promise<TsCodeAction | undefined> {
let codeAction: TsCodeAction;
if (action.name === 'Move to file') {
const navigationTree = await this.client.execute('navtree', { file: document.uri.path }, nulToken);
if (navigationTree.type !== 'response') {
return;
}
const shouldIncludeMoveToAction = MoveToFileCodeAction.isOnDeclarationName(navigationTree.body, rangeOrSelection);
if (!shouldIncludeMoveToAction) {
return;
}
codeAction = new MoveToFileCodeAction(document, action, rangeOrSelection);
} else {
let copilotRename: ((info: Proto.RefactorEditInfo) => vscode.Command) | undefined;
Expand Down

0 comments on commit 5d9d066

Please sign in to comment.