1#![allow(clippy::test_attr_in_doctest)]
2#![allow(unexpected_cfgs)]
3#![cfg_attr(use_proc_macro_diagnostic, feature(proc_macro_diagnostic))]
4extern crate proc_macro;
5
6#[cfg(test)]
8pub(crate) mod test;
9
10#[macro_use]
11mod error;
12mod parse;
13mod refident;
14mod render;
15mod resolver;
16mod utils;
17
18use syn::{parse_macro_input, ItemFn};
19
20use crate::parse::{fixture::FixtureInfo, rstest::RsTestInfo};
21use parse::ExtendWithFunctionAttrs;
22use quote::ToTokens;
23
24#[allow(missing_docs)]
25#[proc_macro_attribute]
26pub fn fixture(
27 args: proc_macro::TokenStream,
28 input: proc_macro::TokenStream,
29) -> proc_macro::TokenStream {
30 let mut info: FixtureInfo = parse_macro_input!(args as FixtureInfo);
31 let mut fixture = parse_macro_input!(input as ItemFn);
32
33 let extend_result = info.extend_with_function_attrs(&mut fixture);
34
35 let mut errors = error::fixture(&fixture, &info);
36
37 if let Err(attrs_errors) = extend_result {
38 attrs_errors.to_tokens(&mut errors);
39 }
40
41 if errors.is_empty() {
42 render::fixture(fixture, info)
43 } else {
44 errors
45 }
46 .into()
47}
48
49#[allow(missing_docs)]
50#[proc_macro_attribute]
51pub fn rstest(
52 args: proc_macro::TokenStream,
53 input: proc_macro::TokenStream,
54) -> proc_macro::TokenStream {
55 let mut test = parse_macro_input!(input as ItemFn);
56 let mut info = parse_macro_input!(args as RsTestInfo);
57
58 let extend_result = info.extend_with_function_attrs(&mut test);
59
60 let mut errors = error::rstest(&test, &info);
61
62 if let Err(attrs_errors) = extend_result {
63 attrs_errors.to_tokens(&mut errors);
64 }
65
66 if errors.is_empty() {
67 if info.data.has_list_values() {
68 render::matrix(test, info)
69 } else if info.data.has_cases() {
70 render::parametrize(test, info)
71 } else {
72 render::single(test, info)
73 }
74 } else {
75 errors
76 }
77 .into()
78}