#
proc_macro/
diagnostic.rs

    1use crate::Span;
    2
    3/// An enum representing a diagnostic level.
    4#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    5#[derive(Copy, Clone, Debug)]
    6#[non_exhaustive]
    7pub enum Level {
    8    /// An error.
    9    Error,
    10    /// A warning.
    11    Warning,
    12    /// A note.
    13    Note,
    14    /// A help message.
    15    Help,
    16}
    17
    18/// Trait implemented by types that can be converted into a set of `Span`s.
    19#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    20pub trait MultiSpan {
    21    /// Converts `self` into a `Vec<Span>`.
    22    fn into_spans(self) -> Vec<Span>;
    23}
    24
    25#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    26impl MultiSpan for Span {
    27    fn into_spans(self) -> Vec<Span> {
    28        vec![self]
    29    }
    30}
    31
    32#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    33impl MultiSpan for Vec<Span> {
    34    fn into_spans(self) -> Vec<Span> {
    35        self
    36    }
    37}
    38
    39#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    40impl<'a> MultiSpan for &'a [Span] {
    41    fn into_spans(self) -> Vec<Span> {
    42        self.to_vec()
    43    }
    44}
    45
    46/// A structure representing a diagnostic message and associated children
    47/// messages.
    48#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    49#[derive(Clone, Debug)]
    50pub struct Diagnostic {
    51    level: Level,
    52    message: String,
    53    spans: Vec<Span>,
    54    children: Vec<Diagnostic>,
    55}
    56
    57macro_rules! diagnostic_child_methods {
    58    ($spanned:ident, $regular:ident, $level:expr) => {
    59        #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    60        #[doc = concat!("Adds a new child diagnostics message to `self` with the [`",
    61                        stringify!($level), "`] level, and the given `spans` and `message`.")]
    62        pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic
    63        where
    64            S: MultiSpan,
    65            T: Into<String>,
    66        {
    67            self.children.push(Diagnostic::spanned(spans, $level, message));
    68            self
    69        }
    70
    71        #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    72        #[doc = concat!("Adds a new child diagnostic message to `self` with the [`",
    73                        stringify!($level), "`] level, and the given `message`.")]
    74        pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
    75            self.children.push(Diagnostic::new($level, message));
    76            self
    77        }
    78    };
    79}
    80
    81/// Iterator over the children diagnostics of a `Diagnostic`.
    82#[derive(Debug, Clone)]
    83#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    84pub struct Children<'a>(std::slice::Iter<'a, Diagnostic>);
    85
    86#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    87impl<'a> Iterator for Children<'a> {
    88    type Item = &'a Diagnostic;
    89
    90    fn next(&mut self) -> Option<Self::Item> {
    91        self.0.next()
    92    }
    93}
    94
    95#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    96impl Diagnostic {
    97    /// Creates a new diagnostic with the given `level` and `message`.
    98    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    99    pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
    100        Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
    101    }
    102
    103    /// Creates a new diagnostic with the given `level` and `message` pointing to
    104    /// the given set of `spans`.
    105    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    106    pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic
    107    where
    108        S: MultiSpan,
    109        T: Into<String>,
    110    {
    111        Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] }
    112    }
    113
    114    diagnostic_child_methods!(span_error, error, Level::Error);
    115    diagnostic_child_methods!(span_warning, warning, Level::Warning);
    116    diagnostic_child_methods!(span_note, note, Level::Note);
    117    diagnostic_child_methods!(span_help, help, Level::Help);
    118
    119    /// Returns the diagnostic `level` for `self`.
    120    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    121    pub fn level(&self) -> Level {
    122        self.level
    123    }
    124
    125    /// Sets the level in `self` to `level`.
    126    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    127    pub fn set_level(&mut self, level: Level) {
    128        self.level = level;
    129    }
    130
    131    /// Returns the message in `self`.
    132    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    133    pub fn message(&self) -> &str {
    134        &self.message
    135    }
    136
    137    /// Sets the message in `self` to `message`.
    138    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    139    pub fn set_message<T: Into<String>>(&mut self, message: T) {
    140        self.message = message.into();
    141    }
    142
    143    /// Returns the `Span`s in `self`.
    144    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    145    pub fn spans(&self) -> &[Span] {
    146        &self.spans
    147    }
    148
    149    /// Sets the `Span`s in `self` to `spans`.
    150    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    151    pub fn set_spans<S: MultiSpan>(&mut self, spans: S) {
    152        self.spans = spans.into_spans();
    153    }
    154
    155    /// Returns an iterator over the children diagnostics of `self`.
    156    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    157    pub fn children(&self) -> Children<'_> {
    158        Children(self.children.iter())
    159    }
    160
    161    /// Emit the diagnostic.
    162    #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
    163    pub fn emit(self) {
    164        fn to_internal(diag: Diagnostic) -> crate::bridge::Diagnostic<crate::bridge::client::Span> {
    165            crate::bridge::Diagnostic {
    166                level: diag.level,
    167                message: diag.message,
    168                spans: diag.spans.into_iter().map(|s| s.0).collect(),
    169                children: diag.children.into_iter().map(to_internal).collect(),
    170            }
    171        }
    172
    173        crate::bridge::client::FreeFunctions::emit_diagnostic(to_internal(self));
    174    }
    175}