11use proc_macro:: TokenStream ;
2- use proc_macro2:: Span ;
2+ use proc_macro2:: { Ident , Span } ;
33use quote:: { quote, quote_spanned, ToTokens } ;
44use syn:: parse:: Parser ;
55
@@ -29,13 +29,15 @@ struct FinalConfig {
2929 flavor : RuntimeFlavor ,
3030 worker_threads : Option < usize > ,
3131 start_paused : Option < bool > ,
32+ package_name : Option < String > ,
3233}
3334
3435/// Config used in case of the attribute not being able to build a valid config
3536const DEFAULT_ERROR_CONFIG : FinalConfig = FinalConfig {
3637 flavor : RuntimeFlavor :: CurrentThread ,
3738 worker_threads : None ,
3839 start_paused : None ,
40+ package_name : None ,
3941} ;
4042
4143struct Configuration {
@@ -45,6 +47,7 @@ struct Configuration {
4547 worker_threads : Option < ( usize , Span ) > ,
4648 start_paused : Option < ( bool , Span ) > ,
4749 is_test : bool ,
50+ package_name : Option < String > ,
4851}
4952
5053impl Configuration {
@@ -59,6 +62,7 @@ impl Configuration {
5962 worker_threads : None ,
6063 start_paused : None ,
6164 is_test,
65+ package_name : None ,
6266 }
6367 }
6468
@@ -104,6 +108,15 @@ impl Configuration {
104108 Ok ( ( ) )
105109 }
106110
111+ fn set_package_name ( & mut self , name : syn:: Lit , span : Span ) -> Result < ( ) , syn:: Error > {
112+ if self . package_name . is_some ( ) {
113+ return Err ( syn:: Error :: new ( span, "`package` set multiple times." ) ) ;
114+ }
115+ let name_ident = parse_ident ( name, span, "package" ) ?;
116+ self . package_name = Some ( name_ident. to_string ( ) ) ;
117+ Ok ( ( ) )
118+ }
119+
107120 fn macro_name ( & self ) -> & ' static str {
108121 if self . is_test {
109122 "tokio::test"
@@ -151,6 +164,7 @@ impl Configuration {
151164 } ;
152165
153166 Ok ( FinalConfig {
167+ package_name : self . package_name . clone ( ) ,
154168 flavor,
155169 worker_threads,
156170 start_paused,
@@ -185,6 +199,27 @@ fn parse_string(int: syn::Lit, span: Span, field: &str) -> Result<String, syn::E
185199 }
186200}
187201
202+ fn parse_ident ( lit : syn:: Lit , span : Span , field : & str ) -> Result < Ident , syn:: Error > {
203+ match lit {
204+ syn:: Lit :: Str ( s) => {
205+ let err = syn:: Error :: new (
206+ span,
207+ format ! (
208+ "Failed to parse value of `{}` as ident: \" {}\" " ,
209+ field,
210+ s. value( )
211+ ) ,
212+ ) ;
213+ let path = s. parse :: < syn:: Path > ( ) . map_err ( |_| err. clone ( ) ) ?;
214+ path. get_ident ( ) . cloned ( ) . ok_or_else ( || err)
215+ }
216+ _ => Err ( syn:: Error :: new (
217+ span,
218+ format ! ( "Failed to parse value of `{}` as ident." , field) ,
219+ ) ) ,
220+ }
221+ }
222+
188223fn parse_bool ( bool : syn:: Lit , span : Span , field : & str ) -> Result < bool , syn:: Error > {
189224 match bool {
190225 syn:: Lit :: Bool ( b) => Ok ( b. value ) ,
@@ -243,9 +278,15 @@ fn build_config(
243278 let msg = "Attribute `core_threads` is renamed to `worker_threads`" ;
244279 return Err ( syn:: Error :: new_spanned ( namevalue, msg) ) ;
245280 }
281+ "package" => {
282+ config. set_package_name (
283+ namevalue. lit . clone ( ) ,
284+ syn:: spanned:: Spanned :: span ( & namevalue. lit ) ,
285+ ) ?;
286+ }
246287 name => {
247288 let msg = format ! (
248- "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`" ,
289+ "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `package` " ,
249290 name,
250291 ) ;
251292 return Err ( syn:: Error :: new_spanned ( namevalue, msg) ) ;
@@ -275,7 +316,7 @@ fn build_config(
275316 format ! ( "The `{}` attribute requires an argument." , name)
276317 }
277318 name => {
278- format ! ( "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`" , name)
319+ format ! ( "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `package` " , name)
279320 }
280321 } ;
281322 return Err ( syn:: Error :: new_spanned ( path, msg) ) ;
@@ -313,12 +354,17 @@ fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> To
313354 ( start, end)
314355 } ;
315356
357+ let package_name = config
358+ . package_name
359+ . map ( |name| Ident :: new ( & name, last_stmt_start_span) )
360+ . unwrap_or_else ( || Ident :: new ( "tokio" , last_stmt_start_span) ) ;
361+
316362 let mut rt = match config. flavor {
317363 RuntimeFlavor :: CurrentThread => quote_spanned ! { last_stmt_start_span=>
318- tokio :: runtime:: Builder :: new_current_thread( )
364+ #package_name :: runtime:: Builder :: new_current_thread( )
319365 } ,
320366 RuntimeFlavor :: Threaded => quote_spanned ! { last_stmt_start_span=>
321- tokio :: runtime:: Builder :: new_multi_thread( )
367+ #package_name :: runtime:: Builder :: new_multi_thread( )
322368 } ,
323369 } ;
324370 if let Some ( v) = config. worker_threads {
0 commit comments