about summary refs log tree commit diff
path: root/compiler/rustc_errors/src/json.rs
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2021-01-18 14:10:31 -0800
committerJeremy Fitzhardinge <jeremy@goop.org>2021-02-07 14:54:22 -0800
commit50572d66295840ba13aee0cd500c20b9513e77f7 (patch)
tree81da7e0ce69f23a750baf4138e3626f3f20934f3 /compiler/rustc_errors/src/json.rs
parent82ccb6582a76d72fb5abaf7195dc7a653f1aa54b (diff)
downloadrust-50572d66295840ba13aee0cd500c20b9513e77f7.tar.gz
rust-50572d66295840ba13aee0cd500c20b9513e77f7.zip
Implement Encoder for Diagnostic manually
...so we can skip serializing `tool_metadata` if it hasn't been set.
This makes the output a bit cleaner, and avoiding having to update a
bunch of unrelated tests.
Diffstat (limited to 'compiler/rustc_errors/src/json.rs')
-rw-r--r--compiler/rustc_errors/src/json.rs34
1 files changed, 33 insertions, 1 deletions
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 89e844879f7..f26c439add9 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -27,6 +27,7 @@ use std::sync::{Arc, Mutex};
 use std::vec;
 
 use rustc_serialize::json::{as_json, as_pretty_json};
+use rustc_serialize::{Encodable, Encoder};
 
 #[cfg(test)]
 mod tests;
@@ -169,7 +170,8 @@ impl Emitter for JsonEmitter {
 
 // The following data types are provided just for serialisation.
 
-#[derive(Encodable)]
+// NOTE: this has a manual implementation of Encodable which needs to be updated in
+// parallel.
 struct Diagnostic {
     /// The primary error message.
     message: String,
@@ -185,6 +187,36 @@ struct Diagnostic {
     tool_metadata: ToolMetadata,
 }
 
+macro_rules! encode_fields {
+    ($enc:expr, $s:expr, $idx:expr, [ $($name:ident),+$(,)? ]) => {
+        {
+            let mut idx = $idx;
+            $(
+                $enc.emit_struct_field(stringify!($name), idx, |enc| $s.$name.encode(enc))?;
+                idx += 1;
+            )+
+            idx
+        }
+    };
+}
+
+// Special-case encoder to skip tool_metadata if not set
+impl<E: Encoder> Encodable<E> for Diagnostic {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        s.emit_struct("diagnostic", 7, |s| {
+            let mut idx = 0;
+
+            idx = encode_fields!(s, self, idx, [message, code, level, spans, children, rendered]);
+            if self.tool_metadata.is_set() {
+                idx = encode_fields!(s, self, idx, [tool_metadata]);
+            }
+
+            let _ = idx;
+            Ok(())
+        })
+    }
+}
+
 #[derive(Encodable)]
 struct DiagnosticSpan {
     file_name: String,