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:
<a href="https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#textDocument_codeAction" rel="nofollow">textDocument/codeAction</a>
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: <a href="https://code.visualstudio.com/docs/extensionAPI/vscode-api" rel="nofollow">https://code.visualstudio.com/docs/extensionAPI/vscode-api</a>
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?Answer1:
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 <a href="https://github.com/spring-projects/sts4/blob/cc5b70a4f7ee711c52f422fae3d607ea5e2b82cf/vscode-extensions/vscode-concourse/package.json" rel="nofollow">example package.json</a>
Now we can use <a href="https://github.com/Microsoft/language-server-protocol/blob/20cf6216a7e30da2afcafea32e5e2593ebe7c65e/protocol.md" rel="nofollow">Version 3</a> (only a draft at the time of this writing, but already usable) of the language-server protocol. These are the interesting pieces:<ul><li>
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 <a href="https://github.com/Microsoft/language-server-protocol/issues/219" rel="nofollow">vscode issue ticket</a> about the topic of implementing quickfixes.
<strong>Important note</strong>: Version 3.2.0 of the language-server client implementation has a <a href="https://github.com/Microsoft/vscode-languageserver-node/issues/199" rel="nofollow">bug</a>, 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.