solar_interface/diagnostics/
message.rs1use crate::Span;
4use std::borrow::Cow;
5
6#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct DiagnosticMessage {
8 inner: Cow<'static, str>,
9}
10
11impl From<&'static str> for DiagnosticMessage {
12 fn from(value: &'static str) -> Self {
13 Self { inner: Cow::Borrowed(value) }
14 }
15}
16
17impl From<String> for DiagnosticMessage {
18 fn from(value: String) -> Self {
19 Self { inner: Cow::Owned(value) }
20 }
21}
22
23impl From<Cow<'static, str>> for DiagnosticMessage {
24 fn from(value: Cow<'static, str>) -> Self {
25 Self { inner: value }
26 }
27}
28
29impl DiagnosticMessage {
30 #[inline]
32 pub fn as_str(&self) -> &str {
33 &self.inner
34 }
35}
36
37#[derive(Clone, Debug)]
39pub struct SpanLabel {
40 pub span: Span,
42
43 pub is_primary: bool,
46
47 pub label: Option<DiagnosticMessage>,
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Hash)]
59pub struct MultiSpan {
60 primary_spans: Vec<Span>,
61 span_labels: Vec<(Span, DiagnosticMessage)>,
62}
63
64impl MultiSpan {
65 #[inline]
66 pub fn new() -> Self {
67 Self { primary_spans: vec![], span_labels: vec![] }
68 }
69
70 pub fn from_span(primary_span: Span) -> Self {
71 Self { primary_spans: vec![primary_span], span_labels: vec![] }
72 }
73
74 pub fn from_spans(mut vec: Vec<Span>) -> Self {
75 vec.sort();
76 Self { primary_spans: vec, span_labels: vec![] }
77 }
78
79 pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) {
80 self.span_labels.push((span, label.into()));
81 }
82
83 pub fn primary_span(&self) -> Option<Span> {
85 self.primary_spans.first().copied()
86 }
87
88 pub fn primary_spans(&self) -> &[Span] {
90 &self.primary_spans
91 }
92
93 pub fn has_primary_spans(&self) -> bool {
95 !self.is_dummy()
96 }
97
98 pub fn is_dummy(&self) -> bool {
100 self.primary_spans.iter().all(|sp| sp.is_dummy())
101 }
102
103 pub fn replace(&mut self, before: Span, after: Span) -> bool {
106 let mut replacements_occurred = false;
107 for primary_span in &mut self.primary_spans {
108 if *primary_span == before {
109 *primary_span = after;
110 replacements_occurred = true;
111 }
112 }
113 for span_label in &mut self.span_labels {
114 if span_label.0 == before {
115 span_label.0 = after;
116 replacements_occurred = true;
117 }
118 }
119 replacements_occurred
120 }
121
122 pub fn pop_span_label(&mut self) -> Option<(Span, DiagnosticMessage)> {
123 self.span_labels.pop()
124 }
125
126 pub fn span_labels(&self) -> Vec<SpanLabel> {
132 let is_primary = |span| self.primary_spans.contains(&span);
133
134 let mut span_labels = self
135 .span_labels
136 .iter()
137 .map(|&(span, ref label)| SpanLabel {
138 span,
139 is_primary: is_primary(span),
140 label: Some(label.clone()),
141 })
142 .collect::<Vec<_>>();
143
144 for &span in &self.primary_spans {
145 if !span_labels.iter().any(|sl| sl.span == span) {
146 span_labels.push(SpanLabel { span, is_primary: true, label: None });
147 }
148 }
149
150 span_labels
151 }
152
153 pub fn has_span_labels(&self) -> bool {
155 self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
156 }
157
158 pub fn clone_ignoring_labels(&self) -> Self {
163 Self { primary_spans: self.primary_spans.clone(), ..Self::new() }
164 }
165}
166
167impl Default for MultiSpan {
168 fn default() -> Self {
169 Self::new()
170 }
171}
172
173impl From<Span> for MultiSpan {
174 fn from(span: Span) -> Self {
175 Self::from_span(span)
176 }
177}
178
179impl From<Vec<Span>> for MultiSpan {
180 fn from(spans: Vec<Span>) -> Self {
181 Self::from_spans(spans)
182 }
183}