rustdoc/passes/
lint.rs

1//! Runs several rustdoc lints, consolidating them into a single pass for
2//! efficiency and simplicity.
3
4mod bare_urls;
5mod check_code_block_syntax;
6mod html_tags;
7mod redundant_explicit_links;
8mod unescaped_backticks;
9mod unportable_markdown;
10
11use super::Pass;
12use crate::clean::*;
13use crate::core::DocContext;
14use crate::visit::DocVisitor;
15
16pub(crate) const RUN_LINTS: Pass =
17    Pass { name: "run-lints", run: Some(run_lints), description: "runs some of rustdoc's lints" };
18
19struct Linter<'a, 'tcx> {
20    cx: &'a mut DocContext<'tcx>,
21}
22
23pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
24    Linter { cx }.visit_crate(&krate);
25    krate
26}
27
28impl DocVisitor<'_> for Linter<'_, '_> {
29    fn visit_item(&mut self, item: &Item) {
30        let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else {
31            // If non-local, no need to check anything.
32            return;
33        };
34        let dox = item.doc_value();
35        if !dox.is_empty() {
36            let may_have_link = dox.contains(&[':', '['][..]);
37            let may_have_block_comment_or_html = dox.contains(['<', '>']);
38            // ~~~rust
39            // // This is a real, supported commonmark syntax for block code
40            // ~~~
41            let may_have_code = dox.contains(&['~', '`', '\t'][..]) || dox.contains("    ");
42            if may_have_link {
43                bare_urls::visit_item(self.cx, item, hir_id, &dox);
44                redundant_explicit_links::visit_item(self.cx, item, hir_id);
45            }
46            if may_have_code {
47                check_code_block_syntax::visit_item(self.cx, item, &dox);
48                unescaped_backticks::visit_item(self.cx, item, hir_id, &dox);
49            }
50            if may_have_block_comment_or_html {
51                html_tags::visit_item(self.cx, item, hir_id, &dox);
52                unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
53            } else if may_have_link {
54                unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
55            }
56        }
57
58        self.visit_item_recur(item)
59    }
60}