Skip to content

Commit eb53ca3

Browse files
committed
Show multiline spans in full if short enough
When dealing with multiline spans that span few lines, show the complete span instead of restricting to the first character of the first line. For example, instead of: ``` % ./rustc foo.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> foo.rs:13:9 | 13 | foo(1 + bar(x, | ^ trait `{integer}: std::ops::Add<()>` not satisfied | ``` show ``` % ./rustc foo.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> foo.rs:13:9 | 13 | foo(1 + bar(x, | ________^ starting here... 14 | | y), | |_____________^ ...ending here: trait `{integer}: std::ops::Add<()>` not satisfied | ```
1 parent fb12219 commit eb53ca3

15 files changed

+1081
-144
lines changed

src/librustc_errors/emitter.rs

+379-105
Large diffs are not rendered by default.

src/librustc_errors/snippet.rs

+100-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,57 @@ pub struct Line {
4141
pub annotations: Vec<Annotation>,
4242
}
4343

44+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
45+
pub enum AnnotationType {
46+
/// Annotation under a single line of code
47+
Singleline,
48+
49+
/// Annotation under the first character of a multiline span
50+
Minimized,
51+
52+
/// Annotation enclosing the first and last character of a multiline span
53+
Multiline {
54+
depth: usize,
55+
line_start: usize,
56+
line_end: usize,
57+
},
58+
59+
// The Multiline type above is replaced with the following three in order
60+
// to reuse the current label drawing code.
61+
//
62+
// Each of these corresponds to one part of the following diagram:
63+
//
64+
// x | foo(1 + bar(x,
65+
// | _________^ starting here... < MultilineStart
66+
// x | | y), < MultilineLine
67+
// | |______________^ ...ending here: label < MultilineEnd
68+
// x | z);
69+
/// Annotation marking the first character of a fully shown multiline span
70+
MultilineStart(usize),
71+
/// Annotation marking the last character of a fully shown multiline span
72+
MultilineEnd(usize),
73+
/// Line at the left enclosing the lines of a fully shown multiline span
74+
MultilineLine(usize),
75+
}
76+
77+
impl AnnotationType {
78+
pub fn depth(&self) -> usize {
79+
match self {
80+
&AnnotationType::Multiline {depth, ..} |
81+
&AnnotationType::MultilineStart(depth) |
82+
&AnnotationType::MultilineLine(depth) |
83+
&AnnotationType::MultilineEnd(depth) => depth,
84+
_ => 0,
85+
}
86+
}
87+
88+
pub fn increase_depth(&mut self) {
89+
if let AnnotationType::Multiline {ref mut depth, ..} = *self {
90+
*depth += 1;
91+
}
92+
}
93+
}
94+
4495
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
4596
pub struct Annotation {
4697
/// Start column, 0-based indexing -- counting *characters*, not
@@ -55,11 +106,57 @@ pub struct Annotation {
55106
/// Is this annotation derived from primary span
56107
pub is_primary: bool,
57108

58-
/// Is this a large span minimized down to a smaller span
59-
pub is_minimized: bool,
60-
61109
/// Optional label to display adjacent to the annotation.
62110
pub label: Option<String>,
111+
112+
/// Is this a single line, multiline or multiline span minimized down to a
113+
/// smaller span.
114+
pub annotation_type: AnnotationType,
115+
}
116+
117+
impl Annotation {
118+
pub fn is_minimized(&self) -> bool {
119+
match self.annotation_type {
120+
AnnotationType::Minimized => true,
121+
_ => false,
122+
}
123+
}
124+
125+
pub fn is_multiline(&self) -> bool {
126+
match self.annotation_type {
127+
AnnotationType::Multiline {..} |
128+
AnnotationType::MultilineStart(_) |
129+
AnnotationType::MultilineLine(_) |
130+
AnnotationType::MultilineEnd(_) => true,
131+
_ => false,
132+
}
133+
}
134+
135+
pub fn as_start(&self) -> Annotation {
136+
let mut a = self.clone();
137+
a.annotation_type = AnnotationType::MultilineStart(self.annotation_type.depth());
138+
a.end_col = a.start_col + 1;
139+
a.label = Some("starting here...".to_owned());
140+
a
141+
}
142+
143+
pub fn as_end(&self) -> Annotation {
144+
let mut a = self.clone();
145+
a.annotation_type = AnnotationType::MultilineEnd(self.annotation_type.depth());
146+
a.start_col = a.end_col - 1;
147+
a.label = match a.label {
148+
Some(l) => Some(format!("...ending here: {}", l)),
149+
None => Some("..ending here".to_owned()),
150+
};
151+
a
152+
}
153+
154+
pub fn as_line(&self) -> Annotation {
155+
let mut a = self.clone();
156+
a.annotation_type = AnnotationType::MultilineLine(self.annotation_type.depth());
157+
a.label = None;
158+
a
159+
}
63160
}
64161

65162
#[derive(Debug)]

src/libsyntax/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,7 @@ pub mod ext {
144144
}
145145
}
146146

147+
#[cfg(test)]
148+
mod test_snippet;
149+
147150
// __build_diagnostic_array! { libsyntax, DIAGNOSTICS }

0 commit comments

Comments
 (0)