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

For C# script, the editor always append generated function signature to the end of file when connecting signal, even if the method already exists. #77250

Open
huisedenanhai opened this issue May 19, 2023 · 4 comments · May be fixed by #77274

Comments

@huisedenanhai
Copy link
Contributor

Godot version

4.1-dev

System information

macOS 13.3 M1 Pro

Issue description

Related to #18721.

I'm using C# for scripting. When I connect signal from editor, the editor always append generated function signature to the end of file, even if the method already exists.

I look at the code and found the editor DOES check the existance of method before try to modify script source.

if (!scr.is_null() && !ClassDB::has_method(target->get_class(), cd.method)) {

I can pick a method of C# class, but ClassDB::has_method returns false.
I tried to modify the code and found ClassDB::has_method and Script::has_method returns different result at this point.

I'm not sure if this behaviour is expected, but it looks strange.

Steps to reproduce

Modify the source, check Script::has_method after ClassDB::has_method returns false.

if (!scr.is_null() && !ClassDB::has_method(target->get_class(), cd.method)) {
    if (scr->has_method(cd.method)) {
	throw "Why";
    }
 //...
}

The exception will be triggered when try to pick and connect a signal to an existing C# method.

Minimal reproduction project

The godot source code.

@ghost
Copy link

ghost commented May 20, 2023

This is a common misunderstanding about classes.
There are differences between classes in ClassDB and "scripts".

I'll explain with GDScript, but the same applies to C#.

For example, imagine this GDScript that defines a "class":

class_name Abc extends Node

func test() -> void:
  pass

Now, if I want to get the "class" of it by the get_class method, see what happens below:

var target := Abc.new()

print(target.get_class()) # "Node" will be printed, not "Abc"
print(ClassDB.class_has_method(target.get_class(), 'test')) # false
print(target.has_method('test')) # true

The reason for that is that the get_class method and ClassDB works on the types exported from the core, not our defined scripts.

The behavior is expected.

I hope I was able to explain myself, if in doubt, feel free to ask.

@huisedenanhai
Copy link
Contributor Author

That makes sense.

I thought ClassDB::has_method check if current script contains the method, but it does not.

Then for automatic code generation when connecting signals from the editor, current implementation check the existstance of method in the base script or class exported from core, but does not check the current script.

Is that an expected behaviour? Otherwise an additional check is needed.

if (scr->has_method(cd.method)) {
    add_script_function = false;
}

With this check, no redundent code will be append to the C# file when the method exists.

@huisedenanhai huisedenanhai changed the title ClassDB::has_method and Script::has_method returns different result For C# script, the editor always append generated function signature to the end of file when connecting signal, even if the method already exists. May 20, 2023
@akien-mga
Copy link
Member

Seems like a duplicate of #18721 to me, but since it has a PR that solves only one aspect of it (duplicated methods), I guess we can keep it separate.

@annakrasner
Copy link

This is still an issue on 4.2.1stable

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

Successfully merging a pull request may close this issue.

4 participants