1
- extern crate proc_macro;
2
-
3
1
use bevy_macro_utils:: BevyManifest ;
2
+ use proc_macro2:: { Span , TokenStream } ;
4
3
use quote:: quote;
5
4
use syn:: parse:: { Parse , ParseStream } ;
6
5
use syn:: token:: Comma ;
7
- use syn:: * ;
6
+ use syn:: { DeriveInput , Expr , ExprLit , Generics , Ident , Lit , LitInt , LitStr , Meta } ;
8
7
use uuid:: Uuid ;
9
8
10
- /// Parses input from a derive of `TypeUuid`.
11
- pub ( crate ) fn type_uuid_derive ( input : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
12
- // Construct a representation of Rust code as a syntax tree
13
- // that we can manipulate
14
- let ast: DeriveInput = syn:: parse ( input) . unwrap ( ) ;
15
- // Build the trait implementation
16
- let type_ident = ast. ident ;
17
-
9
+ pub ( crate ) fn type_uuid_derive ( input : DeriveInput ) -> syn:: Result < TokenStream > {
18
10
let mut uuid = None ;
19
- for attribute in ast. attrs . iter ( ) . filter ( |attr| attr. path ( ) . is_ident ( "uuid" ) ) {
11
+ for attribute in input
12
+ . attrs
13
+ . iter ( )
14
+ . filter ( |attr| attr. path ( ) . is_ident ( "uuid" ) )
15
+ {
20
16
let Meta :: NameValue ( ref name_value) = attribute. meta else {
21
17
continue ;
22
18
} ;
23
19
24
20
let uuid_str = match & name_value. value {
25
21
Expr :: Lit ( ExprLit { lit : Lit :: Str ( lit_str) , ..} ) => lit_str,
26
- _ => panic ! ( "`uuid` attribute must take the form `#[uuid = \" xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\" `." ) ,
22
+ _ => return Err ( syn :: Error :: new_spanned ( attribute , "`uuid` attribute must take the form `#[uuid = \" xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\" ] `." ) ) ,
27
23
} ;
28
24
29
- uuid = Some (
30
- Uuid :: parse_str ( & uuid_str. value ( ) )
31
- . expect ( "Value specified to `#[uuid]` attribute is not a valid UUID." ) ,
32
- ) ;
25
+ uuid =
26
+ Some ( Uuid :: parse_str ( & uuid_str. value ( ) ) . map_err ( |err| {
27
+ syn :: Error :: new_spanned ( uuid_str , format ! ( "Invalid UUID: {err}" ) )
28
+ } ) ? ) ;
33
29
}
34
30
35
- let uuid =
36
- uuid. expect ( "No `#[uuid = \" xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\" ` attribute found." ) ;
37
- gen_impl_type_uuid ( TypeUuidDef {
38
- type_ident,
39
- generics : ast. generics ,
31
+ let uuid = uuid. ok_or_else ( || {
32
+ syn:: Error :: new (
33
+ Span :: call_site ( ) ,
34
+ "No `#[uuid = \" xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\" ]` attribute found." ,
35
+ )
36
+ } ) ?;
37
+
38
+ Ok ( gen_impl_type_uuid ( TypeUuidDef {
39
+ type_ident : input. ident ,
40
+ generics : input. generics ,
40
41
uuid,
41
- } )
42
+ } ) )
42
43
}
43
44
44
45
/// Generates an implementation of `TypeUuid`. If there any generics, the `TYPE_UUID` will be a composite of the generic types' `TYPE_UUID`.
45
- pub ( crate ) fn gen_impl_type_uuid ( def : TypeUuidDef ) -> proc_macro :: TokenStream {
46
+ pub ( crate ) fn gen_impl_type_uuid ( def : TypeUuidDef ) -> TokenStream {
46
47
let uuid = def. uuid ;
47
48
let mut generics = def. generics ;
48
49
let ty = def. type_ident ;
49
50
50
- let bevy_reflect_path: Path = BevyManifest :: default ( ) . get_path ( "bevy_reflect" ) ;
51
+ let bevy_reflect_path = BevyManifest :: default ( ) . get_path ( "bevy_reflect" ) ;
51
52
52
53
generics. type_params_mut ( ) . for_each ( |param| {
53
54
param
@@ -74,12 +75,11 @@ pub(crate) fn gen_impl_type_uuid(def: TypeUuidDef) -> proc_macro::TokenStream {
74
75
}
75
76
} ) ;
76
77
77
- let gen = quote ! {
78
+ quote ! {
78
79
impl #impl_generics #bevy_reflect_path:: TypeUuid for #ty #type_generics #where_clause {
79
80
const TYPE_UUID : #bevy_reflect_path:: Uuid = #type_uuid;
80
81
}
81
- } ;
82
- gen. into ( )
82
+ }
83
83
}
84
84
85
85
/// A struct containing the data required to generate an implementation of `TypeUuid`. This can be generated by either [`impl_type_uuid!`][crate::impl_type_uuid!] or [`type_uuid_derive`].
@@ -90,7 +90,7 @@ pub(crate) struct TypeUuidDef {
90
90
}
91
91
92
92
impl Parse for TypeUuidDef {
93
- fn parse ( input : ParseStream ) -> Result < Self > {
93
+ fn parse ( input : ParseStream ) -> syn :: Result < Self > {
94
94
let type_ident = input. parse :: < Ident > ( ) ?;
95
95
let generics = input. parse :: < Generics > ( ) ?;
96
96
input. parse :: < Comma > ( ) ?;
0 commit comments