15 changed files with 210 additions and 17 deletions
@ -1,2 +1,5 @@
|
||||
[env] |
||||
RUMA_UNSTABLE_EXHAUSTIVE_TYPES = "1" |
||||
|
||||
[alias] |
||||
xtask = "run --package xtask --" |
||||
|
||||
@ -0,0 +1,22 @@
|
||||
[package] |
||||
edition.workspace = true |
||||
homepage.workspace = true |
||||
name = "conduit-macros" |
||||
repository.workspace = true |
||||
rust-version.workspace = true |
||||
version = "0.11.0-alpha" |
||||
|
||||
[lib] |
||||
proc-macro = true |
||||
|
||||
[dependencies] |
||||
proc-macro2 = "1" |
||||
quote = "1" |
||||
syn = { version = "2", features = ["full"] } |
||||
|
||||
[features] |
||||
default = ["doc-generators"] |
||||
doc-generators = [] |
||||
|
||||
[lints] |
||||
workspace = true |
||||
@ -0,0 +1,91 @@
|
||||
use std::{fmt::Display, path::Path}; |
||||
|
||||
use proc_macro::TokenStream; |
||||
use proc_macro2::TokenStream as TokenStream2; |
||||
use quote::{ToTokens, quote}; |
||||
use syn::{Attribute, Expr, Field, Ident, ItemEnum, Lit, MetaNameValue, Variant, parse::Parse}; |
||||
|
||||
pub struct Restrictions { |
||||
ident: Ident, |
||||
variants: Vec<Restriction>, |
||||
} |
||||
|
||||
pub struct Restriction { |
||||
ident: Ident, |
||||
doc_comments: Vec<String>, |
||||
} |
||||
|
||||
impl Parse for Restrictions { |
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { |
||||
let ItemEnum { |
||||
ident, |
||||
variants, |
||||
// Might be useful later.
|
||||
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(); |
||||
|
||||
Ok(Restriction { |
||||
ident, |
||||
doc_comments, |
||||
}) |
||||
}) |
||||
.collect::<syn::Result<Vec<_>>>()?; |
||||
|
||||
Ok(Self { ident, variants }) |
||||
} |
||||
} |
||||
|
||||
/// 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 output = quote! { |
||||
impl DocumentRestrictions for #ident { |
||||
fn variant_doc_comments() -> Vec<(Self, String)> { |
||||
vec![#( (#variants), )*] |
||||
} |
||||
} |
||||
}; |
||||
|
||||
tokens.extend(output); |
||||
} |
||||
} |
||||
|
||||
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"); |
||||
|
||||
// `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) ) )) |
||||
} |
||||
} |
||||
@ -0,0 +1,16 @@
|
||||
use proc_macro::TokenStream; |
||||
use quote::quote; |
||||
|
||||
#[cfg(feature = "doc-generators")] |
||||
mod doc_generators; |
||||
|
||||
#[cfg(feature = "doc-generators")] |
||||
#[proc_macro_derive(DocumentRestrictions)] |
||||
pub fn document_restrictions(item: TokenStream) -> TokenStream { |
||||
use doc_generators::Restrictions; |
||||
use syn::parse_macro_input; |
||||
|
||||
let restrictions = parse_macro_input!(item as Restrictions); |
||||
|
||||
quote! { #restrictions }.into() |
||||
} |
||||
@ -0,0 +1,12 @@
|
||||
[package] |
||||
edition.workspace = true |
||||
homepage.workspace = true |
||||
name = "xtask" |
||||
repository.workspace = true |
||||
rust-version.workspace = true |
||||
version = "0.11.0-alpha" |
||||
|
||||
[dependencies] |
||||
|
||||
[lints] |
||||
workspace = true |
||||
Loading…
Reference in new issue