|
|
|
|
@ -1,15 +1,16 @@
|
|
|
|
|
use proc_macro2::TokenStream as TokenStream2; |
|
|
|
|
use quote::{ToTokens, quote}; |
|
|
|
|
use syn::{Expr, Ident, ItemEnum, Lit, MetaNameValue, Variant, parse::Parse}; |
|
|
|
|
use syn::{Attribute, Expr, Ident, ItemEnum, Lit, MetaNameValue, Variant, parse::Parse}; |
|
|
|
|
|
|
|
|
|
pub(super) struct Restrictions { |
|
|
|
|
ident: Ident, |
|
|
|
|
doc_comment: String, |
|
|
|
|
variants: Vec<Restriction>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct Restriction { |
|
|
|
|
ident: Ident, |
|
|
|
|
doc_comments: Vec<String>, |
|
|
|
|
doc_comment: String, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Parse for Restrictions { |
|
|
|
|
@ -17,50 +18,65 @@ impl Parse for Restrictions {
|
|
|
|
|
let ItemEnum { |
|
|
|
|
ident, |
|
|
|
|
variants, |
|
|
|
|
// Might be useful later.
|
|
|
|
|
attrs: _, |
|
|
|
|
attrs, |
|
|
|
|
.. |
|
|
|
|
} = ItemEnum::parse(input)?; |
|
|
|
|
|
|
|
|
|
let variants = variants |
|
|
|
|
.into_iter() |
|
|
|
|
.map(|Variant { attrs, ident, .. }| { |
|
|
|
|
let doc_comments = attrs |
|
|
|
|
.into_iter() |
|
|
|
|
.filter_map(|attr| { |
|
|
|
|
if let syn::Meta::NameValue(MetaNameValue { path, value, .. }) = attr.meta |
|
|
|
|
&& path.is_ident("doc") |
|
|
|
|
&& let Expr::Lit(lit) = value |
|
|
|
|
&& let Lit::Str(string) = lit.lit |
|
|
|
|
{ |
|
|
|
|
Some(string.value().trim().to_owned() + "\n") |
|
|
|
|
} else { |
|
|
|
|
None |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.collect(); |
|
|
|
|
let doc_comment = attrs_to_doc_comment(attrs); |
|
|
|
|
|
|
|
|
|
Ok(Restriction { |
|
|
|
|
ident, |
|
|
|
|
doc_comments, |
|
|
|
|
}) |
|
|
|
|
Ok(Restriction { ident, doc_comment }) |
|
|
|
|
}) |
|
|
|
|
.collect::<syn::Result<Vec<_>>>()?; |
|
|
|
|
|
|
|
|
|
Ok(Self { ident, variants }) |
|
|
|
|
let doc_comment = attrs_to_doc_comment(attrs); |
|
|
|
|
|
|
|
|
|
Ok(Self { |
|
|
|
|
ident, |
|
|
|
|
variants, |
|
|
|
|
doc_comment, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn attrs_to_doc_comment(attrs: Vec<Attribute>) -> String { |
|
|
|
|
attrs |
|
|
|
|
.into_iter() |
|
|
|
|
.filter_map(|attr| { |
|
|
|
|
if let syn::Meta::NameValue(MetaNameValue { path, value, .. }) = attr.meta |
|
|
|
|
&& path.is_ident("doc") |
|
|
|
|
&& let Expr::Lit(lit) = value |
|
|
|
|
&& let Lit::Str(string) = lit.lit |
|
|
|
|
{ |
|
|
|
|
Some(string.value().trim().to_owned()) |
|
|
|
|
} else { |
|
|
|
|
None |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.collect::<Vec<_>>() |
|
|
|
|
.join("\n") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Produces the following function on said restriction:
|
|
|
|
|
/// - `variant_doc_comments`, returning each variant and it's doc comment.
|
|
|
|
|
impl ToTokens for Restrictions { |
|
|
|
|
fn to_tokens(&self, tokens: &mut TokenStream2) { |
|
|
|
|
let Self { ident, variants } = self; |
|
|
|
|
let Self { |
|
|
|
|
ident, |
|
|
|
|
variants, |
|
|
|
|
doc_comment, /* , doc_comments */ |
|
|
|
|
} = self; |
|
|
|
|
let output = quote! { |
|
|
|
|
impl DocumentRestrictions for #ident { |
|
|
|
|
fn variant_doc_comments() -> Vec<(Self, String)> { |
|
|
|
|
vec![#((#variants)),*] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn container_doc_comment() -> String { |
|
|
|
|
#doc_comment.to_owned() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
@ -70,19 +86,9 @@ impl ToTokens for Restrictions {
|
|
|
|
|
|
|
|
|
|
impl ToTokens for Restriction { |
|
|
|
|
fn to_tokens(&self, tokens: &mut TokenStream2) { |
|
|
|
|
let Self { |
|
|
|
|
ident, |
|
|
|
|
doc_comments, |
|
|
|
|
} = self; |
|
|
|
|
|
|
|
|
|
let doc_comment = doc_comments |
|
|
|
|
.iter() |
|
|
|
|
.map(|attr| attr.trim()) |
|
|
|
|
.collect::<Vec<_>>() |
|
|
|
|
.join("\n"); |
|
|
|
|
let Self { ident, doc_comment } = self; |
|
|
|
|
|
|
|
|
|
// `String::from` because despite `doc_comment` being a `String`, the macro still ends up
|
|
|
|
|
// with a `&str` somehow.
|
|
|
|
|
tokens.extend(quote!( (Self::#ident, String::from(#doc_comment) ) )) |
|
|
|
|
// `clone` because `to_tokens` takes a reference to self.
|
|
|
|
|
tokens.extend(quote!( (Self::#ident, #doc_comment.to_owned() ) )) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|