@@ -9,8 +9,9 @@ pub use shape::*;
9
9
pub use symbol:: * ;
10
10
11
11
use proc_macro:: TokenStream ;
12
- use quote:: quote;
12
+ use quote:: { quote, quote_spanned } ;
13
13
use std:: { env, path:: PathBuf } ;
14
+ use syn:: spanned:: Spanned ;
14
15
use toml:: { map:: Map , Value } ;
15
16
16
17
pub struct BevyManifest {
@@ -125,7 +126,7 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr
125
126
. unwrap ( )
126
127
}
127
128
128
- let ident = input. ident ;
129
+ let ident = input. ident . clone ( ) ;
129
130
130
131
use convert_case:: { Case , Casing } ;
131
132
let trait_snake_case = trait_path
@@ -145,28 +146,42 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr
145
146
. predicates
146
147
. push ( syn:: parse2 ( quote ! { Self : ' static } ) . unwrap ( ) ) ;
147
148
148
- let ignore_fields = input. attrs . iter ( ) . any ( |a| is_ignore ( a, & trait_snake_case) ) ;
149
149
let as_str = match input. data {
150
150
syn:: Data :: Struct ( d) => {
151
151
// see if the user tried to ignore fields incorrectly
152
- if d. fields
152
+ if let Some ( attr) = d
153
+ . fields
153
154
. iter ( )
154
155
. flat_map ( |f| & f. attrs )
155
- . any ( |a| is_ignore ( a, & trait_snake_case) )
156
+ . find ( |a| is_ignore ( a, & trait_snake_case) )
156
157
{
157
- panic ! ( "`#[{trait_snake_case}(ignore_fields)]` cannot be applied to fields individually: add it to the struct declaration" ) ;
158
+ let err_msg = format ! ( "`#[{trait_snake_case}(ignore_fields)]` cannot be applied to fields individually: add it to the struct declaration" ) ;
159
+ return quote_spanned ! {
160
+ attr. span( ) => compile_error!( #err_msg) ;
161
+ }
162
+ . into ( ) ;
158
163
}
159
164
// Structs must either be fieldless, or explicitly ignore the fields.
165
+ let ignore_fields = input. attrs . iter ( ) . any ( |a| is_ignore ( a, & trait_snake_case) ) ;
160
166
if matches ! ( d. fields, syn:: Fields :: Unit ) || ignore_fields {
161
167
let lit = ident. to_string ( ) ;
162
168
quote ! { #lit }
163
169
} else {
164
- panic ! ( "Labels cannot contain data, unless explicitly ignored with `#[{trait_snake_case}(ignore_fields)]`" ) ;
170
+ let err_msg = format ! ( "Labels cannot contain data, unless explicitly ignored with `#[{trait_snake_case}(ignore_fields)]`" ) ;
171
+ return quote_spanned ! {
172
+ d. fields. span( ) => compile_error!( #err_msg) ;
173
+ }
174
+ . into ( ) ;
165
175
}
166
176
}
167
177
syn:: Data :: Enum ( d) => {
168
- if ignore_fields {
169
- panic ! ( "`#[{trait_snake_case}(ignore_fields)]` can only be applied to struct declarations or enum variants" ) ;
178
+ // check if the user put #[label(ignore_fields)] in the wrong place
179
+ if let Some ( attr) = input. attrs . iter ( ) . find ( |a| is_ignore ( a, & trait_snake_case) ) {
180
+ let err_msg = format ! ( "`#[{trait_snake_case}(ignore_fields)]` can only be applied to enum variants or struct declarations" ) ;
181
+ return quote_spanned ! {
182
+ attr. span( ) => compile_error!( #err_msg) ;
183
+ }
184
+ . into ( ) ;
170
185
}
171
186
let arms = d. variants . iter ( ) . map ( |v| {
172
187
// Variants must either be fieldless, or explicitly ignore the fields.
@@ -177,7 +192,10 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr
177
192
let lit = format ! ( "{ident}::{}" , v. ident. clone( ) ) ;
178
193
quote ! { #path { .. } => #lit }
179
194
} else {
180
- panic ! ( "Label variants cannot contain data, unless explicitly ignored with `#[{trait_snake_case}(ignore_fields)]`" ) ;
195
+ let err_msg = format ! ( "Label variants cannot contain data, unless explicitly ignored with `#[{trait_snake_case}(ignore_fields)]`" ) ;
196
+ quote_spanned ! {
197
+ v. fields. span( ) => _ => { compile_error!( #err_msg) ; }
198
+ }
181
199
}
182
200
} ) ;
183
201
quote ! {
@@ -186,7 +204,12 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr
186
204
}
187
205
}
188
206
}
189
- syn:: Data :: Union ( _) => panic ! ( "Unions cannot be used as labels." ) ,
207
+ syn:: Data :: Union ( _) => {
208
+ return quote_spanned ! {
209
+ input. span( ) => compile_error!( "Unions cannot be used as labels." ) ;
210
+ }
211
+ . into ( ) ;
212
+ }
190
213
} ;
191
214
192
215
( quote ! {
0 commit comments