Description
Problems
A user selects some text in a JS file and tries to run extract constant
(though a keyboard shortcut). The selected text is not extractable. However, there is currently no feedback in the editor about why the selected text could not be extracted.
Also, unless the already user know that JS/TS supports extract constant, they may never discover this refactoring exists at all; it will only show up in the refactor menu when the current selection is extractable.
Desired UX
-
If the user explicitly requests to apply a refactoring that cannot be applied (such as
extract constant
for an invalid selection) let extensions surface a human readable error message describing why the refactoring cannot be applied. -
Provide a way for extensions to show refactorings that they support but are currently not supported in the refactor menu. This would help users understand what refactorings are available, while also seeing that those refactorings are not possible (ideally we'd also find a way to surface the error message here too)
Proposal
With microsoft/TypeScript#35098, we are requesting that TypeScript return the reason why a given JS/TS refactoring is not possible. This issue tracks the VS Code side API required and how information from this new API would be surfaced to users.
My API proposal is to let extensions set an disabled
property on the code actions they return:
export class CodeAction {
...
disabled?: {
/**
* Human readable description of why the code action is currently disabled.
*
* This is displayed in the UI.
*/
reason: string;
};
}
I propose including .disabled
on the CodeAction
class because it would let us reuse the existing code action metadata (title
, kind
, ...) without having to introduce new classes (such as InvalidCodeAction
)
How .disabled
would be surfaced to users
Lightbulb menu
This automatic lightbulb menu would drop all error code actions. It would likely be overwhelming to show them all.
I like keeping the lightbulb as showing: here is everything that is possible right now.
Keybinding for code action
There are a few cases here:
-
All returned code actions for the keybinding are errors.
If the user has enabled
apply
as part of the keybinding, in this case we would want to show the.error
from the code action that would have been applied if it were valid. -
A mix of error and valid actions are returned, and the user has not selected to apply the code actions.
Here we would want to show a full list of actions, including the invalid actions disabled.
-
A mix of code error and valid actions are returned, and the user has selected to apply code actions.
We would apply the code actions as if the error code actions were not there. For example, use
"apply": "ifOnly"
would apply the valid code action if it is the only valid code action (ignoring the errored ones)
Refactoring menu
We'd show the errored actions in the refactoring menu but as disabled. The goal of this is to improve discoverability.
With the current proposal it would be up to extensions to say which code actions they return in the error state and which ones they simply drop. For example, it may be overwhelming if JS/TS to showed all of its refactorings in the refactor menu all the time (including rarely used ones such as rewrite export
). Instead, for the generic code action menu, JS/TS would likely always return the most common actions (such as extract constant
) either in a valid or in an error state