Skip to content

Generating a documentation for tests #130463

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ symbols! {
SyncUnsafeCell,
T,
Target,
TestDescAndFn,
ToOwned,
ToString,
TokenStream,
Expand Down
31 changes: 31 additions & 0 deletions src/doc/rustdoc/src/unstable-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,34 @@ will be split as follows:
"you today?",
]
```

### `--document-tests`: show test items

Using this flag looks like this:

```bash
$ rustdoc src/lib.rs -Z unstable-options --cfg test --document-private-items --document-tests
```

By default, `rustdoc` does not document test items.

```rust
/// by default this test function would not be documented
#[test]
fn test_in_module() {
assert_eq!(2, 1 + 1);
}
/// by default this test module would not be documented
#[cfg(test)]
mod tests {
/// by default this test function would not be documented
#[test]
fn test_in_a_test_module() {
assert_eq!(2, 1 + 1);
}
}
```

Note:
* `--cfg test` must be set because tests are guarded by #[cfg(test)].
* `--document-private-items` is typically required because it is standard practice to keep test items private. By enabling this option, you ensure that private items, including tests, are documented as needed while maintaining their non-public status.
6 changes: 5 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,11 @@ fn clean_fn_or_proc_macro<'tcx>(
None => {
let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
clean_fn_decl_legacy_const_generics(&mut func, attrs);
FunctionItem(func)
if cx.cache.document_tests && cx.cache.tests.contains(&item.owner_id.to_def_id()) {
TestItem(func)
} else {
FunctionItem(func)
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,8 @@ impl Item {
}
ItemKind::FunctionItem(_)
| ItemKind::MethodItem(_, _)
| ItemKind::RequiredMethodItem(_) => {
| ItemKind::RequiredMethodItem(_)
| ItemKind::TestItem(_) => {
let def_id = self.def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
}
Expand Down Expand Up @@ -874,6 +875,7 @@ pub(crate) enum ItemKind {
UnionItem(Union),
EnumItem(Enum),
FunctionItem(Box<Function>),
TestItem(Box<Function>),
ModuleItem(Module),
TypeAliasItem(Box<TypeAlias>),
StaticItem(Static),
Expand Down Expand Up @@ -934,6 +936,7 @@ impl ItemKind {
ExternCrateItem { .. }
| ImportItem(_)
| FunctionItem(_)
| TestItem(_)
| TypeAliasItem(_)
| StaticItem(_)
| ConstantItem(_)
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/types/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn should_not_trim() {
fn is_same_generic() {
use crate::clean::types::{PrimitiveType, Type};
use crate::formats::cache::Cache;
let cache = Cache::new(false, false);
let cache = Cache::new(false, false, false);
let generic = Type::Generic(rustc_span::symbol::sym::Any);
let unit = Type::Primitive(PrimitiveType::Unit);
assert!(!generic.is_doc_subtype_of(&unit, &cache));
Expand Down
4 changes: 4 additions & 0 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ pub(crate) struct RenderOptions {
pub(crate) document_private: bool,
/// Document items that have `doc(hidden)`.
pub(crate) document_hidden: bool,
/// Document tests.
pub(crate) document_tests: bool,
/// If `true`, generate a JSON file in the crate folder instead of HTML redirection files.
pub(crate) generate_redirect_map: bool,
/// Show the memory layout of types in the docs.
Expand Down Expand Up @@ -806,6 +808,7 @@ impl Options {
}

let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
let document_tests = matches.opt_present("document-tests");
let with_examples = matches.opt_strs("with-examples");
let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
let doctest_compilation_args = matches.opt_strs("doctest-compilation-args");
Expand Down Expand Up @@ -880,6 +883,7 @@ impl Options {
markdown_playground_url,
document_private,
document_hidden,
document_tests,
generate_redirect_map,
show_type_layout,
unstable_features,
Expand Down
9 changes: 7 additions & 2 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ pub(crate) fn create_config(
} else {
ResolveDocLinks::Exported
};
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false)
|| (cfgs.iter().any(|cfg| cfg == "test") && render_options.document_tests);
// plays with error output here!
let sessopts = config::Options {
sysroot,
Expand Down Expand Up @@ -369,7 +370,11 @@ pub(crate) fn run_global_ctxt(
impl_trait_bounds: Default::default(),
generated_synthetics: Default::default(),
auto_traits,
cache: Cache::new(render_options.document_private, render_options.document_hidden),
cache: Cache::new(
render_options.document_private,
render_options.document_hidden,
render_options.document_tests,
),
inlined: FxHashSet::default(),
output_format,
render_options,
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub(crate) trait DocFolder: Sized {
ExternCrateItem { src: _ }
| ImportItem(_)
| FunctionItem(_)
| TestItem(_)
| StaticItem(_)
| ConstantItem(..)
| TraitAliasItem(_)
Expand Down
10 changes: 8 additions & 2 deletions src/librustdoc/formats/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ pub(crate) struct Cache {
/// Whether to document hidden items.
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
pub(crate) document_hidden: bool,
/// Whether to document tests.
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
pub(crate) document_tests: bool,
/// DefIds of all functions which are tests.
pub(crate) tests: FxHashSet<DefId>,

/// Crates marked with [`#[doc(masked)]`][doc_masked].
///
Expand Down Expand Up @@ -144,8 +149,8 @@ struct CacheBuilder<'a, 'tcx> {
}

impl Cache {
pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self {
Cache { document_private, document_hidden, ..Cache::default() }
pub(crate) fn new(document_private: bool, document_hidden: bool, document_tests: bool) -> Self {
Cache { document_private, document_hidden, document_tests, ..Cache::default() }
}

/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
Expand Down Expand Up @@ -302,6 +307,7 @@ impl DocFolder for CacheBuilder<'_, '_> {
| clean::TraitItem(..)
| clean::TraitAliasItem(..)
| clean::FunctionItem(..)
| clean::TestItem(..)
| clean::ModuleItem(..)
| clean::ForeignFunctionItem(..)
| clean::ForeignStaticItem(..)
Expand Down
3 changes: 3 additions & 0 deletions src/librustdoc/formats/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub(crate) enum ItemType {
TraitAlias = 25,
// This number is reserved for use in JavaScript
// Generic = 26,
Test = 27,
}

impl Serialize for ItemType {
Expand All @@ -83,6 +84,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::UnionItem(..) => ItemType::Union,
clean::EnumItem(..) => ItemType::Enum,
clean::FunctionItem(..) => ItemType::Function,
clean::TestItem(..) => ItemType::Test,
clean::TypeAliasItem(..) => ItemType::TypeAlias,
clean::StaticItem(..) => ItemType::Static,
clean::ConstantItem(..) => ItemType::Constant,
Expand Down Expand Up @@ -178,6 +180,7 @@ impl ItemType {
ItemType::Union => "union",
ItemType::Enum => "enum",
ItemType::Function => "fn",
ItemType::Test => "test",
ItemType::TypeAlias => "type",
ItemType::Static => "static",
ItemType::Trait => "trait",
Expand Down
15 changes: 15 additions & 0 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ struct AllTypes {
attribute_macros: FxIndexSet<ItemEntry>,
derive_macros: FxIndexSet<ItemEntry>,
trait_aliases: FxIndexSet<ItemEntry>,
tests: FxIndexSet<ItemEntry>,
}

impl AllTypes {
Expand All @@ -360,6 +361,7 @@ impl AllTypes {
attribute_macros: new_set(100),
derive_macros: new_set(100),
trait_aliases: new_set(100),
tests: new_set(100),
}
}

Expand All @@ -385,6 +387,7 @@ impl AllTypes {
}
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)),
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)),
ItemType::Test => self.tests.insert(ItemEntry::new(new_url, name)),
_ => true,
};
}
Expand Down Expand Up @@ -414,6 +417,9 @@ impl AllTypes {
if !self.functions.is_empty() {
sections.insert(ItemSection::Functions);
}
if !self.tests.is_empty() {
sections.insert(ItemSection::Tests);
}
if !self.type_aliases.is_empty() {
sections.insert(ItemSection::TypeAliases);
}
Expand All @@ -432,6 +438,9 @@ impl AllTypes {
if !self.trait_aliases.is_empty() {
sections.insert(ItemSection::TraitAliases);
}
if !self.tests.is_empty() {
sections.insert(ItemSection::Tests);
}

sections
}
Expand Down Expand Up @@ -470,6 +479,7 @@ impl AllTypes {
print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros);
print_entries(f, &self.derive_macros, ItemSection::DeriveMacros);
print_entries(f, &self.functions, ItemSection::Functions);
print_entries(f, &self.tests, ItemSection::Tests);
print_entries(f, &self.type_aliases, ItemSection::TypeAliases);
print_entries(f, &self.trait_aliases, ItemSection::TraitAliases);
print_entries(f, &self.statics, ItemSection::Statics);
Expand Down Expand Up @@ -2370,6 +2380,7 @@ pub(crate) enum ItemSection {
Statics,
Traits,
Functions,
Tests,
TypeAliases,
Unions,
Implementations,
Expand Down Expand Up @@ -2402,6 +2413,7 @@ impl ItemSection {
Statics,
Traits,
Functions,
Tests,
TypeAliases,
Unions,
Implementations,
Expand All @@ -2427,6 +2439,7 @@ impl ItemSection {
Self::Unions => "unions",
Self::Enums => "enums",
Self::Functions => "functions",
Self::Tests => "tests",
Self::TypeAliases => "types",
Self::Statics => "statics",
Self::Constants => "constants",
Expand Down Expand Up @@ -2456,6 +2469,7 @@ impl ItemSection {
Self::Unions => "Unions",
Self::Enums => "Enums",
Self::Functions => "Functions",
Self::Tests => "Test Cases",
Self::TypeAliases => "Type Aliases",
Self::Statics => "Statics",
Self::Constants => "Constants",
Expand Down Expand Up @@ -2486,6 +2500,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
ItemType::Union => ItemSection::Unions,
ItemType::Enum => ItemSection::Enums,
ItemType::Function => ItemSection::Functions,
ItemType::Test => ItemSection::Tests,
ItemType::TypeAlias => ItemSection::TypeAliases,
ItemType::Static => ItemSection::Statics,
ItemType::Constant => ItemSection::Constants,
Expand Down
4 changes: 3 additions & 1 deletion src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
}
}
clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ",
clean::TestItem(..) => "Test ",
clean::TraitItem(..) => "Trait ",
clean::StructItem(..) => "Struct ",
clean::UnionItem(..) => "Union ",
Expand Down Expand Up @@ -228,7 +229,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
clean::ModuleItem(m) => {
write!(buf, "{}", item_module(cx, item, &m.items))
}
clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) => {
clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) | clean::TestItem(f) => {
write!(buf, "{}", item_function(cx, item, f))
}
clean::TraitItem(t) => write!(buf, "{}", item_trait(cx, item, t)),
Expand Down Expand Up @@ -326,6 +327,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
ItemType::Static => 8,
ItemType::Trait => 9,
ItemType::Function => 10,
ItemType::Test => 11,
ItemType::TypeAlias => 12,
ItemType::Union => 13,
_ => 14 + ty as u8,
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ function preLoadCss(cssUrl) {
block("static", "static", "Statics");
block("trait", "traits", "Traits");
block("fn", "functions", "Functions");
block("test", "tests", "Tests");
block("type", "types", "Type Aliases");
block("union", "unions", "Unions");
// No point, because these items don't appear in modules
Expand Down
6 changes: 4 additions & 2 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)),
EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)),
VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)),
FunctionItem(f) => ItemEnum::Function(from_function(*f, true, header.unwrap(), renderer)),
FunctionItem(f) | TestItem(f) => {
ItemEnum::Function(from_function(*f, true, header.unwrap(), renderer))
}
ForeignFunctionItem(f, _) => {
ItemEnum::Function(from_function(*f, false, header.unwrap(), renderer))
}
Expand Down Expand Up @@ -820,7 +822,7 @@ impl FromClean<ItemType> for ItemKind {
Struct => ItemKind::Struct,
Union => ItemKind::Union,
Enum => ItemKind::Enum,
Function | TyMethod | Method => ItemKind::Function,
Function | Test | TyMethod | Method => ItemKind::Function,
TypeAlias => ItemKind::TypeAlias,
Static => ItemKind::Static,
Constant => ItemKind::Constant,
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ fn opts() -> Vec<RustcOptGroup> {
"removed, see issue #44136 <https://github.com./rust-lang/rust/issues/44136> for more information",
"[rust]",
),
opt(Unstable, FlagMulti, "", "document-tests", "Generate documentation for tests", ""),
]
}

Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/passes/propagate_stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl DocFolder for StabilityPropagator<'_, '_> {
| ItemKind::UnionItem(..)
| ItemKind::EnumItem(..)
| ItemKind::FunctionItem(..)
| ItemKind::TestItem(..)
| ItemKind::ModuleItem(..)
| ItemKind::TypeAliasItem(..)
| ItemKind::StaticItem(..)
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/passes/stripper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl DocFolder for Stripper<'_, '_> {
| clean::EnumItem(..)
| clean::TraitItem(..)
| clean::FunctionItem(..)
| clean::TestItem(..)
| clean::VariantItem(..)
| clean::ForeignFunctionItem(..)
| clean::ForeignStaticItem(..)
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
ExternCrateItem { src: _ }
| ImportItem(_)
| FunctionItem(_)
| TestItem(_)
| TypeAliasItem(_)
| StaticItem(_)
| ConstantItem(..)
Expand Down
Loading
Loading