Browse Source

Fix breakpointed_lines out of sync when removing lines above

Paulb23 3 years ago
parent
commit
0caab00d66
3 changed files with 80 additions and 3 deletions
  1. 4 3
      scene/gui/code_edit.cpp
  2. 1 0
      scene/gui/code_edit.h
  3. 75 0
      tests/test_code_edit.h

+ 4 - 3
scene/gui/code_edit.cpp

@@ -2937,6 +2937,7 @@ void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
 		return;
 	}
 
+	lines_edited_changed += p_to_line - p_from_line;
 	lines_edited_from = (lines_edited_from == -1) ? MIN(p_from_line, p_to_line) : MIN(lines_edited_from, MIN(p_from_line, p_to_line));
 	lines_edited_to = (lines_edited_to == -1) ? MAX(p_from_line, p_to_line) : MAX(lines_edited_from, MAX(p_from_line, p_to_line));
 }
@@ -2963,7 +2964,6 @@ void CodeEdit::_text_changed() {
 	}
 
 	lc = get_line_count();
-	int line_change_size = (lines_edited_to - lines_edited_from);
 	List<int> breakpoints;
 	breakpointed_lines.get_key_list(&breakpoints);
 	for (const int &line : breakpoints) {
@@ -2974,8 +2974,8 @@ void CodeEdit::_text_changed() {
 		breakpointed_lines.erase(line);
 		emit_signal(SNAME("breakpoint_toggled"), line);
 
-		int next_line = line + line_change_size;
-		if (next_line < lc && is_line_breakpointed(next_line)) {
+		int next_line = line + lines_edited_changed;
+		if (next_line > -1 && next_line < lc && is_line_breakpointed(next_line)) {
 			emit_signal(SNAME("breakpoint_toggled"), next_line);
 			breakpointed_lines[next_line] = true;
 			continue;
@@ -2984,6 +2984,7 @@ void CodeEdit::_text_changed() {
 
 	lines_edited_from = -1;
 	lines_edited_to = -1;
+	lines_edited_changed = 0;
 }
 
 CodeEdit::CodeEdit() {

+ 1 - 0
scene/gui/code_edit.h

@@ -240,6 +240,7 @@ private:
 	int line_spacing = 1;
 
 	/* Callbacks */
+	int lines_edited_changed = 0;
 	int lines_edited_from = -1;
 	int lines_edited_to = -1;
 

+ 75 - 0
tests/test_code_edit.h

@@ -284,6 +284,26 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
 			CHECK_FALSE(code_edit->is_line_breakpointed(1));
 			ERR_PRINT_ON;
 			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			/* Backspace above breakpointed line moves it. */
+			((Array)args[0])[0] = 2;
+
+			code_edit->set_text("\n\n");
+			code_edit->set_line_as_breakpoint(2, true);
+			CHECK(code_edit->is_line_breakpointed(2));
+			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			code_edit->set_caret_line(1);
+
+			Array arg2;
+			arg2.push_back(1);
+			args.push_back(arg2);
+			SEND_GUI_ACTION(code_edit, "ui_text_backspace");
+			ERR_PRINT_OFF;
+			CHECK_FALSE(code_edit->is_line_breakpointed(2));
+			ERR_PRINT_ON;
+			CHECK(code_edit->is_line_breakpointed(1));
+			SIGNAL_CHECK("breakpoint_toggled", args);
 		}
 
 		SUBCASE("[CodeEdit] breakpoints and delete") {
@@ -312,6 +332,26 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
 			CHECK_FALSE(code_edit->is_line_breakpointed(1));
 			ERR_PRINT_ON;
 			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			/* Delete above breakpointed line moves it. */
+			((Array)args[0])[0] = 2;
+
+			code_edit->set_text("\n\n");
+			code_edit->set_line_as_breakpoint(2, true);
+			CHECK(code_edit->is_line_breakpointed(2));
+			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			code_edit->set_caret_line(0);
+
+			Array arg2;
+			arg2.push_back(1);
+			args.push_back(arg2);
+			SEND_GUI_ACTION(code_edit, "ui_text_delete");
+			ERR_PRINT_OFF;
+			CHECK_FALSE(code_edit->is_line_breakpointed(2));
+			ERR_PRINT_ON;
+			CHECK(code_edit->is_line_breakpointed(1));
+			SIGNAL_CHECK("breakpoint_toggled", args);
 		}
 
 		SUBCASE("[CodeEdit] breakpoints and delete selection") {
@@ -330,6 +370,41 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
 			MessageQueue::get_singleton()->flush();
 			CHECK_FALSE(code_edit->is_line_breakpointed(0));
 			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			/* Should handle breakpoint move when deleting selection by adding less text then removed. */
+			((Array)args[0])[0] = 9;
+
+			code_edit->set_text("\n\n\n\n\n\n\n\n\n");
+			code_edit->set_line_as_breakpoint(9, true);
+			CHECK(code_edit->is_line_breakpointed(9));
+			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			code_edit->select(0, 0, 6, 0);
+
+			Array arg2;
+			arg2.push_back(4);
+			args.push_back(arg2);
+			SEND_GUI_ACTION(code_edit, "ui_text_newline");
+			ERR_PRINT_OFF;
+			CHECK_FALSE(code_edit->is_line_breakpointed(9));
+			ERR_PRINT_ON;
+			CHECK(code_edit->is_line_breakpointed(4));
+			SIGNAL_CHECK("breakpoint_toggled", args);
+
+			/* Should handle breakpoint move when deleting selection by adding more text then removed. */
+			((Array)args[0])[0] = 9;
+			((Array)args[1])[0] = 14;
+
+			code_edit->insert_text_at_caret("\n\n\n\n\n");
+			MessageQueue::get_singleton()->flush();
+			SIGNAL_DISCARD("breakpoint_toggled")
+			CHECK(code_edit->is_line_breakpointed(9));
+
+			code_edit->select(0, 0, 6, 0);
+			code_edit->insert_text_at_caret("\n\n\n\n\n\n\n\n\n\n\n");
+			MessageQueue::get_singleton()->flush();
+			CHECK(code_edit->is_line_breakpointed(14));
+			SIGNAL_CHECK("breakpoint_toggled", args);
 		}
 
 		SUBCASE("[CodeEdit] breakpoints and undo") {