]> git.lizzy.rs Git - rust.git/commitdiff
Make a lint instead
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Sat, 15 Jul 2017 22:17:35 +0000 (00:17 +0200)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Thu, 27 Jul 2017 18:38:33 +0000 (20:38 +0200)
src/librustc/hir/mod.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/libsyntax/ast.rs
src/libsyntax/parse/parser.rs
src/test/compile-fail/useless_comment.rs
src/test/compile-fail/useless_comment2.rs [deleted file]
src/test/compile-fail/useless_comment3.rs [deleted file]

index 1b14caad3c83c0a5b0db044a78d7bb9e76855746..a3a133daa09c460bb7a3beec60612ce702a6aeb5 100644 (file)
@@ -892,6 +892,13 @@ pub fn attrs(&self) -> &[Attribute] {
             DeclItem(_) => &[]
         }
     }
+
+    pub fn is_local(&self) -> bool {
+        match *self {
+            Decl_::DeclLocal(_) => true,
+            _ => false,
+        }
+    }
 }
 
 /// represents one arm of a 'match'
index 02d68a41b4cc4dbfb3a524522905999a4c1e5ae3..ca30ed4a536e2be1a0c910bb9a6a183a09fe0a9e 100644 (file)
@@ -722,6 +722,46 @@ fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
     }
 }
 
+declare_lint! {
+    pub UNUSED_DOC_COMMENT,
+    Warn,
+    "detects doc comments that aren't used by rustdoc"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedDocComment;
+
+impl LintPass for UnusedDocComment {
+    fn get_lints(&self) -> LintArray {
+        lint_array![UNUSED_DOC_COMMENT]
+    }
+}
+
+impl UnusedDocComment {
+    fn warn_if_doc<'a, 'tcx,
+                   I: Iterator<Item=&'a ast::Attribute>,
+                   C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) {
+        if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) {
+            cx.struct_span_lint(UNUSED_DOC_COMMENT, attr.span, "doc comment not used by rustdoc")
+              .emit();
+        }
+    }
+}
+
+impl EarlyLintPass for UnusedDocComment {
+    fn check_local(&mut self, cx: &EarlyContext, decl: &ast::Local) {
+        self.warn_if_doc(decl.attrs.iter(), cx);
+    }
+
+    fn check_arm(&mut self, cx: &EarlyContext, arm: &ast::Arm) {
+        self.warn_if_doc(arm.attrs.iter(), cx);
+    }
+
+    fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
+        self.warn_if_doc(expr.attrs.iter(), cx);
+    }
+}
+
 declare_lint! {
     pub UNCONDITIONAL_RECURSION,
     Warn,
index 21dca7f6c61c413234671a38817e6aabba2c9231..83c00c178a0ba540ce6e3588e2efa05709e63a23 100644 (file)
@@ -111,6 +111,7 @@ macro_rules! add_lint_group {
                        UnusedImportBraces,
                        AnonymousParameters,
                        IllegalFloatLiteralPattern,
+                       UnusedDocComment,
                        );
 
     add_early_builtin_with_new!(sess,
index f7d9d532062a99acf62ffcf15a3626a0d6e017ad..df3f68fd1c6c142ae10dc7dd21a85474d7f1a941 100644 (file)
@@ -718,6 +718,13 @@ pub fn add_trailing_semicolon(mut self) -> Self {
         };
         self
     }
+
+    pub fn is_item(&self) -> bool {
+        match self.node {
+            StmtKind::Local(_) => true,
+            _ => false,
+        }
+    }
 }
 
 impl fmt::Debug for Stmt {
index 047f4b979d9841dc4a1c4889ac19d07f2870476b..582f72e398d7cd2a1125e17c2148ceee2ce60c3d 100644 (file)
@@ -2420,12 +2420,6 @@ pub fn parse_dot_or_call_expr_with(&mut self,
             expr.map(|mut expr| {
                 attrs.extend::<Vec<_>>(expr.attrs.into());
                 expr.attrs = attrs;
-                if if let Some(ref doc) = expr.attrs.iter().find(|x| x.is_sugared_doc) {
-                    self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-                    true
-                } else { false } {
-                    return expr;
-                }
                 match expr.node {
                     ExprKind::If(..) | ExprKind::IfLet(..) => {
                         if !expr.attrs.is_empty() {
@@ -3110,9 +3104,6 @@ pub fn parse_lambda_expr(&mut self,
 
     // `else` token already eaten
     pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
-        if self.prev_token_kind == PrevTokenKind::DocComment {
-            return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
-        }
         if self.eat_keyword(keywords::If) {
             return self.parse_if_expr(ThinVec::new());
         } else {
@@ -3126,9 +3117,6 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                           span_lo: Span,
                           mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
 
         let pat = self.parse_pat()?;
         self.expect_keyword(keywords::In)?;
@@ -3144,9 +3132,6 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
     pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                             span_lo: Span,
                             mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         if self.token.is_keyword(keywords::Let) {
             return self.parse_while_let_expr(opt_ident, span_lo, attrs);
         }
@@ -3175,9 +3160,6 @@ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
     pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                            span_lo: Span,
                            mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         let span = span_lo.to(body.span);
@@ -3188,9 +3170,6 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
     pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
         -> PResult<'a, P<Expr>>
     {
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
@@ -3198,9 +3177,6 @@ pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
 
     // `match` token already eaten
     fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         let match_span = self.prev_span;
         let lo = self.prev_span;
         let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL,
@@ -3238,9 +3214,6 @@ pub fn parse_arm(&mut self) -> PResult<'a, Arm> {
         maybe_whole!(self, NtArm, |x| x);
 
         let attrs = self.parse_outer_attributes()?;
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         let pats = self.parse_pats()?;
         let guard = if self.eat_keyword(keywords::If) {
             Some(self.parse_expr()?)
@@ -3695,9 +3668,6 @@ fn parse_pat_ident(&mut self,
 
     /// Parse a local variable declaration
     fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
-        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
-            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
-        }
         let lo = self.span;
         let pat = self.parse_pat()?;
 
@@ -4187,8 +4157,6 @@ fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Blo
                 stmts.push(stmt);
             } else if self.token == token::Eof {
                 break;
-            } else if let token::DocComment(_) = self.token {
-                return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
             } else {
                 // Found only `;` or `}`.
                 continue;
index a32988aff12405dd7feeacf00c13b8f1e50e16a6..bceec186120a7245f1d291c2167cc83e391fa9aa 100644 (file)
@@ -8,19 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo3() -> i32 {
-    let mut x = 12;
-    /// z //~ ERROR E0585
-    while x < 1 {
-        /// x //~ ERROR E0585
-        //~^ ERROR attributes on non-item statements and expressions are experimental
-        x += 1;
+#![deny(unused_doc_comment)]
+
+fn foo() {
+    /// a //~ ERROR unused doc comment
+    let x = 12;
+
+    /// b //~ ERROR unused doc comment
+    match x {
+        /// c //~ ERROR unused doc comment
+        1 => {},
+        _ => {}
     }
-    /// d //~ ERROR E0585
-    return x;
+
+    /// foo //~ ERROR unused doc comment
+    unsafe {}
 }
 
 fn main() {
-    /// e //~ ERROR E0585
-    foo3();
-}
+    foo();
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/useless_comment2.rs b/src/test/compile-fail/useless_comment2.rs
deleted file mode 100644 (file)
index 52ac7b6..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo() {
-    /// a //~ ERROR E0585
-    let x = 12;
-
-    /// b //~ ERROR E0585
-    match x {
-        /// c //~ ERROR E0585
-        1 => {},
-        _ => {}
-    }
-}
-
-fn main() {
-    foo();
-}
\ No newline at end of file
diff --git a/src/test/compile-fail/useless_comment3.rs b/src/test/compile-fail/useless_comment3.rs
deleted file mode 100644 (file)
index c26031b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo() {
-    let x = 13;
-    /// x //~ ERROR E0585
-    if x == 12 {
-        /// y
-        println!("hello");
-    }
-}
-
-fn main() {
-    foo();
-}