Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement quickfix via a language server

Tags:

I've implemented a language server which provides some linting. The linter checks for required properties and issues 'missing property' errors. I would like to have corresponding 'insert missing property' quickfixes for these errors.

I think the general area of the LSP protocol meant for this is:

textDocument/codeAction

With this, the server could return a 'insert missing property' command for a 'missing property' diagnostic marker.

But how does the server implement the 'insert missing property' command itself?

Looking through the lsp spec, I can't find anything that lets the server register commands.

I did find some info about vscode apis for registering commands on the client side here: https://code.visualstudio.com/docs/extensionAPI/vscode-api

So I suppose I could register and implement the 'insert missing properties' on the client side, but...

The client side is only a 'dumb' wrapper delegating most work to the server. As such it doesn't really understand the document structure and isn't a very good place to implement transformations of the document that require understanding that structure.

It seems my best option is to add some 'custom' protocol to my language server so that I can implement the 'insert missing properties' command on the client side, but delegate the hard part of computing the edits for the quickfix back to the server.

Or... is there a better way?

like image 547
Kris Avatar asked Apr 10 '17 16:04

Kris


1 Answers

Yes there is a better way which does not require any custom protocol extensions. These are roughly the steps:

First make sure that your vscode extension's package.json has an up-to-date language-server-client. Mine uses version 3.2.x. I also needed to update vscode engine version to 1.6.x. Here's an example package.json

Now we can use Version 3 (only a draft at the time of this writing, but already usable) of the language-server protocol. These are the interesting pieces:

  • textDocument/codeAction: implement this on the server-side to compute a list of commands that represent the quickfixes.

  • workspace/executeCommand: implement this in the server-side to execute the commands. It can make use of workspace/applyEdit to send a request to the client to perform changes to the documents in the workspace.

  • client/registerCapability: The server can call this with a ExecuteCommandRegistrationOptions object. This registers your server-side command(s) with the client, so that it knows to execute them via the workspace/executeCommand handler implemented in the previous step.

  • initialize: Alternatively to using client/registerCapability you can also register server-side commands by returning a WorkspaceCapabilities object with an appropriate setting for its executeCommandProvider attribute. This method is slightly less complex (but can only be used if you don't require registering/unregistering of commands dynamically).

See also this vscode issue ticket about the topic of implementing quickfixes.

Important note: Version 3.2.0 of the language-server client implementation has a bug, it uses the wrong name client/registerFeature instead of client/registerCapability so you may have to work around that until that bug is fixed. If you use the initialize method then you are not affected by this bug.

like image 125
Kris Avatar answered Sep 25 '22 11:09

Kris