Interactive refactor actions (#53915)

This commit is contained in:
Andrew Branch 2023-04-19 13:01:28 -07:00 committed by GitHub
parent c58231ea3b
commit 7bf0337428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 8 deletions

View File

@ -586,6 +586,14 @@ export interface GetApplicableRefactorsRequest extends Request {
export type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs & {
triggerReason?: RefactorTriggerReason;
kind?: string;
/**
* Include refactor actions that require additional arguments to be passed when
* calling 'GetEditsForRefactor'. When true, clients should inspect the
* `isInteractive` property of each returned `RefactorActionInfo`
* and ensure they are able to collect the appropriate arguments for any
* interactive refactor before offering it.
*/
includeInteractiveActions?: boolean;
};
export type RefactorTriggerReason = "implicit" | "invoked";
@ -650,6 +658,12 @@ export interface RefactorActionInfo {
* The hierarchical dotted name of the refactor action.
*/
kind?: string;
/**
* Indicates that the action requires additional arguments to be passed
* when calling 'GetEditsForRefactor'.
*/
isInteractive?: boolean;
}
export interface GetEditsForRefactorRequest extends Request {

View File

@ -22,11 +22,11 @@ export function registerRefactor(name: string, refactor: Refactor) {
}
/** @internal */
export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] {
export function getApplicableRefactors(context: RefactorContext, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] {
return arrayFrom(flatMapIterator(refactors.values(), refactor =>
context.cancellationToken && context.cancellationToken.isCancellationRequested() ||
!refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined :
refactor.getAvailableActions(context)));
refactor.getAvailableActions(context, includeInteractiveActions)));
}
/** @internal */

View File

@ -2971,10 +2971,10 @@ export function createLanguageService(
return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
}
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string): ApplicableRefactorInfo[] {
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] {
synchronizeHostData();
const file = getValidSourceFile(fileName);
return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind));
return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind), includeInteractiveActions);
}
function getEditsForRefactor(

View File

@ -630,7 +630,13 @@ export interface LanguageService {
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
/**
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
* arguments for any interactive action before offering it.
*/
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@ -963,6 +969,12 @@ export interface RefactorActionInfo {
* The hierarchical dotted name of the refactor action.
*/
kind?: string;
/**
* Indicates that the action requires additional arguments to be passed
* when calling `getEditsForRefactor`.
*/
isInteractive?: boolean;
}
/**
@ -1761,7 +1773,7 @@ export interface Refactor {
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
/** Compute (quickly) which actions are available here */
getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[];
getAvailableActions(context: RefactorContext, includeInteractive?: boolean): readonly ApplicableRefactorInfo[];
}
/** @internal */

View File

@ -501,6 +501,14 @@ declare namespace ts {
type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs & {
triggerReason?: RefactorTriggerReason;
kind?: string;
/**
* Include refactor actions that require additional arguments to be passed when
* calling 'GetEditsForRefactor'. When true, clients should inspect the
* `isInteractive` property of each returned `RefactorActionInfo`
* and ensure they are able to collect the appropriate arguments for any
* interactive refactor before offering it.
*/
includeInteractiveActions?: boolean;
};
type RefactorTriggerReason = "implicit" | "invoked";
/**
@ -557,6 +565,11 @@ declare namespace ts {
* The hierarchical dotted name of the refactor action.
*/
kind?: string;
/**
* Indicates that the action requires additional arguments to be passed
* when calling 'GetEditsForRefactor'.
*/
isInteractive?: boolean;
}
interface GetEditsForRefactorRequest extends Request {
command: CommandTypes.GetEditsForRefactor;
@ -10129,7 +10142,13 @@ declare namespace ts {
applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
/**
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
* arguments for any interactive action before offering it.
*/
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@ -10401,6 +10420,11 @@ declare namespace ts {
* The hierarchical dotted name of the refactor action.
*/
kind?: string;
/**
* Indicates that the action requires additional arguments to be passed
* when calling `getEditsForRefactor`.
*/
isInteractive?: boolean;
}
/**
* A set of edits to make in response to a refactor action, plus an optional

View File

@ -6198,7 +6198,13 @@ declare namespace ts {
applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[];
/**
* @param includeInteractiveActions Include refactor actions that require additional arguments to be
* passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive`
* property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate
* arguments for any interactive action before offering it.
*/
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
@ -6470,6 +6476,11 @@ declare namespace ts {
* The hierarchical dotted name of the refactor action.
*/
kind?: string;
/**
* Indicates that the action requires additional arguments to be passed
* when calling `getEditsForRefactor`.
*/
isInteractive?: boolean;
}
/**
* A set of edits to make in response to a refactor action, plus an optional