From 937285430bb38b22d4e803c3585a5160fe5bf61b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 1 Nov 2021 16:30:27 +0100 Subject: [PATCH] Add --check option for cargo doc --- src/bin/cargo/commands/doc.rs | 9 +++++++++ src/cargo/core/compiler/mod.rs | 12 ++++++++++-- src/cargo/ops/cargo_compile.rs | 12 ++++++++++++ src/cargo/ops/cargo_package.rs | 1 + src/cargo/util/command_prelude.rs | 1 + src/doc/src/reference/unstable.md | 6 ++++++ tests/testsuite/doc.rs | 32 +++++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/bin/cargo/commands/doc.rs b/src/bin/cargo/commands/doc.rs index 875cfcfcc46..2adba0d4c19 100644 --- a/src/bin/cargo/commands/doc.rs +++ b/src/bin/cargo/commands/doc.rs @@ -19,6 +19,10 @@ pub fn cli() -> App { ) .arg(opt("no-deps", "Don't build documentation for dependencies")) .arg(opt("document-private-items", "Document private items")) + .arg(opt( + "check", + "Run rustdoc checks and report errors, but don't build documentation", + )) .arg_jobs() .arg_targets_lib_bin_example( "Document only this package's library", @@ -47,6 +51,11 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let mut compile_opts = args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?; compile_opts.rustdoc_document_private_items = args.is_present("document-private-items"); + compile_opts.rustdoc_check = args.is_present("check"); + + if compile_opts.rustdoc_check { + config.cli_unstable().fail_if_stable_opt("--check", 10025)?; + } let doc_opts = DocOptions { open_result: args.is_present("open"), diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 2f58b60abeb..89b685a24a4 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -629,12 +629,20 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { } let doc_dir = cx.files().out_dir(unit); + let rustdoc_check = cx + .bcx + .extra_args_for(unit) + .map(|a| a.iter().any(|c| c == "--check")) + .unwrap_or(false); + // Create the documentation directory ahead of time as rustdoc currently has // a bug where concurrent invocations will race to create this directory if // it doesn't already exist. - paths::create_dir_all(&doc_dir)?; + if rustdoc_check { + paths::create_dir_all(&doc_dir)?; - rustdoc.arg("-o").arg(&doc_dir); + rustdoc.arg("-o").arg(&doc_dir); + } for feat in &unit.features { rustdoc.arg("--cfg").arg(&format!("feature=\"{}\"", feat)); diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 392cef74085..9d52e0b9717 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -79,6 +79,9 @@ pub struct CompileOptions { /// Whether the build process should check the minimum Rust version /// defined in the cargo metadata for a crate. pub honor_rust_version: bool, + /// Whether the `--check` flags was specified and should be forwarded to + /// `rustdoc`. + pub rustdoc_check: bool, } impl<'a> CompileOptions { @@ -95,6 +98,7 @@ impl<'a> CompileOptions { local_rustdoc_args: None, rustdoc_document_private_items: false, honor_rust_version: true, + rustdoc_check: false, }) } } @@ -335,6 +339,7 @@ pub fn create_bcx<'a, 'cfg>( ref local_rustdoc_args, rustdoc_document_private_items, honor_rust_version, + rustdoc_check, } = *options; let config = ws.config(); @@ -634,6 +639,13 @@ pub fn create_bcx<'a, 'cfg>( args.push("--document-private-items".into()); extra_args = Some(args); } + // Add `--check` rustdoc flag if requested. + if rustdoc_check { + let mut args = extra_args.take().unwrap_or_default(); + args.push("-Zunstable-options".into()); + args.push("--check".into()); + extra_args = Some(args); + } if let Some(args) = extra_args { extra_compiler_args diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 48477ea25e0..e2c691e552e 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -766,6 +766,7 @@ fn run_verify( local_rustdoc_args: None, rustdoc_document_private_items: false, honor_rust_version: true, + rustdoc_check: false, }, &exec, )?; diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index d0cf17824b1..7b1a0b97152 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -545,6 +545,7 @@ pub trait ArgMatchesExt { local_rustdoc_args: None, rustdoc_document_private_items: false, honor_rust_version: !self._is_present("ignore-rust-version"), + rustdoc_check: false, }; if let Some(ws) = workspace { diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 19160662376..52d81b8f6f6 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1398,3 +1398,9 @@ For instance: ``` cargo doc -Z unstable-options -Z rustdoc-scrape-examples=examples ``` + +### check + +* Tracking Issue: [#10025](https://github.com/rust-lang/cargo/issues/10025) + +The `--check` argument runs Rustdoc checks and report errors, but doesn't build documentation. diff --git a/tests/testsuite/doc.rs b/tests/testsuite/doc.rs index 9e7c6e04f2f..4b082e98a7f 100644 --- a/tests/testsuite/doc.rs +++ b/tests/testsuite/doc.rs @@ -2297,3 +2297,35 @@ fn scrape_examples_complex_reverse_dependencies() { .masquerade_as_nightly_cargo() .run(); } + +#[cargo_test] +fn doc_check() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "checker" + version = "0.0.1" + authors = [] + "#, + ) + .file( + "src/lib.rs", + r#" + #![warn(rustdoc::all)] + + pub struct Foo; + "#, + ) + .build(); + p.cargo("doc -Zunstable-options --check") + .masquerade_as_nightly_cargo() + .with_stderr_contains("warning: no documentation found for this crate's top-level module") + .with_stderr_contains("warning: missing code example in this documentation") + .run(); + assert!( + !p.root().join("target/doc").exists() + || !p.root().join("target/doc/checker/index.html").exists() + ); +}