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 // The Multiline type above is replaced with the following three in order
73 // to reuse the current label drawing code.
75 // Each of these corresponds to one part of the following diagram:
78 // | _________^ < MultilineStart
79 // x | | y), < MultilineLine
80 // | |______________^ label < MultilineEnd
82 /// Annotation marking the first character of a fully shown multiline span
83 MultilineStart(usize),
84 /// Annotation marking the last character of a fully shown multiline span
86 /// Line at the left enclosing the lines of a fully shown multiline span
87 // Just a placeholder for the drawing algorithm, to know that it shouldn't skip the first 4
88 // and last 2 lines of code. The actual line is drawn in `emit_message_default` and not in
89 // `draw_multiline_line`.
93 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
94 pub struct Annotation {
95 /// Start column, 0-based indexing -- counting *characters*, not
96 /// utf-8 bytes. Note that it is important that this field goes
97 /// first, so that when we sort, we sort orderings by start
101 /// End column within the line (exclusive)
104 /// Is this annotation derived from primary span
105 pub is_primary: bool,
107 /// Optional label to display adjacent to the annotation.
108 pub label: Option<String>,
110 /// Is this a single line, multiline or multiline span minimized down to a
112 pub annotation_type: AnnotationType,
116 /// Whether this annotation is a vertical line placeholder.
117 pub fn is_line(&self) -> bool {
118 matches!(self.annotation_type, AnnotationType::MultilineLine(_))
121 pub fn len(&self) -> usize {
122 // Account for usize underflows
123 if self.end_col > self.start_col {
124 self.end_col - self.start_col
126 self.start_col - self.end_col
130 pub fn has_label(&self) -> bool {
131 if let Some(ref label) = self.label {
132 // Consider labels with no text as effectively not being there
133 // to avoid weird output with unnecessary vertical lines, like:
135 // X | fn foo(x: u32) {
141 // Note that this would be the complete output users would see.
148 pub fn takes_space(&self) -> bool {
149 // Multiline annotations always have to keep vertical space.
151 self.annotation_type,
152 AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_)
158 pub struct StyledString {
163 #[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]