1 use proc_macro
::{Diagnostic, Level, MultiSpan}
;
2 use proc_macro2
::TokenStream
;
4 use syn
::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta}
;
7 pub(crate) enum SessionDiagnosticDeriveError
{
12 impl SessionDiagnosticDeriveError
{
13 pub(crate) fn to_compile_error(self) -> TokenStream
{
15 SessionDiagnosticDeriveError
::SynError(e
) => e
.to_compile_error(),
16 SessionDiagnosticDeriveError
::ErrorHandled
=> {
17 // Return ! to avoid having to create a blank DiagnosticBuilder to return when an
18 // error has already been emitted to the compiler.
27 impl From
<SynError
> for SessionDiagnosticDeriveError
{
28 fn from(e
: SynError
) -> Self {
29 SessionDiagnosticDeriveError
::SynError(e
)
33 /// Helper function for use with `throw_*` macros - constraints `$f` to an `impl FnOnce`.
34 pub(crate) fn _throw_err(
36 f
: impl FnOnce(Diagnostic
) -> Diagnostic
,
37 ) -> SessionDiagnosticDeriveError
{
39 SessionDiagnosticDeriveError
::ErrorHandled
42 /// Returns an error diagnostic on span `span` with msg `msg`.
43 pub(crate) fn span_err(span
: impl MultiSpan
, msg
: &str) -> Diagnostic
{
44 Diagnostic
::spanned(span
, Level
::Error
, msg
)
47 /// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration
48 /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
50 /// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
51 macro_rules
! throw_span_err
{
52 ($span
:expr
, $msg
:expr
) => {{ throw_span_err!($span, $msg, |diag| diag) }
};
53 ($span
:expr
, $msg
:expr
, $f
:expr
) => {{
54 let diag
= span_err($span
, $msg
);
55 return Err(crate::diagnostics
::error
::_throw_err(diag
, $f
));
59 pub(crate) use throw_span_err
;
61 /// Returns an error diagnostic for an invalid attribute.
62 pub(crate) fn invalid_attr(attr
: &Attribute
, meta
: &Meta
) -> Diagnostic
{
63 let span
= attr
.span().unwrap();
64 let name
= attr
.path
.segments
.last().unwrap().ident
.to_string();
65 let name
= name
.as_str();
68 Meta
::Path(_
) => span_err(span
, &format
!("`#[{}]` is not a valid attribute", name
)),
69 Meta
::NameValue(_
) => {
70 span_err(span
, &format
!("`#[{} = ...]` is not a valid attribute", name
))
72 Meta
::List(_
) => span_err(span
, &format
!("`#[{}(...)]` is not a valid attribute", name
)),
76 /// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration
77 /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
79 /// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
80 macro_rules
! throw_invalid_attr
{
81 ($attr
:expr
, $meta
:expr
) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }
};
82 ($attr
:expr
, $meta
:expr
, $f
:expr
) => {{
83 let diag
= crate::diagnostics
::error
::invalid_attr($attr
, $meta
);
84 return Err(crate::diagnostics
::error
::_throw_err(diag
, $f
));
88 pub(crate) use throw_invalid_attr
;
90 /// Returns an error diagnostic for an invalid nested attribute.
91 pub(crate) fn invalid_nested_attr(attr
: &Attribute
, nested
: &NestedMeta
) -> Diagnostic
{
92 let name
= attr
.path
.segments
.last().unwrap().ident
.to_string();
93 let name
= name
.as_str();
95 let span
= nested
.span().unwrap();
96 let meta
= match nested
{
97 syn
::NestedMeta
::Meta(meta
) => meta
,
98 syn
::NestedMeta
::Lit(_
) => {
99 return span_err(span
, &format
!("`#[{}(\"...\")]` is not a valid attribute", name
));
103 let span
= meta
.span().unwrap();
104 let nested_name
= meta
.path().segments
.last().unwrap().ident
.to_string();
105 let nested_name
= nested_name
.as_str();
107 Meta
::NameValue(..) => span_err(
109 &format
!("`#[{}({} = ...)]` is not a valid attribute", name
, nested_name
),
112 span_err(span
, &format
!("`#[{}({})]` is not a valid attribute", name
, nested_name
))
115 span_err(span
, &format
!("`#[{}({}(...))]` is not a valid attribute", name
, nested_name
))
120 /// Emit a error diagnostic for an invalid nested attribute (optionally performing additional
121 /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
123 /// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
124 macro_rules
! throw_invalid_nested_attr
{
125 ($attr
:expr
, $nested_attr
:expr
) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }
};
126 ($attr
:expr
, $nested_attr
:expr
, $f
:expr
) => {{
127 let diag
= crate::diagnostics
::error
::invalid_nested_attr($attr
, $nested_attr
);
128 return Err(crate::diagnostics
::error
::_throw_err(diag
, $f
));
132 pub(crate) use throw_invalid_nested_attr
;