From 071f9afdee9ccaf0a6e86118dbecf92046d0f5e7 Mon Sep 17 00:00:00 2001 From: Serena Duncan <57880238+smd21@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:57:54 -0400 Subject: [PATCH] Cider-dap launch issues fix (#2180) Fixed issue mentioned in #2091 where debugging in multi session would crash. Also did some general code cleanup + refactoring (in extension.ts in cider-dap) and added a bit of documentation. --------- Co-authored-by: Serena --- cider-dap/calyxDebug/built/extension.js | 177 ++++++++--------------- cider-dap/calyxDebug/extension.ts | 182 ++++++++++-------------- 2 files changed, 134 insertions(+), 225 deletions(-) diff --git a/cider-dap/calyxDebug/built/extension.js b/cider-dap/calyxDebug/built/extension.js index ac70466ef3..c79a7650f8 100644 --- a/cider-dap/calyxDebug/built/extension.js +++ b/cider-dap/calyxDebug/built/extension.js @@ -1,138 +1,91 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; Object.defineProperty(exports, "__esModule", { value: true }); var vscode = require("vscode"); var cp = require("child_process"); // Hold the debug adapter instance var debugAdapter = null; -var programName = null; // Store the program name // Create output channel var outputChannel = vscode.window.createOutputChannel("Cider dap"); +var r = new String(vscode.workspace.workspaceFolders[0].uri); +var root = r.substring(r.indexOf("://") + 3).toString(); +var disposables = []; function logToPanel(message) { - console.log("inside logPanel"); outputChannel.appendLine(message); } -// Function to get the program name from the user -function getProgramName() { - return __awaiter(this, void 0, void 0, function () { - var fileName, path; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, vscode.window.showInputBox({ - placeHolder: "Please enter the name of a futil file in the workspace folder", - value: "default.futil", - })]; - case 1: - fileName = _a.sent(); - if (fileName) { - if (!fileName.startsWith("/")) { - path = require("path"); - return [2 /*return*/, path.join(vscode.workspace.workspaceFolders[0].uri.fsPath, fileName)]; - } - return [2 /*return*/, fileName]; - } - else { - return [2 /*return*/, null]; - } - return [2 /*return*/]; - } - }); - }); -} -// Factory for multi-session var CiderDebugAdapterDescriptorFactoryServer = /** @class */ (function () { - function CiderDebugAdapterDescriptorFactoryServer(adapterPath, stdPath, workspace, outputChannel) { - logToPanel("inside constructor"); - this.adapter = new CiderDebugAdapter(adapterPath, stdPath, workspace, outputChannel); - this.stdPath = stdPath; - this.adapterPath = adapterPath; - this.workspace = workspace; - this.outputChannel = outputChannel; + function CiderDebugAdapterDescriptorFactoryServer() { } - CiderDebugAdapterDescriptorFactoryServer.prototype.createDebugAdapterDescriptor = function (session) { - // Return a new debug adapter descriptor - logToPanel("creating adapter descriptor"); - return new vscode.DebugAdapterServer(this._startDebugServer(session)); - }; - CiderDebugAdapterDescriptorFactoryServer.prototype._startDebugServer = function (session) { - logToPanel("start of startDebugServer"); - // default port: 8888 + CiderDebugAdapterDescriptorFactoryServer.prototype.createDebugAdapterDescriptor = function (session, executable) { + var stdPath = vscode.workspace.getConfiguration("cider-dap").std_lib; + var adapterPath = vscode.workspace.getConfiguration("cider-dap").path; //tried just using the executable.command but that doesnt work idk why var port = vscode.workspace.getConfiguration("cider-dap").port; + this.adapter = new CiderDebugAdapter(adapterPath, stdPath, root, outputChannel); if (!this.adapter.isServerRunning()) { - logToPanel("server is not running"); - this.adapter.start(port); - logToPanel("started dap-server"); + logToPanel("adapter descripter: calling adapter.start(port)"); + var adapterPromise = this.adapter.start(port); + return adapterPromise.then(function (res) { + return new vscode.DebugAdapterServer(res); + }, function () { throw "Failed to start debug server"; }); + } + else { + return new vscode.DebugAdapterServer(port); + } + }; + CiderDebugAdapterDescriptorFactoryServer.prototype.dispose = function () { + logToPanel("disposed multi session factory"); + if (this.adapter) { + this.adapter.stop(); } - logToPanel("exiting startDebugging"); - return port; }; return CiderDebugAdapterDescriptorFactoryServer; }()); +// Factory for single-session +var CiderDebugAdapterDescriptorFactoryExecutable = /** @class */ (function () { + function CiderDebugAdapterDescriptorFactoryExecutable() { + } + CiderDebugAdapterDescriptorFactoryExecutable.prototype.createDebugAdapterDescriptor = function (session, executable) { + // Use the DebugAdapterExecutable as the debug adapter descriptor + return new vscode.DebugAdapterExecutable(vscode.workspace.getConfiguration("cider-dap").path, [], { cwd: root }); + }; + CiderDebugAdapterDescriptorFactoryExecutable.prototype.dispose = function () { + logToPanel("disposed single session factory"); + }; + return CiderDebugAdapterDescriptorFactoryExecutable; +}()); var CiderDebugAdapter = /** @class */ (function () { function CiderDebugAdapter(adapterPath, stdPath, cwd, outputChannel) { - logToPanel("inside CiderDebugAdapter"); this.adapterPath = adapterPath; this.stdPath = stdPath; this.cwd = cwd; this.outputChannel = outputChannel; this.adapterProcess = null; - logToPanel("at the end of ciderDebugAdapter"); } CiderDebugAdapter.prototype.isServerRunning = function () { - logToPanel("checking if server is running"); return this.adapterProcess != null && this.adapterProcess.exitCode == null; }; // Start the debug adapter process CiderDebugAdapter.prototype.start = function (port) { - logToPanel("beginning of start"); + var _this = this; // Spawn a new child process for the debug adapter // Include the port as a command line argument - this.adapterProcess = cp.spawn(this.adapterPath, ["--port", port, "--tcp", "-l", this.stdPath], { cwd: this.cwd }); - // Attach event listener to capture standard output of the adapter process and log it to the output channel - this.adapterProcess.stdout.on("data", function (data) { - logToPanel(data.toString()); - }); - // Attach event listener to capture standard error of the adapter process and log it to the output channel - this.adapterProcess.stderr.on("data", function (data) { - logToPanel(data.toString()); - }); - this.adapterProcess.on("spawn", function () { - logToPanel("Debugger started on port " + port + "!"); + return new Promise(function (resolve, reject) { + _this.adapterProcess = cp.spawn(_this.adapterPath, ["--port", port, "--tcp", "-l", _this.stdPath], { cwd: _this.cwd }); + // Attach event listener to capture standard output of the adapter process and log it to the output channel + _this.adapterProcess.stdout.on("data", function (data) { + logToPanel(data.toString()); + }); + // Attach event listener to capture standard error of the adapter process and log it to the output channel + _this.adapterProcess.stderr.on("data", function (data) { + logToPanel(data.toString()); + }); + _this.adapterProcess.on("spawn", function () { + logToPanel("Debugger started on port " + port + "!"); + setTimeout(function () { return resolve(port); }, 200); //short wait to let the thing start running + }); + _this.adapterProcess.on("error", function () { + logToPanel("Debugger failed to start"); + reject(-1); + }); }); }; CiderDebugAdapter.prototype.stop = function () { @@ -148,18 +101,6 @@ var CiderDebugAdapter = /** @class */ (function () { }; return CiderDebugAdapter; }()); -// Factory for single-session -var CiderDebugAdapterDescriptorFactoryExecutable = /** @class */ (function () { - function CiderDebugAdapterDescriptorFactoryExecutable() { - } - CiderDebugAdapterDescriptorFactoryExecutable.prototype.createDebugAdapterDescriptor = function (_session) { - // Use the DebugAdapterExecutable as the debug adapter descriptor - console.log("inside adapter factory"); - console.log(vscode.workspace.getConfiguration("cider-dap").path); - return new vscode.DebugAdapterExecutable(vscode.workspace.getConfiguration("cider-dap").path, [], { cwd: vscode.workspace.rootPath }); - }; - return CiderDebugAdapterDescriptorFactoryExecutable; -}()); function activate(context) { logToPanel("Extension activated!"); var factory; @@ -167,7 +108,7 @@ function activate(context) { logToPanel("setting up with configuration '" + vscode.workspace.getConfiguration("cider-dap").sessionType + "'. You will need to reload after changing the settings if a different mode is desired."); switch (vscode.workspace.getConfiguration("cider-dap").sessionType) { case "Multi-Session": - factory = new CiderDebugAdapterDescriptorFactoryServer(vscode.workspace.getConfiguration("cider-dap").path, vscode.workspace.getConfiguration("cider-dap").std_lib, vscode.workspace.rootPath, outputChannel); + factory = new CiderDebugAdapterDescriptorFactoryServer(); break; case "Single-Session": default: @@ -175,9 +116,8 @@ function activate(context) { break; } context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory("cider-dap", factory)); - logToPanel("after start server"); - // Update the adapter path with the serverPort and use it for starting the debug adapter - logToPanel("before startDebugging"); + disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory("cider-dap", factory)); + // Update the adapter path with the serverPort and use it for starting the debug adapter - ?? logToPanel("Hello, your extension is now activated!"); } function stopDebugging() { @@ -189,7 +129,10 @@ function stopDebugging() { } } function deactivate() { + //kill server + // when is this called i don't see it on the output logs logToPanel("deactivate"); + disposables.forEach(function (d) { return d.dispose(); }); } module.exports = { activate: activate, diff --git a/cider-dap/calyxDebug/extension.ts b/cider-dap/calyxDebug/extension.ts index 7900c160ad..fea8d5e414 100644 --- a/cider-dap/calyxDebug/extension.ts +++ b/cider-dap/calyxDebug/extension.ts @@ -1,78 +1,64 @@ -import * as vscode from "vscode"; -import cp = require("child_process"); -import net = require("net"); +import * as vscode from 'vscode'; +import * as cp from "child_process" // Hold the debug adapter instance let debugAdapter = null; -let programName = null; // Store the program name // Create output channel -let outputChannel = vscode.window.createOutputChannel("Cider dap"); +const outputChannel = vscode.window.createOutputChannel("Cider dap"); +const r = new String(vscode.workspace.workspaceFolders[0].uri) +const root = r.substring(r.indexOf("://") + 3).toString() + +const disposables: vscode.Disposable[] = [] function logToPanel(message) { - console.log("inside logPanel"); outputChannel.appendLine(message); } -// Function to get the program name from the user -async function getProgramName() { - const fileName = await vscode.window.showInputBox({ - placeHolder: - "Please enter the name of a futil file in the workspace folder", - value: "default.futil", - }); - - if (fileName) { - if (!fileName.startsWith("/")) { - const path = require("path"); - return path.join( - vscode.workspace.workspaceFolders[0].uri.fsPath, - fileName - ); - } - return fileName; - } else { - return null; - } -} - -// Factory for multi-session -class CiderDebugAdapterDescriptorFactoryServer { - adapter: CiderDebugAdapter; - adapterPath: string; - stdPath: string; - workspace: string; - outputChannel: object; - - constructor(adapterPath, stdPath, workspace, outputChannel) { - logToPanel("inside constructor"); - this.adapter = new CiderDebugAdapter(adapterPath, stdPath, workspace, outputChannel); - this.stdPath = stdPath; - this.adapterPath = adapterPath; - this.workspace = workspace; - this.outputChannel = outputChannel; - } +class CiderDebugAdapterDescriptorFactoryServer implements vscode.DebugAdapterDescriptorFactory { + private adapter: CiderDebugAdapter - createDebugAdapterDescriptor(session) { - // Return a new debug adapter descriptor - logToPanel("creating adapter descriptor"); + createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable): vscode.ProviderResult { + let stdPath = vscode.workspace.getConfiguration("cider-dap").std_lib; + let adapterPath = vscode.workspace.getConfiguration("cider-dap").path //tried just using the executable.command but that doesnt work idk why + const port = vscode.workspace.getConfiguration("cider-dap").port; - return new vscode.DebugAdapterServer(this._startDebugServer(session)); - } + this.adapter = new CiderDebugAdapter(adapterPath, stdPath, root, outputChannel); - _startDebugServer(session) { - logToPanel("start of startDebugServer"); - // default port: 8888 - const port = vscode.workspace.getConfiguration("cider-dap").port; if (!this.adapter.isServerRunning()) { - logToPanel("server is not running"); - this.adapter.start(port); - logToPanel("started dap-server"); + logToPanel("adapter descripter: calling adapter.start(port)") + let adapterPromise = this.adapter.start(port) + return adapterPromise.then((res) => { + return new vscode.DebugAdapterServer(res); + }, () => { throw "Failed to start debug server" }) + } + else { + return new vscode.DebugAdapterServer(port) } + } + dispose() { + logToPanel("disposed multi session factory") + if (this.adapter) { + this.adapter.stop() + } + } +} + +// Factory for single-session +class CiderDebugAdapterDescriptorFactoryExecutable implements vscode.DebugAdapterDescriptorFactory { + createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable): vscode.ProviderResult { + // Use the DebugAdapterExecutable as the debug adapter descriptor - logToPanel("exiting startDebugging"); - return port; + return new vscode.DebugAdapterExecutable( + vscode.workspace.getConfiguration("cider-dap").path, + [], + { cwd: root } + ); + } + dispose() { + logToPanel("disposed single session factory") } } + class CiderDebugAdapter { adapterPath: string; stdPath: string; @@ -82,43 +68,43 @@ class CiderDebugAdapter { isRunning: boolean; constructor(adapterPath, stdPath, cwd, outputChannel) { - logToPanel("inside CiderDebugAdapter"); this.adapterPath = adapterPath; this.stdPath = stdPath; this.cwd = cwd; this.outputChannel = outputChannel; this.adapterProcess = null; - logToPanel("at the end of ciderDebugAdapter"); } isServerRunning() { - logToPanel("checking if server is running"); return this.adapterProcess != null && this.adapterProcess.exitCode == null; } // Start the debug adapter process start(port) { - logToPanel("beginning of start"); - // Spawn a new child process for the debug adapter // Include the port as a command line argument - this.adapterProcess = cp.spawn( - this.adapterPath, - ["--port", port, "--tcp", "-l", this.stdPath], - { cwd: this.cwd } - ); - - // Attach event listener to capture standard output of the adapter process and log it to the output channel - this.adapterProcess.stdout.on("data", (data) => { - logToPanel(data.toString()); - }); - - // Attach event listener to capture standard error of the adapter process and log it to the output channel - this.adapterProcess.stderr.on("data", (data) => { - logToPanel(data.toString()); - }); - - this.adapterProcess.on("spawn", () => { - logToPanel("Debugger started on port " + port + "!"); - }); + return new Promise((resolve, reject) => { + this.adapterProcess = cp.spawn( + this.adapterPath, + ["--port", port, "--tcp", "-l", this.stdPath], + { cwd: this.cwd } + ); + // Attach event listener to capture standard output of the adapter process and log it to the output channel + this.adapterProcess.stdout.on("data", (data) => { + logToPanel(data.toString()); + }); + + // Attach event listener to capture standard error of the adapter process and log it to the output channel + this.adapterProcess.stderr.on("data", (data) => { + logToPanel(data.toString()); + }); + this.adapterProcess.on("spawn", () => { + logToPanel("Debugger started on port " + port + "!"); + setTimeout(() => resolve(port), 200) //short wait to let the thing start running + }); + this.adapterProcess.on("error", () => { + logToPanel("Debugger failed to start"); + reject(-1) + }); + }) } stop() { @@ -133,38 +119,17 @@ class CiderDebugAdapter { } } -// Factory for single-session -class CiderDebugAdapterDescriptorFactoryExecutable { - createDebugAdapterDescriptor(_session) { - // Use the DebugAdapterExecutable as the debug adapter descriptor - console.log("inside adapter factory"); - console.log(vscode.workspace.getConfiguration("cider-dap").path); - - return new vscode.DebugAdapterExecutable( - vscode.workspace.getConfiguration("cider-dap").path, - [], - { cwd: vscode.workspace.rootPath } - ); - } -} - function activate(context) { logToPanel("Extension activated!"); let factory: vscode.DebugAdapterDescriptorFactory; // Get session type (multi or single) from package.json configuration - logToPanel("setting up with configuration '" + vscode.workspace.getConfiguration("cider-dap").sessionType + "'. You will need to reload after changing the settings if a different mode is desired.") switch (vscode.workspace.getConfiguration("cider-dap").sessionType) { case "Multi-Session": - factory = new CiderDebugAdapterDescriptorFactoryServer( - vscode.workspace.getConfiguration("cider-dap").path, - vscode.workspace.getConfiguration("cider-dap").std_lib, - vscode.workspace.rootPath, - outputChannel - ); + factory = new CiderDebugAdapterDescriptorFactoryServer(); break; case "Single-Session": @@ -176,10 +141,8 @@ function activate(context) { context.subscriptions.push( vscode.debug.registerDebugAdapterDescriptorFactory("cider-dap", factory) ); - logToPanel("after start server"); - - // Update the adapter path with the serverPort and use it for starting the debug adapter - logToPanel("before startDebugging"); + disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory("cider-dap", factory)) + // Update the adapter path with the serverPort and use it for starting the debug adapter - ?? logToPanel("Hello, your extension is now activated!"); } @@ -192,7 +155,10 @@ function stopDebugging() { } function deactivate() { + //kill server + // when is this called i don't see it on the output logs logToPanel("deactivate"); + disposables.forEach(d => d.dispose()) } module.exports = {