Skip to content

Don't emit "missing backticks" lint if the element is wrapped in <code> HTML tags #12423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions clippy_lints/src/doc/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use url::Url;

use crate::doc::DOC_MARKDOWN;

pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) {
pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span, code_level: isize) {
for orig_word in text.split(|c: char| c.is_whitespace() || c == '\'') {
// Trim punctuation as in `some comment (see foo::bar).`
// ^^
Expand Down Expand Up @@ -46,11 +46,11 @@ pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str,
span.parent(),
);

check_word(cx, word, span);
check_word(cx, word, span, code_level);
}
}

fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) {
/// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
/// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
/// letter (`NASA` is ok).
Expand Down Expand Up @@ -90,7 +90,7 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
}

// We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
if has_underscore(word) && has_hyphen(word) {
if code_level > 0 || (has_underscore(word) && has_hyphen(word)) {
return;
}

Expand Down
18 changes: 13 additions & 5 deletions clippy_lints/src/doc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,19 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
let mut ignore = false;
let mut edition = None;
let mut ticks_unbalanced = false;
let mut text_to_check: Vec<(CowStr<'_>, Range<usize>)> = Vec::new();
let mut text_to_check: Vec<(CowStr<'_>, Range<usize>, isize)> = Vec::new();
let mut paragraph_range = 0..0;
let mut code_level = 0;

for (event, range) in events {
match event {
Html(tag) => {
if tag.starts_with("<code") {
code_level += 1;
} else if tag.starts_with("</code") {
code_level -= 1;
}
},
Start(CodeBlock(ref kind)) => {
in_code = true;
if let CodeBlockKind::Fenced(lang) = kind {
Expand Down Expand Up @@ -652,16 +661,15 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
"a backtick may be missing a pair",
);
} else {
for (text, range) in text_to_check {
for (text, range, assoc_code_level) in text_to_check {
if let Some(span) = fragments.span(cx, range) {
markdown::check(cx, valid_idents, &text, span);
markdown::check(cx, valid_idents, &text, span, assoc_code_level);
}
}
}
text_to_check = Vec::new();
},
Start(_tag) | End(_tag) => (), // We don't care about other tags
Html(_html) => (), // HTML is weird, just ignore it
SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
FootnoteReference(text) | Text(text) => {
paragraph_range.end = range.end;
Expand Down Expand Up @@ -694,7 +702,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
// Don't check the text associated with external URLs
continue;
}
text_to_check.push((text, range));
text_to_check.push((text, range, code_level));
}
},
}
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/doc/issue_9473.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![warn(clippy::doc_markdown)]

// Should not warn!
/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>.
pub struct Foo(u32);

// Should warn.
/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[`FooBar`].
pub struct FooBar(u32);
9 changes: 9 additions & 0 deletions tests/ui/doc/issue_9473.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![warn(clippy::doc_markdown)]

// Should not warn!
/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>.
pub struct Foo(u32);

// Should warn.
/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[FooBar].
pub struct FooBar(u32);
15 changes: 15 additions & 0 deletions tests/ui/doc/issue_9473.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: item in documentation is missing backticks
--> tests/ui/doc/issue_9473.rs:8:58
|
LL | /// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[FooBar].
| ^^^^^^
|
= note: `-D clippy::doc-markdown` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]`
help: try
|
LL | /// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[`FooBar`].
| ~~~~~~~~

error: aborting due to 1 previous error