]> git.lizzy.rs Git - rust.git/commitdiff
Add doc examples count for --show-coverage
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Tue, 18 Aug 2020 11:31:23 +0000 (13:31 +0200)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Tue, 18 Aug 2020 11:31:23 +0000 (13:31 +0200)
src/librustdoc/html/render/cache.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/doc_test_lints.rs

index 5a9e9dda6771ecb7854a6346768bb3c841f0f6b0..ccc07645620a9c8ffe536a071e3c3958e48a2140 100644 (file)
@@ -200,10 +200,12 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
     match *clean_type {
         clean::ResolvedPath { ref path, .. } => {
             let segments = &path.segments;
-            let path_segment = segments.iter().last().unwrap_or_else(|| panic!(
+            let path_segment = segments.iter().last().unwrap_or_else(|| {
+                panic!(
                 "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
                 clean_type, accept_generic
-            ));
+            )
+            });
             Some(path_segment.name.clone())
         }
         clean::Generic(ref s) if accept_generic => Some(s.clone()),
index b722cfc8f7521f9bb3d46912cba0b8f145a40e15..0a836f46c0eb85bc96bc861e94f3af109e58eb1c 100644 (file)
@@ -2,8 +2,9 @@
 use crate::config::OutputFormat;
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
+use crate::html::markdown::{find_testable_code, ErrorCodes};
+use crate::passes::doc_test_lints::Tests;
 use crate::passes::Pass;
-
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
 use serde::Serialize;
@@ -30,15 +31,19 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C
 struct ItemCount {
     total: u64,
     with_docs: u64,
+    with_examples: u64,
 }
 
 impl ItemCount {
-    fn count_item(&mut self, has_docs: bool) {
+    fn count_item(&mut self, has_docs: bool, has_doc_example: bool) {
         self.total += 1;
 
         if has_docs {
             self.with_docs += 1;
         }
+        if has_doc_example {
+            self.with_examples += 1;
+        }
     }
 
     fn percentage(&self) -> Option<f64> {
@@ -48,13 +53,25 @@ fn percentage(&self) -> Option<f64> {
             None
         }
     }
+
+    fn examples_percentage(&self) -> Option<f64> {
+        if self.total > 0 {
+            Some((self.with_examples as f64 * 100.0) / self.total as f64)
+        } else {
+            None
+        }
+    }
 }
 
 impl ops::Sub for ItemCount {
     type Output = Self;
 
     fn sub(self, rhs: Self) -> Self {
-        ItemCount { total: self.total - rhs.total, with_docs: self.with_docs - rhs.with_docs }
+        ItemCount {
+            total: self.total - rhs.total,
+            with_docs: self.with_docs - rhs.with_docs,
+            with_examples: self.with_examples - rhs.with_examples,
+        }
     }
 }
 
@@ -62,6 +79,7 @@ impl ops::AddAssign for ItemCount {
     fn add_assign(&mut self, rhs: Self) {
         self.total += rhs.total;
         self.with_docs += rhs.with_docs;
+        self.with_examples += rhs.with_examples;
     }
 }
 
@@ -103,33 +121,55 @@ fn print_results(&self, output_format: Option<OutputFormat>) {
         let mut total = ItemCount::default();
 
         fn print_table_line() {
-            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
+            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
         }
 
-        fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
+        fn print_table_record(
+            name: &str,
+            count: ItemCount,
+            percentage: f64,
+            examples_percentage: f64,
+        ) {
             println!(
-                "| {:<35} | {:>10} | {:>10} | {:>9.1}% |",
-                name, count.with_docs, count.total, percentage
+                "| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
+                name,
+                count.with_docs,
+                count.total,
+                percentage,
+                count.with_examples,
+                examples_percentage,
             );
         }
 
         print_table_line();
         println!(
-            "| {:<35} | {:>10} | {:>10} | {:>10} |",
-            "File", "Documented", "Total", "Percentage"
+            "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |",
+            "File", "Documented", "Total", "Percentage", "Examples", "Percentage",
         );
         print_table_line();
 
         for (file, &count) in &self.items {
-            if let Some(percentage) = count.percentage() {
-                print_table_record(&limit_filename_len(file.to_string()), count, percentage);
+            if let (Some(percentage), Some(examples_percentage)) =
+                (count.percentage(), count.examples_percentage())
+            {
+                print_table_record(
+                    &limit_filename_len(file.to_string()),
+                    count,
+                    percentage,
+                    examples_percentage,
+                );
 
                 total += count;
             }
         }
 
         print_table_line();
-        print_table_record("Total", total, total.percentage().unwrap_or(0.0));
+        print_table_record(
+            "Total",
+            total,
+            total.percentage().unwrap_or(0.0),
+            total.examples_percentage().unwrap_or(0.0),
+        );
         print_table_line();
     }
 }
@@ -137,6 +177,17 @@ fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
 impl fold::DocFolder for CoverageCalculator {
     fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
         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::<Vec<_>>().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() => {
@@ -187,7 +238,10 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
             }
             _ => {
                 debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename);
-                self.items.entry(i.source.filename.clone()).or_default().count_item(has_docs);
+                self.items
+                    .entry(i.source.filename.clone())
+                    .or_default()
+                    .count_item(has_docs, has_doc_example);
             }
         }
 
index aced7d55281adccb6db96f0883bbcf6d535d3ac1..1fdc4ee247adfc6a34b39c0f14051d59b9fae37d 100644 (file)
@@ -43,6 +43,22 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
     }
 }
 
+pub(crate) struct Tests {
+    pub(crate) found_tests: usize,
+}
+
+impl Tests {
+    pub(crate) fn new() -> Tests {
+        Tests { found_tests: 0 }
+    }
+}
+
+impl crate::test::Tester for Tests {
+    fn add_test(&mut self, _: String, _: LangString, _: usize) {
+        self.found_tests += 1;
+    }
+}
+
 pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
         Some(hir_id) => hir_id,
@@ -52,17 +68,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
         }
     };
 
-    struct Tests {
-        found_tests: usize,
-    }
-
-    impl crate::test::Tester for Tests {
-        fn add_test(&mut self, _: String, _: LangString, _: usize) {
-            self.found_tests += 1;
-        }
-    }
-
-    let mut tests = Tests { found_tests: 0 };
+    let mut tests = Tests::new();
 
     find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);