rename and rename_all attributes

rename
pantonshire 2 years ago
parent 5bd28d6774
commit a3137d86c2

@ -7,8 +7,9 @@ use syn::{DataEnum, Fields, Attribute};
use crate::attribute::{Dict, Value}; use crate::attribute::{Dict, Value};
use crate::error::{MacroError, MacroResult}; use crate::error::{MacroError, MacroResult};
use crate::rename::RenameVariant;
use crate::{TokenStream2, CASE_SENSITIVE}; use crate::{TokenStream2, CASE_SENSITIVE};
use crate::{CASE_INSENSITIVE, CRATE_ATTR, IGNORE, NAME, OTHER}; use crate::{CASE_INSENSITIVE, RENAME, RENAME_ALL, CRATE_ATTR, IGNORE, NAME, OTHER};
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct Enum<'a> { pub(crate) struct Enum<'a> {
@ -192,19 +193,20 @@ pub(crate) fn parse_enum<'a>(data: &'a DataEnum, attrs: &'a [Attribute]) -> Macr
let mut taken_sensitive_names = HashSet::new(); let mut taken_sensitive_names = HashSet::new();
let mut other_variant = false; let mut other_variant = false;
let global_case_insensitive = { let mut global_dict = Dict::from_attrs(CRATE_ATTR, attrs)?;
let mut dict = Dict::from_attrs(CRATE_ATTR, attrs)?;
let (global_case_insensitive, _) = global_dict.remove_typed_or_default(
let (global_case_insensitive, _) = dict.remove_typed_or_default( CASE_INSENSITIVE,
CASE_INSENSITIVE, (false, data.enum_token.span()),
(false, data.enum_token.span()), Value::value_bool,
Value::value_bool, )?;
)?;
dict.assert_empty()?; let global_rename = global_dict.remove_typed(RENAME_ALL, Value::value_string)?
.map(|(global_rename, span)| RenameVariant::from_str(&global_rename, span))
.transpose()?;
global_case_insensitive global_dict.assert_empty()?;
}; drop(global_dict);
for variant in data.variants.iter() { for variant in data.variants.iter() {
let variant_span = variant.span(); let variant_span = variant.span();
@ -213,10 +215,7 @@ pub(crate) fn parse_enum<'a>(data: &'a DataEnum, attrs: &'a [Attribute]) -> Macr
let mut dict = Dict::from_attrs(CRATE_ATTR, &variant.attrs)?; let mut dict = Dict::from_attrs(CRATE_ATTR, &variant.attrs)?;
// Convert the values in the Dict to the appropriate types // Convert the values in the Dict to the appropriate types
let name_opt = dict.remove_typed( let name_opt = dict.remove_typed(NAME, Value::value_string)?;
NAME,
Value::value_string
)?;
let (other, other_span) = dict.remove_typed_or_default( let (other, other_span) = dict.remove_typed_or_default(
OTHER, OTHER,
@ -257,6 +256,11 @@ pub(crate) fn parse_enum<'a>(data: &'a DataEnum, attrs: &'a [Attribute]) -> Macr
} }
}; };
let rename = dict.remove_typed(RENAME, Value::value_string)?
.map(|(rename, span)| RenameVariant::from_str(&rename, span))
.transpose()?
.or(global_rename);
// Return an error if there are any unrecognised keys in the Dict // Return an error if there are any unrecognised keys in the Dict
dict.assert_empty()?; dict.assert_empty()?;
@ -318,7 +322,14 @@ pub(crate) fn parse_enum<'a>(data: &'a DataEnum, attrs: &'a [Attribute]) -> Macr
// Use the str name if one is provided, otherwise use the variant's name // Use the str name if one is provided, otherwise use the variant's name
let (name, name_span) = match name_opt { let (name, name_span) = match name_opt {
Some((name, name_span)) => (name, name_span), Some((name, name_span)) => (name, name_span),
None => (variant.ident.to_string(), variant.ident.span()), None => {
let name_span = variant.ident.span();
let mut name = variant.ident.to_string();
if let Some(rename) = rename {
name = rename.apply(&name);
}
(name, name_span)
},
}; };
// Do not allow duplicate names // Do not allow duplicate names

@ -28,6 +28,8 @@ const OTHER: &'static str = "other";
const IGNORE: &'static str = "ignore"; const IGNORE: &'static str = "ignore";
const CASE_INSENSITIVE: &'static str = "case_insensitive"; const CASE_INSENSITIVE: &'static str = "case_insensitive";
const CASE_SENSITIVE: &'static str = "case_sensitive"; const CASE_SENSITIVE: &'static str = "case_sensitive";
const RENAME: &'static str = "rename";
const RENAME_ALL: &'static str = "rename_all";
type TokenStream2 = proc_macro2::TokenStream; type TokenStream2 = proc_macro2::TokenStream;

@ -20,7 +20,7 @@ impl RenameVariant {
match s { match s {
"lowercase" => Ok(Self::Lower), "lowercase" => Ok(Self::Lower),
"UPPERCASE" => Ok(Self::Upper), "UPPERCASE" => Ok(Self::Upper),
"PascalCase" => Ok(Self::Upper), "PascalCase" => Ok(Self::Pascal),
"camelCase" => Ok(Self::Camel), "camelCase" => Ok(Self::Camel),
"snake_case" => Ok(Self::Snake), "snake_case" => Ok(Self::Snake),
"SCREAMING_SNAKE_CASE" => Ok(Self::ScreamingSnake), "SCREAMING_SNAKE_CASE" => Ok(Self::ScreamingSnake),

@ -0,0 +1,21 @@
use enumscribe::*;
#[derive(ScribeStaticStr, TryUnscribe, PartialEq, Eq, Debug)]
#[enumscribe(rename_all = "snake_case")]
enum Bird {
BlackRedstart,
#[enumscribe(case_insensitive)]
GardenWarbler,
#[enumscribe(rename = "SCREAMING-KEBAB-CASE")]
BarnacleGoose,
}
fn main() {
assert_eq!(Bird::BlackRedstart.scribe(), "black_redstart");
assert_eq!(Bird::GardenWarbler.scribe(), "garden_warbler");
assert_eq!(Bird::BarnacleGoose.scribe(), "BARNACLE-GOOSE");
assert_eq!(Bird::try_unscribe("black_redstart").unwrap(), Bird::BlackRedstart);
assert_eq!(Bird::try_unscribe("gArDeN_wArBlEr").unwrap(), Bird::GardenWarbler);
assert_eq!(Bird::try_unscribe("BARNACLE-GOOSE").unwrap(), Bird::BarnacleGoose);
}
Loading…
Cancel
Save