- [NEW] [debugger] Quan hi ha una excepció, ho notifica al adapter i li dona la info necessaria
This commit is contained in:
181
lua.cpp
181
lua.cpp
@@ -7,7 +7,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -32,6 +32,17 @@ struct FrameInfo {
|
|||||||
//std::vector<Variable> upvalues;
|
//std::vector<Variable> upvalues;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StackFrameInfo {
|
||||||
|
std::string file;
|
||||||
|
int line;
|
||||||
|
std::string function;
|
||||||
|
};
|
||||||
|
std::string lastExceptionTraceback;
|
||||||
|
std::vector<StackFrameInfo> lastExceptionStack;
|
||||||
|
std::string lastExceptionMessage;
|
||||||
|
bool hasException = false;
|
||||||
|
|
||||||
|
std::set<std::string> exceptionFilters;// {"all"};
|
||||||
std::vector<FrameInfo> g_frames;
|
std::vector<FrameInfo> g_frames;
|
||||||
|
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -792,6 +803,78 @@ void sendDebugResponse(const std::string& type, const json& payload) {
|
|||||||
std::cout << "@@DEBUG@@" << msg.dump() << std::endl;
|
std::cout << "@@DEBUG@@" << msg.dump() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseLuaTraceback(const char* tb, std::vector<StackFrameInfo>& out) {
|
||||||
|
out.clear();
|
||||||
|
if (!tb) return;
|
||||||
|
|
||||||
|
std::stringstream ss(tb);
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
bool inFrames = false;
|
||||||
|
|
||||||
|
while (std::getline(ss, line)) {
|
||||||
|
// Quitar espacios iniciales y tabs
|
||||||
|
while (!line.empty() && (line[0] == ' ' || line[0] == '\t'))
|
||||||
|
line.erase(line.begin());
|
||||||
|
|
||||||
|
// Saltar la primera línea (mensaje de error)
|
||||||
|
if (!inFrames) {
|
||||||
|
if (line.rfind("stack traceback:", 0) == 0) {
|
||||||
|
inFrames = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formato esperado:
|
||||||
|
// [string "modules.ia.hero"]:189: in field 'ia'
|
||||||
|
//
|
||||||
|
// O:
|
||||||
|
// [string "main"]:34: in function <[string "main"]:32>
|
||||||
|
|
||||||
|
if (line.rfind("[string \"", 0) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Extraer chunk name
|
||||||
|
size_t q1 = line.find('"');
|
||||||
|
size_t q2 = line.find('"', q1 + 1);
|
||||||
|
if (q1 == std::string::npos || q2 == std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string chunk = line.substr(q1 + 1, q2 - q1 - 1);
|
||||||
|
|
||||||
|
// Extraer línea
|
||||||
|
size_t colon1 = line.find(':', q2 + 1);
|
||||||
|
if (colon1 == std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t colon2 = line.find(':', colon1 + 1);
|
||||||
|
if (colon2 == std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int lineNumber = std::stoi(line.substr(colon1 + 1, colon2 - colon1 - 1));
|
||||||
|
|
||||||
|
// Extraer nombre de función (si existe)
|
||||||
|
std::string func = "unknown";
|
||||||
|
|
||||||
|
size_t inField = line.find("in field '");
|
||||||
|
if (inField != std::string::npos) {
|
||||||
|
size_t start = inField + 10;
|
||||||
|
size_t end = line.find("'", start);
|
||||||
|
func = line.substr(start, end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t inFunc = line.find("in function <");
|
||||||
|
if (inFunc != std::string::npos) {
|
||||||
|
func = "anonymous";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertir chunk → ruta real
|
||||||
|
std::string filePath = chunkToPath(chunk);
|
||||||
|
|
||||||
|
out.push_back({ filePath, lineNumber, func });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void processDebugCommand(const std::string& line) {
|
void processDebugCommand(const std::string& line) {
|
||||||
//printf("COMANDO PROCESADO: %s\n", line.c_str());
|
//printf("COMANDO PROCESADO: %s\n", line.c_str());
|
||||||
if (!line.starts_with("@@DEBUGCMD@@"))
|
if (!line.starts_with("@@DEBUGCMD@@"))
|
||||||
@@ -855,8 +938,33 @@ void processDebugCommand(const std::string& line) {
|
|||||||
g_paused = false;
|
g_paused = false;
|
||||||
}
|
}
|
||||||
else if (cmd == "stackTrace") {
|
else if (cmd == "stackTrace") {
|
||||||
json result = getStackTrace(L);
|
if (hasException) {
|
||||||
sendDebugResponse("stackTrace", result);
|
parseLuaTraceback(lastExceptionTraceback.c_str(), lastExceptionStack);
|
||||||
|
|
||||||
|
json frames = json::array();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < lastExceptionStack.size(); i++) {
|
||||||
|
frames.push_back({
|
||||||
|
{ "id", (int)i + 1 },
|
||||||
|
{ "name", lastExceptionStack[i].function },
|
||||||
|
{ "line", lastExceptionStack[i].line },
|
||||||
|
{ "column", 1 },
|
||||||
|
{ "source", {
|
||||||
|
{ "path", lastExceptionStack[i].file }
|
||||||
|
}}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
json result = {
|
||||||
|
{ "stackFrames", frames },
|
||||||
|
{ "totalFrames", frames.size() }
|
||||||
|
};
|
||||||
|
|
||||||
|
sendDebugResponse("stackTrace", result);
|
||||||
|
} else {
|
||||||
|
json result = getStackTrace(L);
|
||||||
|
sendDebugResponse("stackTrace", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == "locals") {
|
else if (cmd == "locals") {
|
||||||
int frame = j.value("frame", 0);
|
int frame = j.value("frame", 0);
|
||||||
@@ -931,7 +1039,12 @@ void processDebugCommand(const std::string& line) {
|
|||||||
|
|
||||||
sendDebugResponse("setVariable", result);
|
sendDebugResponse("setVariable", result);
|
||||||
}
|
}
|
||||||
|
else if (cmd == "setExceptionFilters") {
|
||||||
|
exceptionFilters.clear();
|
||||||
|
for (auto& f : j["filters"]) {
|
||||||
|
exceptionFilters.insert(f.get<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkBreakpointCondition(lua_State* L, const Breakpoint& bp) {
|
bool checkBreakpointCondition(lua_State* L, const Breakpoint& bp) {
|
||||||
@@ -2719,19 +2832,71 @@ void lua_call_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendExceptionStoppedEvent(const std::string& msg) {
|
||||||
|
json payload = {
|
||||||
|
{ "reason", "exception" },
|
||||||
|
{ "text", msg }
|
||||||
|
};
|
||||||
|
sendDebugResponse("stopped", payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
int luaErrorHandler(lua_State* L) {
|
||||||
|
const char* msg = lua_tostring(L, 1);
|
||||||
|
if (!msg) msg = "Unknown error";
|
||||||
|
|
||||||
|
// Construir traceback
|
||||||
|
luaL_traceback(L, L, msg, 1);
|
||||||
|
|
||||||
|
const char* tb = lua_tostring(L, -1);
|
||||||
|
if (tb) {
|
||||||
|
lastExceptionTraceback = tb;
|
||||||
|
} else {
|
||||||
|
lastExceptionTraceback = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devolver el traceback a Lua (aunque luego Lua lo sustituya)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void lua_call_update() {
|
void lua_call_update() {
|
||||||
if (!update_exists) return;
|
if (!update_exists) return;
|
||||||
function_has_breakpoints = false;
|
function_has_breakpoints = false;
|
||||||
while (!funBreakStack.empty()) funBreakStack.pop();
|
while (!funBreakStack.empty()) funBreakStack.pop();
|
||||||
lua_process_debugger_commands();
|
//lua_process_debugger_commands();
|
||||||
delta_time = float(SDL_GetTicks() - last_update)/1000.0f;
|
delta_time = float(SDL_GetTicks() - last_update)/1000.0f;
|
||||||
last_update = SDL_GetTicks();
|
last_update = SDL_GetTicks();
|
||||||
lua_getglobal(L, "mini");
|
lua_getglobal(L, "mini");
|
||||||
lua_getfield(L, -1, "update");
|
lua_getfield(L, -1, "update");
|
||||||
if (lua_pcall(L, 0, 0, 0)) {
|
|
||||||
log_msg(LOG_LUART, "%s\n", lua_tostring(L, -1));
|
lua_pushcfunction(L, luaErrorHandler);
|
||||||
lua_pop(L,1);
|
lua_insert(L, -2); // poner handler debajo de la función
|
||||||
|
int status = lua_pcall(L, 0, 0, -2);
|
||||||
|
lua_pop(L, 1); // quitar handler
|
||||||
|
|
||||||
|
if (status != LUA_OK) {
|
||||||
|
//log_msg(LOG_LUART, "%s\n", lua_tostring(L, -1));
|
||||||
|
//lua_pop(L,1);
|
||||||
is_playing = false;
|
is_playing = false;
|
||||||
|
|
||||||
|
lastExceptionMessage = lastExceptionTraceback;
|
||||||
|
|
||||||
|
// Limpiar stack anterior
|
||||||
|
//lastExceptionStack.clear();
|
||||||
|
|
||||||
|
// Parsear traceback en frames
|
||||||
|
//parseLuaTraceback(tb, lastExceptionStack);
|
||||||
|
|
||||||
|
lua_pop(L, 1); // pop traceback y error
|
||||||
|
|
||||||
|
hasException = true;
|
||||||
|
|
||||||
|
if (exceptionFilters.count("all") || exceptionFilters.count("uncaught")) {
|
||||||
|
sendExceptionStoppedEvent(lastExceptionMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendLogOutput(lastExceptionMessage);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
mini.cpp
1
mini.cpp
@@ -791,6 +791,7 @@ int main(int argc,char*argv[]){
|
|||||||
|
|
||||||
if (SDL_GetTicks()-dt>13) {
|
if (SDL_GetTicks()-dt>13) {
|
||||||
dt = SDL_GetTicks();
|
dt = SDL_GetTicks();
|
||||||
|
lua_process_debugger_commands();
|
||||||
if (lua_is_playing()) {
|
if (lua_is_playing()) {
|
||||||
lua_call_update();
|
lua_call_update();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user