reproto_core/
diagnostics.rs

1//! Reporter for spanned diagnostics.
2use flavored::RpName;
3use std::fmt;
4use std::slice;
5use {Source, Span};
6
7#[derive(Debug, Clone, Copy, Serialize)]
8pub enum SymbolKind {
9    #[serde(rename = "type")]
10    Type,
11    #[serde(rename = "interface")]
12    Interface,
13    #[serde(rename = "tuple")]
14    Tuple,
15    #[serde(rename = "enum")]
16    Enum,
17    #[serde(rename = "service")]
18    Service,
19}
20
21/// A single diagnostic emitted by the compiler.
22#[derive(Debug, Clone)]
23pub enum Diagnostic {
24    /// A positional error.
25    Error(Span, String),
26    /// A positional information string.
27    Info(Span, String),
28    /// A symbol that was encountered, and its location.
29    Symbol {
30        kind: SymbolKind,
31        span: Span,
32        name: RpName,
33    },
34}
35
36/// A collection of diagnostics emitted by the compiler.
37#[derive(Debug, Clone)]
38pub struct Diagnostics {
39    pub source: Source,
40    pub items: Vec<Diagnostic>,
41}
42
43impl Diagnostics {
44    /// Create a new diagnostics collection.
45    pub fn new(source: Source) -> Self {
46        Self {
47            source,
48            items: Vec::new(),
49        }
50    }
51
52    /// Check if reporter is empty.
53    pub fn has_errors(&self) -> bool {
54        self.items.iter().any(|item| match *item {
55            Diagnostic::Error(_, _) => true,
56            _ => false,
57        })
58    }
59
60    /// Report an error.
61    pub fn err<S: Into<Span>, E: fmt::Display>(&mut self, span: S, error: E) {
62        self.items
63            .push(Diagnostic::Error(span.into(), error.to_string()));
64    }
65
66    /// Report information.
67    pub fn info<S: Into<Span>, I: fmt::Display>(&mut self, span: S, info: I) {
68        self.items
69            .push(Diagnostic::Info(span.into(), info.to_string()));
70    }
71
72    /// Register a symbol.
73    pub fn symbol<P: Into<Span>>(&mut self, kind: SymbolKind, span: P, name: &RpName) {
74        self.items.push(Diagnostic::Symbol {
75            kind,
76            span: span.into(),
77            name: name.clone(),
78        });
79    }
80
81    /// Iterate over all reporter items.
82    pub fn items(&self) -> Items {
83        Items {
84            iter: self.items.iter(),
85        }
86    }
87
88    /// Clear all existing diagnostics.
89    pub fn clear(&mut self) {
90        self.items.clear();
91    }
92}
93
94/// Iterator over items.
95///
96/// Created using `Diagnostics::items`.
97pub struct Items<'a> {
98    iter: slice::Iter<'a, Diagnostic>,
99}
100
101impl<'a> Iterator for Items<'a> {
102    type Item = <slice::Iter<'a, Diagnostic> as Iterator>::Item;
103
104    fn next(&mut self) -> Option<Self::Item> {
105        self.iter.next()
106    }
107}