diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index d16c2a9d0342c..f45e229506438 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -467,3 +467,36 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind ``` Another use case would be to run a test inside an emulator, or through a Virtual Machine. + +### `--show-coverage`: get statistics about code documentation coverage + +This option allows you to get a nice overview over your code documentation coverage, including both +doc-comments and code examples in the doc-comments. Example: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --show-coverage ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| lib.rs | 4 | 100.0% | 1 | 25.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 4 | 100.0% | 1 | 25.0% | ++-------------------------------------+------------+------------+------------+------------+ +``` + +You can also use this option with the `--output-format` one: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --show-coverage --output-format json +{"lib.rs":{"total":4,"with_docs":4,"total_examples":4,"with_examples":1}} +``` + +Calculating code examples follows these rules: + +1. These items aren't accounted by default: + * struct/union field + * enum variant + * constant + * static + * typedef +2. If one of the previously listed items has a code example, then it'll be counted. diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 0a836f46c0eb8..457359e7a3806 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -27,20 +27,29 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C krate } -#[derive(Default, Copy, Clone, Serialize)] +#[derive(Default, Copy, Clone, Serialize, Debug)] struct ItemCount { total: u64, with_docs: u64, + total_examples: u64, with_examples: u64, } impl ItemCount { - fn count_item(&mut self, has_docs: bool, has_doc_example: bool) { + fn count_item( + &mut self, + has_docs: bool, + has_doc_example: bool, + should_have_doc_examples: bool, + ) { self.total += 1; if has_docs { self.with_docs += 1; } + if should_have_doc_examples || has_doc_example { + self.total_examples += 1; + } if has_doc_example { self.with_examples += 1; } @@ -55,8 +64,8 @@ impl ItemCount { } fn examples_percentage(&self) -> Option { - if self.total > 0 { - Some((self.with_examples as f64 * 100.0) / self.total as f64) + if self.total_examples > 0 { + Some((self.with_examples as f64 * 100.0) / self.total_examples as f64) } else { None } @@ -70,6 +79,7 @@ impl ops::Sub for ItemCount { ItemCount { total: self.total - rhs.total, with_docs: self.with_docs - rhs.with_docs, + total_examples: self.total_examples - rhs.total_examples, with_examples: self.with_examples - rhs.with_examples, } } @@ -79,6 +89,7 @@ impl ops::AddAssign for ItemCount { fn add_assign(&mut self, rhs: Self) { self.total += rhs.total; self.with_docs += rhs.with_docs; + self.total_examples += rhs.total_examples; self.with_examples += rhs.with_examples; } } @@ -121,7 +132,7 @@ impl CoverageCalculator { let mut total = ItemCount::default(); fn print_table_line() { - println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); + println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", ""); } fn print_table_record( @@ -131,32 +142,25 @@ impl CoverageCalculator { examples_percentage: f64, ) { println!( - "| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |", - name, - count.with_docs, - count.total, - percentage, - count.with_examples, - examples_percentage, + "| {:<35} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |", + name, count.with_docs, percentage, count.with_examples, examples_percentage, ); } print_table_line(); println!( - "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |", - "File", "Documented", "Total", "Percentage", "Examples", "Percentage", + "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} |", + "File", "Documented", "Percentage", "Examples", "Percentage", ); print_table_line(); for (file, &count) in &self.items { - if let (Some(percentage), Some(examples_percentage)) = - (count.percentage(), count.examples_percentage()) - { + if let Some(percentage) = count.percentage() { print_table_record( &limit_filename_len(file.to_string()), count, percentage, - examples_percentage, + count.examples_percentage().unwrap_or(0.), ); total += count; @@ -176,19 +180,6 @@ impl CoverageCalculator { impl fold::DocFolder for CoverageCalculator { fn fold_item(&mut self, i: clean::Item) -> Option { - let has_docs = !i.attrs.doc_strings.is_empty(); - let mut tests = Tests { found_tests: 0 }; - - find_testable_code( - &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::>().join("\n"), - &mut tests, - ErrorCodes::No, - false, - None, - ); - - let has_doc_example = tests.found_tests != 0; - match i.inner { _ if !i.def_id.is_local() => { // non-local items are skipped because they can be out of the users control, @@ -237,11 +228,37 @@ impl fold::DocFolder for CoverageCalculator { } } _ => { + let has_docs = !i.attrs.doc_strings.is_empty(); + let mut tests = Tests { found_tests: 0 }; + + let should_have_doc_examples = !matches!(i.inner, + clean::StructFieldItem(_) + | clean::VariantItem(_) + | clean::AssocConstItem(_, _) + | clean::AssocTypeItem(_, _) + | clean::TypedefItem(_, _) + | clean::StaticItem(_) + | clean::ConstantItem(_) + | clean::ExternCrateItem(_, _) + | clean::ImportItem(_) + | clean::PrimitiveItem(_) + | clean::KeywordItem(_) + ); + find_testable_code( + &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::>().join("\n"), + &mut tests, + ErrorCodes::No, + false, + None, + ); + + let has_doc_example = tests.found_tests != 0; debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename); - self.items - .entry(i.source.filename.clone()) - .or_default() - .count_item(has_docs, has_doc_example); + self.items.entry(i.source.filename.clone()).or_default().count_item( + has_docs, + has_doc_example, + should_have_doc_examples, + ); } } diff --git a/src/test/rustdoc-ui/coverage/basic.stdout b/src/test/rustdoc-ui/coverage/basic.stdout index 7e795acc575bc..3c602b3da4c7c 100644 --- a/src/test/rustdoc-ui/coverage/basic.stdout +++ b/src/test/rustdoc-ui/coverage/basic.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 7 | 14 | 50.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...est/rustdoc-ui/coverage/basic.rs | 7 | 50.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 7 | 50.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.rs b/src/test/rustdoc-ui/coverage/doc-examples-json.rs new file mode 100644 index 0000000000000..1da1813790e86 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/doc-examples-json.rs @@ -0,0 +1,13 @@ +// check-pass +// compile-flags:-Z unstable-options --output-format json --show-coverage + +// This check ensures that only one doc example is counted since they're "optional" on +// certain items. + +/// ``` +/// let x = 12; +/// ``` +pub const Foo: u32 = 0; + +/// doc +pub const Bar: u32 = 0; diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.stdout b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout new file mode 100644 index 0000000000000..92f58556975ae --- /dev/null +++ b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout @@ -0,0 +1 @@ +{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}} diff --git a/src/test/rustdoc-ui/coverage/doc-examples.stdout b/src/test/rustdoc-ui/coverage/doc-examples.stdout index f25cf79a3f35d..10ed13c9ff566 100644 --- a/src/test/rustdoc-ui/coverage/doc-examples.stdout +++ b/src/test/rustdoc-ui/coverage/doc-examples.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...tdoc-ui/coverage/doc-examples.rs | 4 | 4 | 100.0% | 2 | 50.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 4 | 4 | 100.0% | 2 | 50.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 2 | 50.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 4 | 100.0% | 2 | 50.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/empty.stdout b/src/test/rustdoc-ui/coverage/empty.stdout index 2a6a2231e5b57..890a7d56e162d 100644 --- a/src/test/rustdoc-ui/coverage/empty.stdout +++ b/src/test/rustdoc-ui/coverage/empty.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 0 | 1 | 0.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...est/rustdoc-ui/coverage/empty.rs | 0 | 0.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 0 | 0.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout index dd86f61f8d501..64c012c1f66e3 100644 --- a/src/test/rustdoc-ui/coverage/enums.stdout +++ b/src/test/rustdoc-ui/coverage/enums.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 6 | 8 | 75.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 6 | 75.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/exotic.stdout b/src/test/rustdoc-ui/coverage/exotic.stdout index f920a3abd36bb..e282ff1284375 100644 --- a/src/test/rustdoc-ui/coverage/exotic.stdout +++ b/src/test/rustdoc-ui/coverage/exotic.stdout @@ -1,8 +1,8 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% | 0 | 0.0% | -| | 2 | 2 | 100.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 3 | 3 | 100.0% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 100.0% | 0 | 0.0% | +| | 2 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 3 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs index 2bd6a312ab583..a591cd5dba406 100644 --- a/src/test/rustdoc-ui/coverage/json.rs +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -12,16 +12,54 @@ pub mod foo { pub struct X; /// Bar +/// +/// ``` +/// let x = 12; +/// ``` pub mod bar { /// bar pub struct Bar; /// X - pub enum X { Y } + pub enum X { + /// ``` + /// let x = "should be ignored!"; + /// ``` + Y + } } /// yolo +/// +/// ```text +/// should not be counted as a code example! +/// ``` pub enum Yolo { X } +impl Yolo { + /// ``` + /// let x = "should be ignored!"; + /// ``` + pub const Const: u32 = 0; +} + pub struct Xo { + /// ``` + /// let x = "should be ignored!"; + /// ``` x: T, } + +/// ``` +/// let x = "should be ignored!"; +/// ``` +pub static StaticFoo: u32 = 0; + +/// ``` +/// let x = "should be ignored!"; +/// ``` +pub const ConstFoo: u32 = 0; + +/// ``` +/// let x = "should be ignored!"; +/// ``` +pub type TypeFoo = u32; diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout index 7b5b083e1584c..c2be73ce3edd7 100644 --- a/src/test/rustdoc-ui/coverage/json.stdout +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -1 +1 @@ -{"$DIR/json.rs":{"total":13,"with_docs":7,"with_examples":0}} +{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}} diff --git a/src/test/rustdoc-ui/coverage/private.stdout b/src/test/rustdoc-ui/coverage/private.stdout index bca3d51da59d0..37a0f5187b512 100644 --- a/src/test/rustdoc-ui/coverage/private.stdout +++ b/src/test/rustdoc-ui/coverage/private.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 4 | 7 | 57.1% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...t/rustdoc-ui/coverage/private.rs | 4 | 57.1% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 4 | 57.1% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/statics-consts.stdout b/src/test/rustdoc-ui/coverage/statics-consts.stdout index 31b48cc602a76..dbea3a3ea23cf 100644 --- a/src/test/rustdoc-ui/coverage/statics-consts.stdout +++ b/src/test/rustdoc-ui/coverage/statics-consts.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 6 | 7 | 85.7% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...oc-ui/coverage/statics-consts.rs | 6 | 85.7% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 6 | 85.7% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/traits.stdout b/src/test/rustdoc-ui/coverage/traits.stdout index ac63b65023d0b..e04d48b4980c4 100644 --- a/src/test/rustdoc-ui/coverage/traits.stdout +++ b/src/test/rustdoc-ui/coverage/traits.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ -| Total | 6 | 7 | 85.7% | 0 | 0.0% | -+-------------------------------------+------------+------------+------------+------------+------------+ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...st/rustdoc-ui/coverage/traits.rs | 6 | 85.7% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 6 | 85.7% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+