diff --git a/godot-core/src/deprecated.rs b/godot-core/src/deprecated.rs index bde072132..00c88f4f8 100644 --- a/godot-core/src/deprecated.rs +++ b/godot-core/src/deprecated.rs @@ -37,6 +37,12 @@ pub use crate::emit_deprecated_warning; // ---------------------------------------------------------------------------------------------------------------------------------------------- // Library-side deprecations -- see usage description above. +#[deprecated = "\n\ + #[class(no_init, base=EditorPlugin)] will crash when opened in the editor.\n\ + EditorPlugin classes are automatically instantiated by Godot and require a default constructor.\n\ + Use #[class(init)] instead, or provide a custom init() function in the IEditorPlugin impl."] +pub const fn class_no_init_editor_plugin() {} + // ---------------------------------------------------------------------------------------------------------------------------------------------- // Godot-side deprecations (we may mark them deprecated but keep support). diff --git a/godot-macros/src/class/derive_godot_class.rs b/godot-macros/src/class/derive_godot_class.rs index e2b6533b4..b1696db12 100644 --- a/godot-macros/src/class/derive_godot_class.rs +++ b/godot-macros/src/class/derive_godot_class.rs @@ -290,7 +290,7 @@ pub fn make_existence_check(ident: &Ident) -> TokenStream { // ---------------------------------------------------------------------------------------------------------------------------------------------- // Implementation -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Eq, PartialEq)] enum InitStrategy { Generated, UserDefined, @@ -531,11 +531,12 @@ fn parse_struct_attributes(class: &venial::Struct) -> ParseResult - ::godot::__deprecated::emit_deprecated_warning!(class_editor_plugin); - }); + // Removed #[class(editor_plugin)] + if let Some(key) = parser.handle_alone_with_span("editor_plugin")? { + return bail!( + key, + "#[class(editor_plugin)] has been removed in favor of #[class(tool, base=EditorPlugin)]", + ); } // #[class(rename = NewName)] @@ -556,18 +557,24 @@ fn parse_struct_attributes(class: &venial::Struct) -> ParseResult - ::godot::__deprecated::emit_deprecated_warning!(class_hidden); - }); + // Removed #[class(hidden)] + if let Some(key) = parser.handle_alone_with_span("hidden")? { + return bail!( + key, + "#[class(hidden)] has been renamed to #[class(internal)]", + ); } parser.finish()?; } + // Deprecated: #[class(no_init)] with base=EditorPlugin + if matches!(init_strategy, InitStrategy::Absent) && base_ty == ident("EditorPlugin") { + deprecations.push(quote! { + ::godot::__deprecated::emit_deprecated_warning!(class_no_init_editor_plugin); + }); + } + post_validate(&base_ty, is_tool)?; Ok(ClassAttributes { @@ -587,6 +594,7 @@ fn parse_fields( ) -> ParseResult { let mut all_fields = vec![]; let mut base_field = Option::::None; + #[allow(unused_mut)] // Less chore when adding/removing deprecations. let mut deprecations = vec![]; let mut errors = vec![]; @@ -633,21 +641,12 @@ fn parse_fields( }); } - // Deprecated #[init(default = expr)] - if let Some((key, default)) = parser.handle_expr_with_key("default")? { - if field.default_val.is_some() { - return bail!( - key, - "Cannot use both `val` and `default` keys in #[init]; prefer using `val`" - ); - } - field.default_val = Some(FieldDefault { - default_val: default, - span: parser.span(), - }); - deprecations.push(quote_spanned! { parser.span()=> - ::godot::__deprecated::emit_deprecated_warning!(init_default); - }) + // Removed #[init(default = ...)] + if let Some((key, _default)) = parser.handle_expr_with_key("default")? { + return bail!( + key, + "#[init(default = ...)] has been renamed to #[init(val = ...)]", + ); } // #[init(node = "PATH")] diff --git a/itest/rust/src/object_tests/virtual_methods_test.rs b/itest/rust/src/object_tests/virtual_methods_test.rs index 27ea6e5f1..17fd5e610 100644 --- a/itest/rust/src/object_tests/virtual_methods_test.rs +++ b/itest/rust/src/object_tests/virtual_methods_test.rs @@ -738,7 +738,7 @@ impl GetSetTest { // There isn't a good way to test editor plugins, but we can at least declare one to ensure that the macro // compiles. #[derive(GodotClass)] -#[class(no_init, base = EditorPlugin, tool)] +#[class(init, base = EditorPlugin, tool)] struct CustomEditorPlugin; // Just override EditorPlugin::edit() to verify method is declared with Option.