Skip to content

Commit f4e2eac

Browse files
committed
Auto merge of #12252 - charmitro:master, r=weihanglo
Add unstable `--output-format` option to `cargo rustdoc` Add unstable `--output-format` option to "rustdoc" We achieved this by: * Handle `--output-format` argument, accepting `html` or `json` * A new field `json` in `CompileMode::Doc`. * If `json` is passed, we append the following in `prepare_rustdoc`: 1. `-Zunstable-options` 2. `--output-format=json` Fixes #12103
2 parents 4eef543 + 9276399 commit f4e2eac

File tree

17 files changed

+244
-15
lines changed

17 files changed

+244
-15
lines changed

src/bin/cargo/commands/doc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,15 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
4949
let ws = args.workspace(config)?;
5050
let mode = CompileMode::Doc {
5151
deps: !args.flag("no-deps"),
52+
json: false,
5253
};
5354
let mut compile_opts =
5455
args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?;
5556
compile_opts.rustdoc_document_private_items = args.flag("document-private-items");
5657

5758
let doc_opts = DocOptions {
5859
open_result: args.flag("open"),
60+
output_format: ops::OutputFormat::Html,
5961
compile_opts,
6062
};
6163
ops::doc(&ws, &doc_opts)?;

src/bin/cargo/commands/rustdoc.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use cargo::ops::{self, DocOptions};
1+
use cargo::ops::{self, DocOptions, OutputFormat};
22

33
use crate::command_prelude::*;
44

@@ -38,6 +38,11 @@ pub fn cli() -> Command {
3838
.arg_profile("Build artifacts with the specified profile")
3939
.arg_target_triple("Build for the target triple")
4040
.arg_target_dir()
41+
.arg(
42+
opt("output-format", "The output type to write (unstable)")
43+
.value_name("FMT")
44+
.value_parser(OutputFormat::POSSIBLE_VALUES),
45+
)
4146
.arg_unit_graph()
4247
.arg_timings()
4348
.arg_manifest_path()
@@ -48,20 +53,35 @@ pub fn cli() -> Command {
4853

4954
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
5055
let ws = args.workspace(config)?;
56+
let output_format = if let Some(output_format) = args._value_of("output-format") {
57+
config
58+
.cli_unstable()
59+
.fail_if_stable_opt("--output-format", 12103)?;
60+
output_format.parse()?
61+
} else {
62+
OutputFormat::Html
63+
};
64+
5165
let mut compile_opts = args.compile_options_for_single_package(
5266
config,
53-
CompileMode::Doc { deps: false },
67+
CompileMode::Doc {
68+
deps: false,
69+
json: matches!(output_format, OutputFormat::Json),
70+
},
5471
Some(&ws),
5572
ProfileChecking::Custom,
5673
)?;
5774
let target_args = values(args, "args");
75+
5876
compile_opts.target_rustdoc_args = if target_args.is_empty() {
5977
None
6078
} else {
6179
Some(target_args)
6280
};
81+
6382
let doc_opts = DocOptions {
6483
open_result: args.flag("open"),
84+
output_format,
6585
compile_opts,
6686
};
6787
ops::doc(&ws, &doc_opts)?;

src/cargo/core/compiler/build_config.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,10 @@ pub enum CompileMode {
176176
/// allows some de-duping of Units to occur.
177177
Bench,
178178
/// A target that will be documented with `rustdoc`.
179+
179180
/// If `deps` is true, then it will also document all dependencies.
180-
Doc { deps: bool },
181+
/// if `json` is true, the documentation output is in json format.
182+
Doc { deps: bool, json: bool },
181183
/// A target that will be tested with `rustdoc`.
182184
Doctest,
183185
/// An example or library that will be scraped for function calls by `rustdoc`.

src/cargo/core/compiler/context/compilation_files.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,16 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
435435
bcx: &BuildContext<'a, 'cfg>,
436436
) -> CargoResult<Arc<Vec<OutputFile>>> {
437437
let ret = match unit.mode {
438-
CompileMode::Doc { .. } => {
439-
let path = self
440-
.out_dir(unit)
441-
.join(unit.target.crate_name())
442-
.join("index.html");
438+
CompileMode::Doc { json, .. } => {
439+
let path = if json {
440+
self.out_dir(unit)
441+
.join(format!("{}.json", unit.target.crate_name()))
442+
} else {
443+
self.out_dir(unit)
444+
.join(unit.target.crate_name())
445+
.join("index.html")
446+
};
447+
443448
vec![OutputFile {
444449
path,
445450
hardlink: None,

src/cargo/core/compiler/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ fn prepare_rustdoc(cx: &Context<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuil
762762
build_deps_args(&mut rustdoc, cx, unit)?;
763763
rustdoc::add_root_urls(cx, unit, &mut rustdoc)?;
764764

765+
rustdoc::add_output_format(cx, unit, &mut rustdoc)?;
766+
765767
rustdoc.args(bcx.rustdocflags_args(unit));
766768

767769
if !crate_version_flag_already_present(&rustdoc) {

src/cargo/core/compiler/rustdoc.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use std::fmt;
1111
use std::hash;
1212
use url::Url;
1313

14+
use super::CompileMode;
15+
1416
const DOCS_RS_URL: &'static str = "https://docs.rs/";
1517

1618
/// Mode used for `std`. This is for unstable feature [`-Zrustdoc-map`][1].
@@ -204,6 +206,29 @@ pub fn add_root_urls(
204206
Ok(())
205207
}
206208

209+
/// Adds unstable flag [`--output-format`][1] to the given `rustdoc`
210+
/// invocation. This is for unstable feature [`-Zunstable-features`].
211+
///
212+
/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html?highlight=output-format#-w--output-format-output-format
213+
pub fn add_output_format(
214+
cx: &Context<'_, '_>,
215+
unit: &Unit,
216+
rustdoc: &mut ProcessBuilder,
217+
) -> CargoResult<()> {
218+
let config = cx.bcx.config;
219+
if !config.cli_unstable().unstable_options {
220+
tracing::debug!("`unstable-options` is ignored, required -Zunstable-options flag");
221+
return Ok(());
222+
}
223+
224+
if let CompileMode::Doc { json: true, .. } = unit.mode {
225+
rustdoc.arg("-Zunstable-options");
226+
rustdoc.arg("--output-format=json");
227+
}
228+
229+
Ok(())
230+
}
231+
207232
/// Indicates whether a target should have examples scraped from it by rustdoc.
208233
/// Configured within Cargo.toml and only for unstable feature
209234
/// [`-Zrustdoc-scrape-examples`][1].

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ fn compute_deps_doc(
627627
)?;
628628
ret.push(lib_unit_dep);
629629
if dep_lib.documented() {
630-
if let CompileMode::Doc { deps: true } = unit.mode {
630+
if let CompileMode::Doc { deps: true, .. } = unit.mode {
631631
// Document this lib as well.
632632
let doc_unit_dep = new_unit_dep(
633633
state,

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ pub fn create_bcx<'a, 'cfg>(
420420

421421
// TODO: In theory, Cargo should also dedupe the roots, but I'm uncertain
422422
// what heuristics to use in that case.
423-
if build_config.mode == (CompileMode::Doc { deps: true }) {
423+
if matches!(build_config.mode, CompileMode::Doc { deps: true, .. }) {
424424
remove_duplicate_doc(build_config, &units, &mut unit_graph);
425425
}
426426

src/cargo/ops/cargo_doc.rs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,50 @@ use crate::core::{Shell, Workspace};
22
use crate::ops;
33
use crate::util::config::{Config, PathAndArgs};
44
use crate::util::CargoResult;
5+
use anyhow::{bail, Error};
56
use std::path::Path;
67
use std::path::PathBuf;
78
use std::process::Command;
9+
use std::str::FromStr;
10+
11+
/// Format of rustdoc [`--output-format`][1].
12+
///
13+
/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#-w--output-format-output-format
14+
#[derive(Debug, Default, Clone)]
15+
pub enum OutputFormat {
16+
#[default]
17+
Html,
18+
Json,
19+
}
20+
21+
impl OutputFormat {
22+
pub const POSSIBLE_VALUES: [&'static str; 2] = ["html", "json"];
23+
}
24+
25+
impl FromStr for OutputFormat {
26+
// bail! error instead of string error like impl FromStr for Edition {
27+
type Err = Error;
28+
29+
fn from_str(s: &str) -> Result<Self, Self::Err> {
30+
match s {
31+
"json" => Ok(OutputFormat::Json),
32+
"html" => Ok(OutputFormat::Html),
33+
_ => bail!(
34+
"supported values for --output-format are `json` and `html`, \
35+
but `{}` is unknown",
36+
s
37+
),
38+
}
39+
}
40+
}
841

942
/// Strongly typed options for the `cargo doc` command.
1043
#[derive(Debug)]
1144
pub struct DocOptions {
1245
/// Whether to attempt to open the browser after compiling the docs
1346
pub open_result: bool,
47+
/// Same as `rustdoc --output-format`
48+
pub output_format: OutputFormat,
1449
/// Options to pass through to the compiler
1550
pub compile_opts: ops::CompileOptions,
1651
}
@@ -25,10 +60,18 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions) -> CargoResult<()> {
2560
.get(0)
2661
.ok_or_else(|| anyhow::anyhow!("no crates with documentation"))?;
2762
let kind = options.compile_opts.build_config.single_requested_kind()?;
28-
let path = compilation.root_output[&kind]
29-
.with_file_name("doc")
30-
.join(&name)
31-
.join("index.html");
63+
64+
let path = if matches!(options.output_format, OutputFormat::Json) {
65+
compilation.root_output[&kind]
66+
.with_file_name("doc")
67+
.join(format!("{}.json", &name))
68+
} else {
69+
compilation.root_output[&kind]
70+
.with_file_name("doc")
71+
.join(&name)
72+
.join("index.html")
73+
};
74+
3275
if path.exists() {
3376
let config_browser = {
3477
let cfg: Option<PathAndArgs> = ws.config().get("doc.browser")?;

src/cargo/ops/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub use self::cargo_compile::{
55
compile, compile_with_exec, compile_ws, create_bcx, print, resolve_all_features, CompileOptions,
66
};
77
pub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages};
8-
pub use self::cargo_doc::{doc, DocOptions};
8+
pub use self::cargo_doc::{doc, DocOptions, OutputFormat};
99
pub use self::cargo_fetch::{fetch, FetchOptions};
1010
pub use self::cargo_generate_lockfile::generate_lockfile;
1111
pub use self::cargo_generate_lockfile::update_lockfile;

src/doc/man/cargo-rustdoc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ if its name is the same as the lib target. Binaries are skipped if they have
102102
{{#options}}
103103
{{> options-jobs }}
104104
{{> options-keep-going }}
105+
{{> options-output-format }}
105106
{{/options}}
106107

107108
{{> section-environment }}

src/doc/man/generated_txt/cargo-rustdoc.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,18 @@ OPTIONS
327327
--keep-going would definitely run both builds, even if the one run
328328
first fails.
329329

330+
--output-format
331+
The output type for the documentation emitted. Valid values:
332+
333+
o html (default): Emit the documentation in HTML format.
334+
335+
o json: Emit the documentation in the experimental JSON format
336+
<https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types>.
337+
338+
This option is only available on the nightly channel
339+
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
340+
requires the -Z unstable-options flag to enable.
341+
330342
ENVIRONMENT
331343
See the reference
332344
<https://doc.rust-lang.org/cargo/reference/environment-variables.html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{{#option "`--output-format`"}}
2+
The output type for the documentation emitted. Valid values:
3+
4+
* `html` (default): Emit the documentation in HTML format.
5+
* `json`: Emit the documentation in the [experimental JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types).
6+
7+
This option is only available on the [nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
8+
and requires the `-Z unstable-options` flag to enable.
9+
{{/option}}

src/doc/src/commands/cargo-rustdoc.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,15 @@ one that succeeds (depending on which one of the two builds Cargo picked to run
371371
first), whereas <code>cargo rustdoc -j1 --keep-going</code> would definitely run both
372372
builds, even if the one run first fails.</dd>
373373

374+
<dt class="option-term" id="option-cargo-rustdoc---output-format"><a class="option-anchor" href="#option-cargo-rustdoc---output-format"></a><code>--output-format</code></dt>
375+
<dd class="option-desc">The output type for the documentation emitted. Valid values:</p>
376+
<ul>
377+
<li><code>html</code> (default): Emit the documentation in HTML format.</li>
378+
<li><code>json</code>: Emit the documentation in the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types">experimental JSON format</a>.</li>
379+
</ul>
380+
<p>This option is only available on the <a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
381+
and requires the <code>-Z unstable-options</code> flag to enable.</dd>
382+
374383
</dl>
375384

376385
## ENVIRONMENT

src/etc/man/cargo-rustdoc.1

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,22 @@ one that succeeds (depending on which one of the two builds Cargo picked to run
395395
first), whereas \fBcargo rustdoc \-j1 \-\-keep\-going\fR would definitely run both
396396
builds, even if the one run first fails.
397397
.RE
398+
.sp
399+
\fB\-\-output\-format\fR
400+
.RS 4
401+
The output type for the documentation emitted. Valid values:
402+
.sp
403+
.RS 4
404+
\h'-04'\(bu\h'+02'\fBhtml\fR (default): Emit the documentation in HTML format.
405+
.RE
406+
.sp
407+
.RS 4
408+
\h'-04'\(bu\h'+02'\fBjson\fR: Emit the documentation in the \fIexperimental JSON format\fR <https://doc.rust\-lang.org/nightly/nightly\-rustc/rustdoc_json_types>\&.
409+
.RE
410+
.sp
411+
This option is only available on the \fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
412+
and requires the \fB\-Z unstable\-options\fR flag to enable.
413+
.RE
398414
.SH "ENVIRONMENT"
399415
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
400416
details on environment variables that Cargo reads.

tests/testsuite/cargo_rustdoc/help/stdout.log

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Options:
99
--open Opens the docs in a browser after the operation
1010
--ignore-rust-version Ignore `rust-version` specification in packages
1111
--message-format <FMT> Error format
12+
--output-format <FMT> The output type to write (unstable) [possible values: html, json]
1213
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
1314
-q, --quiet Do not print cargo log messages
1415
--color <WHEN> Coloring: auto, always, never

0 commit comments

Comments
 (0)