99#[ macro_use]
1010extern crate proc_macro_error2;
1111
12- use std:: collections:: HashMap ;
12+ use std:: collections:: HashSet ;
1313
1414use proc_macro2:: Span ;
1515use quote:: quote_spanned;
@@ -19,85 +19,6 @@ use syn::punctuated::Punctuated;
1919use syn:: spanned:: Spanned ;
2020use syn:: * ;
2121
22- struct Args {
23- name : Option < String > ,
24- short_name : bool ,
25- enter_on_poll : bool ,
26- properties : Vec < ( String , String ) > ,
27- }
28-
29- struct Property {
30- key : String ,
31- value : String ,
32- }
33-
34- impl Parse for Property {
35- fn parse ( input : ParseStream ) -> Result < Self > {
36- let key: LitStr = input. parse ( ) ?;
37- input. parse :: < Token ! [ : ] > ( ) ?;
38- let value: LitStr = input. parse ( ) ?;
39- Ok ( Property {
40- key : key. value ( ) ,
41- value : value. value ( ) ,
42- } )
43- }
44- }
45-
46- impl Parse for Args {
47- fn parse ( input : ParseStream ) -> Result < Self > {
48- let mut name = None ;
49- let mut short_name = false ;
50- let mut enter_on_poll = false ;
51- let mut properties = Vec :: new ( ) ;
52- let mut seen = HashMap :: new ( ) ;
53-
54- while !input. is_empty ( ) {
55- let ident: Ident = input. parse ( ) ?;
56- if seen. contains_key ( & ident. to_string ( ) ) {
57- return Err ( Error :: new ( ident. span ( ) , "duplicate argument" ) ) ;
58- }
59- seen. insert ( ident. to_string ( ) , ( ) ) ;
60- input. parse :: < Token ! [ =] > ( ) ?;
61- match ident. to_string ( ) . as_str ( ) {
62- "name" => {
63- let parsed_name: LitStr = input. parse ( ) ?;
64- name = Some ( parsed_name. value ( ) ) ;
65- }
66- "short_name" => {
67- let parsed_short_name: LitBool = input. parse ( ) ?;
68- short_name = parsed_short_name. value ;
69- }
70- "enter_on_poll" => {
71- let parsed_enter_on_poll: LitBool = input. parse ( ) ?;
72- enter_on_poll = parsed_enter_on_poll. value ;
73- }
74- "properties" => {
75- let content;
76- let _brace_token = braced ! ( content in input) ;
77- let property_list = content. parse_terminated ( Property :: parse, Token ! [ , ] ) ?;
78- for property in property_list {
79- if properties. iter ( ) . any ( |( k, _) | k == & property. key ) {
80- return Err ( Error :: new ( Span :: call_site ( ) , "duplicate property key" ) ) ;
81- }
82- properties. push ( ( property. key , property. value ) ) ;
83- }
84- }
85- _ => return Err ( Error :: new ( Span :: call_site ( ) , "unexpected identifier" ) ) ,
86- }
87- if !input. is_empty ( ) {
88- let _ = input. parse :: < Token ! [ , ] > ( ) ;
89- }
90- }
91-
92- Ok ( Args {
93- name,
94- short_name,
95- enter_on_poll,
96- properties,
97- } )
98- }
99- }
100-
10122/// An attribute macro designed to eliminate boilerplate code.
10223///
10324/// This macro automatically creates a span for the annotated function. The span name defaults to
@@ -117,6 +38,7 @@ impl Parse for Args {
11738/// used. Only available for `async fn`. Defaults to `false`.
11839/// * `properties` - A list of key-value pairs to be added as properties to the span. The value can
11940/// be a format string, where the function arguments are accessible. Defaults to `{}`.
41+ /// * `crate` - The path to the fastrace crate. Defaults to `::fastrace`.
12042///
12143/// # Examples
12244///
@@ -271,7 +193,109 @@ pub fn trace(
271193 . into ( )
272194}
273195
196+ struct Args {
197+ name : Option < String > ,
198+ short_name : bool ,
199+ enter_on_poll : bool ,
200+ properties : Vec < ( String , String ) > ,
201+ crate_path : Path ,
202+ }
203+
204+ impl Default for Args {
205+ fn default ( ) -> Self {
206+ Self {
207+ name : None ,
208+ short_name : false ,
209+ enter_on_poll : false ,
210+ properties : Vec :: new ( ) ,
211+ crate_path : parse_quote ! ( :: fastrace) ,
212+ }
213+ }
214+ }
215+
216+ struct Property {
217+ key : String ,
218+ value : String ,
219+ }
220+
221+ impl Parse for Property {
222+ fn parse ( input : ParseStream ) -> Result < Self > {
223+ let key: LitStr = input. parse ( ) ?;
224+ input. parse :: < Token ! [ : ] > ( ) ?;
225+ let value: LitStr = input. parse ( ) ?;
226+ Ok ( Property {
227+ key : key. value ( ) ,
228+ value : value. value ( ) ,
229+ } )
230+ }
231+ }
232+
233+ impl Parse for Args {
234+ fn parse ( input : ParseStream ) -> Result < Self > {
235+ let mut name = None ;
236+ let mut short_name = false ;
237+ let mut enter_on_poll = false ;
238+ let mut properties = Vec :: new ( ) ;
239+ let mut crate_path = parse_quote ! ( :: fastrace) ;
240+ let mut seen = HashSet :: new ( ) ;
241+
242+ while !input. is_empty ( ) {
243+ let key: Path = input. parse ( ) ?;
244+ let key = key
245+ . get_ident ( )
246+ . ok_or_else ( || Error :: new ( key. span ( ) , "expected identifier" ) ) ?;
247+ if seen. contains ( key) {
248+ return Err ( Error :: new ( key. span ( ) , "duplicate argument" ) ) ;
249+ }
250+ seen. insert ( key. clone ( ) ) ;
251+ input. parse :: < Token ! [ =] > ( ) ?;
252+ match key. to_string ( ) . as_str ( ) {
253+ "name" => {
254+ let parsed_name: LitStr = input. parse ( ) ?;
255+ name = Some ( parsed_name. value ( ) ) ;
256+ }
257+ "short_name" => {
258+ let parsed_short_name: LitBool = input. parse ( ) ?;
259+ short_name = parsed_short_name. value ;
260+ }
261+ "enter_on_poll" => {
262+ let parsed_enter_on_poll: LitBool = input. parse ( ) ?;
263+ enter_on_poll = parsed_enter_on_poll. value ;
264+ }
265+ "properties" => {
266+ let content;
267+ let _brace_token = braced ! ( content in input) ;
268+ let property_list = content. parse_terminated ( Property :: parse, Token ! [ , ] ) ?;
269+ for property in property_list {
270+ if properties. iter ( ) . any ( |( k, _) | k == & property. key ) {
271+ return Err ( Error :: new ( Span :: call_site ( ) , "duplicate property key" ) ) ;
272+ }
273+ properties. push ( ( property. key , property. value ) ) ;
274+ }
275+ }
276+ "crate" => {
277+ let parsed_crate_path: Path = input. parse ( ) ?;
278+ crate_path = parsed_crate_path;
279+ }
280+ _ => return Err ( Error :: new ( Span :: call_site ( ) , "unexpected identifier" ) ) ,
281+ }
282+ if !input. is_empty ( ) {
283+ let _ = input. parse :: < Token ! [ , ] > ( ) ;
284+ }
285+ }
286+
287+ Ok ( Args {
288+ name,
289+ short_name,
290+ enter_on_poll,
291+ properties,
292+ crate_path,
293+ } )
294+ }
295+ }
296+
274297fn gen_name ( span : Span , func_name : & str , args : & Args ) -> proc_macro2:: TokenStream {
298+ let crate_path = & args. crate_path ;
275299 match & args. name {
276300 Some ( name) if name. is_empty ( ) => {
277301 abort_call_site ! ( "`name` can not be empty" )
@@ -291,7 +315,7 @@ fn gen_name(span: Span, func_name: &str, args: &Args) -> proc_macro2::TokenStrea
291315 }
292316 None => {
293317 quote_spanned ! ( span=>
294- fastrace :: func_path!( )
318+ #crate_path :: func_path!( )
295319 )
296320 }
297321 }
@@ -350,23 +374,24 @@ fn gen_block(
350374) -> proc_macro2:: TokenStream {
351375 let name = gen_name ( block. span ( ) , func_name, args) ;
352376 let properties = gen_properties ( block. span ( ) , args) ;
377+ let crate_path = & args. crate_path ;
353378
354379 // Generate the instrumented function body.
355380 // If the function is an `async fn`, this will wrap it in an async block.
356381 // Otherwise, this will enter the span and then perform the rest of the body.
357382 if async_context {
358383 let block = if args. enter_on_poll {
359384 quote_spanned ! ( block. span( ) =>
360- fastrace :: future:: FutureExt :: enter_on_poll(
385+ #crate_path :: future:: FutureExt :: enter_on_poll(
361386 async move { #block } ,
362387 #name
363388 )
364389 )
365390 } else {
366391 quote_spanned ! ( block. span( ) =>
367392 {
368- let __span__ = fastrace :: Span :: enter_with_local_parent( #name ) #properties;
369- fastrace :: future:: FutureExt :: in_span(
393+ let __span__ = #crate_path :: Span :: enter_with_local_parent( #name ) #properties;
394+ #crate_path :: future:: FutureExt :: in_span(
370395 async move { #block } ,
371396 __span__,
372397 )
@@ -387,7 +412,7 @@ fn gen_block(
387412 }
388413
389414 quote_spanned ! ( block. span( ) =>
390- let __guard__ = fastrace :: local:: LocalSpan :: enter_with_local_parent( #name ) #properties;
415+ let __guard__ = #crate_path :: local:: LocalSpan :: enter_with_local_parent( #name ) #properties;
391416 #block
392417 )
393418 }
0 commit comments