Skip to content

executeCommandProvider fails with command .. already exists with multi-root servers #333

@Tehnix

Description

@Tehnix

Context: vscode-hie-server

After upgrading vscode-languageclient from 3.5.0 to 4.1.3, we are having problems with multiple spawned language servers, which is needed for multi-root support. I want to note that this works in 3.5.0, and some breaking change was introduced (or errors were made non-silent) in 4.x.

The error comes from hie giving back its capabilities on initialization, where it registers executeCommandProviders. When a second server gets spawned, this command already exists, and VSCode then complains about this.

The Haskell language server sends this response,

{
  "result": {
    "capabilities": {
      "textDocumentSync": {
        "openClose": true,
        "change": 2,
        "willSave": false,
        "willSaveWaitUntil": false,
        "save": { "includeText": false }
      },
      "hoverProvider": true,
      "completionProvider": {
        "resolveProvider": true,
        "triggerCharacters": ["."]
      },
      "definitionProvider": true,
      "referencesProvider": true,
      "documentHighlightProvider": true,
      "documentSymbolProvider": true,
      "codeActionProvider": true,
      "documentFormattingProvider": true,
      "documentRangeFormattingProvider": true,
      "renameProvider": true,
      "executeCommandProvider": {
        "commands": ["applyrefact:applyOne", "hare:demote"]
      }
    }
  },
  "jsonrpc": "2.0",
  "id": 0
}

which causes an error to occur and the process to get shut down on the VSCode side of things,

> command 'applyrefact:applyOne' already exists
> [alanz.vscode-hie-server]command 'applyrefact:applyOne' already exists
> Error: command 'applyrefact:applyOne' already exists
	at e.registerCommand (/Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/node/extensionHostProcess.js:594:33)
	at Object.registerCommand (/Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/node/extensionHostProcess.js:656:797)
	at ExecuteCommandFeature.register (/Users/tehnix/GitHub/Clones/vscode-hie-server/node_modules/vscode-languageclient/lib/client.js:1433:53)
	at ExecuteCommandFeature.initialize (/Users/tehnix/GitHub/Clones/vscode-hie-server/node_modules/vscode-languageclient/lib/client.js:1423:14)
	at LanguageClient.initializeFeatures (/Users/tehnix/GitHub/Clones/vscode-hie-server/node_modules/vscode-languageclient/lib/client.js:2099:21)
	at TextDocumentFeature.initialize.connection.initialize.then (/Users/tehnix/GitHub/Clones/vscode-hie-server/node_modules/vscode-languageclient/lib/client.js:1819:18)
	at <anonymous>

Generally, I'd also like there to be a better story with editor commands and multiple servers. Currently we are doing something like this on activation,

  // Register editor commands for HIE, but only register the commands once.
  if (!hieCommandsRegistered) {
    registerHiePointCommand('hie.commands.genApplicative', 'hare:genapplicative', context);
    // ...
    hieCommandsRegistered = true;
  }

and then register the command like so,

    // Get the current file and workspace folder.
    const uri = editor.document.uri;
    const folder = workspace.getWorkspaceFolder(uri);
    // If there is a client registered for this workspace, use that client.
    if (folder !== undefined && clients.has(folder.uri.toString())) {
      const client = clients.get(folder.uri.toString());
      if (client !== undefined) {
        client.sendRequest('workspace/executeCommand', cmd).then(
          hints => {
            return true;
          },
          e => {
            console.error(e);
          }
        );
      }
    }

which looks up the client on activation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    info-neededIssue requires more information from poster

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions