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