about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2024-08-11 11:49:47 +0200
committerGuillaume Gomez <guillaume.gomez@huawei.com>2024-08-12 13:50:29 +0200
commit18d62008d4196630da20c91f3ee95e93816d613d (patch)
tree6afef9cd30cea33de36ca32a5c31946028faf487
parentc9bd03cb724e13cca96ad320733046cbdb16fbbe (diff)
downloadrust-18d62008d4196630da20c91f3ee95e93816d613d.tar.gz
rust-18d62008d4196630da20c91f3ee95e93816d613d.zip
Add possibility to generate rustdoc JSON output to stdout
-rw-r--r--src/librustdoc/config.rs15
-rw-r--r--src/librustdoc/json/mod.rs47
2 files changed, 41 insertions, 21 deletions
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 9c7a9f8467f..cd2892e7a25 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -286,6 +286,9 @@ pub(crate) struct RenderOptions {
     pub(crate) no_emit_shared: bool,
     /// If `true`, HTML source code pages won't be generated.
     pub(crate) html_no_source: bool,
+    /// This field is only used for the JSON output. If it's set to true, no file will be created
+    /// and content will be displayed in stdout directly.
+    pub(crate) output_to_stdout: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -548,16 +551,17 @@ impl Options {
             dcx.fatal("the `--test` flag must be passed to enable `--no-run`");
         }
 
+        let mut output_to_stdout = false;
         let test_builder_wrappers =
             matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect();
-        let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s));
-        let output = matches.opt_str("output").map(|s| PathBuf::from(&s));
-        let output = match (out_dir, output) {
+        let output = match (matches.opt_str("out-dir"), matches.opt_str("output")) {
             (Some(_), Some(_)) => {
                 dcx.fatal("cannot use both 'out-dir' and 'output' at once");
             }
-            (Some(out_dir), None) => out_dir,
-            (None, Some(output)) => output,
+            (Some(out_dir), None) | (None, Some(out_dir)) => {
+                output_to_stdout = out_dir == "-";
+                PathBuf::from(out_dir)
+            }
             (None, None) => PathBuf::from("doc"),
         };
 
@@ -816,6 +820,7 @@ impl Options {
             call_locations,
             no_emit_shared: false,
             html_no_source,
+            output_to_stdout,
         };
         Some((options, render_options))
     }
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index ea191dc89cf..860672443f2 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -9,7 +9,7 @@ mod import_finder;
 
 use std::cell::RefCell;
 use std::fs::{create_dir_all, File};
-use std::io::{BufWriter, Write};
+use std::io::{stdout, BufWriter, Write};
 use std::path::PathBuf;
 use std::rc::Rc;
 
@@ -37,7 +37,7 @@ pub(crate) struct JsonRenderer<'tcx> {
     /// level field of the JSON blob.
     index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
     /// The directory where the blob will be written to.
-    out_path: PathBuf,
+    out_path: Option<PathBuf>,
     cache: Rc<Cache>,
     imported_items: DefIdSet,
 }
@@ -97,6 +97,20 @@ impl<'tcx> JsonRenderer<'tcx> {
             })
             .unwrap_or_default()
     }
+
+    fn write<T: Write>(
+        &self,
+        output: types::Crate,
+        mut writer: BufWriter<T>,
+        path: &str,
+    ) -> Result<(), Error> {
+        self.tcx
+            .sess
+            .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut writer, &output))
+            .unwrap();
+        try_err!(writer.flush(), path);
+        Ok(())
+    }
 }
 
 impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
@@ -120,7 +134,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
             JsonRenderer {
                 tcx,
                 index: Rc::new(RefCell::new(FxHashMap::default())),
-                out_path: options.output,
+                out_path: if options.output_to_stdout { None } else { Some(options.output) },
                 cache: Rc::new(cache),
                 imported_items,
             },
@@ -264,20 +278,21 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 .collect(),
             format_version: types::FORMAT_VERSION,
         };
-        let out_dir = self.out_path.clone();
-        try_err!(create_dir_all(&out_dir), out_dir);
+        if let Some(ref out_path) = self.out_path {
+            let out_dir = out_path.clone();
+            try_err!(create_dir_all(&out_dir), out_dir);
 
-        let mut p = out_dir;
-        p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
-        p.set_extension("json");
-        let mut file = BufWriter::new(try_err!(File::create(&p), p));
-        self.tcx
-            .sess
-            .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output))
-            .unwrap();
-        try_err!(file.flush(), p);
-
-        Ok(())
+            let mut p = out_dir;
+            p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
+            p.set_extension("json");
+            self.write(
+                output,
+                BufWriter::new(try_err!(File::create(&p), p)),
+                &p.display().to_string(),
+            )
+        } else {
+            self.write(output, BufWriter::new(stdout()), "<stdout>")
+        }
     }
 
     fn cache(&self) -> &Cache {