Commit 300d5af2 authored by Raphaël Gomès's avatar Raphaël Gomès
Browse files

Use scopeguard instead of trying to thing of every possible problem

parent 69911827ce01
......@@ -43,6 +43,7 @@ dependencies = [
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -81,6 +82,11 @@ dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.16"
......@@ -125,6 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
......
......@@ -16,6 +16,7 @@ proc-macro = true
syn = {version = "1.0.16", features = ["full", "extra-traits"]}
quote = "1.0.2"
proc-macro2 = "1.0.9"
scopeguard = "1.1.0"
[dev-dependencies]
log = "0.4.8"
......
......@@ -33,38 +33,7 @@ fn inner_timed(_attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
};
let mut outer = func.clone();
outer.sig.ident = func.sig.ident.to_owned();
let original_func_name = func.sig.ident.to_string();
// Figure out if the `inner` closure needs to be mut based on whether
// the original signature contains a `mut self`, `&mut self`,
// `mut thing: T` or a `thing: &mut T`.
// There are probably more ways you can have a signature need mutability,
// but this is good enough for now.
let needs_mut = func.sig.inputs.iter().any(|arg| match arg {
syn::FnArg::Receiver(rec) => rec.mutability.is_some(),
syn::FnArg::Typed(typed) => match *typed.pat {
syn::Pat::Ident(syn::PatIdent { mutability, .. }) => {
// Is it `mut arg: T`?
if mutability.is_some() {
return true;
}
// Is it `arg: &mut T`?
match *typed.ty {
syn::Type::Reference(ref r) => r.mutability.is_some(),
_ => false,
}
}
_ => false,
},
});
let mutability = if needs_mut {
quote! {mut}
} else {
quote! {}
};
let inner_block = &func.block;
let span = outer.sig.ident.span();
......@@ -74,17 +43,19 @@ fn inner_timed(_attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
let block = quote_spanned! {
span=>
{
let timer = ::std::time::Instant::now();
let #mutability __micro_timer_inner = || #inner_block;
let ret = __micro_timer_inner();
crate::log::trace!(
"Duration of `{}`: {:?}",
#original_func_name,
timer.elapsed()
let __micro_timer_instant = ::std::time::Instant::now();
crate::scopeguard::guard_on_success(
__micro_timer_instant,
|timer| {
crate::log::trace!(
"Duration of `{}`: {:?}",
#original_func_name,
timer.elapsed()
);
}
);
ret
#inner_block
}
};
......@@ -120,81 +91,21 @@ mod tests {
let expected: TokenStream = syn::parse_quote! {
fn my_super_function(_value: usize) -> usize {
let timer = ::std::time::Instant::now();
let __micro_timer_inner = | | {
let __micro_timer_instant = ::std::time::Instant::now();
crate::scopeguard::guard_on_success(
__micro_timer_instant,
|timer| {
crate::log::trace!(
"Duration of `{}`: {:?}",
"my_super_function",
timer.elapsed()
);
}
);
{
let timer = 10;
timer
};
let ret = __micro_timer_inner();
crate::log::trace!(
"Duration of `{}`: {:?}",
"my_super_function",
timer.elapsed()
);
ret
}
};
let output = inner_timed(TokenStream::new(), input);
assert_eq!(output.to_string(), expected.to_string());
}
#[test]
fn test_mut_output() {
let input = syn::parse_quote! {
fn my_super_function(mut value: usize) {
value = 10;
}
};
let expected: TokenStream = syn::parse_quote! {
fn my_super_function(mut value: usize) {
let timer = ::std::time::Instant::now();
let mut __micro_timer_inner = | | {
value = 10;
};
let ret = __micro_timer_inner();
crate::log::trace!(
"Duration of `{}`: {:?}",
"my_super_function",
timer.elapsed()
);
ret
}
};
let output = inner_timed(TokenStream::new(), input);
assert_eq!(output.to_string(), expected.to_string());
}
#[test]
fn test_ref_mut_output() {
let input = syn::parse_quote! {
fn my_super_function(value: &mut String) {
value.push('a');
}
};
let expected: TokenStream = syn::parse_quote! {
fn my_super_function(value: &mut String) {
let timer = ::std::time::Instant::now();
let mut __micro_timer_inner = | | {
value.push('a');
};
let ret = __micro_timer_inner();
crate::log::trace!(
"Duration of `{}`: {:?}",
"my_super_function",
timer.elapsed()
);
ret
}
}
};
let output = inner_timed(TokenStream::new(), input);
......
......@@ -2,6 +2,7 @@
//!
//! Check if the macro actually behaves as intended.
extern crate scopeguard;
use log::{self, LevelFilter, Metadata, Record};
use micro_timer::timed;
use std::sync::atomic::{AtomicIsize, Ordering};
......
//! Compilation tests: they only test if the compilation fails, not the
//! macro output
extern crate scopeguard;
use log;
use micro_timer::timed;
......@@ -19,7 +20,9 @@ fn check_name_conflict() {
fn test_mut() {
#[timed]
fn thing(mut value: usize) {
println!("{}", value);
value = 5;
println!("{}", value);
}
thing(1);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment