about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-03-12 13:06:43 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-04-02 16:14:58 +0200
commit96404ee8443c7475b3b6a7b9beb142e7e9354673 (patch)
treee58feead43d306e1230bd104a7ac9f517acf6a97
parentf694222887cf31f51e68927716c25736e62f037f (diff)
downloadrust-96404ee8443c7475b3b6a7b9beb142e7e9354673.tar.gz
rust-96404ee8443c7475b3b6a7b9beb142e7e9354673.zip
Emit ansi color codes in the `rendered` field of json diagnostics
-rw-r--r--src/librustc/session/config.rs35
-rw-r--r--src/librustc/session/mod.rs21
-rw-r--r--src/librustc_errors/emitter.rs28
-rw-r--r--src/libsyntax/json.rs29
-rw-r--r--src/test/ui/lint/use_suggestion_json.rs2
-rw-r--r--src/test/ui/lint/use_suggestion_json.stderr88
6 files changed, 123 insertions, 80 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 988e4a9ff23..7dcccdb74b4 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -205,7 +205,12 @@ impl OutputType {
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum ErrorOutputType {
     HumanReadable(ColorConfig),
-    Json(bool),
+    Json {
+        /// Render the json in a human readable way (with indents and newlines)
+        pretty: bool,
+        /// The `rendered` field with the command line diagnostics include color codes
+        colorful_rendered: bool,
+    },
     Short(ColorConfig),
 }
 
@@ -1345,6 +1350,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "print some statistics about AST and HIR"),
     always_encode_mir: bool = (false, parse_bool, [TRACKED],
         "encode MIR of all functions into the crate metadata"),
+    colorful_json: bool = (false, parse_bool, [UNTRACKED],
+        "encode color codes in the `rendered` field of json diagnostics"),
     unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED],
         "take the breaks off const evaluation. NOTE: this is unsound"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
@@ -1798,6 +1805,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "How errors and other messages are produced",
             "human|json|short",
         ),
+        opt::opt(
+            "",
+            "colorful-json",
+            "Emit ansi color codes to the `rendered` field of json diagnostics",
+            "TYPE",
+        ),
         opt::opt_s(
             "",
             "color",
@@ -1938,6 +1951,7 @@ pub fn build_session_options_and_crate_config(
         )
     }
 
+    let colorful_rendered = matches.opt_present("colorful-json");
 
     // We need the opts_present check because the driver will send us Matches
     // with only stable options if no unstable options are used. Since error-format
@@ -1946,8 +1960,8 @@ pub fn build_session_options_and_crate_config(
     let error_format = if matches.opts_present(&["error-format".to_owned()]) {
         match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
             Some("human") => ErrorOutputType::HumanReadable(color),
-            Some("json") => ErrorOutputType::Json(false),
-            Some("pretty-json") => ErrorOutputType::Json(true),
+            Some("json") => ErrorOutputType::Json { pretty: false, colorful_rendered },
+            Some("pretty-json") => ErrorOutputType::Json { pretty: true, colorful_rendered },
             Some("short") => ErrorOutputType::Short(color),
             None => ErrorOutputType::HumanReadable(color),
 
@@ -1973,11 +1987,16 @@ pub fn build_session_options_and_crate_config(
 
     let mut debugging_opts = build_debugging_options(matches, error_format);
 
-    if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
-        early_error(
-            ErrorOutputType::Json(false),
-            "--error-format=pretty-json is unstable",
-        );
+    if !debugging_opts.unstable_options {
+        if colorful_rendered {
+            early_error(error_format, "--colorful-json=true is unstable");
+        }
+        if let ErrorOutputType::Json { pretty: true, .. } = error_format {
+            early_error(
+                ErrorOutputType::Json { pretty: false, colorful_rendered: false },
+                "--error-format=pretty-json is unstable",
+            );
+        }
     }
 
     if debugging_opts.pgo_gen.is_some() && !debugging_opts.pgo_use.is_empty() {
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 2f3df32945c..88eee1cd306 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -1046,29 +1046,34 @@ fn default_emitter(
             ).ui_testing(sopts.debugging_opts.ui_testing),
         ),
         (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
-            EmitterWriter::new(dst, Some(source_map.clone()), false, false)
-                .ui_testing(sopts.debugging_opts.ui_testing),
+            EmitterWriter::new(
+                dst, Some(source_map.clone()), false, false, sopts.debugging_opts.colorful_json,
+            ).ui_testing(sopts.debugging_opts.ui_testing),
         ),
-        (config::ErrorOutputType::Json(pretty), None) => Box::new(
+        (config::ErrorOutputType::Json { pretty, colorful_rendered }, None) => Box::new(
             JsonEmitter::stderr(
                 Some(registry),
                 source_map.clone(),
                 pretty,
+                colorful_rendered,
             ).ui_testing(sopts.debugging_opts.ui_testing),
         ),
-        (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
+        (config::ErrorOutputType::Json { pretty, colorful_rendered }, Some(dst)) => Box::new(
             JsonEmitter::new(
                 dst,
                 Some(registry),
                 source_map.clone(),
                 pretty,
+                colorful_rendered,
             ).ui_testing(sopts.debugging_opts.ui_testing),
         ),
         (config::ErrorOutputType::Short(color_config), None) => Box::new(
             EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false),
         ),
         (config::ErrorOutputType::Short(_), Some(dst)) => {
-            Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false))
+            Box::new(EmitterWriter::new(
+                dst, Some(source_map.clone()), true, false, sopts.debugging_opts.colorful_json,
+            ))
         }
     }
 }
@@ -1317,7 +1322,8 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
-        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
+        config::ErrorOutputType::Json { pretty, colorful_rendered } =>
+            Box::new(JsonEmitter::basic(pretty, colorful_rendered)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true, false))
         }
@@ -1332,7 +1338,8 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
-        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
+        config::ErrorOutputType::Json { pretty, colorful_rendered } =>
+            Box::new(JsonEmitter::basic(pretty, colorful_rendered)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true, false))
         }
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index ee2a1b69cbd..0790f9bc761 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -16,7 +16,7 @@ use std::borrow::Cow;
 use std::io::prelude::*;
 use std::io;
 use std::cmp::{min, Reverse};
-use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter};
+use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi};
 use termcolor::{WriteColor, Color, Buffer};
 
 const ANONYMIZED_LINE_NUM: &str = "LL";
@@ -152,13 +152,15 @@ impl EmitterWriter {
         }
     }
 
-    pub fn new(dst: Box<dyn Write + Send>,
-               source_map: Option<Lrc<SourceMapperDyn>>,
-               short_message: bool,
-               teach: bool)
-               -> EmitterWriter {
+    pub fn new(
+        dst: Box<dyn Write + Send>,
+        source_map: Option<Lrc<SourceMapperDyn>>,
+        short_message: bool,
+        teach: bool,
+        colored: bool,
+    ) -> EmitterWriter {
         EmitterWriter {
-            dst: Raw(dst),
+            dst: Raw(dst, colored),
             sm: source_map,
             short_message,
             teach,
@@ -1538,13 +1540,14 @@ fn emit_to_destination(rendered_buffer: &[Vec<StyledString>],
 pub enum Destination {
     Terminal(StandardStream),
     Buffered(BufferWriter),
-    Raw(Box<dyn Write + Send>),
+    Raw(Box<(dyn Write + Send)>, bool),
 }
 
 pub enum WritableDst<'a> {
     Terminal(&'a mut StandardStream),
     Buffered(&'a mut BufferWriter, Buffer),
-    Raw(&'a mut Box<dyn Write + Send>),
+    Raw(&'a mut (dyn Write + Send)),
+    ColoredRaw(Ansi<&'a mut (dyn Write + Send)>),
 }
 
 impl Destination {
@@ -1570,7 +1573,8 @@ impl Destination {
                 let buf = t.buffer();
                 WritableDst::Buffered(t, buf)
             }
-            Destination::Raw(ref mut t) => WritableDst::Raw(t),
+            Destination::Raw(ref mut t, false) => WritableDst::Raw(t),
+            Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)),
         }
     }
 }
@@ -1628,6 +1632,7 @@ impl<'a> WritableDst<'a> {
         match *self {
             WritableDst::Terminal(ref mut t) => t.set_color(color),
             WritableDst::Buffered(_, ref mut t) => t.set_color(color),
+            WritableDst::ColoredRaw(ref mut t) => t.set_color(color),
             WritableDst::Raw(_) => Ok(())
         }
     }
@@ -1636,6 +1641,7 @@ impl<'a> WritableDst<'a> {
         match *self {
             WritableDst::Terminal(ref mut t) => t.reset(),
             WritableDst::Buffered(_, ref mut t) => t.reset(),
+            WritableDst::ColoredRaw(ref mut t) => t.reset(),
             WritableDst::Raw(_) => Ok(()),
         }
     }
@@ -1647,6 +1653,7 @@ impl<'a> Write for WritableDst<'a> {
             WritableDst::Terminal(ref mut t) => t.write(bytes),
             WritableDst::Buffered(_, ref mut buf) => buf.write(bytes),
             WritableDst::Raw(ref mut w) => w.write(bytes),
+            WritableDst::ColoredRaw(ref mut t) => t.write(bytes),
         }
     }
 
@@ -1655,6 +1662,7 @@ impl<'a> Write for WritableDst<'a> {
             WritableDst::Terminal(ref mut t) => t.flush(),
             WritableDst::Buffered(_, ref mut buf) => buf.flush(),
             WritableDst::Raw(ref mut w) => w.flush(),
+            WritableDst::ColoredRaw(ref mut w) => w.flush(),
         }
     }
 }
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 9acd0d099a0..55005a821b2 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -30,37 +30,46 @@ pub struct JsonEmitter {
     sm: Lrc<dyn SourceMapper + sync::Send + sync::Sync>,
     pretty: bool,
     ui_testing: bool,
+    colorful_rendered: bool,
 }
 
 impl JsonEmitter {
-    pub fn stderr(registry: Option<Registry>,
-                  source_map: Lrc<SourceMap>,
-                  pretty: bool) -> JsonEmitter {
+    pub fn stderr(
+        registry: Option<Registry>,
+        source_map: Lrc<SourceMap>,
+        pretty: bool,
+        colorful_rendered: bool,
+    ) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
             registry,
             sm: source_map,
             pretty,
             ui_testing: false,
+            colorful_rendered,
         }
     }
 
-    pub fn basic(pretty: bool) -> JsonEmitter {
+    pub fn basic(pretty: bool, colorful_rendered: bool) -> JsonEmitter {
         let file_path_mapping = FilePathMapping::empty();
         JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)),
-                            pretty)
+                            pretty, colorful_rendered)
     }
 
-    pub fn new(dst: Box<dyn Write + Send>,
-               registry: Option<Registry>,
-               source_map: Lrc<SourceMap>,
-               pretty: bool) -> JsonEmitter {
+    pub fn new(
+        dst: Box<dyn Write + Send>,
+        registry: Option<Registry>,
+        source_map: Lrc<SourceMap>,
+        pretty: bool,
+        colorful_rendered: bool,
+    ) -> JsonEmitter {
         JsonEmitter {
             dst,
             registry,
             sm: source_map,
             pretty,
             ui_testing: false,
+            colorful_rendered,
         }
     }
 
@@ -190,7 +199,7 @@ impl Diagnostic {
         }
         let buf = BufWriter::default();
         let output = buf.clone();
-        EmitterWriter::new(Box::new(buf), Some(je.sm.clone()), false, false)
+        EmitterWriter::new(Box::new(buf), Some(je.sm.clone()), false, false, je.colorful_rendered)
             .ui_testing(je.ui_testing).emit(db);
         let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
         let output = String::from_utf8(output).unwrap();
diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs
index 3bdbaa55f2d..9cf3d0fa403 100644
--- a/src/test/ui/lint/use_suggestion_json.rs
+++ b/src/test/ui/lint/use_suggestion_json.rs
@@ -1,5 +1,5 @@
 // ignore-cloudabi
-// compile-flags: --error-format pretty-json -Zunstable-options
+// compile-flags: --error-format pretty-json -Zunstable-options --colorful-json=true
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index dee7f2f9b16..789bb5ea72f 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -73,8 +73,8 @@ mod foo {
   "spans": [
     {
       "file_name": "$DIR/use_suggestion_json.rs",
-      "byte_start": 440,
-      "byte_end": 444,
+      "byte_start": 461,
+      "byte_end": 465,
       "line_start": 11,
       "line_end": 11,
       "column_start": 12,
@@ -101,8 +101,8 @@ mod foo {
       "spans": [
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -124,8 +124,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -147,8 +147,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -170,8 +170,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -193,8 +193,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -216,8 +216,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -239,8 +239,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -262,8 +262,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -285,8 +285,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -308,8 +308,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -331,8 +331,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -354,8 +354,8 @@ mod foo {
         },
         {
           "file_name": "$DIR/use_suggestion_json.rs",
-          "byte_start": 417,
-          "byte_end": 417,
+          "byte_start": 438,
+          "byte_end": 438,
           "line_start": 10,
           "line_end": 10,
           "column_start": 1,
@@ -380,22 +380,22 @@ mod foo {
       "rendered": null
     }
   ],
-  "rendered": "error[E0412]: cannot find type `Iter` in this scope
-  --> $DIR/use_suggestion_json.rs:11:12
-   |
-LL |     let x: Iter;
-   |            ^^^^ not found in this scope
-help: possible candidates are found in other modules, you can import them into scope
-   |
-LL | use std::collections::binary_heap::Iter;
-   |
-LL | use std::collections::btree_map::Iter;
-   |
-LL | use std::collections::btree_set::Iter;
-   |
-LL | use std::collections::hash_map::Iter;
-   |
-and 8 other candidates
+  "rendered": "/u001b[0m/u001b[1m/u001b[38;5;9merror[E0412]/u001b[0m/u001b[0m/u001b[1m: cannot find type `Iter` in this scope/u001b[0m
+/u001b[0m  /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m--> /u001b[0m/u001b[0m$DIR/use_suggestion_json.rs:11:12/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;12mLL/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0m    let x: Iter;/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0m           /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;9m^^^^/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;9mnot found in this scope/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;14mhelp/u001b[0m/u001b[0m: possible candidates are found in other modules, you can import them into scope/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;12mLL/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0muse std::collections::binary_heap::Iter;/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;12mLL/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0muse std::collections::btree_map::Iter;/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;12mLL/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0muse std::collections::btree_set::Iter;/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0m/u001b[1m/u001b[38;5;12mLL/u001b[0m/u001b[0m /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m| /u001b[0m/u001b[0muse std::collections::hash_map::Iter;/u001b[0m
+/u001b[0m   /u001b[0m/u001b[0m/u001b[1m/u001b[38;5;12m|/u001b[0m
+/u001b[0mand 8 other candidates/u001b[0m
 
 "
 }
@@ -405,7 +405,7 @@ and 8 other candidates
   "level": "error",
   "spans": [],
   "children": [],
-  "rendered": "error: aborting due to previous error
+  "rendered": "/u001b[0m/u001b[1m/u001b[38;5;9merror/u001b[0m/u001b[0m/u001b[1m: aborting due to previous error/u001b[0m
 
 "
 }
@@ -415,6 +415,6 @@ and 8 other candidates
   "level": "",
   "spans": [],
   "children": [],
-  "rendered": "For more information about this error, try `rustc --explain E0412`.
+  "rendered": "/u001b[0m/u001b[1mFor more information about this error, try `rustc --explain E0412`./u001b[0m
 "
 }