microsoft / microsoft/language-server-protocol
Proposal: Easier codeAction/resolve handling
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13k
- Forks
- 1k
- Avg merge
- 6d 1h
- Merged PRs (30d)
- 10
Description
This is a proposal for an easier workflow for lazy code actions.
A lazy code action is a code action where we separate the following, usually for performance:
- resolving the title, kind, and location of the code action
- resolving the edits for the code action
Status Quo
The current flow for lazy code actions is:
- client sends a
textDocument/codeActionrequest, the body of which has typeCodeActionParams - If the server replies with a code action missing
editandcommandfields and (optional)datafield of any type - Then client sends
textDocument/resolve, including thedatathe client replied totextDocument/codeActionwith
The idea of the existing flow, as I understand it, is that the information in data will be sufficient to fill in the edit field of the code action.
The difficulty in implementing is that an LSP server implementor must design and implement a custom protocol for every lazy code action: what information to serialize into data and then read back.
There is no standard way of doing this and it sounds mistake-prone.
Alternative
I suggest adding an alternative flow:
- client sends a
textDocument/codeActionrequest, the body of which has typeCodeActionParams - If the server replies with a code action missing
editandcommandfields - Then client sends
textDocument/resolve, including acodeActionParamsfield of typeCodeActionParamscorresponding to (1)
For backwards compatibility, the flow can be opt-in via a server and client capability called something like supportsCodeActionParamsInResolve.
I found a flow like this easier and simpler to implement because:
- The logic for finding the range and title to show to the user was similar to the logic
for finding the edits for a refactor, so it's natural to reuse the same code path - By reusing the same code path and avoiding custom protocol via
datait's harder to make a mistake
in the generting/consuming the customdataor a mistake in ensuring that the edits go with the appropriate code action. - Once some plumbing is set up, converting code actions to be lazy can be done in two lines of code each
https://github.com/facebook/hhvm/commit/07b43be5a58c69deec8edbba19ecd058496eecb2
Simulating the alternative lazy resolution flow today
I simulated this alernative lazy code action flow with:
textDocument/codeAction server reply implementation:
- Step 1: set
editto a() => WorkspaceEdit[](In OCaml I used alazy, but it shakes out to the same thing) - Step 2: Before serializing, replace
editwithundefinedand copy thecodeActionParamsto thedatafield of each code action.
testDocument/resolve server reply implementation:
- Step 1: same code path as step 1 for
textDocument/codeAction - Step 2: Before serializing, replace the edit field (set to
() => WorkspaceEdit[]) with the result of applying the function, so we
return a fully resolved code action{edit: WorkspaceEdit[], ...}
Downsides of merely simulating are:
- The hack is non-obvious and not discoverable for LSP server implementors
- The
CodeActionParamspayload is repeated by the server once for every code action returned intextDocument/codeAction, which
makes messages harder to read for debugging and testing and has a (small) speed and memory cost
Next steps
I could adapt this into a full proposal after getting feedback.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the textDocument/codeAction and textDocument/resolve entry points and the related client and server capability negotiation described in the proposal. Done means producing an agreed protocol design that addresses compatibility, payload shape, and the proposed supportsCodeActionParamsInResolve capability.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, developer-experience
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100