solar_interface/diagnostics/
message.rs1use crate::Span;
4use std::{borrow::Cow, ops::Deref};
5
6#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct DiagMsg {
8 inner: Cow<'static, str>,
9}
10
11impl Deref for DiagMsg {
12 type Target = str;
13
14 #[inline]
15 fn deref(&self) -> &Self::Target {
16 &self.inner
17 }
18}
19
20impl From<&'static str> for DiagMsg {
21 fn from(value: &'static str) -> Self {
22 Self { inner: Cow::Borrowed(value) }
23 }
24}
25
26impl From<String> for DiagMsg {
27 fn from(value: String) -> Self {
28 Self { inner: Cow::Owned(value) }
29 }
30}
31
32impl From<Cow<'static, str>> for DiagMsg {
33 fn from(value: Cow<'static, str>) -> Self {
34 Self { inner: value }
35 }
36}
37
38impl DiagMsg {
39 #[inline]
41 pub fn as_str(&self) -> &str {
42 &self.inner
43 }
44}
45
46#[derive(Clone, Debug)]
48pub struct SpanLabel {
49 pub span: Span,
51
52 pub is_primary: bool,
55
56 pub label: Option<DiagMsg>,
58}
59
60#[derive(Clone, Debug, PartialEq, Eq, Hash)]
68pub struct MultiSpan {
69 primary_spans: Vec<Span>,
70 span_labels: Vec<(Span, DiagMsg)>,
71}
72
73impl MultiSpan {
74 #[inline]
75 pub fn new() -> Self {
76 Self { primary_spans: vec![], span_labels: vec![] }
77 }
78
79 pub fn from_span(primary_span: Span) -> Self {
80 Self { primary_spans: vec![primary_span], span_labels: vec![] }
81 }
82
83 pub fn from_spans(mut vec: Vec<Span>) -> Self {
84 vec.sort_unstable();
85 Self { primary_spans: vec, span_labels: vec![] }
86 }
87
88 pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMsg>) {
89 self.span_labels.push((span, label.into()));
90 }
91
92 pub fn primary_span(&self) -> Option<Span> {
94 self.primary_spans.first().copied()
95 }
96
97 pub fn primary_spans(&self) -> &[Span] {
99 &self.primary_spans
100 }
101
102 pub fn has_primary_spans(&self) -> bool {
104 !self.is_dummy()
105 }
106
107 pub fn is_dummy(&self) -> bool {
109 self.primary_spans.iter().all(|sp| sp.is_dummy())
110 }
111
112 pub fn replace(&mut self, before: Span, after: Span) -> bool {
115 let mut replacements_occurred = false;
116 for primary_span in &mut self.primary_spans {
117 if *primary_span == before {
118 *primary_span = after;
119 replacements_occurred = true;
120 }
121 }
122 for span_label in &mut self.span_labels {
123 if span_label.0 == before {
124 span_label.0 = after;
125 replacements_occurred = true;
126 }
127 }
128 replacements_occurred
129 }
130
131 pub fn pop_span_label(&mut self) -> Option<(Span, DiagMsg)> {
132 self.span_labels.pop()
133 }
134
135 pub fn span_labels(&self) -> Vec<SpanLabel> {
141 let is_primary = |span| self.primary_spans.contains(&span);
142
143 let mut span_labels = self
144 .span_labels
145 .iter()
146 .map(|&(span, ref label)| SpanLabel {
147 span,
148 is_primary: is_primary(span),
149 label: Some(label.clone()),
150 })
151 .collect::<Vec<_>>();
152
153 for &span in &self.primary_spans {
154 if !span_labels.iter().any(|sl| sl.span == span) {
155 span_labels.push(SpanLabel { span, is_primary: true, label: None });
156 }
157 }
158
159 span_labels
160 }
161
162 pub fn has_span_labels(&self) -> bool {
164 self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
165 }
166
167 pub fn clone_ignoring_labels(&self) -> Self {
172 Self { primary_spans: self.primary_spans.clone(), ..Self::new() }
173 }
174}
175
176impl Default for MultiSpan {
177 fn default() -> Self {
178 Self::new()
179 }
180}
181
182impl From<Span> for MultiSpan {
183 fn from(span: Span) -> Self {
184 Self::from_span(span)
185 }
186}
187
188impl From<Option<Span>> for MultiSpan {
189 fn from(span: Option<Span>) -> Self {
190 if let Some(span) = span { Self::from_span(span) } else { Self::new() }
191 }
192}
193
194impl From<Vec<Span>> for MultiSpan {
195 fn from(spans: Vec<Span>) -> Self {
196 Self::from_spans(spans)
197 }
198}