Open michaelpj opened 2 years ago
Example in the wild: https://github.com/haskell/haskell-language-server/blob/9415e55672a0c60a353f0bff3ae8546bdf0e7903/hls-plugin-api/src/Ide/Types.hs#L185
This handles the case of missing code action support by making a fallback command. That would fit nicely into this framework.
Many specification features take the form of optional additional fields on responses. This means that so long as clients ignore fields they don't recognize or handle, servers can be fairly lax about checking the client capabilities when they return responses.
However:
InsertReplaceTextEdit
is not a subclass of aTextEdit
, so a client that doesn't supportInsertReplaceTextEdit
s will probably just fail if you send it one.labelDetails
field for aCompletionItem
, you might lose useful information for the user if it is just dropped, which otherwise you might have put into thelabel
.But doing better currently relies a lot of discipline to check the client capabilities everywhere and have lots of branching logic.
So here's an idea: provide a way to automatically downgrade a response to match the client capabilities. In many cases this will be trivial: drop the unsupported fields. But in other cases we can do a translation that does its best to carry on as much information as possible: turn an
InsertReplaceTextEdit
into aTextEdit
by taking the insertion edit; droplabelDetails
by adding it to thelabel
, etc. And if we can't do anything we can perhaps emit a warning.Take that, stick it in a typeclass, and then we can give people a generic downgrader that they can stick onto the end of their handlers to ensure they get appropriate output.