proc-macro-workshop:sorted-2

审题

// The #[sorted] macro is only defined to work on enum types, so this is a test
// to ensure that when it's attached to a struct (or anything else) it produces
// some reasonable error. Your macro will need to look into the syn::Item that
// it parsed to ensure that it represents an enum, returning an error for any
// other type of Item such as a struct.
//
// This is an exercise in exploring how to return errors from procedural macros.
// The goal is to produce an understandable error message which is tailored to
// this specific macro (saying that #[sorted] cannot be applied to things other
// than enum). For this you'll want to look at the syn::Error type, how to
// construct it, and how to return it.
//
// Notice that the return value of an attribute macro is simply a TokenStream,
// not a Result with an error. The syn::Error type provides a method to render
// your error as a TokenStream containing an invocation of the compile_error
// macro.
//
// A final tweak you may want to make is to have the `sorted` function delegate
// to a private helper function which works with Result, so most of the macro
// can be written with Result-returning functions while the top-level function
// handles the conversion down to TokenStream.
//
//
// Resources
//
//   - The syn::Error type:
//     https://docs.rs/syn/1.0/syn/struct.Error.html

use sorted::sorted;

#[sorted]
pub struct Error {
    kind: ErrorKind,
    message: String,
}

enum ErrorKind {
    Io,
    Syntax,
    Eof,
}

fn main() {}

这道题主要是报错

error: expected enum or match expression
  --> tests/02-not-enum.rs:31:1
   |
31 | #[sorted]
   | ^^^^^^^^^
   |
   = note: this error originates in the attribute macro `sorted` (in Nightly builds, run with -Z macro-backtrace for more info)

标识的是只能够标记在enum上。

题解

pub(crate) fn solution(item: &syn::Item) -> syn::Result<proc_macro2::TokenStream> {
    match item {
        syn::Item::Enum(node) => crate::solution3::solution(node),
        _ => syn::Result::Err(syn::Error::new(
            proc_macro2::Span::call_site(),
            "expected enum or match expression",
        )),
    }
}

模式匹配即可,顺便引出第三个坑。

proc_macro2:: Span::call_site()真香

完整

#[proc_macro_attribute]
pub fn sorted(
    _args: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let item = syn::parse_macro_input!(input as syn::Item);
    match solution1::solution(&item) {
        syn::Result::Ok(stream) => stream,
        syn::Result::Err(e) => {
            let mut res = e.into_compile_error();
            res.extend(crate::common::to_token_stream(item));
            res
        }
    }
    .into()
}

整体结构不变。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!