diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d3a734cbc6e..dc1ceaf69f0 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -19,6 +19,7 @@ use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; use syntax::feature_gate::UnstableFeatures; +use errors::emitter::HumanReadableErrorType; use errors::{ColorConfig, FatalError, Handler}; @@ -219,14 +220,18 @@ impl OutputType { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ErrorOutputType { - HumanReadable(ColorConfig), - Json(bool), - Short(ColorConfig), + HumanReadable(HumanReadableErrorType), + Json { + /// Render the json in a human readable way (with indents and newlines) + pretty: bool, + /// The way the `rendered` field is created + json_rendered: HumanReadableErrorType, + }, } impl Default for ErrorOutputType { fn default() -> ErrorOutputType { - ErrorOutputType::HumanReadable(ColorConfig::Auto) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) } } @@ -1372,6 +1377,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"), + json_rendered: Option = (None, parse_opt_string, [UNTRACKED], + "describes how to render 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], @@ -1825,6 +1832,12 @@ pub fn rustc_optgroups() -> Vec { "How errors and other messages are produced", "human|json|short", ), + opt::opt( + "", + "json-rendered", + "Choose `rendered` field of json diagnostics render scheme", + "plain|termcolor", + ), opt::opt_s( "", "color", @@ -1965,6 +1978,17 @@ pub fn build_session_options_and_crate_config( ) } + let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() { + "plain" => None, + "termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)), + _ => early_error( + ErrorOutputType::default(), + &format!( + "argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)", + s, + ), + ), + }).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never)); // 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 @@ -1972,14 +1996,14 @@ pub fn build_session_options_and_crate_config( // opt_present because the latter will panic. 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("short") => ErrorOutputType::Short(color), - None => ErrorOutputType::HumanReadable(color), + None | + Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), + Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, + Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, + Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), Some(arg) => early_error( - ErrorOutputType::HumanReadable(color), + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), &format!( "argument for --error-format must be `human`, `json` or \ `short` (instead was `{}`)", @@ -1988,7 +2012,7 @@ pub fn build_session_options_and_crate_config( ), } } else { - ErrorOutputType::HumanReadable(color) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) }; let unparsed_crate_types = matches.opt_strs("crate-type"); @@ -2000,11 +2024,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 matches.opt_str("json-rendered").is_some() { + early_error(error_format, "`--json-rendered=x` is unstable"); + } + if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { + early_error( + ErrorOutputType::Json { pretty: false, json_rendered }, + "--error-format=pretty-json is unstable", + ); + } } if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() { @@ -2928,50 +2957,55 @@ mod tests { let mut v3 = Options::default(); let mut v4 = Options::default(); + const JSON: super::ErrorOutputType = super::ErrorOutputType::Json { + pretty: false, + json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never), + }; + // Reference v1.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a1966c02683..eed516a4381 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1033,39 +1033,42 @@ fn default_emitter( emitter_dest: Option>, ) -> Box { match (sopts.error_format, emitter_dest) { - (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new( - EmitterWriter::stderr( - color_config, - Some(source_map.clone()), - false, - sopts.debugging_opts.teach, - ).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), - ), - (config::ErrorOutputType::Json(pretty), None) => Box::new( + (config::ErrorOutputType::HumanReadable(kind), dst) => { + let (short, color_config) = kind.unzip(); + let emitter = match dst { + None => EmitterWriter::stderr( + color_config, + Some(source_map.clone()), + short, + sopts.debugging_opts.teach, + ), + Some(dst) => EmitterWriter::new( + dst, + Some(source_map.clone()), + short, + false, // no teach messages when writing to a buffer + false, // no colors when writing to a buffer + ), + }; + Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) + }, + (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new( JsonEmitter::stderr( Some(registry), source_map.clone(), pretty, + json_rendered, ).ui_testing(sopts.debugging_opts.ui_testing), ), - (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new( + (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new( JsonEmitter::new( dst, Some(registry), source_map.clone(), pretty, + json_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)) - } } } @@ -1322,13 +1325,12 @@ pub enum IncrCompSession { pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let emitter: Box = match output { - 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::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true, false)) + config::ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new(EmitterWriter::stderr(color_config, None, short, false)) } + config::ErrorOutputType::Json { pretty, json_rendered } => + Box::new(JsonEmitter::basic(pretty, json_rendered)), }; let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal); @@ -1337,13 +1339,12 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let emitter: Box = match output { - 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::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true, false)) + config::ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new(EmitterWriter::stderr(color_config, None, short, false)) } + config::ErrorOutputType::Json { pretty, json_rendered } => + Box::new(JsonEmitter::basic(pretty, json_rendered)), }; let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index ee2a1b69cbd..a1472479afa 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -16,9 +16,35 @@ 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}; +/// Describes the way the content of the `rendered` field of the json output is generated +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum HumanReadableErrorType { + Default(ColorConfig), + Short(ColorConfig), +} + +impl HumanReadableErrorType { + /// Returns a (`short`, `color`) tuple + pub fn unzip(self) -> (bool, ColorConfig) { + match self { + HumanReadableErrorType::Default(cc) => (false, cc), + HumanReadableErrorType::Short(cc) => (true, cc), + } + } + pub fn new_emitter( + self, + dst: Box, + source_map: Option>, + teach: bool, + ) -> EmitterWriter { + let (short, color_config) = self.unzip(); + EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors()) + } +} + const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. @@ -104,8 +130,8 @@ pub enum ColorConfig { } impl ColorConfig { - fn to_color_choice(&self) -> ColorChoice { - match *self { + fn to_color_choice(self) -> ColorChoice { + match self { ColorConfig::Always => { if atty::is(atty::Stream::Stderr) { ColorChoice::Always @@ -120,6 +146,14 @@ impl ColorConfig { ColorConfig::Auto => ColorChoice::Never, } } + fn suggests_using_colors(self) -> bool { + match self { + | ColorConfig::Always + | ColorConfig::Auto + => true, + ColorConfig::Never => false, + } + } } pub struct EmitterWriter { @@ -152,13 +186,15 @@ impl EmitterWriter { } } - pub fn new(dst: Box, - source_map: Option>, - short_message: bool, - teach: bool) - -> EmitterWriter { + pub fn new( + dst: Box, + source_map: Option>, + short_message: bool, + teach: bool, + colored: bool, + ) -> EmitterWriter { EmitterWriter { - dst: Raw(dst), + dst: Raw(dst, colored), sm: source_map, short_message, teach, @@ -1538,13 +1574,15 @@ fn emit_to_destination(rendered_buffer: &[Vec], pub enum Destination { Terminal(StandardStream), Buffered(BufferWriter), - Raw(Box), + // The bool denotes whether we should be emitting ansi color codes or not + Raw(Box<(dyn Write + Send)>, bool), } pub enum WritableDst<'a> { Terminal(&'a mut StandardStream), Buffered(&'a mut BufferWriter, Buffer), - Raw(&'a mut Box), + Raw(&'a mut (dyn Write + Send)), + ColoredRaw(Ansi<&'a mut (dyn Write + Send)>), } impl Destination { @@ -1570,7 +1608,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 +1667,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 +1676,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 +1688,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 +1697,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/librustdoc/config.rs b/src/librustdoc/config.rs index a4d2a3be863..769ea3ff7bc 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -3,7 +3,7 @@ use std::fmt; use std::path::PathBuf; use errors; -use errors::emitter::ColorConfig; +use errors::emitter::{ColorConfig, HumanReadableErrorType}; use getopts; use rustc::lint::Level; use rustc::session::early_error; @@ -254,12 +254,19 @@ impl Options { (instead was `{}`)", arg)); } }; + // FIXME: deduplicate this code from the identical code in librustc/session/config.rs let error_format = 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("short") => ErrorOutputType::Short(color), - None => ErrorOutputType::HumanReadable(color), + None | + Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), + Some("json") => ErrorOutputType::Json { + pretty: false, + json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + }, + Some("pretty-json") => ErrorOutputType::Json { + pretty: true, + json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + }, + Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), Some(arg) => { early_error(ErrorOutputType::default(), &format!("argument for --error-format must be `human`, `json` or \ diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3cf6b32b07c..c141b474815 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -299,15 +299,18 @@ pub fn new_handler(error_format: ErrorOutputType, // stick to the defaults let sessopts = Options::default(); let emitter: Box = match error_format { - ErrorOutputType::HumanReadable(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|cm| cm as _), - false, - sessopts.debugging_opts.teach, - ).ui_testing(ui_testing) - ), - ErrorOutputType::Json(pretty) => { + ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new( + EmitterWriter::stderr( + color_config, + source_map.map(|cm| cm as _), + short, + sessopts.debugging_opts.teach, + ).ui_testing(ui_testing) + ) + }, + ErrorOutputType::Json { pretty, json_rendered } => { let source_map = source_map.unwrap_or_else( || Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()))); Box::new( @@ -315,16 +318,10 @@ pub fn new_handler(error_format: ErrorOutputType, None, source_map, pretty, + json_rendered, ).ui_testing(ui_testing) ) }, - ErrorOutputType::Short(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|cm| cm as _), - true, - false) - ), }; errors::Handler::with_emitter_and_flags( diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0bbc7c5c4b2..abf74158c93 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -381,7 +381,7 @@ pub fn make_test(s: &str, // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = EmitterWriter::new(box io::sink(), None, false, false); + let emitter = EmitterWriter::new(box io::sink(), None, false, false, false); let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, cm); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 838dfc62646..c19b408442a 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -14,7 +14,7 @@ use crate::source_map::{SourceMap, FilePathMapping}; use errors::registry::Registry; use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, SourceMapper}; use errors::{DiagnosticId, Applicability}; -use errors::emitter::{Emitter, EmitterWriter}; +use errors::emitter::{Emitter, HumanReadableErrorType}; use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; use rustc_data_structures::sync::{self, Lrc}; @@ -30,37 +30,46 @@ pub struct JsonEmitter { sm: Lrc, pretty: bool, ui_testing: bool, + json_rendered: HumanReadableErrorType, } impl JsonEmitter { - pub fn stderr(registry: Option, - source_map: Lrc, - pretty: bool) -> JsonEmitter { + pub fn stderr( + registry: Option, + source_map: Lrc, + pretty: bool, + json_rendered: HumanReadableErrorType, + ) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), registry, sm: source_map, pretty, ui_testing: false, + json_rendered, } } - pub fn basic(pretty: bool) -> JsonEmitter { + pub fn basic(pretty: bool, json_rendered: HumanReadableErrorType) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)), - pretty) + pretty, json_rendered) } - pub fn new(dst: Box, - registry: Option, - source_map: Lrc, - pretty: bool) -> JsonEmitter { + pub fn new( + dst: Box, + registry: Option, + source_map: Lrc, + pretty: bool, + json_rendered: HumanReadableErrorType, + ) -> JsonEmitter { JsonEmitter { dst, registry, sm: source_map, pretty, ui_testing: false, + json_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) + je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false) .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/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 5557e281a66..3b980fafc2f 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1920,6 +1920,7 @@ mod tests { let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, + false, false); ParseSess { span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)), diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index 86910ffd894..cba429068fd 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -57,6 +57,7 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), Some(source_map.clone()), false, + false, false); let handler = Handler::with_emitter(true, None, Box::new(emitter)); handler.span_err(msp, "foo"); diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs index 3bdbaa55f2d..9679ce4a2ae 100644 --- a/src/test/ui/lint/use_suggestion_json.rs +++ b/src/test/ui/lint/use_suggestion_json.rs @@ -1,5 +1,6 @@ // ignore-cloudabi -// compile-flags: --error-format pretty-json -Zunstable-options +// ignore-windows +// compile-flags: --error-format pretty-json -Zunstable-options --json-rendered=termcolor // 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..632666db75b 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -73,10 +73,10 @@ mod foo { "spans": [ { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 440, - "byte_end": 444, - "line_start": 11, - "line_end": 11, + "byte_start": 484, + "byte_end": 488, + "line_start": 12, + "line_end": 12, "column_start": 12, "column_end": 16, "is_primary": true, @@ -101,10 +101,10 @@ mod foo { "spans": [ { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -124,10 +124,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -147,10 +147,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -170,10 +170,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -193,10 +193,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -216,10 +216,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -239,10 +239,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -262,10 +262,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -285,10 +285,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -308,10 +308,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -331,10 +331,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -354,10 +354,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -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:12: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 " } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index ba919f4c411..a7615f5f423 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -62,7 +62,7 @@ struct DiagnosticCode { explanation: Option, } -pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { +pub fn extract_rendered(output: &str) -> String { output .lines() .filter_map(|line| { @@ -70,11 +70,12 @@ pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { match serde_json::from_str::(line) { Ok(diagnostic) => diagnostic.rendered, Err(error) => { - proc_res.fatal(Some(&format!( + print!( "failed to decode compiler output as json: \ `{}`\nline: {}\noutput: {}", error, line, output - ))); + ); + panic!() } } } else { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 369bb3fefe5..6df56168973 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2090,50 +2090,10 @@ impl<'test> TestCx<'test> { } fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! { - self.try_print_open_handles(); self.error(err); proc_res.fatal(None); } - // This function is a poor man's attempt to debug rust-lang/rust#38620, if - // that's closed then this should be deleted - // - // This is a very "opportunistic" debugging attempt, so we ignore all - // errors here. - fn try_print_open_handles(&self) { - if !cfg!(windows) { - return; - } - if self.config.mode != Incremental { - return; - } - - let filename = match self.testpaths.file.file_stem() { - Some(path) => path, - None => return, - }; - - let mut cmd = Command::new("handle.exe"); - cmd.arg("-a").arg("-u"); - cmd.arg(filename); - cmd.arg("-nobanner"); - cmd.stdout(Stdio::piped()); - cmd.stderr(Stdio::piped()); - let output = match cmd.spawn().and_then(read2_abbreviated) { - Ok(output) => output, - Err(_) => return, - }; - println!("---------------------------------------------------"); - println!("ran extra command to debug rust-lang/rust#38620: "); - println!("{:?}", cmd); - println!("result: {}", output.status); - println!("--- stdout ----------------------------------------"); - println!("{}", String::from_utf8_lossy(&output.stdout)); - println!("--- stderr ----------------------------------------"); - println!("{}", String::from_utf8_lossy(&output.stderr)); - println!("---------------------------------------------------"); - } - // codegen tests (using FileCheck) fn compile_test_and_save_ir(&self) -> ProcRes { @@ -2844,7 +2804,7 @@ impl<'test> TestCx<'test> { let stderr = if explicit { proc_res.stderr.clone() } else { - json::extract_rendered(&proc_res.stderr, &proc_res) + json::extract_rendered(&proc_res.stderr) }; let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); @@ -3464,7 +3424,9 @@ impl ProcRes { {}\n\ ------------------------------------------\n\ \n", - self.status, self.cmdline, self.stdout, self.stderr + self.status, self.cmdline, + json::extract_rendered(&self.stdout), + json::extract_rendered(&self.stderr), ); // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from // compiletest, which is unnecessary noise.