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 self.total_len.checked_div(self.count).unwrap_or(0)
314 }
315}
316#[allow(dead_code)]
318#[allow(missing_docs)]
319#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
320pub struct FileId(pub u32);
321impl FileId {
322 #[allow(dead_code)]
324 #[allow(missing_docs)]
325 pub const UNKNOWN: FileId = FileId(0);
326 #[allow(dead_code)]
328 #[allow(missing_docs)]
329 pub fn new(id: u32) -> Self {
330 FileId(id)
331 }
332 #[allow(dead_code)]
334 #[allow(missing_docs)]
335 pub fn raw(self) -> u32 {
336 self.0
337 }
338}
339#[allow(dead_code)]
341#[allow(missing_docs)]
342#[derive(Clone, Debug, Default)]
343pub struct SpanChain {
344 spans: Vec<Span>,
345}
346impl SpanChain {
347 #[allow(dead_code)]
348 #[allow(missing_docs)]
349 pub fn new() -> Self {
350 Self::default()
351 }
352 #[allow(dead_code)]
353 #[allow(missing_docs)]
354 pub fn push(&mut self, span: Span) {
355 self.spans.push(span);
356 }
357 #[allow(dead_code)]
358 #[allow(missing_docs)]
359 pub fn total_span(&self) -> Option<Span> {
360 merge_spans(&self.spans)
361 }
362 #[allow(dead_code)]
363 #[allow(missing_docs)]
364 pub fn len(&self) -> usize {
365 self.spans.len()
366 }
367 #[allow(dead_code)]
368 #[allow(missing_docs)]
369 pub fn is_empty(&self) -> bool {
370 self.spans.is_empty()
371 }
372 #[allow(dead_code)]
373 #[allow(missing_docs)]
374 pub fn iter(&self) -> impl Iterator<Item = &Span> {
375 self.spans.iter()
376 }
377 #[allow(dead_code)]
378 #[allow(missing_docs)]
379 pub fn first(&self) -> Option<&Span> {
380 self.spans.first()
381 }
382 #[allow(dead_code)]
383 #[allow(missing_docs)]
384 pub fn last(&self) -> Option<&Span> {
385 self.spans.last()
386 }
387 #[allow(dead_code)]
388 #[allow(missing_docs)]
389 pub fn clear(&mut self) {
390 self.spans.clear();
391 }
392}
393#[derive(Clone, Debug, Default)]
397#[allow(missing_docs)]
398pub struct SpanRegistry {
399 entries: std::collections::HashMap<String, Span>,
400}
401impl SpanRegistry {
402 #[allow(missing_docs)]
404 pub fn new() -> Self {
405 Self {
406 entries: std::collections::HashMap::new(),
407 }
408 }
409 #[allow(missing_docs)]
411 pub fn register(&mut self, key: impl Into<String>, span: Span) {
412 self.entries.insert(key.into(), span);
413 }
414 #[allow(missing_docs)]
416 pub fn get(&self, key: &str) -> Option<&Span> {
417 self.entries.get(key)
418 }
419 #[allow(missing_docs)]
421 pub fn contains(&self, key: &str) -> bool {
422 self.entries.contains_key(key)
423 }
424 #[allow(missing_docs)]
426 pub fn len(&self) -> usize {
427 self.entries.len()
428 }
429 #[allow(missing_docs)]
431 pub fn is_empty(&self) -> bool {
432 self.entries.is_empty()
433 }
434 #[allow(missing_docs)]
436 pub fn iter(&self) -> impl Iterator<Item = (&String, &Span)> {
437 self.entries.iter()
438 }
439 #[allow(missing_docs)]
441 pub fn remove(&mut self, key: &str) -> Option<Span> {
442 self.entries.remove(key)
443 }
444 #[allow(missing_docs)]
446 pub fn merge(&mut self, other: SpanRegistry) {
447 for (k, v) in other.entries {
448 self.entries.insert(k, v);
449 }
450 }
451}
452#[allow(dead_code)]
454#[allow(missing_docs)]
455#[derive(Clone, Debug)]
456pub struct PrioritizedSpan {
457 pub span: Span,
458 pub priority: u32,
459}
460impl PrioritizedSpan {
461 #[allow(dead_code)]
462 #[allow(missing_docs)]
463 pub fn new(span: Span, priority: u32) -> Self {
464 Self { span, priority }
465 }
466}
467#[derive(Clone, Debug, PartialEq)]
471#[allow(missing_docs)]
472pub struct LabeledSpan {
473 pub label: String,
475 pub span: Span,
477}
478impl LabeledSpan {
479 #[allow(missing_docs)]
481 pub fn new(label: impl Into<String>, span: Span) -> Self {
482 Self {
483 label: label.into(),
484 span,
485 }
486 }
487 #[allow(missing_docs)]
489 pub fn len(&self) -> usize {
490 span_len(&self.span)
491 }
492 #[allow(missing_docs)]
494 pub fn is_empty(&self) -> bool {
495 self.len() == 0
496 }
497}
498#[derive(Clone, Debug)]
501#[allow(missing_docs)]
502pub struct SourceCursor<'a> {
503 source: &'a str,
504 pos: usize,
505 line: usize,
506 col: usize,
507}
508impl<'a> SourceCursor<'a> {
509 #[allow(missing_docs)]
511 pub fn new(source: &'a str) -> Self {
512 Self {
513 source,
514 pos: 0,
515 line: 1,
516 col: 1,
517 }
518 }
519 #[allow(missing_docs)]
521 pub fn pos(&self) -> usize {
522 self.pos
523 }
524 #[allow(missing_docs)]
526 pub fn source_pos(&self) -> SourcePos {
527 SourcePos::new(self.line, self.col)
528 }
529 #[allow(missing_docs)]
531 pub fn current_span(&self) -> Span {
532 Span::new(self.pos, self.pos, self.line, self.col)
533 }
534 #[allow(missing_docs)]
536 pub fn is_eof(&self) -> bool {
537 self.pos >= self.source.len()
538 }
539 #[allow(missing_docs)]
541 pub fn peek(&self) -> Option<char> {
542 self.source[self.pos..].chars().next()
543 }
544 #[allow(missing_docs)]
546 pub fn peek_ahead(&self, n: usize) -> Option<char> {
547 self.source[self.pos..].chars().nth(n)
548 }
549 #[allow(missing_docs)]
551 pub fn advance(&mut self) -> Option<char> {
552 let ch = self.source[self.pos..].chars().next()?;
553 self.pos += ch.len_utf8();
554 if ch == '\n' {
555 self.line += 1;
556 self.col = 1;
557 } else {
558 self.col += 1;
559 }
560 Some(ch)
561 }
562 #[allow(missing_docs)]
564 pub fn advance_while<F: Fn(char) -> bool>(&mut self, pred: F) -> &'a str {
565 let start = self.pos;
566 while let Some(ch) = self.peek() {
567 if pred(ch) {
568 self.advance();
569 } else {
570 break;
571 }
572 }
573 &self.source[start..self.pos]
574 }
575 #[allow(missing_docs)]
577 pub fn advance_bytes(&mut self, n: usize) {
578 for _ in 0..n {
579 self.advance();
580 }
581 }
582 #[allow(missing_docs)]
584 pub fn span_from(&self, start: usize, start_line: usize, start_col: usize) -> Span {
585 Span::new(start, self.pos, start_line, start_col)
586 }
587 #[allow(missing_docs)]
589 pub fn rest(&self) -> &'a str {
590 &self.source[self.pos..]
591 }
592 #[allow(missing_docs)]
594 pub fn consumed(&self) -> &'a str {
595 &self.source[..self.pos]
596 }
597}
598#[allow(dead_code)]
600#[allow(missing_docs)]
601#[derive(Clone, Debug, Default)]
602pub struct DiagnosticSet {
603 diagnostics: Vec<DiagnosticSpan>,
604}
605impl DiagnosticSet {
606 #[allow(dead_code)]
608 #[allow(missing_docs)]
609 pub fn new() -> Self {
610 Self::default()
611 }
612 #[allow(dead_code)]
614 #[allow(missing_docs)]
615 pub fn add(&mut self, d: DiagnosticSpan) {
616 self.diagnostics.push(d);
617 }
618 #[allow(dead_code)]
620 #[allow(missing_docs)]
621 pub fn add_error(&mut self, span: Span, msg: impl Into<String>) {
622 self.add(DiagnosticSpan::error(span, msg));
623 }
624 #[allow(dead_code)]
626 #[allow(missing_docs)]
627 pub fn add_warning(&mut self, span: Span, msg: impl Into<String>) {
628 self.add(DiagnosticSpan::warning(span, msg));
629 }
630 #[allow(dead_code)]
632 #[allow(missing_docs)]
633 pub fn add_info(&mut self, span: Span, msg: impl Into<String>) {
634 self.add(DiagnosticSpan::info(span, msg));
635 }
636 #[allow(dead_code)]
638 #[allow(missing_docs)]
639 pub fn count_severity(&self, sev: &SpanSeverity) -> usize {
640 self.diagnostics
641 .iter()
642 .filter(|d| &d.severity == sev)
643 .count()
644 }
645 #[allow(dead_code)]
647 #[allow(missing_docs)]
648 pub fn len(&self) -> usize {
649 self.diagnostics.len()
650 }
651 #[allow(dead_code)]
653 #[allow(missing_docs)]
654 pub fn is_empty(&self) -> bool {
655 self.diagnostics.is_empty()
656 }
657 #[allow(dead_code)]
659 #[allow(missing_docs)]
660 pub fn has_errors(&self) -> bool {
661 self.diagnostics.iter().any(|d| d.severity.is_error())
662 }
663 #[allow(dead_code)]
665 #[allow(missing_docs)]
666 pub fn errors(&self) -> Vec<&DiagnosticSpan> {
667 self.diagnostics
668 .iter()
669 .filter(|d| d.severity.is_error())
670 .collect()
671 }
672 #[allow(dead_code)]
674 #[allow(missing_docs)]
675 pub fn warnings(&self) -> Vec<&DiagnosticSpan> {
676 self.diagnostics
677 .iter()
678 .filter(|d| matches!(d.severity, SpanSeverity::Warning))
679 .collect()
680 }
681 #[allow(dead_code)]
683 #[allow(missing_docs)]
684 pub fn sort_by_position(&mut self) {
685 self.diagnostics.sort_by_key(|d| d.span.start);
686 }
687 #[allow(dead_code)]
689 #[allow(missing_docs)]
690 pub fn iter(&self) -> impl Iterator<Item = &DiagnosticSpan> {
691 self.diagnostics.iter()
692 }
693 #[allow(dead_code)]
695 #[allow(missing_docs)]
696 pub fn clear(&mut self) {
697 self.diagnostics.clear();
698 }
699 #[allow(dead_code)]
701 #[allow(missing_docs)]
702 pub fn merge(&mut self, other: DiagnosticSet) {
703 self.diagnostics.extend(other.diagnostics);
704 }
705}
706#[allow(dead_code)]
708#[allow(missing_docs)]
709#[derive(Debug, Clone)]
710pub struct SpanDiff {
711 pub old: Span,
713 pub new: Span,
715 #[allow(missing_docs)]
717 pub byte_delta: i64,
718}
719impl SpanDiff {
720 #[allow(dead_code)]
722 #[allow(missing_docs)]
723 pub fn compute(old: Span, new: Span) -> Self {
724 let byte_delta = new.end as i64 - old.end as i64;
725 Self {
726 old,
727 new,
728 byte_delta,
729 }
730 }
731 #[allow(dead_code)]
733 #[allow(missing_docs)]
734 pub fn grew(&self) -> bool {
735 self.byte_delta > 0
736 }
737 #[allow(dead_code)]
739 #[allow(missing_docs)]
740 pub fn shrank(&self) -> bool {
741 self.byte_delta < 0
742 }
743 #[allow(dead_code)]
745 #[allow(missing_docs)]
746 pub fn unchanged(&self) -> bool {
747 self.byte_delta == 0
748 }
749}
750#[allow(dead_code)]
752#[allow(missing_docs)]
753#[derive(Clone, Debug, Default)]
754pub struct IncrementalSpanTracker {
755 spans: Vec<Span>,
756 edit_count: usize,
757}
758impl IncrementalSpanTracker {
759 #[allow(dead_code)]
760 #[allow(missing_docs)]
761 pub fn new() -> Self {
762 Self::default()
763 }
764 #[allow(dead_code)]
765 #[allow(missing_docs)]
766 pub fn track(&mut self, span: Span) {
767 self.spans.push(span);
768 }
769 #[allow(dead_code)]
770 #[allow(missing_docs)]
771 pub fn apply_edit(&mut self, edit_start: usize, delta: i64) {
772 shift_spans(&mut self.spans, edit_start, delta);
773 self.edit_count += 1;
774 }
775 #[allow(dead_code)]
776 #[allow(missing_docs)]
777 pub fn spans(&self) -> &[Span] {
778 &self.spans
779 }
780 #[allow(dead_code)]
781 #[allow(missing_docs)]
782 pub fn edit_count(&self) -> usize {
783 self.edit_count
784 }
785 #[allow(dead_code)]
786 #[allow(missing_docs)]
787 pub fn reset(&mut self) {
788 self.spans.clear();
789 self.edit_count = 0;
790 }
791}
792#[derive(Clone, Debug, PartialEq)]
794#[allow(missing_docs)]
795pub struct Spanned<T> {
796 pub value: T,
798 pub span: Span,
800}
801impl<T> Spanned<T> {
802 #[allow(missing_docs)]
804 pub fn new(value: T, span: Span) -> Self {
805 Self { value, span }
806 }
807 #[allow(missing_docs)]
809 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Spanned<U> {
810 Spanned {
811 value: f(self.value),
812 span: self.span,
813 }
814 }
815 #[allow(clippy::should_implement_trait)]
817 #[allow(missing_docs)]
818 pub fn as_ref(&self) -> &T {
819 &self.value
820 }
821 #[allow(missing_docs)]
823 pub fn into_value(self) -> T {
824 self.value
825 }
826}
827#[allow(dead_code)]
829#[allow(missing_docs)]
830#[derive(Clone, Debug, PartialEq)]
831pub enum SpanOrigin {
832 UserSource,
833 MacroExpanded { macro_name: String },
834 Elaborated,
835 Synthetic,
836}
837impl SpanOrigin {
838 #[allow(dead_code)]
839 #[allow(missing_docs)]
840 pub fn is_user_source(&self) -> bool {
841 matches!(self, SpanOrigin::UserSource)
842 }
843 #[allow(dead_code)]
844 #[allow(missing_docs)]
845 pub fn is_synthetic(&self) -> bool {
846 matches!(self, SpanOrigin::Synthetic)
847 }
848 #[allow(dead_code)]
849 #[allow(missing_docs)]
850 pub fn kind_str(&self) -> &'static str {
851 match self {
852 SpanOrigin::UserSource => "user",
853 SpanOrigin::MacroExpanded { .. } => "macro",
854 SpanOrigin::Elaborated => "elab",
855 SpanOrigin::Synthetic => "synthetic",
856 }
857 }
858}
859#[allow(dead_code)]
861#[allow(missing_docs)]
862#[derive(Clone, Debug, PartialEq)]
863pub enum SpanSeverity {
864 Info,
866 Warning,
868 Error,
870}
871impl SpanSeverity {
872 #[allow(dead_code)]
874 #[allow(missing_docs)]
875 pub fn is_error(&self) -> bool {
876 matches!(self, SpanSeverity::Error)
877 }
878 #[allow(dead_code)]
880 #[allow(missing_docs)]
881 pub fn label(&self) -> &'static str {
882 match self {
883 SpanSeverity::Info => "info",
884 SpanSeverity::Warning => "warning",
885 SpanSeverity::Error => "error",
886 }
887 }
888}
889#[allow(dead_code)]
891#[allow(missing_docs)]
892#[derive(Clone, Debug, PartialEq)]
893pub struct AnnotatedSpan {
894 pub span: Span,
895 pub annotation: String,
896 pub tag: Option<String>,
897}
898impl AnnotatedSpan {
899 #[allow(dead_code)]
900 #[allow(missing_docs)]
901 pub fn new(span: Span, annotation: impl Into<String>) -> Self {
902 Self {
903 span,
904 annotation: annotation.into(),
905 tag: None,
906 }
907 }
908 #[allow(dead_code)]
909 #[allow(missing_docs)]
910 pub fn with_tag(span: Span, annotation: impl Into<String>, tag: impl Into<String>) -> Self {
911 Self {
912 span,
913 annotation: annotation.into(),
914 tag: Some(tag.into()),
915 }
916 }
917 #[allow(dead_code)]
918 #[allow(missing_docs)]
919 pub fn len(&self) -> usize {
920 span_len(&self.span)
921 }
922 #[allow(dead_code)]
923 #[allow(missing_docs)]
924 pub fn is_empty(&self) -> bool {
925 self.len() == 0
926 }
927}
928#[allow(dead_code)]
930#[allow(missing_docs)]
931#[derive(Clone, Copy, Debug, PartialEq, Eq)]
932pub struct SpanRange {
933 pub start_idx: usize,
934 pub end_idx: usize,
935}
936impl SpanRange {
937 #[allow(dead_code)]
938 #[allow(missing_docs)]
939 pub fn new(start_idx: usize, end_idx: usize) -> Self {
940 Self { start_idx, end_idx }
941 }
942 #[allow(dead_code)]
943 #[allow(missing_docs)]
944 pub fn len(&self) -> usize {
945 self.end_idx.saturating_sub(self.start_idx)
946 }
947 #[allow(dead_code)]
948 #[allow(missing_docs)]
949 pub fn is_empty(&self) -> bool {
950 self.start_idx >= self.end_idx
951 }
952 #[allow(dead_code)]
953 #[allow(missing_docs)]
954 pub fn contains(&self, idx: usize) -> bool {
955 idx >= self.start_idx && idx < self.end_idx
956 }
957}
958#[allow(dead_code)]
960#[allow(missing_docs)]
961#[derive(Clone, Debug)]
962pub struct PaddedSpan {
963 pub inner: Span,
964 pub left_pad: usize,
965 pub right_pad: usize,
966}
967impl PaddedSpan {
968 #[allow(dead_code)]
969 #[allow(missing_docs)]
970 pub fn new(inner: Span, left_pad: usize, right_pad: usize) -> Self {
971 Self {
972 inner,
973 left_pad,
974 right_pad,
975 }
976 }
977 #[allow(dead_code)]
979 #[allow(missing_docs)]
980 pub fn expanded(&self, source_len: usize) -> Span {
981 let start = self.inner.start.saturating_sub(self.left_pad);
982 let end = (self.inner.end + self.right_pad).min(source_len);
983 Span::new(start, end, self.inner.line, self.inner.column)
984 }
985}
986#[allow(dead_code)]
988#[allow(missing_docs)]
989#[derive(Clone, Debug, Default)]
990pub struct SpanMap<V> {
991 entries: Vec<(usize, V)>,
992}
993impl<V> SpanMap<V> {
994 #[allow(dead_code)]
996 #[allow(missing_docs)]
997 pub fn new() -> Self {
998 Self {
999 entries: Vec::new(),
1000 }
1001 }
1002 #[allow(dead_code)]
1004 #[allow(missing_docs)]
1005 pub fn insert(&mut self, offset: usize, value: V) {
1006 self.entries.push((offset, value));
1007 }
1008 #[allow(dead_code)]
1010 #[allow(missing_docs)]
1011 pub fn get(&self, offset: usize) -> Option<&V> {
1012 self.entries
1013 .iter()
1014 .find(|(o, _)| *o == offset)
1015 .map(|(_, v)| v)
1016 }
1017 #[allow(dead_code)]
1019 #[allow(missing_docs)]
1020 pub fn len(&self) -> usize {
1021 self.entries.len()
1022 }
1023 #[allow(dead_code)]
1025 #[allow(missing_docs)]
1026 pub fn is_empty(&self) -> bool {
1027 self.entries.is_empty()
1028 }
1029 #[allow(dead_code)]
1031 #[allow(missing_docs)]
1032 pub fn iter(&self) -> impl Iterator<Item = &(usize, V)> {
1033 self.entries.iter()
1034 }
1035}
1036#[allow(dead_code)]
1038#[allow(missing_docs)]
1039#[derive(Clone, Debug, PartialEq)]
1040pub struct FileSpan {
1041 pub file: FileId,
1043 pub span: Span,
1045}
1046impl FileSpan {
1047 #[allow(dead_code)]
1049 #[allow(missing_docs)]
1050 pub fn new(file: FileId, span: Span) -> Self {
1051 Self { file, span }
1052 }
1053 #[allow(dead_code)]
1055 #[allow(missing_docs)]
1056 pub fn len(&self) -> usize {
1057 span_len(&self.span)
1058 }
1059 #[allow(dead_code)]
1061 #[allow(missing_docs)]
1062 pub fn is_empty(&self) -> bool {
1063 self.len() == 0
1064 }
1065 #[allow(dead_code)]
1067 #[allow(missing_docs)]
1068 pub fn merge_with(&self, other: &FileSpan) -> FileSpan {
1069 assert_eq!(
1070 self.file, other.file,
1071 "cannot merge spans from different files"
1072 );
1073 FileSpan {
1074 file: self.file,
1075 span: self.span.merge(&other.span),
1076 }
1077 }
1078}
1079#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1081#[allow(missing_docs)]
1082pub struct SourcePos {
1083 pub line: usize,
1085 pub col: usize,
1087}
1088impl SourcePos {
1089 #[allow(missing_docs)]
1091 pub fn new(line: usize, col: usize) -> Self {
1092 Self { line, col }
1093 }
1094 #[allow(missing_docs)]
1096 pub fn start() -> Self {
1097 Self { line: 1, col: 1 }
1098 }
1099 #[allow(missing_docs)]
1101 pub fn advance_col(&self) -> Self {
1102 Self {
1103 line: self.line,
1104 col: self.col + 1,
1105 }
1106 }
1107 #[allow(missing_docs)]
1109 pub fn advance_line(&self) -> Self {
1110 Self {
1111 line: self.line + 1,
1112 col: 1,
1113 }
1114 }
1115 #[allow(missing_docs)]
1117 pub fn same_line(&self, other: &SourcePos) -> bool {
1118 self.line == other.line
1119 }
1120}