Skip to content

Commit

Permalink
Add unstable "--output-format" option to "doc" & "rustdoc"
Browse files Browse the repository at this point in the history
This commit enables the mimicking of `--output-format` option of
"rustdoc".

We achieved this by:
   * Handle `--output-format` arguments, accepts `html` or `json`.
   * If `--ouput-format=json` we append the following to
     `compile_opts.target_rustc_args`:
     	1. `-Zunstable-commands`
	2. `--output-format`
  • Loading branch information
charmitro committed Jun 11, 2023
1 parent 928b956 commit 3a3bc74
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 6 deletions.
19 changes: 18 additions & 1 deletion src/bin/cargo/commands/doc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::command_prelude::*;

use cargo::ops::{self, DocOptions};
use cargo::ops::{self, DocOptions, OutputFormat};

pub fn cli() -> Command {
subcommand("doc")
Expand Down Expand Up @@ -35,6 +35,7 @@ pub fn cli() -> Command {
.arg_features()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg(opt("output-format", "the output type to write (unstable)").value_name("PATH"))
.arg_manifest_path()
.arg_message_format()
.arg_ignore_rust_version()
Expand All @@ -48,12 +49,28 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let mode = CompileMode::Doc {
deps: !args.flag("no-deps"),
};

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 mut target_args = values(args, "args");
let output_format = args.output_format()?;
if output_format.eq(&OutputFormat::Json) {
if config.cli_unstable().unstable_options {
target_args.push("-Zunstable-options".to_string());
}
target_args.push("--output-format=json".to_string());
}

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
17 changes: 15 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 @@ -35,6 +35,7 @@ pub fn cli() -> Command {
.arg_features()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg(opt("output-format", "the output type to write (unstable)").value_name("PATH"))
.arg_manifest_path()
.arg_message_format()
.arg_unit_graph()
Expand All @@ -51,14 +52,26 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
Some(&ws),
ProfileChecking::Custom,
)?;
let target_args = values(args, "args");
let mut target_args = values(args, "args");

let output_format = args.output_format()?;

if output_format.eq(&OutputFormat::Json) {
if config.cli_unstable().unstable_options {
target_args.push("-Zunstable-options".to_string());
}
target_args.push("--output-format=json".to_string());
}

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
15 changes: 14 additions & 1 deletion src/cargo/ops/cargo_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,33 @@ use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub enum OutputFormat {
#[default]
Html,
Json,
}

/// 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,
}

/// Main method for `cargo doc`.
pub fn doc(ws: &Workspace<'_>, options: &DocOptions) -> CargoResult<()> {
if options.open_result && options.output_format.eq(&OutputFormat::Json) {
anyhow::bail!("\"--open\" is not allowed with \"json\" output format.");
}

let compilation = ops::compile(ws, &options.compile_opts)?;

if options.open_result {
if options.open_result && options.output_format.eq(&OutputFormat::Html) {
let name = &compilation
.root_crate_names
.get(0)
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
19 changes: 18 additions & 1 deletion src/cargo/util/command_prelude.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::core::compiler::{BuildConfig, MessageFormat, TimingOutput};
use crate::core::resolver::CliFeatures;
use crate::core::{Edition, Workspace};
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use crate::ops::{
CompileFilter, CompileOptions, NewOptions, OutputFormat, Packages, VersionControl,
};
use crate::util::important_paths::find_root_manifest_for_wd;
use crate::util::interning::InternedString;
use crate::util::restricted_names::is_glob_pattern;
Expand Down Expand Up @@ -366,6 +368,21 @@ pub trait ArgMatchesExt {
Ok(ws)
}

fn output_format(&self) -> CargoResult<OutputFormat> {
let arg: OutputFormat = match self._value_of("output-format") {
None => OutputFormat::default(),
Some(arg) => match arg {
"html" => OutputFormat::Html,
"json" => OutputFormat::Json,
_ => anyhow::bail!(
"Allowed values are for \"--output-format\" are \"html\" or \"json\""
),
},
};

Ok(arg)
}

fn jobs(&self) -> CargoResult<Option<JobsConfig>> {
let arg = match self._value_of("jobs") {
None => None,
Expand Down
1 change: 1 addition & 0 deletions src/doc/man/cargo-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ and supports common Unix glob patterns.
{{#options}}
{{> options-jobs }}
{{> options-keep-going }}
{{> options-output-format }}
{{/options}}

{{> section-environment }}
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 @@ -100,6 +100,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
3 changes: 3 additions & 0 deletions src/doc/man/generated_txt/cargo-doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ OPTIONS
than aborting the build on the first one that fails to build.
Unstable, requires -Zunstable-options.

--output-format
The output type to write. Unstable, requires -Zunstable-options.

ENVIRONMENT
See the reference
<https://doc.rust-lang.org/cargo/reference/environment-variables.html>
Expand Down
3 changes: 3 additions & 0 deletions src/doc/man/generated_txt/cargo-rustdoc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ OPTIONS
than aborting the build on the first one that fails to build.
Unstable, requires -Zunstable-options.

--output-format
The output type to write. Unstable, requires -Zunstable-options.

ENVIRONMENT
See the reference
<https://doc.rust-lang.org/cargo/reference/environment-variables.html>
Expand Down
4 changes: 4 additions & 0 deletions src/doc/man/includes/options-output-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{#option "`--output-format`"}}
The output type to write.
Unstable, requires `-Zunstable-options`.
{{/option}}
5 changes: 5 additions & 0 deletions src/doc/src/commands/cargo-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ the build on the first one that fails to build. Unstable, requires
<code>-Zunstable-options</code>.</dd>


<dt class="option-term" id="option-cargo-doc---output-format"><a class="option-anchor" href="#option-cargo-doc---output-format"></a><code>--output-format</code></dt>
<dd class="option-desc">The output type to write.
Unstable, requires <code>-Zunstable-options</code>.</dd>


</dl>

## ENVIRONMENT
Expand Down
5 changes: 5 additions & 0 deletions src/doc/src/commands/cargo-rustdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ the build on the first one that fails to build. Unstable, requires
<code>-Zunstable-options</code>.</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 to write.
Unstable, requires <code>-Zunstable-options</code>.</dd>


</dl>

## ENVIRONMENT
Expand Down
6 changes: 6 additions & 0 deletions src/etc/man/cargo-doc.1
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,12 @@ Build as many crates in the dependency graph as possible, rather than aborting
the build on the first one that fails to build. Unstable, requires
\fB\-Zunstable\-options\fR\&.
.RE
.sp
\fB\-\-output\-format\fR
.RS 4
The output type to write.
Unstable, requires \fB\-Zunstable\-options\fR\&.
.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
6 changes: 6 additions & 0 deletions src/etc/man/cargo-rustdoc.1
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,12 @@ Build as many crates in the dependency graph as possible, rather than aborting
the build on the first one that fails to build. Unstable, requires
\fB\-Zunstable\-options\fR\&.
.RE
.sp
\fB\-\-output\-format\fR
.RS 4
The output type to write.
Unstable, requires \fB\-Zunstable\-options\fR\&.
.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
93 changes: 93 additions & 0 deletions tests/testsuite/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,99 @@ fn simple() {
assert!(p.root().join("target/doc/foo/index.html").is_file());
}

#[cargo_test(nightly, reason = "--output-format is unstable")]
fn simple_json() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
build = "build.rs"
"#,
)
.file("build.rs", "fn main() {}")
.file("src/lib.rs", "pub fn foo() {}")
.build();

p.cargo("doc -Z unstable-options --output-format json")
.masquerade_as_nightly_cargo(&["unstable-options"])
.with_stderr(
"\
[..] foo v0.0.1 ([CWD])
[..] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
assert!(p.root().join("target/doc").is_dir());
assert!(p.root().join("target/doc/foo.json").is_file());
}

#[cargo_test(nightly, reason = "--output-format is unstable")]
fn doc_invalid_output_format() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
build = "build.rs"
"#,
)
.file("build.rs", "fn main() {}")
.file("src/lib.rs", "pub fn foo() {}")
.build();

p.cargo("doc -Z unstable-options --output-format pdf")
.masquerade_as_nightly_cargo(&["unstable-options"])
.with_status(101)
.with_stderr(
"\
error: Allowed values are for \"--output-format\" are \"html\" or \"json\"
",
)
.run();
}

#[cargo_test(nightly, reason = "--output-format is unstable")]
fn simple_json_fail() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
build = "build.rs"
"#,
)
.file("build.rs", "fn main() {}")
.file("src/lib.rs", "pub fn foo() {}")
.build();

p.cargo("doc --output-format json")
.with_status(101)
.with_stderr(
"\
[..] foo v0.0.1 ([CWD])
[..] foo v0.0.1 ([CWD])
error: the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)
error: could not document `foo`
Caused by:
process didn't exit successfully: `rustdoc --crate-type lib --crate-name foo src/lib.rs -o [CWD]/target/doc --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --output-format=json -C metadata=[..] -L dependency=[CWD]/target/debug/deps --crate-version 0.0.1` (exit status: 1)
",
)
.run();
}

#[cargo_test]
fn doc_no_libs() {
let p = project()
Expand Down
Loading

0 comments on commit 3a3bc74

Please sign in to comment.