1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
use proc_macro2::Span;
use proc_macro_error::Diagnostic;
/// Used to create a error enum that converts into a [`Diagnostic`].
///
/// [`Diagnostic`]: proc_macro_error::Diagnostic
macro_rules! diagnostic_error_enum {
($(#[$meta: meta])* $visibility: vis enum $name: ident {
$(
#[error($($error: tt)*), span = $error_span: expr]
$(#[note($($note: tt)*)$(, span = $note_span: expr)?])*
$(#[help($($help: tt)*)$(, span = $help_span: expr)?])*
$(#[err($($err: tt)*)$(, span = $err_span: expr)?])*
$(#[source($source: ident)])?
$variant: ident {
$($variant_field: ident: $variant_field_type: ty),*
},
)*
}) => {
$(#[$meta])*
#[derive(Debug, Clone)]
$visibility enum $name
{
$(
$variant {
$($variant_field: $variant_field_type),*
},
)*
}
impl From<$name> for ::proc_macro_error::Diagnostic
{
#[must_use]
fn from(err: $name) -> Self
{
use $crate::util::error::DiagnosticErrorVariantInfo;
let DiagnosticErrorVariantInfo {
error, span, notes, helps, errs, source
} = match err {
$(
$name::$variant { $($variant_field),* } => {
DiagnosticErrorVariantInfo {
error: format!($($error)*),
span: $error_span,
notes: vec![$(
(
format!($($note)*),
$crate::util::or!(
($($note_span)?)
else (::proc_macro2::Span::call_site())
)
)
),*],
helps: vec![$(
(
format!($($help)*),
$crate::util::or!(
($($help_span)?)
else (::proc_macro2::Span::call_site())
)
)
),*],
errs: vec![$(
(
format!($($err)*),
$crate::util::or!(
($($err_span)?)
else (::proc_macro2::Span::call_site())
)
)
),*],
source: $crate::util::to_option!($($source.into())?)
}
}
),*
};
if let Some(source_diagnostic) = source {
source_diagnostic.emit();
}
let mut diagnostic = ::proc_macro_error::Diagnostic::spanned(
span,
::proc_macro_error::Level::Error,
error
);
if !notes.is_empty() {
for (note, note_span) in notes {
diagnostic = diagnostic.span_note(note_span, note);
}
}
if !helps.is_empty() {
for (help, help_span) in helps {
diagnostic = diagnostic.span_help(help_span, help);
}
}
if !errs.is_empty() {
for (err, err_span) in errs {
diagnostic = diagnostic.span_error(err_span, err);
}
}
diagnostic
}
}
};
}
/// Used by [`diagnostic_error_enum`].
pub struct DiagnosticErrorVariantInfo
{
pub error: String,
pub span: Span,
pub notes: Vec<(String, Span)>,
pub helps: Vec<(String, Span)>,
pub errs: Vec<(String, Span)>,
pub source: Option<Diagnostic>,
}
pub(crate) use diagnostic_error_enum;
|