@@ -176,6 +176,7 @@ void DebugAdapterProtocol::reset_current_info() {
176176void DebugAdapterProtocol::reset_ids () {
177177 breakpoint_id = 0 ;
178178 breakpoint_list.clear ();
179+ breakpoint_source_list.clear ();
179180
180181 reset_stack_info ();
181182}
@@ -185,6 +186,7 @@ void DebugAdapterProtocol::reset_stack_info() {
185186 variable_id = 1 ;
186187
187188 stackframe_list.clear ();
189+ scope_list.clear ();
188190 variable_list.clear ();
189191 object_list.clear ();
190192 object_pending_set.clear ();
@@ -824,6 +826,30 @@ bool DebugAdapterProtocol::request_remote_evaluate(const String &p_eval, int p_s
824826 return true ;
825827}
826828
829+ const DAP::Source &DebugAdapterProtocol::fetch_source (const String &p_path) {
830+ const String &global_path = ProjectSettings::get_singleton ()->globalize_path (p_path);
831+
832+ HashMap<String, DAP::Source>::Iterator E = breakpoint_source_list.find (global_path);
833+ if (E != breakpoint_source_list.end ()) {
834+ return E->value ;
835+ }
836+ DAP::Source &added_source = breakpoint_source_list.insert (global_path, DAP::Source ())->value ;
837+ added_source.name = global_path.get_file ();
838+ added_source.path = global_path;
839+ added_source.compute_checksums ();
840+
841+ return added_source;
842+ }
843+
844+ void DebugAdapterProtocol::update_source (const String &p_path) {
845+ const String &global_path = ProjectSettings::get_singleton ()->globalize_path (p_path);
846+
847+ HashMap<String, DAP::Source>::Iterator E = breakpoint_source_list.find (global_path);
848+ if (E != breakpoint_source_list.end ()) {
849+ E->value .compute_checksums ();
850+ }
851+ }
852+
827853bool DebugAdapterProtocol::process_message (const String &p_text) {
828854 JSON json;
829855 ERR_FAIL_COND_V_MSG (json.parse (p_text) != OK, true , " Malformed message!" );
@@ -962,22 +988,40 @@ Array DebugAdapterProtocol::update_breakpoints(const String &p_path, const Array
962988
963989 // Add breakpoints
964990 for (int i = 0 ; i < p_lines.size (); i++) {
965- EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, p_lines[i], true );
966- DAP::Breakpoint breakpoint;
991+ DAP::Breakpoint breakpoint (fetch_source (p_path));
967992 breakpoint.line = p_lines[i];
968- breakpoint.source .path = p_path;
969993
970- ERR_FAIL_COND_V (!breakpoint_list.find (breakpoint), Array ());
971- updated_breakpoints.push_back (breakpoint_list.find (breakpoint)->get ().to_json ());
994+ // Avoid duplicated entries.
995+ List<DAP::Breakpoint>::Element *E = breakpoint_list.find (breakpoint);
996+ if (E) {
997+ updated_breakpoints.push_back (E->get ().to_json ());
998+ continue ;
999+ }
1000+
1001+ EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, p_lines[i], true );
1002+
1003+ // Breakpoints are inserted at the end of the breakpoint list.
1004+ List<DAP::Breakpoint>::Element *added_breakpoint = breakpoint_list.back ();
1005+ ERR_FAIL_NULL_V (added_breakpoint, Array ());
1006+ ERR_FAIL_COND_V (!(added_breakpoint->get () == breakpoint), Array ());
1007+ updated_breakpoints.push_back (added_breakpoint->get ().to_json ());
9721008 }
9731009
9741010 // Remove breakpoints
1011+ // Must be deferred because we are iterating the breakpoint list.
1012+ Vector<int > to_remove;
1013+
9751014 for (const DAP::Breakpoint &b : breakpoint_list) {
976- if (b.source . path == p_path && !p_lines.has (b.line )) {
977- EditorDebuggerNode::get_singleton ()-> get_default_debugger ()-> _set_breakpoint (p_path, b.line , false );
1015+ if (b.source -> path == p_path && !p_lines.has (b.line )) {
1016+ to_remove. push_back ( b.line );
9781017 }
9791018 }
9801019
1020+ // Safe to remove queued data now.
1021+ for (const int &line : to_remove) {
1022+ EditorDebuggerNode::get_singleton ()->get_default_debugger ()->_set_breakpoint (p_path, line, false );
1023+ }
1024+
9811025 return updated_breakpoints;
9821026}
9831027
@@ -1020,10 +1064,8 @@ void DebugAdapterProtocol::on_debug_breaked(const bool &p_reallydid, const bool
10201064}
10211065
10221066void DebugAdapterProtocol::on_debug_breakpoint_toggled (const String &p_path, const int &p_line, const bool &p_enabled) {
1023- DAP::Breakpoint breakpoint;
1067+ DAP::Breakpoint breakpoint ( fetch_source (p_path)) ;
10241068 breakpoint.verified = true ;
1025- breakpoint.source .path = ProjectSettings::get_singleton ()->globalize_path (p_path);
1026- breakpoint.source .compute_checksums ();
10271069 breakpoint.line = p_line;
10281070
10291071 if (p_enabled) {
@@ -1046,8 +1088,7 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10461088 if (_processing_breakpoint && !p_stack_dump.is_empty ()) {
10471089 // Find existing breakpoint
10481090 Dictionary d = p_stack_dump[0 ];
1049- DAP::Breakpoint breakpoint;
1050- breakpoint.source .path = ProjectSettings::get_singleton ()->globalize_path (d[" file" ]);
1091+ DAP::Breakpoint breakpoint (fetch_source (d[" file" ]));
10511092 breakpoint.line = d[" line" ];
10521093
10531094 List<DAP::Breakpoint>::Element *E = breakpoint_list.find (breakpoint);
@@ -1060,25 +1101,26 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10601101
10611102 stackframe_id = 0 ;
10621103 stackframe_list.clear ();
1104+ scope_list.clear ();
10631105
10641106 // Fill in stacktrace information
10651107 for (int i = 0 ; i < p_stack_dump.size (); i++) {
10661108 Dictionary stack_info = p_stack_dump[i];
1067- DAP::StackFrame stackframe;
1109+
1110+ DAP::StackFrame stackframe (fetch_source (stack_info[" file" ]));
10681111 stackframe.id = stackframe_id++;
10691112 stackframe.name = stack_info[" function" ];
10701113 stackframe.line = stack_info[" line" ];
10711114 stackframe.column = 0 ;
1072- stackframe.source .path = ProjectSettings::get_singleton ()->globalize_path (stack_info[" file" ]);
1073- stackframe.source .compute_checksums ();
10741115
10751116 // Information for "Locals", "Members" and "Globals" variables respectively
1076- List <int > scope_ids;
1117+ Vector <int > scope_ids;
10771118 for (int j = 0 ; j < 3 ; j++) {
10781119 scope_ids.push_back (variable_id++);
10791120 }
10801121
1081- stackframe_list.insert (stackframe, scope_ids);
1122+ stackframe_list.push_back (stackframe);
1123+ scope_list.insert (stackframe.id , scope_ids);
10821124 }
10831125
10841126 _current_frame = 0 ;
@@ -1087,11 +1129,9 @@ void DebugAdapterProtocol::on_debug_stack_dump(const Array &p_stack_dump) {
10871129
10881130void DebugAdapterProtocol::on_debug_stack_frame_vars (const int &p_size) {
10891131 _remaining_vars = p_size;
1090- DAP::StackFrame frame;
1091- frame.id = _current_frame;
1092- ERR_FAIL_COND (!stackframe_list.has (frame));
1093- List<int > scope_ids = stackframe_list.find (frame)->value ;
1094- for (const int var_id : scope_ids) {
1132+ ERR_FAIL_COND (!scope_list.has (_current_frame));
1133+ Vector<int > scope_ids = scope_list.find (_current_frame)->value ;
1134+ for (const int &var_id : scope_ids) {
10951135 if (variable_list.has (var_id)) {
10961136 variable_list.find (var_id)->value .clear ();
10971137 } else {
@@ -1104,11 +1144,9 @@ void DebugAdapterProtocol::on_debug_stack_frame_var(const Array &p_data) {
11041144 DebuggerMarshalls::ScriptStackVariable stack_var;
11051145 stack_var.deserialize (p_data);
11061146
1107- ERR_FAIL_COND (stackframe_list.is_empty ());
1108- DAP::StackFrame frame;
1109- frame.id = _current_frame;
1147+ ERR_FAIL_COND (!scope_list.has (_current_frame));
1148+ Vector<int > scope_ids = scope_list.find (_current_frame)->value ;
11101149
1111- List<int > scope_ids = stackframe_list.find (frame)->value ;
11121150 ERR_FAIL_COND (scope_ids.size () != 3 );
11131151 ERR_FAIL_INDEX (stack_var.type , 4 );
11141152 int var_id = scope_ids.get (stack_var.type );
0 commit comments