microsoft / vscode-languageserver-node

Language server protocol implementation for VSCode. This allows implementing language services in JS/TS running on node.js
MIT License
1.43k stars 321 forks source link

Passing arguments to vscode command in code action from non-js language server #778

Open ulugbekna opened 3 years ago

ulugbekna commented 3 years ago

When a language server (implemented in OCaml) sends a code action with a command editor.action.goToLocations, it needs to pass various arguments to the command: uri, position, locations, multiple (optional), noResultsMessage (optional), and openInPeek (optional). From diving into implementation, I have several questions:

  1. AFAIU, uri, position, locations should be of format supported by vscode, e.g., position is not common position format for lsp: {line: number, character: number} BUT {lineNumber: number, column: number}. Shouldn't command arguments be more lsp friendly and support common to LSP format?

  2. More importantly, when I pass uri, AFAIU, vscode has the following check for it (from here)

static isUri(thing: any): thing is URI {
        if (thing instanceof URI) {
            return true;
        }
        if (!thing) {
            return false;
        }
        return typeof (<URI>thing).authority === 'string'
            && typeof (<URI>thing).fragment === 'string'
            && typeof (<URI>thing).path === 'string'
            && typeof (<URI>thing).query === 'string'
            && typeof (<URI>thing).scheme === 'string'
            && typeof (<URI>thing).fsPath === 'string'
            && typeof (<URI>thing).with === 'function'
            && typeof (<URI>thing).toString === 'function';
    }

How does one send this json such that this returns true, taking into account with and toString properties?

I see there is some code that converts json to js objects, but it's minimalistic


I think that given vscode has a limited number of commands, the code could specialize handling of arguments to make it more friendly or there is some other easier way to go about this?

rcjsuen commented 3 years ago

When a language server (implemented in OCaml) sends a code action with a command editor.action.goToLocations

For starters, you are aware that editor.action.goToLocations is not mentioned anywhere in the language server protocol and is specific to Visual Studio Code, correct? This means this particular feature of your server will not work with other LSP clients.

  1. AFAIU, uri, position, locations should be of format supported by vscode, e.g., position is not common position format for lsp: {line: number, character: number} BUT {lineNumber: number, column: number}. Shouldn't command arguments be more lsp friendly and support common to LSP format?

Ideally, yes, but an editor's API does not have to conform to the LSP API.

  1. More importantly, when I pass uri, AFAIU, vscode has the following check for it (from here)
static isUri(thing: any): thing is URI {
      if (thing instanceof URI) {
          return true;
      }
      if (!thing) {
          return false;
      }
      return typeof (<URI>thing).authority === 'string'
          && typeof (<URI>thing).fragment === 'string'
          && typeof (<URI>thing).path === 'string'
          && typeof (<URI>thing).query === 'string'
          && typeof (<URI>thing).scheme === 'string'
          && typeof (<URI>thing).fsPath === 'string'
          && typeof (<URI>thing).with === 'function'
          && typeof (<URI>thing).toString === 'function';
  }

How does one send this json such that this returns true, taking into account with and toString properties?

I think the answer here is that you can't.

ulugbekna commented 3 years ago

For starters, you are aware that editor.action.goToLocations is not mentioned anywhere in the language server protocol and is specific to Visual Studio Code, correct? This means this particular feature of your server will not work with other LSP clients.

Correct.

Ideally, yes, but an editor's API does not have to conform to the LSP API.

But here we're talking more about vscode-languageserver and vscode-languageclient, which actually could glue LSP and vscode better. (I'm not criticizing someone's work or ordering them to do the work, just discussing a possibility of such a feature, whoever ends up implementing it voluntarily)

I think the answer here is that you can't.

This is my understanding as well, but that seems like quite a limitation? I think there is nothing really hard preventing this functionality.

rcjsuen commented 3 years ago

Ideally, yes, but an editor's API does not have to conform to the LSP API.

But here we're talking more about vscode-languageserver and vscode-languageclient, which actually could glue LSP and vscode better. (I'm not criticizing someone's work or ordering them to do the work, just discussing a possibility of such a feature, whoever ends up implementing it voluntarily)

Certainly, I think that vscode-languageclient could play a role here. I don't know what the maintainers think though.

I think the answer here is that you can't.

This is my understanding as well, but that seems like quite a limitation? I think there is nothing really hard preventing this functionality.

https://github.com/microsoft/vscode-languageserver-node/blob/3076e79c8e6569fcdeac61446cbffe5a20ff8034/client/src/common/client.ts#L2073-L2075

On second thoughts, I think you might be able to achieve this yourself by using middleware to intercept the returned objects and make conversions yourself to satisfy the requirements of the editor.action.goToLocations command.

dbaeumer commented 3 years ago

The best you can do is to use the middleware right now since it will allow you to modify the result before it is handed back to VS Code.

I am not sure if I want to go down the road of officially supporting this unless we come to a clearer specification of commands as requested here: https://github.com/microsoft/language-server-protocol/issues/642