pub fn emulate_attribute_expansion_fallible<Arg, Res>(
file: File,
macro_path: &str,
macro_fn: impl Fn(Arg, Arg) -> Res
) -> Result<(), Error>where
Arg: From<TokenStream>,
Res: Into<TokenStream>,
Expand description
Parses the given Rust source file, finding attributes macro expansions using macro_path
.
Each time it finds one, it calls derive_fn
, passing it a syn::DeriveInput
.
Note that this parser only handles Rust’s syntax, so it cannot resolve paths to see if they
are equivalent to the given one. The paths used to reference the macro must be exactly equal
to the one given in order to be expanded by this function. For example, if macro_path
is
"foo"
and the file provided calls the macro using #[bar::foo]
, this function will not know
to expand it, and the macro’s code coverage will be underestimated. Also it is important, that
this function would expand every matching attribute, so it is important to design your macros
in the way, the attribute do not collide with other attributes used in tests - not only
actual macros, but also attributes eaten by other macros/derives.
This function follows the standard syn pattern of implementing most of the logic using the
proc_macro2
types, leaving only those methods that can only exist for proc_macro=true
crates, such as types from proc_macro
or syn::parse_macro_input
in the outer function.
This allows use of the inner function in tests which is needed to expand it here.
Returns
Ok
on success, or an instance of Error
indicating any error that occurred when trying to
read or parse the file.
Example
use quote::quote;
use syn::parse_macro_input;
#[proc_macro_attribute]
fn hello(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
hello_internal(attr.into(), item.into()).into()
}
fn hello_internal(attr: proc_macro2::TokenStream, item: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
quote!(#item)
}
#[test]
fn macro_code_coverage() {
let file = std::fs::File::open("tests/tests.rs");
emulate_attribute_expansion_fallible(file, "hello", hello_internal);
}