Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore improving UX / API for refactorings #33555

Closed
mjbvz opened this issue Aug 31, 2017 · 8 comments
Closed

Explore improving UX / API for refactorings #33555

mjbvz opened this issue Aug 31, 2017 · 8 comments
Assignees
Labels
feature-request Request for new features or functionality on-testplan ux User experience issues
Milestone

Comments

@mjbvz
Copy link
Collaborator

mjbvz commented Aug 31, 2017

Refactoring like extract method don't seem like a great fit for the code actions or any other API that VSCode offers. This issue tracks an investigation of what a better ux/api for refactorings could look like

Problems / Background Info

Any other problems you've noticed or thoughts on refactoring support?

@Gama11
Copy link
Contributor

Gama11 commented Aug 31, 2017

don't seem like a great fit for the code actions or any other API that VSCode offers

Not sure about that last part. If "extract method" was implemented as a command (explicitly selected by the user from the command palette), all of the mentioned issues would be resolved:

  • no annoying light bulbs
  • commands support keybindings
  • a command can call showErrorMessage() in case of failure

On the flip side, you might end up with different languages all using different commands, unlike the "Rename Symbol" refactoring, which has explicit VSCode / language server support and uses the same command for all languages.

Edit: the Python extension already seems to follow this pattern:

@jrieken
Copy link
Member

jrieken commented Aug 31, 2017

If "extract method" was implemented as a command (explicitly selected by the user from the command palette),

Wait, everything here is a command. The provideCodeAction-function is spec'd to return a set of Commands. Now, there is some confusing naming going on, let me explain:

  • You call registerCommand to associate a string-identifier to a piece of code (function)
  • You reference that string-identifier from package.json to make it appear in the command palette or other menus
  • Or, you reference that string-identifier via the Command-interface to make that command appear in the UI. That naming is bad and Command should have been named MenuItem because that's what it actually is

Now, it depends on your extension. You can either reference you "xyzRefactor"-command exclusively from Commands returned from your provider, from package.json, or from both. And because code actions are just commands they also have the freedom to do whatever, e.g. show an error message etc.

unlike the "Rename Symbol" refactoring, which has explicit VSCode / language server support

Yeah, rename is a special case. With our provider-pattern we try to generalise and align things such that the editor owns the UI and that extensions just provide data. Finding the smallest common denominator isn't always easy and for more complex refactorings we haven't been brave enough to try.

@Gama11
Copy link
Contributor

Gama11 commented Aug 31, 2017

Yes, "command" is indeed a confusing term here - I meant "implemented as a menu item", hence the added "selected by the user from the command palette".
And I guess you're right, the lack of a proper error message is not due to a limitation of the code actions API.

@mjbvz
Copy link
Collaborator Author

mjbvz commented Aug 31, 2017

While commands work and have some advantages, I think using regular commands for refactoring leaves something to be desired:

  • Each language extension has to provided its own refactoring commands. We don't want to end up with a python.extractMethod command and a php.extractMethod command and a typescript.extractMethod command and so on.

    I'd really prefer something akin to a single vscode.refactor.extractMethod command, with a single keybinding that works across languages

  • No standard UI for presenting refactoring commands

  • Discoverability. The lightbulb may sometimes annoy users currently, but I feel it does help with discoverability. Commands on their own would not be very discoverable

  • Ask vs tell. This one is debatable:

    In the code action model, VSCode tells the user which actions can be performed at a given location. We do not display actions that cannot be performed.

    In the command model, the user asks VS Code to perform an action. If that action cannot be performed, the user only gets this feedback after they have already asked for the action to be performed. One benefit of the ask/command based model is that the user can then get feedback on why an action cannot be performed

@eamodio
Copy link
Contributor

eamodio commented Aug 31, 2017

Could there maybe be 2 types of code actions -- ones that are in @mjbvz terms "Tell" and ones that are "Ask". Meaning some code actions will cause the lightbulb to show up automagically, but refactoring and other similar code actions will only show if asked for (i.e. ctrl+.). It also would be nice, if the "Tell" code actions actually showed in the editor close in proximity to the "issue", while the "Ask" code actions could show the bulb in the gutter area like today.

@jrieken
Copy link
Member

jrieken commented Sep 1, 2017

Since it results in a snippet without a final tab stop, VS Code appends a final tab stop at the end.

Yeah, it is a fine line. Generally, things that don't require UI, like "invert if-else", "insert semi-colon", or "inline variable" are good candidates for being a code action. However, it's not always that easy and when more complex interactions and user-input is required we usually carve out a provider-api including a data model, think of rename, completions etc.

I don't want this issue to be the kitchen sink for all possible refactoring UIs, but would look at them case by case. We did try this in the past with "Extract Method/Function" but weren't confident enough that we cover all cases for all languages.

We are also trying to keep our UI light and free from dialogs/pop-overs etc.

/cc @stevencl

@bmewburn
Copy link

bmewburn commented Sep 1, 2017

A multi select would be nice for rename where you can choose to apply the rename to selected elements. It's not uncommon to have name collisions in PHP.

@mjbvz
Copy link
Collaborator Author

mjbvz commented Jan 29, 2018

Closing out this investigation. Outcome:

  • After some discussions, we decided to focus on improving the existing code action provider to make it suitable rather than introducing a new refactoring provider

  • This culminated in the new CodeAction type and the CodeActionKind type which now can be used to differentiate refactorings from quick fixes (see vscode.d.ts for details)

  • Extensions that provide refactorings can now use CodeActionContext.only to decide if they should return refactorings for the lightbulb menu (see TS extension for example)

  • Code action kinds also enable keybindings for specific refactorings or specific classes of refactorings (Keybinding for applying a specific code action  #33049 (comment))

  • Added new Refactor command that only shows code actions that have been marked as refactorings.

  • Extensions that really want a user pull model for refactorings can use custom commands for this. This also lets the extension provide feedback on why a refactoring is not available. The same if a refactoring requires complex UI interaction

  • We plan to continue improving the refactorings UI in upcoming iterations. Let us know if you have any ideas around this

@mjbvz mjbvz closed this as completed Jan 29, 2018
@vscodebot vscodebot bot locked and limited conversation to collaborators Mar 15, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request Request for new features or functionality on-testplan ux User experience issues
Projects
None yet
Development

No branches or pull requests

5 participants