readme_sync/
codemap_spans.rs1use std::vec::Vec;
2
3use codemap_diagnostic::SpanLabel;
4
5use crate::{CMarkSpan, CodemapFiles, TextSource};
6
7#[derive(Debug)]
9pub struct CodemapSpans<'a> {
10 codemap_files: &'a mut CodemapFiles,
11 span_labels: Vec<SpanLabel>,
12}
13
14impl<'a> CodemapSpans<'a> {
15 pub fn new(codemap_files: &'a mut CodemapFiles) -> Self {
17 CodemapSpans {
18 codemap_files,
19 span_labels: Vec::new(),
20 }
21 }
22
23 pub fn codemap_files(&self) -> &CodemapFiles {
25 self.codemap_files
26 }
27
28 pub fn span_labels(&self) -> &[SpanLabel] {
30 &self.span_labels
31 }
32
33 pub fn into_span_labels(self) -> Vec<SpanLabel> {
35 self.span_labels
36 }
37
38 pub fn span_labels_from<I>(codemap_files: &'a mut CodemapFiles, iter: I) -> Vec<SpanLabel>
40 where
41 I: IntoIterator<Item = CMarkSpan<'a>>,
42 {
43 let mut codemap_spans = Self::new(codemap_files);
44 codemap_spans.extend(iter);
45 codemap_spans.into_span_labels()
46 }
47}
48
49trait FileSubSpan {
50 fn subspan(&self, range: &core::ops::Range<usize>) -> codemap::Span;
51}
52
53impl FileSubSpan for codemap::File {
54 fn subspan(&self, range: &core::ops::Range<usize>) -> codemap::Span {
55 self.span.subspan(range.start as u64, range.end as u64)
56 }
57}
58
59impl<'a> Extend<CMarkSpan<'a>> for CodemapSpans<'_> {
60 fn extend<T: IntoIterator<Item = CMarkSpan<'a>>>(&mut self, iter: T) {
61 use codemap_diagnostic::SpanStyle;
62
63 let iter = iter.into_iter();
64 if let Some(upper) = iter.size_hint().1 {
65 self.span_labels.reserve(upper);
66 }
67 for item in iter {
68 match item.text_source {
69 TextSource::File(file) => {
70 let span = self
71 .codemap_files
72 .get_or_insert_codemap_file(file)
73 .subspan(item.range);
74 self.span_labels.push(SpanLabel {
75 span,
76 style: SpanStyle::Primary,
77 label: None,
78 });
79 }
80 TextSource::FileDocs(file_docs) => {
81 let span = self
82 .codemap_files
83 .get_or_insert_codemap_docs_file(file_docs)
84 .subspan(item.range);
85 self.span_labels.push(SpanLabel {
86 span,
87 style: SpanStyle::Primary,
88 label: None,
89 });
90
91 let file = file_docs.file();
92 let file_range = file_docs.remap_to_file(item.range.clone());
93 if let Some(file_range) = file_range {
94 let span = self
95 .codemap_files
96 .get_or_insert_codemap_file(file)
97 .subspan(&file_range);
98 self.span_labels.push(SpanLabel {
99 span,
100 style: SpanStyle::Secondary,
101 label: None,
102 });
103 }
104 }
105 }
106 }
107 }
108}