From 23a9c021201df810f40d0ad1fe3815dda5da8462 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 1 Oct 2019 00:10:24 +0200 Subject: [PATCH] New lint: needless_doc_main --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/doc.rs | 53 +++++++++++++++++++++++++++++++++-------- clippy_lints/src/lib.rs | 2 ++ src/lintlist/mod.rs | 9 ++++++- 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca0eb65ca3d..c4e04586530 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1105,6 +1105,7 @@ Released 2018-09-13 [`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue +[`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop diff --git a/README.md b/README.md index f944e716e9a..2f7032af87d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 317 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 318 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 59cb282a995..bd959427403 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -68,6 +68,34 @@ declare_clippy_lint! { "`pub unsafe fn` without `# Safety` docs" } +declare_clippy_lint! { + /// **What it does:** Checks for `fn main() { .. }` in doctests + /// + /// **Why is this bad?** The test can be shorter (and likely more readable) + /// if the `fn main()` is left implicit. + /// + /// **Known problems:** None. + /// + /// **Examples:** + /// ``````rust + /// /// An example of a doctest with a `main()` function + /// /// + /// /// # Examples + /// /// + /// /// ``` + /// /// fn main() { + /// /// // this needs not be in an `fn` + /// /// } + /// /// ``` + /// fn needless_main() { + /// unimplemented!(); + /// } + /// `````` + pub NEEDLESS_DOCTEST_MAIN, + style, + "presence of `fn main() {` in code examples" +} + #[allow(clippy::module_name_repetitions)] #[derive(Clone)] pub struct DocMarkdown { @@ -80,7 +108,7 @@ impl DocMarkdown { } } -impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC]); +impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC, NEEDLESS_DOCTEST_MAIN]); impl EarlyLintPass for DocMarkdown { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { @@ -245,17 +273,16 @@ fn check_doc<'a, Events: Iterator, Range o, - Err(e) => e - 1, - }; - - let (begin, span) = spans[index]; - + let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) { + Ok(o) => o, + Err(e) => e - 1, + }; + let (begin, span) = spans[index]; + if in_code { + 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)); - check_text(cx, valid_idents, &text, span); } }, @@ -264,6 +291,12 @@ fn check_doc<'a, Events: Iterator, Range, text: &str, span: Span) { + if text.contains("fn main() {") { + span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); + } +} + fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ed47b6a1857..10a14f3b906 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -713,6 +713,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con copies::IF_SAME_THEN_ELSE, derive::DERIVE_HASH_XOR_EQ, doc::MISSING_SAFETY_DOC, + doc::NEEDLESS_DOCTEST_MAIN, double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, drop_bounds::DROP_BOUNDS, @@ -937,6 +938,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con collapsible_if::COLLAPSIBLE_IF, comparison_chain::COMPARISON_CHAIN, doc::MISSING_SAFETY_DOC, + doc::NEEDLESS_DOCTEST_MAIN, enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, eq_op::OP_REF, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1b838b17f7f..383be8b1da4 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 317] = [ +pub const ALL_LINTS: [Lint; 318] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1225,6 +1225,13 @@ pub const ALL_LINTS: [Lint; 317] = [ deprecation: None, module: "needless_continue", }, + Lint { + name: "needless_doctest_main", + group: "style", + desc: "presence of `fn main() {` in code examples", + deprecation: None, + module: "doc", + }, Lint { name: "needless_lifetimes", group: "complexity",