Skip to content

Commit 14f00fc

Browse files
ifxfrancoislucagladiator
authored andcommitted
Add support to generate documentation for tests
The new option --document-tests is unstable and documented as such. In order to use it is needed to add `--cfg test` and in case the tests are not marked public to add `--document-private-items`. The implementation hide the auto generate main test function and constants.
1 parent 259fdb5 commit 14f00fc

File tree

19 files changed

+139
-15
lines changed

19 files changed

+139
-15
lines changed

Diff for: src/doc/rustdoc/src/unstable-features.md

+31
Original file line numberDiff line numberDiff line change
@@ -830,3 +830,34 @@ will be split as follows:
830830
"you today?",
831831
]
832832
```
833+
834+
### `--document-tests`: show test items
835+
836+
Using this flag looks like this:
837+
838+
```bash
839+
$ rustdoc src/lib.rs -Z unstable-options --cfg test --document-private-items --document-tests
840+
```
841+
842+
By default, `rustdoc` does not document test items.
843+
844+
```rust
845+
/// by default this test function would not be documented
846+
#[test]
847+
fn test_in_module() {
848+
assert_eq!(2, 1 + 1);
849+
}
850+
/// by default this test module would not be documented
851+
#[cfg(test)]
852+
mod tests {
853+
/// by default this test function would not be documented
854+
#[test]
855+
fn test_in_a_test_module() {
856+
assert_eq!(2, 1 + 1);
857+
}
858+
}
859+
```
860+
861+
Note:
862+
* `--cfg test` must be set because tests are guarded by #[cfg(test)].
863+
* `--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.

Diff for: src/librustdoc/clean/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,11 @@ fn clean_fn_or_proc_macro<'tcx>(
10481048
None => {
10491049
let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
10501050
clean_fn_decl_legacy_const_generics(&mut func, attrs);
1051-
FunctionItem(func)
1051+
if cx.cache.document_tests && cx.cache.tests.contains(&item.owner_id.to_def_id()) {
1052+
TestItem(func)
1053+
} else {
1054+
FunctionItem(func)
1055+
}
10521056
}
10531057
}
10541058
}

Diff for: src/librustdoc/clean/types.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,8 @@ impl Item {
697697
}
698698
ItemKind::FunctionItem(_)
699699
| ItemKind::MethodItem(_, _)
700-
| ItemKind::RequiredMethodItem(_) => {
700+
| ItemKind::RequiredMethodItem(_)
701+
| ItemKind::TestItem(_) => {
701702
let def_id = self.def_id().unwrap();
702703
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
703704
}
@@ -874,6 +875,7 @@ pub(crate) enum ItemKind {
874875
UnionItem(Union),
875876
EnumItem(Enum),
876877
FunctionItem(Box<Function>),
878+
TestItem(Box<Function>),
877879
ModuleItem(Module),
878880
TypeAliasItem(Box<TypeAlias>),
879881
StaticItem(Static),
@@ -934,6 +936,7 @@ impl ItemKind {
934936
ExternCrateItem { .. }
935937
| ImportItem(_)
936938
| FunctionItem(_)
939+
| TestItem(_)
937940
| TypeAliasItem(_)
938941
| StaticItem(_)
939942
| ConstantItem(_)

Diff for: src/librustdoc/clean/types/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn should_not_trim() {
7171
fn is_same_generic() {
7272
use crate::clean::types::{PrimitiveType, Type};
7373
use crate::formats::cache::Cache;
74-
let cache = Cache::new(false, false);
74+
let cache = Cache::new(false, false, false);
7575
let generic = Type::Generic(rustc_span::symbol::sym::Any);
7676
let unit = Type::Primitive(PrimitiveType::Unit);
7777
assert!(!generic.is_doc_subtype_of(&unit, &cache));

Diff for: src/librustdoc/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ pub(crate) struct RenderOptions {
283283
pub(crate) document_private: bool,
284284
/// Document items that have `doc(hidden)`.
285285
pub(crate) document_hidden: bool,
286+
/// Document tests.
287+
pub(crate) document_tests: bool,
286288
/// If `true`, generate a JSON file in the crate folder instead of HTML redirection files.
287289
pub(crate) generate_redirect_map: bool,
288290
/// Show the memory layout of types in the docs.
@@ -806,6 +808,7 @@ impl Options {
806808
}
807809

808810
let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
811+
let document_tests = matches.opt_present("document-tests");
809812
let with_examples = matches.opt_strs("with-examples");
810813
let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
811814
let doctest_compilation_args = matches.opt_strs("doctest-compilation-args");
@@ -880,6 +883,7 @@ impl Options {
880883
markdown_playground_url,
881884
document_private,
882885
document_hidden,
886+
document_tests,
883887
generate_redirect_map,
884888
show_type_layout,
885889
unstable_features,

Diff for: src/librustdoc/core.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ pub(crate) fn create_config(
250250
} else {
251251
ResolveDocLinks::Exported
252252
};
253-
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
253+
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false)
254+
|| (cfgs.iter().any(|cfg| cfg == "test") && render_options.document_tests);
254255
// plays with error output here!
255256
let sessopts = config::Options {
256257
sysroot,
@@ -369,7 +370,11 @@ pub(crate) fn run_global_ctxt(
369370
impl_trait_bounds: Default::default(),
370371
generated_synthetics: Default::default(),
371372
auto_traits,
372-
cache: Cache::new(render_options.document_private, render_options.document_hidden),
373+
cache: Cache::new(
374+
render_options.document_private,
375+
render_options.document_hidden,
376+
render_options.document_tests,
377+
),
373378
inlined: FxHashSet::default(),
374379
output_format,
375380
render_options,

Diff for: src/librustdoc/fold.rs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub(crate) trait DocFolder: Sized {
7979
ExternCrateItem { src: _ }
8080
| ImportItem(_)
8181
| FunctionItem(_)
82+
| TestItem(_)
8283
| StaticItem(_)
8384
| ConstantItem(..)
8485
| TraitAliasItem(_)

Diff for: src/librustdoc/formats/cache.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ pub(crate) struct Cache {
9292
/// Whether to document hidden items.
9393
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
9494
pub(crate) document_hidden: bool,
95+
/// Whether to document tests.
96+
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
97+
pub(crate) document_tests: bool,
98+
/// DefIds of all functions which are tests.
99+
pub(crate) tests: FxHashSet<DefId>,
95100

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

146151
impl Cache {
147-
pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self {
148-
Cache { document_private, document_hidden, ..Cache::default() }
152+
pub(crate) fn new(document_private: bool, document_hidden: bool, document_tests: bool) -> Self {
153+
Cache { document_private, document_hidden, document_tests, ..Cache::default() }
149154
}
150155

151156
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
@@ -302,6 +307,7 @@ impl DocFolder for CacheBuilder<'_, '_> {
302307
| clean::TraitItem(..)
303308
| clean::TraitAliasItem(..)
304309
| clean::FunctionItem(..)
310+
| clean::TestItem(..)
305311
| clean::ModuleItem(..)
306312
| clean::ForeignFunctionItem(..)
307313
| clean::ForeignStaticItem(..)

Diff for: src/librustdoc/formats/item_type.rs

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub(crate) enum ItemType {
5757
TraitAlias = 25,
5858
// This number is reserved for use in JavaScript
5959
// Generic = 26,
60+
Test = 27,
6061
}
6162

6263
impl Serialize for ItemType {
@@ -83,6 +84,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
8384
clean::UnionItem(..) => ItemType::Union,
8485
clean::EnumItem(..) => ItemType::Enum,
8586
clean::FunctionItem(..) => ItemType::Function,
87+
clean::TestItem(..) => ItemType::Test,
8688
clean::TypeAliasItem(..) => ItemType::TypeAlias,
8789
clean::StaticItem(..) => ItemType::Static,
8890
clean::ConstantItem(..) => ItemType::Constant,
@@ -178,6 +180,7 @@ impl ItemType {
178180
ItemType::Union => "union",
179181
ItemType::Enum => "enum",
180182
ItemType::Function => "fn",
183+
ItemType::Test => "test",
181184
ItemType::TypeAlias => "type",
182185
ItemType::Static => "static",
183186
ItemType::Trait => "trait",

Diff for: src/librustdoc/html/render/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ struct AllTypes {
341341
attribute_macros: FxIndexSet<ItemEntry>,
342342
derive_macros: FxIndexSet<ItemEntry>,
343343
trait_aliases: FxIndexSet<ItemEntry>,
344+
tests: FxIndexSet<ItemEntry>,
344345
}
345346

346347
impl AllTypes {
@@ -360,6 +361,7 @@ impl AllTypes {
360361
attribute_macros: new_set(100),
361362
derive_macros: new_set(100),
362363
trait_aliases: new_set(100),
364+
tests: new_set(100),
363365
}
364366
}
365367

@@ -385,6 +387,7 @@ impl AllTypes {
385387
}
386388
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)),
387389
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)),
390+
ItemType::Test => self.tests.insert(ItemEntry::new(new_url, name)),
388391
_ => true,
389392
};
390393
}
@@ -414,6 +417,9 @@ impl AllTypes {
414417
if !self.functions.is_empty() {
415418
sections.insert(ItemSection::Functions);
416419
}
420+
if !self.tests.is_empty() {
421+
sections.insert(ItemSection::Tests);
422+
}
417423
if !self.type_aliases.is_empty() {
418424
sections.insert(ItemSection::TypeAliases);
419425
}
@@ -432,6 +438,9 @@ impl AllTypes {
432438
if !self.trait_aliases.is_empty() {
433439
sections.insert(ItemSection::TraitAliases);
434440
}
441+
if !self.tests.is_empty() {
442+
sections.insert(ItemSection::Tests);
443+
}
435444

436445
sections
437446
}
@@ -470,6 +479,7 @@ impl AllTypes {
470479
print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros);
471480
print_entries(f, &self.derive_macros, ItemSection::DeriveMacros);
472481
print_entries(f, &self.functions, ItemSection::Functions);
482+
print_entries(f, &self.tests, ItemSection::Tests);
473483
print_entries(f, &self.type_aliases, ItemSection::TypeAliases);
474484
print_entries(f, &self.trait_aliases, ItemSection::TraitAliases);
475485
print_entries(f, &self.statics, ItemSection::Statics);
@@ -2370,6 +2380,7 @@ pub(crate) enum ItemSection {
23702380
Statics,
23712381
Traits,
23722382
Functions,
2383+
Tests,
23732384
TypeAliases,
23742385
Unions,
23752386
Implementations,
@@ -2402,6 +2413,7 @@ impl ItemSection {
24022413
Statics,
24032414
Traits,
24042415
Functions,
2416+
Tests,
24052417
TypeAliases,
24062418
Unions,
24072419
Implementations,
@@ -2427,6 +2439,7 @@ impl ItemSection {
24272439
Self::Unions => "unions",
24282440
Self::Enums => "enums",
24292441
Self::Functions => "functions",
2442+
Self::Tests => "tests",
24302443
Self::TypeAliases => "types",
24312444
Self::Statics => "statics",
24322445
Self::Constants => "constants",
@@ -2456,6 +2469,7 @@ impl ItemSection {
24562469
Self::Unions => "Unions",
24572470
Self::Enums => "Enums",
24582471
Self::Functions => "Functions",
2472+
Self::Tests => "Tests",
24592473
Self::TypeAliases => "Type Aliases",
24602474
Self::Statics => "Statics",
24612475
Self::Constants => "Constants",
@@ -2486,6 +2500,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
24862500
ItemType::Union => ItemSection::Unions,
24872501
ItemType::Enum => ItemSection::Enums,
24882502
ItemType::Function => ItemSection::Functions,
2503+
ItemType::Test => ItemSection::Tests,
24892504
ItemType::TypeAlias => ItemSection::TypeAliases,
24902505
ItemType::Static => ItemSection::Statics,
24912506
ItemType::Constant => ItemSection::Constants,

Diff for: src/librustdoc/html/render/print_item.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
162162
}
163163
}
164164
clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ",
165+
clean::TestItem(..) => "Test ",
165166
clean::TraitItem(..) => "Trait ",
166167
clean::StructItem(..) => "Struct ",
167168
clean::UnionItem(..) => "Union ",
@@ -228,7 +229,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
228229
clean::ModuleItem(m) => {
229230
write!(buf, "{}", item_module(cx, item, &m.items))
230231
}
231-
clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) => {
232+
clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) | clean::TestItem(f) => {
232233
write!(buf, "{}", item_function(cx, item, f))
233234
}
234235
clean::TraitItem(t) => write!(buf, "{}", item_trait(cx, item, t)),
@@ -326,6 +327,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
326327
ItemType::Static => 8,
327328
ItemType::Trait => 9,
328329
ItemType::Function => 10,
330+
ItemType::Test => 11,
329331
ItemType::TypeAlias => 12,
330332
ItemType::Union => 13,
331333
_ => 14 + ty as u8,

Diff for: src/librustdoc/html/static/js/main.js

+1
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ function preLoadCss(cssUrl) {
654654
block("static", "static", "Statics");
655655
block("trait", "traits", "Traits");
656656
block("fn", "functions", "Functions");
657+
block("test", "tests", "Tests");
657658
block("type", "types", "Type Aliases");
658659
block("union", "unions", "Unions");
659660
// No point, because these items don't appear in modules

Diff for: src/librustdoc/json/conversions.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
251251
StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)),
252252
EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)),
253253
VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)),
254-
FunctionItem(f) => ItemEnum::Function(from_function(*f, true, header.unwrap(), renderer)),
254+
FunctionItem(f) | TestItem(f) => {
255+
ItemEnum::Function(from_function(*f, true, header.unwrap(), renderer))
256+
}
255257
ForeignFunctionItem(f, _) => {
256258
ItemEnum::Function(from_function(*f, false, header.unwrap(), renderer))
257259
}
@@ -820,7 +822,7 @@ impl FromClean<ItemType> for ItemKind {
820822
Struct => ItemKind::Struct,
821823
Union => ItemKind::Union,
822824
Enum => ItemKind::Enum,
823-
Function | TyMethod | Method => ItemKind::Function,
825+
Function | Test | TyMethod | Method => ItemKind::Function,
824826
TypeAlias => ItemKind::TypeAlias,
825827
Static => ItemKind::Static,
826828
Constant => ItemKind::Constant,

Diff for: src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ fn opts() -> Vec<RustcOptGroup> {
699699
"removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
700700
"[rust]",
701701
),
702+
opt(Unstable, FlagMulti, "", "document-tests", "Generate documentation for tests", ""),
702703
]
703704
}
704705

Diff for: src/librustdoc/passes/propagate_stability.rs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl DocFolder for StabilityPropagator<'_, '_> {
7777
| ItemKind::UnionItem(..)
7878
| ItemKind::EnumItem(..)
7979
| ItemKind::FunctionItem(..)
80+
| ItemKind::TestItem(..)
8081
| ItemKind::ModuleItem(..)
8182
| ItemKind::TypeAliasItem(..)
8283
| ItemKind::StaticItem(..)

Diff for: src/librustdoc/passes/stripper.rs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl DocFolder for Stripper<'_, '_> {
5757
| clean::EnumItem(..)
5858
| clean::TraitItem(..)
5959
| clean::FunctionItem(..)
60+
| clean::TestItem(..)
6061
| clean::VariantItem(..)
6162
| clean::ForeignFunctionItem(..)
6263
| clean::ForeignStaticItem(..)

Diff for: src/librustdoc/visit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
3131
ExternCrateItem { src: _ }
3232
| ImportItem(_)
3333
| FunctionItem(_)
34+
| TestItem(_)
3435
| TypeAliasItem(_)
3536
| StaticItem(_)
3637
| ConstantItem(..)

0 commit comments

Comments
 (0)