Skip to content

Commit

Permalink
Add unstable --output-format option to "rustdoc"
Browse files Browse the repository at this point in the history
We achieved this by:
   * Handle `--output-format` argument, accepting `html` or `json`
   * If `json` is passed, we append the following in
   `prepare_rustdoc`:
     	1. `-Zunstable-options`
	2. `--output-format`

Fixes #12103

Signed-off-by: Charalampos Mitrodimas <charmitro@posteo.net>
  • Loading branch information
charmitro committed Jan 11, 2024
1 parent 0c98d6e commit 9276399
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 15 deletions.
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> {
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

0 comments on commit 9276399

Please sign in to comment.