about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs36
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs15
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.rs41
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.stderr20
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.stdout7
5 files changed, 104 insertions, 15 deletions
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 4bca3996eb4..ced26fcf5b0 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,10 +1,12 @@
 use crate::clean;
-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::{should_have_doc_example, Tests};
 use crate::passes::Pass;
+use rustc_lint::builtin::MISSING_DOCS;
+use rustc_middle::lint::LintSource;
+use rustc_session::lint;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
 use serde::Serialize;
@@ -19,10 +21,10 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
 };
 
 fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate {
-    let mut calc = CoverageCalculator::new();
+    let mut calc = CoverageCalculator::new(ctx);
     let krate = calc.fold_crate(krate);
 
-    calc.print_results(ctx.renderinfo.borrow().output_format);
+    calc.print_results();
 
     krate
 }
@@ -41,8 +43,11 @@ impl ItemCount {
         has_docs: bool,
         has_doc_example: bool,
         should_have_doc_examples: bool,
+        should_have_docs: bool,
     ) {
-        self.total += 1;
+        if has_docs || should_have_docs {
+            self.total += 1;
+        }
 
         if has_docs {
             self.with_docs += 1;
@@ -94,8 +99,9 @@ impl ops::AddAssign for ItemCount {
     }
 }
 
-struct CoverageCalculator {
+struct CoverageCalculator<'a, 'b> {
     items: BTreeMap<FileName, ItemCount>,
+    ctx: &'a DocContext<'b>,
 }
 
 fn limit_filename_len(filename: String) -> String {
@@ -108,9 +114,9 @@ fn limit_filename_len(filename: String) -> String {
     }
 }
 
-impl CoverageCalculator {
-    fn new() -> CoverageCalculator {
-        CoverageCalculator { items: Default::default() }
+impl<'a, 'b> CoverageCalculator<'a, 'b> {
+    fn new(ctx: &'a DocContext<'b>) -> CoverageCalculator<'a, 'b> {
+        CoverageCalculator { items: Default::default(), ctx }
     }
 
     fn to_json(&self) -> String {
@@ -124,7 +130,8 @@ impl CoverageCalculator {
         .expect("failed to convert JSON data to string")
     }
 
-    fn print_results(&self, output_format: Option<OutputFormat>) {
+    fn print_results(&self) {
+        let output_format = self.ctx.renderinfo.borrow().output_format;
         if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) {
             println!("{}", self.to_json());
             return;
@@ -178,7 +185,7 @@ impl CoverageCalculator {
     }
 }
 
-impl fold::DocFolder for CoverageCalculator {
+impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
     fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
         match i.inner {
             _ if !i.def_id.is_local() => {
@@ -245,11 +252,18 @@ impl fold::DocFolder for CoverageCalculator {
                 );
 
                 let has_doc_example = tests.found_tests != 0;
+                let hir_id = self.ctx.tcx.hir().local_def_id_to_hir_id(i.def_id.expect_local());
+                let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
+                // `missing_docs` is allow-by-default, so don't treat this as ignoring the item
+                // unless the user had an explicit `allow`
+                let should_have_docs =
+                    level != lint::Level::Allow || matches!(source, LintSource::Default);
                 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,
-                    should_have_doc_example(&i.inner),
+                    should_have_doc_example(self.ctx, &i),
+                    should_have_docs,
                 );
             }
         }
diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs
index 78af9f9b856..686ec51fb06 100644
--- a/src/librustdoc/passes/doc_test_lints.rs
+++ b/src/librustdoc/passes/doc_test_lints.rs
@@ -9,6 +9,7 @@ use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
+use rustc_middle::lint::LintSource;
 use rustc_session::lint;
 
 pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
@@ -56,8 +57,8 @@ impl crate::doctest::Tester for Tests {
     }
 }
 
-pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
-    !matches!(item_kind,
+pub fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
+    if matches!(item.inner,
         clean::StructFieldItem(_)
         | clean::VariantItem(_)
         | clean::AssocConstItem(_, _)
@@ -69,7 +70,13 @@ pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
         | clean::ImportItem(_)
         | clean::PrimitiveItem(_)
         | clean::KeywordItem(_)
-    )
+    ) {
+        return false;
+    }
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
+    let (level, source) =
+        cx.tcx.lint_level_at_node(lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id);
+    level != lint::Level::Allow || matches!(source, LintSource::Default)
 }
 
 pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
@@ -88,7 +95,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     if tests.found_tests == 0
         && rustc_feature::UnstableFeatures::from_environment().is_nightly_build()
     {
-        if should_have_doc_example(&item.inner) {
+        if should_have_doc_example(cx, &item) {
             debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
             let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
             cx.tcx.struct_span_lint_hir(
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
new file mode 100644
index 00000000000..c077be31b20
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
@@ -0,0 +1,41 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! Make sure to have some docs on your crate root
+
+#[allow(missing_docs)]
+pub mod mod_foo {
+    pub struct Bar;
+}
+
+/// This is a struct with a `#[allow(missing_docs)]`
+pub struct AllowTheMissingDocs {
+    #[allow(missing_docs)]
+    pub empty_str: String,
+
+    /// This has
+    #[allow(missing_docs)]
+    /// but also has documentation comments
+    pub hello: usize,
+
+    /// The doc id just to create a boilerplate comment
+    pub doc_id: Vec<u8>,
+}
+
+/// A function that has a documentation
+pub fn this_is_func() {}
+
+#[allow(missing_docs)]
+pub struct DemoStruct {
+    something: usize,
+}
+
+#[allow(missing_docs)]
+pub mod bar {
+    #[warn(missing_docs)]
+    pub struct Bar { //~ WARN
+        pub f: u32, //~ WARN
+    }
+
+    pub struct NeedsNoDocs;
+}
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr b/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr
new file mode 100644
index 00000000000..3d5b512d14d
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.stderr
@@ -0,0 +1,20 @@
+warning: missing documentation for a struct
+  --> $DIR/allow_missing_docs.rs:36:5
+   |
+LL |     pub struct Bar {
+   |     ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/allow_missing_docs.rs:35:12
+   |
+LL |     #[warn(missing_docs)]
+   |            ^^^^^^^^^^^^
+
+warning: missing documentation for a struct field
+  --> $DIR/allow_missing_docs.rs:37:9
+   |
+LL |         pub f: u32,
+   |         ^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
new file mode 100644
index 00000000000..17e8ee9e23d
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...i/coverage/allow_missing_docs.rs |          5 |      71.4% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          5 |      71.4% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+