diff --git a/adapter/debugAdapter.js b/adapter/debugAdapter.js index 21e44a0..0fa5854 100644 --- a/adapter/debugAdapter.js +++ b/adapter/debugAdapter.js @@ -2,8 +2,11 @@ const { LoggingDebugSession, InitializedEvent, TerminatedEvent, - OutputEvent + OutputEvent, + StoppedEvent, + Thread } = require('vscode-debugadapter'); + const { spawn } = require('child_process'); class MyLuaDebugSession extends LoggingDebugSession { @@ -16,37 +19,62 @@ class MyLuaDebugSession extends LoggingDebugSession { initializeRequest(response, args) { this.sendEvent(new InitializedEvent()); + + response.body = { + supportsConfigurationDoneRequest: true + }; + this.sendResponse(response); } + handleLine(line) { + if (line.startsWith("@@DEBUG@@")) { + const json = JSON.parse(line.substring(9)); + + if (json.type === "luaError") { + const e = new OutputEvent(json.message + "\n", "stderr"); + e.body.source = { path: json.file }; + e.body.line = json.line; + this.sendEvent(e); + return; + } + + if (json.type === "break") { + this.currentFile = json.file; + this.currentLine = json.line; + + this.sendEvent(new StoppedEvent("breakpoint", 1)); + return; + } + + return; + } + + // salida normal + this.sendEvent(new OutputEvent(line + "\n", "stdout")); + } + launchRequest(response, args) { const program = args.program; const cwd = args.cwd || process.cwd(); this.process = spawn(program, [], { cwd: cwd, - stdio: ['ignore', 'pipe', 'pipe'] + stdio: ['pipe', 'pipe', 'pipe'] }); + this.stdoutBuffer = ""; + this.process.stdout.on('data', data => { - const text = data.toString(); + this.stdoutBuffer += data.toString(); - if (text.startsWith("@@DEBUG@@")) { - const json = JSON.parse(text.substring(9)); + let idx; + while ((idx = this.stdoutBuffer.indexOf("\n")) >= 0) { + const line = this.stdoutBuffer.slice(0, idx).trim(); + this.stdoutBuffer = this.stdoutBuffer.slice(idx + 1); - if (json.type === "luaError") { - const e = new OutputEvent(json.message + "\n", "stderr"); - e.body.source = { path: json.file }; - e.body.line = json.line; - - this.sendEvent(e); - } - - return; + this.handleLine(line); } - - // salida normal - this.sendEvent(new OutputEvent(text, "stdout")); }); this.process.stderr.on('data', data => { @@ -61,17 +89,87 @@ class MyLuaDebugSession extends LoggingDebugSession { } setBreakPointsRequest(response, args) { - const path = args.source.path; - const bps = args.breakpoints.map(bp => bp.line); + const path = args.source.path; // archivo donde se han puesto breakpoints + const clientBreakpoints = args.breakpoints || []; - // Guardamos los breakpoints internamente - this.breakpoints[path] = bps; + // Extraemos solo las líneas + const lines = clientBreakpoints.map(bp => bp.line); - // Enviar confirmación a VSCode - response.body = { - breakpoints: bps.map(line => ({ verified: true, 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.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" + }; + + this.process.stdin.write( + "@@DEBUGCMD@@" + JSON.stringify(msg) + "\n" + ); + + this.sendResponse(response); + } + + disconnectRequest(response, args) { + const msg = { cmd: "continue" }; // por si estaba pausado + this.process.stdin.write("@@DEBUGCMD@@" + JSON.stringify(msg) + "\n"); + + this.process.kill(); + this.sendResponse(response); + } + + threadsRequest(response) { + // VSCode exige al menos un thread + response.body = { + threads: [ + new Thread(1, "Main Thread") + ] + }; + this.sendResponse(response); + } + + stackTraceRequest(response, args) { + response.body = { + stackFrames: [ + { + id: 1, + name: "Lua", + source: { path: this.currentFile }, + line: this.currentLine, + column: 1 + } + ], + totalFrames: 1 + }; + this.sendResponse(response); + } + + configurationDoneRequest(response, args) { this.sendResponse(response); } diff --git a/package.json b/package.json index 643323d..d7a4621 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ "activationEvents": ["onDebug"], "main": "./extension.js", "contributes": { + "breakpoints": [ + { "language": "lua" } + ], "debuggers": [ { "type": "myLuaApp", @@ -18,6 +21,15 @@ "program": "./adapter/debugAdapter.js", "runtime": "node", "languages": ["lua"], + "request": "launch", + "initialConfigurations": [ + { + "type": "myLuaApp", + "request": "launch", + "name": "Debug My Lua App", + "program": "${workspaceFolder}/miapp" + } + ], "configurationAttributes": { "launch": { "properties": {