macros: Add alias attribute to ruma_enum
This commit is contained in:
parent
9b870cd9af
commit
af61a62202
@ -12,6 +12,8 @@ enum MyEnum {
|
||||
#[ruma_enum(rename = "m.third")]
|
||||
Third,
|
||||
HelloWorld,
|
||||
#[ruma_enum(rename = "io.ruma.unstable", alias = "m.stable", alias = "hs.notareal.unstable")]
|
||||
Stable,
|
||||
_Custom(PrivOwnedStr),
|
||||
}
|
||||
|
||||
@ -21,6 +23,7 @@ fn as_ref_str() {
|
||||
assert_eq!(MyEnum::Second.as_ref(), "second");
|
||||
assert_eq!(MyEnum::Third.as_ref(), "m.third");
|
||||
assert_eq!(MyEnum::HelloWorld.as_ref(), "hello_world");
|
||||
assert_eq!(MyEnum::Stable.as_ref(), "io.ruma.unstable");
|
||||
assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).as_ref(), "HelloWorld");
|
||||
}
|
||||
|
||||
@ -30,6 +33,7 @@ fn display() {
|
||||
assert_eq!(MyEnum::Second.to_string(), "second");
|
||||
assert_eq!(MyEnum::Third.to_string(), "m.third");
|
||||
assert_eq!(MyEnum::HelloWorld.to_string(), "hello_world");
|
||||
assert_eq!(MyEnum::Stable.to_string(), "io.ruma.unstable");
|
||||
assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).to_string(), "HelloWorld");
|
||||
}
|
||||
|
||||
@ -39,6 +43,9 @@ fn from_string() {
|
||||
assert_eq!(MyEnum::from("second"), MyEnum::Second);
|
||||
assert_eq!(MyEnum::from("m.third"), MyEnum::Third);
|
||||
assert_eq!(MyEnum::from("hello_world"), MyEnum::HelloWorld);
|
||||
assert_eq!(MyEnum::from("io.ruma.unstable"), MyEnum::Stable);
|
||||
assert_eq!(MyEnum::from("m.stable"), MyEnum::Stable);
|
||||
assert_eq!(MyEnum::from("hs.notareal.unstable"), MyEnum::Stable);
|
||||
assert_eq!(MyEnum::from("HelloWorld"), MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())));
|
||||
}
|
||||
|
||||
@ -46,6 +53,7 @@ fn from_string() {
|
||||
fn serialize() {
|
||||
assert_eq!(to_json_value(MyEnum::First).unwrap(), json!("first"));
|
||||
assert_eq!(to_json_value(MyEnum::HelloWorld).unwrap(), json!("hello_world"));
|
||||
assert_eq!(to_json_value(MyEnum::Stable).unwrap(), json!("io.ruma.unstable"));
|
||||
assert_eq!(
|
||||
to_json_value(MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))).unwrap(),
|
||||
json!("\\\n\\")
|
||||
@ -56,6 +64,9 @@ fn serialize() {
|
||||
fn deserialize() {
|
||||
assert_eq!(from_json_value::<MyEnum>(json!("first")).unwrap(), MyEnum::First);
|
||||
assert_eq!(from_json_value::<MyEnum>(json!("hello_world")).unwrap(), MyEnum::HelloWorld);
|
||||
assert_eq!(from_json_value::<MyEnum>(json!("io.ruma.unstable")).unwrap(), MyEnum::Stable);
|
||||
assert_eq!(from_json_value::<MyEnum>(json!("m.stable")).unwrap(), MyEnum::Stable);
|
||||
assert_eq!(from_json_value::<MyEnum>(json!("hs.notareal.unstable")).unwrap(), MyEnum::Stable);
|
||||
assert_eq!(
|
||||
from_json_value::<MyEnum>(json!("\\\n\\")).unwrap(),
|
||||
MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))
|
||||
|
@ -6,23 +6,36 @@ use syn::{
|
||||
use super::case::RenameRule;
|
||||
|
||||
mod kw {
|
||||
syn::custom_keyword!(alias);
|
||||
syn::custom_keyword!(rename);
|
||||
syn::custom_keyword!(rename_all);
|
||||
}
|
||||
|
||||
pub struct RenameAttr(LitStr);
|
||||
|
||||
impl RenameAttr {
|
||||
pub fn into_inner(self) -> LitStr {
|
||||
self.0
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct EnumAttrs {
|
||||
pub rename: Option<LitStr>,
|
||||
pub aliases: Vec<LitStr>,
|
||||
}
|
||||
|
||||
impl Parse for RenameAttr {
|
||||
pub enum Attr {
|
||||
Alias(LitStr),
|
||||
Rename(LitStr),
|
||||
}
|
||||
|
||||
impl Parse for Attr {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _: kw::rename = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
Ok(Self(input.parse()?))
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(kw::alias) {
|
||||
let _: kw::alias = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
Ok(Self::Alias(input.parse()?))
|
||||
} else if lookahead.peek(kw::rename) {
|
||||
let _: kw::rename = input.parse()?;
|
||||
let _: Token![=] = input.parse()?;
|
||||
Ok(Self::Rename(input.parse()?))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@ use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum};
|
||||
|
||||
use super::util::{get_rename, get_rename_rule};
|
||||
use super::{
|
||||
attr::EnumAttrs,
|
||||
util::{get_enum_attributes, get_rename_rule},
|
||||
};
|
||||
|
||||
pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> {
|
||||
let enum_name = &input.ident;
|
||||
@ -12,7 +15,8 @@ pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> {
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let variant_name = &v.ident;
|
||||
let (field_capture, variant_str) = match (get_rename(v)?, &v.fields) {
|
||||
let EnumAttrs { rename, .. } = get_enum_attributes(v)?;
|
||||
let (field_capture, variant_str) = match (rename, &v.fields) {
|
||||
(None, Fields::Unit) => (
|
||||
None,
|
||||
rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(),
|
||||
|
@ -2,7 +2,10 @@ use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum};
|
||||
|
||||
use super::util::{get_rename, get_rename_rule};
|
||||
use super::{
|
||||
attr::EnumAttrs,
|
||||
util::{get_enum_attributes, get_rename_rule},
|
||||
};
|
||||
|
||||
pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
|
||||
let enum_name = &input.ident;
|
||||
@ -13,7 +16,8 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let variant_name = &v.ident;
|
||||
let variant_str = match (get_rename(v)?, &v.fields) {
|
||||
let EnumAttrs { rename, aliases } = get_enum_attributes(v)?;
|
||||
let variant_str = match (rename, &v.fields) {
|
||||
(None, Fields::Unit) => Some(
|
||||
rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(),
|
||||
),
|
||||
@ -56,7 +60,12 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(variant_str.map(|s| quote! { #s => #enum_name :: #variant_name }))
|
||||
Ok(variant_str.map(|s| {
|
||||
quote! {
|
||||
#( #aliases => #enum_name :: #variant_name, )*
|
||||
#s => #enum_name :: #variant_name
|
||||
}
|
||||
}))
|
||||
})
|
||||
.collect::<syn::Result<_>>()?;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use proc_macro2::Span;
|
||||
use syn::{ItemEnum, LitStr, Variant};
|
||||
use syn::{punctuated::Punctuated, ItemEnum, Token, Variant};
|
||||
|
||||
use super::{
|
||||
attr::{RenameAllAttr, RenameAttr},
|
||||
attr::{Attr, EnumAttrs, RenameAllAttr},
|
||||
case::RenameRule,
|
||||
};
|
||||
|
||||
@ -24,16 +24,32 @@ pub fn get_rename_rule(input: &ItemEnum) -> syn::Result<RenameRule> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rename(input: &Variant) -> syn::Result<Option<LitStr>> {
|
||||
let renames: Vec<_> = input
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path.is_ident("ruma_enum"))
|
||||
.map(|attr| attr.parse_args::<RenameAttr>().map(RenameAttr::into_inner))
|
||||
.collect::<syn::Result<_>>()?;
|
||||
pub fn get_enum_attributes(input: &Variant) -> syn::Result<EnumAttrs> {
|
||||
let mut attributes = EnumAttrs::default();
|
||||
|
||||
match renames.len() {
|
||||
0 | 1 => Ok(renames.into_iter().next()),
|
||||
_ => Err(syn::Error::new(Span::call_site(), "found multiple ruma_enum(rename) attributes")),
|
||||
for attr in &input.attrs {
|
||||
if !attr.path.is_ident("ruma_enum") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let enum_attrs = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?;
|
||||
for enum_attr in enum_attrs {
|
||||
match enum_attr {
|
||||
Attr::Rename(s) => {
|
||||
if attributes.rename.is_some() {
|
||||
return Err(syn::Error::new(
|
||||
Span::call_site(),
|
||||
"found multiple ruma_enum(rename) attributes",
|
||||
));
|
||||
}
|
||||
attributes.rename = Some(s);
|
||||
}
|
||||
Attr::Alias(s) => {
|
||||
attributes.aliases.push(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(attributes)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user