1 // Code for annotating snippets.
5 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
8 pub annotations: Vec<Annotation>,
11 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
12 pub struct MultilineAnnotation {
14 pub line_start: usize,
19 pub label: Option<String>,
20 pub overlaps_exactly: bool,
23 impl MultilineAnnotation {
24 pub fn increase_depth(&mut self) {
28 /// Compare two `MultilineAnnotation`s considering only the `Span` they cover.
29 pub fn same_span(&self, other: &MultilineAnnotation) -> bool {
30 self.line_start == other.line_start
31 && self.line_end == other.line_end
32 && self.start_col == other.start_col
33 && self.end_col == other.end_col
36 pub fn as_start(&self) -> Annotation {
38 start_col: self.start_col,
39 end_col: self.start_col + 1,
40 is_primary: self.is_primary,
42 annotation_type: AnnotationType::MultilineStart(self.depth),
46 pub fn as_end(&self) -> Annotation {
48 start_col: self.end_col.saturating_sub(1),
49 end_col: self.end_col,
50 is_primary: self.is_primary,
51 label: self.label.clone(),
52 annotation_type: AnnotationType::MultilineEnd(self.depth),
56 pub fn as_line(&self) -> Annotation {
60 is_primary: self.is_primary,
62 annotation_type: AnnotationType::MultilineLine(self.depth),
67 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
68 pub enum AnnotationType {
69 /// Annotation under a single line of code
72 /// Annotation enclosing the first and last character of a multiline span
73 Multiline(MultilineAnnotation),
75 // The Multiline type above is replaced with the following three in order
76 // to reuse the current label drawing code.
78 // Each of these corresponds to one part of the following diagram:
81 // | _________^ < MultilineStart
82 // x | | y), < MultilineLine
83 // | |______________^ label < MultilineEnd
85 /// Annotation marking the first character of a fully shown multiline span
86 MultilineStart(usize),
87 /// Annotation marking the last character of a fully shown multiline span
89 /// Line at the left enclosing the lines of a fully shown multiline span
90 // Just a placeholder for the drawing algorithm, to know that it shouldn't skip the first 4
91 // and last 2 lines of code. The actual line is drawn in `emit_message_default` and not in
92 // `draw_multiline_line`.
96 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
97 pub struct Annotation {
98 /// Start column, 0-based indexing -- counting *characters*, not
99 /// utf-8 bytes. Note that it is important that this field goes
100 /// first, so that when we sort, we sort orderings by start
102 pub start_col: usize,
104 /// End column within the line (exclusive)
107 /// Is this annotation derived from primary span
108 pub is_primary: bool,
110 /// Optional label to display adjacent to the annotation.
111 pub label: Option<String>,
113 /// Is this a single line, multiline or multiline span minimized down to a
115 pub annotation_type: AnnotationType,
119 /// Whether this annotation is a vertical line placeholder.
120 pub fn is_line(&self) -> bool {
121 matches!(self.annotation_type, AnnotationType::MultilineLine(_))
124 pub fn len(&self) -> usize {
125 // Account for usize underflows
126 if self.end_col > self.start_col {
127 self.end_col - self.start_col
129 self.start_col - self.end_col
133 pub fn has_label(&self) -> bool {
134 if let Some(ref label) = self.label {
135 // Consider labels with no text as effectively not being there
136 // to avoid weird output with unnecessary vertical lines, like:
138 // X | fn foo(x: u32) {
144 // Note that this would be the complete output users would see.
151 pub fn takes_space(&self) -> bool {
152 // Multiline annotations always have to keep vertical space.
154 self.annotation_type,
155 AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_)
161 pub struct StyledString {
166 #[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]