Ящик proc-macro2
заменяет proc_macro
за исключением того, что он доступен вне макросов, что делает его тестируемым. Все его типы конвертируются в типы proc_macro
и имеют идентичные методы.
Обычный шаблон для написания нетривиального макроса - использовать proc_macro
только для точки входа и использовать proc-macro2
для вся реальная работа:
extern crate proc_macro;
use proc_macro2::TokenStream;
#[proc_macro]
pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let output = transform_stream(TokenStream::from(input));
proc_macro::TokenStream::from(output)
}
// A testable function!
fn transform_stream(input: TokenStream) -> TokenStream {
// actual work goes here
}
Обычно элементы из proc-macro2
импортируются, чтобы их можно было использовать неквалифицированно, и просто использовали полностью определенные имена для proc_macro
, так как вы будете использовать его только один раз находится в точке входа. Также обычно помещают основные компоненты в отдельный ящик библиотеки, который не зависит от proc_macro
.
В тестах вы можете создать TokenStream
из строки:
use std::str::FromStr;
let ts = TokenStream::from_str("fn foo() {}").unwrap();