diff options
| author | Jeremy Fitzhardinge <jsgf@fb.com> | 2023-09-08 18:47:59 -0700 |
|---|---|---|
| committer | Jeremy Fitzhardinge <jsgf@fb.com> | 2023-09-19 14:17:02 -0700 |
| commit | 5c8170656bb18995795124d4690f8f3ab503e184 (patch) | |
| tree | df7cc6adc980f06f231322457eb03703cfc302a2 /compiler/rustc_errors/src/json.rs | |
| parent | ac5ac4754a4a837f7138a1fa5ab01475b63fc9fe (diff) | |
| download | rust-5c8170656bb18995795124d4690f8f3ab503e184.tar.gz rust-5c8170656bb18995795124d4690f8f3ab503e184.zip | |
Add `type` field to json diagnostic outputs
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_incompat: Report of future incompatibility unused_extern: Unused crate warnings/errors This matches the "internally tagged" representation for serde enums.
Diffstat (limited to 'compiler/rustc_errors/src/json.rs')
| -rw-r--r-- | compiler/rustc_errors/src/json.rs | 46 |
1 files changed, 22 insertions, 24 deletions
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 0cb75c71b73..7b937bd1459 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -145,6 +145,24 @@ impl JsonEmitter { pub fn ignored_directories_in_source_blocks(self, value: Vec<String>) -> Self { Self { ignored_directories_in_source_blocks: value, ..self } } + + fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> { + if self.pretty { + writeln!(self.dst, "{}", serde_json::to_string_pretty(&val).unwrap()) + } else { + writeln!(self.dst, "{}", serde_json::to_string(&val).unwrap()) + } + .and_then(|_| self.dst.flush()) + } +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +enum EmitTyped<'a> { + Diagnostic(Diagnostic), + Artifact(ArtifactNotification<'a>), + FutureIncompat(FutureIncompatReport), + UnusedExtern(UnusedExterns<'a, 'a, 'a>), } impl Translate for JsonEmitter { @@ -160,12 +178,7 @@ 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(EmitTyped::Diagnostic(data)); if let Err(e) = result { panic!("failed to print diagnostics: {e:?}"); } @@ -173,12 +186,7 @@ impl Emitter for JsonEmitter { 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(EmitTyped::Artifact(data)); if let Err(e) = result { panic!("failed to print notification: {e:?}"); } @@ -195,12 +203,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(EmitTyped::FutureIncompat(report)); if let Err(e) = result { panic!("failed to print future breakage report: {e:?}"); } @@ -209,12 +212,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(EmitTyped::UnusedExtern(data)); if let Err(e) = result { panic!("failed to print unused externs: {e:?}"); } |
