From a960a567c6b0c501940d23978157d1c3a28f9082 Mon Sep 17 00:00:00 2001 From: michele Date: Sat, 1 May 2021 15:23:10 +0200 Subject: [PATCH] #98 Base impl --- src/lib.rs | 9 +++++++-- src/parse/fixture.rs | 25 ++++++++++++++++++++++++ tests/resources/fixture/async_fixture.rs | 23 +++++++++++----------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dc5d07a..36367e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,9 +244,12 @@ mod render; mod resolver; mod utils; -use syn::{parse_macro_input, ItemFn}; +use syn::{parse_macro_input, visit_mut::VisitMut, ItemFn}; -use crate::parse::{fixture::FixtureInfo, rstest::RsTestInfo}; +use crate::parse::{ + fixture::{FixtureInfo, ReplacerFutureAttribute}, + rstest::RsTestInfo, +}; use parse::ExtendWithFunctionAttrs; use quote::ToTokens; @@ -459,6 +462,7 @@ pub fn fixture( let mut info: FixtureInfo = parse_macro_input!(args as FixtureInfo); let mut fixture = parse_macro_input!(input as ItemFn); + ReplacerFutureAttribute::default().visit_item_fn_mut(&mut fixture); let extend_result = info.extend_with_function_attrs(&mut fixture); let mut errors = error::fixture(&fixture, &info); @@ -1071,6 +1075,7 @@ pub fn rstest( let mut test = parse_macro_input!(input as ItemFn); let mut info = parse_macro_input!(args as RsTestInfo); + ReplacerFutureAttribute::default().visit_item_fn_mut(&mut test); let extend_result = info.extend_with_function_attrs(&mut test); let mut errors = error::rstest(&test, &info); diff --git a/src/parse/fixture.rs b/src/parse/fixture.rs index e76fd53..2300d55 100644 --- a/src/parse/fixture.rs +++ b/src/parse/fixture.rs @@ -1,3 +1,5 @@ +use std::mem; + /// `fixture`'s related data and parsing use syn::{ parse::{Parse, ParseStream}, @@ -99,6 +101,29 @@ impl VisitMut for FixturesFunctionExtractor { } } +#[derive(Default)] +pub(crate) struct ReplacerFutureAttribute(pub(crate) Vec); + +impl VisitMut for ReplacerFutureAttribute { + fn visit_fn_arg_mut(&mut self, node: &mut FnArg) { + match node { + FnArg::Typed(t) => { + let attrs = mem::take(&mut t.attrs); + let (futures, attrs): (Vec<_>, Vec<_>) = + attrs.into_iter().partition(|a| attr_is(a, "future")); + if futures.len() > 0 { + let ty = &t.ty; + t.ty = parse_quote! { + impl std::future::Future + } + } + t.attrs = attrs; + } + FnArg::Receiver(_) => {} + } + } +} + /// Simple struct used to visit function attributes and extract fixture default values info and /// eventualy parsing errors #[derive(Default)] diff --git a/tests/resources/fixture/async_fixture.rs b/tests/resources/fixture/async_fixture.rs index ab5fb4a..f9fc96c 100644 --- a/tests/resources/fixture/async_fixture.rs +++ b/tests/resources/fixture/async_fixture.rs @@ -1,4 +1,3 @@ -use std::future::Future; use std::io::prelude::*; use rstest::*; @@ -9,12 +8,12 @@ async fn async_u32() -> u32 { } #[fixture] -async fn nest_fixture(async_u32: impl Future) -> u32 { +async fn nest_fixture(#[future] async_u32: u32) -> u32 { async_u32.await } #[fixture(fortytwo = async { 42 })] -async fn nest_fixture_with_default(fortytwo: impl Future) -> u32 { +async fn nest_fixture_with_default(#[future] fortytwo: u32) -> u32 { fortytwo.await } @@ -24,22 +23,22 @@ async fn default_is_async() { } #[rstest] -async fn use_async_nest_fixture_default(nest_fixture: impl Future) { +async fn use_async_nest_fixture_default(#[future] nest_fixture: u32) { assert_eq!(42, nest_fixture.await); } #[rstest(nest_fixture(async { 24 }))] -async fn use_async_nest_fixture_injected(nest_fixture: impl Future) { +async fn use_async_nest_fixture_injected(#[future] nest_fixture: u32) { assert_eq!(24, nest_fixture.await); } #[rstest] -async fn use_async_nest_fixture_with_default(nest_fixture_with_default: impl Future) { +async fn use_async_nest_fixture_with_default(#[future] nest_fixture_with_default: u32) { assert_eq!(42, nest_fixture_with_default.await); } #[rstest] -async fn use_async_fixture(async_u32: impl Future) { +async fn use_async_fixture(#[future] async_u32: u32) { assert_eq!(42, async_u32.await); } @@ -49,26 +48,26 @@ async fn async_impl_output() -> impl Read { } #[rstest] -async fn use_async_impl_output(async_impl_output: impl Future) { +async fn use_async_impl_output(#[future] async_impl_output: T) { let reader = async_impl_output.await; } #[fixture(four = async { 4 }, two = 2)] -async fn two_args_mix_fixture(four: impl Future, two: u32) -> u32 { +async fn two_args_mix_fixture(#[future] four: u32, two: u32) -> u32 { four.await * 10 + two } #[rstest] -async fn use_two_args_mix_fixture(two_args_mix_fixture: impl Future) { +async fn use_two_args_mix_fixture(#[future] two_args_mix_fixture: u32) { assert_eq!(42, two_args_mix_fixture.await); } #[rstest(two_args_mix_fixture(async { 5 }))] -async fn use_two_args_mix_fixture_inject_first(two_args_mix_fixture: impl Future) { +async fn use_two_args_mix_fixture_inject_first(#[future] two_args_mix_fixture: u32) { assert_eq!(52, two_args_mix_fixture.await); } #[rstest(two_args_mix_fixture(async { 3 }, 1))] -async fn use_two_args_mix_fixture_inject_both(two_args_mix_fixture: impl Future) { +async fn use_two_args_mix_fixture_inject_both(#[future] two_args_mix_fixture: u32) { assert_eq!(31, two_args_mix_fixture.await); } \ No newline at end of file