瀏覽代碼

GDScript: Fix duplication of inherited script properties

Danil Alexeev 1 年之前
父節點
當前提交
16e860bcb3

+ 10 - 8
modules/gdscript/gdscript.cpp

@@ -306,6 +306,9 @@ void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_incl
 	while (sptr) {
 		Vector<_GDScriptMemberSort> msort;
 		for (const KeyValue<StringName, MemberInfo> &E : sptr->member_indices) {
+			if (!sptr->members.has(E.key)) {
+				continue; // Skip base class members.
+			}
 			_GDScriptMemberSort ms;
 			ms.index = E.value.index;
 			ms.name = E.key;
@@ -1648,15 +1651,11 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
 }
 
 Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
-	const GDScript *sptr = script.ptr();
-	while (sptr) {
-		if (sptr->member_indices.has(p_name)) {
-			if (r_is_valid) {
-				*r_is_valid = true;
-			}
-			return sptr->member_indices[p_name].property_info.type;
+	if (script->member_indices.has(p_name)) {
+		if (r_is_valid) {
+			*r_is_valid = true;
 		}
-		sptr = sptr->_base;
+		return script->member_indices[p_name].property_info.type;
 	}
 
 	if (r_is_valid) {
@@ -1732,6 +1731,9 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
 
 		Vector<_GDScriptMemberSort> msort;
 		for (const KeyValue<StringName, GDScript::MemberInfo> &F : sptr->member_indices) {
+			if (!sptr->members.has(F.key)) {
+				continue; // Skip base class members.
+			}
 			_GDScriptMemberSort ms;
 			ms.index = F.value.index;
 			ms.name = F.key;

+ 8 - 4
modules/gdscript/gdscript.h

@@ -94,12 +94,16 @@ class GDScript : public Script {
 	GDScript *_base = nullptr; //fast pointer access
 	GDScript *_owner = nullptr; //for subclasses
 
-	HashSet<StringName> members; //members are just indices to the instantiated script.
-	HashMap<StringName, Variant> constants;
+	// Members are just indices to the instantiated script.
+	HashMap<StringName, MemberInfo> member_indices; // Includes member info of all base GDScript classes.
+	HashSet<StringName> members; // Only members of the current class.
+
+	// Only static variables of the current class.
 	HashMap<StringName, MemberInfo> static_variables_indices;
-	Vector<Variant> static_variables;
+	Vector<Variant> static_variables; // Static variable values.
+
+	HashMap<StringName, Variant> constants;
 	HashMap<StringName, GDScriptFunction *> member_functions;
-	HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
 	HashMap<StringName, Ref<GDScript>> subclasses;
 	HashMap<StringName, MethodInfo> _signals;
 	Dictionary rpc_config;

+ 1 - 1
modules/gdscript/gdscript_compiler.cpp

@@ -2783,7 +2783,7 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
 				minfo.property_info = prop_info;
 
 				p_script->member_indices[name] = minfo;
-				p_script->members.insert(Variant());
+				p_script->members.insert(name);
 			} break;
 
 			case GDScriptParser::ClassNode::Member::FUNCTION: {

+ 45 - 0
modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd

@@ -0,0 +1,45 @@
+# GH-82169
+
+const Utils = preload("../../utils.notest.gd")
+
+class A:
+	static var test_static_var_a1
+	static var test_static_var_a2
+	var test_var_a1
+	var test_var_a2
+	static func test_static_func_a1(): pass
+	static func test_static_func_a2(): pass
+	func test_func_a1(): pass
+	func test_func_a2(): pass
+	signal test_signal_a1()
+	signal test_signal_a2()
+
+class B extends A:
+	static var test_static_var_b1
+	static var test_static_var_b2
+	var test_var_b1
+	var test_var_b2
+	static func test_static_func_b1(): pass
+	static func test_static_func_b2(): pass
+	func test_func_b1(): pass
+	func test_func_b2(): pass
+	signal test_signal_b1()
+	signal test_signal_b2()
+
+func test():
+	var b := B.new()
+	for property in (B as GDScript).get_property_list():
+		if str(property.name).begins_with("test_"):
+			print(Utils.get_property_signature(property, true))
+	print("---")
+	for property in b.get_property_list():
+		if str(property.name).begins_with("test_"):
+			print(Utils.get_property_signature(property))
+	print("---")
+	for method in b.get_method_list():
+		if str(method.name).begins_with("test_"):
+			print(Utils.get_method_signature(method))
+	print("---")
+	for method in b.get_signal_list():
+		if str(method.name).begins_with("test_"):
+			print(Utils.get_method_signature(method, true))

+ 24 - 0
modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out

@@ -0,0 +1,24 @@
+GDTEST_OK
+static var test_static_var_a1: Variant
+static var test_static_var_a2: Variant
+static var test_static_var_b1: Variant
+static var test_static_var_b2: Variant
+---
+var test_var_b1: Variant
+var test_var_b2: Variant
+var test_var_a1: Variant
+var test_var_a2: Variant
+---
+static func test_static_func_b1() -> void
+static func test_static_func_b2() -> void
+func test_func_b1() -> void
+func test_func_b2() -> void
+static func test_static_func_a1() -> void
+static func test_static_func_a2() -> void
+func test_func_a1() -> void
+func test_func_a2() -> void
+---
+signal test_signal_b1()
+signal test_signal_b2()
+signal test_signal_a1()
+signal test_signal_a2()