Skip to content

Commit

Permalink
Add type field to json diagnostic outputs
Browse files Browse the repository at this point in the history
Currently the json-formatted outputs have no way to unambiguously
determine which kind of message is being output. A consumer can look for
specific fields in the json object (eg "message"), but there's no
guarantee that in future some other kind of output will have a field of
the same name.

This PR adds a `"type"` field to add json outputs which can be used to
unambiguously determine which kind of output it is. The mapping is:

diagnostic: regular compiler diagnostics
artifact: artifact notifications
future_breakage: Future breakage report
unused_extern: Unused crate warnings/errors

This matches the "internally tagged" representation for serde enums.
  • Loading branch information
jsgf committed Sep 9, 2023
1 parent b0b8c52 commit cea4f53
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 96 deletions.
48 changes: 24 additions & 24 deletions compiler/rustc_errors/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@ impl JsonEmitter {
pub fn ui_testing(self, ui_testing: bool) -> Self {
Self { ui_testing, ..self }
}

fn emit_typed(
&mut self,
ty: &str,
val: impl Serialize,
) -> io::Result<()> {
let mut v = serde_json::to_value(val).unwrap();

// only attempt to type objects
if let Some(obj) = v.as_object_mut() {
obj.insert("type".to_string(), ty.into());
}

if self.pretty {
writeln!(self.dst, "{}", serde_json::to_string_pretty(&v).unwrap())
} else {
writeln!(self.dst, "{}", serde_json::to_string(&v).unwrap())
}
.and_then(|_| self.dst.flush())
}
}

impl Translate for JsonEmitter {
Expand All @@ -153,25 +173,15 @@ impl Translate for JsonEmitter {
impl Emitter for JsonEmitter {
fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) {
let data = Diagnostic::from_errors_diagnostic(diag, self);
let result = if self.pretty {
writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap())
} else {
writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap())
}
.and_then(|_| self.dst.flush());
let result = self.emit_typed("diagnostic", data);
if let Err(e) = result {
panic!("failed to print diagnostics: {e:?}");
}
}

fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) {
let data = ArtifactNotification { artifact: path, emit: artifact_type };
let result = if self.pretty {
writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap())
} else {
writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap())
}
.and_then(|_| self.dst.flush());
let result = self.emit_typed("artifact", data);
if let Err(e) = result {
panic!("failed to print notification: {e:?}");
}
Expand All @@ -188,12 +198,7 @@ impl Emitter for JsonEmitter {
})
.collect();
let report = FutureIncompatReport { future_incompat_report: data };
let result = if self.pretty {
writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&report).unwrap())
} else {
writeln!(&mut self.dst, "{}", serde_json::to_string(&report).unwrap())
}
.and_then(|_| self.dst.flush());
let result = self.emit_typed("future_breakage", report);
if let Err(e) = result {
panic!("failed to print future breakage report: {e:?}");
}
Expand All @@ -202,12 +207,7 @@ impl Emitter for JsonEmitter {
fn emit_unused_externs(&mut self, lint_level: rustc_lint_defs::Level, unused_externs: &[&str]) {
let lint_level = lint_level.as_str();
let data = UnusedExterns { lint_level, unused_extern_names: unused_externs };
let result = if self.pretty {
writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap())
} else {
writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap())
}
.and_then(|_| self.dst.flush());
let result = self.emit_typed("unused_extern", data);
if let Err(e) = result {
panic!("failed to print unused externs: {e:?}");
}
Expand Down
14 changes: 7 additions & 7 deletions tests/ui/diagnostic-width/flag-json.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
{"children":[],"code":{"code":"E0308","explanation":"Expected type did not match the received type.

Erroneous code examples:

Expand All @@ -24,17 +24,17 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types
"},"level":"error","message":"mismatched types","rendered":"error[E0308]: mismatched types
--> $DIR/flag-json.rs:7:17
|
LL | ..._: () = 42;
| -- ^^ expected `()`, found integer
| |
| expected due to this

"}
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
","spans":[{"byte_end":245,"byte_start":243,"column_end":19,"column_start":17,"expansion":null,"file_name":"$DIR/flag-json.rs","is_primary":true,"label":"expected `()`, found integer","line_end":7,"line_start":7,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":19,"highlight_start":17,"text":" let _: () = 42;"}]},{"byte_end":240,"byte_start":238,"column_end":14,"column_start":12,"expansion":null,"file_name":"$DIR/flag-json.rs","is_primary":false,"label":"expected due to this","line_end":7,"line_start":7,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":14,"highlight_start":12,"text":" let _: () = 42;"}]}],"type":"diagnostic"}
{"children":[],"code":null,"level":"error","message":"aborting due to previous error","rendered":"error: aborting due to previous error

"}
{"message":"For more information about this error, try `rustc --explain E0308`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0308`.
"}
","spans":[],"type":"diagnostic"}
{"children":[],"code":null,"level":"failure-note","message":"For more information about this error, try `rustc --explain E0308`.","rendered":"For more information about this error, try `rustc --explain E0308`.
","spans":[],"type":"diagnostic"}
28 changes: 14 additions & 14 deletions tests/ui/json/json-bom-plus-crlf-multifile.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
{"children":[{"children":[],"code":null,"level":"help","message":"try using a conversion method","rendered":null,"spans":[{"byte_end":622,"byte_start":622,"column_end":23,"column_start":23,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":null,"line_end":17,"line_start":17,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","text":[{"highlight_end":23,"highlight_start":23,"text":" let s : String = 1; // Error in the middle of line."}]}]}],"code":{"code":"E0308","explanation":"Expected type did not match the received type.

Erroneous code examples:

Expand All @@ -24,9 +24,9 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
"},"level":"error","message":"mismatched types","rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
","spans":[{"byte_end":622,"byte_start":621,"column_end":23,"column_start":22,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":"expected `String`, found integer","line_end":17,"line_start":17,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":23,"highlight_start":22,"text":" let s : String = 1; // Error in the middle of line."}]},{"byte_end":618,"byte_start":612,"column_end":19,"column_start":13,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":false,"label":"expected due to this","line_end":17,"line_start":17,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":19,"highlight_start":13,"text":" let s : String = 1; // Error in the middle of line."}]}],"type":"diagnostic"}
{"children":[{"children":[],"code":null,"level":"help","message":"try using a conversion method","rendered":null,"spans":[{"byte_end":682,"byte_start":682,"column_end":23,"column_start":23,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":null,"line_end":19,"line_start":19,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","text":[{"highlight_end":23,"highlight_start":23,"text":" let s : String = 1"}]}]}],"code":{"code":"E0308","explanation":"Expected type did not match the received type.

Erroneous code examples:

Expand All @@ -52,9 +52,9 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
"},"level":"error","message":"mismatched types","rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
","spans":[{"byte_end":682,"byte_start":681,"column_end":23,"column_start":22,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":"expected `String`, found integer","line_end":19,"line_start":19,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":23,"highlight_start":22,"text":" let s : String = 1"}]},{"byte_end":678,"byte_start":672,"column_end":19,"column_start":13,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":false,"label":"expected due to this","line_end":19,"line_start":19,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":19,"highlight_start":13,"text":" let s : String = 1"}]}],"type":"diagnostic"}
{"children":[{"children":[],"code":null,"level":"help","message":"try using a conversion method","rendered":null,"spans":[{"byte_end":746,"byte_start":746,"column_end":2,"column_start":2,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":null,"line_end":23,"line_start":23,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","text":[{"highlight_end":2,"highlight_start":2,"text":"1; // Error after the newline."}]}]}],"code":{"code":"E0308","explanation":"Expected type did not match the received type.

Erroneous code examples:

Expand All @@ -80,9 +80,9 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
"},"level":"error","message":"mismatched types","rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
","spans":[{"byte_end":746,"byte_start":745,"column_end":2,"column_start":1,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":"expected `String`, found integer","line_end":23,"line_start":23,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":2,"highlight_start":1,"text":"1; // Error after the newline."}]},{"byte_end":741,"byte_start":735,"column_end":19,"column_start":13,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":false,"label":"expected due to this","line_end":22,"line_start":22,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":19,"highlight_start":13,"text":" let s : String ="}]}],"type":"diagnostic"}
{"children":[],"code":{"code":"E0308","explanation":"Expected type did not match the received type.

Erroneous code examples:

Expand All @@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
"},"level":"error","message":"mismatched types","rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
","spans":[{"byte_end":809,"byte_start":801,"column_end":6,"column_start":22,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":true,"label":"expected `String`, found `()`","line_end":26,"line_start":25,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":23,"highlight_start":22,"text":" let s : String = ("},{"highlight_end":6,"highlight_start":1,"text":" ); // Error spanning the newline."}]},{"byte_end":798,"byte_start":792,"column_end":19,"column_start":13,"expansion":null,"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","is_primary":false,"label":"expected due to this","line_end":25,"line_start":25,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":19,"highlight_start":13,"text":" let s : String = ("}]}],"type":"diagnostic"}
{"children":[],"code":null,"level":"error","message":"aborting due to 4 previous errors","rendered":"error: aborting due to 4 previous errors
","spans":[],"type":"diagnostic"}
Loading

0 comments on commit cea4f53

Please sign in to comment.