Как найти правильный тип возвращаемого значения для syn::parse?

У меня есть TokenStream это происходит из определения функции Rust. Я хочу разобрать это с syn::parse (а также .unrwap()). Однако я не знаю, каким должен быть тип возвращаемого значения:

let ast: ??? = syn::parse(token_stream_from_function_definition).unwrap();

Какой тип должен ast быть?

2 ответа

Решение

syn::parse функция пытается разобрать TokenStream во все, что вы ожидаете. Как сказано в документации:

Разобрать токены исходного кода в выбранном узле синтаксического дерева.

Он принимает параметр типа, который вы обычно предоставляете, используя вывод типа. Например, если вы ожидали проанализировать объявление функции:

let fn_decl: syn::FnDecl = syn::parse(token_stream).unwrap();

Это бы запаниковало, если бы он не мог разобрать fn декларация.


Если вы точно не знаете, чего ожидать, вы можете сделать более общий подход, сопоставить набор возможностей и затем проверить, что вы найдете. Для групп синтаксиса предусмотрены некоторые перечисления, которые могут появляться в одних и тех же местах. Например, если вы анализируете код в контексте, где вы ожидаете найти объявление функции или некоторые другие объявления на том же уровне, вам, вероятно, нужно проанализировать Item а затем сопоставьте все возможные типы элементов:

use syn::Item;

let item: Item = syn::parse(token_stream).unwrap();
match item {
    Item::Fn(fn_decl) => {}
    Item::Mod(mod_item) => {}
    Item::Struct(struct_item) => {}
    Item::Enum(enum_item) => {}
    _ => {}
}

Обратите внимание, что syn::Item имеет 18 вариантов для соответствия, и syn::Expr имеет 40! Определенно стоит сузить возможности и выбрать тип для анализа, наиболее подходящий для ваших нужд. Вы могли бы также рассмотреть определение своего собственного типа, представляющего различные синтаксические конструкции, которые вы ожидаете найти, и затем реализацию syn::Parse черта вручную.

Если вы ищетеsynтип, связанный с некоторым типом, который вы анализируете, полезным местом может быть исходный файл элемента .

На широком уровне:

  • для элементов в глобальной области видимости, т. е. fn, один из Item
  • для элементов в структуре impl один из ImplItem
  • для элементов в свойстве один из TraitItem
  • для аргумента функции один из FnArg

и т. д...

т.е. для функции используйтеItemFn:

      let stream = quote!(fn foo(&self)->i32{0});

let a:syn::ItemFn = syn::parse2(stream).unwrap();
Другие вопросы по тегам