From f5935b673ba58ef137279f78b07fb6d54d7845e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20K=C3=A4nner?= Date: Wed, 17 Apr 2024 16:59:24 +0200 Subject: [PATCH] add doctest --- src/lib.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4b1b696..edca453 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,11 @@ +//! This crate creates `miniconf::Tree` implementations fields in a struct. These carry some extra +//! extra information about the field. + use std::iter::once; use convert_case::{Case, Casing}; use proc_macro::TokenStream; -use proc_macro2::{Span as Span2, TokenStream as TokenStream2}; +use proc_macro2::{Span as Span2, TokenStream as TokenStream2, TokenTree as TokenTree2}; use quote::{format_ident, quote, ToTokens}; use syn::{ parse_macro_input, parse_quote, Attribute, DataStruct, DeriveInput, Expr, ExprLit, Field, @@ -12,6 +15,20 @@ use syn::{ /// Creates structs for the values to extend them with extra metadata. /// /// supported metadata is `min`, `max` and `default`. Doc comments are parsed as `description` +/// +/// # Example +/// ``` +/// use macroconf::config; +/// +/// #[config] +/// struct Config { +/// /// This will be parsed as description +/// #[min] // This will use i32::MIN for the minimum +/// #[max = 50] // The value 50 is used for the maximum +/// #[default = 42] // A `Default` implementation will be generated returning 42 +/// field1: i32, +/// } +/// ``` #[proc_macro_attribute] pub fn config(_attr: TokenStream, item: TokenStream) -> TokenStream { let mut input = parse_macro_input!(item as DeriveInput); @@ -37,6 +54,32 @@ pub fn config(_attr: TokenStream, item: TokenStream) -> TokenStream { } } + if let Some(attr) = input + .attrs + .iter_mut() + .find(|attr| attr.path().is_ident("derive")) + { + if let Ok(meta) = attr.meta.require_list() { + let derives_tree = meta + .tokens + .clone() + .into_iter() + .filter_map(|token| match token { + TokenTree2::Ident(ident) if ident == Ident::new("Tree", ident.span()) => { + Some(ident) + } + _ => None, + }) + .count() + == 1; + if !derives_tree { + input.attrs.push(parse_quote!(#[derive(::miniconf::Tree)])); + } + } + } else { + input.attrs.push(parse_quote!(#[derive(::miniconf::Tree)])); + } + quote! { #input #(#new_types)* @@ -339,7 +382,7 @@ fn generate_serde(ident: &Ident, ty: &Type, checked_new: bool) -> TokenStream2 { let conversion = if checked_new { quote! { Self::new(value).ok_or_else(|| { - D::Error::custom("checking value bounds") + ::custom("checking value bounds") }) } } else {