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

GDScript: Show script errors from depended scripts #75216

Merged
merged 1 commit into from Jul 24, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions core/object/script_language.h
Expand Up @@ -263,6 +263,7 @@ class ScriptLanguage : public Object {
};

struct ScriptError {
String path;
int line = -1;
int column = -1;
String message;
Expand Down
63 changes: 63 additions & 0 deletions editor/plugins/script_text_editor.cpp
Expand Up @@ -282,6 +282,22 @@ void ScriptTextEditor::_error_clicked(Variant p_line) {
if (p_line.get_type() == Variant::INT) {
code_editor->get_text_editor()->remove_secondary_carets();
code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
} else if (p_line.get_type() == Variant::DICTIONARY) {
Dictionary meta = p_line.operator Dictionary();
const String path = meta["path"].operator String();
const int line = meta["line"].operator int64_t();
const int column = meta["column"].operator int64_t();
if (path.is_empty()) {
code_editor->get_text_editor()->remove_secondary_carets();
code_editor->get_text_editor()->set_caret_line(line);
} else {
Ref<Resource> scr = ResourceLoader::load(path);
if (!scr.is_valid()) {
EditorNode::get_singleton()->show_warning(TTR("Could not load file at:") + "\n\n" + path, TTR("Error!"));
} else {
ScriptEditor::get_singleton()->edit(scr, line, column);
}
}
}
}

Expand Down Expand Up @@ -458,9 +474,17 @@ void ScriptTextEditor::_validate_script() {

warnings.clear();
errors.clear();
depended_errors.clear();
safe_lines.clear();

if (!script->get_language()->validate(text, script->get_path(), &fnc, &errors, &warnings, &safe_lines)) {
for (List<ScriptLanguage::ScriptError>::Element *E = errors.front(); E; E = E->next()) {
if (E->get().path.is_empty() || E->get().path != script->get_path()) {
depended_errors[E->get().path].push_back(E->get());
E->erase();
}
}

// TRANSLATORS: Script error pointing to a line and column number.
String error_text = vformat(TTR("Error at (%d, %d):"), errors[0].line, errors[0].column) + " " + errors[0].message;
code_editor->set_error(error_text);
Expand Down Expand Up @@ -560,6 +584,10 @@ void ScriptTextEditor::_update_errors() {
errors_panel->clear();
errors_panel->push_table(2);
for (const ScriptLanguage::ScriptError &err : errors) {
Dictionary click_meta;
click_meta["line"] = err.line;
click_meta["column"] = err.column;

errors_panel->push_cell();
errors_panel->push_meta(err.line - 1);
errors_panel->push_color(warnings_panel->get_theme_color(SNAME("error_color"), SNAME("Editor")));
Expand All @@ -575,6 +603,41 @@ void ScriptTextEditor::_update_errors() {
}
errors_panel->pop(); // Table

for (const KeyValue<String, List<ScriptLanguage::ScriptError>> &KV : depended_errors) {
Dictionary click_meta;
click_meta["path"] = KV.key;
click_meta["line"] = 1;

errors_panel->add_newline();
errors_panel->add_newline();
errors_panel->push_meta(click_meta);
errors_panel->add_text(vformat(R"(%s:)", KV.key));
errors_panel->pop(); // Meta goto.
errors_panel->add_newline();

errors_panel->push_indent(1);
errors_panel->push_table(2);
String filename = KV.key.get_file();
for (const ScriptLanguage::ScriptError &err : KV.value) {
click_meta["line"] = err.line;
click_meta["column"] = err.column;

errors_panel->push_cell();
errors_panel->push_meta(click_meta);
errors_panel->push_color(errors_panel->get_theme_color(SNAME("error_color"), SNAME("Editor")));
errors_panel->add_text(TTR("Line") + " " + itos(err.line) + ":");
errors_panel->pop(); // Color.
errors_panel->pop(); // Meta goto.
errors_panel->pop(); // Cell.

errors_panel->push_cell();
errors_panel->add_text(err.message);
errors_panel->pop(); // Cell.
}
errors_panel->pop(); // Table
errors_panel->pop(); // Indent.
}

CodeEdit *te = code_editor->get_text_editor();
bool highlight_safe = EDITOR_GET("text_editor/appearance/gutters/highlight_type_safe_lines");
bool last_is_safe = false;
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/script_text_editor.h
Expand Up @@ -68,6 +68,7 @@ class ScriptTextEditor : public ScriptEditorBase {
Vector<String> functions;
List<ScriptLanguage::Warning> warnings;
List<ScriptLanguage::ScriptError> errors;
HashMap<String, List<ScriptLanguage::ScriptError>> depended_errors;
HashSet<int> safe_lines;

List<Connection> missing_connections;
Expand Down
4 changes: 4 additions & 0 deletions modules/gdscript/gdscript_analyzer.cpp
Expand Up @@ -4517,6 +4517,10 @@ Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNo
return result;
}

const HashMap<String, Ref<GDScriptParserRef>> &GDScriptAnalyzer::get_depended_parsers() {
return depended_parsers;
}

GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
GDScriptParser::DataType result;
result.is_constant = true;
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript_analyzer.h
Expand Up @@ -144,6 +144,7 @@ class GDScriptAnalyzer {
Error analyze();

Variant make_variable_default_value(GDScriptParser::VariableNode *p_variable);
const HashMap<String, Ref<GDScriptParserRef>> &get_depended_parsers();

GDScriptAnalyzer(GDScriptParser *p_parser);
};
Expand Down
16 changes: 14 additions & 2 deletions modules/gdscript/gdscript_editor.cpp
Expand Up @@ -143,14 +143,26 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li
#endif
if (err) {
if (r_errors) {
for (const GDScriptParser::ParserError &E : parser.get_errors()) {
const GDScriptParser::ParserError &pe = E;
for (const GDScriptParser::ParserError &pe : parser.get_errors()) {
ScriptLanguage::ScriptError e;
e.path = p_path;
e.line = pe.line;
e.column = pe.column;
e.message = pe.message;
r_errors->push_back(e);
}

for (KeyValue<String, Ref<GDScriptParserRef>> E : analyzer.get_depended_parsers()) {
GDScriptParser *depended_parser = E.value->get_parser();
for (const GDScriptParser::ParserError &pe : depended_parser->get_errors()) {
ScriptLanguage::ScriptError e;
e.path = E.key;
e.line = pe.line;
e.column = pe.column;
e.message = pe.message;
r_errors->push_back(e);
}
}
}
return false;
} else {
Expand Down