1mod miette;
2
3#[cfg(feature = "miette")]
4use ::miette::LabeledSpan;
5use std::cmp;
6use std::fmt::{self, Display, Formatter};
7
8#[cfg(feature = "miette")]
9pub use crate::diagnostics::miette::diagnose;
10
11pub type Span = (usize, usize);
32
33pub trait SpanExt {
34 fn union(&self, other: &Self) -> Self;
35}
36
37impl SpanExt for Span {
38 fn union(&self, other: &Self) -> Self {
39 let start = cmp::min(self.0, other.0);
40 let end = cmp::max(self.0 + self.1, other.0 + other.1);
41 (start, end - start)
42 }
43}
44
45pub trait LocatedError: Display {
56 fn span(&self) -> Span;
58}
59
60#[derive(Clone, Copy, Debug)]
61pub struct CompositeSpan {
62 label: &'static str,
63 kind: CompositeSpanKind,
64}
65
66impl CompositeSpan {
67 pub fn spanned(label: &'static str, span: Span) -> Self {
68 CompositeSpan {
69 label,
70 kind: CompositeSpanKind::Span(span),
71 }
72 }
73
74 pub fn correlated(label: &'static str, span: Span, correlated: CorrelatedSpan) -> Self {
75 CompositeSpan {
76 label,
77 kind: CompositeSpanKind::Correlated { span, correlated },
78 }
79 }
80
81 #[cfg(feature = "miette")]
82 pub fn labels(&self) -> Vec<LabeledSpan> {
83 let label = Some(self.label.to_string());
84 match self.kind {
85 CompositeSpanKind::Span(ref span) => vec![LabeledSpan::new_with_span(label, *span)],
86 CompositeSpanKind::Correlated {
87 ref span,
88 ref correlated,
89 } => Some(LabeledSpan::new_with_span(label, *span))
90 .into_iter()
91 .chain(correlated.labels())
92 .collect(),
93 }
94 }
95}
96
97impl Display for CompositeSpan {
98 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
99 write!(f, "{}", self.label)
100 }
101}
102
103impl LocatedError for CompositeSpan {
104 fn span(&self) -> Span {
105 match self.kind {
106 CompositeSpanKind::Span(ref span) | CompositeSpanKind::Correlated { ref span, .. } => {
107 *span
108 },
109 }
110 }
111}
112
113#[derive(Clone, Copy, Debug)]
114enum CompositeSpanKind {
115 Span(Span),
116 Correlated {
117 span: Span,
118 #[cfg_attr(not(feature = "miette"), allow(dead_code))]
119 correlated: CorrelatedSpan,
120 },
121}
122
123#[derive(Clone, Copy, Debug)]
124pub enum CorrelatedSpan {
125 Contiguous(Span),
126 Split(Span, Span),
127}
128
129impl CorrelatedSpan {
130 pub fn split_some(left: Option<Span>, right: Span) -> Self {
131 if let Some(left) = left {
132 CorrelatedSpan::Split(left, right)
133 }
134 else {
135 CorrelatedSpan::Contiguous(right)
136 }
137 }
138
139 #[cfg(feature = "miette")]
140 pub fn labels(&self) -> Vec<LabeledSpan> {
141 let label = Some("here".to_string());
142 match self {
143 CorrelatedSpan::Contiguous(ref span) => {
144 vec![LabeledSpan::new_with_span(label, *span)]
145 },
146 CorrelatedSpan::Split(ref left, ref right) => vec![
147 LabeledSpan::new_with_span(label.clone(), *left),
148 LabeledSpan::new_with_span(label, *right),
149 ],
150 }
151 }
152}
153
154impl From<Span> for CorrelatedSpan {
155 fn from(span: Span) -> Self {
156 CorrelatedSpan::Contiguous(span)
157 }
158}