Skip to content
Merged
106 changes: 70 additions & 36 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -204,14 +205,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))
}
}

Expand Down Expand Up @@ -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"),
json_rendered: Option<String> = (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],
Expand Down Expand Up @@ -1798,6 +1805,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
"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",
Expand Down Expand Up @@ -1938,21 +1951,32 @@ 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
// is unstable, it will not be present. We have to use opts_present not
// 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 `{}`)",
Expand All @@ -1961,7 +1985,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");
Expand All @@ -1973,11 +1997,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.is_some() && !debugging_opts.pgo_use.is_empty() {
Expand Down Expand Up @@ -2881,50 +2910,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());
Expand Down
65 changes: 33 additions & 32 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1037,39 +1037,42 @@ fn default_emitter(
emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
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))
}
}
}

Expand Down Expand Up @@ -1314,13 +1317,12 @@ pub enum IncrCompSession {

pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
let emitter: Box<dyn Emitter + sync::Send> = 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);
Expand All @@ -1329,13 +1331,12 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {

pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
let emitter: Box<dyn Emitter + sync::Send> = 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);
Expand Down
Loading