gdnative_derive/
lib.rs

1extern crate proc_macro;
2extern crate proc_macro2;
3#[macro_use]
4extern crate syn;
5#[macro_use]
6extern crate quote;
7
8use proc_macro::TokenStream;
9use proc_macro2::TokenStream as TokenStream2;
10use quote::ToTokens;
11use syn::{parse::Parser, AttributeArgs, DeriveInput, ItemFn, ItemImpl, ItemType};
12
13mod methods;
14mod native_script;
15mod profiled;
16mod syntax;
17mod utils;
18mod varargs;
19mod variant;
20
21/// Collects method signatures of all functions in a `NativeClass` that have the `#[method]`
22/// attribute and registers them with Godot.
23///
24/// The `#[methods]` attribute can be used with both `impl Type` and `impl Trait for Type`
25/// blocks. The semantics change depending on whether a mix-in name is provided for the block.
26///
27/// ## Universal `impl` blocks: `#[methods]`
28///
29/// An `impl` block that doesn't have a `mixin` parameter is universal. Universal `#[methods]`
30/// blocks **must not overlap**. Usually, this means that **only one** `impl` block per struct
31/// may be universal.
32///
33/// When applied to a generic `impl`, the `impl` block must apply to **all** monomorphizations
34/// of the type, i.e. be *universal*.
35///
36/// One applicable universal block must be present for each type one wishes to use as a
37/// `NativeClass`. Universal blocks are always registered automatically.
38///
39/// ## Mix-ins: `#[methods(mixin = "Name")]`
40///
41/// When given a name with the `mixin` argument, a block behaves instead as a mix-in block.
42/// `#[method(mixin = "Name")]` creates an opaque type called `Name` under the current scope,
43/// that can be manually registered to any type the `impl` block covers. This can be done in
44/// a `register_with` callback with `builder.mixin::<MyMixin>()`.
45///
46/// Unlike universal blocks, mix-in blocks have a **many-to-many** relationship with the types
47/// they are registered to. Any number of mix-ins can be applied to any number of compatible
48/// types. This can be useful for reusing generics `impl`s, or organizing code for big interfaces.
49///
50/// Additionally, the attribute accepts the following arguments:
51///
52/// - `#[methods(pub)]`<br>
53/// Mix-in types are private by default. The `pub` argument makes them public instead.
54///
55/// ## Example
56///
57/// ### Universal
58///
59/// ```
60/// use gdnative::prelude::*;
61///
62/// #[derive(NativeClass)]
63/// #[inherit(Reference)]
64/// #[no_constructor]
65/// struct Foo {}
66///
67/// #[methods]
68/// impl Foo {
69///     #[method]
70///     fn foo(&self, #[base] _base: &Reference, bar: i64) -> i64 {
71///         bar
72///     }
73/// }
74///
75/// ```
76///
77/// ### Mix-in
78///
79/// ```
80/// use gdnative::prelude::*;
81///
82/// #[derive(NativeClass)]
83/// #[inherit(Reference)]
84/// #[register_with(register_foo)]
85/// #[no_constructor]
86/// struct Foo {}
87///
88/// fn register_foo(builder: &ClassBuilder<Foo>) {
89///     builder.mixin::<FooMixin>();
90/// }
91///
92/// #[methods(mixin = "FooMixin")]
93/// impl Foo {
94///     #[method]
95///     fn foo(&self, #[base] _base: &Reference, bar: i64) -> i64 {
96///         bar
97///     }
98/// }
99/// ```
100#[proc_macro_attribute]
101pub fn methods(meta: TokenStream, input: TokenStream) -> TokenStream {
102    let args =
103        match syn::punctuated::Punctuated::<syn::NestedMeta, syn::Token![,]>::parse_terminated
104            .parse(meta)
105        {
106            Ok(args) => args.into_iter().collect::<Vec<_>>(),
107            Err(err) => return error_with_input(input, err),
108        };
109
110    let impl_block = match syn::parse::<ItemImpl>(input.clone()) {
111        Ok(impl_block) => impl_block,
112        Err(err) => return error_with_input(input, err),
113    };
114
115    fn error_with_input(input: TokenStream, err: syn::Error) -> TokenStream {
116        let mut err = TokenStream::from(err.to_compile_error());
117        err.extend(std::iter::once(input));
118        err
119    }
120
121    match methods::derive_methods(args, impl_block) {
122        Ok(ts) => ts.into(),
123        Err(err) => error_with_input(input, err),
124    }
125}
126
127/// Makes a function profiled in Godot's built-in profiler. This macro automatically
128/// creates a tag using the name of the current module and the function by default.
129///
130/// This attribute may also be used on non-exported functions. If the GDNative API isn't
131/// initialized when the function is called, the data will be ignored silently.
132///
133/// A custom tag can also be provided using the `tag` option.
134///
135/// See the `gdnative::export::profiler` for a lower-level API to the profiler with
136/// more control.
137///
138/// # Examples
139///
140/// ```ignore
141/// mod foo {
142///     // This function will show up as `foo/bar` under Script Functions.
143///     #[profiled]
144///     fn bar() {
145///         std::thread::sleep(std::time::Duration::from_millis(1));
146///     }
147/// }
148/// ```
149///
150/// ```ignore
151/// // This function will show up as `my_custom_tag` under Script Functions.
152/// #[profiled(tag = "my_custom_tag")]
153/// fn baz() {
154///     std::thread::sleep(std::time::Duration::from_millis(1));
155/// }
156/// ```
157#[proc_macro_attribute]
158pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream {
159    let args = parse_macro_input!(meta as AttributeArgs);
160    let item_fn = parse_macro_input!(input as ItemFn);
161
162    match profiled::derive_profiled(args, item_fn) {
163        Ok(tokens) => tokens.into(),
164        Err(err) => err.to_compile_error().into(),
165    }
166}
167
168/// Makes it possible to use a type as a NativeScript. Automatically registers the type
169/// if the `inventory` feature is enabled on supported platforms.
170///
171/// ## Type attributes
172///
173/// The behavior of the derive macro can be customized using attributes on the type
174/// deriving `NativeClass`. All type attributes are optional.
175///
176/// ### `#[inherit(gdnative::api::BaseClass)]`
177///
178/// Sets `gdnative::api::BaseClass` as the base class for the script. This *must* be
179/// a type from the generated Godot API (that implements `GodotObject`). All `owner`
180/// arguments of exported methods must be references (`TRef`, `Ref`, or `&`) to this
181/// type.
182///
183/// Inheritance from other scripts, either in Rust or other languages, is
184/// not supported.
185///
186/// If no `#[inherit(...)]` is provided, [`gdnative::api::Reference`](../gdnative/api/struct.Reference.html)
187/// is used as a base class. This behavior is consistent with GDScript: omitting the
188/// `extends` keyword will inherit `Reference`.
189///
190///
191/// ### `#[user_data(gdnative::user_data::SomeWrapper<Self>)]`
192///
193/// Use the given type as the user-data wrapper. See the module-level docs on
194/// `gdnative::user_data` for more information.
195///
196/// ### `#[register_with(path::to::function)]`
197///
198/// Use a custom function to register signals, properties or methods, in addition
199/// to the one generated by `#[methods]`:
200///
201/// ```
202/// use gdnative::prelude::*;
203/// use gdnative::export::hint::{RangeHint, FloatHint};
204///
205/// #[derive(NativeClass)]
206/// #[inherit(Reference)]
207/// #[register_with(Self::my_register_function)]
208/// struct Foo;
209///
210/// #[methods]
211/// impl Foo {
212///     fn new(_: &Reference) -> Self {
213///         Self {}
214///     }
215///     fn my_register_function(builder: &ClassBuilder<Foo>) {
216///         builder.signal("my_sig").done();
217///         builder.property::<f32>("my_prop")
218///             .with_getter(|_, _| 42.0)
219///             .with_hint(FloatHint::Range(RangeHint::new(0.0, 100.0)))
220///             .done();
221///     }
222/// }
223/// ```
224///
225/// ### `#[no_constructor]`
226///
227/// Indicates that this type has no zero-argument constructor. Instances of such
228/// scripts can only be created from Rust using `Instance::emplace`. `Instance::new`
229/// or `ScriptName.new` from GDScript will result in panics at runtime.
230///
231/// See documentation on `Instance::emplace` for an example on how this can be used.
232///
233///
234/// ## Field attributes
235///
236/// All field attributes are optional.
237///
238/// ### `#[property]`
239///
240/// Convenience attribute to register a field as a property. Possible arguments for
241/// the attribute are:
242///
243/// - `path = "my_category/my_property_name"`
244///
245///   Puts the property under the `my_category` category and renames it to
246///   `my_property_name` in the inspector and for GDScript.
247///
248/// - `default = 42.0`
249///
250///   Sets the default value *in the inspector* for this property. The setter is *not*
251///   guaranteed to be called by the engine with the value.
252///
253/// - `get` / `get_ref` / `set`
254///
255///   Configure getter/setter for property. All of them can accept a path to specify a custom
256///   property accessor. For example, `#[property(get = "Self::my_getter")]` will use
257///   `Self::my_getter` as the getter.
258///
259///   The difference of `get` and `get_ref` is that `get` will register the getter with
260///   `with_getter` function, which means your getter should return an owned value `T`, but
261///   `get_ref` use `with_ref_getter` to register getter. In this case, your custom getter
262///   should return a shared reference `&T`.
263///
264///   Situations with custom getters/setters and no backing fields require the use of the
265///   type [`Property<T>`][gdnative::export::Property]. Consult its documentation for
266///   a deeper elaboration of property exporting.
267///
268/// - `no_editor`
269///
270///   Hides the property from the editor. Does not prevent it from being sent over network or saved in storage.
271///
272/// - `rpc = "selected_rpc"`
273///
274///   Sets the [Multiplayer API RPC Mode](https://docs.godotengine.org/en/stable/classes/class_multiplayerapi.html?highlight=RPC#enumerations) for the property.
275///   See the `#[method]` documentation below for possible values and their semantics.
276///
277/// ### `#[methods]`
278/// Adds the necessary information to a an `impl` block to register the properties and methods with Godot.
279///
280/// One and only one universal `impl` block must be available for each `NativeClass`
281/// monomorphization, along with any number of additional mix-ins. See [`methods`](attr.methods.html)
282/// for more information.
283///
284/// ### `#[method]`
285/// Registers the attributed function signature to be used by Godot.
286///
287/// This attribute was formerly called `#[export]`, but is not directly related to the concept of
288/// [exporting](https://docs.godotengine.org/en/stable/tutorials/export/exporting_basics.html) in GDScript.
289///
290/// A valid function signature must have:
291/// - `self`, `&self` or `&mut self` as its first parameter, if applicable.
292/// - Up of one of each of the following special arguments, in any order, denoted by the attributes:
293///     - `#[base]` - A reference to the base/owner object. This may be `&T` or `TRef<T>`m where `T` refers to
294///       the type declared in `#[inherit(T)]` attribute for the `NativeClass` type.
295///     - `#[async_ctx]` - The [async context](gdnative::tasks::Context), for async methods. See the `async` argument
296///       below.
297/// - Any number of required parameters, which must have the type `Variant` or must implement the `FromVariant` trait.
298///  `FromVariant` is implemented for most common types.
299/// - Any number of optional parameters annotated with `#[opt]`. Same rules as for required parameters apply.
300///   Optional parameters must appear at the end of the parameter list.
301/// - Return values must implement the `OwnedToVariant` trait (automatically implemented by `ToVariant`)
302///   or be a `Variant` type.
303///
304/// ```ignore
305/// // Associated function
306/// #[method]
307/// fn foo();
308///
309/// // No access to base parameter
310/// #[method]
311/// fn foo(&self);
312///
313/// // Access base parameter as &T
314/// #[method]
315/// fn foo(&self, #[base] base: &Reference);
316///
317/// // Access base parameter as TRef<T>
318/// #[method]
319/// fn foo(&self, #[base] base: TRef<Reference>);
320///
321/// // Access only the async context. Both variations are valid.
322/// #[method]
323/// async fn foo(#[async_ctx] ctx: Arc<Context>);
324/// #[method(async)]
325/// fn foo(#[async_ctx] ctx: Arc<Context>) -> impl Future<Output = ()> + 'static;
326///
327/// // Access the base parameter as TRef<T>, and the async context. Both variations are valid.
328/// // Note the absence of `async fn`s here: this is due to a current limitation in Rust's lifetime elision rules.
329/// // See the `async` attribute argument down below for more details.
330/// #[method(async)]
331/// fn foo(&self, #[base] base: TRef<Reference>, #[async_ctx] ctx: Arc<Context>) -> impl Future<Output = ()> + 'static;
332/// #[method(async)]
333/// fn foo(&self, #[async_ctx] ctx: Arc<Context>, #[base] base: TRef<Reference>) -> impl Future<Output = ()> + 'static;
334/// ```
335///
336/// **Note**: Marking a function with `#[method]` does not have any effect unless inside an `impl` block that has the `#[methods]` attribute.
337///
338/// Possible arguments for this attribute are:
339///
340/// - `name = "overridden_function_name"`
341///
342///   Overrides the function name as the method name to be registered in Godot.
343///
344/// - `rpc = "selected_rpc"`
345///
346///   `"selected_rpc"` must be one of the following values, which refer to the associated [Multiplayer API RPC Mode](https://docs.godotengine.org/en/stable/classes/class_multiplayerapi.html?highlight=RPC#enumerations).
347///   See also the Rust type [`export::RpcMode`].
348///     - `"disabled"`
349///     - `"remote"`
350///     - `"remote_sync"`
351///     - `"master"`
352///     - `"master_sync"`
353///     - `"puppet"`
354///     - `"puppet_sync"`
355///
356///   This enables you to set the [Multiplayer API RPC Mode](https://docs.godotengine.org/en/stable/classes/class_multiplayerapi.html?highlight=RPC#enumerations) for the function.
357///   Refer to [Godot's Remote Procedure documentation](https://docs.godotengine.org/en/stable/tutorials/networking/high_level_multiplayer.html#rpc) for more details.
358///
359/// - `deref_return`
360///
361///   Allows you to return a type using its `Deref` representation. This can avoid extra intermediate copies for larger objects, by explicitly
362///   returning a reference (or in general, a type that dereferences to something that can be exported).
363///
364///   For example:
365///   ```ignore
366///   #[method(deref_return)]
367///   fn get_numbers(&self) -> std::cell::Ref<Vec<i32>> {
368///      // Assume self.cell is std::cell::RefCell<Vec<i32>>
369///      self.cell.borrow()
370///   }
371///   ```
372///
373/// - `async`
374///
375///   Marks the function as async. This is used for functions that aren't `async` themselves, but return `Future`s instead.
376///   This is especially useful for working around Rust's lifetime elision rules, which put the lifetime of `&self` into the
377///   return value for `async fn`s. The `impl Future` syntax instead allows one to explicitly specify a `'static` lifetime,
378///   as required by the async runtime:
379///
380///   ```ignore
381///   // This will NOT compile: Rust assumes that any futures returned by an `async fn` may only live as long as each of its
382///   // arguments, and there is no way to tell it otherwise. As a result, it will emit some cryptic complaints about lifetime.
383///   #[method]
384///   async fn answer(&self) -> i32 {
385///      42
386///   }
387///
388///   // This, however, compiles, thanks to the explicit `'static` lifetime in the return signature.
389///   #[method(async)]
390///   fn answer(&self) -> impl Future<Output = i32> + 'static {
391///      async { 42 }
392///   }
393///
394///   ```
395///
396///
397/// #### `Node` virtual functions
398///
399/// This is a list of common Godot virtual functions that are automatically called via [notifications](https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-notification).
400///
401/// It is assumed that every method is exported via `#[method]` attribute. The parameter `#[base] base: &Node` can be omitted if you don't need it.
402///
403/// ```ignore
404/// fn _ready(&self, #[base] base: &Node);
405/// ```
406/// Called when both the node and its children have entered the scene tree.  
407/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-ready) for more information._
408/// <br><br>
409///
410/// ```ignore
411/// fn _enter_tree(&self, #[base] base: &Node);
412/// ```
413/// Called when the node enters the scene tree.  
414/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-enter-tree) for more information._
415/// <br><br>
416///
417/// ```ignore
418/// fn _exit_tree(&self, #[base] base: &Node);
419/// ```
420/// Called when the node is removed from the scene tree.  
421/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-exit-tree) for more information._
422/// <br><br>
423///
424/// ```ignore
425/// fn _get_configuration_warning(&self, #[base] base: &Node) -> GodotString;
426/// ```
427/// The string returned from this method is displayed as a warning in the Scene Dock if the script that overrides it is a tool script.  
428/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-get-configuration-warning) for more information._
429/// <br><br>
430///
431/// ```ignore
432/// fn _process(&mut self, #[base] base: &Node, delta: f64);
433/// ```
434/// Called during processing step of the main loop.  
435/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-process) for more information._
436/// <br><br>
437///
438/// ```ignore
439/// fn _physics_process(&self, #[base] base: &Node, delta: f64);
440/// ```
441/// Called during physics update, with a fixed timestamp.  
442/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-physics-process) for more information._
443/// <br><br>
444///
445/// ```ignore
446/// fn _input(&self, #[base] base: &Node, event: Ref<InputEvent>);
447/// ```
448/// Called when there is an input event.  
449/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-input) for more information._
450/// <br><br>
451///
452/// ```ignore
453/// fn _unhandled_input(&self, #[base] base: &Node, event: Ref<InputEvent>);
454/// ```
455/// Called when an `InputEvent` hasn't been consumed by `_input()` or any GUI.  
456/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-unhandled-input) for more information._
457/// <br><br>
458///
459/// ```ignore
460/// fn _unhandled_key_input (&self, #[base] base: &Node, event: Ref<InputKeyEvent>);
461/// ```
462/// Called when an `InputEventKey` hasn't been consumed by `_input()` or any GUI.  
463/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-unhandled-key-input) for more information._
464/// <br><br>
465///
466/// #### `Control` virtual functions
467///
468/// This is a list of common Godot virtual functions that are automatically called via [notifications](https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-notification).
469///
470/// ```ignore
471/// fn _clips_input(&self, #[base] base: &Control) -> bool;
472/// ```
473/// Returns whether `_gui_input()` should not be called for children controls outside this control's rectangle.  
474/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_control.html#class-control-method-clips-input) for more information._
475/// <br><br>
476///
477/// ```ignore
478/// fn _get_minimum_size(&self, #[base] base: &Control) -> Vector2;
479/// ```
480/// Returns the minimum size for this control.  
481/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_control.html#class-control-method-get-minimum-size) for more information._
482/// <br><br>
483///
484/// ```ignore
485/// fn _gui_input(&self, #[base] base: &Control, event: Ref<InputEvent>);
486/// ```
487/// Use this method to process and accept inputs on UI elements.  
488/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_control.html#class-control-method-gui-input) for more information._
489/// <br><br>
490///
491/// ```ignore
492/// fn _make_custom_tooltip(&self, #[base] base: &Control, for_text: String) -> Ref<Control>;
493/// ```
494/// Returns a `Control` node that should be used as a tooltip instead of the default one.  
495/// _See [Godot docs](https://docs.godotengine.org/en/stable/classes/class_control.html#class-control-method-make-custom-tooltip) for more information._
496/// <br><br>
497#[proc_macro_derive(
498    NativeClass,
499    attributes(inherit, register_with, no_constructor, user_data, property)
500)]
501pub fn derive_native_class(input: TokenStream) -> TokenStream {
502    // Converting the proc_macro::TokenStream into non proc_macro types so that tests
503    // can be written against the inner functions.
504    let derive_input = syn::parse_macro_input!(input as DeriveInput);
505
506    // Implement NativeClass for the input
507    let derived = native_script::derive_native_class(&derive_input).map_or_else(
508        |err| {
509            // Silence the other errors that happen because NativeClass is not implemented
510            let empty_nativeclass = native_script::impl_empty_nativeclass(&derive_input);
511            let err = err.to_compile_error();
512
513            quote! {
514                #empty_nativeclass
515                #err
516            }
517        },
518        std::convert::identity,
519    );
520
521    TokenStream::from(derived)
522}
523
524/// Wires up necessary internals for a concrete monomorphization of a generic `NativeClass`,
525/// represented as a type alias, so it can be registered.
526///
527/// The monomorphized type will be available to Godot under the name of the type alias,
528/// once registered.  Automatically registers the type if the `inventory` feature is enabled on
529/// supported platforms.
530///
531/// For more context, please refer to [gdnative::derive::NativeClass](NativeClass).
532///
533/// ## Type attributes
534///
535/// The behavior of the attribute can be customized using additional attributes on the type
536/// alias. All type attributes are optional.
537///
538/// ### `#[register_with(path::to::function)]`
539///
540/// Use a custom function to register signals, properties or methods, in addition
541/// to the one generated by a universal `#[methods]` block on the generic type.
542/// This can be used to register extra mix-ins that apply to the specific monomorphization.
543#[proc_macro_attribute]
544pub fn monomorphize(meta: TokenStream, input: TokenStream) -> TokenStream {
545    let args = parse_macro_input!(meta as AttributeArgs);
546    let item_type = parse_macro_input!(input as ItemType);
547
548    match native_script::derive_monomorphize(args, item_type) {
549        Ok(tokens) => tokens.into(),
550        Err(err) => err.to_compile_error().into(),
551    }
552}
553
554#[proc_macro_derive(ToVariant, attributes(variant))]
555pub fn derive_to_variant(input: TokenStream) -> TokenStream {
556    match variant::derive_to_variant(variant::ToVariantTrait::ToVariant, input) {
557        Ok(stream) => stream.into(),
558        Err(err) => err.to_compile_error().into(),
559    }
560}
561
562#[proc_macro_derive(OwnedToVariant, attributes(variant))]
563pub fn derive_owned_to_variant(input: TokenStream) -> TokenStream {
564    match variant::derive_to_variant(variant::ToVariantTrait::OwnedToVariant, input) {
565        Ok(stream) => stream.into(),
566        Err(err) => err.to_compile_error().into(),
567    }
568}
569
570#[proc_macro_derive(FromVariant, attributes(variant))]
571pub fn derive_from_variant(input: TokenStream) -> TokenStream {
572    let derive_input = syn::parse_macro_input!(input as syn::DeriveInput);
573    match variant::derive_from_variant(derive_input) {
574        Ok(stream) => stream.into(),
575        Err(err) => err.to_compile_error().into(),
576    }
577}
578
579/// Enable struct types to be parsed as argument lists.
580///
581/// The `FromVarargs` trait can be derived for structure types where each type implements
582/// `FromVariant`. The order of fields matter for this purpose:
583///
584/// ```ignore
585/// #[derive(FromVarargs)]
586/// struct MyArgs {
587///     foo: i32,
588///     bar: String,
589///     #[opt] baz: Option<Ref<Node>>,
590/// }
591/// ```
592///
593/// ## Field attributes
594///
595/// Attributes can be used to customize behavior of certain fields. All attributes are optional.
596///
597/// ### `#[opt]`
598///
599/// Marks an argument as optional. Required arguments must precede all optional arguments.
600/// Default values are obtained through `Default::default`.
601///
602/// ### `#[skip]`
603///
604/// Instructs the macro to skip a field. Skipped fields do not affect the signature of the
605/// argument list. They may be located anywhere. Values are obtained through `Default::default`.
606#[proc_macro_derive(FromVarargs, attributes(opt, skip))]
607pub fn derive_from_varargs(input: TokenStream) -> TokenStream {
608    let derive_input = syn::parse_macro_input!(input as syn::DeriveInput);
609    match varargs::derive_from_varargs(derive_input) {
610        Ok(stream) => stream.into(),
611        Err(err) => err.to_compile_error().into(),
612    }
613}
614
615/// Convenience macro to wrap an object's method into a `Method` implementor
616/// that can be passed to the engine when registering a class.
617#[proc_macro]
618#[deprecated = "The legacy manual export macro is deprecated and will be removed in a future godot-rust version. \
619Either use the `#[methods]` attribute macro, or implement the `Method` trait manually instead."]
620pub fn godot_wrap_method(input: TokenStream) -> TokenStream {
621    match methods::expand_godot_wrap_method(input.into()) {
622        Ok(stream) => stream.into(),
623        Err(xs) => {
624            let mut tokens = TokenStream2::new();
625            for err in xs {
626                tokens.extend(err.to_compile_error());
627            }
628            tokens.into()
629        }
630    }
631}
632
633/// Returns a standard header for derived implementations.
634///
635/// Adds the `automatically_derived` attribute and prevents common lints from triggering
636/// in user code. See:
637///
638/// - https://doc.rust-lang.org/reference/attributes/derive.html
639/// - https://doc.rust-lang.org/rustc/lints/groups.html
640/// - https://github.com/rust-lang/rust-clippy#clippy
641fn automatically_derived() -> proc_macro2::TokenStream {
642    quote! {
643        #[automatically_derived]
644        #[allow(nonstandard_style, unused, clippy::style, clippy::complexity, clippy::perf, clippy::pedantic)]
645    }
646}
647
648/// Returns the (possibly renamed or imported as `gdnative`) identifier of the `gdnative_core` crate.
649fn crate_gdnative_core() -> proc_macro2::TokenStream {
650    let found_crate = proc_macro_crate::crate_name("gdnative-core")
651        .or_else(|_| proc_macro_crate::crate_name("gdnative"))
652        .expect("crate not found");
653
654    match found_crate {
655        proc_macro_crate::FoundCrate::Itself => {
656            // Workaround: `proc-macro-crate` returns `Itself` in doc-tests, and refuses to use unstable env
657            // variables for detection.
658            // See https://github.com/bkchr/proc-macro-crate/issues/11
659            if std::env::var_os("UNSTABLE_RUSTDOC_TEST_PATH").is_some() {
660                quote!(gdnative_core)
661            } else {
662                quote!(crate)
663            }
664        }
665        proc_macro_crate::FoundCrate::Name(name) => {
666            let ident = proc_macro2::Ident::new(&name, proc_macro2::Span::call_site());
667            ident.to_token_stream()
668        }
669    }
670}
671
672/// Returns the (possibly renamed or imported as `gdnative`) identifier of the `gdnative_async` crate,
673/// if found.
674fn crate_gdnative_async() -> proc_macro2::TokenStream {
675    if let Ok(found_crate) = proc_macro_crate::crate_name("gdnative-async") {
676        return match found_crate {
677            proc_macro_crate::FoundCrate::Itself => quote!(crate),
678            proc_macro_crate::FoundCrate::Name(name) => {
679                let ident = proc_macro2::Ident::new(&name, proc_macro2::Span::call_site());
680                ident.to_token_stream()
681            }
682        };
683    }
684
685    let found_crate = proc_macro_crate::crate_name("gdnative").expect("crate not found");
686
687    match found_crate {
688        proc_macro_crate::FoundCrate::Itself => quote!(crate::tasks),
689        proc_macro_crate::FoundCrate::Name(name) => {
690            let ident = proc_macro2::Ident::new(&name, proc_macro2::Span::call_site());
691            quote!( #ident::tasks )
692        }
693    }
694}
695
696/// Returns the (possibly renamed or imported as `gdnative`) identifier of the `gdnative_bindings` crate.
697fn crate_gdnative_bindings() -> proc_macro2::TokenStream {
698    if let Ok(found_crate) = proc_macro_crate::crate_name("gdnative-bindings") {
699        return match found_crate {
700            proc_macro_crate::FoundCrate::Itself => quote!(crate),
701            proc_macro_crate::FoundCrate::Name(name) => {
702                let ident = proc_macro2::Ident::new(&name, proc_macro2::Span::call_site());
703                ident.to_token_stream()
704            }
705        };
706    }
707
708    let found_crate = proc_macro_crate::crate_name("gdnative").expect("crate not found");
709
710    match found_crate {
711        proc_macro_crate::FoundCrate::Itself => quote!(crate::api),
712        proc_macro_crate::FoundCrate::Name(name) => {
713            let ident = proc_macro2::Ident::new(&name, proc_macro2::Span::call_site());
714            quote!( #ident::api )
715        }
716    }
717}
718
719/// Hack to emit a warning in expression position through `deprecated`.
720/// This is because there is no way to emit warnings from macros in stable Rust.
721fn emit_warning<S: std::fmt::Display>(
722    span: proc_macro2::Span,
723    warning_name: &str,
724    message: S,
725) -> proc_macro2::TokenStream {
726    let warning_name = proc_macro2::Ident::new(warning_name, span);
727    let message = message.to_string();
728
729    quote_spanned! { span =>
730        {
731            #[deprecated = #message]
732            fn #warning_name() {}
733            #warning_name()
734        }
735    }
736}