about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs67
1 files changed, 64 insertions, 3 deletions
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index d4a7f3313a4..0ca5a956bdb 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,4 +1,5 @@
 use crate::clean;
+use crate::config::OutputFormat;
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::passes::Pass;
@@ -6,6 +7,7 @@ use crate::passes::Pass;
 use rustc_ast::attr;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
+use serialize::json::{ToJson, Json};
 
 use std::collections::BTreeMap;
 use std::ops;
@@ -16,8 +18,8 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
     description: "counts the number of items with and without documentation",
 };
 
-fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
-    let mut calc = CoverageCalculator::default();
+fn calculate_doc_coverage( krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate {
+    let mut calc = CoverageCalculator::new(ctx.renderinfo.borrow().output_format);
     let krate = calc.fold_crate(krate);
 
     calc.print_results();
@@ -64,13 +66,72 @@ impl ops::AddAssign for ItemCount {
     }
 }
 
-#[derive(Default)]
 struct CoverageCalculator {
     items: BTreeMap<FileName, ItemCount>,
+    output_format: Option<OutputFormat>,
+}
+
+fn limit_filename_len(filename: String) -> String {
+    // if a filename is too long, shorten it so we don't blow out the table
+    // FIXME(misdreavus): this needs to count graphemes, and probably also track
+    // double-wide characters...
+    if filename.len() > 35 {
+        "...".to_string() + &filename[filename.len() - 32..]
+    } else {
+        filename
+    }
+}
+
+impl ToJson for CoverageCalculator {
+    fn to_json(&self) -> Json {
+        let mut total = ItemCount::default();
+        let mut entries = BTreeMap::default();
+
+        entries.insert("files".to_owned(), Json::Array(self.items
+            .iter()
+            .filter_map(|(file, &count)| {
+                count.percentage().map(|percent| {
+                    (limit_filename_len(file.to_string()), count, percent)
+                })
+            })
+            .map(|(name, count, percentage)| {
+                let mut fields = BTreeMap::default();
+
+                fields.insert("documented".to_owned(), Json::U64(count.with_docs));
+                fields.insert("total".to_owned(), Json::U64(count.total));
+                fields.insert("percentage".to_owned(), Json::F64(percentage));
+
+                total += count;
+
+                let mut obj = BTreeMap::default();
+                obj.insert(name, Json::Object(fields));
+
+                Json::Object(obj)
+            })
+            .collect::<Vec<_>>()));
+        let mut fields = BTreeMap::default();
+        fields.insert("documented".to_owned(), Json::U64(total.with_docs));
+        fields.insert("total".to_owned(), Json::U64(total.total));
+        fields.insert("percentage".to_owned(), Json::F64(total.percentage().unwrap_or(0.0)));
+
+        entries.insert("total".to_owned(), Json::Object(fields));
+        Json::Object(entries)
+    }
 }
 
 impl CoverageCalculator {
+    fn new(output_format: Option<OutputFormat>) -> CoverageCalculator {
+        CoverageCalculator {
+            items: Default::default(),
+            output_format,
+        }
+    }
+
     fn print_results(&self) {
+        if self.output_format.map(|o| o.is_json()).unwrap_or_else(|| false) {
+            println!("{}", self.to_json().pretty());
+            return;
+        }
         let mut total = ItemCount::default();
 
         fn print_table_line() {