diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 4a65a9f431a..dbb67345ba0 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -24,7 +24,7 @@ use crate::html; use crate::html::markdown::IdMap; use crate::html::static_files; use crate::opts; -use crate::passes::{self, DefaultPassOption}; +use crate::passes::{self, Condition, DefaultPassOption}; use crate::theme; /// Configuration options for rustdoc. @@ -98,6 +98,10 @@ pub struct Options { /// /// Be aware: This option can come both from the CLI and from crate attributes! pub default_passes: DefaultPassOption, + /// Document items that have lower than `pub` visibility. + pub document_private: bool, + /// Document items that have `doc(hidden)`. + pub document_hidden: bool, /// Any passes manually selected by the user. /// /// Be aware: This option can come both from the CLI and from crate attributes! @@ -146,6 +150,8 @@ impl fmt::Debug for Options { .field("test_args", &self.test_args) .field("persist_doctests", &self.persist_doctests) .field("default_passes", &self.default_passes) + .field("document_private", &self.document_private) + .field("document_hidden", &self.document_hidden) .field("manual_passes", &self.manual_passes) .field("display_warnings", &self.display_warnings) .field("show_coverage", &self.show_coverage) @@ -240,22 +246,26 @@ impl Options { println!("{:>20} - {}", pass.name, pass.description); } println!("\nDefault passes for rustdoc:"); - for pass in passes::DEFAULT_PASSES { - println!("{:>20}", pass.name); - } - println!("\nPasses run with `--document-private-items`:"); - for pass in passes::DEFAULT_PRIVATE_PASSES { - println!("{:>20}", pass.name); + for p in passes::DEFAULT_PASSES { + print!("{:>20}", p.pass.name); + println_condition(p.condition); } if nightly_options::is_nightly_build() { println!("\nPasses run with `--show-coverage`:"); - for pass in passes::DEFAULT_COVERAGE_PASSES { - println!("{:>20}", pass.name); + for p in passes::COVERAGE_PASSES { + print!("{:>20}", p.pass.name); + println_condition(p.condition); } - println!("\nPasses run with `--show-coverage --document-private-items`:"); - for pass in passes::PRIVATE_COVERAGE_PASSES { - println!("{:>20}", pass.name); + } + + fn println_condition(condition: Condition) { + use Condition::*; + match condition { + Always => println!(), + WhenDocumentPrivate => println!(" (when --document-private-items)"), + WhenNotDocumentPrivate => println!(" (when not --document-private-items)"), + WhenNotDocumentHidden => println!(" (when not --document-hidden-items)"), } } @@ -449,16 +459,11 @@ impl Options { }); let show_coverage = matches.opt_present("show-coverage"); - let document_private = matches.opt_present("document-private-items"); let default_passes = if matches.opt_present("no-defaults") { passes::DefaultPassOption::None - } else if show_coverage && document_private { - passes::DefaultPassOption::PrivateCoverage } else if show_coverage { passes::DefaultPassOption::Coverage - } else if document_private { - passes::DefaultPassOption::Private } else { passes::DefaultPassOption::Default }; @@ -497,6 +502,8 @@ impl Options { let runtool = matches.opt_str("runtool"); let runtool_args = matches.opt_strs("runtool-arg"); let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); + let document_private = matches.opt_present("document-private-items"); + let document_hidden = matches.opt_present("document-hidden-items"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -523,6 +530,8 @@ impl Options { should_test, test_args, default_passes, + document_private, + document_hidden, manual_passes, display_warnings, show_coverage, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cb22039327e..64c2a28de83 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -33,7 +33,7 @@ use crate::clean::{AttributesExt, MAX_DEF_ID}; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::html::render::RenderInfo; -use crate::passes; +use crate::passes::{self, Condition::*, ConditionalPass}; pub use rustc::session::config::{CodegenOptions, Input, Options}; pub use rustc::session::search_paths::SearchPath; @@ -234,6 +234,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt describe_lints, lint_cap, mut default_passes, + mut document_private, + document_hidden, mut manual_passes, display_warnings, render_options, @@ -470,16 +472,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } if attr.is_word() && name == sym::document_private_items { - if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::Private; - } + document_private = true; } } - let passes = passes::defaults(default_passes).iter().chain( + let passes = passes::defaults(default_passes).iter().copied().chain( manual_passes.into_iter().flat_map(|name| { if let Some(pass) = passes::find_pass(&name) { - Some(pass) + Some(ConditionalPass::always(pass)) } else { error!("unknown pass {}, skipping", name); None @@ -489,9 +489,17 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt info!("Executing passes"); - for pass in passes { - debug!("running pass {}", pass.name); - krate = (pass.pass)(krate, &ctxt); + for p in passes { + let run = match p.condition { + Always => true, + WhenDocumentPrivate => document_private, + WhenNotDocumentPrivate => !document_private, + WhenNotDocumentHidden => !document_hidden, + }; + if run { + debug!("running pass {}", p.pass.name); + krate = (p.pass.run)(krate, &ctxt); + } } ctxt.sess().abort_if_errors(); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 998b28b8807..281e78a692a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -173,6 +173,9 @@ fn opts() -> Vec { stable("document-private-items", |o| { o.optflag("", "document-private-items", "document private items") }), + unstable("document-hidden-items", |o| { + o.optflag("", "document-hidden-items", "document items that have doc(hidden)") + }), stable("test", |o| o.optflag("", "test", "run code examples as tests")), stable("test-args", |o| { o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 803bcc2cfdf..7ed531c9206 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -12,7 +12,7 @@ use std::ops; pub const CALCULATE_DOC_COVERAGE: Pass = Pass { name: "calculate-doc-coverage", - pass: calculate_doc_coverage, + run: calculate_doc_coverage, description: "counts the number of items with and without documentation", }; diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index b568d034d89..476c4a0a9c0 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -13,7 +13,7 @@ use crate::passes::Pass; pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { name: "check-code-block-syntax", - pass: check_code_block_syntax, + run: check_code_block_syntax, description: "validates syntax inside Rust code blocks", }; diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index c6b22883e97..c2185592d14 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -8,7 +8,7 @@ use std::mem::take; pub const COLLAPSE_DOCS: Pass = Pass { name: "collapse-docs", - pass: collapse_docs, + run: collapse_docs, description: "concatenates all document attributes into one document attribute", }; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a8bb40a06b9..26d49cf3485 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -28,7 +28,7 @@ use super::span_of_attrs; pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass { name: "collect-intra-doc-links", - pass: collect_intra_doc_links, + run: collect_intra_doc_links, description: "reads a crate's documentation to resolve intra-doc-links", }; diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 63ad9a66a48..473e683df01 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -9,7 +9,7 @@ use rustc_span::symbol::sym; pub const COLLECT_TRAIT_IMPLS: Pass = Pass { name: "collect-trait-impls", - pass: collect_trait_impls, + run: collect_trait_impls, description: "retrieves trait impls for items in the crate", }; diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 7ac3009d827..6fa226433fc 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -9,6 +9,7 @@ use rustc_span::{InnerSpan, Span, DUMMY_SP}; use std::mem; use std::ops::Range; +use self::Condition::*; use crate::clean::{self, GetDefId, Item}; use crate::core::DocContext; use crate::fold::{DocFolder, StripItem}; @@ -53,10 +54,29 @@ pub use self::calculate_doc_coverage::CALCULATE_DOC_COVERAGE; #[derive(Copy, Clone)] pub struct Pass { pub name: &'static str, - pub pass: fn(clean::Crate, &DocContext<'_>) -> clean::Crate, + pub run: fn(clean::Crate, &DocContext<'_>) -> clean::Crate, pub description: &'static str, } +/// In a list of passes, a pass that may or may not need to be run depending on options. +#[derive(Copy, Clone)] +pub struct ConditionalPass { + pub pass: Pass, + pub condition: Condition, +} + +/// How to decide whether to run a conditional pass. +#[derive(Copy, Clone)] +pub enum Condition { + Always, + /// When `--document-private-items` is passed. + WhenDocumentPrivate, + /// When `--document-private-items` is not passed. + WhenNotDocumentPrivate, + /// When `--document-hidden-items` is not passed. + WhenNotDocumentHidden, +} + /// The full list of passes. pub const PASSES: &[Pass] = &[ CHECK_PRIVATE_ITEMS_DOC_TESTS, @@ -73,63 +93,58 @@ pub const PASSES: &[Pass] = &[ ]; /// The list of passes run by default. -pub const DEFAULT_PASSES: &[Pass] = &[ - COLLECT_TRAIT_IMPLS, - COLLAPSE_DOCS, - UNINDENT_COMMENTS, - CHECK_PRIVATE_ITEMS_DOC_TESTS, - STRIP_HIDDEN, - STRIP_PRIVATE, - COLLECT_INTRA_DOC_LINKS, - CHECK_CODE_BLOCK_SYNTAX, - PROPAGATE_DOC_CFG, -]; - -/// The list of default passes run with `--document-private-items` is passed to rustdoc. -pub const DEFAULT_PRIVATE_PASSES: &[Pass] = &[ - COLLECT_TRAIT_IMPLS, - COLLAPSE_DOCS, - UNINDENT_COMMENTS, - CHECK_PRIVATE_ITEMS_DOC_TESTS, - STRIP_PRIV_IMPORTS, - COLLECT_INTRA_DOC_LINKS, - CHECK_CODE_BLOCK_SYNTAX, - PROPAGATE_DOC_CFG, +pub const DEFAULT_PASSES: &[ConditionalPass] = &[ + ConditionalPass::always(COLLECT_TRAIT_IMPLS), + ConditionalPass::always(COLLAPSE_DOCS), + ConditionalPass::always(UNINDENT_COMMENTS), + ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS), + ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), + ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), + ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate), + ConditionalPass::always(COLLECT_INTRA_DOC_LINKS), + ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX), + ConditionalPass::always(PROPAGATE_DOC_CFG), ]; /// The list of default passes run when `--doc-coverage` is passed to rustdoc. -pub const DEFAULT_COVERAGE_PASSES: &[Pass] = - &[COLLECT_TRAIT_IMPLS, STRIP_HIDDEN, STRIP_PRIVATE, CALCULATE_DOC_COVERAGE]; +pub const COVERAGE_PASSES: &[ConditionalPass] = &[ + ConditionalPass::always(COLLECT_TRAIT_IMPLS), + ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), + ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), + ConditionalPass::always(CALCULATE_DOC_COVERAGE), +]; -/// The list of default passes run when `--doc-coverage --document-private-items` is passed to -/// rustdoc. -pub const PRIVATE_COVERAGE_PASSES: &[Pass] = &[COLLECT_TRAIT_IMPLS, CALCULATE_DOC_COVERAGE]; +impl ConditionalPass { + pub const fn always(pass: Pass) -> Self { + Self::new(pass, Always) + } + + pub const fn new(pass: Pass, condition: Condition) -> Self { + ConditionalPass { pass, condition } + } +} /// A shorthand way to refer to which set of passes to use, based on the presence of -/// `--no-defaults` or `--document-private-items`. +/// `--no-defaults` and `--show-coverage`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum DefaultPassOption { Default, - Private, Coverage, - PrivateCoverage, None, } /// Returns the given default set of passes. -pub fn defaults(default_set: DefaultPassOption) -> &'static [Pass] { +pub fn defaults(default_set: DefaultPassOption) -> &'static [ConditionalPass] { match default_set { DefaultPassOption::Default => DEFAULT_PASSES, - DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES, - DefaultPassOption::Coverage => DEFAULT_COVERAGE_PASSES, - DefaultPassOption::PrivateCoverage => PRIVATE_COVERAGE_PASSES, + DefaultPassOption::Coverage => COVERAGE_PASSES, DefaultPassOption::None => &[], } } /// If the given name matches a known pass, returns its information. -pub fn find_pass(pass_name: &str) -> Option<&'static Pass> { - PASSES.iter().find(|p| p.name == pass_name) +pub fn find_pass(pass_name: &str) -> Option { + PASSES.iter().find(|p| p.name == pass_name).copied() } struct Stripper<'a> { diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs index 23e27270970..aec5a6bd4e2 100644 --- a/src/librustdoc/passes/private_items_doc_tests.rs +++ b/src/librustdoc/passes/private_items_doc_tests.rs @@ -5,7 +5,7 @@ use crate::passes::{look_for_tests, Pass}; pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass { name: "check-private-items-doc-tests", - pass: check_private_items_doc_tests, + run: check_private_items_doc_tests, description: "check private items doc tests", }; diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index a296e73e3b5..64b0c45ba65 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -8,7 +8,7 @@ use crate::passes::Pass; pub const PROPAGATE_DOC_CFG: Pass = Pass { name: "propagate-doc-cfg", - pass: propagate_doc_cfg, + run: propagate_doc_cfg, description: "propagates `#[doc(cfg(...))]` to child items", }; diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 9698ad1d231..47f43958ed5 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -10,7 +10,7 @@ use crate::passes::{ImplStripper, Pass}; pub const STRIP_HIDDEN: Pass = Pass { name: "strip-hidden", - pass: strip_hidden, + run: strip_hidden, description: "strips all doc(hidden) items from the output", }; diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index af34842ad0f..35b26fb8ab0 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -5,7 +5,7 @@ use crate::passes::{ImportStripper, Pass}; pub const STRIP_PRIV_IMPORTS: Pass = Pass { name: "strip-priv-imports", - pass: strip_priv_imports, + run: strip_priv_imports, description: "strips all private import statements (`use`, `extern crate`) from a crate", }; diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 5113afa4840..e0379d7ffe2 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -7,7 +7,7 @@ use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper}; pub const STRIP_PRIVATE: Pass = Pass { name: "strip-private", - pass: strip_private, + run: strip_private, description: "strips all private items from a crate which cannot be seen externally, \ implies strip-priv-imports", }; diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 3212af055ef..d4e09ce47a3 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -12,7 +12,7 @@ mod tests; pub const UNINDENT_COMMENTS: Pass = Pass { name: "unindent-comments", - pass: unindent_comments, + run: unindent_comments, description: "removes excess indentation on comments in order for markdown to like it", }; diff --git a/src/test/rustdoc/issue-46380.rs b/src/test/rustdoc/issue-46380.rs deleted file mode 100644 index 8837a6b463e..00000000000 --- a/src/test/rustdoc/issue-46380.rs +++ /dev/null @@ -1,5 +0,0 @@ -// compile-flags: --document-private-items - -// @has issue_46380/struct.Hidden.html -#[doc(hidden)] -pub struct Hidden; diff --git a/src/test/rustdoc/issue-67851-both.rs b/src/test/rustdoc/issue-67851-both.rs new file mode 100644 index 00000000000..d69b9431734 --- /dev/null +++ b/src/test/rustdoc/issue-67851-both.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zunstable-options --document-private-items --document-hidden-items + +// @has issue_67851_both/struct.Hidden.html +#[doc(hidden)] +pub struct Hidden; + +// @has issue_67851_both/struct.Private.html +struct Private; diff --git a/src/test/rustdoc/issue-67851-hidden.rs b/src/test/rustdoc/issue-67851-hidden.rs new file mode 100644 index 00000000000..8a3cafe4c3d --- /dev/null +++ b/src/test/rustdoc/issue-67851-hidden.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zunstable-options --document-hidden-items + +// @has issue_67851_hidden/struct.Hidden.html +#[doc(hidden)] +pub struct Hidden; + +// @!has issue_67851_hidden/struct.Private.html +struct Private; diff --git a/src/test/rustdoc/issue-67851-neither.rs b/src/test/rustdoc/issue-67851-neither.rs new file mode 100644 index 00000000000..4e3cd832853 --- /dev/null +++ b/src/test/rustdoc/issue-67851-neither.rs @@ -0,0 +1,6 @@ +// @!has issue_67851_neither/struct.Hidden.html +#[doc(hidden)] +pub struct Hidden; + +// @!has issue_67851_neither/struct.Private.html +struct Private; diff --git a/src/test/rustdoc/issue-67851-private.rs b/src/test/rustdoc/issue-67851-private.rs new file mode 100644 index 00000000000..8addc7f3e4b --- /dev/null +++ b/src/test/rustdoc/issue-67851-private.rs @@ -0,0 +1,8 @@ +// compile-flags: --document-private-items + +// @!has issue_67851_private/struct.Hidden.html +#[doc(hidden)] +pub struct Hidden; + +// @has issue_67851_private/struct.Private.html +struct Private;