From 1d81b59163fd5e43bc28248fd659940efdf70fd7 Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Tue, 28 Mar 2023 17:26:03 +0400 Subject: [PATCH] Derive derives on Error not ErrorKind --- Cargo.toml | 6 +-- derive/Cargo.toml | 4 +- derive/src/lib.rs | 94 +++++++++++++++++++++++++++-------------------- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc4f466..dbce9c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ctxerr" -version = "0.2.0" +version = "0.2.3" authors = ["Andrey Tkachenko "] repository = "https://github.com/andreytkachenko/ctxerr.git" keywords = ["error", "handling", "thiserror", "context", "backtrace"] @@ -15,5 +15,5 @@ resolver = "2" members = ["derive"] [dependencies] -ctxerr_derive = {version = "0.3.0", path = "derive"} -thiserror = "1.0.39" +ctxerr_derive = {version = "0.4.0", path = "derive"} +thiserror = "1.0.40" diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 0cc622e..078901f 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ctxerr_derive" -version = "0.3.0" +version = "0.4.0" authors = ["Andrey Tkachenko "] repository = "https://github.com/andreytkachenko/ctxerr.git" keywords = ["error", "handling", "thiserror", "context", "backtrace"] @@ -16,4 +16,4 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = {version = "1", features = ["full"]} +syn = {version = "2", features = ["full"]} diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 5b8757e..aeb1ab4 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -11,7 +11,7 @@ pub fn ctxerr( _metadata: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let ast: DeriveInput = syn::parse(input).unwrap(); + let mut ast: DeriveInput = syn::parse(input).unwrap(); let name = ast.ident.to_string(); if !name.ends_with("Kind") { panic!("Ttypename should ends with `Kind`!"); @@ -19,53 +19,69 @@ pub fn ctxerr( let name_ident = &ast.ident; let base_name = Ident::new(&name[0..name.len() - 4], ast.ident.span()); + let attrs = ast + .attrs + .drain(..) + .filter_map(|x| match x.meta { + syn::Meta::List(list) => Some(list.tokens), + _ => None, + }) + .collect::>(); + let tokens = quote! { - #[derive(Debug, ctxerr::thiserror::Error)] - #ast + pub use __private::*; - #[derive(ctxerr::thiserror::Error)] - pub struct #base_name { - kind: #name_ident, - backtrace: Option, - location: Option<&'static core::panic::Location<'static>>, - } + mod __private { + use super::*; + use ctxerr::thiserror; - impl std::fmt::Debug for #base_name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "{:?}: {}", self.kind, self.kind)?; - if let Some(b) = &self.backtrace { - writeln!(f, "backtrace: \n{}", b)?; - } + #[derive(Debug, ctxerr::thiserror::Error)] + #ast - Ok(()) + #[derive(ctxerr::thiserror::Error #(, #attrs)*)] + pub struct #base_name { + kind: #name_ident, + backtrace: Option, + location: Option<&'static core::panic::Location<'static>>, } - } - impl std::fmt::Display for #base_name { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}: {}", self.kind, self.kind)?; - if let Some(loc) = self.location { - writeln!(f, " file: {}:{}:{}", loc.file(), loc.line(), loc.column())?; - } else { - writeln!(f)?; + impl std::fmt::Debug for #base_name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "{:?}: {}", self.kind, self.kind)?; + if let Some(b) = &self.backtrace { + writeln!(f, "backtrace: \n{}", b)?; + } + + Ok(()) } - - if let Some(b) = &self.backtrace { - writeln!(f, "backtrace: \n{}", b)?; - } - - Ok(()) } - } - impl> From for #base_name { - #[track_caller] - fn from(val: T) -> Self { - let b = std::backtrace::Backtrace::capture(); - Self{ - kind: val.into(), - backtrace: Some(std::backtrace::Backtrace::capture()), - location: Some(core::panic::Location::caller()), + impl std::fmt::Display for #base_name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}: {}", self.kind, self.kind)?; + if let Some(loc) = self.location { + writeln!(f, " file: {}:{}:{}", loc.file(), loc.line(), loc.column())?; + } else { + writeln!(f)?; + } + + if let Some(b) = &self.backtrace { + writeln!(f, "backtrace: \n{}", b)?; + } + + Ok(()) + } + } + + impl> From for #base_name { + #[track_caller] + fn from(val: T) -> Self { + let b = std::backtrace::Backtrace::capture(); + Self{ + kind: val.into(), + backtrace: Some(std::backtrace::Backtrace::capture()), + location: Some(core::panic::Location::caller()), + } } } }