const { LoggingDebugSession, InitializedEvent, TerminatedEvent, OutputEvent, StoppedEvent, Thread } = require('vscode-debugadapter'); const { spawn } = require('child_process'); class MyLuaDebugSession extends LoggingDebugSession { constructor() { super("myLuaDebug.txt"); this.setDebuggerLinesStartAt1(true); this.setDebuggerColumnsStartAt1(true); } 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: ['pipe', 'pipe', 'pipe'] }); this.stdoutBuffer = ""; this.process.stdout.on('data', data => { this.stdoutBuffer += data.toString(); let idx; while ((idx = this.stdoutBuffer.indexOf("\n")) >= 0) { const line = this.stdoutBuffer.slice(0, idx).trim(); this.stdoutBuffer = this.stdoutBuffer.slice(idx + 1); this.handleLine(line); } }); this.process.stderr.on('data', data => { this.sendEvent(new OutputEvent(data.toString(), "stderr")); }); this.process.on('exit', () => { this.sendEvent(new TerminatedEvent()); }); 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.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); } } new MyLuaDebugSession().start(process.stdin, process.stdout);