Skip to content

Commit 5616b92

Browse files
committedJan 12, 2015
Implement multi-line errors
1 parent 24ace16 commit 5616b92

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed
 

‎src/compiletest/runtest.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,16 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
966966
line.starts_with( prefix )
967967
}
968968

969+
// A multi-line error will have followup lines which will always
970+
// start with one of these strings.
971+
fn continuation( line: &str) -> bool {
972+
line.starts_with(" expected") ||
973+
line.starts_with(" found") ||
974+
// 1234
975+
// Should have 4 spaces: see issue 18946
976+
line.starts_with("(")
977+
}
978+
969979
// Scan and extract our error/warning messages,
970980
// which look like:
971981
// filename:line1:col1: line2:col2: *error:* msg
@@ -981,7 +991,7 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
981991
ee.kind,
982992
ee.msg,
983993
line);
984-
if prefix_matches(line, prefixes[i].as_slice()) &&
994+
if (prefix_matches(line, prefixes[i].as_slice()) || continuation(line)) &&
985995
line.contains(ee.kind.as_slice()) &&
986996
line.contains(ee.msg.as_slice()) {
987997
found_flags[i] = true;

‎src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern crate flate;
3535
extern crate getopts;
3636
extern crate graphviz;
3737
extern crate libc;
38+
extern crate regex;
3839
extern crate rustc_llvm;
3940
extern crate rustc_back;
4041
extern crate serialize;

‎src/librustc/session/mod.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use metadata::filesearch;
1515
use session::search_paths::PathKind;
1616
use util::nodemap::NodeMap;
1717

18+
use regex::Regex;
19+
1820
use syntax::ast::NodeId;
1921
use syntax::codemap::Span;
2022
use syntax::diagnostic::{self, Emitter};
@@ -71,7 +73,58 @@ impl Session {
7173
self.diagnostic().handler().fatal(msg)
7274
}
7375
pub fn span_err(&self, sp: Span, msg: &str) {
74-
self.diagnostic().span_err(sp, msg)
76+
// Conditions for enabling multi-line errors:
77+
if !msg.contains("mismatched types") &&
78+
!msg.contains("type mismatch resolving") &&
79+
!msg.contains("if and else have incompatible types") &&
80+
!msg.contains("if may be missing an else clause") &&
81+
!msg.contains("match arms have incompatible types") &&
82+
!msg.contains("structure constructor specifies a structure of type") {
83+
return self.diagnostic().span_err(sp, msg);
84+
}
85+
86+
let first = Regex::new(r"[( ]expected").unwrap();
87+
let second = Regex::new(r" found").unwrap();
88+
let third = Regex::new(
89+
r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
90+
91+
let mut new_msg = String::new();
92+
let mut head = 0u;
93+
94+
// Insert `\n` before expected and found.
95+
for (pos1, pos2) in first.find_iter(msg).zip(
96+
second.find_iter(msg)) {
97+
new_msg = new_msg +
98+
// A `(` may be preceded by a space and it should be trimmed
99+
msg[head..pos1.0].trim_right() + // prefix
100+
"\n" + // insert before first
101+
&msg[pos1.0..pos1.1] + // insert what first matched
102+
&msg[pos1.1..pos2.0] + // between matches
103+
"\n " + // insert before second
104+
// 123
105+
// `expected` is 3 char longer than `found`. To align the types, `found` gets
106+
// 3 spaces prepended.
107+
&msg[pos2.0..pos2.1]; // insert what second matched
108+
109+
head = pos2.1;
110+
}
111+
112+
let mut tail = &msg[head..];
113+
// Insert `\n` before any remaining messages which match.
114+
for pos in third.find_iter(tail).take(1) {
115+
// The end of the message may just be wrapped in `()` without `expected`/`found`.
116+
// Push this also to a new line and add the final tail after.
117+
new_msg = new_msg +
118+
// `(` is usually preceded by a space and should be trimmed.
119+
tail[..pos.0].trim_right() + // prefix
120+
"\n" + // insert before paren
121+
&tail[pos.0..]; // append the tail
122+
123+
tail = "";
124+
}
125+
126+
new_msg.push_str(tail);
127+
self.diagnostic().span_err(sp, &new_msg[])
75128
}
76129
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
77130
self.diagnostic().span_err_with_code(sp, msg, code)

0 commit comments

Comments
 (0)
Please sign in to comment.