From a80c8b183c3838aa27bb8685c4a757dbe7405c4f Mon Sep 17 00:00:00 2001 From: James Norton Date: Thu, 1 Jun 2017 21:20:11 -0400 Subject: [PATCH] 130 non debug repl (#136) * Fixed some issues with running in non-debug mode. * Prepared for new release. --- CHANGELOG.md | 9 ++ README.md | 50 ++++++---- package.json | 22 +++-- src/clojureDebug.ts | 236 +++++++++++++++++++++++++++++--------------- src/extension.ts | 29 ++++-- 5 files changed, 232 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4bb94c..75a4ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changes +## V1.2.0 + +* Added optional REPL startup in non-debug mode + * Code runs twice as fast +* Fixed some bugs with test run support + * Error handing + * Clearing old errors/failures before each test run +* Added `$lein_path` template var for launch.json to fill in lein path from preferences + ## V1.1.0 * Added new test run support. diff --git a/README.md b/README.md index dfc8277..1c26d22 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Visual Studio Code Version](https://img.shields.io/badge/Visual%20Studio%20Code-1.10.1-6193DF.svg) ![Join the chat at https://gitter.im/vscode-continuum/Lobby](https://badges.gitter.im/vscode-continuum/Lobby.svg)](https://gitter.im/vscode-continuum/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -\*\***NEW** *New features for running tests with feedback*\*\* +\*\***NEW** *Running the debugger is now optional - you can launch the REPL and access other features in non-debug mode - code runs twice as fast*\*\* ## Introduction @@ -23,10 +23,11 @@ as language support and debugging. * Peek at / jump to symbol definition * Fix namespace declaration - cleans up requires/imports * Function signature help -* \*\***New** *Run tests with progress feedback in status bar and links to tests that fail or result in error in the Problems view*\*\* -* Set breakpoints -* Examine stack frames / variables at breakpoint -* Evaluate code at breakpoints +* Run tests with progress feedback in status bar and links to tests that fail or result in error in the Problems view +* Debugger (now optional - can run interactive REPL without debugging) + * Set breakpoints + * Examine stack frames / variables at breakpoint + * Evaluate code at breakpoints * Adds a Clojure specific setting for "editor.wordSeparators" to make selecting Clojure symbols easier * Project type agnostic (leiningen, boot, etc.) @@ -39,12 +40,11 @@ as language support and debugging. * Symbol search * Find references * Linter support -* Test result / VS Code problems view integration * Exception stack traces in REPL output with links to jump to file ## Installation -**tl;dr** watch the [YouTube video](https://youtu.be/73PnuVBkXxU); otherwise, follow the instructions here. Note that the video has not been updated yet to reflect the change in way [the REPL is launched](#launching-a-repl). +**tl;dr** The quickest way to get started is to clone the github [demo project](https://github.com/indiejames/clojure-code-demo) and follow the (brief) instructions in the README.md file. If you want to get started with your own project right away then read on. #### Prerequisites * [Visual Studio Code](https://code.visualstudio.com/) 1.10.1 or higher @@ -94,18 +94,10 @@ You can get started by opening a Clojure project in VS Code and creating a launc A launch.json file will be created with a default launch configuration. You should edit this file for your own environment. VS Code provides Intellisense support when editing this file to help you make valid choices. Also, as of version 0.4.0, you can set defaults for several of the fields in the extension preferences. These defaults will be used for any of the fields you leave blank. The full details of the available settings are documented at the end of this readme file, but for now the only fields you need to change are the following: -* `commandLine` - the exact command plus arguments needed to launch your REPL. The default uses leiningen and sets the profile to `debug-repl` (the one defined in the example above). You _do not_ need to use leiningen, but you do need to make sure the REPL uses the debug middleware. Also, if you do not start the REPL on the same port as in your extension preference settings then you need to specify the port in the launch configuration using the `replPort` setting. This gives you maximum flexibility in choosing the way to launch your code. It just has to run in (or provide) nREPL running with the debug middleware. -* `replPort` - Set this if you are not launching on the default port as specified in your extension preference settings. - -The extension can launch the REPL in three different ways: in the internal debug console, in an internal command terminal, or in an external terminal. This is controlled by the **console** attribute. The default uses the internal debug console. Running in a terminal can be useful if, for example, you need to type input into your program or if your program expects to run in a terminal environment. +* `commandLine` - the exact command plus arguments needed to launch your REPL. The default uses leiningen and sets the profile to `debug-repl` (the one defined in the example above). You _do not_ need to use leiningen, but you do need to make sure the REPL uses the debug middleware. If you do use leiningen you can use the `$lein_path` template variable here and the full path to the `lein` binary will be filled in from your prefrences setting. -## Starting the REPL - -The functionality of the extension is not available unless a REPL is running. You need to either launch a REPL or attach to one. We will cover launching a REPL first. - -#### Launching a REPL - -Once you have set up your profile (or otherwise enabled the nREPL middleware) and created a suitable launch.json file you can launch the REPL by going to the Debug viewlet, choosing the launch configuration you want to use, then clicking the debug icon ![START](http://i.imgur.com/ZAmkn5M.png). Note that this has changed from the previous method of launching the REPL from the command palette. +Also, if you do not start the REPL on the same port as in your extension preference settings then you need to specify the port in the launch configuration using the `replPort` setting. This gives you maximum flexibility in choosing the way to launch your code. It just has to run in (or provide) nREPL running with the debug middleware. +* `replPort` - Set this if you are not launching on the default port as specified in your extension preference settings. On a mac an example launch configuration might look like this @@ -115,7 +107,7 @@ On a mac an example launch configuration might look like this "type": "clojure", "request": "launch", "commandLine": [ - "/usr/local/bin/lein", + "$lein_path", "with-profile", "+debug-repl", "repl", @@ -130,6 +122,20 @@ On a mac an example launch configuration might look like this } ``` +The extension can launch the REPL in three different ways: in the internal debug console, in an internal command terminal, or in an external terminal. This is controlled by the **console** attribute. The default uses the internal debug console. Running in a terminal can be useful if, for example, you need to type input into your program or if your program expects to run in a terminal environment. + +\*\***NEW** *Running the debugger is now optional when starting the REPL.*\*\* + +You can launch the REPL and access all the other features in non-debug mode. Code runs twice as fast when not in debug mode - really useful if you are going to run many tests. In order to run without the debuger just add `"debug": false` to your `launch.json` file. + +## Starting the REPL + +The functionality of the extension is not available unless a REPL is running. You need to either launch a REPL or attach to one. We will cover launching a REPL first. + +#### Launching a REPL + +Once you have set up your profile (or otherwise enabled the nREPL middleware) and created a suitable launch.json file you can launch the REPL by going to the Debug viewlet, choosing the launch configuration you want to use, then clicking the debug icon ![START](http://i.imgur.com/ZAmkn5M.png). + ![LAUNCH](http://i.imgur.com/dJDFgNA.gif) This can take a while (minutes for large projects). You should see output from the REPL as is starts up in the debug console or in the terminal (for terminal launches). Eventually you should see a screen like the following (note color change in status bar at bottom). You should see the status message 'Attached to process' at the bottom and information in the debug console about the running REPLs and namespaces that were loaded. @@ -179,6 +185,7 @@ The second way to evaluate code is by typing it into the debug console input box #### Setting Breakpoints +*Note: to debug code the REPL must be started in debug mode (the default).* Currently Clojure Code supports two kinds of breakpoints, line breakpoints and exceptions breakpoints. Line breakpoints let you set set a breakpoint at a specific line in a given file. These are set by clicking in the left margin of an open editor. ![BREAKPOINT](https://media.giphy.com/media/l3q2YGpocqMDRnMTS/source.gif) @@ -197,9 +204,11 @@ If you have the source for the Java code in your source path then VS Code will d ### Running Tests -Clojure code contributes three commands to support running tests. These can can be accessed from the command palette (`cmd+shift+p` (mac) / `ctrl+shift+p` (win/linux)) and allow you to run all tests, run a single test (the one under the cursor), and run all tests in the currently opened namespace. In order to run all tests you need to tell the extension which directories contin tests that are safe to run in parallel and which ones must be run sequentially. This is done using the +Clojure code contributes three commands to support running tests. These can can be accessed from the command palette (`cmd+shift+p` (mac) / `ctrl+shift+p` (win/linux)) and allow you to run all tests, run a single test (the one under the cursor), and run all tests in the currently opened namespace. In order to run all tests you need to tell the extension which directories contain tests that are safe to run in parallel and which ones must be run sequentially. This is done using the `parallelTestDirs` and `sequentialTestDirs` settings in the launch.json file. +While the tests are running a progress bar is shown in the status bar. After the tests complete the `PROBLEM` panel provides a list of tests that failed or ran into errors while running. Clicking on these will jump to the location with the test file. Hovering over the red squiggly lines under the failed/errored tests pops up a summary of the problem. + ![TESTS](https://media.giphy.com/media/l0Iya2NoKQl2lLagw/source.gif) ### All Contributed Commands @@ -275,6 +284,7 @@ The latest version by Shaun LeBron is based on the Atom plugin and is excellent. | cwd | string | Workspace relative or absolute path to the working directory of the program being debugged. | The current workspace | | debugPort | number | JDI port on which the debugger should connect to the process to be debugged. | 8030 | | debugReplPort | number | Port on which the client/debugger nREPL should listen. | 5556 | +| debug | boolean | If true the REPL starts in debug mode | true | | env | map | Environment variables passed to the program. | {} | | leinPath | string | Path the the lein executable. | "/usr/local/bin/lein" | | refreshOnLaunch | boolean | Automatically load all namespaces on launch. | true | diff --git a/package.json b/package.json index f391658..eee434f 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Clojure Code", "license": "MIT", "version": "1.1.0", - "debugMiddlewareVersion": "0.5.1", + "debugMiddlewareVersion": "0.5.2", "publisher": "jamesnorton", "description": "Clojure debugger / nREPL / language support for Visual Studio Code.", "preview": false, @@ -235,7 +235,7 @@ "toolsJar": { "type": "string", "description": "Path to the tools.jar in your Java installation.", - "default": "${env.JAVA_HOME}/lib/tools.jar" + "default": "$tools_jar_path" }, "cwd": { "type": "string", @@ -244,8 +244,7 @@ }, "leinPath": { "type": "string", - "description": "Path the the lein executable.", - "default": "/usr/local/bin/lein" + "description": "Path the the lein executable." }, "replHost": { "type": "string", @@ -263,6 +262,11 @@ "type": "number", "description": "JDI port on which the debugger should connect to the process to be debugged." }, + "debug": { + "type": "boolean", + "description": "Whether or not to start the debugger.", + "default": true + }, "sideChannelPort": { "type": "number", "description": "Port on which the debugger should talk to the extension." @@ -305,8 +309,7 @@ }, "leinPath": { "type": "string", - "description": "Path the the lein executable.", - "default": "/usr/local/bin/lein" + "description": "Path the the lein executable." }, "replPort": { "type": "number", @@ -323,6 +326,11 @@ "description": "JDI port on which the debugger should connect to the process to be debugged.", "default": 8030 }, + "debug": { + "type": "boolean", + "description": "Whether or not to start the debugger.", + "default": true + }, "sideChannelPort": { "type": "number", "description": "Port on which the debugger should talk to the extension.", @@ -361,7 +369,7 @@ "initialConfigurations": [ { "commandLine": [ - "lein", + "$lein_path", "with-profile", "+debug-repl", "repl", diff --git a/src/clojureDebug.ts b/src/clojureDebug.ts index 7856d72..20b6ace 100644 --- a/src/clojureDebug.ts +++ b/src/clojureDebug.ts @@ -41,7 +41,9 @@ let projectClj = `(defproject repl_connect "0.1.0-SNAPSHOT" // Constants to represent the various states of the debugger class DebuggerState { public static get PRE_LAUNCH(): string { return "PRE_LAUNCH"; } + public static get DEBUGGED_REPL_STARTED(): string { return "DEBUGGED_REPL_STARTED"} public static get REPL_STARTED(): string { return "REPL_STARTED"; } + public static get REPL_ATTACHED(): string { return "REPL_ATTACHED"} public static get DEBUGGER_ATTACHED(): string { return "DEBUGGER_ATTACHED"; } public static get REPL_READY(): string { return "REPL_READY"; } public static get LAUNCH_COMPLETE(): string { return "LAUNCH_COMPLETE"; } @@ -67,6 +69,8 @@ export interface BaseRequestArguments { debugReplPort: number; // Port for JDWP connection debugPort: number; + // Whether or not to start the debugger - false means start the REPL but not the debugger + debug: boolean; // Port for side channel sideChannelPort: number; // Path to lein @@ -97,7 +101,7 @@ export interface LaunchRequestArguments extends BaseRequestArguments { // The environment variables that should be set when running the target. env: {}; // Refresh namespaces on launch. Defaults to true. - refreshOnLaunch?: boolean; + refreshOnLaunch: boolean; } // needed because Array.includes was not available on Windows or more likely I just don't know @@ -444,6 +448,22 @@ class ClojureDebugSession extends DebugSession { } } + if (this._debuggerState == DebuggerState.REPL_STARTED && stripped.search(/user=>/) != -1) { + // tell the extension to connect + const reqId = this.getNextRequestId() + let primaryReplPort = 5555; + if (args.replPort) { + primaryReplPort = args.replPort + } + let replHost = "127.0.0.1" + if (args["replHost"]) { + replHost = args["replHost"] + } + this.requestData[reqId] = {response: response}; + this.sideChannel.emit("connect-to-repl", {id: reqId, hostPort: replHost + ":" + primaryReplPort}) + this._debuggerState = DebuggerState.REPL_ATTACHED + } + this.pout(cleanOutput(output)) } @@ -672,7 +692,7 @@ class ClojureDebugSession extends DebugSession { this.debuggerRepl.stdout.on('data', (data) => { const output = '' + data; - if ((output.search(/nREPL server started/) != -1)) { + if ((output.search(/nREPL server started/) != -1)) { self._debuggerState = DebuggerState.REPL_READY; self.replConnection = new ReplConnection(); self.replConnection.connect("127.0.0.1", replPort, @@ -747,35 +767,45 @@ class ClojureDebugSession extends DebugSession { } private setUpDebugREPL(response: DebugProtocol.LaunchResponse, args: BaseRequestArguments){ - const self = this; - this.baseArgs = args; - - const env = {"HOME": process.env["HOME"], "DEBUG_MIDDLEWARE_VERSION": args.middlewareVersion, "PATH_TO_TOOLS_JAR": args.toolsJar}; - let primaryReplPort = 5555; if (args.replPort) { primaryReplPort = args.replPort; } - let debugReplPort = 5556; - if (args.debugReplPort) { - debugReplPort = args.debugReplPort; - } + if (args.debug) { - let debugPort = 8030; - if (args.debugPort) { - debugPort = args.debugPort; - } + this.baseArgs = args; + + const env = {"HOME": process.env["HOME"], "DEBUG_MIDDLEWARE_VERSION": args.middlewareVersion, "PATH_TO_TOOLS_JAR": args.toolsJar}; + + + + let debugReplPort = 5556; + if (args.debugReplPort) { + debugReplPort = args.debugReplPort; + } + + let debugPort = 8030; + if (args.debugPort) { + debugPort = args.debugPort; + } + + let leinPath = "/usr/local/bin/lein"; + if (args.leinPath) { + leinPath = args.leinPath; + } + + this.debuggerRepl = spawn(leinPath, ["repl", ":headless", ":port", "" + debugReplPort], {cwd: this.tmpProjectDir, env: env }); + this._debuggerState = DebuggerState.REPL_STARTED; + console.log("DEBUGGER REPL STARTED"); + this.connectToDebugREPL(response, args, primaryReplPort, debugReplPort, debugPort); - let leinPath = "/usr/local/bin/lein"; - if (args.leinPath) { - leinPath = args.leinPath; } + // else { - self.debuggerRepl = spawn(leinPath, ["repl", ":headless", ":port", "" + debugReplPort], {cwd: this.tmpProjectDir, env: env }); - self._debuggerState = DebuggerState.REPL_STARTED; - console.log("DEBUGGER REPL STARTED"); - self.connectToDebugREPL(response, args, primaryReplPort, debugReplPort, debugPort); + // response.success = true; + // this.sendResponse(response); + // } } @@ -847,7 +877,18 @@ class ClojureDebugSession extends DebugSession { jvmOpts = jvmOpts + " " + args.env["JVM_OPTS"]; } - let env = {"HOME": home, "CLOJURE_DEBUG_JDWP_PORT": "" + debugPort, "JVM_OPTS": jvmOpts, "PATH_TO_TOOLS_JAR": args.toolsJar}; + let env = {"HOME": home} + if (args.debug) { + env["CLOJURE_DEBUG_JDWP_PORT"] = "" + debugPort + env["JVM_OPTS"] = jvmOpts + env["PATH_TO_TOOLS_JAR"] = args.toolsJar + } else { + if (args.env && args.env["JVM_OPTS"]) { + env["JVM_OPTS"] = args.env["JVM_OPTS"] + } + env["PATH_TO_TOOLS_JAR"] = args.toolsJar + } + for (let attrname in args.env) { if (attrname != "JVM_OPTS") { env[attrname] = args.env[attrname]; @@ -896,6 +937,7 @@ class ClojureDebugSession extends DebugSession { let cmdArgs = args.commandLine.slice(1, args.commandLine.length); this.primaryRepl = spawn(cmd, cmdArgs, {cwd: args.cwd, env: env}); + this._debuggerState = DebuggerState.REPL_STARTED this.primaryRepl.stdout.on('data', (data) => { const output = '' + data; @@ -1020,77 +1062,104 @@ class ClojureDebugSession extends DebugSession { } protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void { - const clientLines = args.lines; - const debugLines = JSON.stringify(clientLines, null, 4); - console.log(debugLines); - const srcPath = args.source.path; - // make exploded jar file paths amenable to cdt - const cdtPath = srcPath.replace(".jar/", ".jar:/"); - const reqId = this.getNextRequestId(); - this.requestData[reqId] = {response: response, args: args, path: srcPath}; - const self = this; + if (this.replConnection){ - if (this._debuggerSubState == DebuggerSubState.BREAKPOINT_HIT) { - self.replConnection.clearBreakpoints(cdtPath, (err: any, result: any) => { - if (err) { - // TODO figure out what to do here - console.error(err); - } else { - // don't try to load the namespace first if we are already - // at a breakpoint - self.finishBreakPointsRequest(response, args, srcPath); - } - }); - } else { - this.replConnection.clearBreakpoints(cdtPath, (err: any, result: any) => { - if (err) { - // TODO figure out what to do here - console.error(err); - } else { - const fileContents = readFileSync(srcPath); - //const regex = /\(ns\s+?(.*?)(\s|\))/; - const regex = /\(ns(\s+\^\{[\s\S]*?\})?\s+([\w\.\-_\d\*\+!\?]+)/; - const ns = regex.exec(fileContents.toString())[2]; - - // Load the associated namespace into the REPL. - // We have to use the extension connection to load the namespace - // We must wait for the response before replying with the SetBreakpointResponse. - self.sideChannel.emit("load-namespace", {id: reqId, ns: ns}); - } - }); + const clientLines = args.lines; + const debugLines = JSON.stringify(clientLines, null, 4); + console.log(debugLines); + const srcPath = args.source.path; + // make exploded jar file paths amenable to cdt + const cdtPath = srcPath.replace(".jar/", ".jar:/"); + const reqId = this.getNextRequestId(); + this.requestData[reqId] = {response: response, args: args, path: srcPath}; + const self = this; + + if (this._debuggerSubState == DebuggerSubState.BREAKPOINT_HIT) { + self.replConnection.clearBreakpoints(cdtPath, (err: any, result: any) => { + if (err) { + // TODO figure out what to do here + console.error(err); + } else { + // don't try to load the namespace first if we are already + // at a breakpoint + self.finishBreakPointsRequest(response, args, srcPath); + } + }); + } else { + this.replConnection.clearBreakpoints(cdtPath, (err: any, result: any) => { + if (err) { + // TODO figure out what to do here + console.error(err); + } else { + const fileContents = readFileSync(srcPath); + //const regex = /\(ns\s+?(.*?)(\s|\))/; + const regex = /\(ns(\s+\^\{[\s\S]*?\})?\s+([\w\.\-_\d\*\+!\?]+)/; + const ns = regex.exec(fileContents.toString())[2]; + + // Load the associated namespace into the REPL. + // We have to use the extension connection to load the namespace + // We must wait for the response before replying with the SetBreakpointResponse. + self.sideChannel.emit("load-namespace", {id: reqId, ns: ns}); + } + }); + + } + + } else { + // Not a debug session, so just return + response.body = { + breakpoints: [] + } + response.success = false + this.sendResponse(response) } + // TODO reject breakpoint requests outside of a namespace } protected setExceptionBreakPointsRequest(response: DebugProtocol.SetExceptionBreakpointsResponse, args: DebugProtocol.SetExceptionBreakpointsArguments): void { - // get the class type for the exceptions from the extension (response handler will do the rest) - const reqId = this.getNextRequestId(); - this.requestData[reqId] = {response: response, args: args} - this.sideChannel.emit('get-breakpoint-exception-class', {id: reqId}); + if (this.replConnection) { + // get the class type for the exceptions from the extension (response handler will do the rest) + const reqId = this.getNextRequestId(); + this.requestData[reqId] = {response: response, args: args} + this.sideChannel.emit('get-breakpoint-exception-class', {id: reqId}); + } else { + response.success = false; + this.sendResponse(response) + } } protected threadsRequest(response: DebugProtocol.ThreadsResponse): void { - const debug = this; - this.replConnection.listThreads((err: any, result: any) => { - console.log(result); - debug.updateThreads(result[0]["threads"]); + if (this.replConnection) { + const debug = this; + this.replConnection.listThreads((err: any, result: any) => { + console.log(result); + debug.updateThreads(result[0]["threads"]); - console.log("Sending threads to debugger:\n"); - for (let i = 0; i < debug.threads.length; i++) { - let th = debug.threads[i]; - console.log("id: " + th.id + " name: " + th.name); - } + console.log("Sending threads to debugger:\n"); + for (let i = 0; i < debug.threads.length; i++) { + let th = debug.threads[i]; + console.log("id: " + th.id + " name: " + th.name); + } + response.body = { + threads: debug.threads + }; + + debug.sendResponse(response); + }); + } else { response.body = { - threads: debug.threads - }; + threads: [] + } + response.success = false + this.sendResponse(response) + } - debug.sendResponse(response); - }); } @@ -1225,12 +1294,17 @@ class ClojureDebugSession extends DebugSession { protected continueRequest(response: DebugProtocol.ContinueResponse, args: DebugProtocol.ContinueArguments): void { const debug = this; - this.replConnection.continue((err: any, result: any) => { - // TODO handle errors here + if (this.replConnection) { + this.replConnection.continue((err: any, result: any) => { + // TODO handle errors here + debug._debuggerSubState = DebuggerSubState.NOOP; + debug.sendResponse(response); + console.log(result); + }); + } else { debug._debuggerSubState = DebuggerSubState.NOOP; debug.sendResponse(response); - console.log(result); - }); + } } protected nextRequest(response: DebugProtocol.NextResponse, args: DebugProtocol.NextArguments): void { diff --git a/src/extension.ts b/src/extension.ts index 17a6254..aa665ee 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -459,6 +459,10 @@ function removeReplActions(context: ExtensionContext) { // Add Diagnostics for tests that fail or error function handleTestOutput(result: any) { + if (diagnostics) { + diagnostics.clear() + } + const errMsg = result[0]["err-msg"] if (errMsg){ //const message = "Error Running Tests\n\r" + errMsg @@ -494,7 +498,7 @@ function handleTestOutput(result: any) { const source: string = e["source"] let file let line - let m = source.match(/\(.*?\) \((.*?):(\d+)\)/) + let m = source.match(/.*? \((.*?):(\d+)\)/) if (m) { file = m[1] line = Number(m[2]) - 1 @@ -648,7 +652,6 @@ function setUpReplActions(context: ExtensionContext, rconn: ReplConnection){ if (!replRunning) { window.showErrorMessage("Please launch or attach to a REPL before running tests."); } else { - diagnostics = languages.createDiagnosticCollection("test results") if (cfg.get("refreshNamespacesBeforeRunnningAllTests") === true) { console.log("Calling refresh...") @@ -779,9 +782,7 @@ function connect(reqId: number, sock:SocketIO.Socket, host: string, port: number if (err) { console.error(err); } else { - outputChannel.appendLine(result); rconn.eval("(use 'compliment.core)", (err: any, result: any) => { - outputChannel.appendLine(result); console.log("Compliment namespace loaded"); replRunning = true; @@ -796,6 +797,7 @@ function connect(reqId: number, sock:SocketIO.Socket, host: string, port: number }); } +// fill in the launch.json config that was chosen to start the REPL function fillInConfig(config: any): any { let extConfig = workspace.getConfiguration("clojure"); if (!config["toolsJar"]) { @@ -806,6 +808,12 @@ function fillInConfig(config: any): any { config["leinPath"] = extConfig["leinPath"]; } + if (config["commandLine"]) { + config["commandLine"] = config["commandLine"].map( (entry: string): string => { + return entry.replace("$lein_path", extConfig["leinPath"]) + } ) + } + if (config["refreshOnLaunch"] == null) { config["refreshOnLaunch"] = extConfig["refreshOnLaunch"]; } @@ -822,6 +830,10 @@ function fillInConfig(config: any): any { config["debugPort"] = extConfig["debugPort"]; } + if (config["debug"] == null) { + config["debug"] = true + } + if (!config["sideChannelPort"]) { config["sideChannelPort"] = extConfig["sideChannelPort"]; } @@ -872,7 +884,12 @@ function startSession(config: any): StartSessionResult { result.content = config; let fixConfig = Promise.resolve(); fixConfig.then(() => { - window.setStatusBarMessage("Starting debugger"); + if (config["debug"]) { + window.setStatusBarMessage("Starting debugger") + } else { + window.setStatusBarMessage("Starting REPL") + } + commands.executeCommand('vscode.startDebug', config); }); const sideChannelPort = config["sideChannelPort"]; @@ -887,7 +904,7 @@ export function activate(context: ExtensionContext) { languages.setLanguageConfiguration("clojure", languageConfiguration); - outputChannel = window.createOutputChannel("Clojure"); + diagnostics = languages.createDiagnosticCollection("test results") // Keep track of the active file editor so we can execute code in the namespace currently // being edited. This is necessary because as of VS Code 1.5 the input to the debugger