Skip to content

Commit

Permalink
Handle the unknown-op status from test commands.
Browse files Browse the repository at this point in the history
Calva currently fails silently when the test commands fail due to the
unknown-op status. Here we handle that error and show a warning message
when it occurs. This doesn't address the root cause of the issue, but it
will help users to understand the problem.

This will help to debug #1269
  • Loading branch information
marcomorain committed Oct 27, 2021
1 parent 3377305 commit 8762921
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 23 deletions.
63 changes: 44 additions & 19 deletions src/nrepl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,39 @@ import { getStateValue, prettyPrint } from '../../out/cljs-lib/cljs-lib';
import { getConfig } from '../config';
import { log, Direction, loggingEnabled } from './logging';

// The result object that is returned from an nREPL command.
interface Result {
id: string
op: string
session: string
status: string[]
err?: string
error?: string
reloading?: string[]
}

// https://nrepl.org/nrepl/design/handlers.html
// If the handler being used by an nREPL server does not recognize or cannot
// perform the operation indicated by a request message’s :op, then it should
// respond with a message containing a :status of "unknown-op".
function unknownOperation(res: Result): boolean {
return res.status.indexOf("unknown-op") > -1;
}

// When a test command fails becuase of an unknonw-op (usually caused by missing
// middleware), we can mark the operation as failed, so that we can show a message
// in the UI to the user.
function testResultHandler(resolve: any, reject: any) {
return (res: Result): boolean => {
if (unknownOperation(res)) {
reject("The server does not recognize or cannot perform the '" + res.op + "' operation");
} else {
resolve(res);
}
return true;
}
}

/** An nREPL client */
export class NReplClient {
private _nextId = 0;
Expand Down Expand Up @@ -176,7 +209,7 @@ export class NReplSession {
}
}

messageHandlers: { [id: string]: (msg: any) => boolean } = {};
messageHandlers: { [id: string]: (msg: Result) => boolean } = {};
replType: ReplSessionType = null;

close() {
Expand Down Expand Up @@ -395,7 +428,7 @@ export class NReplSession {
this.client.write({ op: "info", ns, symbol, id, session: this.sessionId })
})
}

classpath() {
return new Promise<any>((resolve, reject) => {
let id = this.client.nextId;
Expand All @@ -411,7 +444,11 @@ export class NReplSession {
return new Promise<any>((resolve, reject) => {
const id = this.client.nextId;
this.messageHandlers[id] = (msg) => {
resolve(msg);
if (unknownOperation(msg)) {
reject("The server does not recognize or cannot perform the '" + msg.op + "' operation");
} else {
resolve(msg);
}
return true;
};
this.client.write({
Expand All @@ -433,10 +470,7 @@ export class NReplSession {
testNs(ns: string) {
return new Promise<any>((resolve, reject) => {
let id = this.client.nextId;
this.messageHandlers[id] = (msg) => {
resolve(msg);
return true;
}
this.messageHandlers[id] = testResultHandler(resolve, reject);
this.client.write({
op: "test-var-query", ns, id, session: this.sessionId, "var-query": {
"ns-query": {
Expand All @@ -450,32 +484,23 @@ export class NReplSession {
testAll() {
return new Promise<any>((resolve, reject) => {
let id = this.client.nextId;
this.messageHandlers[id] = (msg) => {
resolve(msg);
return true;
}
this.messageHandlers[id] = testResultHandler(resolve, reject);
this.client.write({ op: "test-all", id, session: this.sessionId, "load?": true });
})
}

retest() {
return new Promise<any>((resolve, reject) => {
let id = this.client.nextId;
this.messageHandlers[id] = (msg) => {
resolve(msg);
return true;
}
this.messageHandlers[id] = testResultHandler(resolve, reject);
this.client.write({ op: "retest", id, session: this.sessionId });
})
}

loadAll() {
return new Promise<any>((resolve, reject) => {
let id = this.client.nextId;
this.messageHandlers[id] = (msg) => {
resolve(msg);
return true;
}
this.messageHandlers[id] = testResultHandler(resolve, reject);
this.client.write({ op: "ns-load-all", id, session: this.sessionId });
})
}
Expand Down
16 changes: 12 additions & 4 deletions src/testRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ function runAllTestsCommand() {
vscode.window.showInformationMessage('You must connect to a REPL server to run this command.')
return;
}
runAllTests().catch(() => { });
runAllTests().catch((msg) => {
vscode.window.showWarningMessage(msg)
});
}

async function considerTestNS(ns: string, session: NReplSession, nss: string[]): Promise<string[]> {
Expand Down Expand Up @@ -219,15 +221,19 @@ function runTestUnderCursorCommand() {
vscode.window.showInformationMessage('You must connect to a REPL server to run this command.')
return;
}
runTestUnderCursor().catch(() => { });
runTestUnderCursor().catch((msg) => {
vscode.window.showWarningMessage(msg)
});
}

function runNamespaceTestsCommand() {
if (!util.getConnectedState()) {
vscode.window.showInformationMessage('You must connect to a REPL server to run this command.')
return;
}
runNamespaceTests();
runNamespaceTests().catch((msg) => {
vscode.window.showWarningMessage(msg)
});
}

async function rerunTests(document = {}) {
Expand All @@ -243,7 +249,9 @@ function rerunTestsCommand() {
vscode.window.showInformationMessage('You must connect to a REPL server to run this command.')
return;
}
rerunTests();
rerunTests().catch((msg) => {
vscode.window.showWarningMessage(msg)
});
}

export default {
Expand Down

0 comments on commit 8762921

Please sign in to comment.