diff --git a/modules/gdb-dap/debugSession.js b/modules/gdb-dap/debugSession.js index 93ab8a4..8b9567c 100644 --- a/modules/gdb-dap/debugSession.js +++ b/modules/gdb-dap/debugSession.js @@ -6,7 +6,7 @@ const EventEmitter = require("events"); // eslint-disable-next-line no-unused-vars const net = require("node:net"); -const { toHexString, getAPI, uiSetAllStopComponent } = require("../utils/utils"); +const { toHexString, getAPI, uiSetAllStopComponent, ContextKeys } = require("../utils/utils"); const { TerminatedEvent, OutputEvent, InitializedEvent } = require("@vscode/debugadapter"); const { getExtensionPathOf } = require("../utils/sysutils"); const { CustomRequests } = require("../debugSessionCustomRequests"); @@ -277,10 +277,6 @@ class MidasDAPSession extends DebugAdapter.DebugSession { } }); - this.on("exit", (evt) => { - this.dispose(); - }); - this.on("error", (event) => { this.sendEvent(new DebugAdapter.OutputEvent(event.body, "console", event)); }); @@ -288,7 +284,7 @@ class MidasDAPSession extends DebugAdapter.DebugSession { } dispose() { - this.#checkpointsUI.tearDown(); + vscode.commands.executeCommand("setContext", ContextKeys.RRSession, false); this.disposeTerminal(); super.dispose(); } @@ -468,7 +464,6 @@ class MidasDAPSession extends DebugAdapter.DebugSession { // eslint-disable-next-line no-unused-vars disconnectRequest(response, args, request) { - this.#checkpointsUI.tearDown(); this.gdb.sendRequest(request, args); } diff --git a/modules/ui/checkpoints/checkpoints.js b/modules/ui/checkpoints/checkpoints.js index cfa6370..e880f63 100644 --- a/modules/ui/checkpoints/checkpoints.js +++ b/modules/ui/checkpoints/checkpoints.js @@ -13,6 +13,8 @@ class CheckpointsViewProvider { */ constructor(extensionContext) { this.#extensionUri = extensionContext.extensionUri; + this.checkpointIdToNameMap = new Map(); + let setCheckpoint = registerCommand("midas.set-checkpoint", () => { vscode.debug.activeDebugSession.customRequest(CustomRequests.SetCheckpoint); }); @@ -33,18 +35,14 @@ class CheckpointsViewProvider { updateCheckpoints(checkpoints, show = true) { if (this.#view) { - if (show) this.#view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders - + if (show) this.#view.show?.(true); + for(let cp of checkpoints) { + cp.name = this.checkpointIdToNameMap.get(cp.id) ?? `${cp.where.path}:${cp.where.line}`; + } this.#view.webview.postMessage({ type: UI_MESSAGES.UpdateCheckpoints, payload: checkpoints }); } } - addCheckpoint(checkpoint) { - if (this.#view) { - this.#view.show?.(true); // `show` is not implemented in 1.49 but is for 1.50 insiders - this.#view.webview.postMessage({ type: UI_MESSAGES.AddCheckpoint, payload: checkpoint }); - } - } /** * Gets resource `resource` from the Checkpoints UI module. * @param {string} resource @@ -69,6 +67,9 @@ class CheckpointsViewProvider { // eslint-disable-next-line no-unused-vars async resolveWebviewView(webviewView, context, token) { this.#view = webviewView; + this.#view.onDidDispose(() => { + this.checkpointIdToNameMap.clear(); + }); webviewView.webview.options = { // Allow scripts in the webview enableScripts: true, @@ -77,15 +78,27 @@ class CheckpointsViewProvider { webviewView.webview.html = this.#createHTMLForWebView(webviewView.webview); - webviewView.webview.onDidReceiveMessage((data) => { + webviewView.webview.onDidReceiveMessage(async (data) => { switch (data.type) { case UI_REQUESTS.DeleteCheckpoint: { + this.checkpointIdToNameMap.delete(data.value); vscode.debug.activeDebugSession.customRequest(CustomRequests.DeleteCheckpoint, data.value); break; } case UI_REQUESTS.RunToCheckpoint: vscode.debug.activeDebugSession.customRequest(CustomRequests.RestartCheckpoint, data.value); break; + case UI_REQUESTS.NameCheckpoint: + const { checkpointId, name } = data.value; + this.checkpointIdToNameMap.set(checkpointId, name); + break; + case UI_REQUESTS.GotoSourceLoc: + const { path, line } = data.value; + const doc = await vscode.workspace.openTextDocument(path); + const editor = await vscode.window.showTextDocument(doc, { preview: false }); + const position = new vscode.Position(line, 0); + editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); + break; } }); } diff --git a/modules/ui/checkpoints/main.js b/modules/ui/checkpoints/main.js index d763986..4dbffdf 100644 --- a/modules/ui/checkpoints/main.js +++ b/modules/ui/checkpoints/main.js @@ -6,60 +6,77 @@ function setupUI(protocol) { (function () { const vscode = acquireVsCodeApi(); function create_row(container, cp) { - let name = document.createElement("span"); - name.textContent = `${cp.when}`; - name.className = "checkpoints-list-when"; + const checkpointEventNumber = document.createElement("span"); + checkpointEventNumber.textContent = `${cp.when}`; + checkpointEventNumber.className = "checkpoints-list-when"; + container.appendChild(checkpointEventNumber); - container.appendChild(name); + const checkpointName = document.createElement("span"); + checkpointName.textContent = cp.name; + checkpointName.className = "file-path"; + checkpointName.addEventListener("click", () => { + const sourceLocPath = cp.where.path.split(" at ")[1]; - let path = document.createElement("span"); - path.textContent = cp.where.path; - path.className = "file-path"; - container.appendChild(path); + if(sourceLocPath) + vscode.postMessage({ type: UI_REQUESTS.GotoSourceLoc, value: { path: sourceLocPath, line: cp.where.line }}); + }); + + checkpointName.addEventListener("keydown", (event) => { + if (event.keyCode === 13) { + checkpointName.contentEditable = false; + event.target.blur(); + } + }); + + checkpointName.addEventListener("blur", (event) => { + const payload = { checkpointId: cp.id, name: event.target.textContent }; + vscode.postMessage({ type: UI_MESSAGES.NameCheckpoint, value: payload }); + }); - let action_bar = document.createElement("div"); - action_bar.className = "checkpoints-action-bar"; - let action_container = document.createElement("ul"); + checkpointName.id = `cp-${cp.id}`; + + container.appendChild(checkpointName); + + const actionBar = document.createElement("div"); + actionBar.className = "checkpoints-action-bar"; + let actionContainer = document.createElement("ul"); + + const editButton = document.createElement("li"); + editButton.className = "row-button codicon codicon-edit"; + + editButton.addEventListener("click", () => { + checkpointName.contentEditable = true; + checkpointName.focus(); + }); - let play_button = document.createElement("li"); - play_button.className = "row-button codicon codicon-debug-continue"; + const playButton = document.createElement("li"); + playButton.className = "row-button codicon codicon-debug-continue"; - play_button.addEventListener("click", () => { + playButton.addEventListener("click", () => { vscode.postMessage({ type: UI_REQUESTS.RunToCheckpoint, value: container.dataset.checkpointId }); }); - let remove_button = document.createElement("li"); - remove_button.className = "row-button codicon codicon-chrome-close"; + const removeButton = document.createElement("li"); + removeButton.className = "row-button codicon codicon-chrome-close"; - remove_button.addEventListener("click", () => { + removeButton.addEventListener("click", () => { vscode.postMessage({ type: UI_REQUESTS.DeleteCheckpoint, value: container.dataset.checkpointId }); }); - action_container.appendChild(play_button); - action_container.appendChild(remove_button); - action_bar.appendChild(action_container); - container.appendChild(action_bar); - - let line = document.createElement("span"); - line.textContent = +cp.where.line; - line.className = "checkpoints-count-badge"; - container.appendChild(line); - // div.appendChild(container); - // return div; + actionContainer.appendChild(editButton); + actionContainer.appendChild(playButton); + actionContainer.appendChild(removeButton); + actionBar.appendChild(actionContainer); + container.appendChild(actionBar); } - const oldState = { checkpoints: [] }; - /** @type {Array} */ - let checkpoints = oldState.checkpoints; - updateCheckpointsList(checkpoints); // Handle messages sent from the extension to the webview window.addEventListener("message", (event) => { const message = event.data; // The json data that the extension sent switch (message.type) { case UI_MESSAGES.ClearCheckpoints: { - checkpoints = []; - updateCheckpointsList(checkpoints); + updateCheckpointsList([]); break; } case UI_MESSAGES.RemovedCheckpoint: { @@ -83,20 +100,17 @@ function setupUI(protocol) { for (const cp of checkpoints) { const row = document.createElement("div"); row.className = "checkpoints-list-row"; - // row.role = "checkbox"; - //row.ariaChecked = true; row.dataIndex = idx; row.dataLastElement = idx == checkpoints.length - 1; row.dataset.index = idx; row.dataset.checkpointId = cp.id; row.ariaPosInSet = idx + 1; + row.id = `cp-row-${cp.id}`; create_row(row, cp); cp_list.appendChild(row); idx += 1; } - // Update the saved state - vscode.setState({ checkpoints: checkpoints }); } function removeCheckpoint(checkpointId) { diff --git a/modules/ui/checkpoints/ui_protocol.js b/modules/ui/checkpoints/ui_protocol.js index 26ca216..da77cc4 100644 --- a/modules/ui/checkpoints/ui_protocol.js +++ b/modules/ui/checkpoints/ui_protocol.js @@ -3,9 +3,10 @@ const UI_MESSAGES = { ClearCheckpoints: "clear-checkpoint", RemovedCheckpoint: "removed-checkpoint", UpdateCheckpoints: "update-checkpoints", + NameCheckpoint: "name-checkpoint" }; -const UI_REQUESTS = { DeleteCheckpoint: "delete-checkpoint", RunToCheckpoint: "run-to-checkpoint" }; +const UI_REQUESTS = { DeleteCheckpoint: "delete-checkpoint", RunToCheckpoint: "run-to-checkpoint", NameCheckpoint: "name-checkpoint", GotoSourceLoc: "goto-source-location"}; module.exports.UI_MESSAGES = UI_MESSAGES; module.exports.UI_REQUESTS = UI_REQUESTS;