about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndre Bogus <bogusandre@gmail.com>2019-10-01 00:10:24 +0200
committerAndre Bogus <bogusandre@gmail.com>2019-10-02 17:17:22 +0200
commit23a9c021201df810f40d0ad1fe3815dda5da8462 (patch)
tree6d6a0a39103c26ced5ef75a12414132722cde4b8
parent83f90aaedf7e756c22e4a8712233fd0425f1ee85 (diff)
downloadrust-23a9c021201df810f40d0ad1fe3815dda5da8462.tar.gz
rust-23a9c021201df810f40d0ad1fe3815dda5da8462.zip
New lint: needless_doc_main
-rw-r--r--CHANGELOG.md1
-rw-r--r--README.md2
-rw-r--r--clippy_lints/src/doc.rs53
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--src/lintlist/mod.rs9
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<Item = (pulldown_cmark::Event<'a>, Range<usize
                     continue;
                 }
                 safety_header |= in_heading && text.trim() == "Safety";
-                if !in_code {
-                    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];
-
+                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<Item = (pulldown_cmark::Event<'a>, Range<usize
     safety_header
 }
 
+fn check_code(cx: &EarlyContext<'_>, 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<String>, 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",
@@ -1226,6 +1226,13 @@ pub const ALL_LINTS: [Lint; 317] = [
         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",
         desc: "using explicit lifetimes for references in function arguments when elision rules would allow omitting them",