- [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
This commit is contained in:
2026-03-31 13:01:41 +02:00
parent ecd24bd2e0
commit 8c3c50eae1

View File

@@ -30,18 +30,10 @@ constructor() {
this._nextRef = 1000; // IDs únicos para tablas this._nextRef = 1000; // IDs únicos para tablas
this._pendingEval = null; this._pendingEval = null;
this.programStarted = false; 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) { initializeRequest(response, args) {
console.log("[ADAPTER] initializeRequest"); console.log("[ADAPTER] initializeRequest");
this.sendEvent(new InitializedEvent()); this.sendEvent(new InitializedEvent());
@@ -50,7 +42,7 @@ constructor() {
supportsConfigurationDoneRequest: true, supportsConfigurationDoneRequest: true,
supportsEvaluateForHovers: true, supportsEvaluateForHovers: true,
supportsStepBack: false, supportsStepBack: false,
supportsSetVariable: false, supportsSetVariable: true,
supportsRestartFrame: false, supportsRestartFrame: false,
supportsGotoTargetsRequest: false, supportsGotoTargetsRequest: false,
supportsStepInTargetsRequest: false, supportsStepInTargetsRequest: false,
@@ -59,12 +51,12 @@ constructor() {
supportsExceptionInfoRequest: false, supportsExceptionInfoRequest: false,
supportsDelayedStackTraceLoading: false, supportsDelayedStackTraceLoading: false,
supportsLoadedSourcesRequest: false, supportsLoadedSourcesRequest: false,
supportsLogPoints: false, supportsLogPoints: true,
supportsTerminateRequest: true, supportsTerminateRequest: true,
supportsTerminateDebuggee: true, supportsTerminateDebuggee: true,
supportsFunctionBreakpoints: false, supportsFunctionBreakpoints: false,
supportsConditionalBreakpoints: false, supportsConditionalBreakpoints: true,
supportsHitConditionalBreakpoints: false, supportsHitConditionalBreakpoints: true,
supportsConfigurationDoneRequest: true, supportsConfigurationDoneRequest: true,
supportsSetExpression: false, supportsSetExpression: false,
supportsClipboardContext: false, supportsClipboardContext: false,
@@ -218,6 +210,17 @@ constructor() {
return; 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 // salida normal
this.sendEvent(new OutputEvent(line + "\n", "stdout")); this.sendEvent(new OutputEvent(line + "\n", "stdout"));
} }
@@ -232,6 +235,7 @@ constructor() {
cwd: cwd, cwd: cwd,
stdio: ['pipe', 'pipe', 'pipe'] stdio: ['pipe', 'pipe', 'pipe']
}); });
this.programStarted = true; this.programStarted = true;
this.stdoutBuffer = ""; this.stdoutBuffer = "";
@@ -259,12 +263,12 @@ constructor() {
// 3. Ahora que stdout ya está conectado, enviar breakpoints // 3. Ahora que stdout ya está conectado, enviar breakpoints
if (this.breakpoints) { if (this.breakpoints) {
for (const path in this.breakpoints) { for (const path in this.breakpoints) {
const lines = this.breakpoints[path]; //const lines = this.breakpoints[path];
this.sendDebugCommand({ this.sendDebugCommand({
cmd: "setBreakpoints", cmd: "setBreakpoints",
file: path, file: path,
lines: lines breakpoints: this.breakpoints[path] //lines
}); });
} }
} }
@@ -305,14 +309,20 @@ constructor() {
if (!this.breakpoints) if (!this.breakpoints)
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 // Si el programa YA está corriendo → enviar breakpoints al motor
if (this.programStarted) { if (this.programStarted) {
this.sendDebugCommand({ this.sendDebugCommand({
cmd: "setBreakpoints", cmd: "setBreakpoints",
file: path, file: path,
lines: lines breakpoints: this.breakpoints[path]
}); });
} }
@@ -326,42 +336,6 @@ constructor() {
this.sendResponse(response); 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) { continueRequest(response, args) {
const msg = { const msg = {
cmd: "continue" cmd: "continue"
@@ -380,38 +354,6 @@ constructor() {
this.sendResponse(response); 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) { disconnectRequest(response, args) {
console.log("[ADAPTER] disconnectRequest"); console.log("[ADAPTER] disconnectRequest");
@@ -474,7 +416,7 @@ constructor() {
response.body = { response.body = {
stackFrames: frames.map((f, i) => ({ stackFrames: frames.map((f, i) => ({
id: i + 1, id: i,
name: f.name, name: f.name,
source: { path: f.file }, source: { path: f.file },
line: f.line, line: f.line,
@@ -482,6 +424,7 @@ constructor() {
})), })),
totalFrames: frames.length totalFrames: frames.length
}; };
this._lastFrames = frames;
this.sendResponse(response); this.sendResponse(response);
} else { } else {
@@ -492,16 +435,22 @@ constructor() {
check(); check();
} }
makeVarRef(type, frameId) {
const ref = this._nextVarRef++;
this._varRefMap.set(ref, { type, frameId });
return ref;
}
// Aún no tiene en cuenta el frame // Aún no tiene en cuenta el frame
scopesRequest(response, args) { scopesRequest(response, args) {
console.log("[ADAPTER] scopesRequest, frameId =", args.frameId); console.log("[ADAPTER] scopesRequest, frameId =", args.frameId);
const frameId = args.frameId;
response.body = { response.body = {
scopes: [ scopes: [
new Scope("Locals", 1, false), new Scope("Locals", this.makeVarRef("locals", frameId), false),
new Scope("Upvalues", 2, false), new Scope("Upvalues", this.makeVarRef("upvalues", frameId), false),
new Scope("Globals", 3, true) new Scope("Globals", this.makeVarRef("globals", frameId), true) ]
]
}; };
this.sendResponse(response); this.sendResponse(response);
@@ -509,25 +458,29 @@ constructor() {
variablesRequest(response, args) { variablesRequest(response, args) {
console.log("[ADAPTER] variablesRequest ref =", args.variablesReference); console.log("[ADAPTER] variablesRequest ref =", args.variablesReference);
const info = this._varRefMap.get(args.variablesReference);
if (args.variablesReference === 1) { if (info) {
this._pendingLocals = response; const { type, frameId } = info;
this.sendDebugCommand({ cmd: "locals" });
return; 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 // Expansión de tablas
if (args.variablesReference >= 1000) { if (args.variablesReference >= 1000) {
const luaRef = this._refTable.get(args.variablesReference); 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) { configurationDoneRequest(response, args) {
console.log("[ADAPTER] configurationDoneRequest"); console.log("[ADAPTER] configurationDoneRequest");
this.sendResponse(response); this.sendResponse(response);