Skip to content

Commit

Permalink
Ensure clojure-lsp commands are still registered
Browse files Browse the repository at this point in the history
This resolves a regression from BetterThanTomorrow#2020 which prevents certain vscode
operations such as organise-imports and add-missing-import from
functioning correctly.

This was a result of disabling the automatic command registrations being
performed by the lsp client. Originally it was assumed that these
commands were unused, however they are used internally by vscode to
handle their native organise-imports and related operations.

This is now fixed by manually registering the missing commands with the
added functionality of multi-client support.

Addresses BetterThanTomorrow#2041
Fixes BetterThanTomorrow#2040
  • Loading branch information
julienvincent committed Jan 30, 2023
1 parent 5827fb7 commit ada725e
Showing 1 changed file with 96 additions and 59 deletions.
155 changes: 96 additions & 59 deletions src/lsp/commands/lsp-commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as vscode_lsp from 'vscode-languageclient/node';
import * as calva_utils from '../../utilities';
import * as defs from '../definitions';
import * as vscode from 'vscode';
Expand Down Expand Up @@ -53,16 +54,37 @@ function sendCommandRequest(
}

client
.sendRequest('workspace/executeCommand', {
.sendRequest(vscode_lsp.ExecuteCommandRequest.type, {
command,
arguments: args,
})
.catch((error) => {
return client.handleFailedRequest(
vscode_lsp.ExecuteCommandRequest.type,
undefined,
error,
undefined
);
})
.catch((e) => {
console.error('Failed to execute lsp command', e);
});
}

function registerLspCommand(
const getLSPCommandParams = () => {
const editor = calva_utils.getActiveTextEditor();
const document = calva_utils.tryToGetDocument(editor.document);
if (!document || document.languageId !== 'clojure') {
return;
}

const line = editor.selection.start.line;
const column = editor.selection.start.character;
const doc_uri = `${document.uri.scheme}://${document.uri.path}`;
return [doc_uri, line, column];
};

function registerUserspaceLspCommand(
clients: defs.LSPClientMap,
command: ClojureLspCommand
): vscode.Disposable {
Expand All @@ -71,18 +93,26 @@ function registerLspCommand(
m.substring(1).toUpperCase()
)}`;
return vscode.commands.registerCommand(vscodeCommand, async () => {
const editor = calva_utils.getActiveTextEditor();
const document = calva_utils.tryToGetDocument(editor.document);
if (document && document.languageId === 'clojure') {
const line = editor.selection.start.line;
const column = editor.selection.start.character;
const docUri = `${document.uri.scheme}://${document.uri.path}`;
const params = [docUri, line, column];
const extraParam = command.extraParamFn ? await command.extraParamFn() : undefined;
if (!command.extraParamFn || (command.extraParamFn && extraParam)) {
sendCommandRequest(clients, command.command, extraParam ? [...params, extraParam] : params);
}
const params = getLSPCommandParams();
if (!params) {
return;
}

const extraParam = command.extraParamFn ? await command.extraParamFn() : undefined;
if (command.extraParamFn && !extraParam) {
return;
}

sendCommandRequest(clients, command.command, extraParam ? [...params, extraParam] : params);
});
}

function registerInternalLspCommand(
clients: defs.LSPClientMap,
command: ClojureLspCommand
): vscode.Disposable {
return vscode.commands.registerCommand(command.command, async (...args) => {
sendCommandRequest(clients, command.command, args);
});
}

Expand Down Expand Up @@ -124,51 +154,46 @@ export function registerLspCommands(clients: defs.LSPClientMap) {
];

const clojureLspCommands: ClojureLspCommand[] = [
{
command: 'clean-ns',
},
{
command: 'add-missing-libspec',
},
// This seems to be similar to Calva's rewrap commands
//{
// command: 'cycle-coll'
//},
{
command: 'cycle-privacy',
},
{
command: 'drag-backward',
category: 'clojureLsp',
},
{
command: 'drag-forward',
category: 'clojureLsp',
},
{
command: 'expand-let',
},
{
command: 'thread-first',
},
{
command: 'thread-first-all',
},
{
command: 'thread-last',
},
{
command: 'thread-last-all',
},
{
command: 'inline-symbol',
},
{
command: 'unwind-all',
},
{
command: 'unwind-thread',
},
{ command: 'add-import-to-namespace' },
{ command: 'add-missing-import' },
{ command: 'add-missing-libspec' },
{ command: 'add-require-suggestion' },
{ command: 'change-coll' },
{ command: 'clean-ns' },
{ command: 'create-function' },
{ command: 'create-test' },
{ command: 'cycle-coll' },
{ command: 'cycle-keyword-auto-resolve' },
{ command: 'cycle-privacy' },
{ command: 'demote-fn' },
{ command: 'destructure-keys' },
{ command: 'drag-backward', category: 'clojureLsp' },
{ command: 'drag-forward', category: 'clojureLsp' },
{ command: 'drag-param-backward' },
{ command: 'drag-param-forward' },
{ command: 'expand-let' },
{ command: 'extract-to-def' },
{ command: 'get-in-all' },
{ command: 'get-in-less' },
{ command: 'get-in-more' },
{ command: 'get-in-none' },
{ command: 'inline-symbol' },
{ command: 'move-coll-entry-down' },
{ command: 'move-coll-entry-up' },
{ command: 'move-form' },
{ command: 'promote-fn' },
{ command: 'resolve-macro-as' },
{ command: 'restructure-keys' },
{ command: 'sort-clauses' },
{ command: 'sort-map' },
{ command: 'suppress-diagnostic' },
{ command: 'thread-first' },
{ command: 'thread-first-all' },
{ command: 'thread-last' },
{ command: 'thread-last-all' },
{ command: 'unwind-all' },
{ command: 'unwind-thread' },

{
command: 'introduce-let',
extraParamFn: makePromptForInput('Bind to'),
Expand All @@ -193,7 +218,19 @@ export function registerLspCommands(clients: defs.LSPClientMap) {
});
}),

...clojureLspCommands.map((command) => registerLspCommand(clients, command)),
...clojureLspCommands.map((command) => registerUserspaceLspCommand(clients, command)),

/**
* The clojure-lsp server previously used to dynamically register all of these top-level commands but that behaviour was
* disabled to add support for provisioning multiple lsp clients in the same vscode window. The build-in behaviour resulted
* in command registration conflicts.
*
* Independently there are some vscode operations (such as organise-imports) which are bound to execute these lsp commands
* which are now no longer dynamically registered by the client.
*
* We therefore manually register them here with added support for selecting the appropriate active lsp client on execution.
*/
...clojureLspCommands.map((command) => registerInternalLspCommand(clients, command)),
];
}

Expand Down

0 comments on commit ada725e

Please sign in to comment.