Commit 33f19c38 authored by Raphaël Gomès's avatar Raphaël Gomès
Browse files

Move logic into a subcrate to avoid client crates from adding our dependencies

parent be6869fb3160
^target/
^libs/micro-timer-macros/target/
^.idea/
\ No newline at end of file
......@@ -18,8 +18,8 @@ name = "ctor"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -38,13 +38,22 @@ dependencies = [
[[package]]
name = "micro-timer"
version = "0.1.2"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"micro-timer-macros 0.2.0",
"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "micro-timer-macros"
version = "0.2.0"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"quote 1.0.3 (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)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -76,7 +85,7 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -89,11 +98,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -130,9 +139,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
"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 quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"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 syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"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"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
......
[workspace]
[package]
name = "micro-timer"
description = "Dumb tiny logging timer"
......@@ -9,15 +11,9 @@ edition = "2018"
homepage = "https://heptapod.octobus.net/Alphare/micro-timer"
repository = "https://heptapod.octobus.net/Alphare/micro-timer"
[lib]
proc-macro = true
[dependencies]
syn = {version = "1.0.16", features = ["full", "extra-traits"]}
quote = "1.0.2"
proc-macro2 = "1.0.9"
scopeguard = "1.1.0"
micro-timer-macros = {path = "libs/micro-timer-macros"}
[dev-dependencies]
log = "0.4.8"
pretty_assertions = "0.6.1"
log = "0.4.8"
\ No newline at end of file
[package]
name = "micro-timer-macros"
description = "Macros for the micro-timer crate"
license-file = "LICENCE"
readme = "README.md"
version = "0.2.0"
authors = ["Raphaël Gomès <rgomes@octobus.net>"]
edition = "2018"
homepage = "https://heptapod.octobus.net/Alphare/micro-timer"
repository = "https://heptapod.octobus.net/Alphare/micro-timer"
[lib]
proc-macro = true
[dependencies]
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"
pretty_assertions = "0.6.1"
Copyright (c) 2020 Raphaël Gomès
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
\ No newline at end of file
# Micro-timer-macros
Do not use this crate, it is meant for internal use only. Use [``micro-timer``](https://crates.io/crates/micro-timer) instead.
\ No newline at end of file
// micro-timer-macros
//
// Do not use this crate. It is only meant for internal use. Use `micro-timer`
// instead.
//
// Copyright 2020, Raphaël Gomès <rgomes@octobus.net>
/// `extern crate` Required even for 2018 edition
extern crate proc_macro;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::spanned::Spanned;
/// Logs the time elapsed for the body of the target function for each call.
///
/// ```compile_fail
/// use micro_timer::timed;
///
/// #[timed] // Can only be used on functions
/// struct Thing;
/// ```
#[proc_macro_attribute]
pub fn timed(
attrs: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
inner_timed(attrs.into(), item.into()).into()
}
/// This is the unit-testable version using `proc_macro2`
fn inner_timed(_attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
let ast = syn::parse2(fn_ts.clone()).unwrap();
let func = match parse_function(ast) {
Ok(f) => f,
Err(stream) => return stream,
};
let mut outer = func.clone();
let original_func_name = func.sig.ident.to_string();
let inner_block: TokenStream = func
.block
.stmts
.iter()
.map(|s| s.to_token_stream())
.collect();
let span = outer.sig.ident.span();
// We use `__micro_timer_inner` as a name in case it pops up in error
// messages to make it obvious that it's an issue caused by this crate,
// it is not meant to prevent name collision.
let block = quote_spanned! {
span=>
{
let __micro_timer_instant = ::std::time::Instant::now();
let __micro_timer_guard =
::micro_timer::scopeguard::guard_on_success(
__micro_timer_instant,
|timer| {
crate::log::trace!(
"Duration of `{}`: {:?}",
#original_func_name,
timer.elapsed()
);
}
);
#inner_block
}
};
outer.block = syn::parse2(block).unwrap();
(quote! {#outer})
}
fn parse_function(item: syn::Item) -> Result<syn::ItemFn, TokenStream> {
match item {
syn::Item::Fn(func) => Ok(func),
i => Err(quote_spanned! {
i.span()=>
compile_error!("`#[timed]` can only be used on functions");
#i
}),
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_output() {
let input = syn::parse_quote! {
fn my_super_function(_value: usize) -> usize {
let timer = 10;
timer
}
};
let expected: TokenStream = syn::parse_quote! {
fn my_super_function(_value: usize) -> usize {
let __micro_timer_instant = ::std::time::Instant::now();
::micro_timer::scopeguard::guard_on_success(
__micro_timer_instant,
|timer| {
crate::log::trace!(
"Duration of `{}`: {:?}",
"my_super_function",
timer.elapsed()
);
}
);
let timer = 10;
timer
}
};
let output = inner_timed(TokenStream::new(), input);
assert_eq!(output.to_string(), expected.to_string());
}
}
......@@ -2,113 +2,5 @@
//
// Copyright 2020, Raphaël Gomès <rgomes@octobus.net>
/// `extern crate` Required even for 2018 edition
extern crate proc_macro;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
/// Logs the time elapsed for the body of the target function for each call.
///
/// ```compile_fail
/// use micro_timer::timed;
///
/// #[timed] // Can only be used on functions
/// struct Thing;
/// ```
#[proc_macro_attribute]
pub fn timed(
attrs: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
inner_timed(attrs.into(), item.into()).into()
}
/// This is the unit-testable version using `proc_macro2`
fn inner_timed(_attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
let ast = syn::parse2(fn_ts.clone()).unwrap();
let func = match parse_function(ast) {
Ok(f) => f,
Err(stream) => return stream,
};
let mut outer = func.clone();
let original_func_name = func.sig.ident.to_string();
let inner_block = &func.block;
let span = outer.sig.ident.span();
// We use `__micro_timer_inner` as a name in case it pops up in error
// messages to make it obvious that it's an issue caused by this crate,
// it is not meant to prevent name collision.
let block = quote_spanned! {
span=>
{
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()
);
}
);
#inner_block
}
};
outer.block = syn::parse2(block).unwrap();
(quote! {#outer})
}
fn parse_function(item: syn::Item) -> Result<syn::ItemFn, TokenStream> {
match item {
syn::Item::Fn(func) => Ok(func),
i => Err(quote_spanned! {
i.span()=>
compile_error!("`#[timed]` can only be used on functions");
#i
}),
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_output() {
let input = syn::parse_quote! {
fn my_super_function(_value: usize) -> usize {
let timer = 10;
timer
}
};
let expected: TokenStream = syn::parse_quote! {
fn my_super_function(_value: usize) -> usize {
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 output = inner_timed(TokenStream::new(), input);
assert_eq!(output.to_string(), expected.to_string());
}
}
pub extern crate scopeguard;
pub use micro_timer_macros::timed;
......@@ -2,7 +2,6 @@
//!
//! 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;
......
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