needless_doc_main: only check rust code

This commit is contained in:
Andre Bogus 2020-03-10 20:19:37 +01:00
parent bc51a1a1e9
commit 2fa3da4869
3 changed files with 65 additions and 7 deletions

View file

@ -367,6 +367,8 @@ fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, a
check_doc(cx, valid_idents, events, &spans)
}
const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail", "edition2018"];
fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize>)>>(
cx: &LateContext<'_, '_>,
valid_idents: &FxHashSet<String>,
@ -374,6 +376,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
spans: &[(usize, Span)],
) -> DocHeaders {
// true if a safety header was found
use pulldown_cmark::CodeBlockKind;
use pulldown_cmark::Event::{
Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
};
@ -386,11 +389,20 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
let mut in_code = false;
let mut in_link = None;
let mut in_heading = false;
let mut is_rust = false;
for (event, range) in events {
match event {
Start(CodeBlock(_)) => in_code = true,
End(CodeBlock(_)) => in_code = false,
Start(CodeBlock(ref kind)) => {
in_code = true;
if let CodeBlockKind::Fenced(lang) = kind {
is_rust =
lang.is_empty() || !lang.contains("ignore") && lang.split(',').any(|i| RUST_CODE.contains(&i));
}
},
End(CodeBlock(_)) => {
in_code = false;
is_rust = false;
},
Start(Link(_, url, _)) => in_link = Some(url),
End(Link(..)) => in_link = None,
Start(Heading(_)) => in_heading = true,
@ -413,7 +425,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
};
let (begin, span) = spans[index];
if in_code {
if is_rust {
check_code(cx, &text, span);
}
} else {
// Adjust for the beginning of the current `Event`
let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));

View file

@ -8,7 +8,23 @@
/// unimplemented!();
/// }
/// ```
fn bad_doctest() {}
///
/// This should, too.
///
/// ```rust
/// fn main() {
/// unimplemented!();
/// }
/// ```
///
/// This one too.
///
/// ```no_run
/// fn main() {
/// unimplemented!();
/// }
/// ```
fn bad_doctests() {}
/// # Examples
///
@ -34,9 +50,25 @@ fn bad_doctest() {}
/// assert_eq(1u8, test::black_box(1));
/// }
/// ```
///
/// We should not lint non-rust examples:
///
/// ```rust,ignore
/// fn main() {
/// unimplemented!();
/// }
/// ```
///
/// Or even non-rust examples:
///
/// ```text
/// fn main() {
/// is what starts the program
/// }
/// ```
fn no_false_positives() {}
fn main() {
bad_doctest();
bad_doctests();
no_false_positives();
}

View file

@ -6,5 +6,17 @@ LL | /// fn main() {
|
= note: `-D clippy::needless-doctest-main` implied by `-D warnings`
error: aborting due to previous error
error: needless `fn main` in doctest
--> $DIR/needless_doc_main.rs:15:4
|
LL | /// fn main() {
| ^^^^^^^^^^^^
error: needless `fn main` in doctest
--> $DIR/needless_doc_main.rs:23:4
|
LL | /// fn main() {
| ^^^^^^^^^^^^
error: aborting due to 3 previous errors