Auto merge of #45737 - oli-obk:json, r=petrochenkov

Pretty print json in ui tests

I found the json output in one line to not be useful for reviewing

r? @petrochenkov
This commit is contained in:
bors 2017-11-06 12:18:12 +00:00
commit 74be072068
8 changed files with 468 additions and 77 deletions

View file

@ -155,7 +155,7 @@ impl OutputType {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
HumanReadable(ColorConfig),
Json,
Json(bool),
Short(ColorConfig),
}
@ -1433,7 +1433,8 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
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,
Some("json") => ErrorOutputType::Json(false),
Some("pretty-json") => ErrorOutputType::Json(true),
Some("short") => ErrorOutputType::Short(color),
None => ErrorOutputType::HumanReadable(color),
@ -1474,6 +1475,11 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
let 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");
}
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
@ -2254,46 +2260,46 @@ mod tests {
let mut v5 = super::basic_options();
// Reference
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Native changed
v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Crate changed
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Dependency changed
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json);
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Framework changed
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json);
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// All changed
v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json);
v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
@ -2316,29 +2322,29 @@ mod tests {
let mut v4 = super::basic_options();
// Reference
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());

View file

@ -372,7 +372,7 @@ impl Session {
match self.opts.error_format {
// when outputting JSON for tool consumption, the tool might want
// the duplicates
config::ErrorOutputType::Json => {
config::ErrorOutputType::Json(_) => {
do_method()
},
_ => {
@ -736,11 +736,11 @@ pub fn build_session_with_codemap(sopts: config::Options,
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false))
}
(config::ErrorOutputType::Json, None) => {
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
(config::ErrorOutputType::Json(pretty), None) => {
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty))
}
(config::ErrorOutputType::Json, Some(dst)) => {
Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
(config::ErrorOutputType::Json(pretty), Some(dst)) => {
Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty))
}
(config::ErrorOutputType::Short(color_config), None) => {
Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true))
@ -918,7 +918,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, false))
}
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
config::ErrorOutputType::Short(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, true))
}
@ -933,7 +933,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, false))
}
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
config::ErrorOutputType::Short(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, true))
}

View file

@ -30,36 +30,41 @@ use std::rc::Rc;
use std::io::{self, Write};
use std::vec;
use rustc_serialize::json::as_json;
use rustc_serialize::json::{as_json, as_pretty_json};
pub struct JsonEmitter {
dst: Box<Write + Send>,
registry: Option<Registry>,
cm: Rc<CodeMapper + 'static>,
pretty: bool,
}
impl JsonEmitter {
pub fn stderr(registry: Option<Registry>,
code_map: Rc<CodeMap>) -> JsonEmitter {
code_map: Rc<CodeMap>,
pretty: bool) -> JsonEmitter {
JsonEmitter {
dst: Box::new(io::stderr()),
registry,
cm: code_map,
pretty,
}
}
pub fn basic() -> JsonEmitter {
pub fn basic(pretty: bool) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)))
JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty)
}
pub fn new(dst: Box<Write + Send>,
registry: Option<Registry>,
code_map: Rc<CodeMap>) -> JsonEmitter {
code_map: Rc<CodeMap>,
pretty: bool) -> JsonEmitter {
JsonEmitter {
dst,
registry,
cm: code_map,
pretty,
}
}
}
@ -67,7 +72,12 @@ impl JsonEmitter {
impl Emitter for JsonEmitter {
fn emit(&mut self, db: &DiagnosticBuilder) {
let data = Diagnostic::from_diagnostic_builder(db, self);
if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
let result = if self.pretty {
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
} else {
writeln!(&mut self.dst, "{}", as_json(&data))
};
if let Err(e) = result {
panic!("failed to print diagnostics: {:?}", e);
}
}
@ -85,9 +95,7 @@ struct Diagnostic {
spans: Vec<DiagnosticSpan>,
/// Associated diagnostic messages.
children: Vec<Diagnostic>,
/// The message as rustc would render it. Currently this is only
/// `Some` for "suggestions", but eventually it will include all
/// snippets.
/// The message as rustc would render it. Currently this is always `None`
rendered: Option<String>,
}
@ -110,9 +118,7 @@ struct DiagnosticSpan {
/// Label that should be placed at this location (if any)
label: Option<String>,
/// If we are suggesting a replacement, this will contain text
/// that should be sliced in atop this span. You may prefer to
/// load the fully rendered version from the parent `Diagnostic`,
/// however.
/// that should be sliced in atop this span.
suggested_replacement: Option<String>,
/// Macro invocations that created the code at this span, if any.
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --error-format json
// compile-flags: --error-format pretty-json -Zunstable-options
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested

View file

@ -1 +1,91 @@
{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"lint level defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":847,"byte_end":860,"line_start":19,"line_end":19,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![warn(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":null}],"rendered":null}
{
"message": "unnecessary parentheses around assigned value",
"code": {
"code": "unused_parens",
"explanation": null
},
"level": "warning",
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
"byte_start": 1027,
"byte_end": 1040,
"line_start": 24,
"line_end": 24,
"column_start": 14,
"column_end": 27,
"is_primary": true,
"text": [
{
"text": " let _a = (1 / (2 + 3));",
"highlight_start": 14,
"highlight_end": 27
}
],
"label": null,
"suggested_replacement": null,
"expansion": null
}
],
"children": [
{
"message": "lint level defined here",
"code": null,
"level": "note",
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
"byte_start": 873,
"byte_end": 886,
"line_start": 19,
"line_end": 19,
"column_start": 9,
"column_end": 22,
"is_primary": true,
"text": [
{
"text": "#![warn(unused_parens)]",
"highlight_start": 9,
"highlight_end": 22
}
],
"label": null,
"suggested_replacement": null,
"expansion": null
}
],
"children": [],
"rendered": null
},
{
"message": "remove these parentheses",
"code": null,
"level": "help",
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
"byte_start": 1027,
"byte_end": 1040,
"line_start": 24,
"line_end": 24,
"column_start": 14,
"column_end": 27,
"is_primary": true,
"text": [
{
"text": " let _a = (1 / (2 + 3));",
"highlight_start": 14,
"highlight_end": 27
}
],
"label": null,
"suggested_replacement": "1 / (2 + 3)",
"expansion": null
}
],
"children": [],
"rendered": null
}
],
"rendered": null
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --error-format json
// compile-flags: --error-format pretty-json -Zunstable-options
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested

File diff suppressed because one or more lines are too long

View file

@ -2391,7 +2391,8 @@ actual:\n\
fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
let parent_dir = self.testpaths.file.parent().unwrap();
let cflags = self.props.compile_flags.join(" ");
let parent_dir_str = if cflags.contains("--error-format json") {
let parent_dir_str = if cflags.contains("--error-format json")
|| cflags.contains("--error-format pretty-json") {
parent_dir.display().to_string().replace("\\", "\\\\")
} else {
parent_dir.display().to_string()