-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Teach diagnostics to correct margin of multiline messages #38916
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
db5ec8b
to
7f7a0dc
Compare
Make the suggestion list have a correct padding: ``` error[E0308]: mismatched types --> file.rs:3:20 | 3 | let x: usize = ""; | ^^ expected usize, found reference | = note: expected type `usize` = note: found type `&'static str` = help: here are some functions which might fulfill your needs: - .len() - .foo() - .bar() ```
7f7a0dc
to
43b10fa
Compare
format!("{}\n{}", | ||
&child.message, | ||
&child.list.iter().map(|item| { | ||
format!("{} - {}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is hard for to understand the inner loop.
Can you describe it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comments.
.collect::<String>(), | ||
item) | ||
}).collect::<Vec<String>>() | ||
.join("\n")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that collect
and join
are more efficient than fold
?
EDIT:
I think that it is more efficient.
@@ -699,6 +699,7 @@ impl EmitterWriter { | |||
.to_string(), | |||
span: MultiSpan::new(), | |||
render_span: None, | |||
list: vec![], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nikomatsakis,
Is vec![]
idiomatic way to create an empty vector?
I mean that vec!
is a macro.
It requires expansion.
I think that Vec::new
is more appropriate.
@@ -191,11 +197,23 @@ impl Diagnostic { | |||
message: &str, | |||
span: MultiSpan, | |||
render_span: Option<RenderSpan>) { | |||
self.sub_with_list(level, message, span, render_span, vec![]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nikomatsakis,
Is vec![]
idiomatic way to create an empty vector?
I mean that vec!
is a macro.
It requires expansion.
I think that Vec::new
is more appropriate.
3d4a19d
to
a54d700
Compare
a934320
to
ba7503c
Compare
I realized that this could be generalized in a better way by making the diagnostic renderer aware of multiline strings, and make it provide the appropriate margin instead. By doing it that way
|
fn msg_with_padding(&self, msg: &str, padding: usize) -> String { | ||
let padding = (0..padding) | ||
.map(|_| " ") | ||
.collect::<String>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I get it right, it will allocate every time the method is called.
What do you think about adding a function
fn add_padding(msg: &mut String, padding: usize) {
for _ in 0..padding {
msg.push(' ');
}
}
and using it instead of pushing padding.
} | ||
acc.push_str(&x.1); | ||
acc.push_str("\n"); | ||
acc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need other opinions, but I think that before 711 lines you call measure a new string size and reserve it to prevent allocations in 713, 715, 716 lines.
@@ -721,7 +736,10 @@ impl EmitterWriter { | |||
draw_note_separator(&mut buffer, 0, max_line_num_len + 1); | |||
buffer.append(0, &level.to_string(), Style::HeaderMsg); | |||
buffer.append(0, ": ", Style::NoStyle); | |||
buffer.append(0, msg, Style::NoStyle); | |||
|
|||
// The extra 9 ` ` is the padding that's always needed to align to the `note: `. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about "note".len() + 5
(and "suggestion".len() + 5
further down) to have one magic number instead of two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Make any diagnostic line to have the correct margin to align with the first line: ``` error: message --> file.rs:3:20 | 3 | <CODE> | ^^^^ | = note: this is a multiline note with a correct margin = note: this is a single line note = help: here are some functions which might fulfill your needs: - .len() - .foo() - .bar() = suggestion: this is a multiline suggestion with a correct margin ```
ba7503c
to
b206064
Compare
buffer.append(0, msg, Style::NoStyle); | ||
|
||
// The extra 3 ` ` is the padding that's always needed to align to the `note: `. | ||
let message = self.msg_with_padding(msg, max_line_num_len + "note: ".len() + 3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does 3
stand for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error: message
--> file.rs:3:20
|
3 | <CODE>
| ^^^^
|
= note: multiline
message
+^^^------
| | |
| | length of "note: "
| the magic `3`
`max_line_num_len`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e424c0e
to
04e4a60
Compare
@bors r+ This is very nice. |
📌 Commit 04e4a60 has been approved by |
@@ -703,6 +703,40 @@ impl EmitterWriter { | |||
} | |||
} | |||
|
|||
/// Add a left margin to every line but the first, given a padding length and the label being | |||
/// displayed. | |||
fn msg_with_padding(&self, msg: &str, padding: usize, label: &str) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the labels attached to a span might also need wrapping, not just notes, right?
But I guess this code is not about "autowrap" but specifically targeting \n
that are embedded in a message. I see, carry on.
Teach diagnostics to correct margin of multiline messages Make the suggestion list have a correct padding: ``` error[E0308]: mismatched types --> file.rs:3:20 | 3 | let x: usize = ""; | ^^ expected usize, found reference | = note: expected type `usize` = note: found type `&'static str` = help: here are some functions which might fulfill your needs: - .len() - .foo() - .bar() ```
☀️ Test successful - status-appveyor, status-travis |
Make the suggestion list have a correct padding: