- [NEW] pause, resume
- [NEW] stackTrace - [NEW] stepIn, stepOut, stepOver - [NEW] variables locals, upvalues i globals - [NEW] Expansió de tables
This commit is contained in:
@@ -4,26 +4,72 @@ const {
|
|||||||
TerminatedEvent,
|
TerminatedEvent,
|
||||||
OutputEvent,
|
OutputEvent,
|
||||||
StoppedEvent,
|
StoppedEvent,
|
||||||
Thread
|
ThreadEvent,
|
||||||
} = require('vscode-debugadapter');
|
Thread,
|
||||||
|
Scope,
|
||||||
|
Variable
|
||||||
|
} = require('vscode-debugadapter');
|
||||||
|
|
||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
class MyLuaDebugSession extends LoggingDebugSession {
|
class MyLuaDebugSession extends LoggingDebugSession {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("myLuaDebug.txt");
|
super();
|
||||||
console.log("ADAPTER INICIADO");
|
|
||||||
|
// Redirigir console.log a la Debug Console
|
||||||
|
console.log = (...args) => { this.sendEvent(new OutputEvent(args.join(" ") + "\n")); };
|
||||||
|
console.log("Debug Adapter iniciado");
|
||||||
this._stackFrames = [];
|
this._stackFrames = [];
|
||||||
this.setDebuggerLinesStartAt1(true);
|
this.setDebuggerLinesStartAt1(true);
|
||||||
this.setDebuggerColumnsStartAt1(true);
|
this.setDebuggerColumnsStartAt1(true);
|
||||||
|
this._pendingLocals = null;
|
||||||
|
this._pendingUpvalues = null;
|
||||||
|
this._pendingGlobals = null;
|
||||||
|
this._refTable = new Map(); // ref → { luaRef }
|
||||||
|
this._nextRef = 1000; // IDs únicos para tablas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//initializeRequest(response, args) {
|
||||||
|
// this.sendEvent(new InitializedEvent());
|
||||||
|
//
|
||||||
|
// response.body = {
|
||||||
|
// supportsConfigurationDoneRequest: true
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// this.sendResponse(response);
|
||||||
|
//}
|
||||||
|
|
||||||
initializeRequest(response, args) {
|
initializeRequest(response, args) {
|
||||||
|
console.log("[ADAPTER] initializeRequest");
|
||||||
this.sendEvent(new InitializedEvent());
|
this.sendEvent(new InitializedEvent());
|
||||||
|
|
||||||
response.body = {
|
response.body = {
|
||||||
supportsConfigurationDoneRequest: true
|
supportsConfigurationDoneRequest: true,
|
||||||
|
supportsEvaluateForHovers: true,
|
||||||
|
supportsStepBack: false,
|
||||||
|
supportsSetVariable: false,
|
||||||
|
supportsRestartFrame: false,
|
||||||
|
supportsGotoTargetsRequest: false,
|
||||||
|
supportsStepInTargetsRequest: false,
|
||||||
|
supportsCompletionsRequest: false,
|
||||||
|
supportsRestartRequest: false,
|
||||||
|
supportsExceptionInfoRequest: false,
|
||||||
|
supportsDelayedStackTraceLoading: false,
|
||||||
|
supportsLoadedSourcesRequest: false,
|
||||||
|
supportsLogPoints: false,
|
||||||
|
supportsTerminateRequest: true,
|
||||||
|
supportsTerminateDebuggee: true,
|
||||||
|
supportsFunctionBreakpoints: false,
|
||||||
|
supportsConditionalBreakpoints: false,
|
||||||
|
supportsHitConditionalBreakpoints: false,
|
||||||
|
supportsConfigurationDoneRequest: true,
|
||||||
|
supportsSetExpression: false,
|
||||||
|
supportsClipboardContext: false,
|
||||||
|
supportsValueFormattingOptions: false,
|
||||||
|
supportsExceptionOptions: false,
|
||||||
|
supportsExceptionFilterOptions: false,
|
||||||
|
supportsSingleThreadExecutionRequests: true
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
@@ -34,30 +80,116 @@ class MyLuaDebugSession extends LoggingDebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleLine(line) {
|
handleLine(line) {
|
||||||
if (line.startsWith("@@DEBUG@@")) {
|
console.log("[ADAPTER] RAW LINE:", JSON.stringify(line));
|
||||||
const json = JSON.parse(line.substring(9));
|
|
||||||
|
|
||||||
if (json.type === "luaError") {
|
if (!line.startsWith("@@DEBUG@@")) {
|
||||||
const e = new OutputEvent(json.message + "\n", "stderr");
|
console.log("[ADAPTER] Ignorando línea no-debug");
|
||||||
e.body.source = { path: json.file };
|
return;
|
||||||
e.body.line = json.line;
|
}
|
||||||
this.sendEvent(e);
|
|
||||||
|
const jsonStr = line.substring(9);
|
||||||
|
console.log("[ADAPTER] JSON A PARSEAR:", jsonStr);
|
||||||
|
|
||||||
|
let json;
|
||||||
|
try {
|
||||||
|
json = JSON.parse(jsonStr);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[ADAPTER] ERROR PARSEANDO JSON:", e.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[ADAPTER] JSON OK:", json);
|
||||||
|
console.log("[ADAPTER] TYPE:", json.type);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (json.type === "step") {
|
||||||
|
this.sendEvent(new StoppedEvent("step", 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.type === "pause") {
|
||||||
|
this.sendEvent(new StoppedEvent("pause", 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.type === "stackTrace") {
|
||||||
|
console.log("[ADAPTER] STACKTRACE PAYLOAD:", JSON.stringify(json.payload));
|
||||||
|
console.log("[ADAPTER] BEFORE HANDLING STACKTRACE");
|
||||||
|
this.pendingStackTrace(json.payload.frames);
|
||||||
|
console.log("[ADAPTER] AFTER HANDLING STACKTRACE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.type === "variables") {
|
||||||
|
console.log("[ADAPTER] VARIABLES PAYLOAD:", JSON.stringify(json.payload));
|
||||||
|
|
||||||
|
// 1. Convertimos las variables del motor a formato DAP
|
||||||
|
const vars = json.payload.variables.map(v => {
|
||||||
|
if (v.type === "table" && v.ref > 0) {
|
||||||
|
const id = this._nextRef++;
|
||||||
|
this._refTable.set(id, v.ref);
|
||||||
|
return {
|
||||||
|
name: v.name,
|
||||||
|
value: v.value,
|
||||||
|
type: v.type,
|
||||||
|
variablesReference: id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: v.name,
|
||||||
|
value: v.value,
|
||||||
|
type: v.type,
|
||||||
|
variablesReference: 0
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Seleccionamos el pendingResponse correcto según el kind
|
||||||
|
let response = null;
|
||||||
|
|
||||||
|
if (json.payload.kind === "locals") {
|
||||||
|
response = this._pendingLocals;
|
||||||
|
this._pendingLocals = null;
|
||||||
|
|
||||||
|
} else if (json.payload.kind === "upvalues") {
|
||||||
|
response = this._pendingUpvalues;
|
||||||
|
this._pendingUpvalues = null;
|
||||||
|
|
||||||
|
} else if (json.payload.kind === "globals") {
|
||||||
|
response = this._pendingGlobals;
|
||||||
|
this._pendingGlobals = null;
|
||||||
|
|
||||||
|
} else if (json.payload.kind === "expand") {
|
||||||
|
response = this._pendingExpand;
|
||||||
|
this._pendingExpand = null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log("[ADAPTER] VARIABLES: kind desconocido:", json.payload.kind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.type === "break") {
|
if (!response) {
|
||||||
this.currentFile = json.file;
|
console.log("[ADAPTER] VARIABLES: no pending response para kind", json.payload.kind);
|
||||||
this.currentLine = json.line;
|
|
||||||
|
|
||||||
this.sendEvent(new StoppedEvent("breakpoint", 1));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.type === "stackTrace") {
|
|
||||||
this.pendingStackTrace(json.payload.frames);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Enviamos la respuesta a VSCode
|
||||||
|
response.body = { variables: vars };
|
||||||
|
this.sendResponse(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +198,8 @@ class MyLuaDebugSession extends LoggingDebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launchRequest(response, args) {
|
launchRequest(response, args) {
|
||||||
|
console.log("[ADAPTER] launchRequest");
|
||||||
|
|
||||||
const program = args.program;
|
const program = args.program;
|
||||||
const cwd = args.cwd || process.cwd();
|
const cwd = args.cwd || process.cwd();
|
||||||
|
|
||||||
@@ -74,6 +208,8 @@ class MyLuaDebugSession extends LoggingDebugSession {
|
|||||||
stdio: ['pipe', 'pipe', 'pipe']
|
stdio: ['pipe', 'pipe', 'pipe']
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.sendEvent(new ThreadEvent("started", 1));
|
||||||
|
|
||||||
this.stdoutBuffer = "";
|
this.stdoutBuffer = "";
|
||||||
|
|
||||||
this.process.stdout.on('data', data => {
|
this.process.stdout.on('data', data => {
|
||||||
@@ -101,8 +237,8 @@ class MyLuaDebugSession extends LoggingDebugSession {
|
|||||||
|
|
||||||
sendDebugCommand(obj) {
|
sendDebugCommand(obj) {
|
||||||
if (!this.process || !this.process.stdin) return;
|
if (!this.process || !this.process.stdin) return;
|
||||||
console.log("ENVIANDO CMD:", obj);
|
|
||||||
const msg = "@@DEBUGCMD@@" + JSON.stringify(obj) + "\n";
|
const msg = "@@DEBUGCMD@@" + JSON.stringify(obj) + "\n";
|
||||||
|
console.log("ENVIANDO CMD:", msg);
|
||||||
this.process.stdin.write(msg);
|
this.process.stdin.write(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,22 +363,96 @@ class MyLuaDebugSession extends LoggingDebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stackTraceRequest(response, args) {
|
stackTraceRequest(response, args) {
|
||||||
response.body = {
|
console.log("[ADAPTER] stackTraceRequest");
|
||||||
stackFrames: [
|
|
||||||
{
|
// Pedimos el stack trace al motor
|
||||||
id: 1,
|
this.sendDebugCommand({ cmd: "stackTrace" });
|
||||||
name: "Lua",
|
|
||||||
source: { path: this.currentFile },
|
// Esperamos la respuesta del motor
|
||||||
line: this.currentLine,
|
const check = () => {
|
||||||
column: 1
|
if (this._stackFrames && this._stackFrames.length > 0) {
|
||||||
}
|
const frames = this._stackFrames;
|
||||||
],
|
this._stackFrames = [];
|
||||||
totalFrames: 1
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aún no tiene en cuenta el frame
|
||||||
|
scopesRequest(response, args) {
|
||||||
|
console.log("[ADAPTER] scopesRequest, frameId =", args.frameId);
|
||||||
|
|
||||||
|
response.body = {
|
||||||
|
scopes: [
|
||||||
|
new Scope("Locals", 1, false),
|
||||||
|
new Scope("Upvalues", 2, false),
|
||||||
|
new Scope("Globals", 3, true)
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
variablesRequest(response, args) {
|
||||||
|
console.log("[ADAPTER] variablesRequest ref =", args.variablesReference);
|
||||||
|
|
||||||
|
if (args.variablesReference === 1) {
|
||||||
|
this._pendingLocals = response;
|
||||||
|
this.sendDebugCommand({ cmd: "locals" });
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!luaRef) {
|
||||||
|
console.log("[ADAPTER] No existe luaRef para", args.variablesReference);
|
||||||
|
response.body = { variables: [] };
|
||||||
|
this.sendResponse(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._pendingExpand = response;
|
||||||
|
this.sendDebugCommand({ cmd: "expand", ref: luaRef });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// de momento, resto vacío
|
||||||
|
response.body = { variables: [] };
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
configurationDoneRequest(response, args) {
|
configurationDoneRequest(response, args) {
|
||||||
|
console.log("[ADAPTER] configurationDoneRequest");
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user