globetrotter_model/
diagnostics.rs1use codespan_reporting::diagnostic::{self, Diagnostic, Label, Severity};
2use indexmap::IndexMap;
3
4pub type FileId = usize;
5pub type Span = std::ops::Range<usize>;
6
7pub trait ToDiagnostics {
8 fn to_diagnostics<F: Copy + PartialEq>(&self, file_id: F) -> Vec<Diagnostic<F>>;
9}
10
11pub trait DiagnosticExt {
12 fn is_error(&self) -> bool;
13 fn is_warning(&self) -> bool;
14 fn warning_or_error(strict: bool) -> Self;
15}
16
17impl<F> DiagnosticExt for Diagnostic<F> {
18 fn is_error(&self) -> bool {
19 match self.severity {
20 Severity::Bug | Severity::Error => true,
21 Severity::Warning | Severity::Note | Severity::Help => false,
22 }
23 }
24
25 fn is_warning(&self) -> bool {
26 match self.severity {
27 Severity::Warning => true,
28 Severity::Bug | Severity::Error | Severity::Note | Severity::Help => false,
29 }
30 }
31
32 fn warning_or_error(strict: bool) -> Self {
33 if strict {
34 Self::error()
35 } else {
36 Self::warning()
37 }
38 }
39}
40
41pub struct DisplayRepr<'a, T>(pub &'a T);
42
43impl<T> std::fmt::Debug for DisplayRepr<'_, T>
50where
51 T: std::fmt::Display,
52{
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 std::fmt::Display::fmt(self.0, f)
55 }
56}
57
58impl<T> std::fmt::Display for DisplayRepr<'_, T>
59where
60 T: std::fmt::Display,
61{
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 std::fmt::Display::fmt(self.0, f)
64 }
65}
66
67#[derive(Debug, Clone)]
68pub struct Spanned<T> {
69 pub inner: T,
70 pub span: Span,
71}
72
73impl<T> serde::Serialize for Spanned<T>
74where
75 T: serde::Serialize,
76{
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: serde::Serializer,
80 {
81 self.inner.serialize(serializer)
82 }
83}
84
85impl<T> std::ops::Deref for Spanned<T> {
86 type Target = T;
87 fn deref(&self) -> &Self::Target {
88 &self.inner
89 }
90}
91
92impl<T> AsRef<T> for Spanned<T> {
93 fn as_ref(&self) -> &T {
94 &self.inner
95 }
96}
97
98impl<T> Spanned<T> {
99 pub fn new(span: impl Into<Span>, value: T) -> Self {
100 Self {
101 span: span.into(),
102 inner: value,
103 }
104 }
105
106 pub fn dummy(value: T) -> Self {
107 Self {
108 span: Span::default(),
109 inner: value,
110 }
111 }
112
113 pub fn into_inner(self) -> T {
114 self.inner
115 }
116
117 pub fn display(&self) -> DisplayRepr<'_, Self> {
118 DisplayRepr(self)
119 }
120}
121
122impl<T> std::fmt::Display for Spanned<T>
123where
124 T: std::fmt::Display,
125{
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 std::fmt::Display::fmt(&self.inner, f)
128 }
129}
130
131impl<T> PartialEq for Spanned<T>
132where
133 T: PartialEq,
134{
135 fn eq(&self, other: &Self) -> bool {
136 self.inner == other.inner
137 }
138}
139
140impl<T> PartialEq<T> for Spanned<T>
141where
142 T: PartialEq,
143{
144 fn eq(&self, other: &T) -> bool {
145 (&self.inner as &dyn PartialEq<T>).eq(other)
146 }
147}
148
149impl<T> PartialEq<&T> for Spanned<T>
150where
151 T: PartialEq,
152{
153 fn eq(&self, other: &&T) -> bool {
154 (&self.inner as &dyn PartialEq<T>).eq(*other)
155 }
156}
157
158impl<T> Ord for Spanned<T>
159where
160 T: Ord,
161{
162 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
163 Ord::cmp(&self.inner, &other.inner)
164 }
165}
166
167impl<T> PartialOrd for Spanned<T>
168where
169 T: PartialOrd,
170{
171 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
172 PartialOrd::partial_cmp(&self.inner, &other.inner)
173 }
174}
175
176impl<T> PartialOrd<T> for Spanned<T>
177where
178 T: PartialOrd,
179{
180 fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
181 PartialOrd::partial_cmp(&self.inner, other)
182 }
183}
184
185impl<T> Eq for Spanned<T> where T: Eq {}
186
187impl<T> std::hash::Hash for Spanned<T>
188where
189 T: std::hash::Hash,
190{
191 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
192 self.inner.hash(state);
193 }
194}