Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom formatting #37

Merged
merged 12 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/example_custom_format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use trace::trace;

trace::init_depth_var!();

fn main() {
foo(5, 4);
}

#[trace(format_enter = "{y} and {z} {{7}}", format_exit = "{r} * {r}")]
fn foo(z: u32, y: u32) -> u32 {
z
}

#[cfg(test)]
#[macro_use]
mod trace_test;

#[cfg(test)]
trace_test!(test_custom_format, main());
2 changes: 2 additions & 0 deletions examples/expected_test_outputs/test_custom_format.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[+] Entering foo(4 and 5 {7})
[-] Exiting foo = 5 * 5
101 changes: 81 additions & 20 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use syn::{self, spanned::Spanned};
pub(crate) struct Args {
pub(crate) prefix_enter: String,
pub(crate) prefix_exit: String,
pub(crate) format_enter: Option<String>,
pub(crate) format_exit: Option<String>,
pub(crate) filter: Filter,
pub(crate) pause: bool,
pub(crate) pretty: bool,
Expand All @@ -23,6 +25,17 @@ const DEFAULT_PAUSE: bool = false;
const DEFAULT_PRETTY: bool = false;
const DEFAULT_LOGGING: bool = false;

macro_rules! try_extract_str {
($lit:expr, $meta:expr, $arg_ty:ident) => {{
match *$lit {
syn::Lit::Str(ref lit_str) => Ok(Arg::$arg_ty($meta.span(), lit_str.value())),
_ => Err(vec![syn::Error::new_spanned(
$lit,
format!("`{}` must have a string value", stringify!($arg_ty)),
)]),
}
}};
}
impl Args {
pub(crate) fn from_raw_args(raw_args: syn::AttributeArgs) -> Result<Self, Vec<syn::Error>> {
// Different types of arguments accepted by `#[trace]`;
Expand All @@ -35,6 +48,8 @@ impl Args {
Pause(proc_macro2::Span, bool),
Pretty(proc_macro2::Span, bool),
Logging(proc_macro2::Span, bool),
FormatEnter(proc_macro2::Span, String),
FormatExit(proc_macro2::Span, String),
}

// Parse arguments
Expand All @@ -43,6 +58,8 @@ impl Args {
enum ArgName {
PrefixEnter,
PrefixExit,
FormatEnter,
FormatExit,
Enable,
Disable,
Pause,
Expand All @@ -54,6 +71,8 @@ impl Args {
let arg_name = match ident.to_string().as_str() {
"prefix_enter" => ArgName::PrefixEnter,
"prefix_exit" => ArgName::PrefixExit,
"format_enter" => ArgName::FormatEnter,
"format_exit" => ArgName::FormatExit,
"enable" => ArgName::Enable,
"disable" => ArgName::Disable,
"pause" => ArgName::Pause,
Expand All @@ -79,6 +98,18 @@ impl Args {
"`prefix_exit` requires a string value",
)]
};
let format_enter_type_error = || {
vec![syn::Error::new_spanned(
ident.clone(),
"`format_enter` requires a string value",
)]
};
let format_exit_type_error = || {
vec![syn::Error::new_spanned(
ident.clone(),
"`format_exit` requires a string value",
)]
};
let enable_type_error = || {
vec![syn::Error::new_spanned(
ident.clone(),
Expand Down Expand Up @@ -115,11 +146,12 @@ impl Args {
ArgName::Pause => Ok(Arg::Pause(meta.span(), true)),
ArgName::Pretty => Ok(Arg::Pretty(meta.span(), true)),
ArgName::Logging => Ok(Arg::Logging(meta.span(), true)),

ArgName::PrefixEnter => Err(prefix_enter_type_error()),
ArgName::PrefixExit => Err(prefix_exit_type_error()),
ArgName::Enable => Err(enable_type_error()),
ArgName::Disable => Err(disable_type_error()),
ArgName::FormatEnter => Err(format_enter_type_error()),
ArgName::FormatExit => Err(format_exit_type_error()),
},
syn::Meta::List(syn::MetaList { ref nested, .. }) => match arg_name {
ArgName::Enable => {
Expand Down Expand Up @@ -172,27 +204,14 @@ impl Args {
ArgName::Pause => Err(pause_type_error()),
ArgName::Pretty => Err(pretty_type_error()),
ArgName::Logging => Err(logging_type_error()),
ArgName::FormatEnter => Err(format_enter_type_error()),
ArgName::FormatExit => Err(format_exit_type_error()),
},
syn::Meta::NameValue(syn::MetaNameValue { ref lit, .. }) => match arg_name {
ArgName::PrefixEnter => match *lit {
syn::Lit::Str(ref lit_str) => {
Ok(Arg::PrefixEnter(meta.span(), lit_str.value()))
}
_ => Err(vec![syn::Error::new_spanned(
lit,
"`prefix_enter` must have a string value",
)]),
},
ArgName::PrefixExit => match *lit {
syn::Lit::Str(ref lit_str) => {
Ok(Arg::PrefixExit(meta.span(), lit_str.value()))
}
_ => Err(vec![syn::Error::new_spanned(
lit,
"`prefix_exit` must have a string value",
)]),
},

ArgName::PrefixEnter => try_extract_str!(lit, meta, PrefixEnter),
ArgName::PrefixExit => try_extract_str!(lit, meta, PrefixExit),
ArgName::FormatEnter => try_extract_str!(lit, meta, FormatEnter),
ArgName::FormatExit => try_extract_str!(lit, meta, FormatExit),
ArgName::Enable => Err(enable_type_error()),
ArgName::Disable => Err(disable_type_error()),
ArgName::Pause => Err(pause_type_error()),
Expand All @@ -209,6 +228,8 @@ impl Args {

let mut prefix_enter_args = vec![];
let mut prefix_exit_args = vec![];
let mut format_enter_args = vec![];
let mut format_exit_args = vec![];
let mut enable_args = vec![];
let mut disable_args = vec![];
let mut pause_args = vec![];
Expand All @@ -227,6 +248,8 @@ impl Args {
Arg::Pause(span, b) => pause_args.push((span, b)),
Arg::Pretty(span, b) => pretty_args.push((span, b)),
Arg::Logging(span, b) => logging_args.push((span, b)),
Arg::FormatEnter(span, s) => format_enter_args.push((span, s)),
Arg::FormatExit(span, s) => format_exit_args.push((span, s)),
},
Err(es) => errors.extend(es),
}
Expand All @@ -247,6 +270,20 @@ impl Args {
.map(|(span, _)| syn::Error::new(*span, "duplicate `prefix_exit`")),
);
}
if format_enter_args.len() >= 2 {
errors.extend(
format_enter_args
.iter()
.map(|(span, _)| syn::Error::new(*span, "duplicate `format_enter`")),
);
}
if format_exit_args.len() >= 2 {
errors.extend(
format_exit_args
.iter()
.map(|(span, _)| syn::Error::new(*span, "duplicate `format_exit`")),
);
}
if enable_args.len() >= 2 {
errors.extend(
enable_args
Expand Down Expand Up @@ -294,6 +331,26 @@ impl Args {
"cannot have both `enable` and `disable`",
));
}
if pretty_args.len() == 1 && format_enter_args.len() == 1 {
errors.push(syn::Error::new(
pretty_args[0].0,
"cannot have both `pretty` and `format_enter`",
));
errors.push(syn::Error::new(
format_enter_args[0].0,
"cannot have both `pretty` and `format_enter`",
));
}
if pretty_args.len() == 1 && format_exit_args.len() == 1 {
errors.push(syn::Error::new(
pretty_args[0].0,
"cannot have both `pretty` and `format_exit`",
));
errors.push(syn::Error::new(
format_exit_args[0].0,
"cannot have both `pretty` and `format_exit`",
));
}

if errors.is_empty() {
macro_rules! first_no_span {
Expand All @@ -306,6 +363,8 @@ impl Args {
.unwrap_or_else(|| DEFAULT_PREFIX_ENTER.to_owned());
let prefix_exit =
first_no_span!(prefix_exit_args).unwrap_or_else(|| DEFAULT_PREFIX_EXIT.to_owned());
let format_enter = first_no_span!(format_enter_args);
let format_exit = first_no_span!(format_exit_args);
let filter = match (first_no_span!(enable_args), first_no_span!(disable_args)) {
(None, None) => Filter::None,
(Some(idents), None) => Filter::Enable(idents),
Expand All @@ -323,6 +382,8 @@ impl Args {
pause,
pretty,
logging,
format_enter,
format_exit,
})
} else {
Err(errors)
Expand Down
Loading
Loading