summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanil Alexeev <danil@alexeev.xyz>2023-09-23 15:19:43 +0300
committerDanil Alexeev <danil@alexeev.xyz>2023-09-23 15:30:23 +0300
commit16e860bcb3a263b4e10dcd85149bda68e74eec3c (patch)
treeb0a27ed04d323e3e5758b8a6243392738e34d574
parentc12d63556b5c1da03a00dd4c45c40e60bd8d68c2 (diff)
downloadredot-engine-16e860bcb3a263b4e10dcd85149bda68e74eec3c.tar.gz
GDScript: Fix duplication of inherited script properties
-rw-r--r--modules/gdscript/gdscript.cpp18
-rw-r--r--modules/gdscript/gdscript.h12
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd45
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out24
5 files changed, 88 insertions, 13 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 62d2c14c17..fc74b3e84e 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/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;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 2fd2ec236a..cbd1dced2f 100644
--- a/modules/gdscript/gdscript.h
+++ b/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;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7f2c401afc..1b48047433 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/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: {
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
new file mode 100644
index 0000000000..d0cbeeab85
--- /dev/null
+++ b/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))
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out
new file mode 100644
index 0000000000..f294b66ef9
--- /dev/null
+++ b/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()