Skip to content

Commit 0d098d3

Browse files
committed
Support REPL expressions through DAP evaluate request
1 parent 6aac039 commit 0d098d3

File tree

6 files changed

+71
-11
lines changed

6 files changed

+71
-11
lines changed

editor/debugger/debug_adapter/debug_adapter_parser.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
#include "debug_adapter_parser.h"
3232

33+
#include "core/variant/variant.h"
34+
#include "editor/debugger/debug_adapter/debug_adapter_types.h"
3335
#include "editor/debugger/editor_debugger_node.h"
3436
#include "editor/debugger/script_editor_debugger.h"
3537
#include "editor/export/editor_export_platform.h"
@@ -487,16 +489,27 @@ Dictionary DebugAdapterParser::req_stepIn(const Dictionary &p_params) const {
487489
}
488490

489491
Dictionary DebugAdapterParser::req_evaluate(const Dictionary &p_params) const {
490-
Dictionary response = prepare_success_response(p_params), body;
491-
response["body"] = body;
492-
493492
Dictionary args = p_params["arguments"];
493+
String expression = args["expression"];
494+
int frame_id = args.has("frameId") ? static_cast<int>(args["frameId"]) : DebugAdapterProtocol::get_singleton()->_current_frame;
494495

495-
String value = EditorDebuggerNode::get_singleton()->get_var_value(args["expression"]);
496-
body["result"] = value;
497-
body["variablesReference"] = 0;
496+
if (HashMap<String, DAP::Variable>::Iterator E = DebugAdapterProtocol::get_singleton()->eval_list.find(expression); E) {
497+
Dictionary response = prepare_success_response(p_params);
498+
Dictionary body;
499+
response["body"] = body;
498500

499-
return response;
501+
DAP::Variable var = E->value;
502+
503+
body["result"] = var.value;
504+
body["variablesReference"] = var.variablesReference;
505+
506+
// Since an evaluation can alter the state of the debuggee, they are volatile, and should only be used once
507+
DebugAdapterProtocol::get_singleton()->eval_list.erase(E->key);
508+
return response;
509+
} else {
510+
DebugAdapterProtocol::get_singleton()->request_remote_evaluate(expression, frame_id);
511+
}
512+
return Dictionary();
500513
}
501514

502515
Dictionary DebugAdapterParser::req_godot_put_msg(const Dictionary &p_params) const {

editor/debugger/debug_adapter/debug_adapter_protocol.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,22 @@ void DebugAdapterProtocol::parse_object(SceneDebuggerObject &p_obj) {
799799
variable_list.insert(object_list[object_id], properties);
800800
}
801801

802+
void DebugAdapterProtocol::parse_evaluation(DebuggerMarshalls::ScriptStackVariable &p_var) {
803+
// If the eval is not on the pending list, we weren't expecting it. Ignore it.
804+
String eval = p_var.name;
805+
if (!eval_pending_list.erase(eval)) {
806+
return;
807+
}
808+
809+
DAP::Variable variable;
810+
variable.name = p_var.name;
811+
variable.value = p_var.value;
812+
variable.type = Variant::get_type_name(p_var.value.get_type());
813+
variable.variablesReference = parse_variant(p_var.value);
814+
815+
eval_list.insert(variable.name, variable);
816+
}
817+
802818
const Variant DebugAdapterProtocol::parse_object_variable(const SceneDebuggerObject::SceneDebuggerProperty &p_property) {
803819
const PropertyInfo &info = p_property.first;
804820
const Variant &value = p_property.second;
@@ -833,6 +849,18 @@ bool DebugAdapterProtocol::request_remote_object(const ObjectID &p_object_id) {
833849
return true;
834850
}
835851

852+
bool DebugAdapterProtocol::request_remote_evaluate(const String &p_eval, int p_stack_frame) {
853+
// If the eval is already on the pending list, we don't need to request it again
854+
if (eval_pending_list.has(p_eval)) {
855+
return false;
856+
}
857+
858+
EditorDebuggerNode::get_singleton()->get_default_debugger()->request_remote_evaluate(p_eval, p_stack_frame);
859+
eval_pending_list.insert(p_eval);
860+
861+
return true;
862+
}
863+
836864
bool DebugAdapterProtocol::process_message(const String &p_text) {
837865
JSON json;
838866
ERR_FAIL_COND_V_MSG(json.parse(p_text) != OK, true, "Malformed message!");
@@ -1148,6 +1176,12 @@ void DebugAdapterProtocol::on_debug_data(const String &p_msg, const Array &p_dat
11481176
remote_obj.deserialize(p_data);
11491177

11501178
parse_object(remote_obj);
1179+
} else if (p_msg == "evaluation_return") {
1180+
// An evaluation was requested from the debuggee; parse it.
1181+
DebuggerMarshalls::ScriptStackVariable remote_evaluation;
1182+
remote_evaluation.deserialize(p_data);
1183+
1184+
parse_evaluation(remote_evaluation);
11511185
}
11521186

11531187
notify_custom_data(p_msg, p_data);

editor/debugger/debug_adapter/debug_adapter_protocol.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
#ifndef DEBUG_ADAPTER_PROTOCOL_H
3232
#define DEBUG_ADAPTER_PROTOCOL_H
3333

34+
#include "core/debugger/debugger_marshalls.h"
3435
#include "core/io/stream_peer_tcp.h"
3536
#include "core/io/tcp_server.h"
3637

38+
#include "core/object/object_id.h"
3739
#include "debug_adapter_parser.h"
3840
#include "debug_adapter_types.h"
3941
#include "scene/debugger/scene_debugger.h"
@@ -103,9 +105,11 @@ class DebugAdapterProtocol : public Object {
103105
int parse_variant(const Variant &p_var);
104106
void parse_object(SceneDebuggerObject &p_obj);
105107
const Variant parse_object_variable(const SceneDebuggerObject::SceneDebuggerProperty &p_property);
108+
void parse_evaluation(DebuggerMarshalls::ScriptStackVariable &p_var);
106109

107110
ObjectID search_object_id(DAPVarID p_var_id);
108111
bool request_remote_object(const ObjectID &p_object_id);
112+
bool request_remote_evaluate(const String &p_eval, int p_stack_frame);
109113

110114
bool _initialized = false;
111115
bool _processing_breakpoint = false;
@@ -129,6 +133,9 @@ class DebugAdapterProtocol : public Object {
129133
HashMap<ObjectID, DAPVarID> object_list;
130134
HashSet<ObjectID> object_pending_set;
131135

136+
HashMap<String, DAP::Variable> eval_list;
137+
HashSet<String> eval_pending_list;
138+
132139
public:
133140
friend class DebugAdapterServer;
134141

editor/debugger/editor_expression_evaluator.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ void EditorExpressionEvaluator::_evaluate() {
6464
return;
6565
}
6666

67-
Array expr_data;
68-
expr_data.push_back(expression);
69-
expr_data.push_back(editor_debugger->get_stack_script_frame());
70-
editor_debugger->send_message("evaluate", expr_data);
67+
editor_debugger->request_remote_evaluate(expression, editor_debugger->get_stack_script_frame());
7168

7269
expression_input->clear();
7370
}

editor/debugger/script_editor_debugger.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ const SceneDebuggerTree *ScriptEditorDebugger::get_remote_tree() {
253253
return scene_tree;
254254
}
255255

256+
void ScriptEditorDebugger::request_remote_evaluate(const String &p_expression, int p_stack_frame) {
257+
Array msg;
258+
msg.push_back(p_expression);
259+
msg.push_back(p_stack_frame);
260+
_put_msg("evaluate", msg);
261+
}
262+
256263
void ScriptEditorDebugger::update_remote_object(ObjectID p_obj_id, const String &p_prop, const Variant &p_value) {
257264
Array msg;
258265
msg.push_back(p_obj_id);

editor/debugger/script_editor_debugger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ class ScriptEditorDebugger : public MarginContainer {
254254
void request_remote_tree();
255255
const SceneDebuggerTree *get_remote_tree();
256256

257+
void request_remote_evaluate(const String &p_expression, int p_stack_frame);
258+
257259
void start(Ref<RemoteDebuggerPeer> p_peer);
258260
void stop();
259261

0 commit comments

Comments
 (0)