Можно ли отладить процедурный макрос как функцию? - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь отладить сложный процедурный макрос в библиотеке, которую использую.

Поскольку я не могу использовать отладчик с макросами, и различные инструменты расширения макросов оказались здесь бесполезными, я ищу альтернатива.

Может ли процедурный макрос выполняться как функция при правильной отладке? Я представляю, как сохранить результат proc_macro::TokenStream в переменной.

1 Ответ

4 голосов
/ 06 августа 2020

Ящик 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();
...