@@ -7,6 +7,7 @@ extern crate quote;
77
88use proc_macro:: TokenStream ;
99use proc_macro2:: TokenStream as TokenStream2 ;
10+ use quote:: ToTokens ;
1011use syn:: { AttributeArgs , DeriveInput , ItemFn , ItemImpl } ;
1112
1213mod extend_bounds;
@@ -18,7 +19,12 @@ mod variant;
1819
1920/// Collects method signatures of all functions in a `NativeClass` that have the `#[method]` attribute and registers them with Godot.
2021///
21- /// For example, in the following class
22+ /// **Important**: Only one `impl` block per struct may be attributed with `#[methods]`.
23+ ///
24+ /// For more context, please refer to [gdnative::derive::NativeClass](NativeClass).
25+ ///
26+ /// ## Example
27+ ///
2228/// ```
2329/// use gdnative::prelude::*;
2430///
@@ -36,34 +42,6 @@ mod variant;
3642/// }
3743///
3844/// ```
39- /// Will expand to
40- /// ```
41- /// use gdnative::prelude::*;
42- /// struct Foo {}
43- /// impl NativeClass for Foo {
44- /// type Base = gdnative::api::Reference;
45- /// type UserData = gdnative::export::user_data::LocalCellData<Self>;
46- /// }
47- /// impl gdnative::export::StaticallyNamed for Foo {
48- /// const CLASS_NAME: &'static str = "Foo";
49- /// }
50- /// impl gdnative::export::NativeClassMethods for Foo {
51- /// fn nativeclass_register(builder: &ClassBuilder<Self>) {
52- /// use gdnative::export::*;
53- /// builder.method("foo", gdnative::export::godot_wrap_method!(Foo, false, fn foo(&self, #[base] _base: &Reference, bar: i64) -> i64))
54- /// .with_rpc_mode(RpcMode::Disabled)
55- /// .done_stateless();
56- /// }
57- /// }
58- /// impl Foo {
59- /// fn foo(&self, _owner: &Reference, bar: i64) -> i64 {
60- /// bar
61- /// }
62- /// }
63- /// ```
64- /// **Important**: Only one `impl` block per struct may be attributed with `#[methods]`.
65- ///
66- /// For more context, please refer to [gdnative::derive::NativeClass](NativeClass).
6745#[ proc_macro_attribute]
6846pub fn methods ( meta : TokenStream , input : TokenStream ) -> TokenStream {
6947 if syn:: parse :: < syn:: parse:: Nothing > ( meta. clone ( ) ) . is_err ( ) {
@@ -237,18 +215,19 @@ pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream {
237215///
238216/// **Important**: This needs to be added to one and only one `impl` block for a given `NativeClass`.
239217///
240- /// For additional details about how `#[methods]` expands, please refer to [gdnative::methods](macro@methods)
241- ///
242218/// ### `#[method]`
243219/// Registers the attributed function signature to be used by Godot.
244220///
245221/// This attribute was formerly called `#[export]`, but is not directly related to the concept of
246222/// [exporting](https://docs.godotengine.org/en/stable/tutorials/export/exporting_basics.html) in GDScript.
247223///
248224/// A valid function signature must have:
249- /// - `&self` or `&mut self` as its first parameter
250- /// - Optionally, `&T` or `TRef<T>` where T refers to the type declared in `#[inherit(T)]` attribute as it's second parameter;
251- /// this is typically called the _base_. The parameter must be attributed with `#[base]`.
225+ /// - `self`, `&self` or `&mut self` as its first parameter, if applicable.
226+ /// - Up of one of each of the following special arguments, in any order, denoted by the attributes:
227+ /// - `#[base]` - A reference to the base/owner object. This may be `&T` or `TRef<T>`m where `T` refers to
228+ /// the type declared in `#[inherit(T)]` attribute for the `NativeClass` type.
229+ /// - `#[async_ctx]` - The [async context](gdnative::tasks::Context), for async methods. See the `async` argument
230+ /// below.
252231/// - Any number of required parameters, which must have the type `Variant` or must implement the `FromVariant` trait.
253232/// `FromVariant` is implemented for most common types.
254233/// - Any number of optional parameters annotated with `#[opt]`. Same rules as for required parameters apply.
@@ -257,6 +236,10 @@ pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream {
257236/// or be a `Variant` type.
258237///
259238/// ```ignore
239+ /// // Associated function
240+ /// #[method]
241+ /// fn foo();
242+ ///
260243/// // No access to base parameter
261244/// #[method]
262245/// fn foo(&self);
@@ -268,6 +251,20 @@ pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream {
268251/// // Access base parameter as TRef<T>
269252/// #[method]
270253/// fn foo(&self, #[base] base: TRef<Reference>);
254+ ///
255+ /// // Access only the async context. Both variations are valid.
256+ /// #[method]
257+ /// async fn foo(#[async_ctx] ctx: Arc<Context>);
258+ /// #[method(async)]
259+ /// fn foo(#[async_ctx] ctx: Arc<Context>) -> impl Future<Output = ()> + 'static;
260+ ///
261+ /// // Access the base parameter as TRef<T>, and the async context. Both variations are valid.
262+ /// // Note the absence of `async fn`s here: this is due to a current limitation in Rust's lifetime elision rules.
263+ /// // See the `async` attribute argument down below for more details.
264+ /// #[method(async)]
265+ /// fn foo(&self, #[base] base: TRef<Reference>, #[async_ctx] ctx: Arc<Context>) -> impl Future<Output = ()> + 'static;
266+ /// #[method(async)]
267+ /// fn foo(&self, #[async_ctx] ctx: Arc<Context>, #[base] base: TRef<Reference>) -> impl Future<Output = ()> + 'static;
271268/// ```
272269///
273270/// **Note**: Marking a function with `#[method]` does not have any effect unless inside an `impl` block that has the `#[methods]` attribute.
@@ -307,6 +304,29 @@ pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream {
307304/// }
308305/// ```
309306///
307+ /// - `async`
308+ ///
309+ /// Marks the function as async. This is used for functions that aren't `async` themselves, but return `Future`s instead.
310+ /// This is especially useful for working around Rust's lifetime elision rules, which put the lifetime of `&self` into the
311+ /// return value for `async fn`s. The `impl Future` syntax instead allows one to explicitly specify a `'static` lifetime,
312+ /// as required by the async runtime:
313+ ///
314+ /// ```ignore
315+ /// // This will NOT compile: Rust assumes that any futures returned by an `async fn` may only live as long as each of its
316+ /// // arguments, and there is no way to tell it otherwise. As a result, it will emit some cryptic complaints about lifetime.
317+ /// #[method]
318+ /// async fn answer(&self) -> i32 {
319+ /// 42
320+ /// }
321+ ///
322+ /// // This, however, compiles, thanks to the explicit `'static` lifetime in the return signature.
323+ /// #[method(async)]
324+ /// fn answer(&self) -> impl Future<Output = i32> + 'static {
325+ /// async { 42 }
326+ /// }
327+ ///
328+ /// ```
329+ ///
310330///
311331/// #### `Node` virtual functions
312332///
@@ -525,7 +545,31 @@ fn crate_gdnative_core() -> proc_macro2::TokenStream {
525545 proc_macro_crate:: FoundCrate :: Itself => quote ! ( crate ) ,
526546 proc_macro_crate:: FoundCrate :: Name ( name) => {
527547 let ident = proc_macro2:: Ident :: new ( & name, proc_macro2:: Span :: call_site ( ) ) ;
528- quote ! ( #ident )
548+ ident. to_token_stream ( )
549+ }
550+ }
551+ }
552+
553+ /// Returns the (possibly renamed or imported as `gdnative`) identifier of the `gdnative_async` crate,
554+ /// if found.
555+ fn crate_gdnative_async ( ) -> proc_macro2:: TokenStream {
556+ if let Ok ( found_crate) = proc_macro_crate:: crate_name ( "gdnative-async" ) {
557+ return match found_crate {
558+ proc_macro_crate:: FoundCrate :: Itself => quote ! ( crate ) ,
559+ proc_macro_crate:: FoundCrate :: Name ( name) => {
560+ let ident = proc_macro2:: Ident :: new ( & name, proc_macro2:: Span :: call_site ( ) ) ;
561+ ident. to_token_stream ( )
562+ }
563+ } ;
564+ }
565+
566+ let found_crate = proc_macro_crate:: crate_name ( "gdnative" ) . expect ( "crate not found" ) ;
567+
568+ match found_crate {
569+ proc_macro_crate:: FoundCrate :: Itself => quote ! ( crate :: tasks) ,
570+ proc_macro_crate:: FoundCrate :: Name ( name) => {
571+ let ident = proc_macro2:: Ident :: new ( & name, proc_macro2:: Span :: call_site ( ) ) ;
572+ quote ! ( #ident:: tasks )
529573 }
530574 }
531575}
0 commit comments