diff options
Diffstat (limited to 'modules/gdscript')
36 files changed, 391 insertions, 334 deletions
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 2f507db548..1dc4768186 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -7,7 +7,7 @@ env_gdscript = env_modules.Clone() env_gdscript.add_source_files(env.modules_sources, "*.cpp") -if env["tools"]: +if env.editor_build: env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") SConscript("editor/script_templates/SCsub") diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index a0855b75f4..bc44479f93 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -450,7 +450,7 @@ <param index="1" name="prefix" type="String" default="""" /> <description> Define a new group for the following exported properties. This helps to organize properties in the Inspector dock. Groups can be added with an optional [param prefix], which would make group to only consider properties that have this prefix. The grouping will break on the first property that doesn't have a prefix. The prefix is also removed from the property's name in the Inspector dock. - If no [param prefix] is provided, the every following property is added to the group. The group ends when then next group or category is defined. You can also force end a group by using this annotation with empty strings for paramters, [code]@export_group("", "")[/code]. + If no [param prefix] is provided, the every following property is added to the group. The group ends when then next group or category is defined. You can also force end a group by using this annotation with empty strings for parameters, [code]@export_group("", "")[/code]. Groups cannot be nested, use [annotation @export_subgroup] to add subgroups to your groups. See also [constant PROPERTY_USAGE_GROUP]. [codeblock] @@ -507,7 +507,7 @@ <param index="3" name="extra_hints" type="String" default="""" /> <description> Export a numeric property as a range value. The range must be defined by [param min] and [param max], as well as an optional [param step] and a variety of extra hints. The [param step] defaults to [code]1[/code] for integer properties. For floating-point numbers this value depends on your [code]EditorSettings.interface/inspector/default_float_step[/code] setting. - If hints [code]"or_greater"[/code] and [code]"or_less"[/code] are provided, the editor widget will not cap the value at range boundaries. The [code]"exp"[/code] hint will make the edited values on range to change exponentially. The [code]"no_slider"[/code] hint will hide the slider element of the editor widget. + If hints [code]"or_greater"[/code] and [code]"or_less"[/code] are provided, the editor widget will not cap the value at range boundaries. The [code]"exp"[/code] hint will make the edited values on range to change exponentially. The [code]"hide_slider"[/code] hint will hide the slider element of the editor widget. Hints also allow to indicate the units for the edited value. Using [code]"radians"[/code] you can specify that the actual value is in radians, but should be displayed in degrees in the Inspector dock. [code]"degrees"[/code] allows to add a degree sign as a unit suffix. Finally, a custom suffix can be provided using [code]"suffix:unit"[/code], where "unit" can be any string. See also [constant PROPERTY_HINT_RANGE]. [codeblock] diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index e0deea1106..996d323a7f 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -43,26 +43,28 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l String prev_text = ""; int prev_column = 0; - bool prev_is_char = false; bool prev_is_digit = false; bool prev_is_binary_op = false; + bool in_keyword = false; bool in_word = false; bool in_number = false; - bool in_function_name = false; - bool in_lambda = false; - bool in_variable_declaration = false; - bool in_signal_declaration = false; - bool in_function_args = false; - bool in_member_variable = false; bool in_node_path = false; bool in_node_ref = false; bool in_annotation = false; bool in_string_name = false; bool is_hex_notation = false; bool is_bin_notation = false; + bool in_member_variable = false; + bool in_lambda = false; + + bool in_function_name = false; + bool in_function_args = false; + bool in_variable_declaration = false; + bool in_signal_declaration = false; bool expect_type = false; + Color keyword_color; Color color; @@ -241,16 +243,21 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } } - // A bit of a hack, but couldn't come up with anything better. + // VERY hacky... but couldn't come up with anything better. if (j > 0 && (str[j] == '&' || str[j] == '^' || str[j] == '%' || str[j] == '+' || str[j] == '-' || str[j] == '~' || str[j] == '.')) { - if (prev_text == "true" || prev_text == "false" || prev_text == "self" || prev_text == "null" || prev_text == "PI" || prev_text == "TAU" || prev_text == "INF" || prev_text == "NAN") { - is_binary_op = true; - } else if (!keywords.has(prev_text)) { - int k = j - 1; - while (k > 0 && is_whitespace(str[k])) { - k--; - } - if (!is_symbol(str[k]) || str[k] == '"' || str[k] == '\'' || str[k] == ')' || str[k] == ']' || str[k] == '}') { + int to = j - 1; + // Find what the last text was (prev_text won't work if there's no whitespace, so we need to do it manually). + while (to > 0 && is_whitespace(str[to])) { + to--; + } + int from = to; + while (from > 0 && !is_symbol(str[from])) { + from--; + } + String word = str.substr(from + 1, to - from); + // Keywords need to be exceptions, except for keywords that represent a value. + if (word == "true" || word == "false" || word == "null" || word == "PI" || word == "TAU" || word == "INF" || word == "NAN" || word == "self" || word == "super" || !reserved_keywords.has(word)) { + if (!is_symbol(str[to]) || str[to] == '"' || str[to] == '\'' || str[to] == ')' || str[to] == ']' || str[to] == '}') { is_binary_op = true; } } @@ -285,16 +292,18 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l is_hex_notation = true; } else if (!((str[j] == '-' || str[j] == '+') && str[j - 1] == 'e' && !prev_is_digit) && !(str[j] == '_' && (prev_is_digit || str[j - 1] == 'b' || str[j - 1] == 'x' || str[j - 1] == '.')) && - !((str[j] == 'e' || str[j] == '.') && (prev_is_digit || str[j - 1] == '_')) && + !(str[j] == 'e' && (prev_is_digit || str[j - 1] == '_')) && + !(str[j] == '.' && (prev_is_digit || (!prev_is_binary_op && (j > 0 && (str[j - 1] == '-' || str[j - 1] == '+' || str[j - 1] == '~'))))) && !((str[j] == '-' || str[j] == '+' || str[j] == '~') && !prev_is_binary_op && str[j - 1] != 'e')) { - /* 1st row of condition: '+' or '-' after scientific notation; - 2nd row of condition: '_' as a numeric separator; - 3rd row of condition: Scientific notation 'e' and floating points; - 4th row of condition: Multiple unary operators. */ + /* This condition continues Number highlighting in special cases. + 1st row: '+' or '-' after scientific notation; + 2nd row: '_' as a numeric separator; + 3rd row: Scientific notation 'e' and floating points; + 4th row: Floating points inside the number, or leading if after a unary mathematical operator; + 5th row: Multiple unary mathematical operators */ in_number = false; } - } else if ((str[j] == '-' || str[j] == '+' || str[j] == '~' || (str[j] == '.' && str[j + 1] != '.' && (j == 0 || (j > 0 && str[j - 1] != '.')))) && !is_binary_op) { - // Start a number from unary mathematical operators and floating points, except for '..' + } else if (!is_binary_op && (str[j] == '-' || str[j] == '+' || str[j] == '~' || (str[j] == '.' && str[j + 1] != '.' && (j == 0 || (j > 0 && str[j - 1] != '.'))))) { in_number = true; } @@ -316,7 +325,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l Color col = Color(); if (global_functions.has(word)) { // "assert" and "preload" are reserved, so highlight even if not followed by a bracket. - if (word == "assert" || word == "preload") { + if (word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::ASSERT) || word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::PRELOAD)) { col = global_function_color; } else { // For other global functions, check if followed by bracket. @@ -329,8 +338,10 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l col = global_function_color; } } - } else if (keywords.has(word)) { - col = keywords[word]; + } else if (class_names.has(word)) { + col = class_names[word]; + } else if (reserved_keywords.has(word)) { + col = reserved_keywords[word]; } else if (member_keywords.has(word)) { col = member_keywords[word]; } @@ -406,11 +417,11 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l in_function_args = false; } - if (expect_type && (prev_is_char || str[j] == '=')) { + if (expect_type && (prev_is_char || str[j] == '=') && str[j] != '[') { expect_type = false; } - if (j > 0 && str[j] == '>' && str[j - 1] == '-') { + if (j > 0 && str[j - 1] == '-' && str[j] == '>') { expect_type = true; } @@ -554,7 +565,8 @@ PackedStringArray GDScriptSyntaxHighlighter::_get_supported_languages() const { } void GDScriptSyntaxHighlighter::_update_cache() { - keywords.clear(); + class_names.clear(); + reserved_keywords.clear(); member_keywords.clear(); global_functions.clear(); color_regions.clear(); @@ -571,7 +583,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<StringName> types; ClassDB::get_class_list(&types); for (const StringName &E : types) { - keywords[E] = types_color; + class_names[E] = types_color; } /* User types. */ @@ -579,14 +591,14 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<StringName> global_classes; ScriptServer::get_global_class_list(&global_classes); for (const StringName &E : global_classes) { - keywords[E] = usertype_color; + class_names[E] = usertype_color; } /* Autoloads. */ for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { - keywords[info.name] = usertype_color; + class_names[info.name] = usertype_color; } } @@ -597,7 +609,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<String> core_types; gdscript->get_core_type_words(&core_types); for (const String &E : core_types) { - keywords[StringName(E)] = basetype_color; + class_names[StringName(E)] = basetype_color; } /* Reserved words. */ @@ -607,9 +619,9 @@ void GDScriptSyntaxHighlighter::_update_cache() { gdscript->get_reserved_words(&keyword_list); for (const String &E : keyword_list) { if (gdscript->is_control_flow_keyword(E)) { - keywords[StringName(E)] = control_flow_keyword_color; + reserved_keywords[StringName(E)] = control_flow_keyword_color; } else { - keywords[StringName(E)] = keyword_color; + reserved_keywords[StringName(E)] = keyword_color; } } @@ -644,23 +656,23 @@ void GDScriptSyntaxHighlighter::_update_cache() { add_color_region(beg, end, string_color, end.is_empty()); } - const Ref<Script> script = _get_edited_resource(); - if (script.is_valid()) { + const Ref<Script> scr = _get_edited_resource(); + if (scr.is_valid()) { /* Member types. */ const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); - StringName instance_base = script->get_instance_base_type(); + StringName instance_base = scr->get_instance_base_type(); if (instance_base != StringName()) { List<PropertyInfo> plist; ClassDB::get_property_list(instance_base, &plist); for (const PropertyInfo &E : plist) { - String name = E.name; + String prop_name = E.name; if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) { continue; } - if (name.contains("/")) { + if (prop_name.contains("/")) { continue; } - member_keywords[name] = member_variable_color; + member_keywords[prop_name] = member_variable_color; } List<String> clist; diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 60b5b092d4..7c22eb30b1 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -47,7 +47,8 @@ private: Vector<ColorRegion> color_regions; HashMap<int, int> color_region_cache; - HashMap<StringName, Color> keywords; + HashMap<StringName, Color> class_names; + HashMap<StringName, Color> reserved_keywords; HashMap<StringName, Color> member_keywords; HashSet<StringName> global_functions; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 54cadf7df3..0a9dad04c7 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -111,9 +111,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { if (p_script->initializer) { return p_script->initializer; } else { - GDScript *base = p_script->_base; - if (base != nullptr) { - return _super_constructor(base); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + return _super_constructor(base_src); } else { return nullptr; } @@ -121,9 +121,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { } void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error) { - GDScript *base = p_script->_base; - if (base != nullptr) { - _super_implicit_constructor(base, p_instance, r_error); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + _super_implicit_constructor(base_src, p_instance, r_error); if (r_error.error != Callable::CallError::CALL_OK) { return; } @@ -151,7 +151,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco /* STEP 2, INITIALIZE AND CONSTRUCT */ { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.insert(instance->owner); } @@ -160,7 +160,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -177,7 +177,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -396,9 +396,9 @@ ScriptInstance *GDScript::instance_create(Object *p_this) { if (top->native.is_valid()) { if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'"); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type: '" + p_this->get_class() + "'"); } - ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type '" + p_this->get_class() + "'" + "."); + ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type '" + p_this->get_class() + "'" + "."); } } @@ -418,7 +418,7 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) } bool GDScript::instance_has(const Object *p_this) const { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); return instances.has((Object *)p_this); } @@ -620,11 +620,11 @@ void GDScript::_update_doc() { } if (!is_enum) { DocData::ConstantDoc constant_doc; - String doc_description; + String const_description; if (doc_constants.has(E.key)) { - doc_description = doc_constants[E.key]; + const_description = doc_constants[E.key]; } - DocData::constant_doc_from_variant(constant_doc, E.key, E.value, doc_description); + DocData::constant_doc_from_variant(constant_doc, E.key, E.value, const_description); doc.constants.push_back(constant_doc); } } @@ -675,35 +675,35 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc } if (c->extends_used) { - String path = ""; + String ext_path = ""; if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) { - path = c->extends_path; - if (path.is_relative_path()) { - String base = get_path(); - if (base.is_empty() || base.is_relative_path()) { - ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data()); + ext_path = c->extends_path; + if (ext_path.is_relative_path()) { + String base_path = get_path(); + if (base_path.is_empty() || base_path.is_relative_path()) { + ERR_PRINT(("Could not resolve relative path for parent class: " + ext_path).utf8().get_data()); } else { - path = base.get_base_dir().path_join(path); + ext_path = base_path.get_base_dir().path_join(ext_path); } } } else if (c->extends.size() != 0) { - const StringName &base = c->extends[0]; + const StringName &base_class = c->extends[0]; - if (ScriptServer::is_global_class(base)) { - path = ScriptServer::get_global_class_path(base); + if (ScriptServer::is_global_class(base_class)) { + ext_path = ScriptServer::get_global_class_path(base_class); } } - if (!path.is_empty()) { - if (path != get_path()) { - Ref<GDScript> bf = ResourceLoader::load(path); + if (!ext_path.is_empty()) { + if (ext_path != get_path()) { + Ref<GDScript> bf = ResourceLoader::load(ext_path); if (bf.is_valid()) { base_cache = bf; bf->inheriters_cache.insert(get_instance_id()); } } else { - ERR_PRINT(("Path extending itself in " + path).utf8().get_data()); + ERR_PRINT(("Path extending itself in " + ext_path).utf8().get_data()); } } } @@ -843,7 +843,7 @@ String GDScript::_get_debug_path() const { Error GDScript::reload(bool p_keep_state) { bool has_instances; { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); has_instances = instances.size(); } @@ -1187,7 +1187,7 @@ GDScript::GDScript() : script_list(this) { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.add(&script_list); } @@ -1258,7 +1258,7 @@ void GDScript::_init_rpc_methods_properties() { GDScript::~GDScript() { { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1295,7 +1295,7 @@ GDScript::~GDScript() { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.remove(&script_list); } @@ -1722,7 +1722,7 @@ GDScriptInstance::GDScriptInstance() { } GDScriptInstance::~GDScriptInstance() { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1825,7 +1825,7 @@ void GDScriptLanguage::finish() { void GDScriptLanguage::profiling_start() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1847,7 +1847,7 @@ void GDScriptLanguage::profiling_start() { void GDScriptLanguage::profiling_stop() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); profiling = false; #endif @@ -1857,7 +1857,7 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1880,7 +1880,7 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_ int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1926,7 +1926,7 @@ void GDScriptLanguage::reload_all_scripts() { print_verbose("GDScript: Reloading all scripts"); List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1942,10 +1942,10 @@ void GDScriptLanguage::reload_all_scripts() { scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - print_verbose("GDScript: Reloading: " + script->get_path()); - script->load_source_code(script->get_path()); - script->reload(true); + for (Ref<GDScript> &scr : scripts) { + print_verbose("GDScript: Reloading: " + scr->get_path()); + scr->load_source_code(scr->get_path()); + scr->reload(true); } #endif } @@ -1955,7 +1955,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1974,21 +1974,21 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - bool reload = script == p_script || to_reload.has(script->get_base()); + for (Ref<GDScript> &scr : scripts) { + bool reload = scr == p_script || to_reload.has(scr->get_base()); if (!reload) { continue; } - to_reload.insert(script, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); + to_reload.insert(scr, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); if (!p_soft_reload) { //save state and remove script from instances - HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script]; + HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[scr]; - while (script->instances.front()) { - Object *obj = script->instances.front()->get(); + while (scr->instances.front()) { + Object *obj = scr->instances.front()->get(); //save instance info List<Pair<StringName, Variant>> state; if (obj->get_script_instance()) { @@ -2001,8 +2001,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //same thing for placeholders #ifdef TOOLS_ENABLED - while (script->placeholders.size()) { - Object *obj = (*script->placeholders.begin())->get_owner(); + while (scr->placeholders.size()) { + Object *obj = (*scr->placeholders.begin())->get_owner(); //save instance info if (obj->get_script_instance()) { @@ -2012,13 +2012,13 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so obj->set_script(Variant()); } else { // no instance found. Let's remove it so we don't loop forever - script->placeholders.erase(*script->placeholders.begin()); + scr->placeholders.erase(*scr->placeholders.begin()); } } #endif - for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : script->pending_reload_state) { + for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : scr->pending_reload_state) { map[F.key] = F.value; //pending to reload, use this one instead } } @@ -2043,9 +2043,9 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } obj->set_script(scr); - ScriptInstance *script_instance = obj->get_script_instance(); + ScriptInstance *script_inst = obj->get_script_instance(); - if (!script_instance) { + if (!script_inst) { //failed, save reload state for next time if not saved if (!scr->pending_reload_state.has(obj->get_instance_id())) { scr->pending_reload_state[obj->get_instance_id()] = saved_state; @@ -2053,14 +2053,14 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so continue; } - if (script_instance->is_placeholder() && scr->is_placeholder_fallback_enabled()) { - PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_instance); + if (script_inst->is_placeholder() && scr->is_placeholder_fallback_enabled()) { + PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_inst); for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { placeholder->property_set_fallback(G->get().first, G->get().second); } } else { for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { - script_instance->set(G->get().first, G->get().second); + script_inst->set(G->get().first, G->get().second); } } @@ -2078,7 +2078,7 @@ void GDScriptLanguage::frame() { #ifdef DEBUG_ENABLED if (profiling) { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -2339,26 +2339,26 @@ GDScriptLanguage::~GDScriptLanguage() { // Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit). SelfList<GDScript> *s = script_list.first(); while (s) { - GDScript *script = s->self(); + GDScript *scr = s->self(); // This ensures the current script is not released before we can check what's the next one // in the list (we can't get the next upfront because we don't know if the reference breaking // will cause it -or any other after it, for that matter- to be released so the next one // is not the same as before). - script->reference(); + scr->reference(); - for (KeyValue<StringName, GDScriptFunction *> &E : script->member_functions) { + for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) { GDScriptFunction *func = E.value; for (int i = 0; i < func->argument_types.size(); i++) { func->argument_types.write[i].script_type_ref = Ref<Script>(); } func->return_type.script_type_ref = Ref<Script>(); } - for (KeyValue<StringName, GDScript::MemberInfo> &E : script->member_indices) { + for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) { E.value.data_type.script_type_ref = Ref<Script>(); } s = s->next(); - script->unreference(); + scr->unreference(); } singleton = nullptr; @@ -2390,20 +2390,20 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str } Error err; - Ref<GDScript> script = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE); + Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE); // TODO: Reintroduce binary and encrypted scripts. - if (script.is_null()) { + if (scr.is_null()) { // Don't fail loading because of parsing error. - script.instantiate(); + scr.instantiate(); } if (r_error) { *r_error = OK; } - return script; + return scr; } void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index e4b12d4ddb..0a010e5ad0 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -342,7 +342,7 @@ class GDScriptLanguage : public ScriptLanguage { friend class GDScriptInstance; - Mutex lock; + Mutex mutex; friend class GDScript; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 32d9aec84f..6fbdec863f 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -262,19 +262,19 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, if (p_class->extends_path.is_relative_path()) { p_class->extends_path = class_type.script_path.get_base_dir().path_join(p_class->extends_path).simplify_path(); } - Ref<GDScriptParserRef> parser = get_parser_for(p_class->extends_path); - if (parser.is_null()) { + Ref<GDScriptParserRef> ext_parser = get_parser_for(p_class->extends_path); + if (ext_parser.is_null()) { push_error(vformat(R"(Could not resolve super class path "%s".)", p_class->extends_path), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = ext_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", p_class->extends_path), p_class); return err; } - base = parser->get_parser()->head->get_datatype(); + base = ext_parser->get_parser()->head->get_datatype(); } else { if (p_class->extends.is_empty()) { push_error("Could not resolve an empty super class path.", p_class); @@ -289,18 +289,18 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, if (base_path == parser->script_path) { base = parser->head->get_datatype(); } else { - Ref<GDScriptParserRef> parser = get_parser_for(base_path); - if (parser.is_null()) { + Ref<GDScriptParserRef> base_parser = get_parser_for(base_path); + if (base_parser.is_null()) { push_error(vformat(R"(Could not resolve super class "%s".)", name), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = base_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class); return err; } - base = parser->get_parser()->head->get_datatype(); + base = base_parser->get_parser()->head->get_datatype(); } } else if (ProjectSettings::get_singleton()->has_autoload(name) && ProjectSettings::get_singleton()->get_autoload(name).is_singleton) { const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(name); @@ -309,13 +309,13 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, return ERR_PARSE_ERROR; } - Ref<GDScriptParserRef> parser = get_parser_for(info.path); - if (parser.is_null()) { + Ref<GDScriptParserRef> info_parser = get_parser_for(info.path); + if (info_parser.is_null()) { push_error(vformat(R"(Could not parse singleton from "%s".)", info.path), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = info_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class); return err; @@ -1041,7 +1041,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { } } -void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) { +void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root) { ERR_FAIL_COND_MSG(p_node == nullptr, "Trying to resolve type of a null node."); switch (p_node->type) { @@ -1114,7 +1114,7 @@ void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) { case GDScriptParser::Node::SUBSCRIPT: case GDScriptParser::Node::TERNARY_OPERATOR: case GDScriptParser::Node::UNARY_OPERATOR: - reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), true); + reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), p_is_root); break; case GDScriptParser::Node::BREAK: case GDScriptParser::Node::BREAKPOINT: @@ -1411,7 +1411,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else? p_for->variable->set_datatype(variable_type); } else if (p_for->list) { - resolve_node(p_for->list); + resolve_node(p_for->list, false); if (p_for->list->datatype.has_container_element_type()) { variable_type = p_for->list->datatype.get_container_element_type(); variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; @@ -1439,7 +1439,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } void GDScriptAnalyzer::resolve_while(GDScriptParser::WhileNode *p_while) { - resolve_node(p_while->condition); + resolve_node(p_while->condition, false); resolve_suite(p_while->loop); p_while->set_datatype(p_while->loop->get_datatype()); @@ -1824,7 +1824,7 @@ void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expre reduce_binary_op(static_cast<GDScriptParser::BinaryOpNode *>(p_expression)); break; case GDScriptParser::Node::CALL: - reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), p_is_root); + reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), false, p_is_root); break; case GDScriptParser::Node::CAST: reduce_cast(static_cast<GDScriptParser::CastNode *>(p_expression)); @@ -2548,6 +2548,16 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a mark_lambda_use_self(); } +#ifdef DEBUG_ENABLED + if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) { + parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name); + } + + if (is_static && !base_type.is_meta_type && !(callee_type != GDScriptParser::Node::SUBSCRIPT && parser->current_function != nullptr && parser->current_function->is_static)) { + parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, base_type.to_string()); + } +#endif // DEBUG_ENABLED + call_type = return_type; } else { bool found = false; @@ -3093,11 +3103,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident result.kind = GDScriptParser::DataType::NATIVE; result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; if (autoload.path.to_lower().ends_with(GDScriptLanguage::get_singleton()->get_extension())) { - Ref<GDScriptParserRef> parser = get_parser_for(autoload.path); - if (parser.is_valid()) { - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path); + if (singl_parser.is_valid()) { + Error err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err == OK) { - result = type_from_metatype(parser->get_parser()->head->get_datatype()); + result = type_from_metatype(singl_parser->get_parser()->head->get_datatype()); } } } diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 3966b81b6e..217a856ce0 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -63,7 +63,7 @@ class GDScriptAnalyzer { void resolve_class_body(GDScriptParser::ClassNode *p_class); void resolve_function_signature(GDScriptParser::FunctionNode *p_function); void resolve_function_body(GDScriptParser::FunctionNode *p_function); - void resolve_node(GDScriptParser::Node *p_node); + void resolve_node(GDScriptParser::Node *p_node, bool p_is_root = true); void resolve_suite(GDScriptParser::SuiteNode *p_suite); void resolve_if(GDScriptParser::IfNode *p_if); void resolve_for(GDScriptParser::ForNode *p_for); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index fd418ced47..7acd1cdb96 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -522,11 +522,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code // Create temporary for result first since it will be deleted last. GDScriptCodeGenerator::Address result = codegen.add_temporary(cast_type); - GDScriptCodeGenerator::Address source = _parse_expression(codegen, r_error, cn->operand); + GDScriptCodeGenerator::Address src = _parse_expression(codegen, r_error, cn->operand); - gen->write_cast(result, source, cast_type); + gen->write_cast(result, src, cast_type); - if (source.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + if (src.mode == GDScriptCodeGenerator::Address::TEMPORARY) { gen->pop_temporary(); } @@ -1650,7 +1650,7 @@ void GDScriptCompiler::_add_locals_in_block(CodeGen &codegen, const GDScriptPars } Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals) { - Error error = OK; + Error err = OK; GDScriptCodeGenerator *gen = codegen.generator; codegen.start_block(); @@ -1676,9 +1676,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui // Evaluate the match expression. GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype())); - GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, error, match->test); - if (error) { - return error; + GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test); + if (err) { + return err; } // Assign to local. @@ -1723,9 +1723,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui // For each pattern in branch. GDScriptCodeGenerator::Address pattern_result = codegen.add_temporary(); for (int k = 0; k < branch->patterns.size(); k++) { - pattern_result = _parse_match_pattern(codegen, error, branch->patterns[k], value, type, pattern_result, k == 0, false); - if (error != OK) { - return error; + pattern_result = _parse_match_pattern(codegen, err, branch->patterns[k], value, type, pattern_result, k == 0, false); + if (err != OK) { + return err; } } @@ -1736,9 +1736,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->pop_temporary(); // Parse the branch block. - error = _parse_block(codegen, branch->block, false); // Don't add locals again. - if (error) { - return error; + err = _parse_block(codegen, branch->block, false); // Don't add locals again. + if (err) { + return err; } codegen.end_block(); // Get out of extra block. @@ -1753,9 +1753,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui } break; case GDScriptParser::Node::IF: { const GDScriptParser::IfNode *if_n = static_cast<const GDScriptParser::IfNode *>(s); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, if_n->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, if_n->condition); + if (err) { + return err; } gen->write_if(condition); @@ -1764,17 +1764,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->pop_temporary(); } - error = _parse_block(codegen, if_n->true_block); - if (error) { - return error; + err = _parse_block(codegen, if_n->true_block); + if (err) { + return err; } if (if_n->false_block) { gen->write_else(); - error = _parse_block(codegen, if_n->false_block); - if (error) { - return error; + err = _parse_block(codegen, if_n->false_block); + if (err) { + return err; } } @@ -1788,9 +1788,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype())); - GDScriptCodeGenerator::Address list = _parse_expression(codegen, error, for_n->list); - if (error) { - return error; + GDScriptCodeGenerator::Address list = _parse_expression(codegen, err, for_n->list); + if (err) { + return err; } gen->write_for_assignment(iterator, list); @@ -1801,9 +1801,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->write_for(); - error = _parse_block(codegen, for_n->loop); - if (error) { - return error; + err = _parse_block(codegen, for_n->loop); + if (err) { + return err; } gen->write_endfor(); @@ -1815,9 +1815,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->start_while_condition(); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, while_n->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, while_n->condition); + if (err) { + return err; } gen->write_while(condition); @@ -1826,9 +1826,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->pop_temporary(); } - error = _parse_block(codegen, while_n->loop); - if (error) { - return error; + err = _parse_block(codegen, while_n->loop); + if (err) { + return err; } gen->write_endwhile(); @@ -1850,9 +1850,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui GDScriptCodeGenerator::Address return_value; if (return_n->return_value != nullptr) { - return_value = _parse_expression(codegen, error, return_n->return_value); - if (error) { - return error; + return_value = _parse_expression(codegen, err, return_n->return_value); + if (err) { + return err; } } @@ -1865,17 +1865,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui #ifdef DEBUG_ENABLED const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, as->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, as->condition); + if (err) { + return err; } GDScriptCodeGenerator::Address message; if (as->message) { - message = _parse_expression(codegen, error, as->message); - if (error) { - return error; + message = _parse_expression(codegen, err, as->message); + if (err) { + return err; } } gen->write_assert(condition, message); @@ -1908,9 +1908,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>()); } } - GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, error, lv->initializer); - if (error) { - return error; + GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, err, lv->initializer); + if (err) { + return err; } if (lv->use_conversion_assign) { gen->write_assign_with_conversion(local, src_address); @@ -1946,9 +1946,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui default: { // Expression. if (s->is_expression()) { - GDScriptCodeGenerator::Address expr = _parse_expression(codegen, error, static_cast<const GDScriptParser::ExpressionNode *>(s), true); - if (error) { - return error; + GDScriptCodeGenerator::Address expr = _parse_expression(codegen, err, static_cast<const GDScriptParser::ExpressionNode *>(s), true); + if (err) { + return err; } if (expr.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); @@ -2180,7 +2180,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ } Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter) { - Error error = OK; + Error err = OK; GDScriptParser::FunctionNode *function; @@ -2190,9 +2190,9 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP function = p_variable->getter; } - _parse_function(error, p_script, p_class, function); + _parse_function(err, p_script, p_class, function); - return error; + return err; } Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 4841884e2d..e4264ea55b 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -81,10 +81,10 @@ class GDScriptCompiler { type.kind = GDScriptDataType::NATIVE; type.native_type = obj->get_class_name(); - Ref<Script> script = obj->get_script(); - if (script.is_valid()) { - type.script_type = script.ptr(); - Ref<GDScript> gdscript = script; + Ref<Script> scr = obj->get_script(); + if (scr.is_valid()) { + type.script_type = scr.ptr(); + Ref<GDScript> gdscript = scr; if (gdscript.is_valid()) { type.kind = GDScriptDataType::GDSCRIPT; } else { diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index b38c7c6699..b5a209c805 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -104,10 +104,10 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += ": "; // This makes the compiler complain if some opcode is unchecked in the switch. - Opcode code = Opcode(_code_ptr[ip] & INSTR_MASK); + Opcode opcode = Opcode(_code_ptr[ip] & INSTR_MASK); int instr_var_args = (_code_ptr[ip] & INSTR_ARGS_MASK) >> INSTR_BITS; - switch (code) { + switch (opcode) { case OPCODE_OPERATOR: { int operation = _code_ptr[ip + 4]; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index c00036c9f0..3c68993b36 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -61,8 +61,8 @@ bool GDScriptLanguage::is_using_templates() { } Ref<Script> GDScriptLanguage::make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { - Ref<GDScript> script; - script.instantiate(); + Ref<GDScript> scr; + scr.instantiate(); String processed_template = p_template; bool type_hints = false; #ifdef TOOLS_ENABLED @@ -82,8 +82,8 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri processed_template = processed_template.replace("_BASE_", p_base_class_name) .replace("_CLASS_", p_class_name) .replace("_TS_", _get_indentation()); - script->set_source_code(processed_template); - return script; + scr->set_source_code(processed_template); + return scr; } Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(StringName p_object) { @@ -318,10 +318,10 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> * return; } - Ref<GDScript> script = instance->get_script(); - ERR_FAIL_COND(script.is_null()); + Ref<GDScript> scr = instance->get_script(); + ERR_FAIL_COND(scr.is_null()); - const HashMap<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices(); + const HashMap<StringName, GDScript::MemberInfo> &mi = scr->debug_get_member_indices(); for (const KeyValue<StringName, GDScript::MemberInfo> &E : mi) { p_members->push_back(E.key); @@ -344,7 +344,7 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { const HashMap<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); - const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array(); + const Variant *gl_array = GDScriptLanguage::get_singleton()->get_global_array(); List<Pair<String, Variant>> cinfo; get_public_constants(&cinfo); @@ -365,7 +365,7 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> continue; } - const Variant &var = globals[E.value]; + const Variant &var = gl_array[E.value]; if (Object *obj = var) { if (Object::cast_to<GDScriptNativeClass>(obj)) { continue; @@ -766,7 +766,7 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a ScriptLanguage::CodeCompletionOption slider2("or_less", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider2.insert_text = slider2.display.quote(p_quote_style); r_result.insert(slider2.display, slider2); - ScriptLanguage::CodeCompletionOption slider3("no_slider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption slider3("hide_slider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider3.insert_text = slider3.display.quote(p_quote_style); r_result.insert(slider3.display, slider3); } @@ -1205,8 +1205,8 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context _find_built_in_variants(r_result); static const char *_keywords[] = { - "false", "PI", "TAU", "INF", "NAN", "self", "true", "breakpoint", "tool", "super", - "break", "continue", "pass", "return", + "true", "false", "PI", "TAU", "INF", "NAN", "null", "self", "super", + "break", "breakpoint", "continue", "pass", "return", nullptr }; @@ -1218,7 +1218,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context } static const char *_keywords_with_space[] = { - "and", "in", "not", "or", "as", "class", "extends", "is", "func", "signal", "await", + "and", "not", "or", "in", "as", "class", "class_name", "extends", "is", "func", "signal", "await", "const", "enum", "static", "var", "if", "elif", "else", "for", "match", "while", nullptr }; @@ -3302,17 +3302,17 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) { const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(p_symbol); if (autoload.is_singleton) { - String script = autoload.path; - if (!script.ends_with(".gd")) { + String scr_path = autoload.path; + if (!scr_path.ends_with(".gd")) { // Not a script, try find the script anyway, // may have some success. - script = script.get_basename() + ".gd"; + scr_path = scr_path.get_basename() + ".gd"; } - if (FileAccess::exists(script)) { + if (FileAccess::exists(scr_path)) { r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION; r_result.location = 0; - r_result.script = ResourceLoader::load(script); + r_result.script = ResourceLoader::load(scr_path); return OK; } } diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index cd3b7d69c5..98b3e40f1b 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -142,7 +142,7 @@ GDScriptFunction::GDScriptFunction() { name = "<anonymous>"; #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->function_list.add(&function_list); } #endif @@ -155,7 +155,7 @@ GDScriptFunction::~GDScriptFunction() { #ifdef DEBUG_ENABLED - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->function_list.remove(&function_list); #endif @@ -201,7 +201,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { } if (p_extended_check) { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); // Script gone? if (!scripts_list.in_list()) { @@ -219,7 +219,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { Variant GDScriptFunctionState::resume(const Variant &p_arg) { ERR_FAIL_COND_V(!function, Variant()); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); if (!scripts_list.in_list()) { #ifdef DEBUG_ENABLED @@ -304,7 +304,7 @@ GDScriptFunctionState::GDScriptFunctionState() : GDScriptFunctionState::~GDScriptFunctionState() { { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); scripts_list.remove_from_list(); instances_list.remove_from_list(); } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index b4da94e448..bdf6fb35b6 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2932,11 +2932,16 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre // Allow for trailing comma. break; } + bool use_identifier_completion = current.cursor_place == GDScriptTokenizer::CURSOR_END || current.cursor_place == GDScriptTokenizer::CURSOR_MIDDLE; ExpressionNode *argument = parse_expression(false); if (argument == nullptr) { push_error(R"(Expected expression as the function argument.)"); } else { call->arguments.push_back(argument); + + if (argument->type == Node::IDENTIFIER && use_identifier_completion) { + completion_context.type = COMPLETION_IDENTIFIER; + } } ct = COMPLETION_CALL_ARGUMENTS; } while (match(GDScriptTokenizer::Token::COMMA)); @@ -3948,28 +3953,22 @@ GDScriptParser::DataType GDScriptParser::SuiteNode::Local::get_datatype() const } String GDScriptParser::SuiteNode::Local::get_name() const { - String name; switch (type) { case SuiteNode::Local::PARAMETER: - name = "parameter"; - break; + return "parameter"; case SuiteNode::Local::CONSTANT: - name = "constant"; - break; + return "constant"; case SuiteNode::Local::VARIABLE: - name = "variable"; - break; + return "variable"; case SuiteNode::Local::FOR_VARIABLE: - name = "for loop iterator"; - break; + return "for loop iterator"; case SuiteNode::Local::PATTERN_BIND: - name = "pattern_bind"; - break; + return "pattern_bind"; case SuiteNode::Local::UNDEFINED: - name = "<undefined>"; - break; + return "<undefined>"; + default: + return String(); } - return name; } String GDScriptParser::DataType::to_string() const { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index d4efab173b..1850a44678 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -578,19 +578,19 @@ public: return m_enum->get_datatype(); case ENUM_VALUE: { // Always integer. - DataType type; - type.type_source = DataType::ANNOTATED_EXPLICIT; - type.kind = DataType::BUILTIN; - type.builtin_type = Variant::INT; - return type; + DataType out_type; + out_type.type_source = DataType::ANNOTATED_EXPLICIT; + out_type.kind = DataType::BUILTIN; + out_type.builtin_type = Variant::INT; + return out_type; } case SIGNAL: { - DataType type; - type.type_source = DataType::ANNOTATED_EXPLICIT; - type.kind = DataType::BUILTIN; - type.builtin_type = Variant::SIGNAL; + DataType out_type; + out_type.type_source = DataType::ANNOTATED_EXPLICIT; + out_type.kind = DataType::BUILTIN; + out_type.builtin_type = Variant::SIGNAL; // TODO: Add parameter info. - return type; + return out_type; } case GROUP: { return DataType(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 6c17afe939..9bbfd7aece 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -516,15 +516,15 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { _advance(); } - int length = _current - _start; + int len = _current - _start; - if (length == 1 && _peek(-1) == '_') { + if (len == 1 && _peek(-1) == '_') { // Lone underscore. return make_token(Token::UNDERSCORE); } - String name(_start, length); - if (length < MIN_KEYWORD_LENGTH || length > MAX_KEYWORD_LENGTH) { + String name(_start, len); + if (len < MIN_KEYWORD_LENGTH || len > MAX_KEYWORD_LENGTH) { // Cannot be a keyword, as the length doesn't match any. return make_identifier(name); } @@ -538,7 +538,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { const int keyword_length = sizeof(keyword) - 1; \ static_assert(keyword_length <= MAX_KEYWORD_LENGTH, "There's a keyword longer than the defined maximum length"); \ static_assert(keyword_length >= MIN_KEYWORD_LENGTH, "There's a keyword shorter than the defined minimum length"); \ - if (keyword_length == length && name == keyword) { \ + if (keyword_length == len && name == keyword) { \ return make_token(token_type); \ } \ } @@ -551,13 +551,13 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { } // Check if it's a special literal - if (length == 4) { + if (len == 4) { if (name == "true") { return make_literal(true); } else if (name == "null") { return make_literal(Variant()); } - } else if (length == 5) { + } else if (len == 5) { if (name == "false") { return make_literal(false); } @@ -725,8 +725,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() { } // Create a string with the whole number. - int length = _current - _start; - String number = String(_start, length).replace("_", ""); + int len = _current - _start; + String number = String(_start, len).replace("_", ""); // Convert to the appropriate literal type. if (base == 16) { diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index afebe3c149..c73ba798aa 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -2216,7 +2216,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a gdfs->state.line = line; gdfs->state.script = _script; { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); _script->pending_func_states.add(&gdfs->scripts_list); if (p_instance) { gdfs->state.instance = p_instance; diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 1cae7bdfac..a0c107aa53 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -155,6 +155,10 @@ String GDScriptWarning::get_message() const { case INT_ASSIGNED_TO_ENUM: { return "Integer used when an enum value is expected. If this is intended cast the integer to the enum type."; } + case STATIC_CALLED_ON_INSTANCE: { + CHECK_SYMBOLS(2); + return vformat(R"(The function '%s()' is a static function but was called from an instance. Instead, it should be directly called from the type: '%s.%s()'.)", symbols[0], symbols[1], symbols[0]); + } case WARNING_MAX: break; // Can't happen, but silences warning } @@ -215,6 +219,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "EMPTY_FILE", "SHADOWED_GLOBAL_IDENTIFIER", "INT_ASSIGNED_TO_ENUM", + "STATIC_CALLED_ON_INSTANCE", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index a639e7b44e..7e4e975510 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -78,6 +78,7 @@ public: EMPTY_FILE, // A script file is empty. SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable. INT_ASSIGNED_TO_ENUM, // An integer value was assigned to an enum-typed variable without casting. + STATIC_CALLED_ON_INSTANCE, // A static method was called on an instance of a class instead of on the class itself. WARNING_MAX, }; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 46a9b33eb0..de3becbaf8 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -38,8 +38,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.clear(); - const List<ParserError> &errors = get_errors(); - for (const ParserError &error : errors) { + const List<ParserError> &parser_errors = get_errors(); + for (const ParserError &error : parser_errors) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Error; diagnostic.message = error.message; @@ -47,9 +47,9 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostic.code = -1; lsp::Range range; lsp::Position pos; - const PackedStringArray lines = get_lines(); - int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, lines.size() - 1); - const String &line_text = lines[line]; + const PackedStringArray line_array = get_lines(); + int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, line_array.size() - 1); + const String &line_text = line_array[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); range.start = pos; @@ -59,8 +59,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.push_back(diagnostic); } - const List<GDScriptWarning> &warnings = get_warnings(); - for (const GDScriptWarning &warning : warnings) { + const List<GDScriptWarning> &parser_warnings = get_warnings(); + for (const GDScriptWarning &warning : parser_warnings) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Warning; diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message(); @@ -83,8 +83,7 @@ void ExtendGDScriptParser::update_diagnostics() { void ExtendGDScriptParser::update_symbols() { members.clear(); - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { parse_class_symbol(gdclass, class_symbol); for (int i = 0; i < class_symbol.children.size(); i++) { @@ -107,26 +106,26 @@ void ExtendGDScriptParser::update_symbols() { void ExtendGDScriptParser::update_document_links(const String &p_code) { document_links.clear(); - GDScriptTokenizer tokenizer; + GDScriptTokenizer scr_tokenizer; Ref<FileAccess> fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); - tokenizer.set_source_code(p_code); + scr_tokenizer.set_source_code(p_code); while (true) { - GDScriptTokenizer::Token token = tokenizer.scan(); + GDScriptTokenizer::Token token = scr_tokenizer.scan(); if (token.type == GDScriptTokenizer::Token::TK_EOF) { break; } else if (token.type == GDScriptTokenizer::Token::LITERAL) { const Variant &const_val = token.literal; if (const_val.get_type() == Variant::STRING) { - String path = const_val; - bool exists = fs->file_exists(path); + String scr_path = const_val; + bool exists = fs->file_exists(scr_path); if (!exists) { - path = get_path().get_base_dir() + "/" + path; - exists = fs->file_exists(path); + scr_path = get_path().get_base_dir() + "/" + scr_path; + exists = fs->file_exists(scr_path); } if (exists) { String value = const_val; lsp::DocumentLink link; - link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path); + link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(scr_path); link.range.start.line = LINE_NUMBER_TO_INDEX(token.start_line); link.range.end.line = LINE_NUMBER_TO_INDEX(token.end_line); link.range.start.character = LINE_NUMBER_TO_INDEX(token.start_column); @@ -437,11 +436,11 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { if (!p_docs_down) { // inline comment String inline_comment = lines[p_line]; - int comment_start = inline_comment.find("#"); + int comment_start = inline_comment.find("##"); if (comment_start != -1) { inline_comment = inline_comment.substr(comment_start, inline_comment.length()).strip_edges(); if (inline_comment.length() > 1) { - doc_lines.push_back(inline_comment.substr(1, inline_comment.length())); + doc_lines.push_back(inline_comment.substr(2, inline_comment.length())); } } } @@ -454,8 +453,8 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { } String line_comment = lines[i].strip_edges(true, false); - if (line_comment.begins_with("#")) { - line_comment = line_comment.substr(1, line_comment.length()); + if (line_comment.begins_with("##")) { + line_comment = line_comment.substr(2, line_comment.length()); if (p_docs_down) { doc_lines.push_back(line_comment); } else { @@ -731,7 +730,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Array nested_classes; Array constants; - Array members; + Array class_members; Array signals; Array methods; Array static_functions; @@ -792,7 +791,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode api["signature"] = symbol->detail; api["description"] = symbol->documentation; } - members.push_back(api); + class_members.push_back(api); } break; case ClassNode::Member::SIGNAL: { Dictionary api; @@ -824,7 +823,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode class_api["sub_classes"] = nested_classes; class_api["constants"] = constants; - class_api["members"] = members; + class_api["members"] = class_members; class_api["signals"] = signals; class_api["methods"] = methods; class_api["static_functions"] = static_functions; @@ -834,8 +833,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Dictionary ExtendGDScriptParser::generate_api() const { Dictionary api; - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { api = dump_class_api(gdclass); } return api; diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index ead4ef1987..38bea314a0 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -61,12 +61,12 @@ void GDScriptLanguageServer::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - String host = String(_EDITOR_GET("network/language_server/remote_host")); - int port = (int)_EDITOR_GET("network/language_server/remote_port"); - bool use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); - if (host != this->host || port != this->port || use_thread != this->use_thread) { - this->stop(); - this->start(); + String remote_host = String(_EDITOR_GET("network/language_server/remote_host")); + int remote_port = (int)_EDITOR_GET("network/language_server/remote_port"); + bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); + if (remote_host != host || remote_port != port || remote_use_thread != use_thread) { + stop(); + start(); } } break; } diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index ccde0521f2..3905e28bcb 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -42,6 +42,7 @@ void GDScriptTextDocument::_bind_methods() { ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen); ClassDB::bind_method(D_METHOD("didClose"), &GDScriptTextDocument::didClose); ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange); + ClassDB::bind_method(D_METHOD("willSaveWaitUntil"), &GDScriptTextDocument::willSaveWaitUntil); ClassDB::bind_method(D_METHOD("didSave"), &GDScriptTextDocument::didSave); ClassDB::bind_method(D_METHOD("nativeSymbol"), &GDScriptTextDocument::nativeSymbol); ClassDB::bind_method(D_METHOD("documentSymbol"), &GDScriptTextDocument::documentSymbol); @@ -81,6 +82,16 @@ void GDScriptTextDocument::didChange(const Variant &p_param) { sync_script_content(doc.uri, doc.text); } +void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) { + lsp::TextDocumentItem doc = load_document_item(p_param); + + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<Script> scr = ResourceLoader::load(path); + if (scr.is_valid()) { + ScriptEditor::get_singleton()->clear_docs_from_script(scr); + } +} + void GDScriptTextDocument::didSave(const Variant &p_param) { lsp::TextDocumentItem doc = load_document_item(p_param); Dictionary dict = p_param; @@ -88,11 +99,16 @@ void GDScriptTextDocument::didSave(const Variant &p_param) { sync_script_content(doc.uri, text); - /*String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); - - Ref<GDScript> script = ResourceLoader::load(path); - script->load_source_code(path); - script->reload(true);*/ + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<GDScript> scr = ResourceLoader::load(path); + if (scr.is_valid() && (scr->load_source_code(path) == OK)) { + if (scr->is_tool()) { + scr->get_language()->reload_tool_script(scr, true); + } else { + scr->reload(true); + } + ScriptEditor::get_singleton()->update_docs_from_script(scr); + } } lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) { @@ -213,8 +229,8 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { arr = native_member_completions.duplicate(); for (KeyValue<String, ExtendGDScriptParser *> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts) { - ExtendGDScriptParser *script = E.value; - const Array &items = script->get_member_completions(); + ExtendGDScriptParser *scr = E.value; + const Array &items = scr->get_member_completions(); const int start_size = arr.size(); arr.resize(start_size + items.size()); @@ -417,14 +433,6 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content); EditorFileSystem::get_singleton()->update_file(path); - Error error; - Ref<GDScript> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error); - if (error == OK) { - if (script->load_source_code(path) == OK) { - script->reload(true); - ScriptEditor::get_singleton()->reload_scripts(true); // Refresh scripts opened in the internal editor. - } - } } void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 87bc08a34e..456c7d71fe 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -45,6 +45,7 @@ protected: void didOpen(const Variant &p_param); void didClose(const Variant &p_param); void didChange(const Variant &p_param); + void willSaveWaitUntil(const Variant &p_param); void didSave(const Variant &p_param); void sync_script_content(const String &p_path, const String &p_content); diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 16461b0a6c..390460bed9 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -55,14 +55,14 @@ void GDScriptWorkspace::_bind_methods() { } void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStringArray args) { - Ref<Script> script = obj->get_script(); + Ref<Script> scr = obj->get_script(); - if (script->get_language()->get_name() != "GDScript") { + if (scr->get_language()->get_name() != "GDScript") { return; } String function_signature = "func " + function; - String source = script->get_source_code(); + String source = scr->get_source_code(); if (source.contains(function_signature)) { return; @@ -98,7 +98,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr text_edit.newText = function_body; - String uri = get_file_uri(script->get_path()); + String uri = get_file_uri(scr->get_path()); lsp::ApplyWorkspaceEditParams params; params.edit.add_edit(uri, text_edit); @@ -118,12 +118,12 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { void GDScriptWorkspace::remove_cache_parser(const String &p_path) { HashMap<String, ExtendGDScriptParser *>::Iterator parser = parse_results.find(p_path); - HashMap<String, ExtendGDScriptParser *>::Iterator script = scripts.find(p_path); - if (parser && script) { - if (script->value && script->value == parser->value) { - memdelete(script->value); + HashMap<String, ExtendGDScriptParser *>::Iterator scr = scripts.find(p_path); + if (parser && scr) { + if (scr->value && scr->value == parser->value) { + memdelete(scr->value); } else { - memdelete(script->value); + memdelete(scr->value); memdelete(parser->value); } parse_results.erase(p_path); @@ -131,8 +131,8 @@ void GDScriptWorkspace::remove_cache_parser(const String &p_path) { } else if (parser) { memdelete(parser->value); parse_results.erase(p_path); - } else if (script) { - memdelete(script->value); + } else if (scr) { + memdelete(scr->value); scripts.erase(p_path); } } @@ -587,8 +587,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S while (!stack.is_empty()) { current = Object::cast_to<Node>(stack.pop_back()); - Ref<GDScript> script = current->get_script(); - if (script.is_valid() && script->get_path() == path) { + Ref<GDScript> scr = current->get_script(); + if (scr.is_valid() && scr->get_path() == path) { break; } for (int i = 0; i < current->get_child_count(); ++i) { @@ -596,8 +596,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S } } - Ref<GDScript> script = current->get_script(); - if (!script.is_valid() || script->get_path() != path) { + Ref<GDScript> scr = current->get_script(); + if (!scr.is_valid() || scr->get_path() != path) { current = owner_scene_node; } } @@ -691,13 +691,13 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP } for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) { - const ExtendGDScriptParser *script = E.value; - const ClassMembers &members = script->get_members(); + const ExtendGDScriptParser *scr = E.value; + const ClassMembers &members = scr->get_members(); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { r_list.push_back(*symbol); } - for (const KeyValue<String, ClassMembers> &F : script->get_inner_classes()) { + for (const KeyValue<String, ClassMembers> &F : scr->get_inner_classes()) { const ClassMembers *inner_class = &F.value; if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) { r_list.push_back(*symbol); diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h index fbd40796c4..024da1cab7 100644 --- a/modules/gdscript/language_server/godot_lsp.h +++ b/modules/gdscript/language_server/godot_lsp.h @@ -546,7 +546,7 @@ struct TextDocumentSyncOptions { * If present will save wait until requests are sent to the server. If omitted the request should not be * sent. */ - bool willSaveWaitUntil = false; + bool willSaveWaitUntil = true; /** * If present save notifications are sent to the server. If omitted the notification should not be diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 6c346acb7e..15131afde7 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -479,9 +479,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (const GDScriptParser::ParserError &E : errors) { - result.output += E.message + "\n"; // TODO: line, column? - break; // Only the first error since the following might be cascading. + if (!errors.is_empty()) { + // Only the first error since the following might be cascading. + result.output += errors[0].message + "\n"; // TODO: line, column? } if (!p_is_generating) { result.passed = check_output(result.output); @@ -498,9 +498,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (const GDScriptParser::ParserError &E : errors) { - result.output += E.message + "\n"; // TODO: line, column? - break; // Only the first error since the following might be cascading. + if (!errors.is_empty()) { + // Only the first error since the following might be cascading. + result.output += errors[0].message + "\n"; // TODO: line, column? } if (!p_is_generating) { result.passed = check_output(result.output); diff --git a/modules/gdscript/tests/scripts/parser/features/class.gd b/modules/gdscript/tests/scripts/parser/features/class.gd index 6652f85ad9..af24b32322 100644 --- a/modules/gdscript/tests/scripts/parser/features/class.gd +++ b/modules/gdscript/tests/scripts/parser/features/class.gd @@ -21,5 +21,5 @@ func test(): assert(test_sub.number == 25) # From Test. assert(test_sub.other_string == "bye") # From TestSub. - TestConstructor.new() - TestConstructor.new(500) + var _test_constructor = TestConstructor.new() + _test_constructor = TestConstructor.new(500) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary.out b/modules/gdscript/tests/scripts/parser/features/dictionary.out index 5f999f573a..e1eeb46f78 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary.out @@ -7,8 +7,8 @@ null false empty array zero Vector2i -{22:{4:["nesting", "arrays"]}} -{4:["nesting", "arrays"]} +{ 22: { 4: ["nesting", "arrays"] } } +{ 4: ["nesting", "arrays"] } ["nesting", "arrays"] nesting arrays diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out index 5143d040a9..553d40d953 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out @@ -1,2 +1,2 @@ GDTEST_OK -{"a":1, "b":2, "with spaces":3, "2":4} +{ "a": 1, "b": 2, "with spaces": 3, "2": 4 } diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out index dd28609850..cf79845f53 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out @@ -1,2 +1,2 @@ GDTEST_OK -{"hello":{"world":{"is":"beautiful"}}} +{ "hello": { "world": { "is": "beautiful" } } } diff --git a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out index 8b8c33202f..508f0ff217 100644 --- a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out +++ b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out @@ -1,5 +1,5 @@ GDTEST_OK -{8:{"key":"value"}} -{"key":"value"} +{ 8: { "key": "value" } } +{ "key": "value" } value value diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out index d73c5eb7cd..13f759dd46 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out +++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out @@ -1 +1,5 @@ GDTEST_OK +>> WARNING +>> Line: 6 +>> RETURN_VALUE_DISCARDED +>> The function 'i_return_int()' returns a value, but this value is never used. diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd new file mode 100644 index 0000000000..29d8501b78 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd @@ -0,0 +1,11 @@ +class Player: + var x = 3 + +func test(): + # These should not emit a warning. + var _player = Player.new() + print(String.num_uint64(8589934592)) # 2 ^ 33 + + # This should emit a warning. + var some_string = String() + print(some_string.num_uint64(8589934592)) # 2 ^ 33 diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out new file mode 100644 index 0000000000..3933a35178 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out @@ -0,0 +1,7 @@ +GDTEST_OK +>> WARNING +>> Line: 11 +>> STATIC_CALLED_ON_INSTANCE +>> The function 'num_uint64()' is a static function but was called from an instance. Instead, it should be directly called from the type: 'String.num_uint64()'. +8589934592 +8589934592 diff --git a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out index 5e7ccf534a..22929bf636 100644 --- a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out +++ b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out @@ -1,6 +1,6 @@ GDTEST_OK -{1:(2, 0)} -{3:(4, 0)} +{ 1: (2, 0) } +{ 3: (4, 0) } [[(5, 0)]] [[(6, 0)]] [[(7, 0)]] diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.out b/modules/gdscript/tests/scripts/runtime/features/stringify.out index d4468737a5..1f33de00cc 100644 --- a/modules/gdscript/tests/scripts/runtime/features/stringify.out +++ b/modules/gdscript/tests/scripts/runtime/features/stringify.out @@ -21,7 +21,7 @@ hello/world RID(0) Node::get_name Node::[signal]property_list_changed -{"hello":123} +{ "hello": 123 } ["hello", 123] [255, 0, 1] [-1, 0, 1] |