diff options
6 files changed, 32 insertions, 5 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 8da77b9e5b..3d248e3da7 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -32,6 +32,7 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" +#include "core/core_string_names.h" #include "core/io/file_access.h" #include "core/io/resource_loader.h" #include "core/object/class_db.h" @@ -132,7 +133,7 @@ static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) { return type; } -bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class) { +bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) { if (p_class->members_indices.has(p_member_name)) { int index = p_class->members_indices[p_member_name]; const GDScriptParser::ClassNode::Member *member = &p_class->members[index]; @@ -145,6 +146,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName member->type == GDScriptParser::ClassNode::Member::SIGNAL) { return true; } + if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) { + return true; + } } return false; @@ -160,6 +164,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) { return true; } + if (p_member_name == CoreStringNames::get_singleton()->_script) { + return true; + } return false; } @@ -187,14 +194,15 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C const GDScriptParser::DataType *current_data_type = &p_class_node->base_type; while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) { GDScriptParser::ClassNode *current_class_node = current_data_type->class_type; - if (has_member_name_conflict_in_script_class(p_member_name, current_class_node)) { - push_error(vformat(R"(The member "%s" already exists in a parent class.)", p_member_name), + if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) { + push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, current_class_node->identifier->name), p_member_node); return ERR_PARSE_ERROR; } current_data_type = ¤t_class_node->base_type; } + // No need for native class recursion because Node exposes all Object's properties. if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) { if (current_data_type->native_type != StringName()) { return check_native_member_name_conflict( @@ -2912,7 +2920,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod base_class = base_class->base_type.class_type; } - // Check native members. + // Check native members. No need for native class recursion because Node exposes all Object's properties. const StringName &native = base.native_type; if (class_exists(native)) { diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 217a856ce0..23a3ad39a5 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -45,7 +45,7 @@ class GDScriptAnalyzer { List<GDScriptParser::LambdaNode *> lambda_stack; // Tests for detecting invalid overloading of script members - static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node); + static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node, const GDScriptParser::Node *p_member); static _FORCE_INLINE_ bool has_member_name_conflict_in_native_type(const StringName &p_name, const StringName &p_native_type_string); Error check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string); Error check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node); diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd new file mode 100644 index 0000000000..5c8b9fa4ae --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd @@ -0,0 +1,6 @@ +extends Node + +var script: int + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out new file mode 100644 index 0000000000..8454aaa404 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Member "script" redefined (original in native class 'Node') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd new file mode 100644 index 0000000000..28561ff94b --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd @@ -0,0 +1,9 @@ +func test(): + pass + +class A: + func overload_me(): + pass + +class B extends A: + var overload_me diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out new file mode 100644 index 0000000000..32357f9f6a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The member "overload_me" already exists in parent class A. |