Skip to content

Commit 39231b4

Browse files
committed
Auto merge of #8385 - cameron1024:doc_link_with_quotes, r=llogiq
add doc_link_with_quotes lint I'm not sure about wording, it seems OK to me but happy to change if other people have better ideas closes #8383 --- changelog: add [`doc_link_with_quotes`] lint
2 parents 5920fa3 + c9be57d commit 39231b4

7 files changed

+87
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3362,6 +3362,7 @@ Released 2018-09-13
33623362
[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
33633363
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
33643364
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
3365+
[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
33653366
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
33663367
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
33673368
[`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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.60.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+
}

clippy_lints/src/lib.register_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ store.register_lints(&[
124124
doc::MISSING_PANICS_DOC,
125125
doc::MISSING_SAFETY_DOC,
126126
doc::NEEDLESS_DOCTEST_MAIN,
127+
doc_link_with_quotes::DOC_LINK_WITH_QUOTES,
127128
double_comparison::DOUBLE_COMPARISONS,
128129
double_parens::DOUBLE_PARENS,
129130
drop_forget_ref::DROP_COPY,

clippy_lints/src/lib.register_pedantic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
2626
LintId::of(doc::DOC_MARKDOWN),
2727
LintId::of(doc::MISSING_ERRORS_DOC),
2828
LintId::of(doc::MISSING_PANICS_DOC),
29+
LintId::of(doc_link_with_quotes::DOC_LINK_WITH_QUOTES),
2930
LintId::of(empty_enum::EMPTY_ENUM),
3031
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
3132
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ mod disallowed_methods;
208208
mod disallowed_script_idents;
209209
mod disallowed_types;
210210
mod doc;
211+
mod doc_link_with_quotes;
211212
mod double_comparison;
212213
mod double_parens;
213214
mod drop_forget_ref;
@@ -886,6 +887,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
886887
store.register_late_pass(move || Box::new(borrow_as_ptr::BorrowAsPtr::new(msrv)));
887888
store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv)));
888889
store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation));
890+
store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes));
889891
store.register_late_pass(|| Box::new(only_used_in_recursion::OnlyUsedInRecursion));
890892
store.register_late_pass(|| Box::new(significant_drop_in_scrutinee::SignificantDropInScrutinee));
891893
let allow_dbg_in_tests = conf.allow_dbg_in_tests;

tests/ui/doc_link_with_quotes.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![warn(clippy::doc_link_with_quotes)]
2+
3+
fn main() {
4+
foo()
5+
}
6+
7+
/// Calls ['bar']
8+
pub fn foo() {
9+
bar()
10+
}
11+
12+
pub fn bar() {}

tests/ui/doc_link_with_quotes.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: possible intra-doc link using quotes instead of backticks
2+
--> $DIR/doc_link_with_quotes.rs:7:1
3+
|
4+
LL | /// Calls ['bar']
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::doc-link-with-quotes` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)