Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn on connected functions without correct argument count #12450

Open
N0hbdy opened this issue Oct 28, 2017 · 8 comments
Open

Warn on connected functions without correct argument count #12450

N0hbdy opened this issue Oct 28, 2017 · 8 comments

Comments

@N0hbdy
Copy link
Contributor

N0hbdy commented Oct 28, 2017

Operating system or device, Godot version, GPU Model and driver (if graphics related):
MacOS, Godot 3.0 alpha

Issue description:

Connecting a signal to a function that doesn't have the correct number of arguments means that the function is never called (and I haven't seen any warnings in the debugger being called). Ideally, either the editor puts a lint warning up, or when attempting to call the function it complains that the function is invalid.

Steps to reproduce:
I connected a no-argument function to an animation_finished callback, which never is called. Can upload examples if needed!

Link to minimal example project:

Happy to make one if it helps; might poke around to see if I can cobble something together!

@mhilbrunner
Copy link
Member

Maybe users should even be warned when overriding methods, e.g. defining _process(): without the delta argument.

@akien-mga akien-mga changed the title [Feature] Warn on connected functions without correct argument count Warn on connected functions without correct argument count Oct 28, 2017
@N0hbdy
Copy link
Contributor Author

N0hbdy commented Oct 29, 2017

Any tips on where to start digging into this? I'd like to see if I can get this added :)

@bojidar-bg
Copy link
Contributor

Some pointers which I guess might be useful, from core/object.cpp and modules/gdscript/gd_function.cpp.

Object::emit_signal, the lines related to calling the method:

godot/core/object.cpp

Lines 1116 to 1131 in 62a3dcd

if (c.flags & CONNECT_DEFERRED) {
MessageQueue::get_singleton()->push_call(target->get_instance_id(), c.method, args, argc, true);
} else {
Variant::CallError ce;
target->call(c.method, args, argc, ce);
if (ce.error != Variant::CallError::CALL_OK) {
if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
//most likely object is not initialized yet, do not throw error.
} else {
ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce));
err = ERR_METHOD_NOT_FOUND;
}
}
}


GDScript/GDInstance::call() correctly returns CALL_ERROR_TOO_FEW_ARGUMENTS:

} else if (p_argcount < _argument_count - _default_arg_count) {
r_err.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;


Object::call directly returns the error returned by the script (by passing r_error to it, which is passed by reference):

godot/core/object.cpp

Lines 818 to 832 in 62a3dcd

ret = script_instance->call(p_method, p_args, p_argcount, r_error);
//force jumptable
switch (r_error.error) {
case Variant::CallError::CALL_OK:
return ret;
case Variant::CallError::CALL_ERROR_INVALID_METHOD:
break;
case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT:
case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
return ret;
case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
}
}


_test_call_error, a debug-only helper function, which might be useful:

godot/core/object.cpp

Lines 600 to 618 in 62a3dcd

static bool _test_call_error(const StringName &p_func, const Variant::CallError &error) {
switch (error.error) {
case Variant::CallError::CALL_OK:
return true;
case Variant::CallError::CALL_ERROR_INVALID_METHOD:
return false;
case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: {
ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(error.expected));
ERR_FAIL_V(true);
} break;
case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument));
ERR_FAIL_V(true);
} break;

@robfram
Copy link
Contributor

robfram commented Mar 4, 2018

Has this issue being solved? I get an error in the debug window in this cases, and remember being that way since December at least. I don't know if the message shown is not enough and a better method to inform or alert the user is required.

error

@Nufflee
Copy link
Contributor

Nufflee commented Jul 20, 2018

I can try adding a lint message for this.

@jordgubben
Copy link

jordgubben commented Mar 10, 2019

I've tinkered a bit now and I think I'm slowly getting somewhere. This is my first attempt to contribute to Godot, so I still need to spend a lot of time just browsing the source code.

I have one question: Is there any simple way to get the MethodInfo of a single method? Invoking Object::get_method_list() and iterating over an entire List<MethodInfo>seems a bit of a performance waste when it's already a hash-map behind the scenes?

@jordgubben
Copy link

So far I've managed to add a warning in the Connections dialogue. I need to rebase all the things before I submit a Draft-PR.

Godot Invalid Arity 2019-03-17 kl  11 03 17

@Anutrix
Copy link
Contributor

Anutrix commented Oct 12, 2020

In current master it gives something like:

ERROR: Error calling from signal 'button_down' to callable: Node2D(Node2D.gd)::hello : Method expected 1 arguments, but called with 0..
   at: emit_signal (core\object.cpp:1088)

It does need a better warning.
I think we should disallow connecting to methods having non-matching number of arguments at signal connection window itself OR it should create new function with same name but signal's supplied number of arguments instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants