diff options
Diffstat (limited to 'modules/gdscript')
9 files changed, 49 insertions, 35 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 9c8adb4cf1..33f4198ac1 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -4,10 +4,10 @@ Built-in GDScript functions. </brief_description> <description> - List of core built-in GDScript functions. Math functions and other utilities. Everything else is provided by objects. (Keywords: builtin, built in, global functions.) + A list of GDScript-specific utility functions accessed in any script. + For the list of the global functions and constants see [@GlobalScope]. </description> <tutorials> - <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> </tutorials> <methods> <method name="Color8"> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 68da588c3d..b76c2c0437 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -427,7 +427,7 @@ void GDScript::_add_doc(const DocData::ClassDoc &p_inner_class) { } else { for (int i = 0; i < docs.size(); i++) { if (docs[i].name == p_inner_class.name) { - docs.remove(i); + docs.remove_at(i); break; } } @@ -2131,7 +2131,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b const GDScriptParser::ClassNode *inner_class = subclass->members[i].m_class; if (inner_class->identifier->name == extend_classes[0]) { - extend_classes.remove(0); + extend_classes.remove_at(0); found = true; subclass = inner_class; break; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index cd8fd361c5..1ecde53dd0 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -3001,7 +3001,7 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) { // TODO: Don't load if validating: use completion cache. p_preload->resource = ResourceLoader::load(p_preload->resolved_path); if (p_preload->resource.is_null()) { - push_error(vformat(R"(Could not p_preload resource file "%s".)", p_preload->resolved_path), p_preload->path); + push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path); } } } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index bde6783322..41b2d2191c 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -741,20 +741,22 @@ void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)() if (member->identifier != nullptr) { if (!((String)member->identifier->name).is_empty()) { // Enums may be unnamed. + +#ifdef DEBUG_ENABLED List<MethodInfo> gdscript_funcs; GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); for (MethodInfo &info : gdscript_funcs) { if (info.name == member->identifier->name) { - push_error(vformat(R"(%s "%s" has the same name as a built-in function.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); - return; + push_warning(member->identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_member_kind, member->identifier->name, "built-in function"); } } + if (Variant::has_utility_function(member->identifier->name)) { + push_warning(member->identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_member_kind, member->identifier->name, "built-in function"); + } +#endif + if (current_class->members_indices.has(member->identifier->name)) { push_error(vformat(R"(%s "%s" has the same name as a previously declared %s.)", p_member_kind.capitalize(), member->identifier->name, current_class->get_member(member->identifier->name).get_type_name()), member->identifier); - } else if (Variant::has_utility_function(member->identifier->name)) { - push_error(vformat(R"(%s "%s" has the same name as a built-in function.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); - } else if (ClassDB::class_exists(member->identifier->name)) { - push_error(vformat(R"(%s "%s" has the same name as a global class.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); } else { current_class->add_member(member); } @@ -827,21 +829,18 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper GDScriptParser::IdentifierNode *identifier = parse_identifier(); +#ifdef DEBUG_ENABLED List<MethodInfo> gdscript_funcs; GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); for (MethodInfo &info : gdscript_funcs) { if (info.name == identifier->name) { - push_error(vformat(R"(Local var "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "local variable", identifier->name, "built-in function"); } } if (Variant::has_utility_function(identifier->name)) { - push_error(vformat(R"(Local var "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; - } else if (ClassDB::class_exists(identifier->name)) { - push_error(vformat(R"(Local var "%s" has the same name as a global class.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "local variable", identifier->name, "built-in function"); } +#endif VariableNode *variable = alloc_node<VariableNode>(); variable->identifier = identifier; @@ -1099,22 +1098,20 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() { } GDScriptParser::IdentifierNode *identifier = parse_identifier(); - +#ifdef DEBUG_ENABLED List<MethodInfo> gdscript_funcs; GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); for (MethodInfo &info : gdscript_funcs) { if (info.name == identifier->name) { - push_error(vformat(R"(Parameter "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "built-in function"); } } if (Variant::has_utility_function(identifier->name)) { - push_error(vformat(R"(Parameter "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "built-in function"); } else if (ClassDB::class_exists(identifier->name)) { - push_error(vformat(R"(Parameter "%s" has the same name as a global class.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "global class"); } +#endif ParameterNode *parameter = alloc_node<ParameterNode>(); parameter->identifier = identifier; @@ -1195,8 +1192,10 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { HashMap<StringName, int> elements; +#ifdef DEBUG_ENABLED List<MethodInfo> gdscript_funcs; GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); +#endif do { if (check(GDScriptTokenizer::Token::BRACE_CLOSE)) { @@ -1205,20 +1204,18 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for enum key.)")) { EnumNode::Value item; GDScriptParser::IdentifierNode *identifier = parse_identifier(); - +#ifdef DEBUG_ENABLED for (MethodInfo &info : gdscript_funcs) { if (info.name == identifier->name) { - push_error(vformat(R"(Enum member "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "enum member", identifier->name, "built-in function"); } } if (Variant::has_utility_function(identifier->name)) { - push_error(vformat(R"(Enum member "%s" has the same name as a built-in function.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "enum member", identifier->name, "built-in function"); } else if (ClassDB::class_exists(identifier->name)) { - push_error(vformat(R"(Enum member "%s" has the same name as a global class.)", identifier->name), identifier); - return nullptr; + push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "enum member", identifier->name, "global class"); } +#endif item.identifier = identifier; item.parent_enum = enum_node; item.line = previous.start_line; @@ -3417,7 +3414,7 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation) p_annotation->resolved_arguments.push_back(r); if (error.error != Callable::CallError::CALL_OK) { push_error(vformat(R"(Expected %s as argument %d of annotation "%s").)", Variant::get_type_name(parameter.type), i + 1, p_annotation->name)); - p_annotation->resolved_arguments.remove(p_annotation->resolved_arguments.size() - 1); + p_annotation->resolved_arguments.remove_at(p_annotation->resolved_arguments.size() - 1); return false; } break; @@ -3441,7 +3438,7 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation) p_annotation->resolved_arguments.push_back(r); if (error.error != Callable::CallError::CALL_OK) { push_error(vformat(R"(Expected %s as argument %d of annotation "%s").)", Variant::get_type_name(parameter.type), i + 1, p_annotation->name)); - p_annotation->resolved_arguments.remove(p_annotation->resolved_arguments.size() - 1); + p_annotation->resolved_arguments.remove_at(p_annotation->resolved_arguments.size() - 1); return false; } break; diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 7a483a16ba..a351bd6dad 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -148,6 +148,10 @@ String GDScriptWarning::get_message() const { case EMPTY_FILE: { return "Empty script file."; } + case SHADOWED_GLOBAL_IDENTIFIER: { + CHECK_SYMBOLS(3); + return vformat(R"(The %s '%s' has the same name as a %s.)", symbols[0], symbols[1], symbols[2]); + } case WARNING_MAX: break; // Can't happen, but silences warning } @@ -194,6 +198,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "ASSERT_ALWAYS_FALSE", "REDUNDANT_AWAIT", "EMPTY_FILE", + "SHADOWED_GLOBAL_IDENTIFIER", }; 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 8de46b08c1..d05f47efe7 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -69,6 +69,7 @@ public: ASSERT_ALWAYS_FALSE, // Expression for assert argument is always false. REDUNDANT_AWAIT, // await is used but expression is synchronous (not a signal nor a coroutine). EMPTY_FILE, // A script file is empty. + SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable. WARNING_MAX, }; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 5cf1e0fc5f..578943696e 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -115,7 +115,7 @@ Error GDScriptLanguageProtocol::LSPeer::send_data() { // Response sent if (res_sent >= c_res.size() - 1) { res_sent = 0; - res_queue.remove(0); + res_queue.remove_at(0); } } return OK; diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.gd b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.gd new file mode 100644 index 0000000000..3c64be571b --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.gd @@ -0,0 +1,2 @@ +func test(): + var abs = "This variable has the same name as the built-in function." diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out new file mode 100644 index 0000000000..f2b29e5bad --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out @@ -0,0 +1,9 @@ +GDTEST_OK +>> WARNING +>> Line: 2 +>> SHADOWED_GLOBAL_IDENTIFIER +>> The local variable 'abs' has the same name as a built-in function. +>> WARNING +>> Line: 2 +>> UNUSED_VARIABLE +>> The local variable 'abs' is declared but never used in the block. If this is intended, prefix it with an underscore: '_abs' |