remove unwraps and panics

This commit is contained in:
Max Känner 2024-04-15 21:40:32 +02:00
parent 3ad76d1c00
commit 65b47996e3

View File

@ -3,7 +3,7 @@ use std::iter::once;
use convert_case::{Case, Casing};
use proc_macro::TokenStream;
use proc_macro2::{Span as Span2, TokenStream as TokenStream2};
use quote::{format_ident, quote};
use quote::{format_ident, quote, ToTokens};
use syn::{
parse_macro_input, parse_quote, Attribute, DataStruct, DeriveInput, Expr, ExprLit, Field,
Ident, Lit, Type, Visibility,
@ -12,10 +12,6 @@ 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`
///
/// # Panics
///
/// Panics if it is unable to generate a config struct from the input
#[proc_macro_attribute]
pub fn config(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(item as DeriveInput);
@ -33,8 +29,12 @@ pub fn config(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
}
syn::Data::Enum(_) => panic!("Enums are not supported"),
syn::Data::Union(_) => panic!("Unions are not supported"),
syn::Data::Enum(_) => {
return quote! {compile_error!("Enums are not supported")}.into();
}
syn::Data::Union(_) => {
return quote! {compile_error!("Unions are not supported")}.into();
}
}
quote! {
@ -145,9 +145,12 @@ fn parse_min(
let const_ident = Ident::new(KEY.to_case(Case::Upper).as_str(), Span2::mixed_site());
let (value, new_check) = attr.meta.require_path_only().map_or_else(
|_| {
let value = &attr.meta.require_name_value().unwrap().value;
let value = match &attr.meta.require_name_value() {
Ok(meta) => &meta.value,
Err(e) => return (e.to_owned().into_compile_error(), None),
};
(
quote!(#value),
value.to_token_stream(),
Some(quote! {
if (value < Self::#const_ident.0) {
return None;
@ -177,9 +180,12 @@ fn parse_max(
let const_ident = Ident::new(KEY.to_case(Case::Upper).as_str(), Span2::mixed_site());
let (value, new_check) = attr.meta.require_path_only().map_or_else(
|_| {
let value = &attr.meta.require_name_value().unwrap().value;
let value = match &attr.meta.require_name_value() {
Ok(meta) => &meta.value,
Err(e) => return (e.to_owned().into_compile_error(), None),
};
(
quote!(#value),
value.to_token_stream(),
Some(quote! {
if (value > Self::#const_ident.0) {
return None;
@ -208,9 +214,9 @@ fn parse_default(
}
let const_ident = Ident::new(KEY.to_case(Case::Upper).as_str(), Span2::mixed_site());
let value = attr.meta.require_path_only().map_or_else(
|_| {
let value = &attr.meta.require_name_value().unwrap().value;
quote!(#value)
|_| match &attr.meta.require_name_value() {
Ok(meta) => meta.value.to_token_stream(),
Err(e) => e.to_owned().into_compile_error(),
},
|_| quote!(#ty::#const_ident),
);
@ -237,13 +243,24 @@ fn parse_description(
return None;
}
let const_ident = Ident::new(KEY.to_case(Case::Upper).as_str(), Span2::mixed_site());
let value = &attr.meta.require_name_value().ok()?.value;
let value = match attr.meta.require_name_value() {
Ok(meta) => &meta.value,
Err(e) => {
return Some((e.into_compile_error(), const_ident, KEY));
}
};
let value = match value {
Expr::Lit(ExprLit {
attrs: _,
lit: Lit::Str(ref string),
}) => string.value(),
_ => panic!("doc comment must be a string"),
_ => {
return Some((
quote!(compile_error!("doc comment must be a string")),
const_ident,
KEY,
))
}
};
let trimmed_value = value.trim();
let impl_quote = quote! {