From b31f5d05b1c10c1f99b5bc3c14499ff537c7b692 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 8 Oct 2020 18:05:01 +0200
Subject: [PATCH] Inherit lint level from parents

---
 .../passes/calculate_doc_coverage.rs          | 40 ++++++++-----------
 .../rustdoc-ui/coverage/allow_missing_docs.rs |  8 ++++
 .../coverage/allow_missing_docs.stdout        |  4 +-
 3 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 30dd8def70e..093b77d4e94 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,11 +1,13 @@
 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_span::symbol::{sym, Ident};
+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
 }
@@ -97,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 {
@@ -111,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 {
@@ -127,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;
@@ -181,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() => {
@@ -232,15 +236,6 @@ impl fold::DocFolder for CoverageCalculator {
             }
             _ => {
                 let has_docs = !i.attrs.doc_strings.is_empty();
-                let should_have_docs = !i.attrs.other_attrs.iter().any(|a| {
-                    a.has_name(sym::allow)
-                        && a.meta_item_list().iter().any(|meta_list_item| {
-                            meta_list_item.iter().any(|li| match li.ident() {
-                                Some(ident) => ident == Ident::from_str("missing_docs"),
-                                _ => false,
-                            })
-                        })
-                });
                 let mut tests = Tests { found_tests: 0 };
 
                 find_testable_code(
@@ -257,6 +252,9 @@ 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);
+                let should_have_docs = level != lint::Level::Allow || !matches!(source, LintSource::Node(..));
                 debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename);
                 self.items.entry(i.source.filename.clone()).or_default().count_item(
                     has_docs,
@@ -264,10 +262,6 @@ impl fold::DocFolder for CoverageCalculator {
                     should_have_doc_example(&i.inner),
                     should_have_docs,
                 );
-
-                if !should_have_docs {
-                    return Some(i);
-                }
             }
         }
 
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
index 8c076761ede..87af1a45864 100644
--- a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
@@ -29,3 +29,11 @@ pub fn this_is_func() {}
 pub struct DemoStruct {
     something: usize,
 }
+
+#[allow(missing_docs)]
+pub mod bar {
+    #[warn(missing_docs)]
+    pub struct Bar { //~ WARN
+        pub f: u32, //~ WARN
+    }
+}
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
index ea5380e3204..17e8ee9e23d 100644
--- a/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.stdout
@@ -1,7 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...i/coverage/allow_missing_docs.rs |          5 |     100.0% |          0 |       0.0% |
+| ...i/coverage/allow_missing_docs.rs |          5 |      71.4% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
-| Total                               |          5 |     100.0% |          0 |       0.0% |
+| Total                               |          5 |      71.4% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+