@@ -174,6 +174,7 @@ void DebugAdapterProtocol::reset_current_info() {
174174void DebugAdapterProtocol::reset_ids () {
175175 breakpoint_id = 0 ;
176176 breakpoint_list.clear ();
177+ breakpoint_source_list.clear ();
177178
178179 reset_stack_info ();
179180}
@@ -183,6 +184,7 @@ void DebugAdapterProtocol::reset_stack_info() {
183184 variable_id = 1 ;
184185
185186 stackframe_list.clear ();
187+ scope_list.clear ();
186188 variable_list.clear ();
187189 object_list.clear ();
188190 object_pending_set.clear ();
@@ -822,6 +824,30 @@ bool DebugAdapterProtocol::request_remote_evaluate(const String &p_eval, int p_s
822824 return true ;
823825}
824826
827+ const DAP::Source &DebugAdapterProtocol::fetch_source (const String &p_path) {
828+ const String &global_path = ProjectSettings::get_singleton ()->globalize_path (p_path);
829+
830+ HashMap<String, DAP::Source>::Iterator E = breakpoint_source_list.find (global_path);
831+ if (E != breakpoint_source_list.end ()) {
832+ return E->value ;
833+ }
834+ DAP::Source &added_source = breakpoint_source_list.insert (global_path, DAP::Source ())->value ;
835+ added_source.name = global_path.get_file ();
836+ added_source.path = global_path;
837+ added_source.compute_checksums ();
838+
839+ return added_source;
840+ }
841+
842+ void DebugAdapterProtocol::update_source (const String &p_path) {
843+ const String &global_path = ProjectSettings::get_singleton ()->globalize_path (p_path);
844+
845+ HashMap<String, DAP::Source>::Iterator E = breakpoint_source_list.find (global_path);
846+ if (E != breakpoint_source_list.end ()) {
847+ E->value .compute_checksums ();
848+ }
849+ }
850+
825851bool DebugAdapterProtocol::process_message (const String &p_text) {
826852 JSON json;
827853 ERR_FAIL_COND_V_MSG (json.parse (p_text) != OK, true , " Malformed message!" );
@@ -960,22 +986,40 @@ Array DebugAdapterProtocol::update_breakpoints(const String &p_path, const Array
960986
961987 // Add breakpoints
962988 for (int i = 0 ; i < p_lines.size (); i++) {
963- EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, p_lines[i], true );
964- DAP::Breakpoint breakpoint;
989+ DAP::Breakpoint breakpoint (fetch_source (p_path));
965990 breakpoint.line = p_lines[i];
966- breakpoint.source .path = p_path;
967991
968- ERR_FAIL_COND_V (!breakpoint_list.find (breakpoint), Array ());
969- updated_breakpoints.push_back (breakpoint_list.find (breakpoint)->get ().to_json ());
992+ // Avoid duplicated entries.
993+ List<DAP::Breakpoint>::Element *E = breakpoint_list.find (breakpoint);
994+ if (E) {
995+ updated_breakpoints.push_back (E->get ().to_json ());
996+ continue ;
997+ }
998+
999+ EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, p_lines[i], true );
1000+
1001+ // Breakpoints are inserted at the end of the breakpoint list.
1002+ List<DAP::Breakpoint>::Element *added_breakpoint = breakpoint_list.back ();
1003+ ERR_FAIL_NULL_V (added_breakpoint, Array ());
1004+ ERR_FAIL_COND_V (!(added_breakpoint->get () == breakpoint), Array ());
1005+ updated_breakpoints.push_back (added_breakpoint->get ().to_json ());
9701006 }
9711007
9721008 // Remove breakpoints
1009+ // Must be deferred because we are iterating the breakpoint list.
1010+ Vector<int > to_remove;
1011+
9731012 for (const DAP::Breakpoint &b : breakpoint_list) {
974- if (b.source . path == p_path && !p_lines.has (b.line )) {
975- EditorDebuggerNode::get_singleton ()-> get_default_debugger ()-> _set_breakpoint (p_path, b.line , false );
1013+ if (b.source -> path == p_path && !p_lines.has (b.line )) {
1014+ to_remove. push_back ( b.line );
9761015 }
9771016 }
9781017
1018+ // Safe to remove queued data now.
1019+ for (const int &line : to_remove) {
1020+ EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, line, false );
1021+ }
1022+
9791023 return updated_breakpoints;
9801024}
9811025
@@ -1018,10 +1062,8 @@ void DebugAdapterProtocol::on_debug_breaked(const bool &p_reallydid, const bool
10181062}
10191063
10201064void DebugAdapterProtocol::on_debug_breakpoint_toggled (const String &p_path, const int &p_line, const bool &p_enabled) {
1021- DAP::Breakpoint breakpoint;
1065+ DAP::Breakpoint breakpoint ( fetch_source (p_path)) ;
10221066 breakpoint.verified = true ;
1023- breakpoint.source .path = ProjectSettings::get_singleton ()->globalize_path (p_path);
1024- breakpoint.source .compute_checksums ();
10251067 breakpoint.line = p_line;
10261068
10271069 if (p_enabled) {
@@ -1044,8 +1086,7 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10441086 if (_processing_breakpoint && !p_stack_dump.is_empty ()) {
10451087 // Find existing breakpoint
10461088 Dictionary d = p_stack_dump[0 ];
1047- DAP::Breakpoint breakpoint;
1048- breakpoint.source .path = ProjectSettings::get_singleton ()->globalize_path (d[" file" ]);
1089+ DAP::Breakpoint breakpoint (fetch_source (d[" file" ]));
10491090 breakpoint.line = d[" line" ];
10501091
10511092 List<DAP::Breakpoint>::Element *E = breakpoint_list.find (breakpoint);
@@ -1058,25 +1099,26 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10581099
10591100 stackframe_id = 0 ;
10601101 stackframe_list.clear ();
1102+ scope_list.clear ();
10611103
10621104 // Fill in stacktrace information
10631105 for (int i = 0 ; i < p_stack_dump.size (); i++) {
10641106 Dictionary stack_info = p_stack_dump[i];
1065- DAP::StackFrame stackframe;
1107+
1108+ DAP::StackFrame stackframe (fetch_source (stack_info[" file" ]));
10661109 stackframe.id = stackframe_id++;
10671110 stackframe.name = stack_info[" function" ];
10681111 stackframe.line = stack_info[" line" ];
10691112 stackframe.column = 0 ;
1070- stackframe.source .path = ProjectSettings::get_singleton ()->globalize_path (stack_info[" file" ]);
1071- stackframe.source .compute_checksums ();
10721113
10731114 // Information for "Locals", "Members" and "Globals" variables respectively
1074- List <int > scope_ids;
1115+ Vector <int > scope_ids;
10751116 for (int j = 0 ; j < 3 ; j++) {
10761117 scope_ids.push_back (variable_id++);
10771118 }
10781119
1079- stackframe_list.insert (stackframe, scope_ids);
1120+ stackframe_list.push_back (stackframe);
1121+ scope_list.insert (stackframe.id , scope_ids);
10801122 }
10811123
10821124 _current_frame = 0 ;
@@ -1085,11 +1127,9 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10851127
10861128void DebugAdapterProtocol::on_debug_stack_frame_vars (const int &p_size) {
10871129 _remaining_vars = p_size;
1088- DAP::StackFrame frame;
1089- frame.id = _current_frame;
1090- ERR_FAIL_COND (!stackframe_list.has (frame));
1091- List<int > scope_ids = stackframe_list.find (frame)->value ;
1092- for (const int var_id : scope_ids) {
1130+ ERR_FAIL_COND (!scope_list.has (_current_frame));
1131+ Vector<int > scope_ids = scope_list.find (_current_frame)->value ;
1132+ for (const int &var_id : scope_ids) {
10931133 if (variable_list.has (var_id)) {
10941134 variable_list.find (var_id)->value .clear ();
10951135 } else {
@@ -1102,11 +1142,9 @@ void DebugAdapterProtocol::on_debug_stack_frame_var(const Array &p_data) {
11021142 DebuggerMarshalls::ScriptStackVariable stack_var;
11031143 stack_var.deserialize (p_data);
11041144
1105- ERR_FAIL_COND (stackframe_list.is_empty ());
1106- DAP::StackFrame frame;
1107- frame.id = _current_frame;
1145+ ERR_FAIL_COND (!scope_list.has (_current_frame));
1146+ Vector<int > scope_ids = scope_list.find (_current_frame)->value ;
11081147
1109- List<int > scope_ids = stackframe_list.find (frame)->value ;
11101148 ERR_FAIL_COND (scope_ids.size () != 3 );
11111149 ERR_FAIL_INDEX (stack_var.type , 4 );
11121150 int var_id = scope_ids.get (stack_var.type );
0 commit comments