Skip to content

Commit c89bc54

Browse files
authored
Rollup merge of #59128 - oli-obk:colorful_json, r=mark-i-m,eddyb
Emit ansi color codes in the `rendered` field of json diagnostics cc @ljedrz Implemented for #56595 (comment) (x.py clippy)
2 parents 258e3b3 + 5c6a43a commit c89bc54

File tree

13 files changed

+287
-230
lines changed

13 files changed

+287
-230
lines changed

src/librustc/session/config.rs

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use syntax::parse::token;
1919
use syntax::parse;
2020
use syntax::symbol::Symbol;
2121
use syntax::feature_gate::UnstableFeatures;
22+
use errors::emitter::HumanReadableErrorType;
2223

2324
use errors::{ColorConfig, FatalError, Handler};
2425

@@ -219,14 +220,18 @@ impl OutputType {
219220

220221
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
221222
pub enum ErrorOutputType {
222-
HumanReadable(ColorConfig),
223-
Json(bool),
224-
Short(ColorConfig),
223+
HumanReadable(HumanReadableErrorType),
224+
Json {
225+
/// Render the json in a human readable way (with indents and newlines)
226+
pretty: bool,
227+
/// The way the `rendered` field is created
228+
json_rendered: HumanReadableErrorType,
229+
},
225230
}
226231

227232
impl Default for ErrorOutputType {
228233
fn default() -> ErrorOutputType {
229-
ErrorOutputType::HumanReadable(ColorConfig::Auto)
234+
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
230235
}
231236
}
232237

@@ -1372,6 +1377,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
13721377
"print some statistics about AST and HIR"),
13731378
always_encode_mir: bool = (false, parse_bool, [TRACKED],
13741379
"encode MIR of all functions into the crate metadata"),
1380+
json_rendered: Option<String> = (None, parse_opt_string, [UNTRACKED],
1381+
"describes how to render the `rendered` field of json diagnostics"),
13751382
unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED],
13761383
"take the breaks off const evaluation. NOTE: this is unsound"),
13771384
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
@@ -1825,6 +1832,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
18251832
"How errors and other messages are produced",
18261833
"human|json|short",
18271834
),
1835+
opt::opt(
1836+
"",
1837+
"json-rendered",
1838+
"Choose `rendered` field of json diagnostics render scheme",
1839+
"plain|termcolor",
1840+
),
18281841
opt::opt_s(
18291842
"",
18301843
"color",
@@ -1965,21 +1978,32 @@ pub fn build_session_options_and_crate_config(
19651978
)
19661979
}
19671980

1981+
let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() {
1982+
"plain" => None,
1983+
"termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)),
1984+
_ => early_error(
1985+
ErrorOutputType::default(),
1986+
&format!(
1987+
"argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)",
1988+
s,
1989+
),
1990+
),
1991+
}).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never));
19681992

19691993
// We need the opts_present check because the driver will send us Matches
19701994
// with only stable options if no unstable options are used. Since error-format
19711995
// is unstable, it will not be present. We have to use opts_present not
19721996
// opt_present because the latter will panic.
19731997
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
19741998
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
1975-
Some("human") => ErrorOutputType::HumanReadable(color),
1976-
Some("json") => ErrorOutputType::Json(false),
1977-
Some("pretty-json") => ErrorOutputType::Json(true),
1978-
Some("short") => ErrorOutputType::Short(color),
1979-
None => ErrorOutputType::HumanReadable(color),
1999+
None |
2000+
Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
2001+
Some("json") => ErrorOutputType::Json { pretty: false, json_rendered },
2002+
Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
2003+
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
19802004

19812005
Some(arg) => early_error(
1982-
ErrorOutputType::HumanReadable(color),
2006+
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
19832007
&format!(
19842008
"argument for --error-format must be `human`, `json` or \
19852009
`short` (instead was `{}`)",
@@ -1988,7 +2012,7 @@ pub fn build_session_options_and_crate_config(
19882012
),
19892013
}
19902014
} else {
1991-
ErrorOutputType::HumanReadable(color)
2015+
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
19922016
};
19932017

19942018
let unparsed_crate_types = matches.opt_strs("crate-type");
@@ -2000,11 +2024,16 @@ pub fn build_session_options_and_crate_config(
20002024

20012025
let mut debugging_opts = build_debugging_options(matches, error_format);
20022026

2003-
if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
2004-
early_error(
2005-
ErrorOutputType::Json(false),
2006-
"--error-format=pretty-json is unstable",
2007-
);
2027+
if !debugging_opts.unstable_options {
2028+
if matches.opt_str("json-rendered").is_some() {
2029+
early_error(error_format, "`--json-rendered=x` is unstable");
2030+
}
2031+
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
2032+
early_error(
2033+
ErrorOutputType::Json { pretty: false, json_rendered },
2034+
"--error-format=pretty-json is unstable",
2035+
);
2036+
}
20082037
}
20092038

20102039
if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() {
@@ -2928,50 +2957,55 @@ mod tests {
29282957
let mut v3 = Options::default();
29292958
let mut v4 = Options::default();
29302959

2960+
const JSON: super::ErrorOutputType = super::ErrorOutputType::Json {
2961+
pretty: false,
2962+
json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never),
2963+
};
2964+
29312965
// Reference
29322966
v1.search_paths
2933-
.push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
2967+
.push(SearchPath::from_cli_opt("native=abc", JSON));
29342968
v1.search_paths
2935-
.push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
2969+
.push(SearchPath::from_cli_opt("crate=def", JSON));
29362970
v1.search_paths
2937-
.push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
2971+
.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
29382972
v1.search_paths
2939-
.push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
2973+
.push(SearchPath::from_cli_opt("framework=jkl", JSON));
29402974
v1.search_paths
2941-
.push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
2975+
.push(SearchPath::from_cli_opt("all=mno", JSON));
29422976

29432977
v2.search_paths
2944-
.push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
2978+
.push(SearchPath::from_cli_opt("native=abc", JSON));
29452979
v2.search_paths
2946-
.push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
2980+
.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
29472981
v2.search_paths
2948-
.push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
2982+
.push(SearchPath::from_cli_opt("crate=def", JSON));
29492983
v2.search_paths
2950-
.push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
2984+
.push(SearchPath::from_cli_opt("framework=jkl", JSON));
29512985
v2.search_paths
2952-
.push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
2986+
.push(SearchPath::from_cli_opt("all=mno", JSON));
29532987

29542988
v3.search_paths
2955-
.push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
2989+
.push(SearchPath::from_cli_opt("crate=def", JSON));
29562990
v3.search_paths
2957-
.push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
2991+
.push(SearchPath::from_cli_opt("framework=jkl", JSON));
29582992
v3.search_paths
2959-
.push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
2993+
.push(SearchPath::from_cli_opt("native=abc", JSON));
29602994
v3.search_paths
2961-
.push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
2995+
.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
29622996
v3.search_paths
2963-
.push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
2997+
.push(SearchPath::from_cli_opt("all=mno", JSON));
29642998

29652999
v4.search_paths
2966-
.push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
3000+
.push(SearchPath::from_cli_opt("all=mno", JSON));
29673001
v4.search_paths
2968-
.push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
3002+
.push(SearchPath::from_cli_opt("native=abc", JSON));
29693003
v4.search_paths
2970-
.push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
3004+
.push(SearchPath::from_cli_opt("crate=def", JSON));
29713005
v4.search_paths
2972-
.push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
3006+
.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
29733007
v4.search_paths
2974-
.push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
3008+
.push(SearchPath::from_cli_opt("framework=jkl", JSON));
29753009

29763010
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
29773011
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());

src/librustc/session/mod.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,39 +1033,42 @@ fn default_emitter(
10331033
emitter_dest: Option<Box<dyn Write + Send>>,
10341034
) -> Box<dyn Emitter + sync::Send> {
10351035
match (sopts.error_format, emitter_dest) {
1036-
(config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
1037-
EmitterWriter::stderr(
1038-
color_config,
1039-
Some(source_map.clone()),
1040-
false,
1041-
sopts.debugging_opts.teach,
1042-
).ui_testing(sopts.debugging_opts.ui_testing),
1043-
),
1044-
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
1045-
EmitterWriter::new(dst, Some(source_map.clone()), false, false)
1046-
.ui_testing(sopts.debugging_opts.ui_testing),
1047-
),
1048-
(config::ErrorOutputType::Json(pretty), None) => Box::new(
1036+
(config::ErrorOutputType::HumanReadable(kind), dst) => {
1037+
let (short, color_config) = kind.unzip();
1038+
let emitter = match dst {
1039+
None => EmitterWriter::stderr(
1040+
color_config,
1041+
Some(source_map.clone()),
1042+
short,
1043+
sopts.debugging_opts.teach,
1044+
),
1045+
Some(dst) => EmitterWriter::new(
1046+
dst,
1047+
Some(source_map.clone()),
1048+
short,
1049+
false, // no teach messages when writing to a buffer
1050+
false, // no colors when writing to a buffer
1051+
),
1052+
};
1053+
Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
1054+
},
1055+
(config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new(
10491056
JsonEmitter::stderr(
10501057
Some(registry),
10511058
source_map.clone(),
10521059
pretty,
1060+
json_rendered,
10531061
).ui_testing(sopts.debugging_opts.ui_testing),
10541062
),
1055-
(config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
1063+
(config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new(
10561064
JsonEmitter::new(
10571065
dst,
10581066
Some(registry),
10591067
source_map.clone(),
10601068
pretty,
1069+
json_rendered,
10611070
).ui_testing(sopts.debugging_opts.ui_testing),
10621071
),
1063-
(config::ErrorOutputType::Short(color_config), None) => Box::new(
1064-
EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false),
1065-
),
1066-
(config::ErrorOutputType::Short(_), Some(dst)) => {
1067-
Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false))
1068-
}
10691072
}
10701073
}
10711074

@@ -1322,13 +1325,12 @@ pub enum IncrCompSession {
13221325

13231326
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
13241327
let emitter: Box<dyn Emitter + sync::Send> = match output {
1325-
config::ErrorOutputType::HumanReadable(color_config) => {
1326-
Box::new(EmitterWriter::stderr(color_config, None, false, false))
1327-
}
1328-
config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
1329-
config::ErrorOutputType::Short(color_config) => {
1330-
Box::new(EmitterWriter::stderr(color_config, None, true, false))
1328+
config::ErrorOutputType::HumanReadable(kind) => {
1329+
let (short, color_config) = kind.unzip();
1330+
Box::new(EmitterWriter::stderr(color_config, None, short, false))
13311331
}
1332+
config::ErrorOutputType::Json { pretty, json_rendered } =>
1333+
Box::new(JsonEmitter::basic(pretty, json_rendered)),
13321334
};
13331335
let handler = errors::Handler::with_emitter(true, None, emitter);
13341336
handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal);
@@ -1337,13 +1339,12 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
13371339

13381340
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
13391341
let emitter: Box<dyn Emitter + sync::Send> = match output {
1340-
config::ErrorOutputType::HumanReadable(color_config) => {
1341-
Box::new(EmitterWriter::stderr(color_config, None, false, false))
1342-
}
1343-
config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
1344-
config::ErrorOutputType::Short(color_config) => {
1345-
Box::new(EmitterWriter::stderr(color_config, None, true, false))
1342+
config::ErrorOutputType::HumanReadable(kind) => {
1343+
let (short, color_config) = kind.unzip();
1344+
Box::new(EmitterWriter::stderr(color_config, None, short, false))
13461345
}
1346+
config::ErrorOutputType::Json { pretty, json_rendered } =>
1347+
Box::new(JsonEmitter::basic(pretty, json_rendered)),
13471348
};
13481349
let handler = errors::Handler::with_emitter(true, None, emitter);
13491350
handler.emit(&MultiSpan::new(), msg, errors::Level::Warning);

0 commit comments

Comments
 (0)