Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unstable --output-format option to cargo rustdoc #12252

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bin/cargo/commands/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
let mode = CompileMode::Doc {
deps: !args.flag("no-deps"),
json: false,
};
let mut compile_opts =
args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?;
compile_opts.rustdoc_document_private_items = args.flag("document-private-items");

let doc_opts = DocOptions {
open_result: args.flag("open"),
output_format: ops::OutputFormat::Html,
compile_opts,
};
ops::doc(&ws, &doc_opts)?;
Expand Down
24 changes: 22 additions & 2 deletions src/bin/cargo/commands/rustdoc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cargo::ops::{self, DocOptions};
use cargo::ops::{self, DocOptions, OutputFormat};

use crate::command_prelude::*;

Expand Down Expand Up @@ -38,6 +38,11 @@ pub fn cli() -> Command {
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg(
opt("output-format", "The output type to write (unstable)")
.value_name("FMT")
.value_parser(OutputFormat::POSSIBLE_VALUES),
)
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
Expand All @@ -48,20 +53,35 @@ pub fn cli() -> Command {

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
let output_format = if let Some(output_format) = args._value_of("output-format") {
config
.cli_unstable()
.fail_if_stable_opt("--output-format", 12103)?;
output_format.parse()?
} else {
OutputFormat::Html
};

let mut compile_opts = args.compile_options_for_single_package(
config,
CompileMode::Doc { deps: false },
CompileMode::Doc {
deps: false,
json: matches!(output_format, OutputFormat::Json),
},
Some(&ws),
ProfileChecking::Custom,
)?;
let target_args = values(args, "args");

compile_opts.target_rustdoc_args = if target_args.is_empty() {
None
} else {
Some(target_args)
};

let doc_opts = DocOptions {
open_result: args.flag("open"),
output_format,
compile_opts,
};
ops::doc(&ws, &doc_opts)?;
Expand Down
4 changes: 3 additions & 1 deletion src/cargo/core/compiler/build_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ pub enum CompileMode {
/// allows some de-duping of Units to occur.
Bench,
/// A target that will be documented with `rustdoc`.

/// If `deps` is true, then it will also document all dependencies.
Doc { deps: bool },
/// if `json` is true, the documentation output is in json format.
Doc { deps: bool, json: bool },
/// A target that will be tested with `rustdoc`.
Doctest,
/// An example or library that will be scraped for function calls by `rustdoc`.
Expand Down
15 changes: 10 additions & 5 deletions src/cargo/core/compiler/context/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,11 +435,16 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
bcx: &BuildContext<'a, 'cfg>,
) -> CargoResult<Arc<Vec<OutputFile>>> {
let ret = match unit.mode {
CompileMode::Doc { .. } => {
let path = self
.out_dir(unit)
.join(unit.target.crate_name())
.join("index.html");
CompileMode::Doc { json, .. } => {
let path = if json {
self.out_dir(unit)
.join(format!("{}.json", unit.target.crate_name()))
} else {
self.out_dir(unit)
.join(unit.target.crate_name())
.join("index.html")
};

vec![OutputFile {
path,
hardlink: None,
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,8 @@ fn prepare_rustdoc(cx: &Context<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuil
build_deps_args(&mut rustdoc, cx, unit)?;
rustdoc::add_root_urls(cx, unit, &mut rustdoc)?;

rustdoc::add_output_format(cx, unit, &mut rustdoc)?;

rustdoc.args(bcx.rustdocflags_args(unit));

if !crate_version_flag_already_present(&rustdoc) {
Expand Down
25 changes: 25 additions & 0 deletions src/cargo/core/compiler/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use std::fmt;
use std::hash;
use url::Url;

use super::CompileMode;

const DOCS_RS_URL: &'static str = "https://docs.rs/";

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

/// Adds unstable flag [`--output-format`][1] to the given `rustdoc`
/// invocation. This is for unstable feature [`-Zunstable-features`].
///
/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html?highlight=output-format#-w--output-format-output-format
pub fn add_output_format(
cx: &Context<'_, '_>,
unit: &Unit,
rustdoc: &mut ProcessBuilder,
) -> CargoResult<()> {
let config = cx.bcx.config;
if !config.cli_unstable().unstable_options {
tracing::debug!("`unstable-options` is ignored, required -Zunstable-options flag");
return Ok(());
}

if let CompileMode::Doc { json: true, .. } = unit.mode {
rustdoc.arg("-Zunstable-options");
rustdoc.arg("--output-format=json");
}

Ok(())
}

/// Indicates whether a target should have examples scraped from it by rustdoc.
/// Configured within Cargo.toml and only for unstable feature
/// [`-Zrustdoc-scrape-examples`][1].
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ fn compute_deps_doc(
)?;
ret.push(lib_unit_dep);
if dep_lib.documented() {
if let CompileMode::Doc { deps: true } = unit.mode {
if let CompileMode::Doc { deps: true, .. } = unit.mode {
// Document this lib as well.
let doc_unit_dep = new_unit_dep(
state,
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ pub fn create_bcx<'a, 'cfg>(

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

Expand Down
51 changes: 47 additions & 4 deletions src/cargo/ops/cargo_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,50 @@ use crate::core::{Shell, Workspace};
use crate::ops;
use crate::util::config::{Config, PathAndArgs};
use crate::util::CargoResult;
use anyhow::{bail, Error};
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;

/// Format of rustdoc [`--output-format`][1].
///
/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#-w--output-format-output-format
#[derive(Debug, Default, Clone)]
pub enum OutputFormat {
#[default]
Html,
Json,
}

impl OutputFormat {
pub const POSSIBLE_VALUES: [&'static str; 2] = ["html", "json"];
}

impl FromStr for OutputFormat {
// bail! error instead of string error like impl FromStr for Edition {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
weihanglo marked this conversation as resolved.
Show resolved Hide resolved
match s {
"json" => Ok(OutputFormat::Json),
"html" => Ok(OutputFormat::Html),
_ => bail!(
"supported values for --output-format are `json` and `html`, \
but `{}` is unknown",
s
),
}
}
}

/// Strongly typed options for the `cargo doc` command.
#[derive(Debug)]
pub struct DocOptions {
/// Whether to attempt to open the browser after compiling the docs
pub open_result: bool,
/// Same as `rustdoc --output-format`
pub output_format: OutputFormat,
/// Options to pass through to the compiler
pub compile_opts: ops::CompileOptions,
}
Expand All @@ -25,10 +60,18 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions) -> CargoResult<()> {
.get(0)
.ok_or_else(|| anyhow::anyhow!("no crates with documentation"))?;
let kind = options.compile_opts.build_config.single_requested_kind()?;
let path = compilation.root_output[&kind]
.with_file_name("doc")
.join(&name)
.join("index.html");

let path = if matches!(options.output_format, OutputFormat::Json) {
compilation.root_output[&kind]
.with_file_name("doc")
.join(format!("{}.json", &name))
} else {
compilation.root_output[&kind]
.with_file_name("doc")
.join(&name)
.join("index.html")
};

if path.exists() {
let config_browser = {
let cfg: Option<PathAndArgs> = ws.config().get("doc.browser")?;
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub use self::cargo_compile::{
compile, compile_with_exec, compile_ws, create_bcx, print, resolve_all_features, CompileOptions,
};
pub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages};
pub use self::cargo_doc::{doc, DocOptions};
pub use self::cargo_doc::{doc, DocOptions, OutputFormat};
pub use self::cargo_fetch::{fetch, FetchOptions};
pub use self::cargo_generate_lockfile::generate_lockfile;
pub use self::cargo_generate_lockfile::update_lockfile;
Expand Down
1 change: 1 addition & 0 deletions src/doc/man/cargo-rustdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ if its name is the same as the lib target. Binaries are skipped if they have
{{#options}}
{{> options-jobs }}
{{> options-keep-going }}
{{> options-output-format }}
{{/options}}

{{> section-environment }}
Expand Down
12 changes: 12 additions & 0 deletions src/doc/man/generated_txt/cargo-rustdoc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,18 @@ OPTIONS
--keep-going would definitely run both builds, even if the one run
first fails.

--output-format
The output type for the documentation emitted. Valid values:

o html (default): Emit the documentation in HTML format.

o json: Emit the documentation in the experimental JSON format
<https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types>.

This option is only available on the nightly channel
<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
requires the -Z unstable-options flag to enable.

ENVIRONMENT
See the reference
<https://doc.rust-lang.org/cargo/reference/environment-variables.html>
Expand Down
9 changes: 9 additions & 0 deletions src/doc/man/includes/options-output-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{#option "`--output-format`"}}
The output type for the documentation emitted. Valid values:

* `html` (default): Emit the documentation in HTML format.
* `json`: Emit the documentation in the [experimental JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types).

This option is only available on the [nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
and requires the `-Z unstable-options` flag to enable.
{{/option}}
9 changes: 9 additions & 0 deletions src/doc/src/commands/cargo-rustdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,15 @@ one that succeeds (depending on which one of the two builds Cargo picked to run
first), whereas <code>cargo rustdoc -j1 --keep-going</code> would definitely run both
builds, even if the one run first fails.</dd>

<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>
<dd class="option-desc">The output type for the documentation emitted. Valid values:</p>
<ul>
<li><code>html</code> (default): Emit the documentation in HTML format.</li>
<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>
</ul>
<p>This option is only available on the <a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
and requires the <code>-Z unstable-options</code> flag to enable.</dd>

</dl>

## ENVIRONMENT
Expand Down
16 changes: 16 additions & 0 deletions src/etc/man/cargo-rustdoc.1
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,22 @@ one that succeeds (depending on which one of the two builds Cargo picked to run
first), whereas \fBcargo rustdoc \-j1 \-\-keep\-going\fR would definitely run both
builds, even if the one run first fails.
.RE
.sp
\fB\-\-output\-format\fR
.RS 4
The output type for the documentation emitted. Valid values:
.sp
.RS 4
\h'-04'\(bu\h'+02'\fBhtml\fR (default): Emit the documentation in HTML format.
.RE
.sp
.RS 4
\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>\&.
.RE
.sp
This option is only available on the \fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
and requires the \fB\-Z unstable\-options\fR flag to enable.
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
details on environment variables that Cargo reads.
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/cargo_rustdoc/help/stdout.log
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Options:
--open Opens the docs in a browser after the operation
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
--output-format <FMT> The output type to write (unstable) [possible values: html, json]
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
-q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
Expand Down
Loading