@@ -21,8 +21,12 @@ pub fn derive_godot_class(item: venial::Item) -> ParseResult<TokenStream> {
21
21
. ok_or_else ( || venial:: Error :: new ( "Not a valid struct" ) ) ?;
22
22
23
23
let named_fields = named_fields ( class) ?;
24
- let struct_cfg = parse_struct_attributes ( class) ?;
25
- let fields = parse_fields ( named_fields, struct_cfg. init_strategy ) ?;
24
+ let mut struct_cfg = parse_struct_attributes ( class) ?;
25
+ let mut fields = parse_fields ( named_fields, struct_cfg. init_strategy ) ?;
26
+ let is_editor_plugin = struct_cfg. is_editor_plugin ( ) ;
27
+
28
+ let mut deprecations = std:: mem:: take ( & mut struct_cfg. deprecations ) ;
29
+ deprecations. append ( & mut fields. deprecations ) ;
26
30
27
31
let class_name = & class. name ;
28
32
let class_name_str: String = struct_cfg
@@ -33,8 +37,7 @@ pub fn derive_godot_class(item: venial::Item) -> ParseResult<TokenStream> {
33
37
let class_name_cstr = util:: c_str ( & class_name_str) ;
34
38
let class_name_obj = util:: class_name_obj ( class_name) ;
35
39
36
- let is_editor_plugin = struct_cfg. is_editor_plugin ;
37
- let is_hidden = struct_cfg. is_hidden ;
40
+ let is_internal = struct_cfg. is_internal ;
38
41
let base_ty = & struct_cfg. base_ty ;
39
42
#[ cfg( all( feature = "docs" , since_api = "4.3" ) ) ]
40
43
let docs = crate :: docs:: make_definition_docs (
@@ -75,7 +78,6 @@ pub fn derive_godot_class(item: venial::Item) -> ParseResult<TokenStream> {
75
78
let mut create_fn = quote ! { None } ;
76
79
let mut recreate_fn = quote ! { None } ;
77
80
let mut is_instantiable = true ;
78
- let deprecations = & fields. deprecations ;
79
81
80
82
match struct_cfg. init_strategy {
81
83
InitStrategy :: Generated => {
@@ -153,7 +155,7 @@ pub fn derive_godot_class(item: venial::Item) -> ParseResult<TokenStream> {
153
155
default_get_virtual_fn: #default_get_virtual_fn,
154
156
is_tool: #is_tool,
155
157
is_editor_plugin: #is_editor_plugin,
156
- is_hidden : #is_hidden ,
158
+ is_internal : #is_internal ,
157
159
is_instantiable: #is_instantiable,
158
160
#docs
159
161
} ,
@@ -201,9 +203,15 @@ struct ClassAttributes {
201
203
base_ty : Ident ,
202
204
init_strategy : InitStrategy ,
203
205
is_tool : bool ,
204
- is_editor_plugin : bool ,
205
- is_hidden : bool ,
206
+ is_internal : bool ,
206
207
rename : Option < Ident > ,
208
+ deprecations : Vec < TokenStream > ,
209
+ }
210
+
211
+ impl ClassAttributes {
212
+ fn is_editor_plugin ( & self ) -> bool {
213
+ self . base_ty == ident ( "EditorPlugin" )
214
+ }
207
215
}
208
216
209
217
fn make_godot_init_impl ( class_name : & Ident , fields : & Fields ) -> TokenStream {
@@ -310,9 +318,9 @@ fn parse_struct_attributes(class: &venial::Struct) -> ParseResult<ClassAttribute
310
318
let mut base_ty = ident ( "RefCounted" ) ;
311
319
let mut init_strategy = InitStrategy :: UserDefined ;
312
320
let mut is_tool = false ;
313
- let mut is_editor_plugin = false ;
314
- let mut is_hidden = false ;
321
+ let mut is_internal = false ;
315
322
let mut rename: Option < Ident > = None ;
323
+ let mut deprecations = vec ! [ ] ;
316
324
317
325
// #[class] attribute on struct
318
326
if let Some ( mut parser) = KvParser :: parse ( & class. attributes , "class" ) ? {
@@ -333,50 +341,45 @@ fn parse_struct_attributes(class: &venial::Struct) -> ParseResult<ClassAttribute
333
341
is_tool = true ;
334
342
}
335
343
336
- // #[class(editor_plugin)]
337
- if let Some ( attr_key) = parser. handle_alone_with_span ( "editor_plugin" ) ? {
338
- is_editor_plugin = true ;
339
-
340
- // Requires #[class(tool, base=EditorPlugin)].
341
- // The base=EditorPlugin check should come first to create the best compile errors since it's more complex to resolve.
342
- // See https://github.com/godot-rust/gdext/pull/773
343
- if base_ty != ident ( "EditorPlugin" ) {
344
- return bail ! (
345
- attr_key,
346
- "#[class(editor_plugin)] requires additional key-value `base=EditorPlugin`"
347
- ) ;
348
- }
349
- if !is_tool {
350
- return bail ! (
351
- attr_key,
352
- "#[class(editor_plugin)] requires additional key `tool`"
353
- ) ;
354
- }
344
+ // Deprecated #[class(editor_plugin)]
345
+ if let Some ( _attr_key) = parser. handle_alone_with_span ( "editor_plugin" ) ? {
346
+ deprecations. push ( quote ! {
347
+ :: godot:: __deprecated:: emit_deprecated_warning!( class_editor_plugin) ;
348
+ } ) ;
355
349
}
356
350
357
351
// #[class(rename = NewName)]
358
352
rename = parser. handle_ident ( "rename" ) ?;
359
353
360
- // #[class(hidden)]
361
- // TODO consider naming this "internal"; godot-cpp uses that terminology:
362
- // https://github.com/godotengine/godot-cpp/blob/master/include/godot_cpp/core/class_db.hpp#L327
354
+ // #[class(internal)]
355
+ // Named "internal" following Godot terminology: https://github.com/godotengine/godot-cpp/blob/master/include/godot_cpp/core/class_db.hpp#L327
356
+ if let Some ( span) = parser. handle_alone_with_span ( "internal" ) ? {
357
+ require_api_version ! ( "4.2" , span, "#[class(internal)]" ) ?;
358
+ is_internal = true ;
359
+ }
360
+
361
+ // Deprecated #[class(hidden)]
363
362
if let Some ( span) = parser. handle_alone_with_span ( "hidden" ) ? {
364
363
require_api_version ! ( "4.2" , span, "#[class(hidden)]" ) ?;
365
- is_hidden = true ;
364
+ is_internal = true ;
365
+
366
+ deprecations. push ( quote ! {
367
+ :: godot:: __deprecated:: emit_deprecated_warning!( class_hidden) ;
368
+ } ) ;
366
369
}
367
370
368
371
parser. finish ( ) ?;
369
372
}
370
373
371
- post_validate ( & base_ty, is_tool, is_editor_plugin ) ?;
374
+ post_validate ( & base_ty, is_tool) ?;
372
375
373
376
Ok ( ClassAttributes {
374
377
base_ty,
375
378
init_strategy,
376
379
is_tool,
377
- is_editor_plugin,
378
- is_hidden,
380
+ is_internal,
379
381
rename,
382
+ deprecations,
380
383
} )
381
384
}
382
385
@@ -561,7 +564,7 @@ fn handle_opposite_keys(
561
564
}
562
565
563
566
/// Checks more logical combinations of attributes.
564
- fn post_validate ( base_ty : & Ident , is_tool : bool , is_editor_plugin : bool ) -> ParseResult < ( ) > {
567
+ fn post_validate ( base_ty : & Ident , is_tool : bool ) -> ParseResult < ( ) > {
565
568
// TODO: this should be delegated to either:
566
569
// a) the type system: have a trait IsTool which is implemented when #[class(tool)] is set.
567
570
// Then, for certain base classes, require a tool bound (e.g. generate method `fn type_check<T: IsTool>()`).
@@ -579,12 +582,6 @@ fn post_validate(base_ty: &Ident, is_tool: bool, is_editor_plugin: bool) -> Pars
579
582
"Base class `{}` is a virtual extension class, which runs in the editor and thus requires #[class(tool)]." ,
580
583
base_ty
581
584
) ;
582
- } else if class_name == "EditorPlugin" && !is_editor_plugin {
583
- return bail ! (
584
- base_ty,
585
- "Classes extending `{}` require #[class(editor_plugin)] to get registered as a plugin in the editor. See: https://godot-rust.github.io/book/recipes/editor-plugin/index.html" ,
586
- base_ty
587
- ) ;
588
585
} else if is_class_editor && !is_tool {
589
586
return bail ! (
590
587
base_ty,
0 commit comments