From 8c3c50eae1fb3c5ec040905d3f788bd58f03c50c Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Tue, 31 Mar 2026 13:01:41 +0200 Subject: [PATCH] - [NEW] Se mostren les variables locals i upvalues segons en el frame del stack que estem - [NEW] Breakpoints condicionals - [NEW] Es poden modificar totes les variables del joc des de la finestra VARIABLES de vscode --- adapter/debugAdapter.js | 205 +++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 108 deletions(-) diff --git a/adapter/debugAdapter.js b/adapter/debugAdapter.js index 5728e40..58d8d1a 100644 --- a/adapter/debugAdapter.js +++ b/adapter/debugAdapter.js @@ -30,18 +30,10 @@ constructor() { this._nextRef = 1000; // IDs únicos para tablas this._pendingEval = null; this.programStarted = false; + this._nextVarRef = 100; + this._varRefMap = new Map(); } - //initializeRequest(response, args) { - // this.sendEvent(new InitializedEvent()); -// - // response.body = { - // supportsConfigurationDoneRequest: true - // }; -// - // this.sendResponse(response); - //} - initializeRequest(response, args) { console.log("[ADAPTER] initializeRequest"); this.sendEvent(new InitializedEvent()); @@ -50,7 +42,7 @@ constructor() { supportsConfigurationDoneRequest: true, supportsEvaluateForHovers: true, supportsStepBack: false, - supportsSetVariable: false, + supportsSetVariable: true, supportsRestartFrame: false, supportsGotoTargetsRequest: false, supportsStepInTargetsRequest: false, @@ -59,12 +51,12 @@ constructor() { supportsExceptionInfoRequest: false, supportsDelayedStackTraceLoading: false, supportsLoadedSourcesRequest: false, - supportsLogPoints: false, + supportsLogPoints: true, supportsTerminateRequest: true, supportsTerminateDebuggee: true, supportsFunctionBreakpoints: false, - supportsConditionalBreakpoints: false, - supportsHitConditionalBreakpoints: false, + supportsConditionalBreakpoints: true, + supportsHitConditionalBreakpoints: true, supportsConfigurationDoneRequest: true, supportsSetExpression: false, supportsClipboardContext: false, @@ -218,6 +210,17 @@ constructor() { return; } + if (json.type === "setVariable") { + if (this._pendingSetVariable) { + //const newValue = String(msg.payload.value); + this._pendingSetVariable.body = { + value: json.payload.value + }; + this.sendResponse(this._pendingSetVariable); + this._pendingSetVariable = null; + } + } + // salida normal this.sendEvent(new OutputEvent(line + "\n", "stdout")); } @@ -232,6 +235,7 @@ constructor() { cwd: cwd, stdio: ['pipe', 'pipe', 'pipe'] }); + this.programStarted = true; this.stdoutBuffer = ""; @@ -259,12 +263,12 @@ constructor() { // 3. Ahora que stdout ya está conectado, enviar breakpoints if (this.breakpoints) { for (const path in this.breakpoints) { - const lines = this.breakpoints[path]; + //const lines = this.breakpoints[path]; this.sendDebugCommand({ cmd: "setBreakpoints", file: path, - lines: lines + breakpoints: this.breakpoints[path] //lines }); } } @@ -305,14 +309,20 @@ constructor() { if (!this.breakpoints) this.breakpoints = {}; - this.breakpoints[path] = lines; + //this.breakpoints[path] = lines; + this.breakpoints[path] = clientBreakpoints.map(bp => ({ + line: bp.line, + condition: bp.condition || null, + logMessage: bp.logMessage || null, + hitCondition: bp.hitCondition || null + })); // Si el programa YA está corriendo → enviar breakpoints al motor if (this.programStarted) { this.sendDebugCommand({ cmd: "setBreakpoints", file: path, - lines: lines + breakpoints: this.breakpoints[path] }); } @@ -326,42 +336,6 @@ constructor() { this.sendResponse(response); } - /*setBreakPointsRequest(response, args) { - const path = args.source.path; // archivo donde se han puesto breakpoints - const clientBreakpoints = args.breakpoints || []; - - // Extraemos solo las líneas - const lines = clientBreakpoints.map(bp => bp.line); - - // Guardamos internamente los breakpoints - if (!this.breakpoints) - this.breakpoints = {}; - - this.breakpoints[path] = lines; - - // Enviamos los breakpoints a tu aplicación por stdin - const msg = { - cmd: "setBreakpoints", - file: path, - lines: lines - }; - - this.sendDebugCommand(msg); - //this.process.stdin.write( - // "@@DEBUGCMD@@" + JSON.stringify(msg) + "\n" - //); - - // VSCode necesita una respuesta con los breakpoints "verificados" - response.body = { - breakpoints: lines.map(line => ({ - verified: true, - line: line - })) - }; - - this.sendResponse(response); - }*/ - continueRequest(response, args) { const msg = { cmd: "continue" @@ -380,38 +354,6 @@ constructor() { this.sendResponse(response); } - stackTraceRequest(response, args) { - // Pedimos al motor el stack trace - this.sendDebugCommand({ cmd: "stackTrace" }); - - // IMPORTANTE: el motor responde async, así que esperamos - // a que llegue el mensaje @@DEBUG@@ con type=stackTrace - - const check = () => { - if (this._stackFrames.length > 0) { - const frames = this._stackFrames; - this._stackFrames = []; - - response.body = { - stackFrames: frames.map((f, i) => ({ - id: i + 1, - name: f.name, - source: { path: f.file }, - line: f.line, - column: 1 - })), - totalFrames: frames.length - }; - - this.sendResponse(response); - } else { - setTimeout(check, 5); - } - }; - - check(); - } - disconnectRequest(response, args) { console.log("[ADAPTER] disconnectRequest"); @@ -474,7 +416,7 @@ constructor() { response.body = { stackFrames: frames.map((f, i) => ({ - id: i + 1, + id: i, name: f.name, source: { path: f.file }, line: f.line, @@ -482,6 +424,7 @@ constructor() { })), totalFrames: frames.length }; + this._lastFrames = frames; this.sendResponse(response); } else { @@ -492,16 +435,22 @@ constructor() { check(); } + makeVarRef(type, frameId) { + const ref = this._nextVarRef++; + this._varRefMap.set(ref, { type, frameId }); + return ref; + } + // Aún no tiene en cuenta el frame scopesRequest(response, args) { console.log("[ADAPTER] scopesRequest, frameId =", args.frameId); + const frameId = args.frameId; response.body = { scopes: [ - new Scope("Locals", 1, false), - new Scope("Upvalues", 2, false), - new Scope("Globals", 3, true) - ] + new Scope("Locals", this.makeVarRef("locals", frameId), false), + new Scope("Upvalues", this.makeVarRef("upvalues", frameId), false), + new Scope("Globals", this.makeVarRef("globals", frameId), true) ] }; this.sendResponse(response); @@ -509,25 +458,29 @@ constructor() { variablesRequest(response, args) { console.log("[ADAPTER] variablesRequest ref =", args.variablesReference); + const info = this._varRefMap.get(args.variablesReference); - if (args.variablesReference === 1) { - this._pendingLocals = response; - this.sendDebugCommand({ cmd: "locals" }); - return; + if (info) { + const { type, frameId } = info; + + if (type === "locals") { + this._pendingLocals = response; + this.sendDebugCommand({ cmd: "locals", frame: frameId }); + return; + } + + if (type === "upvalues") { + this._pendingUpvalues = response; + this.sendDebugCommand({ cmd: "upvalues", frame: frameId }); + return; + } + + if (type === "globals") { + this._pendingGlobals = response; + this.sendDebugCommand({ cmd: "globals" }); + return; + } } - - if (args.variablesReference === 2) { - this._pendingUpvalues = response; - this.sendDebugCommand({ cmd: "upvalues" }); - return; - } - - if (args.variablesReference === 3) { - this._pendingGlobals = response; - this.sendDebugCommand({ cmd: "globals" }); - return; - } - // Expansión de tablas if (args.variablesReference >= 1000) { const luaRef = this._refTable.get(args.variablesReference); @@ -560,6 +513,42 @@ constructor() { }); } + setVariableRequest(response, args) { + const { variablesReference, name, value } = args; + + // Caso 1: locals/upvalues/globals + const info = this._varRefMap.get(variablesReference); + if (info) { + this._pendingSetVariable = response; + this.sendDebugCommand({ + cmd: "setVariable", + frame: info.frameId, + scope: info.type, + name: name, + value: value + }); + return; + } + + // Caso 2: miembros de tabla + if (variablesReference >= 1000) { + const luaRef = this._refTable.get(variablesReference); + + this._pendingSetVariable = response; + this.sendDebugCommand({ + cmd: "setTableField", + ref: luaRef, + key: name, + value: value + }); + return; + } + + // fallback + response.body = { value: value }; + this.sendResponse(response); + } + configurationDoneRequest(response, args) { console.log("[ADAPTER] configurationDoneRequest"); this.sendResponse(response);