Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resurrect integrated error display for the Debugger. #21884

Merged
merged 1 commit into from
Sep 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 124 additions & 98 deletions editor/script_editor_debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,27 +712,65 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
bool warning = err[9];
bool e;
String time = String("%d:%02d:%02d:%04d").sprintf(vals, &e);
String txt = time + " - " + (err[8].is_zero() ? String(err[7]) : String(err[8]));
String txt = err[8].is_zero() ? String(err[7]) : String(err[8]);

String tooltip = TTR("Type:") + String(warning ? TTR("Warning") : TTR("Error"));
tooltip += "\n" + TTR("Description:") + " " + String(err[8]);
tooltip += "\n" + TTR("Time:") + " " + time;
tooltip += "\nC " + TTR("Error:") + " " + String(err[7]);
tooltip += "\nC " + TTR("Source:") + " " + String(err[5]) + ":" + String(err[6]);
tooltip += "\nC " + TTR("Function:") + " " + String(err[4]);
TreeItem *r = error_tree->get_root();
if (!r) {
r = error_tree->create_item();
}

error_list->add_item(txt, EditorNode::get_singleton()->get_gui_base()->get_icon(warning ? "Warning" : "Error", "EditorIcons"));
error_list->set_item_tooltip(error_list->get_item_count() - 1, tooltip);
TreeItem *error = error_tree->create_item(r);
error->set_collapsed(true);

int scc = p_data[1];
error->set_icon(0, get_icon(warning ? "Warning" : "Error", "EditorIcons"));
error->set_text(0, time);
error->set_text_align(0, TreeItem::ALIGN_LEFT);

error->set_text(1, txt);

String source(err[5]);
bool source_is_project_file = source.begins_with("res://");
if (source_is_project_file)
source = source.get_file();

txt = source + ":" + String(err[6]);
String method = err[4];
if (method.length() > 0)
txt += " @ " + method + "()";

Array stack;
stack.resize(scc);
for (int i = 0; i < scc; i++) {
stack[i] = p_data[2 + i];
TreeItem *c_info = error_tree->create_item(error);
c_info->set_text(0, "<" + TTR(source_is_project_file ? "Source" : "C Source") + ">");
c_info->set_text(1, txt);
c_info->set_text_align(0, TreeItem::ALIGN_LEFT);

if (source_is_project_file) {
Array meta;
meta.push_back(source);
meta.push_back(err[6]);
error->set_metadata(0, meta);
c_info->set_metadata(0, meta);
}

error_list->set_item_metadata(error_list->get_item_count() - 1, stack);
int scc = p_data[1];

for (int i = 0; i < scc; i += 3) {
String script = p_data[2 + i];
String method = p_data[3 + i];
int line = p_data[4 + i];
TreeItem *stack_trace = error_tree->create_item(error);

Array meta;
meta.push_back(script);
meta.push_back(line);
stack_trace->set_metadata(0, meta);

if (i == 0) {
stack_trace->set_text(0, "<" + TTR("Stack Trace") + ">");
stack_trace->set_text_align(0, TreeItem::ALIGN_LEFT);
error->set_metadata(0, meta);
}
stack_trace->set_text(1, script.get_file() + ":" + itos(line) + " @ " + method + "()");
}

if (warning)
warning_count++;
Expand Down Expand Up @@ -970,8 +1008,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
//scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
le_set->connect("pressed", this, "_live_edit_set");
le_clear->connect("pressed", this, "_live_edit_clear");
error_list->connect("item_selected", this, "_error_selected");
error_stack->connect("item_selected", this, "_error_stack_selected");
error_tree->connect("item_selected", this, "_error_selected");
error_tree->connect("item_activated", this, "_error_activated");
vmem_refresh->set_icon(get_icon("Reload", "EditorIcons"));

reason->add_color_override("font_color", get_color("error_color", "Editor"));
Expand Down Expand Up @@ -1017,19 +1055,19 @@ void ScriptEditorDebugger::_notification(int p_what) {
if (error_count != last_error_count || warning_count != last_warning_count) {

if (error_count == 0 && warning_count == 0) {
error_split->set_name(TTR("Errors"));
error_tree->set_name(TTR("Errors"));
debugger_button->set_text(TTR("Debugger"));
debugger_button->set_icon(Ref<Texture>());
tabs->set_tab_icon(error_split->get_index(), Ref<Texture>());
tabs->set_tab_icon(error_tree->get_index(), Ref<Texture>());
} else {
error_split->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")");
error_tree->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")");
debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")");
if (error_count == 0) {
debugger_button->set_icon(get_icon("Warning", "EditorIcons"));
tabs->set_tab_icon(error_split->get_index(), get_icon("Warning", "EditorIcons"));
tabs->set_tab_icon(error_tree->get_index(), get_icon("Warning", "EditorIcons"));
} else {
debugger_button->set_icon(get_icon("Error", "EditorIcons"));
tabs->set_tab_icon(error_split->get_index(), get_icon("Error", "EditorIcons"));
tabs->set_tab_icon(error_tree->get_index(), get_icon("Error", "EditorIcons"));
}
}
last_error_count = error_count;
Expand Down Expand Up @@ -1060,8 +1098,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
inspect_scene_tree->clear();
le_set->set_disabled(true);
le_clear->set_disabled(false);
error_list->clear();
error_stack->clear();
error_tree->clear();
error_count = 0;
warning_count = 0;
profiler_signature.clear();
Expand Down Expand Up @@ -1659,45 +1696,26 @@ void ScriptEditorDebugger::reload_scripts() {
}
}

void ScriptEditorDebugger::_error_selected(int p_idx) {

error_stack->clear();
Array st = error_list->get_item_metadata(p_idx);
for (int i = 0; i < st.size(); i += 3) {

String script = st[i];
String func = st[i + 1];
int line = st[i + 2];
Array md;
md.push_back(st[i]);
md.push_back(st[i + 1]);
md.push_back(st[i + 2]);

String str = func;
String tooltip_str = TTR("Function:") + " " + func;
if (script.length() > 0) {
str += " in " + script.get_file();
tooltip_str = TTR("File:") + " " + script + "\n" + tooltip_str;
if (line > 0) {
str += ":line " + itos(line);
tooltip_str += "\n" + TTR("Line:") + " " + itos(line);
}
}
void ScriptEditorDebugger::_error_activated() {
TreeItem *selected = error_tree->get_selected();

error_stack->add_item(str);
error_stack->set_item_metadata(error_stack->get_item_count() - 1, md);
error_stack->set_item_tooltip(error_stack->get_item_count() - 1, tooltip_str);
TreeItem *ci = selected->get_children();
if (ci) {
selected->set_collapsed(!selected->is_collapsed());
}
}

void ScriptEditorDebugger::_error_stack_selected(int p_idx) {
void ScriptEditorDebugger::_error_selected() {
TreeItem *selected = error_tree->get_selected();

Array arr = error_stack->get_item_metadata(p_idx);
if (arr.size() != 3)
Array meta = selected->get_metadata(0);

if (meta.size() == 0) {
return;
}

Ref<Script> s = ResourceLoader::load(arr[0]);
emit_signal("goto_script_line", s, int(arr[2]) - 1);
Ref<Script> s = ResourceLoader::load(meta[0]);
emit_signal("goto_script_line", s, int(meta[1]) - 1);
}

void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) {
Expand Down Expand Up @@ -1754,27 +1772,24 @@ void ScriptEditorDebugger::_clear_remote_objects() {

void ScriptEditorDebugger::_clear_errors_list() {

error_list->clear();
error_tree->clear();
error_count = 0;
warning_count = 0;
_notification(NOTIFICATION_PROCESS);
}

// Right click on specific file(s) or folder(s).
void ScriptEditorDebugger::_error_list_item_rmb_selected(int p_item, const Vector2 &p_pos) {
void ScriptEditorDebugger::_error_tree_item_rmb_selected(const Vector2 &p_pos) {

item_menu->clear();
item_menu->set_size(Size2(1, 1));

// Allow specific actions only on one item.
bool single_item_selected = error_list->get_selected_items().size() == 1;

if (single_item_selected) {
if (error_tree->is_anything_selected()) {
item_menu->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Error"), ITEM_MENU_COPY_ERROR);
}

if (item_menu->get_item_count() > 0) {
item_menu->set_position(error_list->get_global_position() + p_pos);
item_menu->set_position(error_tree->get_global_position() + p_pos);
item_menu->popup();
}
}
Expand All @@ -1784,10 +1799,30 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
switch (p_option) {

case ITEM_MENU_COPY_ERROR: {
String title = error_list->get_item_text(error_list->get_current());
String desc = error_list->get_item_tooltip(error_list->get_current());
TreeItem *ti = error_tree->get_selected();
while (ti->get_parent() != error_tree->get_root())
ti = ti->get_parent();

String type;

if (ti->get_icon(0) == get_icon("Warning", "EditorIcons")) {
type = "W ";
} else if (ti->get_icon(0) == get_icon("Error", "EditorIcons")) {
type = "E ";
}

String text = ti->get_text(0) + " ";
int rpad_len = text.length();

text = type + text + ti->get_text(1) + "\n";
TreeItem *ci = ti->get_children();
while (ci) {
text += " " + ci->get_text(0).rpad(rpad_len) + ci->get_text(1) + "\n";
ci = ci->get_next();
}

OS::get_singleton()->set_clipboard(text);

OS::get_singleton()->set_clipboard(title + "\n----------\n" + desc);
} break;
case ITEM_MENU_SAVE_REMOTE_NODE: {

Expand Down Expand Up @@ -1826,12 +1861,12 @@ void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("_live_edit_clear"), &ScriptEditorDebugger::_live_edit_clear);

ClassDB::bind_method(D_METHOD("_error_selected"), &ScriptEditorDebugger::_error_selected);
ClassDB::bind_method(D_METHOD("_error_stack_selected"), &ScriptEditorDebugger::_error_stack_selected);
ClassDB::bind_method(D_METHOD("_error_activated"), &ScriptEditorDebugger::_error_activated);
ClassDB::bind_method(D_METHOD("_profiler_activate"), &ScriptEditorDebugger::_profiler_activate);
ClassDB::bind_method(D_METHOD("_profiler_seeked"), &ScriptEditorDebugger::_profiler_seeked);
ClassDB::bind_method(D_METHOD("_clear_errors_list"), &ScriptEditorDebugger::_clear_errors_list);

ClassDB::bind_method(D_METHOD("_error_list_item_rmb_selected"), &ScriptEditorDebugger::_error_list_item_rmb_selected);
ClassDB::bind_method(D_METHOD("_error_tree_item_rmb_selected"), &ScriptEditorDebugger::_error_tree_item_rmb_selected);
ClassDB::bind_method(D_METHOD("_item_menu_id_pressed"), &ScriptEditorDebugger::_item_menu_id_pressed);

ClassDB::bind_method(D_METHOD("_paused"), &ScriptEditorDebugger::_paused);
Expand Down Expand Up @@ -1967,44 +2002,35 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
}

{ //errors

error_split = memnew(HSplitContainer);
VBoxContainer *errvb = memnew(VBoxContainer);
HBoxContainer *errhb = memnew(HBoxContainer);
errvb->set_h_size_flags(SIZE_EXPAND_FILL);
Label *velb = memnew(Label(TTR("Errors:")));
velb->set_h_size_flags(SIZE_EXPAND_FILL);
errhb->add_child(velb);
errhb->set_name(TTR("Errors"));

clearbutton = memnew(Button);
clearbutton->set_text(TTR("Clear"));
clearbutton->connect("pressed", this, "_clear_errors_list");
errhb->add_child(clearbutton);
errvb->add_child(errhb);
error_tree = memnew(Tree);
error_tree->set_columns(2);

error_list = memnew(ItemList);
error_list->set_v_size_flags(SIZE_EXPAND_FILL);
error_list->set_h_size_flags(SIZE_EXPAND_FILL);
error_list->connect("item_rmb_selected", this, "_error_list_item_rmb_selected");
error_list->set_allow_rmb_select(true);
error_list->set_autoscroll_to_bottom(true);
error_tree->set_column_expand(0, false);
error_tree->set_column_min_width(0, 140);

item_menu = memnew(PopupMenu);
item_menu->connect("id_pressed", this, "_item_menu_id_pressed");
error_list->add_child(item_menu);
error_tree->set_column_expand(1, true);

errvb->add_child(error_list);
error_tree->set_select_mode(Tree::SELECT_ROW);
error_tree->set_hide_root(true);
error_tree->set_h_size_flags(SIZE_EXPAND_FILL);
error_tree->set_allow_rmb_select(true);
error_tree->connect("item_rmb_selected", this, "_error_tree_item_rmb_selected");
errhb->add_child(error_tree);

error_split->add_child(errvb);
item_menu = memnew(PopupMenu);
item_menu->connect("id_pressed", this, "_item_menu_id_pressed");
error_tree->add_child(item_menu);

errvb = memnew(VBoxContainer);
errvb->set_h_size_flags(SIZE_EXPAND_FILL);
error_stack = memnew(ItemList);
errvb->add_margin_child(TTR("Stack Trace (if applicable):"), error_stack, true);
error_split->add_child(errvb);
clearbutton = memnew(Button);
clearbutton->set_text(TTR("Clear"));
clearbutton->set_v_size_flags(0);
clearbutton->connect("pressed", this, "_clear_errors_list");
errhb->add_child(clearbutton);

error_split->set_name(TTR("Errors"));
tabs->add_child(error_split);
tabs->add_child(errhb);
}

{ // remote scene tree
Expand Down
9 changes: 4 additions & 5 deletions editor/script_editor_debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ class ScriptEditorDebugger : public Control {
Set<ObjectID> unfold_cache;

HSplitContainer *error_split;
ItemList *error_list;
ItemList *error_stack;
Tree *error_tree;
Tree *inspect_scene_tree;
Button *clearbutton;
PopupMenu *item_menu;
Expand Down Expand Up @@ -179,8 +178,8 @@ class ScriptEditorDebugger : public Control {
void _method_changed(Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
void _property_changed(Object *p_base, const StringName &p_property, const Variant &p_value);

void _error_selected(int p_idx);
void _error_stack_selected(int p_idx);
void _error_activated();
void _error_selected();

void _profiler_activate(bool p_enable);
void _profiler_seeked();
Expand All @@ -191,7 +190,7 @@ class ScriptEditorDebugger : public Control {
void _clear_remote_objects();
void _clear_errors_list();

void _error_list_item_rmb_selected(int p_item, const Vector2 &p_pos);
void _error_tree_item_rmb_selected(const Vector2 &p_pos);
void _item_menu_id_pressed(int p_option);

protected:
Expand Down