-
-
Notifications
You must be signed in to change notification settings - Fork 198
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
Conversation
2ab8845
to
352f84a
Compare
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-419 |
There was a problem hiding this 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!
godot-core/src/registry.rs
Outdated
) | ||
.unwrap_or_else(|_| | ||
panic!( | ||
"the definition for `{}` is overloaded; you may have multiple `GodotClass`es named `{}` which you should #[class(rename=...)]", |
There was a problem hiding this comment.
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:
"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=...)]`", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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)
godot-macros/src/lib.rs
Outdated
@@ -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 |
There was a problem hiding this comment.
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.
godot-macros/src/lib.rs
Outdated
/// 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. |
There was a problem hiding this comment.
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)] |
There was a problem hiding this comment.
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)] |
There was a problem hiding this comment.
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.
#[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"); | ||
} |
There was a problem hiding this comment.
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 🙂
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Oh that's very annoying, noted! |
352f84a
to
b82d645
Compare
There was a problem hiding this 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...
godot-core/src/registry.rs
Outdated
) | ||
.unwrap_or_else(|_| | ||
panic!( | ||
"the definition for `{}` is overloaded; you may have multiple `GodotClass`es named `{}` which you should #[class(rename=...)]", |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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 🙂
Sorry about the conflicts, merging #393 caused some changes. |
d403c4c
to
83ca3e1
Compare
Sorry about that, forgot to stage most of the changes, woops. Should be good now, assuming the CI approves, |
Thank you! The CI errors now, in |
// note: this test doesn't really fail; if it doesn't succeed, then | ||
// the runner hangs. I don't know how to solve that. |
There was a problem hiding this comment.
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?
83ca3e1
to
e98d16f
Compare
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.
e98d16f
to
6e07b1d
Compare
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