1 use proc_macro::TokenStream;
2 use proc_macro2::Span;
3 use quote::quote;
4 use syn::Error;
5
6 #[derive(Copy, Clone)]
7 pub enum Kind {
8 Enum,
9 Match,
10 Struct,
11 Let,
12 }
13
emit(err: Error, kind: Kind, original: TokenStream) -> TokenStream14 pub fn emit(err: Error, kind: Kind, original: TokenStream) -> TokenStream {
15 let mut err = err;
16 if !probably_has_spans(kind) {
17 // Otherwise the error is printed without any line number.
18 err = Error::new(Span::call_site(), &err.to_string());
19 }
20
21 let err = err.to_compile_error();
22 let original = proc_macro2::TokenStream::from(original);
23
24 let expanded = match kind {
25 Kind::Enum | Kind::Let | Kind::Struct => quote!(#err #original),
26 Kind::Match => quote!({ #err #original }),
27 };
28
29 TokenStream::from(expanded)
30 }
31
32 // Rustc is so bad at spans.
33 // https://github.com/rust-lang/rust/issues/43081
probably_has_spans(kind: Kind) -> bool34 fn probably_has_spans(kind: Kind) -> bool {
35 match kind {
36 Kind::Enum | Kind::Struct => true,
37 Kind::Match | Kind::Let => false,
38 }
39 }
40