mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-27 19:12:56 +01:00
make runtime macros more IDE friendly (#391)
This commit is contained in:
parent
5c555a9408
commit
4ff8a2cf68
@ -1,6 +1,10 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
* Improve error recovery potential when macro input is invalid. [#391]
|
||||||
|
* Allow custom `System`s on test macro. [#391]
|
||||||
|
|
||||||
|
[#391]: https://github.com/actix/actix-net/pull/391
|
||||||
|
|
||||||
|
|
||||||
## 0.2.1 - 2021-02-02
|
## 0.2.1 - 2021-02-02
|
||||||
|
@ -28,7 +28,12 @@ use quote::quote;
|
|||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||||
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let mut input = syn::parse_macro_input!(item as syn::ItemFn);
|
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
|
||||||
|
Ok(input) => input,
|
||||||
|
// on parse err, make IDEs happy; see fn docs
|
||||||
|
Err(err) => return input_and_compile_error(item, err),
|
||||||
|
};
|
||||||
|
|
||||||
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
|
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
|
||||||
|
|
||||||
let attrs = &input.attrs;
|
let attrs = &input.attrs;
|
||||||
@ -101,8 +106,15 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let mut input = syn::parse_macro_input!(item as syn::ItemFn);
|
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
|
||||||
|
Ok(input) => input,
|
||||||
|
// on parse err, make IDEs happy; see fn docs
|
||||||
|
Err(err) => return input_and_compile_error(item, err),
|
||||||
|
};
|
||||||
|
|
||||||
|
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
|
||||||
|
|
||||||
let attrs = &input.attrs;
|
let attrs = &input.attrs;
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
let sig = &mut input.sig;
|
let sig = &mut input.sig;
|
||||||
@ -132,13 +144,59 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
quote!(#[test])
|
quote!(#[test])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut system = syn::parse_str::<syn::Path>("::actix_rt::System").unwrap();
|
||||||
|
|
||||||
|
for arg in &args {
|
||||||
|
match arg {
|
||||||
|
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
||||||
|
lit: syn::Lit::Str(lit),
|
||||||
|
path,
|
||||||
|
..
|
||||||
|
})) => match path
|
||||||
|
.get_ident()
|
||||||
|
.map(|i| i.to_string().to_lowercase())
|
||||||
|
.as_deref()
|
||||||
|
{
|
||||||
|
Some("system") => match lit.parse() {
|
||||||
|
Ok(path) => system = path,
|
||||||
|
Err(_) => {
|
||||||
|
return syn::Error::new_spanned(lit, "Expected path")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return syn::Error::new_spanned(arg, "Unknown attribute specified")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return syn::Error::new_spanned(arg, "Unknown attribute specified")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(quote! {
|
(quote! {
|
||||||
#missing_test_attr
|
#missing_test_attr
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#vis #sig {
|
#vis #sig {
|
||||||
actix_rt::System::new()
|
<#system>::new().block_on(async { #body })
|
||||||
.block_on(async { #body })
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the error to a token stream and appends it to the original input.
|
||||||
|
///
|
||||||
|
/// Returning the original input in addition to the error is good for IDEs which can gracefully
|
||||||
|
/// recover and show more precise errors within the macro body.
|
||||||
|
///
|
||||||
|
/// See <https://github.com/rust-analyzer/rust-analyzer/issues/10468> for more info.
|
||||||
|
fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream {
|
||||||
|
let compile_err = TokenStream::from(err.to_compile_error());
|
||||||
|
item.extend(compile_err);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
@ -11,4 +11,7 @@ fn compile_macros() {
|
|||||||
t.pass("tests/trybuild/test-01-basic.rs");
|
t.pass("tests/trybuild/test-01-basic.rs");
|
||||||
t.pass("tests/trybuild/test-02-keep-attrs.rs");
|
t.pass("tests/trybuild/test-02-keep-attrs.rs");
|
||||||
t.compile_fail("tests/trybuild/test-03-only-async.rs");
|
t.compile_fail("tests/trybuild/test-03-only-async.rs");
|
||||||
|
t.pass("tests/trybuild/test-04-system-path.rs");
|
||||||
|
t.compile_fail("tests/trybuild/test-05-system-expect-path.rs");
|
||||||
|
t.compile_fail("tests/trybuild/test-06-unknown-attr.rs");
|
||||||
}
|
}
|
||||||
|
10
actix-macros/tests/trybuild/test-04-system-path.rs
Normal file
10
actix-macros/tests/trybuild/test-04-system-path.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
mod system {
|
||||||
|
pub use actix_rt::System as MySystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test(system = "system::MySystem")]
|
||||||
|
async fn my_test() {
|
||||||
|
futures_util::future::ready(()).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,4 @@
|
|||||||
|
#[actix_rt::test(system = "!@#*&")]
|
||||||
|
async fn my_test() {}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,5 @@
|
|||||||
|
error: Expected path
|
||||||
|
--> $DIR/test-05-system-expect-path.rs:1:27
|
||||||
|
|
|
||||||
|
1 | #[actix_rt::test(system = "!@#*&")]
|
||||||
|
| ^^^^^^^
|
7
actix-macros/tests/trybuild/test-06-unknown-attr.rs
Normal file
7
actix-macros/tests/trybuild/test-06-unknown-attr.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#[actix_rt::test(foo = "bar")]
|
||||||
|
async fn my_test_1() {}
|
||||||
|
|
||||||
|
#[actix_rt::test(bar::baz)]
|
||||||
|
async fn my_test_2() {}
|
||||||
|
|
||||||
|
fn main() {}
|
11
actix-macros/tests/trybuild/test-06-unknown-attr.stderr
Normal file
11
actix-macros/tests/trybuild/test-06-unknown-attr.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error: Unknown attribute specified
|
||||||
|
--> $DIR/test-06-unknown-attr.rs:1:18
|
||||||
|
|
|
||||||
|
1 | #[actix_rt::test(foo = "bar")]
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: Unknown attribute specified
|
||||||
|
--> $DIR/test-06-unknown-attr.rs:4:18
|
||||||
|
|
|
||||||
|
4 | #[actix_rt::test(bar::baz)]
|
||||||
|
| ^^^^^^^^
|
@ -24,4 +24,5 @@ serde = { version = "1.0", optional = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
ahash = { version = "0.7", default-features = false }
|
# TODO: remove when ahash MSRV is restored
|
||||||
|
ahash = { version = "=0.7.4", default-features = false }
|
||||||
|
Loading…
Reference in New Issue
Block a user