Skip to content

Commit

Permalink
#119 async once fixtere should raise error
Browse files Browse the repository at this point in the history
  • Loading branch information
la10736 committed Nov 13, 2021
1 parent a126c90 commit d9523f0
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 18 deletions.
11 changes: 11 additions & 0 deletions src/error.rs
Expand Up @@ -25,10 +25,21 @@ pub(crate) fn rstest(test: &ItemFn, info: &RsTestInfo) -> TokenStream {
pub(crate) fn fixture(test: &ItemFn, info: &FixtureInfo) -> TokenStream {
missed_arguments(test, info.data.items.iter())
.chain(duplicate_arguments(info.data.items.iter()))
.chain(async_once(test, &info))
.map(|e| e.to_compile_error())
.collect()
}

fn async_once<'a>(test: &'a ItemFn, info: &FixtureInfo) -> Errors<'a> {
match (test.sig.asyncness, info.attributes.get_once()) {
(Some(_asyncness), Some(once)) => Box::new(std::iter::once(syn::Error::new(
once.span(),
"Cannot apply #[once] to async fixture.",
))),
_ => Box::new(std::iter::empty()),
}
}

#[derive(Debug, Default)]
pub(crate) struct ErrorsVec(Vec<syn::Error>);

Expand Down
34 changes: 21 additions & 13 deletions src/parse/fixture.rs
Expand Up @@ -11,7 +11,12 @@ use super::{
extract_partials_return_type, parse_vector_trailing_till_double_comma, Attributes,
ExtendWithFunctionAttrs, Fixture,
};
use crate::{error::ErrorsVec, parse::extract_once, refident::RefIdent, utils::attr_is};
use crate::{
error::ErrorsVec,
parse::extract_once,
refident::{MaybeIdent, RefIdent},
utils::attr_is,
};
use crate::{parse::Attribute, utils::attr_in};
use proc_macro2::TokenStream;
use quote::{format_ident, ToTokens};
Expand Down Expand Up @@ -54,7 +59,7 @@ impl ExtendWithFunctionAttrs for FixtureInfo {
defaults,
default_return_type,
partials_return_type,
is_once
once
) = merge_errors!(
extract_fixtures(item_fn),
extract_defaults(item_fn),
Expand All @@ -74,9 +79,10 @@ impl ExtendWithFunctionAttrs for FixtureInfo {
for (id, return_type) in partials_return_type {
self.attributes.set_partial_return_type(id, return_type);
}
if is_once {
self.attributes.set_once();
}
match once {
Some(ident) => self.attributes.set_once(ident),
None => {}
};
Ok(())
}
}
Expand Down Expand Up @@ -289,16 +295,18 @@ impl FixtureModifiers {
))
}

pub(crate) fn set_once(&mut self) {
self.inner
.attributes
.push(Attribute::Attr(format_ident!("once")))
pub(crate) fn set_once(&mut self, once: syn::Ident) {
self.inner.attributes.push(Attribute::Attr(once))
}

pub(crate) fn is_once(&self) -> bool {
pub(crate) fn get_once(&self) -> Option<&Ident> {
self.iter()
.find(|&a| a == &Attribute::Attr(format_ident!("once")))
.is_some()
.and_then(|a| a.maybe_ident())
}

pub(crate) fn is_once(&self) -> bool {
self.get_once().is_some()
}

fn extract_type(&self, attr_name: &str) -> Option<syn::ReturnType> {
Expand Down Expand Up @@ -566,7 +574,7 @@ mod extend {

info.extend_with_function_attrs(&mut item_fn).unwrap();

assert!(info.attributes.is_once(),);
assert!(info.attributes.is_once());
}

#[test]
Expand All @@ -580,7 +588,7 @@ mod extend {

info.extend_with_function_attrs(&mut item_fn).unwrap();

assert!(!info.attributes.is_once(),);
assert!(!info.attributes.is_once());
}

mod raise_error {
Expand Down
10 changes: 5 additions & 5 deletions src/parse/mod.rs
Expand Up @@ -224,7 +224,7 @@ pub(crate) fn extract_partials_return_type(
partials_type_extractor.take()
}

pub(crate) fn extract_once(item_fn: &mut ItemFn) -> Result<bool, ErrorsVec> {
pub(crate) fn extract_once(item_fn: &mut ItemFn) -> Result<Option<Ident>, ErrorsVec> {
let mut extractor = IsOnceAttributeFunctionExtractor::default();
extractor.visit_item_fn_mut(item_fn);
extractor.take()
Expand Down Expand Up @@ -362,17 +362,17 @@ impl VisitMut for PartialsTypeFunctionExtractor {

/// Simple struct used to visit function attributes and extract once
/// type
struct IsOnceAttributeFunctionExtractor(Result<bool, ErrorsVec>);
struct IsOnceAttributeFunctionExtractor(Result<Option<Ident>, ErrorsVec>);

impl IsOnceAttributeFunctionExtractor {
fn take(self) -> Result<bool, ErrorsVec> {
fn take(self) -> Result<Option<Ident>, ErrorsVec> {
self.0
}
}

impl Default for IsOnceAttributeFunctionExtractor {
fn default() -> Self {
Self(Ok(false))
Self(Ok(None))
}
}

Expand All @@ -384,7 +384,7 @@ impl VisitMut for IsOnceAttributeFunctionExtractor {

node.attrs = remain;
if onces.len() == 1 {
self.0 = Ok(true);
self.0 = Ok(onces[0].path.get_ident().cloned());
} else if onces.len() > 1 {
self.0 = Err(onces
.into_iter()
Expand Down
9 changes: 9 additions & 0 deletions src/refident.rs
Expand Up @@ -75,3 +75,12 @@ impl MaybeIdent for syn::GenericParam {
}
}
}

impl MaybeIdent for crate::parse::Attribute {
fn maybe_ident(&self) -> Option<&Ident> {
use crate::parse::Attribute::*;
match self {
Attr(ident) | Tagged(ident, _) | Type(ident, _) => Some(ident),
}
}
}
15 changes: 15 additions & 0 deletions tests/fixture/mod.rs
Expand Up @@ -290,5 +290,20 @@ mod should {
)
.unindent()
);

assert_in!(
output.stderr.str(),
format!(
r#"
error: Cannot apply #[once] to async fixture.
--> {}/src/lib.rs:38:3
|
38 | #[once]
| ^^^^
"#,
name
)
.unindent()
);
}
}
5 changes: 5 additions & 0 deletions tests/resources/fixture/errors.rs
Expand Up @@ -33,3 +33,8 @@ fn f(name: &str) -> String {
#[fixture(f("first"), f("second"))]
fn error_inject_a_fixture_more_than_once(f: String) {
}

#[fixture]
#[once]
async fn error_async_once_fixture() {
}

0 comments on commit d9523f0

Please sign in to comment.