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

Allow different class names in rust and Godot #419

Merged
merged 1 commit into from
Oct 3, 2023

Conversation

fpdotmonkey
Copy link
Contributor

There's an issue that two structs with the same name in different modules will conflict with each other when sent to Godot since only the struct name is considered. This resolves that by allowing the API user to manually change the name of the class as Godot understands it. This also improves the error message that occurs when theres are aliased classes.

Future work may seek to catch this issue at compile time rather than at runtime.

Relevant to #332

@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-419

@Bromeon Bromeon linked an issue Sep 21, 2023 that may be closed by this pull request
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot!

One thing that went through my head is the string-based syntax #[class(rename="MyClass")], but since it's effectively an identifier in GDScript, I think this is fine!

)
.unwrap_or_else(|_|
panic!(
"the definition for `{}` is overloaded; you may have multiple `GodotClass`es named `{}` which you should #[class(rename=...)]",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"overloaded" is a bit imprecise here, but I also think there is no need to repeat the class name.

Maybe simply:

Suggested change
"the definition for `{}` is overloaded; you may have multiple `GodotClass`es named `{}` which you should #[class(rename=...)]",
"class `{}` is already defined; to register equally named structs under different names, use `#[class(rename=...)]`",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to keep GodotClass in there to point the user to that symbol (I guess class is technically the relevant symbol, but it reads as generic here).

I'll take another shot at this error message

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would still need to be updated 🙂

Regarding GodotClass, you could mention:

                    "class `{}` is already defined; to register equally named structs under\n\
                    different names, use `#[derive(GodotClass)` with `#[class(rename=...)]`"

(it might deserve the newline)

@@ -318,6 +318,34 @@ use crate::util::ident;
/// for more information and further customization.
///
/// This is very similar to [GDScript's `@tool` feature](https://docs.godotengine.org/en/stable/tutorials/plugins/running_code_in_the_editor.html).
///
///
/// # Class Name Aliasing
Copy link
Member

@Bromeon Bromeon Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "Class renaming" -- aliasing is typically associated with &mut.

Comment on lines 325 to 329
/// You may want to have structs with the same name. With rust, this is
/// allowed using `mod`. However in GDScript, there are no modules,
/// namespaces, or any such diambiguation. Therefore, you need to
/// change the names before they can get to Godot. You can use the
/// `rename` key while defining your `GodotClass` for this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a bit wider lines if possible (~120 chars).

Also, some typos:

  • rust -> Rust
  • diambiguation
  • no need for double space after full stop

use super::*;

#[derive(GodotClass)]
#[class(init, base = Node)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[class] could probably be emitted entirely, since neither the constructor nor the base class are relevant.

use super::*;

#[derive(GodotClass)]
#[class(init, base = Node, rename = NoRepeat)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, just #[class(rename = NoRepeat)] would be enough.

Comment on lines 26 to 33
#[itest]
fn renaming_changes_the_name() {
// note: this test doesn't really fail; if it doesn't succeed, then
// the runner hangs. I don't know how to solve that.
assert!(dont_rename::RepeatMe::class_name() != rename::RepeatMe::class_name());
assert_eq!(dont_rename::RepeatMe::class_name().as_str(), "RepeatMe");
assert_eq!(rename::RepeatMe::class_name().as_str(), "NoRepeat");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just hangs -- do you see any error or so?

First statement could be assert_ne!, by the way 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hang is maybe imprecise? If you don't rename the class, you hit the error mentioned in the issue and Godot throws some errors and the runner can't proceed

> godot4 --path itest/godot --headless -- \[\]
Initialize GDExtension API for Rust: Godot Engine v4.1.1.stable.official
Godot Engine v4.1.1.stable.official.bd6af8e0e - https://godotengine.org
 
ERROR: Rust function panicked in file godot-core/src/registry.rs at line 209. Context: failed to initialize GDExtension level `Scene`
   at: <function unset> (godot-core/src/lib.rs:154)
ERROR: Panic msg:  the definition for `RepeatMe` is overloaded; you may have multiple `GodotClass`es named `RepeatMe` which you should #[class(rename=...)]
   at: <function unset> (godot-core/src/lib.rs:102)
SCRIPT ERROR: Parse Error: Identifier "IntegrationTests" not declared in the current scope.
          at: GDScript::reload (res://TestRunner.gd:31)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I've now discovered that this is solved by not having the init or base in the class declarations as you suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always forget about assert_ne, I always try assert_neq and when that doesn't work, go for assert

@Bromeon Bromeon added feature Adds functionality to the library c: register Register classes, functions and other symbols to GDScript labels Sep 21, 2023
@Bromeon
Copy link
Member

Bromeon commented Sep 21, 2023

Another small request: please exclude issue/PR references from commit messages. Unfortunately GitHub is not very smart about them and links even those of abandoned branches permanently, which clutters the issue quite a bit:
grafik

@fpdotmonkey
Copy link
Contributor Author

Another small request: please exclude issue/PR references from commit messages. Unfortunately GitHub is not very smart about them and links even those of abandoned branches permanently, which clutters the issue quite a bit

Oh that's very annoying, noted!

Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you push the correct commit? Many of my reviews are still unaddressed 🤔

Maybe check the diff directly, the conversation tab is sometimes not very good to keep an overview...

)
.unwrap_or_else(|_|
panic!(
"the definition for `{}` is overloaded; you may have multiple `GodotClass`es named `{}` which you should #[class(rename=...)]",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would still need to be updated 🙂

Regarding GodotClass, you could mention:

                    "class `{}` is already defined; to register equally named structs under\n\
                    different names, use `#[derive(GodotClass)` with `#[class(rename=...)]`"

(it might deserve the newline)

@@ -21,7 +21,7 @@ pub fn derive_godot_class(decl: Declaration) -> ParseResult<TokenStream> {
let fields = parse_fields(class)?;

let class_name = &class.name;
let class_name_str = class.name.to_string();
let class_name_str = struct_cfg.rename.unwrap_or(class.name.clone()).to_string();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This always executes both clone() and to_string().

map_or_else() or a good old if let Some(...) would be a bit nicer 🙂

@Bromeon
Copy link
Member

Bromeon commented Sep 24, 2023

Sorry about the conflicts, merging #393 caused some changes.

@fpdotmonkey fpdotmonkey force-pushed the alias-class-definitions branch 2 times, most recently from d403c4c to 83ca3e1 Compare September 28, 2023 14:48
@fpdotmonkey
Copy link
Contributor Author

Did you push the correct commit?

Sorry about that, forgot to stage most of the changes, woops. Should be good now, assuming the CI approves,

@Bromeon
Copy link
Member

Bromeon commented Sep 29, 2023

Thank you! The CI errors now, in dictionary_test, seem unrelated to this. Will look into it...

Comment on lines 27 to 28
// note: this test doesn't really fail; if it doesn't succeed, then
// the runner hangs. I don't know how to solve that.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update this description?

@Bromeon Bromeon force-pushed the alias-class-definitions branch 2 times, most recently from 83ca3e1 to e98d16f Compare September 30, 2023 08:39
There's an issue that two structs with the same name in different
modules will conflict with each other when sent to Godot since only the
struct name is considered.  This resolves that by allowing the API user
to manually change the name of the class as Godot understands it.  This
also improves the error message that occurs when there are aliased
classes.

Future work may seek to catch this issue at compile time rather than at
runtime.
@Bromeon Bromeon added this pull request to the merge queue Oct 3, 2023
Merged via the queue into godot-rust:master with commit 88a7934 Oct 3, 2023
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: register Register classes, functions and other symbols to GDScript feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Classname Alias
3 participants