Adds support for step over, step into and step out.
This commit is contained in:
parent
a2d8293c04
commit
d5cc939a6b
|
@ -37,8 +37,37 @@ void AngelscriptDebugger::on_line_callback(asIScriptContext* ctx, AngelscriptDeb
|
||||||
const char* scriptSection = nullptr;
|
const char* scriptSection = nullptr;
|
||||||
int column = 0;
|
int column = 0;
|
||||||
int line = ctx->GetLineNumber(0, &column, &scriptSection);
|
int line = ctx->GetLineNumber(0, &column, &scriptSection);
|
||||||
if (line == 0)
|
if (line == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->_next && d->_nextContext == ctx && d->_nextDepth >= ctx->GetCallstackSize()) {
|
||||||
|
d->_next = false;
|
||||||
|
ctx->Suspend();
|
||||||
|
d->_pausedContexts.push_back(ctx);
|
||||||
|
auto* o = new DebugAdapterProtocol::StoppedEvent(new DebugAdapterProtocol::StoppedEventBody("step", "", ""));
|
||||||
|
|
||||||
|
d->Send(o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (d->_stepInto && d->_nextContext == ctx) {
|
||||||
|
d->_stepInto = false;
|
||||||
|
ctx->Suspend();
|
||||||
|
d->_pausedContexts.push_back(ctx);
|
||||||
|
auto* o = new DebugAdapterProtocol::StoppedEvent(new DebugAdapterProtocol::StoppedEventBody("step", "", ""));
|
||||||
|
|
||||||
|
d->Send(o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (d->_stepOut && d->_nextContext == ctx && d->_nextDepth > ctx->GetCallstackSize()) {
|
||||||
|
d->_stepOut = false;
|
||||||
|
ctx->Suspend();
|
||||||
|
d->_pausedContexts.push_back(ctx);
|
||||||
|
auto* o = new DebugAdapterProtocol::StoppedEvent(new DebugAdapterProtocol::StoppedEventBody("step", "", ""));
|
||||||
|
|
||||||
|
d->Send(o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto resolvedScriptPath = d->GetResolvedScriptPath(scriptSection);
|
auto resolvedScriptPath = d->GetResolvedScriptPath(scriptSection);
|
||||||
auto sectionBreakpoints = d->_breakpoints.find(resolvedScriptPath);
|
auto sectionBreakpoints = d->_breakpoints.find(resolvedScriptPath);
|
||||||
|
@ -257,7 +286,7 @@ void AngelscriptDebugger::OnRequest(asio::ip::tcp::socket* client, DebugAdapterP
|
||||||
const char* scriptSection = nullptr;
|
const char* scriptSection = nullptr;
|
||||||
int column = 0;
|
int column = 0;
|
||||||
int line;
|
int line;
|
||||||
if (i == 0 && ctx->GetExceptionString() != nullptr) {
|
if (i == 0 && ctx->GetExceptionFunction() != nullptr) {
|
||||||
line = ctx->GetExceptionLineNumber(&column, &scriptSection);
|
line = ctx->GetExceptionLineNumber(&column, &scriptSection);
|
||||||
} else {
|
} else {
|
||||||
line = ctx->GetLineNumber(i, &column, &scriptSection);
|
line = ctx->GetLineNumber(i, &column, &scriptSection);
|
||||||
|
@ -330,7 +359,48 @@ void AngelscriptDebugger::OnRequest(asio::ip::tcp::socket* client, DebugAdapterP
|
||||||
auto body = new DebugAdapterProtocol::VariablesResponseBody(variables);
|
auto body = new DebugAdapterProtocol::VariablesResponseBody(variables);
|
||||||
response->body = body;
|
response->body = body;
|
||||||
Send(client, response);
|
Send(client, response);
|
||||||
|
} else if (msg->GetCommand() == "next") {
|
||||||
|
Next(_pausedContexts.at(0));
|
||||||
|
} else if (msg->GetCommand() == "stepIn") {
|
||||||
|
StepInto(_pausedContexts.at(0));
|
||||||
|
} else if (msg->GetCommand() == "stepOut") {
|
||||||
|
StepOut(_pausedContexts.at(0));
|
||||||
} else {
|
} else {
|
||||||
|
std::cout << "Unhandled message: " << msg->GetCommand() << std::endl;
|
||||||
Send(client, new DebugAdapterProtocol::DefinedResponse<DebugAdapterProtocol::ResponseBody, empty>(msg->seq));
|
Send(client, new DebugAdapterProtocol::DefinedResponse<DebugAdapterProtocol::ResponseBody, empty>(msg->seq));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void AngelscriptDebugger::Next(asIScriptContext* ctx) {
|
||||||
|
_nextContext = ctx;
|
||||||
|
_next = true;
|
||||||
|
_nextDepth = ctx->GetCallstackSize();
|
||||||
|
_storedVariableReferences.clear();
|
||||||
|
while (!_pausedContexts.empty()) {
|
||||||
|
auto* c = _pausedContexts[_pausedContexts.size() - 1];
|
||||||
|
_pausedContexts.pop_back();
|
||||||
|
std::thread([](asIScriptContext* c) { c->Execute(); }, c).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AngelscriptDebugger::StepInto(asIScriptContext* ctx) {
|
||||||
|
_nextContext = ctx;
|
||||||
|
_stepInto = true;
|
||||||
|
_nextDepth = ctx->GetCallstackSize();
|
||||||
|
_storedVariableReferences.clear();
|
||||||
|
while (!_pausedContexts.empty()) {
|
||||||
|
auto* c = _pausedContexts[_pausedContexts.size() - 1];
|
||||||
|
_pausedContexts.pop_back();
|
||||||
|
std::thread([](asIScriptContext* c) { c->Execute(); }, c).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void AngelscriptDebugger::StepOut(asIScriptContext* ctx) {
|
||||||
|
_nextContext = ctx;
|
||||||
|
_stepOut = true;
|
||||||
|
_nextDepth = ctx->GetCallstackSize();
|
||||||
|
_storedVariableReferences.clear();
|
||||||
|
while (!_pausedContexts.empty()) {
|
||||||
|
auto* c = _pausedContexts[_pausedContexts.size() - 1];
|
||||||
|
_pausedContexts.pop_back();
|
||||||
|
std::thread([](asIScriptContext* c) { c->Execute(); }, c).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,10 @@ private:
|
||||||
void OnRequest(asio::ip::tcp::socket* client, DebugAdapterProtocol::Request* msg);
|
void OnRequest(asio::ip::tcp::socket* client, DebugAdapterProtocol::Request* msg);
|
||||||
std::string GetResolvedScriptPath(const char* scriptSection);
|
std::string GetResolvedScriptPath(const char* scriptSection);
|
||||||
|
|
||||||
|
void Next(asIScriptContext* ctx);
|
||||||
|
void StepInto(asIScriptContext* ctx);
|
||||||
|
void StepOut(asIScriptContext* ctx);
|
||||||
|
|
||||||
asio::io_context _ioContext;
|
asio::io_context _ioContext;
|
||||||
asio::ip::tcp::acceptor* _server;
|
asio::ip::tcp::acceptor* _server;
|
||||||
std::unordered_set<asio::ip::tcp::socket*> _connections;
|
std::unordered_set<asio::ip::tcp::socket*> _connections;
|
||||||
|
@ -64,6 +68,12 @@ private:
|
||||||
std::vector<asIScriptContext*> _pausedContexts;
|
std::vector<asIScriptContext*> _pausedContexts;
|
||||||
std::optional<std::string> _scriptPath;
|
std::optional<std::string> _scriptPath;
|
||||||
|
|
||||||
|
asIScriptContext* _nextContext;
|
||||||
|
bool _next;
|
||||||
|
size_t _nextDepth;
|
||||||
|
bool _stepInto;
|
||||||
|
bool _stepOut;
|
||||||
|
|
||||||
struct StackScope {
|
struct StackScope {
|
||||||
size_t StackLevel;
|
size_t StackLevel;
|
||||||
uint8_t Type;
|
uint8_t Type;
|
||||||
|
|
|
@ -182,7 +182,7 @@ namespace DebugAdapterProtocol {
|
||||||
EventDefinition(Stopped, "stopped", {
|
EventDefinition(Stopped, "stopped", {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::optional<size_t> number;
|
std::optional<size_t> threadId = 0;
|
||||||
std::optional<bool> preserveFocusHint = false;
|
std::optional<bool> preserveFocusHint = false;
|
||||||
std::optional<std::string> text;
|
std::optional<std::string> text;
|
||||||
std::optional<bool> allThreadsStopped = true;
|
std::optional<bool> allThreadsStopped = true;
|
||||||
|
@ -197,7 +197,7 @@ namespace DebugAdapterProtocol {
|
||||||
auto o = EventBody::ToJson();
|
auto o = EventBody::ToJson();
|
||||||
o["reason"] = reason;
|
o["reason"] = reason;
|
||||||
JsonSerializeOptional(o, description);
|
JsonSerializeOptional(o, description);
|
||||||
JsonSerializeOptional(o, number);
|
JsonSerializeOptional(o, threadId);
|
||||||
JsonSerializeOptional(o, preserveFocusHint);
|
JsonSerializeOptional(o, preserveFocusHint);
|
||||||
JsonSerializeOptional(o, text);
|
JsonSerializeOptional(o, text);
|
||||||
JsonSerializeOptional(o, allThreadsStopped);
|
JsonSerializeOptional(o, allThreadsStopped);
|
||||||
|
|
Loading…
Reference in New Issue