Skip to content

Commit

Permalink
Merge pull request #818 from piodul/dont-panic
Browse files Browse the repository at this point in the history
scylla-macros: report errors as compile errors, not panics
  • Loading branch information
piodul authored Oct 5, 2023
2 parents b51ac06 + 89a071c commit d60a8d9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 30 deletions.
10 changes: 5 additions & 5 deletions scylla-macros/src/from_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput};

/// #[derive(FromRow)] derives FromRow for struct
pub fn from_row_derive(tokens_input: TokenStream) -> TokenStream {
let item = syn::parse::<DeriveInput>(tokens_input).expect("No DeriveInput");
let path = crate::parser::get_path(&item).expect("No path");
let struct_fields = crate::parser::parse_named_fields(&item, "FromRow");
pub fn from_row_derive(tokens_input: TokenStream) -> Result<TokenStream, syn::Error> {
let item = syn::parse::<DeriveInput>(tokens_input)?;
let path = crate::parser::get_path(&item)?;
let struct_fields = crate::parser::parse_named_fields(&item, "FromRow")?;

let struct_name = &item.ident;
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
Expand Down Expand Up @@ -56,5 +56,5 @@ pub fn from_row_derive(tokens_input: TokenStream) -> TokenStream {
}
};

TokenStream::from(generated)
Ok(TokenStream::from(generated))
}
10 changes: 5 additions & 5 deletions scylla-macros/src/from_user_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput};

/// #[derive(FromUserType)] allows to parse a struct as User Defined Type
pub fn from_user_type_derive(tokens_input: TokenStream) -> TokenStream {
let item = syn::parse::<DeriveInput>(tokens_input).expect("No DeriveInput");
let path = crate::parser::get_path(&item).expect("Couldn't get path to the scylla crate");
let struct_fields = crate::parser::parse_named_fields(&item, "FromUserType");
pub fn from_user_type_derive(tokens_input: TokenStream) -> Result<TokenStream, syn::Error> {
let item = syn::parse::<DeriveInput>(tokens_input)?;
let path = crate::parser::get_path(&item)?;
let struct_fields = crate::parser::parse_named_fields(&item, "FromUserType")?;

let struct_name = &item.ident;
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
Expand Down Expand Up @@ -74,5 +74,5 @@ pub fn from_user_type_derive(tokens_input: TokenStream) -> TokenStream {
}
};

TokenStream::from(generated)
Ok(TokenStream::from(generated))
}
10 changes: 5 additions & 5 deletions scylla-macros/src/into_user_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput};

/// #[derive(IntoUserType)] allows to parse a struct as User Defined Type
pub fn into_user_type_derive(tokens_input: TokenStream) -> TokenStream {
let item = syn::parse::<DeriveInput>(tokens_input).expect("No DeriveInput");
let path = crate::parser::get_path(&item).expect("No path");
let struct_fields = crate::parser::parse_named_fields(&item, "IntoUserType");
pub fn into_user_type_derive(tokens_input: TokenStream) -> Result<TokenStream, syn::Error> {
let item = syn::parse::<DeriveInput>(tokens_input)?;
let path = crate::parser::get_path(&item)?;
let struct_fields = crate::parser::parse_named_fields(&item, "IntoUserType")?;

let struct_name = &item.ident;
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
Expand Down Expand Up @@ -45,5 +45,5 @@ pub fn into_user_type_derive(tokens_input: TokenStream) -> TokenStream {
}
};

TokenStream::from(generated)
Ok(TokenStream::from(generated))
}
12 changes: 8 additions & 4 deletions scylla-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,30 @@ mod value_list;
/// Works only on simple structs without generics etc
#[proc_macro_derive(FromRow, attributes(scylla_crate))]
pub fn from_row_derive(tokens_input: TokenStream) -> TokenStream {
from_row::from_row_derive(tokens_input)
let res = from_row::from_row_derive(tokens_input);
res.unwrap_or_else(|e| e.into_compile_error().into())
}

/// #[derive(FromUserType)] allows to parse a struct as User Defined Type
/// Works only on simple structs without generics etc
#[proc_macro_derive(FromUserType, attributes(scylla_crate))]
pub fn from_user_type_derive(tokens_input: TokenStream) -> TokenStream {
from_user_type::from_user_type_derive(tokens_input)
let res = from_user_type::from_user_type_derive(tokens_input);
res.unwrap_or_else(|e| e.into_compile_error().into())
}

/// #[derive(IntoUserType)] allows to parse a struct as User Defined Type
/// Works only on simple structs without generics etc
#[proc_macro_derive(IntoUserType, attributes(scylla_crate))]
pub fn into_user_type_derive(tokens_input: TokenStream) -> TokenStream {
into_user_type::into_user_type_derive(tokens_input)
let res = into_user_type::into_user_type_derive(tokens_input);
res.unwrap_or_else(|e| e.into_compile_error().into())
}

/// #[derive(ValueList)] derives ValueList for struct
/// Works only on simple structs without generics etc
#[proc_macro_derive(ValueList, attributes(scylla_crate))]
pub fn value_list_derive(tokens_input: TokenStream) -> TokenStream {
value_list::value_list_derive(tokens_input)
let res = value_list::value_list_derive(tokens_input);
res.unwrap_or_else(|e| e.into_compile_error().into())
}
28 changes: 22 additions & 6 deletions scylla-macros/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,32 @@ use syn::{Expr, Meta};
pub(crate) fn parse_named_fields<'a>(
input: &'a DeriveInput,
current_derive: &str,
) -> &'a FieldsNamed {
) -> Result<&'a FieldsNamed, syn::Error> {
match &input.data {
Data::Struct(data) => match &data.fields {
Fields::Named(named_fields) => named_fields,
_ => panic!(
"derive({}) works only for structs with named fields. Tuples don't need derive.",
Fields::Named(named_fields) => Ok(named_fields),
_ => Err(syn::Error::new_spanned(
data.struct_token,
format!(
"derive({}) works only for structs with named fields",
current_derive
),
)),
},
Data::Enum(e) => Err(syn::Error::new_spanned(
e.enum_token,
format!(
"derive({}) works only for structs with named fields",
current_derive
),
},
_ => panic!("derive({}) works only on structs!", current_derive),
)),
Data::Union(u) => Err(syn::Error::new_spanned(
u.union_token,
format!(
"derive({}) works only for structs with named fields",
current_derive
),
)),
}
}

Expand Down
10 changes: 5 additions & 5 deletions scylla-macros/src/value_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use syn::DeriveInput;

/// #[derive(ValueList)] allows to parse a struct as a list of values,
/// which can be fed to the query directly.
pub fn value_list_derive(tokens_input: TokenStream) -> TokenStream {
let item = syn::parse::<DeriveInput>(tokens_input).expect("No DeriveInput");
let path = crate::parser::get_path(&item).expect("No path");
let struct_fields = crate::parser::parse_named_fields(&item, "ValueList");
pub fn value_list_derive(tokens_input: TokenStream) -> Result<TokenStream, syn::Error> {
let item = syn::parse::<DeriveInput>(tokens_input)?;
let path = crate::parser::get_path(&item)?;
let struct_fields = crate::parser::parse_named_fields(&item, "ValueList")?;

let struct_name = &item.ident;
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
Expand All @@ -27,5 +27,5 @@ pub fn value_list_derive(tokens_input: TokenStream) -> TokenStream {
}
};

TokenStream::from(generated)
Ok(TokenStream::from(generated))
}

0 comments on commit d60a8d9

Please sign in to comment.