]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs
Rollup merge of #101624 - notriddle:notriddle/search, r=GuillaumeGomez
[rust.git] / src / tools / clippy / clippy_lints / src / doc_link_with_quotes.rs
1 use clippy_utils::diagnostics::span_lint;
2 use itertools::Itertools;
3 use rustc_ast::{AttrKind, Attribute};
4 use rustc_lint::{EarlyContext, EarlyLintPass};
5 use rustc_session::{declare_lint_pass, declare_tool_lint};
6
7 declare_clippy_lint! {
8     /// ### What it does
9     /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
10     /// outside of code blocks
11     /// ### Why is this bad?
12     /// It is likely a typo when defining an intra-doc link
13     ///
14     /// ### Example
15     /// ```rust
16     /// /// See also: ['foo']
17     /// fn bar() {}
18     /// ```
19     /// Use instead:
20     /// ```rust
21     /// /// See also: [`foo`]
22     /// fn bar() {}
23     /// ```
24     #[clippy::version = "1.63.0"]
25     pub DOC_LINK_WITH_QUOTES,
26     pedantic,
27     "possible typo for an intra-doc link"
28 }
29 declare_lint_pass!(DocLinkWithQuotes => [DOC_LINK_WITH_QUOTES]);
30
31 impl EarlyLintPass for DocLinkWithQuotes {
32     fn check_attribute(&mut self, ctx: &EarlyContext<'_>, attr: &Attribute) {
33         if let AttrKind::DocComment(_, symbol) = attr.kind {
34             if contains_quote_link(symbol.as_str()) {
35                 span_lint(
36                     ctx,
37                     DOC_LINK_WITH_QUOTES,
38                     attr.span,
39                     "possible intra-doc link using quotes instead of backticks",
40                 );
41             }
42         }
43     }
44 }
45
46 fn contains_quote_link(s: &str) -> bool {
47     let mut in_backticks = false;
48     let mut found_opening = false;
49
50     for c in s.chars().tuple_windows::<(char, char)>() {
51         match c {
52             ('`', _) => in_backticks = !in_backticks,
53             ('[', '\'') if !in_backticks => found_opening = true,
54             ('\'', ']') if !in_backticks && found_opening => return true,
55             _ => {},
56         }
57     }
58
59     false
60 }