1use super::functions::*;
6use crate::tokens::Span;
7
8#[allow(dead_code)]
10#[allow(missing_docs)]
11#[derive(Clone, Debug, Default)]
12pub struct FileRegistry {
13 entries: Vec<(FileId, String, String)>,
14 next_id: u32,
15}
16impl FileRegistry {
17 #[allow(dead_code)]
19 #[allow(missing_docs)]
20 pub fn new() -> Self {
21 Self {
22 entries: Vec::new(),
23 next_id: 1,
24 }
25 }
26 #[allow(dead_code)]
28 #[allow(missing_docs)]
29 pub fn register(&mut self, path: impl Into<String>, source: impl Into<String>) -> FileId {
30 let id = FileId(self.next_id);
31 self.next_id += 1;
32 self.entries.push((id, path.into(), source.into()));
33 id
34 }
35 #[allow(dead_code)]
37 #[allow(missing_docs)]
38 pub fn source(&self, id: FileId) -> Option<&str> {
39 self.entries
40 .iter()
41 .find(|(fid, _, _)| *fid == id)
42 .map(|(_, _, src)| src.as_str())
43 }
44 #[allow(dead_code)]
46 #[allow(missing_docs)]
47 pub fn path(&self, id: FileId) -> Option<&str> {
48 self.entries
49 .iter()
50 .find(|(fid, _, _)| *fid == id)
51 .map(|(_, p, _)| p.as_str())
52 }
53 #[allow(dead_code)]
55 #[allow(missing_docs)]
56 pub fn len(&self) -> usize {
57 self.entries.len()
58 }
59 #[allow(dead_code)]
61 #[allow(missing_docs)]
62 pub fn is_empty(&self) -> bool {
63 self.entries.is_empty()
64 }
65 #[allow(dead_code)]
67 #[allow(missing_docs)]
68 pub fn extract(&self, fspan: &FileSpan) -> &str {
69 self.source(fspan.file)
70 .and_then(|src| src.get(fspan.span.start..fspan.span.end))
71 .unwrap_or("")
72 }
73}
74#[allow(dead_code)]
76#[allow(missing_docs)]
77#[derive(Clone, Debug)]
78pub struct DiagnosticSpan {
79 pub span: Span,
81 pub severity: SpanSeverity,
83 #[allow(missing_docs)]
85 pub message: String,
86}
87impl DiagnosticSpan {
88 #[allow(dead_code)]
90 #[allow(missing_docs)]
91 pub fn new(span: Span, severity: SpanSeverity, message: impl Into<String>) -> Self {
92 Self {
93 span,
94 severity,
95 message: message.into(),
96 }
97 }
98 #[allow(dead_code)]
100 #[allow(missing_docs)]
101 pub fn error(span: Span, message: impl Into<String>) -> Self {
102 Self::new(span, SpanSeverity::Error, message)
103 }
104 #[allow(dead_code)]
106 #[allow(missing_docs)]
107 pub fn warning(span: Span, message: impl Into<String>) -> Self {
108 Self::new(span, SpanSeverity::Warning, message)
109 }
110 #[allow(dead_code)]
112 #[allow(missing_docs)]
113 pub fn info(span: Span, message: impl Into<String>) -> Self {
114 Self::new(span, SpanSeverity::Info, message)
115 }
116 #[allow(dead_code)]
118 #[allow(missing_docs)]
119 pub fn format_short(&self) -> String {
120 format!(
121 "[{}] {}: {}",
122 self.severity.label(),
123 span_short(&self.span),
124 self.message
125 )
126 }
127}
128#[allow(dead_code)]
130#[allow(missing_docs)]
131#[derive(Clone, Debug)]
132pub struct ProvenanceSpan {
133 pub span: Span,
134 pub origin: SpanOrigin,
135}
136impl ProvenanceSpan {
137 #[allow(dead_code)]
138 #[allow(missing_docs)]
139 pub fn new(span: Span, origin: SpanOrigin) -> Self {
140 Self { span, origin }
141 }
142 #[allow(dead_code)]
143 #[allow(missing_docs)]
144 pub fn user(span: Span) -> Self {
145 Self::new(span, SpanOrigin::UserSource)
146 }
147 #[allow(dead_code)]
148 #[allow(missing_docs)]
149 pub fn synthetic() -> Self {
150 Self::new(dummy_span(), SpanOrigin::Synthetic)
151 }
152 #[allow(dead_code)]
153 #[allow(missing_docs)]
154 pub fn macro_expanded(span: Span, macro_name: impl Into<String>) -> Self {
155 Self::new(
156 span,
157 SpanOrigin::MacroExpanded {
158 macro_name: macro_name.into(),
159 },
160 )
161 }
162}
163#[allow(dead_code)]
165#[allow(missing_docs)]
166#[derive(Clone, Debug, Default)]
167pub struct SpanAnnotations {
168 items: Vec<AnnotatedSpan>,
169}
170impl SpanAnnotations {
171 #[allow(dead_code)]
172 #[allow(missing_docs)]
173 pub fn new() -> Self {
174 Self::default()
175 }
176 #[allow(dead_code)]
177 #[allow(missing_docs)]
178 pub fn add(&mut self, a: AnnotatedSpan) {
179 self.items.push(a);
180 }
181 #[allow(dead_code)]
182 #[allow(missing_docs)]
183 pub fn annotate(&mut self, span: Span, text: impl Into<String>) {
184 self.items.push(AnnotatedSpan::new(span, text));
185 }
186 #[allow(dead_code)]
187 #[allow(missing_docs)]
188 pub fn at_offset(&self, offset: usize) -> Vec<&AnnotatedSpan> {
189 self.items
190 .iter()
191 .filter(|a| span_contains(&a.span, offset))
192 .collect()
193 }
194 #[allow(dead_code)]
195 #[allow(missing_docs)]
196 pub fn with_tag<'a>(&'a self, tag: &str) -> Vec<&'a AnnotatedSpan> {
197 self.items
198 .iter()
199 .filter(|a| a.tag.as_deref() == Some(tag))
200 .collect()
201 }
202 #[allow(dead_code)]
203 #[allow(missing_docs)]
204 pub fn len(&self) -> usize {
205 self.items.len()
206 }
207 #[allow(dead_code)]
208 #[allow(missing_docs)]
209 pub fn is_empty(&self) -> bool {
210 self.items.is_empty()
211 }
212 #[allow(dead_code)]
213 #[allow(missing_docs)]
214 pub fn sort_by_start(&mut self) {
215 self.items.sort_by_key(|a| a.span.start);
216 }
217 #[allow(dead_code)]
218 #[allow(missing_docs)]
219 pub fn iter(&self) -> impl Iterator<Item = &AnnotatedSpan> {
220 self.items.iter()
221 }
222 #[allow(dead_code)]
223 #[allow(missing_docs)]
224 pub fn clear(&mut self) {
225 self.items.clear();
226 }
227 #[allow(dead_code)]
228 #[allow(missing_docs)]
229 pub fn merge(&mut self, other: SpanAnnotations) {
230 self.items.extend(other.items);
231 }
232}
233#[derive(Clone, Debug)]
235#[allow(missing_docs)]
236pub struct SpanBuilder {
237 start: usize,
238 line: usize,
239 column: usize,
240}
241impl SpanBuilder {
242 #[allow(missing_docs)]
244 pub fn new(start: usize, line: usize, column: usize) -> Self {
245 Self {
246 start,
247 line,
248 column,
249 }
250 }
251 #[allow(missing_docs)]
253 pub fn finish(&self, end: usize) -> Span {
254 Span::new(self.start, end, self.line, self.column)
255 }
256 #[allow(missing_docs)]
258 pub fn start(&self) -> usize {
259 self.start
260 }
261 #[allow(missing_docs)]
263 pub fn pos(&self) -> SourcePos {
264 SourcePos::new(self.line, self.column)
265 }
266}
267#[allow(dead_code)]
271#[allow(missing_docs)]
272pub struct Utf16Span {
273 pub start_utf16: usize,
275 pub end_utf16: usize,
277 #[allow(missing_docs)]
279 pub line: usize,
280}
281#[allow(dead_code)]
283#[allow(missing_docs)]
284#[derive(Clone, Debug, Default)]
285pub struct SpanStats {
286 pub count: usize,
287 pub total_len: usize,
288 pub min_len: usize,
289 pub max_len: usize,
290}
291impl SpanStats {
292 #[allow(dead_code)]
293 #[allow(missing_docs)]
294 pub fn compute(spans: &[Span]) -> Self {
295 if spans.is_empty() {
296 return Self::default();
297 }
298 let count = spans.len();
299 let lengths: Vec<usize> = spans.iter().map(span_len).collect();
300 let total_len: usize = lengths.iter().sum();
301 let min_len = *lengths.iter().min().unwrap_or(&0);
302 let max_len = *lengths.iter().max().unwrap_or(&0);
303 Self {
304 count,
305 total_len,
306 min_len,
307 max_len,
308 }
309 }
310 #[allow(dead_code)]
311 #[allow(missing_docs)]
312 pub fn avg_len(&self) -> usize {
313 if self.count == 0 {
314 0
315 } else {
316 self.total_len / self.count
317 }
318 }
319}
320#[allow(dead_code)]
322#[allow(missing_docs)]
323#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
324pub struct FileId(pub u32);
325impl FileId {
326 #[allow(dead_code)]
328 #[allow(missing_docs)]
329 pub const UNKNOWN: FileId = FileId(0);
330 #[allow(dead_code)]
332 #[allow(missing_docs)]
333 pub fn new(id: u32) -> Self {
334 FileId(id)
335 }
336 #[allow(dead_code)]
338 #[allow(missing_docs)]
339 pub fn raw(self) -> u32 {
340 self.0
341 }
342}
343#[allow(dead_code)]
345#[allow(missing_docs)]
346#[derive(Clone, Debug, Default)]
347pub struct SpanChain {
348 spans: Vec<Span>,
349}
350impl SpanChain {
351 #[allow(dead_code)]
352 #[allow(missing_docs)]
353 pub fn new() -> Self {
354 Self::default()
355 }
356 #[allow(dead_code)]
357 #[allow(missing_docs)]
358 pub fn push(&mut self, span: Span) {
359 self.spans.push(span);
360 }
361 #[allow(dead_code)]
362 #[allow(missing_docs)]
363 pub fn total_span(&self) -> Option<Span> {
364 merge_spans(&self.spans)
365 }
366 #[allow(dead_code)]
367 #[allow(missing_docs)]
368 pub fn len(&self) -> usize {
369 self.spans.len()
370 }
371 #[allow(dead_code)]
372 #[allow(missing_docs)]
373 pub fn is_empty(&self) -> bool {
374 self.spans.is_empty()
375 }
376 #[allow(dead_code)]
377 #[allow(missing_docs)]
378 pub fn iter(&self) -> impl Iterator<Item = &Span> {
379 self.spans.iter()
380 }
381 #[allow(dead_code)]
382 #[allow(missing_docs)]
383 pub fn first(&self) -> Option<&Span> {
384 self.spans.first()
385 }
386 #[allow(dead_code)]
387 #[allow(missing_docs)]
388 pub fn last(&self) -> Option<&Span> {
389 self.spans.last()
390 }
391 #[allow(dead_code)]
392 #[allow(missing_docs)]
393 pub fn clear(&mut self) {
394 self.spans.clear();
395 }
396}
397#[derive(Clone, Debug, Default)]
401#[allow(missing_docs)]
402pub struct SpanRegistry {
403 entries: std::collections::HashMap<String, Span>,
404}
405impl SpanRegistry {
406 #[allow(missing_docs)]
408 pub fn new() -> Self {
409 Self {
410 entries: std::collections::HashMap::new(),
411 }
412 }
413 #[allow(missing_docs)]
415 pub fn register(&mut self, key: impl Into<String>, span: Span) {
416 self.entries.insert(key.into(), span);
417 }
418 #[allow(missing_docs)]
420 pub fn get(&self, key: &str) -> Option<&Span> {
421 self.entries.get(key)
422 }
423 #[allow(missing_docs)]
425 pub fn contains(&self, key: &str) -> bool {
426 self.entries.contains_key(key)
427 }
428 #[allow(missing_docs)]
430 pub fn len(&self) -> usize {
431 self.entries.len()
432 }
433 #[allow(missing_docs)]
435 pub fn is_empty(&self) -> bool {
436 self.entries.is_empty()
437 }
438 #[allow(missing_docs)]
440 pub fn iter(&self) -> impl Iterator<Item = (&String, &Span)> {
441 self.entries.iter()
442 }
443 #[allow(missing_docs)]
445 pub fn remove(&mut self, key: &str) -> Option<Span> {
446 self.entries.remove(key)
447 }
448 #[allow(missing_docs)]
450 pub fn merge(&mut self, other: SpanRegistry) {
451 for (k, v) in other.entries {
452 self.entries.insert(k, v);
453 }
454 }
455}
456#[allow(dead_code)]
458#[allow(missing_docs)]
459#[derive(Clone, Debug)]
460pub struct PrioritizedSpan {
461 pub span: Span,
462 pub priority: u32,
463}
464impl PrioritizedSpan {
465 #[allow(dead_code)]
466 #[allow(missing_docs)]
467 pub fn new(span: Span, priority: u32) -> Self {
468 Self { span, priority }
469 }
470}
471#[derive(Clone, Debug, PartialEq)]
475#[allow(missing_docs)]
476pub struct LabeledSpan {
477 pub label: String,
479 pub span: Span,
481}
482impl LabeledSpan {
483 #[allow(missing_docs)]
485 pub fn new(label: impl Into<String>, span: Span) -> Self {
486 Self {
487 label: label.into(),
488 span,
489 }
490 }
491 #[allow(missing_docs)]
493 pub fn len(&self) -> usize {
494 span_len(&self.span)
495 }
496 #[allow(missing_docs)]
498 pub fn is_empty(&self) -> bool {
499 self.len() == 0
500 }
501}
502#[derive(Clone, Debug)]
505#[allow(missing_docs)]
506pub struct SourceCursor<'a> {
507 source: &'a str,
508 pos: usize,
509 line: usize,
510 col: usize,
511}
512impl<'a> SourceCursor<'a> {
513 #[allow(missing_docs)]
515 pub fn new(source: &'a str) -> Self {
516 Self {
517 source,
518 pos: 0,
519 line: 1,
520 col: 1,
521 }
522 }
523 #[allow(missing_docs)]
525 pub fn pos(&self) -> usize {
526 self.pos
527 }
528 #[allow(missing_docs)]
530 pub fn source_pos(&self) -> SourcePos {
531 SourcePos::new(self.line, self.col)
532 }
533 #[allow(missing_docs)]
535 pub fn current_span(&self) -> Span {
536 Span::new(self.pos, self.pos, self.line, self.col)
537 }
538 #[allow(missing_docs)]
540 pub fn is_eof(&self) -> bool {
541 self.pos >= self.source.len()
542 }
543 #[allow(missing_docs)]
545 pub fn peek(&self) -> Option<char> {
546 self.source[self.pos..].chars().next()
547 }
548 #[allow(missing_docs)]
550 pub fn peek_ahead(&self, n: usize) -> Option<char> {
551 self.source[self.pos..].chars().nth(n)
552 }
553 #[allow(missing_docs)]
555 pub fn advance(&mut self) -> Option<char> {
556 let ch = self.source[self.pos..].chars().next()?;
557 self.pos += ch.len_utf8();
558 if ch == '\n' {
559 self.line += 1;
560 self.col = 1;
561 } else {
562 self.col += 1;
563 }
564 Some(ch)
565 }
566 #[allow(missing_docs)]
568 pub fn advance_while<F: Fn(char) -> bool>(&mut self, pred: F) -> &'a str {
569 let start = self.pos;
570 while let Some(ch) = self.peek() {
571 if pred(ch) {
572 self.advance();
573 } else {
574 break;
575 }
576 }
577 &self.source[start..self.pos]
578 }
579 #[allow(missing_docs)]
581 pub fn advance_bytes(&mut self, n: usize) {
582 for _ in 0..n {
583 self.advance();
584 }
585 }
586 #[allow(missing_docs)]
588 pub fn span_from(&self, start: usize, start_line: usize, start_col: usize) -> Span {
589 Span::new(start, self.pos, start_line, start_col)
590 }
591 #[allow(missing_docs)]
593 pub fn rest(&self) -> &'a str {
594 &self.source[self.pos..]
595 }
596 #[allow(missing_docs)]
598 pub fn consumed(&self) -> &'a str {
599 &self.source[..self.pos]
600 }
601}
602#[allow(dead_code)]
604#[allow(missing_docs)]
605#[derive(Clone, Debug, Default)]
606pub struct DiagnosticSet {
607 diagnostics: Vec<DiagnosticSpan>,
608}
609impl DiagnosticSet {
610 #[allow(dead_code)]
612 #[allow(missing_docs)]
613 pub fn new() -> Self {
614 Self::default()
615 }
616 #[allow(dead_code)]
618 #[allow(missing_docs)]
619 pub fn add(&mut self, d: DiagnosticSpan) {
620 self.diagnostics.push(d);
621 }
622 #[allow(dead_code)]
624 #[allow(missing_docs)]
625 pub fn add_error(&mut self, span: Span, msg: impl Into<String>) {
626 self.add(DiagnosticSpan::error(span, msg));
627 }
628 #[allow(dead_code)]
630 #[allow(missing_docs)]
631 pub fn add_warning(&mut self, span: Span, msg: impl Into<String>) {
632 self.add(DiagnosticSpan::warning(span, msg));
633 }
634 #[allow(dead_code)]
636 #[allow(missing_docs)]
637 pub fn add_info(&mut self, span: Span, msg: impl Into<String>) {
638 self.add(DiagnosticSpan::info(span, msg));
639 }
640 #[allow(dead_code)]
642 #[allow(missing_docs)]
643 pub fn count_severity(&self, sev: &SpanSeverity) -> usize {
644 self.diagnostics
645 .iter()
646 .filter(|d| &d.severity == sev)
647 .count()
648 }
649 #[allow(dead_code)]
651 #[allow(missing_docs)]
652 pub fn len(&self) -> usize {
653 self.diagnostics.len()
654 }
655 #[allow(dead_code)]
657 #[allow(missing_docs)]
658 pub fn is_empty(&self) -> bool {
659 self.diagnostics.is_empty()
660 }
661 #[allow(dead_code)]
663 #[allow(missing_docs)]
664 pub fn has_errors(&self) -> bool {
665 self.diagnostics.iter().any(|d| d.severity.is_error())
666 }
667 #[allow(dead_code)]
669 #[allow(missing_docs)]
670 pub fn errors(&self) -> Vec<&DiagnosticSpan> {
671 self.diagnostics
672 .iter()
673 .filter(|d| d.severity.is_error())
674 .collect()
675 }
676 #[allow(dead_code)]
678 #[allow(missing_docs)]
679 pub fn warnings(&self) -> Vec<&DiagnosticSpan> {
680 self.diagnostics
681 .iter()
682 .filter(|d| matches!(d.severity, SpanSeverity::Warning))
683 .collect()
684 }
685 #[allow(dead_code)]
687 #[allow(missing_docs)]
688 pub fn sort_by_position(&mut self) {
689 self.diagnostics.sort_by_key(|d| d.span.start);
690 }
691 #[allow(dead_code)]
693 #[allow(missing_docs)]
694 pub fn iter(&self) -> impl Iterator<Item = &DiagnosticSpan> {
695 self.diagnostics.iter()
696 }
697 #[allow(dead_code)]
699 #[allow(missing_docs)]
700 pub fn clear(&mut self) {
701 self.diagnostics.clear();
702 }
703 #[allow(dead_code)]
705 #[allow(missing_docs)]
706 pub fn merge(&mut self, other: DiagnosticSet) {
707 self.diagnostics.extend(other.diagnostics);
708 }
709}
710#[allow(dead_code)]
712#[allow(missing_docs)]
713#[derive(Debug, Clone)]
714pub struct SpanDiff {
715 pub old: Span,
717 pub new: Span,
719 #[allow(missing_docs)]
721 pub byte_delta: i64,
722}
723impl SpanDiff {
724 #[allow(dead_code)]
726 #[allow(missing_docs)]
727 pub fn compute(old: Span, new: Span) -> Self {
728 let byte_delta = new.end as i64 - old.end as i64;
729 Self {
730 old,
731 new,
732 byte_delta,
733 }
734 }
735 #[allow(dead_code)]
737 #[allow(missing_docs)]
738 pub fn grew(&self) -> bool {
739 self.byte_delta > 0
740 }
741 #[allow(dead_code)]
743 #[allow(missing_docs)]
744 pub fn shrank(&self) -> bool {
745 self.byte_delta < 0
746 }
747 #[allow(dead_code)]
749 #[allow(missing_docs)]
750 pub fn unchanged(&self) -> bool {
751 self.byte_delta == 0
752 }
753}
754#[allow(dead_code)]
756#[allow(missing_docs)]
757#[derive(Clone, Debug, Default)]
758pub struct IncrementalSpanTracker {
759 spans: Vec<Span>,
760 edit_count: usize,
761}
762impl IncrementalSpanTracker {
763 #[allow(dead_code)]
764 #[allow(missing_docs)]
765 pub fn new() -> Self {
766 Self::default()
767 }
768 #[allow(dead_code)]
769 #[allow(missing_docs)]
770 pub fn track(&mut self, span: Span) {
771 self.spans.push(span);
772 }
773 #[allow(dead_code)]
774 #[allow(missing_docs)]
775 pub fn apply_edit(&mut self, edit_start: usize, delta: i64) {
776 shift_spans(&mut self.spans, edit_start, delta);
777 self.edit_count += 1;
778 }
779 #[allow(dead_code)]
780 #[allow(missing_docs)]
781 pub fn spans(&self) -> &[Span] {
782 &self.spans
783 }
784 #[allow(dead_code)]
785 #[allow(missing_docs)]
786 pub fn edit_count(&self) -> usize {
787 self.edit_count
788 }
789 #[allow(dead_code)]
790 #[allow(missing_docs)]
791 pub fn reset(&mut self) {
792 self.spans.clear();
793 self.edit_count = 0;
794 }
795}
796#[derive(Clone, Debug, PartialEq)]
798#[allow(missing_docs)]
799pub struct Spanned<T> {
800 pub value: T,
802 pub span: Span,
804}
805impl<T> Spanned<T> {
806 #[allow(missing_docs)]
808 pub fn new(value: T, span: Span) -> Self {
809 Self { value, span }
810 }
811 #[allow(missing_docs)]
813 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Spanned<U> {
814 Spanned {
815 value: f(self.value),
816 span: self.span,
817 }
818 }
819 #[allow(clippy::should_implement_trait)]
821 #[allow(missing_docs)]
822 pub fn as_ref(&self) -> &T {
823 &self.value
824 }
825 #[allow(missing_docs)]
827 pub fn into_value(self) -> T {
828 self.value
829 }
830}
831#[allow(dead_code)]
833#[allow(missing_docs)]
834#[derive(Clone, Debug, PartialEq)]
835pub enum SpanOrigin {
836 UserSource,
837 MacroExpanded { macro_name: String },
838 Elaborated,
839 Synthetic,
840}
841impl SpanOrigin {
842 #[allow(dead_code)]
843 #[allow(missing_docs)]
844 pub fn is_user_source(&self) -> bool {
845 matches!(self, SpanOrigin::UserSource)
846 }
847 #[allow(dead_code)]
848 #[allow(missing_docs)]
849 pub fn is_synthetic(&self) -> bool {
850 matches!(self, SpanOrigin::Synthetic)
851 }
852 #[allow(dead_code)]
853 #[allow(missing_docs)]
854 pub fn kind_str(&self) -> &'static str {
855 match self {
856 SpanOrigin::UserSource => "user",
857 SpanOrigin::MacroExpanded { .. } => "macro",
858 SpanOrigin::Elaborated => "elab",
859 SpanOrigin::Synthetic => "synthetic",
860 }
861 }
862}
863#[allow(dead_code)]
865#[allow(missing_docs)]
866#[derive(Clone, Debug, PartialEq)]
867pub enum SpanSeverity {
868 Info,
870 Warning,
872 Error,
874}
875impl SpanSeverity {
876 #[allow(dead_code)]
878 #[allow(missing_docs)]
879 pub fn is_error(&self) -> bool {
880 matches!(self, SpanSeverity::Error)
881 }
882 #[allow(dead_code)]
884 #[allow(missing_docs)]
885 pub fn label(&self) -> &'static str {
886 match self {
887 SpanSeverity::Info => "info",
888 SpanSeverity::Warning => "warning",
889 SpanSeverity::Error => "error",
890 }
891 }
892}
893#[allow(dead_code)]
895#[allow(missing_docs)]
896#[derive(Clone, Debug, PartialEq)]
897pub struct AnnotatedSpan {
898 pub span: Span,
899 pub annotation: String,
900 pub tag: Option<String>,
901}
902impl AnnotatedSpan {
903 #[allow(dead_code)]
904 #[allow(missing_docs)]
905 pub fn new(span: Span, annotation: impl Into<String>) -> Self {
906 Self {
907 span,
908 annotation: annotation.into(),
909 tag: None,
910 }
911 }
912 #[allow(dead_code)]
913 #[allow(missing_docs)]
914 pub fn with_tag(span: Span, annotation: impl Into<String>, tag: impl Into<String>) -> Self {
915 Self {
916 span,
917 annotation: annotation.into(),
918 tag: Some(tag.into()),
919 }
920 }
921 #[allow(dead_code)]
922 #[allow(missing_docs)]
923 pub fn len(&self) -> usize {
924 span_len(&self.span)
925 }
926 #[allow(dead_code)]
927 #[allow(missing_docs)]
928 pub fn is_empty(&self) -> bool {
929 self.len() == 0
930 }
931}
932#[allow(dead_code)]
934#[allow(missing_docs)]
935#[derive(Clone, Copy, Debug, PartialEq, Eq)]
936pub struct SpanRange {
937 pub start_idx: usize,
938 pub end_idx: usize,
939}
940impl SpanRange {
941 #[allow(dead_code)]
942 #[allow(missing_docs)]
943 pub fn new(start_idx: usize, end_idx: usize) -> Self {
944 Self { start_idx, end_idx }
945 }
946 #[allow(dead_code)]
947 #[allow(missing_docs)]
948 pub fn len(&self) -> usize {
949 self.end_idx.saturating_sub(self.start_idx)
950 }
951 #[allow(dead_code)]
952 #[allow(missing_docs)]
953 pub fn is_empty(&self) -> bool {
954 self.start_idx >= self.end_idx
955 }
956 #[allow(dead_code)]
957 #[allow(missing_docs)]
958 pub fn contains(&self, idx: usize) -> bool {
959 idx >= self.start_idx && idx < self.end_idx
960 }
961}
962#[allow(dead_code)]
964#[allow(missing_docs)]
965#[derive(Clone, Debug)]
966pub struct PaddedSpan {
967 pub inner: Span,
968 pub left_pad: usize,
969 pub right_pad: usize,
970}
971impl PaddedSpan {
972 #[allow(dead_code)]
973 #[allow(missing_docs)]
974 pub fn new(inner: Span, left_pad: usize, right_pad: usize) -> Self {
975 Self {
976 inner,
977 left_pad,
978 right_pad,
979 }
980 }
981 #[allow(dead_code)]
983 #[allow(missing_docs)]
984 pub fn expanded(&self, source_len: usize) -> Span {
985 let start = self.inner.start.saturating_sub(self.left_pad);
986 let end = (self.inner.end + self.right_pad).min(source_len);
987 Span::new(start, end, self.inner.line, self.inner.column)
988 }
989}
990#[allow(dead_code)]
992#[allow(missing_docs)]
993#[derive(Clone, Debug, Default)]
994pub struct SpanMap<V> {
995 entries: Vec<(usize, V)>,
996}
997impl<V> SpanMap<V> {
998 #[allow(dead_code)]
1000 #[allow(missing_docs)]
1001 pub fn new() -> Self {
1002 Self {
1003 entries: Vec::new(),
1004 }
1005 }
1006 #[allow(dead_code)]
1008 #[allow(missing_docs)]
1009 pub fn insert(&mut self, offset: usize, value: V) {
1010 self.entries.push((offset, value));
1011 }
1012 #[allow(dead_code)]
1014 #[allow(missing_docs)]
1015 pub fn get(&self, offset: usize) -> Option<&V> {
1016 self.entries
1017 .iter()
1018 .find(|(o, _)| *o == offset)
1019 .map(|(_, v)| v)
1020 }
1021 #[allow(dead_code)]
1023 #[allow(missing_docs)]
1024 pub fn len(&self) -> usize {
1025 self.entries.len()
1026 }
1027 #[allow(dead_code)]
1029 #[allow(missing_docs)]
1030 pub fn is_empty(&self) -> bool {
1031 self.entries.is_empty()
1032 }
1033 #[allow(dead_code)]
1035 #[allow(missing_docs)]
1036 pub fn iter(&self) -> impl Iterator<Item = &(usize, V)> {
1037 self.entries.iter()
1038 }
1039}
1040#[allow(dead_code)]
1042#[allow(missing_docs)]
1043#[derive(Clone, Debug, PartialEq)]
1044pub struct FileSpan {
1045 pub file: FileId,
1047 pub span: Span,
1049}
1050impl FileSpan {
1051 #[allow(dead_code)]
1053 #[allow(missing_docs)]
1054 pub fn new(file: FileId, span: Span) -> Self {
1055 Self { file, span }
1056 }
1057 #[allow(dead_code)]
1059 #[allow(missing_docs)]
1060 pub fn len(&self) -> usize {
1061 span_len(&self.span)
1062 }
1063 #[allow(dead_code)]
1065 #[allow(missing_docs)]
1066 pub fn is_empty(&self) -> bool {
1067 self.len() == 0
1068 }
1069 #[allow(dead_code)]
1071 #[allow(missing_docs)]
1072 pub fn merge_with(&self, other: &FileSpan) -> FileSpan {
1073 assert_eq!(
1074 self.file, other.file,
1075 "cannot merge spans from different files"
1076 );
1077 FileSpan {
1078 file: self.file,
1079 span: self.span.merge(&other.span),
1080 }
1081 }
1082}
1083#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1085#[allow(missing_docs)]
1086pub struct SourcePos {
1087 pub line: usize,
1089 pub col: usize,
1091}
1092impl SourcePos {
1093 #[allow(missing_docs)]
1095 pub fn new(line: usize, col: usize) -> Self {
1096 Self { line, col }
1097 }
1098 #[allow(missing_docs)]
1100 pub fn start() -> Self {
1101 Self { line: 1, col: 1 }
1102 }
1103 #[allow(missing_docs)]
1105 pub fn advance_col(&self) -> Self {
1106 Self {
1107 line: self.line,
1108 col: self.col + 1,
1109 }
1110 }
1111 #[allow(missing_docs)]
1113 pub fn advance_line(&self) -> Self {
1114 Self {
1115 line: self.line + 1,
1116 col: 1,
1117 }
1118 }
1119 #[allow(missing_docs)]
1121 pub fn same_line(&self, other: &SourcePos) -> bool {
1122 self.line == other.line
1123 }
1124}