]> git.lizzy.rs Git - rust.git/commitdiff
Make multiline errors work with codes
authorBrian Anderson <banderson@mozilla.com>
Tue, 20 Jan 2015 22:18:35 +0000 (14:18 -0800)
committerBrian Anderson <banderson@mozilla.com>
Tue, 20 Jan 2015 22:18:35 +0000 (14:18 -0800)
src/librustc/session/mod.rs

index 0392fbfdeaecca8f95a7373f9b4b2329f7458a66..4150335abc3d3080ddbc4a7dc3c2c239c1acd787 100644 (file)
@@ -76,61 +76,16 @@ pub fn fatal(&self, msg: &str) -> ! {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        // Conditions for enabling multi-line errors:
-        if !msg.contains("mismatched types") &&
-           !msg.contains("type mismatch resolving") &&
-           !msg.contains("if and else have incompatible types") &&
-           !msg.contains("if may be missing an else clause") &&
-           !msg.contains("match arms have incompatible types") &&
-           !msg.contains("structure constructor specifies a structure of type") {
-            return self.diagnostic().span_err(sp, msg);
+        match split_msg_into_multilines(msg) {
+            Some(msg) => self.diagnostic().span_err(sp, &msg[]),
+            None => self.diagnostic().span_err(sp, msg)
         }
-
-        let first  = Regex::new(r"[( ]expected").unwrap();
-        let second = Regex::new(r" found").unwrap();
-        let third  = Regex::new(
-                     r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
-
-        let mut new_msg = String::new();
-        let mut head = 0u;
-
-        // Insert `\n` before expected and found.
-        for (pos1, pos2) in first.find_iter(msg).zip(
-                            second.find_iter(msg)) {
-            new_msg = new_msg +
-            // A `(` may be preceded by a space and it should be trimmed
-                      msg[head..pos1.0].trim_right() + // prefix
-                      "\n" +                           // insert before first
-                      &msg[pos1.0..pos1.1] +           // insert what first matched
-                      &msg[pos1.1..pos2.0] +           // between matches
-                      "\n   " +                        // insert before second
-            //           123
-            // `expected` is 3 char longer than `found`. To align the types, `found` gets
-            // 3 spaces prepended.
-                      &msg[pos2.0..pos2.1];            // insert what second matched
-
-            head = pos2.1;
-        }
-
-        let mut tail = &msg[head..];
-        // Insert `\n` before any remaining messages which match.
-        for pos in third.find_iter(tail).take(1) {
-            // The end of the message may just be wrapped in `()` without `expected`/`found`.
-            // Push this also to a new line and add the final tail after.
-            new_msg = new_msg +
-            // `(` is usually preceded by a space and should be trimmed.
-                      tail[..pos.0].trim_right() + // prefix
-                      "\n" +                       // insert before paren
-                      &tail[pos.0..];              // append the tail
-
-            tail = "";
-        }
-
-        new_msg.push_str(tail);
-        self.diagnostic().span_err(sp, &new_msg[])
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
-        self.diagnostic().span_err_with_code(sp, msg, code)
+        match split_msg_into_multilines(msg) {
+            Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[], code),
+            None => self.diagnostic().span_err_with_code(sp, msg, code)
+        }
     }
     pub fn err(&self, msg: &str) {
         self.diagnostic().handler().err(msg)
@@ -288,6 +243,62 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
     }
 }
 
+fn split_msg_into_multilines(msg: &str) -> Option<String> {
+    // Conditions for enabling multi-line errors:
+    if !msg.contains("mismatched types") &&
+        !msg.contains("type mismatch resolving") &&
+        !msg.contains("if and else have incompatible types") &&
+        !msg.contains("if may be missing an else clause") &&
+        !msg.contains("match arms have incompatible types") &&
+        !msg.contains("structure constructor specifies a structure of type") {
+            return None
+    }
+
+    let first  = Regex::new(r"[( ]expected").unwrap();
+    let second = Regex::new(r" found").unwrap();
+    let third  = Regex::new(
+        r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
+
+    let mut new_msg = String::new();
+    let mut head = 0u;
+
+    // Insert `\n` before expected and found.
+    for (pos1, pos2) in first.find_iter(msg).zip(
+        second.find_iter(msg)) {
+        new_msg = new_msg +
+            // A `(` may be preceded by a space and it should be trimmed
+            msg[head..pos1.0].trim_right() + // prefix
+            "\n" +                           // insert before first
+            &msg[pos1.0..pos1.1] +           // insert what first matched
+            &msg[pos1.1..pos2.0] +           // between matches
+            "\n   " +                        // insert before second
+            //           123
+            // `expected` is 3 char longer than `found`. To align the types, `found` gets
+            // 3 spaces prepended.
+            &msg[pos2.0..pos2.1];            // insert what second matched
+
+        head = pos2.1;
+    }
+
+    let mut tail = &msg[head..];
+    // Insert `\n` before any remaining messages which match.
+    for pos in third.find_iter(tail).take(1) {
+        // The end of the message may just be wrapped in `()` without `expected`/`found`.
+        // Push this also to a new line and add the final tail after.
+        new_msg = new_msg +
+            // `(` is usually preceded by a space and should be trimmed.
+            tail[..pos.0].trim_right() + // prefix
+            "\n" +                       // insert before paren
+            &tail[pos.0..];              // append the tail
+
+        tail = "";
+    }
+
+    new_msg.push_str(tail);
+
+    return Some(new_msg)
+}
+
 pub fn build_session(sopts: config::Options,
                      local_crate_source_file: Option<Path>,
                      registry: diagnostics::registry::Registry)