@@ -2,6 +2,7 @@ use std::borrow::Cow;
22use std:: collections:: { HashMap , HashSet } ;
33use std:: fmt:: Display ;
44use std:: iter;
5+ use std:: ops:: Range ;
56
67use collection_literals:: hash;
78use interpolator:: { format, Formattable } ;
@@ -10,8 +11,8 @@ use proc_macro2::{Literal, Span, TokenStream};
1011use proc_macro_utils:: { TokenParser , TokenStream2Ext } ;
1112use quote:: { format_ident, ToTokens } ;
1213use quote_use:: quote_use as quote;
13- use syn:: { spanned:: Spanned , Visibility } ;
14- use syn:: { DataStruct , DeriveInput , Field , Fields , Generics , Ident , LitStr , Type } ;
14+ use syn:: spanned:: Spanned ;
15+ use syn:: { DataStruct , DeriveInput , Field , Fields , Generics , Ident , LitStr , Type , Visibility } ;
1516
1617const ATTRIBUTE_IDENT : & str = "attribute" ;
1718
@@ -170,8 +171,13 @@ struct StructAttrs {
170171}
171172
172173impl StructAttrs {
173- fn from_attrs ( attrs : impl IntoIterator < Item = syn:: Attribute > ) -> Result < Self > {
174- const VALID_FORMAT : & str = r#"expected `#[attribute(ident=attribute_name, aliases=[alias1, alias2], error="..", error(unknown_field="..", unknown_field_single="..", unknown_field_empty="..", duplicate_field="..", missing_field="..", field_help=".."))]`"# ;
174+ fn from_attrs (
175+ struct_ident : & Ident ,
176+ attrs : impl IntoIterator < Item = syn:: Attribute > ,
177+ ) -> Result < Self > {
178+ const VALID_FORMAT : & str = r#"expected `#[attribute(ident=attribute_name/!ident, aliases=[alias1, alias2], error="..", error(unknown_field="..", unknown_field_single="..", unknown_field_empty="..", duplicate_field="..", missing_field="..", field_help=".."))]`"# ;
179+
180+ let mut ident_span: Option < Range < Span > > = None ;
175181 let mut ident: Option < Ident > = None ;
176182 let mut aliases: Vec < String > = vec ! [ ] ;
177183 let mut error = StructError :: Specific ( Default :: default ( ) ) ;
@@ -188,105 +194,152 @@ impl StructAttrs {
188194 . clone ( )
189195 . parser ( ) ;
190196 while !parser. is_empty ( ) {
191- let field = parser
192- . next_ident ( )
193- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
194- match field. to_string ( ) . as_str ( ) {
195- "ident" => {
196- parser
197- . next_tt_eq ( )
198- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
199- ident = Some (
200- parser
201- . next_ident ( )
202- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?,
203- )
204- }
205- "aliases" => {
206- parser
207- . next_tt_eq ( )
208- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
209- let mut parser = parser
210- . next_bracketed ( )
211- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?
212- . stream ( )
213- . parser ( ) ;
214- aliases. extend ( iter:: from_fn ( || {
215- _ = parser. next_tt_comma ( ) ;
216- parser. next_ident ( ) . map ( |t| t. to_string ( ) )
217- } ) ) ;
218- if !parser. is_empty ( ) {
219- bail ! ( "{VALID_FORMAT}" )
197+ eprintln ! ( "{}" , parser. to_token_stream( ) ) ;
198+ if let Some ( not) = parser. next_tt_not ( ) {
199+ if let Some ( kw) = parser. next_keyword ( "ident" ) {
200+ if let Some ( ident_span) = ident_span {
201+ bail ! (
202+ error_message!( ident_span, "ident is specified twice" )
203+ + error_message!(
204+ not. span( ) ..kw. span( ) ,
205+ "ident was already specified"
206+ )
207+ )
208+ } else {
209+ ident_span = Some ( not. span ( ) ..kw. span ( ) ) ;
220210 }
221211 }
222- "error" => {
223- if parser. next_tt_eq ( ) . is_some ( ) {
224- error = StructError :: Generic (
225- FormatString :: parse ( parser)
212+ } else {
213+ let field = parser
214+ . next_ident ( )
215+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
216+ match field. to_string ( ) . as_str ( ) {
217+ "ident" => {
218+ parser
219+ . next_tt_eq ( )
220+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
221+ ident = Some (
222+ parser
223+ . next_ident ( )
226224 . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?,
227225 ) ;
228- } else {
229- let parser = & mut parser
230- . next_parenthesized ( )
226+ if let Some ( ident_span) = ident_span {
227+ bail ! (
228+ error_message!( ident_span, "ident is specified twice" )
229+ + error_message!(
230+ field. span( ) ..ident. unwrap( ) . span( ) ,
231+ "ident was already specified"
232+ )
233+ )
234+ }
235+ }
236+ "aliases" => {
237+ parser
238+ . next_tt_eq ( )
239+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
240+ let mut parser = parser
241+ . next_bracketed ( )
231242 . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?
232243 . stream ( )
233244 . parser ( ) ;
234- let error = if let StructError :: Specific ( error) = & mut error {
235- error
245+ aliases. extend ( iter:: from_fn ( || {
246+ _ = parser. next_tt_comma ( ) ;
247+ parser. next_ident ( ) . map ( |t| t. to_string ( ) )
248+ } ) ) ;
249+ if !parser. is_empty ( ) {
250+ bail ! ( "{VALID_FORMAT}" )
251+ }
252+ }
253+ "error" => {
254+ if parser. next_tt_eq ( ) . is_some ( ) {
255+ error = StructError :: Generic (
256+ FormatString :: parse ( parser)
257+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?,
258+ ) ;
236259 } else {
237- error = StructError :: Specific ( Default :: default ( ) ) ;
238- if let StructError :: Specific ( error) = & mut error {
260+ let parser = & mut parser
261+ . next_parenthesized ( )
262+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?
263+ . stream ( )
264+ . parser ( ) ;
265+ let error = if let StructError :: Specific ( error) = & mut error {
239266 error
240267 } else {
241- unreachable ! ( )
242- }
243- } ;
244- while !parser. is_empty ( ) {
245- let field = parser
246- . next_ident ( )
247- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
248- let mut string = |f : & mut _ | -> Result < ( ) > {
249- parser
250- . next_tt_eq ( )
251- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
252- * f = FormatString :: parse ( parser)
253- . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
254- Ok ( ( ) )
255- } ;
256- match field. to_string ( ) . as_str ( ) {
257- "unknown_field" => string ( & mut error. unknown_field ) ,
258- "unknown_field_empty" => string ( & mut error. unknown_field_empty ) ,
259- "unknown_field_single" => {
260- string ( & mut error. unknown_field_single )
268+ error = StructError :: Specific ( Default :: default ( ) ) ;
269+ if let StructError :: Specific ( error) = & mut error {
270+ error
271+ } else {
272+ unreachable ! ( )
261273 }
262- "duplicate_field" => string ( & mut error. duplicate_field ) ,
263- "missing_field" => string ( & mut error. missing_field ) ,
264- "field_help" => string ( & mut error. field_help ) ,
265- "conflict" => string ( & mut error. conflict ) ,
266- _ => bail ! ( field, "{VALID_FORMAT}" ) ,
267- } ?;
268- _ = parser. next_tt_comma ( ) ;
274+ } ;
275+ while !parser. is_empty ( ) {
276+ let field = parser
277+ . next_ident ( )
278+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
279+ let mut string = |f : & mut _ | -> Result < ( ) > {
280+ parser
281+ . next_tt_eq ( )
282+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
283+ * f = FormatString :: parse ( parser)
284+ . ok_or_else ( || ErrorMessage :: call_site ( VALID_FORMAT ) ) ?;
285+ Ok ( ( ) )
286+ } ;
287+ match field. to_string ( ) . as_str ( ) {
288+ "unknown_field" => string ( & mut error. unknown_field ) ,
289+ "unknown_field_empty" => {
290+ string ( & mut error. unknown_field_empty )
291+ }
292+ "unknown_field_single" => {
293+ string ( & mut error. unknown_field_single )
294+ }
295+ "duplicate_field" => string ( & mut error. duplicate_field ) ,
296+ "missing_field" => string ( & mut error. missing_field ) ,
297+ "field_help" => string ( & mut error. field_help ) ,
298+ "conflict" => string ( & mut error. conflict ) ,
299+ _ => bail ! ( field, "{VALID_FORMAT}" ) ,
300+ } ?;
301+ _ = parser. next_tt_comma ( ) ;
302+ }
269303 }
270304 }
305+ // "duplicate" => {
306+ // parser.next_eq() .ok_or_else(||
307+ // ErrorMessage::call_site(VALID_FORMAT))?; let strategy
308+ // = parser.next_ident() .ok_or_else(||
309+ // ErrorMessage::call_site(VALID_FORMAT))?; duplicate =
310+ // match strategy.to_string().as_str() {
311+ // "AggregateOrError" => DuplicateStrategy::AggregateOrError,
312+ // "Error" => DuplicateStrategy::Error,
313+ // "AggregateOrOverride" => DuplicateStrategy::AggregateOrOverride,
314+ // "Override" => DuplicateStrategy::Override,
315+ // _ => abort!(strategy, VALID_FORMAT),
316+ // }
317+ // }
318+ _ => bail ! ( field, "{VALID_FORMAT}" ) ,
271319 }
272- // "duplicate" => {
273- // parser.next_eq() .ok_or_else(||
274- // ErrorMessage::call_site(VALID_FORMAT))?; let strategy
275- // = parser.next_ident() .ok_or_else(||
276- // ErrorMessage::call_site(VALID_FORMAT))?; duplicate =
277- // match strategy.to_string().as_str() {
278- // "AggregateOrError" => DuplicateStrategy::AggregateOrError,
279- // "Error" => DuplicateStrategy::Error,
280- // "AggregateOrOverride" => DuplicateStrategy::AggregateOrOverride,
281- // "Override" => DuplicateStrategy::Override,
282- // _ => abort!(strategy, VALID_FORMAT),
283- // }
284- // }
285- _ => bail ! ( field, "{VALID_FORMAT}" ) ,
286320 }
287321 _ = parser. next_tt_comma ( ) ;
288322 }
289323 }
324+
325+ if ident_span. is_none ( ) && ident. is_none ( ) {
326+ let ident_string = struct_ident. to_string ( ) ;
327+ let mut out = String :: with_capacity ( ident_string. len ( ) ) ;
328+ let mut ident_string = ident_string. chars ( ) ;
329+
330+ out. extend ( ident_string. next ( ) . into_iter ( ) . flat_map ( char:: to_lowercase) ) ;
331+ for c in ident_string {
332+ if c. is_uppercase ( ) {
333+ out. push ( '_' ) ;
334+ out. extend ( c. to_lowercase ( ) ) ;
335+ } else {
336+ out. push ( c) ;
337+ }
338+ }
339+
340+ ident = Some ( Ident :: new ( & out, struct_ident. span ( ) ) ) ;
341+ }
342+
290343 Ok ( Self {
291344 ident,
292345 aliases,
@@ -790,11 +843,11 @@ pub fn from_attr_derive(
790843 mut aliases,
791844 error : ref struct_error,
792845 // duplicate,
793- } = StructAttrs :: from_attrs ( attrs) ?;
846+ } = StructAttrs :: from_attrs ( & ident , attrs) ?;
794847
795848 let ( impl_generics, ty_generics, where_clause) = generics. split_for_impl ( ) ;
796849
797- if let Some ( attribute_ident) = attribute_ident. clone ( ) {
850+ if let Some ( ref attribute_ident) = attribute_ident {
798851 aliases. insert ( 0 , attribute_ident. to_string ( ) ) ;
799852 }
800853
@@ -815,7 +868,7 @@ pub fn from_attr_derive(
815868 fields : fields @ ( Fields :: Named ( _) | Fields :: Unnamed ( _) ) ,
816869 ..
817870 } ) => AttrField :: parse_fields ( fields, struct_error, attribute_ident) ?,
818- _ => bail ! ( "only works on structs with named fields" ) ,
871+ _ => bail ! ( "only works on structs with fields" ) ,
819872 } ;
820873
821874 let conflicts = conflicts. to_tokens ( struct_error) ?;
0 commit comments