Skip to content

Commit 00aa3c7

Browse files
authored
Merge pull request #30 from fasfsfgs/show-errors
Errors shown in OUTPUT Panel with stacktrace
2 parents 286f79c + 7ddb231 commit 00aa3c7

File tree

4 files changed

+103
-109
lines changed

4 files changed

+103
-109
lines changed

src/clojureEval.ts

Lines changed: 66 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,86 @@
11
'use strict';
22

3-
import * as fs from 'fs';
4-
import * as os from 'os';
5-
import * as path from 'path';
63
import * as vscode from 'vscode';
74

8-
import {
9-
nREPLClient
10-
} from './nreplClient';
5+
import { nREPLClient } from './nreplClient';
6+
import { getNamespace } from './clojureProvider';
117

12-
import {
13-
ClojureProvider
14-
} from './clojureProvider';
8+
export function clojureEval(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel) {
9+
evaluate(context, outputChannel, false);
10+
}
1511

16-
interface ErrorDescription {
17-
position: vscode.Position,
18-
message: string
12+
export function clojureEvalAndShowResult(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel) {
13+
evaluate(context, outputChannel, true);
1914
}
2015

21-
export function clojureEval(context: vscode.ExtensionContext, outputChannel?: vscode.OutputChannel) {
16+
function evaluate(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel, showResults: boolean) {
17+
const editor = vscode.window.activeTextEditor;
18+
const selection = editor.selection;
2219

23-
let editor = vscode.window.activeTextEditor;
2420
let text: string = editor.document.getText();
25-
let ns: string;
26-
let match = text.match(/^[\s\t]*\((?:[\s\t\n]*(?:in-){0,1}ns)[\s\t\n]+'?([\w.\-\/]+)[\s\S]*\)[\s\S]*/);
27-
match ? ns = match[1] : ns = 'user';
28-
let selection = editor.selection;
29-
let isSelection = !selection.isEmpty;
30-
31-
if (isSelection) {
32-
text = `(ns ${ns}) ${editor.document.getText(selection)}`;
21+
if (!selection.isEmpty) {
22+
const ns: string = getNamespace(text);
23+
text = `(ns ${ns})\n${editor.document.getText(selection)}`;
3324
}
3425

35-
let port = context.workspaceState.get < number > ('port');
36-
let host = context.workspaceState.get < string > ('host');
37-
26+
const port = context.workspaceState.get<number>('port');
27+
const host = context.workspaceState.get<string>('host');
3828
if ((!port) || (!host)) {
3929
vscode.window.showInformationMessage('You should connect to nREPL first to evaluate code.')
4030
return;
4131
}
32+
const nrepl = new nREPLClient(port, host);
4233

43-
let filename = editor.document.fileName;
34+
const filename = editor.document.fileName;
4435

45-
let nrepl1 = new nREPLClient(port, host);
46-
let diagnostics = vscode.languages.createDiagnosticCollection('Compilation Errors');
47-
diagnostics.clear();
48-
nrepl1.evalFile(text, filename).then(respObjs => {
49-
respObjs.forEach(result => {
50-
if (result.out && outputChannel) {
51-
outputChannel.append(result.out);
52-
outputChannel.show();
53-
}
54-
if (result.value) {
55-
if (outputChannel) {
56-
outputChannel.appendLine(`=> ${result.value}`);
57-
outputChannel.show();
58-
} else {
59-
vscode.window.showInformationMessage('Successfully compiled');
60-
}
61-
} else if (result.ex) {
62-
let nrepl2 = new nREPLClient(port, host);
63-
nrepl2.stacktrace(result.session, (stackteace) => {
64-
vscode.window.showErrorMessage('Compilation error');
65-
let errLine = stackteace.line - 1;
66-
let errChar = stackteace.column - 1;
67-
let errFile = stackteace.file;
68-
let errFileUri: vscode.Uri;
69-
if (errFile) {
70-
errFileUri = vscode.Uri.file(errFile);
71-
} else {
72-
errFileUri = vscode.window.activeTextEditor.document.uri;
73-
}
74-
let errMsg = stackteace.message;
75-
76-
// Adjust an error position if a selection has been evaluated
77-
if (isSelection) {
78-
errLine = errLine + selection.start.line;
79-
errChar = errChar + selection.start.character;
80-
}
81-
82-
let errPos = new vscode.Position(errLine, errChar);
83-
editor.selection = new vscode.Selection(errPos, errPos);
84-
let errLineLength = editor.document.lineAt(errLine).text.length;
85-
86-
diagnostics.set(errFileUri, [new vscode.Diagnostic(new vscode.Range(errLine, errChar, errLine, errLineLength), errMsg, vscode.DiagnosticSeverity.Error)]);
87-
nrepl2.close(() => {});
88-
})
36+
nrepl.evalFile(text, filename)
37+
.then(respObjs => {
38+
if (!!respObjs[0].ex)
39+
return handleError(nrepl, outputChannel, selection, showResults, respObjs[0].session);
8940

90-
}
41+
return handleSuccess(outputChannel, showResults, respObjs);
9142
})
92-
});
93-
}
43+
.then(() => nrepl.close());
44+
}
45+
46+
function handleError(nrepl: nREPLClient, outputChannel: vscode.OutputChannel, selection: vscode.Selection, showResults: boolean, session: string) {
47+
if (!showResults)
48+
vscode.window.showErrorMessage('Compilation error');
49+
50+
return nrepl.stacktrace(session)
51+
.then(stacktraceObjs => {
52+
const stacktraceObj = stacktraceObjs[0];
53+
54+
let errLine = stacktraceObj.line - 1;
55+
let errChar = stacktraceObj.column - 1;
56+
57+
if (!selection.isEmpty) {
58+
errLine += selection.start.line;
59+
errChar += selection.start.character;
60+
}
61+
62+
outputChannel.appendLine(`${stacktraceObj.class} ${stacktraceObj.message}`);
63+
outputChannel.appendLine(` at ${stacktraceObj.file}:${errLine}:${errChar}`);
64+
65+
stacktraceObj.stacktrace.forEach(trace => {
66+
if (trace.flags.indexOf('tooling') > -1)
67+
outputChannel.appendLine(` ${trace.class}.${trace.method} (${trace.file}:${trace.line})`);
68+
});
69+
70+
outputChannel.show();
71+
});
72+
}
73+
74+
function handleSuccess(outputChannel: vscode.OutputChannel, showResults: boolean, respObjs: any[]) {
75+
if (!showResults) {
76+
vscode.window.showInformationMessage('Successfully compiled');
77+
} else {
78+
respObjs.forEach(respObj => {
79+
if (respObj.out)
80+
outputChannel.append(respObj.out);
81+
if (respObj.value)
82+
outputChannel.appendLine(`=> ${respObj.value}`);
83+
outputChannel.show();
84+
});
85+
}
86+
}

src/clojureMain.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import * as vscode from 'vscode';
66

77
import { CLOJURE_MODE } from './clojureMode';
88
import { ClojureCompletionItemProvider } from './clojureSuggest';
9-
import { clojureEval } from './clojureEval';
9+
import { clojureEval, clojureEvalAndShowResult } from './clojureEval';
1010
import { ClojureDefinitionProvider } from './clojureDefinition';
1111
import { ClojureLanguageConfiguration } from './clojureConfiguration';
1212
import { ClojureHoverProvider } from './clojureHover';
1313
import { ClojureSignatureProvider } from './clojureSignature';
1414
import { nREPLClient } from './nreplClient';
1515
import { JarContentProvider } from './jarContentProvider';
1616

17-
let connectionIndicator = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
17+
const connectionIndicator = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
1818

1919
function updateConnectionIndicator(port: number, host: string) {
2020
connectionIndicator.text = `⚡nrepl://${host}:${port}`;
@@ -32,9 +32,9 @@ function updateConnectionParams(context: vscode.ExtensionContext): void {
3232
let projectDir = vscode.workspace.rootPath;
3333

3434
if (projectDir) {
35-
let localNREPLFile = path.join(projectDir, '.nrepl-port');
35+
const localNREPLFile = path.join(projectDir, '.nrepl-port');
3636
if (fs.existsSync(localNREPLFile)) {
37-
nreplPort = Number.parseInt(fs.readFileSync(localNREPLFile, 'utf-8'))
37+
nreplPort = Number.parseInt(fs.readFileSync(localNREPLFile, 'utf-8'));
3838
}
3939
}
4040

@@ -64,7 +64,7 @@ function connect(context: vscode.ExtensionContext) {
6464
}
6565
port = Number.parseInt(value);
6666
if (!port) {
67-
vscode.window.showErrorMessage('Port number should be an integer.')
67+
vscode.window.showErrorMessage('Port number should be an integer.');
6868
return Promise.reject(false);
6969
}
7070
}).then((value) => {
@@ -90,10 +90,10 @@ function connect(context: vscode.ExtensionContext) {
9090
}
9191

9292
export function activate(context: vscode.ExtensionContext) {
93-
let evaluationResultChannel = vscode.window.createOutputChannel('Evaluation results');
93+
const evaluationResultChannel = vscode.window.createOutputChannel('Evaluation results');
9494
vscode.commands.registerCommand('clojureVSCode.connect', () => { connect(context) });
95-
vscode.commands.registerCommand('clojureVSCode.eval', () => { clojureEval(context) });
96-
vscode.commands.registerCommand('clojureVSCode.evalAndShowResult', () => { clojureEval(context, evaluationResultChannel) });
95+
vscode.commands.registerCommand('clojureVSCode.eval', () => { clojureEval(context, evaluationResultChannel) });
96+
vscode.commands.registerCommand('clojureVSCode.evalAndShowResult', () => { clojureEvalAndShowResult(context, evaluationResultChannel) });
9797
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(CLOJURE_MODE, new ClojureCompletionItemProvider(context), '.', '/'));
9898
context.subscriptions.push(vscode.languages.registerDefinitionProvider(CLOJURE_MODE, new ClojureDefinitionProvider(context)));
9999
context.subscriptions.push(vscode.languages.registerHoverProvider(CLOJURE_MODE, new ClojureHoverProvider(context)));
@@ -108,7 +108,7 @@ export function activate(context: vscode.ExtensionContext) {
108108
if (port && host) {
109109
updateConnectionIndicator(port, host);
110110
testConnection(port, host, (response) => {
111-
vscode.window.showInformationMessage(onSuccesfullConnectMessage)
111+
vscode.window.showInformationMessage(onSuccesfullConnectMessage);
112112
});
113113
}
114114
}

src/clojureProvider.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
'use strinct';
22

3-
import * as fs from 'fs';
4-
import * as os from 'os';
5-
import * as path from 'path';
63
import * as vscode from 'vscode';
7-
import {
8-
nREPLClient
9-
} from './nreplClient';
4+
5+
import { nREPLClient } from './nreplClient';
106

117
/**
128
* Base class for Clojure providers.
@@ -18,7 +14,7 @@ export class ClojureProvider {
1814
/**
1915
* @param context Extention context
2016
*/
21-
constructor(context : vscode.ExtensionContext) {
17+
constructor(context: vscode.ExtensionContext) {
2218
this.context = context;
2319
}
2420

@@ -28,8 +24,8 @@ export class ClojureProvider {
2824
protected getNREPL(): nREPLClient {
2925
let port: number;
3026
let host: string;
31-
port = this.context.workspaceState.get< number >('port');
32-
host = this.context.workspaceState.get< string >('host');
27+
port = this.context.workspaceState.get<number>('port');
28+
host = this.context.workspaceState.get<string>('host');
3329
return new nREPLClient(port, host);
3430
}
3531

@@ -39,7 +35,12 @@ export class ClojureProvider {
3935
* @param text Clojure code snippet
4036
*/
4137
protected getNamespace(text): string {
42-
let m = text.match(/^[\s\t]*\((?:[\s\t\n]*(?:in-){0,1}ns)[\s\t\n]+'?([\w\-.]+)[\s\S]*\)[\s\S]*/);
43-
return m ? m[1] : 'user';
38+
return getNamespace(text);
4439
}
45-
}
40+
41+
}
42+
43+
export function getNamespace(text: string): string {
44+
const m = text.match(/^[\s\t]*\((?:[\s\t\n]*(?:in-){0,1}ns)[\s\t\n]+'?([\w\-.]+)[\s\S]*\)[\s\S]*/);
45+
return m ? m[1] : 'user';
46+
}

src/nreplClient.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
import * as net from 'net';
4-
import {Buffer} from 'buffer';
4+
import { Buffer } from 'buffer';
55

66
import * as bencodeUtil from './bencodeUtil';
77

@@ -54,44 +54,44 @@ export class nREPLClient {
5454
}
5555

5656
public complete(symbol: string, ns: string, callback) {
57-
let msg: nREPLCompleteMessage = {op: 'complete', symbol: symbol, ns: ns};
57+
const msg: nREPLCompleteMessage = { op: 'complete', symbol: symbol, ns: ns };
5858
this.send(msg).then(respObjs => callback(respObjs[0]));
5959
}
6060

6161
public info(symbol: string, ns: string, callback) {
62-
let msg: nREPLInfoMessage = {op: 'info', symbol: symbol, ns: ns};
62+
const msg: nREPLInfoMessage = { op: 'info', symbol: symbol, ns: ns };
6363
this.send(msg).then(respObjs => callback(respObjs[0]));
6464
}
6565

6666
public eval(code: string): Promise<any[]> {
6767
return this.clone().then((new_session) => {
68-
let session_id = new_session['new-session'];
69-
let msg: nREPLSingleEvalMessage = {op: 'eval', code: code, session: session_id};
68+
const session_id = new_session['new-session'];
69+
const msg: nREPLSingleEvalMessage = { op: 'eval', code: code, session: session_id };
7070
return this.send(msg);
7171
});
7272
}
7373

7474
public evalFile(code: string, filepath: string): Promise<any[]> {
7575
return this.clone().then((new_session) => {
76-
let session_id = new_session['new-session'];
77-
let msg: nREPLEvalMessage = {op: 'load-file', file: code, 'file-path': filepath, session: session_id};
76+
const session_id = new_session['new-session'];
77+
const msg: nREPLEvalMessage = { op: 'load-file', file: code, 'file-path': filepath, session: session_id };
7878
return this.send(msg);
7979
});
8080
}
8181

82-
public stacktrace(session: string, callback) {
83-
let msg: nREPLStacktraceMessage = {op: 'stacktrace', session: session};
84-
this.send(msg).then(respObjs => callback(respObjs[0]));
82+
public stacktrace(session: string): Promise<any> {
83+
const msg: nREPLStacktraceMessage = { op: 'stacktrace', session: session };
84+
return this.send(msg);
8585
}
8686

8787
public clone(): Promise<any[]> {
88-
let msg = {op: 'clone'};
88+
const msg = { op: 'clone' };
8989
return this.send(msg).then(respObjs => respObjs[0]);
9090
}
9191

92-
public close(callback) {
93-
let msg: nREPLCloseMessage = {op: 'close'};
94-
this.send(msg).then(respObjs => callback(respObjs));
92+
public close(): Promise<any[]> {
93+
const msg: nREPLCloseMessage = { op: 'close' };
94+
return this.send(msg);
9595
}
9696

9797
private send(msg: nREPLCompleteMessage | nREPLInfoMessage | nREPLEvalMessage | nREPLStacktraceMessage | nREPLCloneMessage | nREPLCloseMessage | nREPLSingleEvalMessage): Promise<any[]> {
@@ -109,7 +109,7 @@ export class nREPLClient {
109109
const respObjects = [];
110110
client.on('data', data => {
111111
nreplResp = Buffer.concat([nreplResp, data]);
112-
const {decodedObjects, rest} = bencodeUtil.decodeObjects(nreplResp);
112+
const { decodedObjects, rest } = bencodeUtil.decodeObjects(nreplResp);
113113
nreplResp = rest;
114114
const validDecodedObjects = decodedObjects.reduce((objs, obj) => {
115115
if (!isLastNreplObject(objs))

0 commit comments

Comments
 (0)