1 //! lib-proc-macro diagnostic
3 //! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
4 //! augmented with removing unstable features
8 /// An enum representing a diagnostic level.
9 #[derive(Copy, Clone, Debug)]
22 /// Trait implemented by types that can be converted into a set of `Span`s.
24 /// Converts `self` into a `Vec<Span>`.
25 fn into_spans(self) -> Vec<Span>;
28 impl MultiSpan for Span {
29 fn into_spans(self) -> Vec<Span> {
34 impl MultiSpan for Vec<Span> {
35 fn into_spans(self) -> Vec<Span> {
40 impl<'a> MultiSpan for &'a [Span] {
41 fn into_spans(self) -> Vec<Span> {
46 /// A structure representing a diagnostic message and associated children
48 #[derive(Clone, Debug)]
49 pub struct Diagnostic {
53 children: Vec<Diagnostic>,
56 macro_rules! diagnostic_child_methods {
57 ($spanned:ident, $regular:ident, $level:expr) => {
58 #[doc = concat!("Adds a new child diagnostics message to `self` with the [`",
59 stringify!($level), "`] level, and the given `spans` and `message`.")]
60 pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic
65 self.children.push(Diagnostic::spanned(spans, $level, message));
69 #[doc = concat!("Adds a new child diagnostic message to `self` with the [`",
70 stringify!($level), "`] level, and the given `message`.")]
71 pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
72 self.children.push(Diagnostic::new($level, message));
78 /// Iterator over the children diagnostics of a `Diagnostic`.
79 #[derive(Debug, Clone)]
80 pub struct Children<'a>(std::slice::Iter<'a, Diagnostic>);
82 impl<'a> Iterator for Children<'a> {
83 type Item = &'a Diagnostic;
85 fn next(&mut self) -> Option<Self::Item> {
91 /// Creates a new diagnostic with the given `level` and `message`.
92 pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
93 Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
96 /// Creates a new diagnostic with the given `level` and `message` pointing to
97 /// the given set of `spans`.
98 pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic
103 Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] }
106 diagnostic_child_methods!(span_error, error, Level::Error);
107 diagnostic_child_methods!(span_warning, warning, Level::Warning);
108 diagnostic_child_methods!(span_note, note, Level::Note);
109 diagnostic_child_methods!(span_help, help, Level::Help);
111 /// Returns the diagnostic `level` for `self`.
112 pub fn level(&self) -> Level {
116 /// Sets the level in `self` to `level`.
117 pub fn set_level(&mut self, level: Level) {
121 /// Returns the message in `self`.
122 pub fn message(&self) -> &str {
126 /// Sets the message in `self` to `message`.
127 pub fn set_message<T: Into<String>>(&mut self, message: T) {
128 self.message = message.into();
131 /// Returns the `Span`s in `self`.
132 pub fn spans(&self) -> &[Span] {
136 /// Sets the `Span`s in `self` to `spans`.
137 pub fn set_spans<S: MultiSpan>(&mut self, spans: S) {
138 self.spans = spans.into_spans();
141 /// Returns an iterator over the children diagnostics of `self`.
142 pub fn children(&self) -> Children<'_> {
143 Children(self.children.iter())
146 /// Emit the diagnostic.
148 fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan {
149 let mut multi_span = super::bridge::client::MultiSpan::new();
151 multi_span.push(span.0);
156 let mut diag = super::bridge::client::Diagnostic::new(
159 to_internal(self.spans),
161 for c in self.children {
162 diag.sub(c.level, &c.message[..], to_internal(c.spans));