Skip to content
This repository has been archived by the owner on Jun 10, 2020. It is now read-only.

Code action? #75

Open
tdavis opened this issue Oct 14, 2018 · 2 comments
Open

Code action? #75

tdavis opened this issue Oct 14, 2018 · 2 comments

Comments

@tdavis
Copy link

tdavis commented Oct 14, 2018

Hi there! Thanks for this very promising project, I love anything that gets me out of an IDE and back into Emacs! Your critique of eclim is spot on; it is both slow and finicky about project setup. The biggest differentiator to me at least is the ability to fix issues automatically. In eclim it is clunky and takes a crazy amount of time to apply the change, but it's still faster than checking the flycheck error and manually applying a fix. I would be happy to take a shot at implementing the functionality but all of this lsp stuff is so new to me I'm not sure how to begin. Any pointers? Thanks again!

@Ruin0x11
Copy link
Owner

Ruin0x11 commented Oct 14, 2018

Hello. The two main actions applicable to code documents would be code refactorings and problem quickfixes. In LSP both can be represented using the CodeAction system. By the specification, the user can call codeAction on a region and get back an LSP CodeAction list, which contains a specific command to execute for each action. The CodeAction types could be things like Extract function/Organize imports for globally available refactors, or Import missing package/Create missing class for diagnostic fixes. The two types use different systems in IntelliJ, so they would probably need implementing separately.

Refactorings

Some actions would be globally available regardless of which errors/warnings are in the file. The process for gathering the list of those available code actions would be something like:

  1. User invokes the codeAction request for a region.
  2. In the server, the availability for each supported code action is checked, and the ones available for the region are returned in the response as CodeAction[]. Each code action would return an LSP command identifier for use with the executeCommand request.
  3. On the client, when one of the received code action commands is executed, start the dialog in IntelliJ for setting the options of the refactoring.
  4. Make the command result return a list of document edits. (The return value of an LSP command can be any value, so a convention would be needed.)
  5. On the client, make a request to apply the command's edits on the server, if any were returned.

The second part could be accomplished using part of the RefactoringActionHandler in the IntelliJ SDK. It could be used for determining which code actions to add and how to calculate the result of the corresponding LSP command associated with the action.

Quickfixes

The quickfix menu in IntelliJ seems to use a separate mechanism for applying fixes. A single problem can have multiple quickfixes, and the code actions available for a region depend on specific instances of diagnostics being available in that region. If a code action for one of the diagnostics is selected, the server would have to correlate which IntelliJ problem it is associated with, then return actions associated with the quickfixes for that problem. Also, the problems would have to be retrieved later if the quickfix code action is selected, so a caching or synchronization mechanism might be needed.

There is support for the codeAction request to add a list of diagnostics in a CodeActionContext object, so that is how the list of problems would be sent to the server for getting quickfix actions.

Here is where IntelliJ's quickfixes seem to be held. You would be able to call applyFix by providing the instance of the quickfix information that was generated by a diagnostics pass. To obtain the edits needed, something like differenceFromAction could be run to apply the quickfix inside a copy of the working document, then using the difference as the workspace edits to send to the client. It seems a specific diagnostic can hold multiple quickfixes at once, and may not be constrained to a single working document (which differenceFromAction expects), but that's the general idea.


There are a lot of subtleties and synchronization that would be needed to interface with IntelliJ's mechanisms for both refactoring and the quickfix feature, but it's probably doable with enough time. Also, it may be necessary to add support for certain features to clients nto completely compatible with the spec. I added some amount of extra code to the Emacs client for running certain commands and showing executable tests or main entry points.

Hopefully this is somewhat informative. Although I'm sort of occupied by other projects at the moment, if something isn't clear, please ask.

@tdavis
Copy link
Author

tdavis commented Oct 25, 2018

This is all great information, thanks! Going to start poking around...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants