From 72efc1ec160907f1031ecd184143b1327c0b8f9a Mon Sep 17 00:00:00 2001 From: Francois Belair Date: Tue, 30 Nov 2021 14:41:28 -0500 Subject: [PATCH] Add script formatter, comment parsing in parser, and editor settings * Add verbose messages for debugging purposes * Add disabled lines handling to parser * Force newline at end of code --- core/object/script_language.h | 1 + doc/classes/EditorSettings.xml | 11 +- editor/editor_settings.cpp | 5 + editor/plugins/script_editor_plugin.cpp | 94 +- editor/plugins/script_editor_plugin.h | 2 + editor/plugins/script_text_editor.cpp | 38 + editor/plugins/script_text_editor.h | 2 + editor/plugins/text_editor.cpp | 3 + editor/plugins/text_editor.h | 1 + modules/gdscript/gdscript.h | 1 + modules/gdscript/gdscript_editor.cpp | 7 + modules/gdscript/gdscript_format.cpp | 2181 ++++++++++++ modules/gdscript/gdscript_format.h | 204 ++ modules/gdscript/gdscript_parser.cpp | 508 ++- modules/gdscript/gdscript_parser.h | 22 + modules/gdscript/gdscript_tokenizer.cpp | 59 +- modules/gdscript/gdscript_tokenizer.h | 2 + .../gdscript/tests/test_gdscript_formatter.h | 2943 +++++++++++++++++ 18 files changed, 5990 insertions(+), 94 deletions(-) create mode 100644 modules/gdscript/gdscript_format.cpp create mode 100644 modules/gdscript/gdscript_format.h create mode 100644 modules/gdscript/tests/test_gdscript_formatter.h diff --git a/core/object/script_language.h b/core/object/script_language.h index 12a21150bc64..33dfaed54657 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -370,6 +370,7 @@ class ScriptLanguage : public Object { virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } + virtual String format_code(const String &p_code) { return p_code; } virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const = 0; virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) = 0; virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value) {} diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 6a7bb96e0f6a..0242d46a7033 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -662,7 +662,7 @@ The shape of the caret to use in the script editor. [b]Line[/b] displays a vertical line to the left of the current character, whereas [b]Block[/b] displays a outline over the current character. - The column at which to display a subtle line as a line length guideline for scripts. This should generally be greater than [member text_editor/appearance/guidelines/line_length_guideline_soft_column]. + The column at which to display a subtle line as a line length guideline for scripts. This should generally be greater than [member text_editor/appearance/guidelines/line_length_guideline_soft_column]. This also sets the target line length that the code formatter tries to target. The column at which to display a [i]very[/i] subtle line as a line length guideline for scripts. This should generally be lower than [member text_editor/appearance/guidelines/line_length_guideline_hard_column]. @@ -721,6 +721,15 @@ If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy. + + If [code]true[/code], uses the code formatter before saving a script. + + + The number of indents for the formatter to include when wrapping single line statements into multi-line blocks. + + + The number of extra lines between functions the formatter inserts. + If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line. diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 73acab387633..4fda05f30ca2 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -553,6 +553,11 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/indent/size", 4, "1,64,1") // size of 0 crashes. _initial_set("text_editor/behavior/indent/auto_indent", true); + // Behavior: Formatter + _initial_set("text_editor/behavior/formatter/indent_in_multiline_block", 2); + _initial_set("text_editor/behavior/formatter/lines_between_functions", 2); + _initial_set("text_editor/behavior/formatter/format_on_save", false); + // Behavior: Files _initial_set("text_editor/behavior/files/trim_trailing_whitespace_on_save", false); _initial_set("text_editor/behavior/files/autosave_interval_secs", 0); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index ad114e022f0b..42f552b324e9 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -912,18 +912,23 @@ void ScriptEditor::_resave_scripts(const String &p_str) { continue; //internal script, who cares } - if (trim_trailing_whitespace_on_save) { - se->trim_trailing_whitespace(); - } + if (!format_on_save) { + if (trim_trailing_whitespace_on_save) { + se->trim_trailing_whitespace(); + } - se->insert_final_newline(); + se->insert_final_newline(); - if (convert_indent_on_save) { - if (use_space_indentation) { - se->convert_indent_to_spaces(); - } else { - se->convert_indent_to_tabs(); + if (convert_indent_on_save) { + if (use_space_indentation) { + se->convert_indent_to_spaces(); + } else { + se->convert_indent_to_tabs(); + } } + + } else { + se->format_code(); } Ref text_file = script; @@ -1265,18 +1270,21 @@ void ScriptEditor::_menu_option(int p_option) { save_current_script(); } break; case FILE_SAVE_AS: { - if (trim_trailing_whitespace_on_save) { - current->trim_trailing_whitespace(); - } - - current->insert_final_newline(); + if (!format_on_save) { + if (trim_trailing_whitespace_on_save) { + current->trim_trailing_whitespace(); + } + current->insert_final_newline(); - if (convert_indent_on_save) { - if (use_space_indentation) { - current->convert_indent_to_spaces(); - } else { - current->convert_indent_to_tabs(); + if (convert_indent_on_save) { + if (use_space_indentation) { + current->convert_indent_to_spaces(); + } else { + current->convert_indent_to_tabs(); + } } + } else { + current->format_code(); } Ref resource = current->get_edited_resource(); @@ -2400,18 +2408,22 @@ void ScriptEditor::save_current_script() { return; } - if (trim_trailing_whitespace_on_save) { - current->trim_trailing_whitespace(); - } + if (!format_on_save) { + if (trim_trailing_whitespace_on_save) { + current->trim_trailing_whitespace(); + } - current->insert_final_newline(); + current->insert_final_newline(); - if (convert_indent_on_save) { - if (use_space_indentation) { - current->convert_indent_to_spaces(); - } else { - current->convert_indent_to_tabs(); + if (convert_indent_on_save) { + if (use_space_indentation) { + current->convert_indent_to_spaces(); + } else { + current->convert_indent_to_tabs(); + } } + } else { + current->format_code(); } Ref resource = current->get_edited_resource(); @@ -2465,19 +2477,23 @@ void ScriptEditor::save_all_scripts() { continue; } - if (convert_indent_on_save) { - if (use_space_indentation) { - se->convert_indent_to_spaces(); - } else { - se->convert_indent_to_tabs(); + if (format_on_save) { + if (convert_indent_on_save) { + if (use_space_indentation) { + se->convert_indent_to_spaces(); + } else { + se->convert_indent_to_tabs(); + } } - } - if (trim_trailing_whitespace_on_save) { - se->trim_trailing_whitespace(); - } + if (trim_trailing_whitespace_on_save) { + se->trim_trailing_whitespace(); + } - se->insert_final_newline(); + se->insert_final_newline(); + } else { + se->format_code(); + } if (!se->is_unsaved()) { continue; @@ -2702,6 +2718,7 @@ void ScriptEditor::_editor_settings_changed() { trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save"); convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save"); use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type"); + format_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/formatter/format_on_save"); members_overview_enabled = EditorSettings::get_singleton()->get("text_editor/script_list/show_members_overview"); help_overview_enabled = EditorSettings::get_singleton()->get("text_editor/help/show_help_index"); @@ -3959,6 +3976,7 @@ ScriptEditor::ScriptEditor() { trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save"); convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save"); use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type"); + format_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/formatter/format_on_save"); ScriptServer::edit_request_func = _open_script_request; diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index a8e6cc686863..e6c75e4b69a2 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -150,6 +150,7 @@ class ScriptEditorBase : public VBoxContainer { virtual void set_executing_line(int p_line) = 0; virtual void clear_executing_line() = 0; virtual void trim_trailing_whitespace() = 0; + virtual void format_code() = 0; virtual void insert_final_newline() = 0; virtual void convert_indent_to_spaces() = 0; virtual void convert_indent_to_tabs() = 0; @@ -371,6 +372,7 @@ class ScriptEditor : public PanelContainer { bool open_textfile_after_create = true; bool trim_trailing_whitespace_on_save; + bool format_on_save; bool use_space_indentation; bool convert_indent_on_save; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index fff956a05e52..697df404f846 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -352,6 +352,40 @@ void ScriptTextEditor::trim_trailing_whitespace() { code_editor->trim_trailing_whitespace(); } +void ScriptTextEditor::format_code() { + CodeEdit *tx = code_editor->get_text_editor(); + const String original = tx->get_text(); + Ref