diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2024-03-13 22:16:43 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-03-13 22:16:43 +0100 |
commit | a1c476f9d754e9c3420eb092b236325029151c0b (patch) | |
tree | ffa5bd5899adf40ed1c9a67a8425e4c777aeddcc /modules/gdscript | |
parent | 89ba6178248569813cbd8cc44e402b411b88ac36 (diff) | |
parent | 59bcc2888c0c6002428ed1040ef6b36957a80e98 (diff) | |
download | redot-engine-a1c476f9d754e9c3420eb092b236325029151c0b.tar.gz |
Merge pull request #87680 from AThousandShips/the_angry_count
Add methods to get argument count of methods
Diffstat (limited to 'modules/gdscript')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 34 | ||||
-rw-r--r-- | modules/gdscript/gdscript.h | 6 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_lambda_callable.cpp | 18 | ||||
-rw-r--r-- | modules/gdscript/gdscript_lambda_callable.h | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_rpc_callable.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript_rpc_callable.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_utility_callable.cpp | 15 | ||||
-rw-r--r-- | modules/gdscript/gdscript_utility_callable.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_utility_functions.cpp | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_utility_functions.h | 2 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/runtime/features/argument_count.gd | 102 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/runtime/features/argument_count.out | 27 |
13 files changed, 213 insertions, 2 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 94aa077014..8e74de4242 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -354,6 +354,21 @@ bool GDScript::has_static_method(const StringName &p_method) const { return member_functions.has(p_method) && member_functions[p_method]->is_static(); } +int GDScript::get_script_method_argument_count(const StringName &p_method, bool *r_is_valid) const { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method); + if (!E) { + if (r_is_valid) { + *r_is_valid = false; + } + return 0; + } + + if (r_is_valid) { + *r_is_valid = true; + } + return E->value->get_argument_count(); +} + MethodInfo GDScript::get_method_info(const StringName &p_method) const { HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method); if (!E) { @@ -1916,6 +1931,25 @@ bool GDScriptInstance::has_method(const StringName &p_method) const { return false; } +int GDScriptInstance::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const { + const GDScript *sptr = script.ptr(); + while (sptr) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method); + if (E) { + if (r_is_valid) { + *r_is_valid = true; + } + return E->value->get_argument_count(); + } + sptr = sptr->_base; + } + + if (r_is_valid) { + *r_is_valid = false; + } + return 0; +} + Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); if (unlikely(p_method == SNAME("_ready"))) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 7c471c285b..fd5ad837f9 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -312,6 +312,9 @@ public: virtual void get_script_method_list(List<MethodInfo> *p_list) const override; virtual bool has_method(const StringName &p_method) const override; virtual bool has_static_method(const StringName &p_method) const override; + + virtual int get_script_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override; + virtual MethodInfo get_method_info(const StringName &p_method) const override; virtual void get_script_property_list(List<PropertyInfo> *p_list) const override; @@ -376,6 +379,9 @@ public: virtual void get_method_list(List<MethodInfo> *p_list) const; virtual bool has_method(const StringName &p_method) const; + + virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const; + virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 177c68533e..002fc159fa 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -511,6 +511,7 @@ public: _FORCE_INLINE_ GDScript *get_script() const { return _script; } _FORCE_INLINE_ bool is_static() const { return _static; } _FORCE_INLINE_ MethodInfo get_method_info() const { return method_info; } + _FORCE_INLINE_ int get_argument_count() const { return _argument_count; } _FORCE_INLINE_ Variant get_rpc_config() const { return rpc_config; } _FORCE_INLINE_ int get_max_stack_size() const { return _stack_size; } diff --git a/modules/gdscript/gdscript_lambda_callable.cpp b/modules/gdscript/gdscript_lambda_callable.cpp index f6fa17c84f..626ef6ccb0 100644 --- a/modules/gdscript/gdscript_lambda_callable.cpp +++ b/modules/gdscript/gdscript_lambda_callable.cpp @@ -78,6 +78,15 @@ StringName GDScriptLambdaCallable::get_method() const { return function->get_name(); } +int GDScriptLambdaCallable::get_argument_count(bool &r_is_valid) const { + if (function == nullptr) { + r_is_valid = false; + return 0; + } + r_is_valid = true; + return function->get_argument_count(); +} + void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { int captures_amount = captures.size(); @@ -189,6 +198,15 @@ ObjectID GDScriptLambdaSelfCallable::get_object() const { return object->get_instance_id(); } +int GDScriptLambdaSelfCallable::get_argument_count(bool &r_is_valid) const { + if (function == nullptr) { + r_is_valid = false; + return 0; + } + r_is_valid = true; + return function->get_argument_count(); +} + void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { #ifdef DEBUG_ENABLED if (object->get_script_instance() == nullptr || object->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) { diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h index 2c5d01aa16..45c0235913 100644 --- a/modules/gdscript/gdscript_lambda_callable.h +++ b/modules/gdscript/gdscript_lambda_callable.h @@ -59,6 +59,7 @@ public: CompareLessFunc get_compare_less_func() const override; ObjectID get_object() const override; StringName get_method() const override; + int get_argument_count(bool &r_is_valid) const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; GDScriptLambdaCallable(GDScriptLambdaCallable &) = delete; @@ -86,6 +87,7 @@ public: CompareEqualFunc get_compare_equal_func() const override; CompareLessFunc get_compare_less_func() const override; ObjectID get_object() const override; + int get_argument_count(bool &r_is_valid) const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; GDScriptLambdaSelfCallable(GDScriptLambdaSelfCallable &) = delete; diff --git a/modules/gdscript/gdscript_rpc_callable.cpp b/modules/gdscript/gdscript_rpc_callable.cpp index df014d3cfe..3139371eb5 100644 --- a/modules/gdscript/gdscript_rpc_callable.cpp +++ b/modules/gdscript/gdscript_rpc_callable.cpp @@ -68,6 +68,10 @@ StringName GDScriptRPCCallable::get_method() const { return method; } +int GDScriptRPCCallable::get_argument_count(bool &r_is_valid) const { + return object->get_method_argument_count(method, &r_is_valid); +} + void GDScriptRPCCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { r_return_value = object->callp(method, p_arguments, p_argcount, r_call_error); } diff --git a/modules/gdscript/gdscript_rpc_callable.h b/modules/gdscript/gdscript_rpc_callable.h index 66052157be..2ca6290951 100644 --- a/modules/gdscript/gdscript_rpc_callable.h +++ b/modules/gdscript/gdscript_rpc_callable.h @@ -52,6 +52,7 @@ public: CompareLessFunc get_compare_less_func() const override; ObjectID get_object() const override; StringName get_method() const override; + int get_argument_count(bool &r_is_valid) const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override; diff --git a/modules/gdscript/gdscript_utility_callable.cpp b/modules/gdscript/gdscript_utility_callable.cpp index 7708a18044..edd7e05b22 100644 --- a/modules/gdscript/gdscript_utility_callable.cpp +++ b/modules/gdscript/gdscript_utility_callable.cpp @@ -80,6 +80,21 @@ ObjectID GDScriptUtilityCallable::get_object() const { return ObjectID(); } +int GDScriptUtilityCallable::get_argument_count(bool &r_is_valid) const { + switch (type) { + case TYPE_INVALID: + r_is_valid = false; + return 0; + case TYPE_GLOBAL: + r_is_valid = true; + return Variant::get_utility_function_argument_count(function_name); + case TYPE_GDSCRIPT: + r_is_valid = true; + return GDScriptUtilityFunctions::get_function_argument_count(function_name); + } + ERR_FAIL_V_MSG(0, "Invalid type."); +} + void GDScriptUtilityCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { switch (type) { case TYPE_INVALID: diff --git a/modules/gdscript/gdscript_utility_callable.h b/modules/gdscript/gdscript_utility_callable.h index 675bc4ddd9..c5736e815f 100644 --- a/modules/gdscript/gdscript_utility_callable.h +++ b/modules/gdscript/gdscript_utility_callable.h @@ -57,6 +57,7 @@ public: bool is_valid() const override; StringName get_method() const override; ObjectID get_object() const override; + int get_argument_count(bool &r_is_valid) const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; GDScriptUtilityCallable(const StringName &p_function_name); diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index f8cb460e40..e5b0f55df8 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -759,7 +759,7 @@ Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringN return info->info.arguments[p_arg].type; } -int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function, int p_arg) { +int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) { GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function); ERR_FAIL_NULL_V(info, 0); return info->info.arguments.size(); diff --git a/modules/gdscript/gdscript_utility_functions.h b/modules/gdscript/gdscript_utility_functions.h index 40e9379a3a..1c4e4452c8 100644 --- a/modules/gdscript/gdscript_utility_functions.h +++ b/modules/gdscript/gdscript_utility_functions.h @@ -46,7 +46,7 @@ public: static Variant::Type get_function_return_type(const StringName &p_function); static StringName get_function_return_class(const StringName &p_function); static Variant::Type get_function_argument_type(const StringName &p_function, int p_arg); - static int get_function_argument_count(const StringName &p_function, int p_arg); + static int get_function_argument_count(const StringName &p_function); static bool is_function_vararg(const StringName &p_function); static bool is_function_constant(const StringName &p_function); diff --git a/modules/gdscript/tests/scripts/runtime/features/argument_count.gd b/modules/gdscript/tests/scripts/runtime/features/argument_count.gd new file mode 100644 index 0000000000..c67ce25cbe --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/argument_count.gd @@ -0,0 +1,102 @@ +extends Node + +func my_func_1(_foo, _bar): + pass + +func my_func_2(_foo, _bar, _baz): + pass + +static func my_static_func_1(_foo, _bar): + pass + +static func my_static_func_2(_foo, _bar, _baz): + pass + +@rpc +func my_rpc_func_1(_foo, _bar): + pass + +@rpc +func my_rpc_func_2(_foo, _bar, _baz): + pass + +func test(): + # Test built-in methods. + var builtin_callable_1 : Callable = add_to_group + print(builtin_callable_1.get_argument_count()) # Should print 2. + var builtin_callable_2 : Callable = find_child + print(builtin_callable_2.get_argument_count()) # Should print 3. + + # Test built-in vararg methods. + var builtin_vararg_callable_1 : Callable = call_thread_safe + print(builtin_vararg_callable_1.get_argument_count()) # Should print 1. + var builtin_vararg_callable_2 : Callable = rpc_id + print(builtin_vararg_callable_2.get_argument_count()) # Should print 2. + + # Test plain methods. + var callable_1 : Callable = my_func_1 + print(callable_1.get_argument_count()) # Should print 2. + var callable_2 : Callable = my_func_2 + print(callable_2.get_argument_count()) # Should print 3. + + # Test static methods. + var static_callable_1 : Callable = my_static_func_1 + print(static_callable_1.get_argument_count()) # Should print 2. + var static_callable_2 : Callable = my_static_func_2 + print(static_callable_2.get_argument_count()) # Should print 3. + + # Test rpc methods. + var rpc_callable_1 : Callable = my_rpc_func_1 + print(rpc_callable_1.get_argument_count()) # Should print 2. + var rpc_callable_2 : Callable = my_rpc_func_2 + print(rpc_callable_2.get_argument_count()) # Should print 3. + + # Test lambdas. + var lambda_callable_1 : Callable = func(_foo, _bar): pass + print(lambda_callable_1.get_argument_count()) # Should print 2. + var lambda_callable_2 : Callable = func(_foo, _bar, _baz): pass + print(lambda_callable_2.get_argument_count()) # Should print 3. + + # Test lambas with self. + var lambda_self_callable_1 : Callable = func(_foo, _bar): return self + print(lambda_self_callable_1.get_argument_count()) # Should print 2. + var lambda_self_callable_2 : Callable = func(_foo, _bar, _baz): return self + print(lambda_self_callable_2.get_argument_count()) # Should print 3. + + # Test bind. + var bind_callable_1 : Callable = my_func_2.bind(1) + print(bind_callable_1.get_argument_count()) # Should print 2. + var bind_callable_2 : Callable = my_func_2.bind(1, 2) + print(bind_callable_2.get_argument_count()) # Should print 1. + + # Test unbind. + var unbind_callable_1 : Callable = my_func_2.unbind(1) + print(unbind_callable_1.get_argument_count()) # Should print 4. + var unbind_callable_2 : Callable = my_func_2.unbind(2) + print(unbind_callable_2.get_argument_count()) # Should print 5. + + # Test variant callables. + var string_tmp := String() + var variant_callable_1 : Callable = string_tmp.replace + print(variant_callable_1.get_argument_count()) # Should print 2. + var variant_callable_2 : Callable = string_tmp.rsplit + print(variant_callable_2.get_argument_count()) # Should print 3. + + # Test variant vararg callables. + var callable_tmp := Callable() + var variant_vararg_callable_1 : Callable = callable_tmp.call + print(variant_vararg_callable_1.get_argument_count()) # Should print 0. + var variant_vararg_callable_2 : Callable = callable_tmp.rpc_id + print(variant_vararg_callable_2.get_argument_count()) # Should print 1. + + # Test global methods. + var global_callable_1 = is_equal_approx + print(global_callable_1.get_argument_count()) # Should print 2. + var global_callable_2 = inverse_lerp + print(global_callable_2.get_argument_count()) # Should print 3. + + # Test GDScript methods. + var gdscript_callable_1 = char + print(gdscript_callable_1.get_argument_count()) # Should print 1. + var gdscript_callable_2 = is_instance_of + print(gdscript_callable_2.get_argument_count()) # Should print 2. diff --git a/modules/gdscript/tests/scripts/runtime/features/argument_count.out b/modules/gdscript/tests/scripts/runtime/features/argument_count.out new file mode 100644 index 0000000000..42c4ece37d --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/argument_count.out @@ -0,0 +1,27 @@ +GDTEST_OK +2 +3 +1 +2 +2 +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 +1 +4 +5 +2 +3 +0 +1 +2 +3 +1 +2 |