macro: cleanup error handling, remove error module

syn::Error already covers this

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-07-18 14:41:26 +02:00
parent 09eaef022f
commit 4b3333aa5c
5 changed files with 28 additions and 44 deletions

View File

@ -16,7 +16,7 @@ pub fn api_macro(attr: TokenStream, item: TokenStream) -> Result<TokenStream, Er
let definition = match definition { let definition = match definition {
TokenTree::Group(ref group) if group.delimiter() == Delimiter::Brace => group.stream(), TokenTree::Group(ref group) if group.delimiter() == Delimiter::Brace => group.stream(),
_ => c_bail!(definition.span() => "expected api definition in braces"), _ => c_bail!(definition => "expected api definition in braces"),
}; };
let def_span = definition.span(); let def_span = definition.span();
@ -24,7 +24,7 @@ pub fn api_macro(attr: TokenStream, item: TokenStream) -> Result<TokenStream, Er
// Now parse the item, based on which we decide whether this is an API method which needs a // Now parse the item, based on which we decide whether this is an API method which needs a
// wrapper, or an API type which needs an ApiType implementation! // wrapper, or an API type which needs an ApiType implementation!
let item: syn::Item = syn::parse2(item).unwrap(); let mut item: syn::Item = syn::parse2(item).unwrap();
match item { match item {
syn::Item::Struct(ref itemstruct) => { syn::Item::Struct(ref itemstruct) => {
@ -34,13 +34,13 @@ pub fn api_macro(attr: TokenStream, item: TokenStream) -> Result<TokenStream, Er
Ok(output) Ok(output)
} }
syn::Item::Fn(func) => handle_function(def_span, definition, func), syn::Item::Fn(func) => handle_function(def_span, definition, func),
syn::Item::Enum(ref itemenum) => { syn::Item::Enum(ref mut itemenum) => {
let extra = handle_enum(definition, itemenum)?; let extra = handle_enum(definition, itemenum)?;
let mut output = item.into_token_stream(); let mut output = item.into_token_stream();
output.extend(extra); output.extend(extra);
Ok(output) Ok(output)
} }
_ => c_bail!(item.span() => "api macro currently only applies to structs and functions"), _ => c_bail!(item => "api macro currently only applies to structs and functions"),
} }
} }
@ -573,7 +573,7 @@ fn handle_named_struct_fields(
/// ///
/// For enums we automatically implement `ToString`, `FromStr`, and derive `Serialize` and /// For enums we automatically implement `ToString`, `FromStr`, and derive `Serialize` and
/// `Deserialize` via `serde_plain`. /// `Deserialize` via `serde_plain`.
fn handle_enum(mut definition: Object, item: &syn::ItemEnum) -> Result<TokenStream, Error> { fn handle_enum(mut definition: Object, item: &mut syn::ItemEnum) -> Result<TokenStream, Error> {
if item.generics.lt_token.is_some() { if item.generics.lt_token.is_some() {
c_bail!( c_bail!(
item.generics.span(), item.generics.span(),
@ -588,7 +588,7 @@ fn handle_enum(mut definition: Object, item: &syn::ItemEnum) -> Result<TokenStre
let mut display_entries = TokenStream::new(); let mut display_entries = TokenStream::new();
let mut from_str_entries = TokenStream::new(); let mut from_str_entries = TokenStream::new();
for variant in item.variants.iter() { for variant in item.variants.iter_mut() {
if variant.fields != syn::Fields::Unit { if variant.fields != syn::Fields::Unit {
c_bail!(variant.span(), "#[api] enums cannot have fields"); c_bail!(variant.span(), "#[api] enums cannot have fields");
} }
@ -610,7 +610,7 @@ fn handle_enum(mut definition: Object, item: &syn::ItemEnum) -> Result<TokenStre
let apidef = ParameterDefinition::from_object(definition)?; let apidef = ParameterDefinition::from_object(definition)?;
if let Some(validate) = apidef.validate { if let Some(validate) = apidef.validate {
c_bail!(validate.span() => "validators are not allowed on enum types"); c_bail!(validate => "validators are not allowed on enum types");
} }
let description = common.description; let description = common.description;

View File

@ -1,31 +0,0 @@
#[derive(Debug)]
pub struct CompileError {
pub tokens: proc_macro::TokenStream,
}
unsafe impl Send for CompileError {}
unsafe impl Sync for CompileError {}
impl std::fmt::Display for CompileError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "generic compile error")
}
}
impl std::error::Error for CompileError {}
macro_rules! c_format_err {
($span:expr => $($msg:tt)*) => {
crate::error::CompileError {
tokens: ::quote::quote_spanned! { $span => compile_error!($($msg)*); }.into()
}
};
($span:expr, $($msg:tt)*) => { c_format_err!($span => $($msg)*) }
}
macro_rules! c_bail {
($span:expr => $($msg:tt)*) => {
return Err(c_format_err!($span => $($msg)*).into());
};
($span:expr, $($msg:tt)*) => { c_bail!($span => $($msg)*) }
}

View File

@ -6,19 +6,18 @@ extern crate proc_macro2;
use proc_macro::TokenStream; use proc_macro::TokenStream;
#[macro_use] #[macro_use]
mod error; mod util;
mod api_def; mod api_def;
mod parsing; mod parsing;
mod types; mod types;
mod util;
mod api_macro; mod api_macro;
mod router_macro; mod router_macro;
fn handle_error(kind: &'static str, err: failure::Error) -> TokenStream { fn handle_error(kind: &'static str, err: failure::Error) -> TokenStream {
match err.downcast::<error::CompileError>() { match err.downcast::<syn::Error>() {
Ok(err) => err.tokens, Ok(err) => err.to_compile_error().into(),
Err(err) => panic!("error in {}: {}", kind, err), Err(err) => panic!("error in {}: {}", kind, err),
} }
} }

View File

@ -287,7 +287,7 @@ pub fn parse_object(tokens: TokenStream) -> Result<Object, Error> {
let value = parse_object_value(&mut tokens, &key)?; let value = parse_object_value(&mut tokens, &key)?;
if out.insert(key.clone(), value).is_some() { if out.insert(key.clone(), value).is_some() {
c_bail!(key.span() => "duplicate entry: {}", key.as_str()); c_bail!(key.span(), "duplicate entry: {}", key.as_str());
} }
} }
@ -313,7 +313,7 @@ fn parse_object_value(tokens: &mut TokenIter, key: &Name) -> Result<Expression,
Some(token) => token, Some(token) => token,
None => { None => {
if first { if first {
c_bail!(key.span(), "missing value after key '{}'", key.as_str()); c_bail!(key => "missing value after key '{}'", key.as_str());
} }
break; break;
} }

View File

@ -1,3 +1,19 @@
use proc_macro2::Ident;
use syn::Token;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
macro_rules! c_format_err {
($span:expr => $($msg:tt)*) => { syn::Error::new_spanned($span, format!($($msg)*)) };
($span:expr, $($msg:tt)*) => { syn::Error::new($span, format!($($msg)*)) };
}
macro_rules! c_bail {
($span:expr => $($msg:tt)*) => { return Err(c_format_err!($span => $($msg)*).into()) };
($span:expr, $($msg:tt)*) => { return Err(c_format_err!($span, $($msg)*).into()) };
}
/// Convert `this_kind_of_text` to `ThisKindOfText`. /// Convert `this_kind_of_text` to `ThisKindOfText`.
pub fn to_camel_case(text: &str) -> String { pub fn to_camel_case(text: &str) -> String {
let mut out = String::new(); let mut out = String::new();