pub fn emulate_functionlike_macro_expansion<'a, F>(
file: File,
macro_paths_and_proc_macro_fns: &[(&'a str, F)]
) -> Result<(), Error>
Expand description
Searches the given Rust source code file for function-like macro calls and calls the functions that define how to expand them.
Each time it finds one, this function calls the corresponding procedural macro function, passing
it the inner TokenStream
just as if the macro were being expanded. The only effect is to
verify that the macro doesn’t panic, as the expansion is not actually applied to the AST or the
source code.
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, this function uses proc_macro2::TokenStream
, not the standard proc_macro::TokenStream
.
The Rust compiler disallows using the proc_macro
API for anything except defining a procedural
macro (i.e. we can’t use it at runtime). You can convert between the two types using their
into
methods, as shown below.
§Returns
Ok
on success, or an instance of Error
indicating any error that occurred when trying to
read or parse the file.
§Example
#[proc_macro]
fn remove(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
// This stub just allows us to use `proc_macro2` instead of `proc_macro`.
remove_internal(ts.into()).into()
}
fn remove_internal(_: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
// This macro just eats its input and replaces it with nothing.
proc_macro2::TokenStream::new()
}
#[test]
fn macro_code_coverage() {
let file = std::fs::File::open("tests/tests.rs").unwrap();
emulate_functionlike_macro_expansion(file, &[("remove", remove_internal)]).unwrap();
}