Skip to content

Commit 7bf0337

Browse files
authored
Interactive refactor actions (#53915)
1 parent c58231e commit 7bf0337

File tree

6 files changed

+69
-8
lines changed

6 files changed

+69
-8
lines changed

src/server/protocol.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,14 @@ export interface GetApplicableRefactorsRequest extends Request {
586586
export type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs & {
587587
triggerReason?: RefactorTriggerReason;
588588
kind?: string;
589+
/**
590+
* Include refactor actions that require additional arguments to be passed when
591+
* calling 'GetEditsForRefactor'. When true, clients should inspect the
592+
* `isInteractive` property of each returned `RefactorActionInfo`
593+
* and ensure they are able to collect the appropriate arguments for any
594+
* interactive refactor before offering it.
595+
*/
596+
includeInteractiveActions?: boolean;
589597
};
590598

591599
export type RefactorTriggerReason = "implicit" | "invoked";
@@ -650,6 +658,12 @@ export interface RefactorActionInfo {
650658
* The hierarchical dotted name of the refactor action.
651659
*/
652660
kind?: string;
661+
662+
/**
663+
* Indicates that the action requires additional arguments to be passed
664+
* when calling 'GetEditsForRefactor'.
665+
*/
666+
isInteractive?: boolean;
653667
}
654668

655669
export interface GetEditsForRefactorRequest extends Request {

src/services/refactorProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ export function registerRefactor(name: string, refactor: Refactor) {
2222
}
2323

2424
/** @internal */
25-
export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] {
25+
export function getApplicableRefactors(context: RefactorContext, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] {
2626
return arrayFrom(flatMapIterator(refactors.values(), refactor =>
2727
context.cancellationToken && context.cancellationToken.isCancellationRequested() ||
2828
!refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined :
29-
refactor.getAvailableActions(context)));
29+
refactor.getAvailableActions(context, includeInteractiveActions)));
3030
}
3131

3232
/** @internal */

src/services/services.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2971,10 +2971,10 @@ export function createLanguageService(
29712971
return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
29722972
}
29732973

2974-
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string): ApplicableRefactorInfo[] {
2974+
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] {
29752975
synchronizeHostData();
29762976
const file = getValidSourceFile(fileName);
2977-
return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind));
2977+
return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind), includeInteractiveActions);
29782978
}
29792979

29802980
function getEditsForRefactor(

src/services/types.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,13 @@ export interface LanguageService {
630630
/** @deprecated `fileName` will be ignored */
631631
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
632632

633-
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
633+
/**
634+
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
635+
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
636+
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
637+
* arguments for any interactive action before offering it.
638+
*/
639+
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
634640
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
635641
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
636642
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@@ -963,6 +969,12 @@ export interface RefactorActionInfo {
963969
* The hierarchical dotted name of the refactor action.
964970
*/
965971
kind?: string;
972+
973+
/**
974+
* Indicates that the action requires additional arguments to be passed
975+
* when calling `getEditsForRefactor`.
976+
*/
977+
isInteractive?: boolean;
966978
}
967979

968980
/**
@@ -1761,7 +1773,7 @@ export interface Refactor {
17611773
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
17621774

17631775
/** Compute (quickly) which actions are available here */
1764-
getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[];
1776+
getAvailableActions(context: RefactorContext, includeInteractive?: boolean): readonly ApplicableRefactorInfo[];
17651777
}
17661778

17671779
/** @internal */

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,14 @@ declare namespace ts {
501501
type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs & {
502502
triggerReason?: RefactorTriggerReason;
503503
kind?: string;
504+
/**
505+
* Include refactor actions that require additional arguments to be passed when
506+
* calling 'GetEditsForRefactor'. When true, clients should inspect the
507+
* `isInteractive` property of each returned `RefactorActionInfo`
508+
* and ensure they are able to collect the appropriate arguments for any
509+
* interactive refactor before offering it.
510+
*/
511+
includeInteractiveActions?: boolean;
504512
};
505513
type RefactorTriggerReason = "implicit" | "invoked";
506514
/**
@@ -557,6 +565,11 @@ declare namespace ts {
557565
* The hierarchical dotted name of the refactor action.
558566
*/
559567
kind?: string;
568+
/**
569+
* Indicates that the action requires additional arguments to be passed
570+
* when calling 'GetEditsForRefactor'.
571+
*/
572+
isInteractive?: boolean;
560573
}
561574
interface GetEditsForRefactorRequest extends Request {
562575
command: CommandTypes.GetEditsForRefactor;
@@ -10129,7 +10142,13 @@ declare namespace ts {
1012910142
applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
1013010143
/** @deprecated `fileName` will be ignored */
1013110144
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
10132-
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
10145+
/**
10146+
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
10147+
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
10148+
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
10149+
* arguments for any interactive action before offering it.
10150+
*/
10151+
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
1013310152
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
1013410153
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
1013510154
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@@ -10401,6 +10420,11 @@ declare namespace ts {
1040110420
* The hierarchical dotted name of the refactor action.
1040210421
*/
1040310422
kind?: string;
10423+
/**
10424+
* Indicates that the action requires additional arguments to be passed
10425+
* when calling `getEditsForRefactor`.
10426+
*/
10427+
isInteractive?: boolean;
1040410428
}
1040510429
/**
1040610430
* A set of edits to make in response to a refactor action, plus an optional

tests/baselines/reference/api/typescript.d.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6198,7 +6198,13 @@ declare namespace ts {
61986198
applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
61996199
/** @deprecated `fileName` will be ignored */
62006200
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
6201-
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
6201+
/**
6202+
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
6203+
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
6204+
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
6205+
* arguments for any interactive action before offering it.
6206+
*/
6207+
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
62026208
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
62036209
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
62046210
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@@ -6470,6 +6476,11 @@ declare namespace ts {
64706476
* The hierarchical dotted name of the refactor action.
64716477
*/
64726478
kind?: string;
6479+
/**
6480+
* Indicates that the action requires additional arguments to be passed
6481+
* when calling `getEditsForRefactor`.
6482+
*/
6483+
isInteractive?: boolean;
64736484
}
64746485
/**
64756486
* A set of edits to make in response to a refactor action, plus an optional

0 commit comments

Comments
 (0)