forked from Proxmox/proxmox
macro: ability to rename enum variants via an attribute
In PVE we have multiple different enum types: hyphenated, all-caps, underscores. By default our api-macro enums will convert CamelCase to underscores, so we need a way to represent the rest: enum AnEnum { CaseOne, // becomes "case_one", #[api(rename = "case-two")] CaseTwo, // "case-two", #[api(rename = "CASE_THREE")] CaseThree, } Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
4b3333aa5c
commit
f340968773
@ -1,3 +1,5 @@
|
||||
use std::mem;
|
||||
|
||||
use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
|
||||
|
||||
use failure::{bail, format_err, Error};
|
||||
@ -596,6 +598,25 @@ fn handle_enum(mut definition: Object, item: &mut syn::ItemEnum) -> Result<Token
|
||||
let variant_ident = &variant.ident;
|
||||
let span = variant_ident.span();
|
||||
let underscore_name = util::to_underscore_case(&variant_ident.to_string());
|
||||
let mut underscore_name = syn::LitStr::new(&underscore_name, variant_ident.span());
|
||||
|
||||
let cap = variant.attrs.len();
|
||||
for attr in mem::replace(&mut variant.attrs, Vec::with_capacity(cap)) {
|
||||
if attr.path.is_ident(Ident::new("api", Span::call_site())) {
|
||||
use util::ApiItem;
|
||||
|
||||
let attrs: util::ApiAttr = syn::parse2(attr.tts)?;
|
||||
|
||||
for attr in attrs.items {
|
||||
match attr {
|
||||
ApiItem::Rename(to) => underscore_name = to,
|
||||
//other => c_bail!(other.span(), "unsupported attribute on enum variant"),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
variant.attrs.push(attr);
|
||||
}
|
||||
}
|
||||
|
||||
display_entries.extend(quote_spanned! {
|
||||
span => #enum_ident::#variant_ident => write!(f, #underscore_name),
|
||||
|
@ -28,10 +28,6 @@ impl Name {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.1.clone()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use proc_macro2::Ident;
|
||||
|
||||
use syn::Token;
|
||||
use syn::{parenthesized, Token};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::punctuated::Punctuated;
|
||||
|
||||
@ -52,3 +52,44 @@ pub fn to_underscore_case(text: &str) -> String {
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
pub struct ApiAttr {
|
||||
pub paren_token: syn::token::Paren,
|
||||
pub items: Punctuated<ApiItem, Token![,]>,
|
||||
}
|
||||
|
||||
impl Parse for ApiAttr {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let content;
|
||||
Ok(ApiAttr {
|
||||
paren_token: parenthesized!(content in input),
|
||||
items: content.parse_terminated(ApiItem::parse)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ApiItem {
|
||||
Rename(syn::LitStr),
|
||||
}
|
||||
|
||||
impl Parse for ApiItem {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let what: Ident = input.parse()?;
|
||||
let what_str = what.to_string();
|
||||
match what_str.as_str() {
|
||||
"rename" => {
|
||||
let _: Token![=] = input.parse()?;
|
||||
Ok(ApiItem::Rename(input.parse()?))
|
||||
}
|
||||
_ => c_bail!(what => "unrecognized api attribute: {}", what_str),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl ApiItem {
|
||||
// pub fn span(&self) -> Span {
|
||||
// match self {
|
||||
// ApiItem::Rename(x) => x.span(),
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
Loading…
Reference in New Issue
Block a user