]> git.lizzy.rs Git - rust.git/commitdiff
Suggest removing inline attributes
authorRyan Cumming <etaoins@gmail.com>
Wed, 17 Jan 2018 19:08:03 +0000 (06:08 +1100)
committerRyan Cumming <etaoins@gmail.com>
Thu, 18 Jan 2018 09:02:42 +0000 (20:02 +1100)
This adds a `suggest_remove_item` helper that will remove an item and
all trailing whitespace. This should handle both attributes on the same
line as the function and on a separate line; the function takes the
position of the original attribute.

clippy_lints/src/inline_fn_without_body.rs
clippy_lints/src/utils/sugg.rs
tests/ui/inline_fn_without_body.rs
tests/ui/inline_fn_without_body.stderr

index f2b7560867499c8444997b815e5f41fbc7d76567..1bb9519d304c33fbe626a352933fb56f34c7f31b 100644 (file)
@@ -3,7 +3,8 @@
 use rustc::lint::*;
 use rustc::hir::*;
 use syntax::ast::{Attribute, Name};
-use utils::span_lint;
+use utils::span_lint_and_then;
+use utils::sugg::DiagnosticBuilderExt;
 
 /// **What it does:** Checks for `#[inline]` on trait methods without bodies
 ///
@@ -51,11 +52,14 @@ fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) {
             continue;
         }
 
-        span_lint(
+        span_lint_and_then(
             cx,
             INLINE_FN_WITHOUT_BODY,
             attr.span,
             &format!("use of `#[inline]` on trait method `{}` which has no body", name),
+            |db| {
+                db.suggest_remove_item(cx, attr.span, "remove");
+            },
         );
     }
 }
index c680e3eeb5b2b0e41f08002a40b1cf552c12a33b..2f651917bc157c128ffe292f5646985d296b7ab1 100644 (file)
@@ -15,6 +15,7 @@
 use syntax::util::parser::AssocOp;
 use syntax::ast;
 use utils::{higher, snippet, snippet_opt};
+use syntax_pos::{BytePos, Pos};
 
 /// A helper type to build suggestion correctly handling parenthesis.
 pub enum Sugg<'a> {
@@ -454,6 +455,19 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
     /// }");
     /// ```
     fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
+
+    /// Suggest to completely remove an item.
+    ///
+    /// This will remove an item and all following whitespace until the next non-whitespace
+    /// character. This should work correctly if item is on the same indentation level as the
+    /// following item.
+    ///
+    /// # Example
+    ///
+    /// ```rust,ignore
+    /// db.suggest_remove_item(cx, item, "remove this")
+    /// ```
+    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str);
 }
 
 impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
@@ -485,4 +499,21 @@ fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str
             self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent));
         }
     }
+
+    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) {
+        let mut remove_span = item;
+        let fmpos = cx.sess()
+            .codemap()
+            .lookup_byte_offset(remove_span.next_point().hi());
+
+        if let Some(ref src) = fmpos.fm.src {
+            let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
+
+            if let Some(non_whitespace_offset) = non_whitespace_offset {
+                remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset as u32))
+            }
+        }
+
+        self.span_suggestion(remove_span, msg, String::new());
+    }
 }
index aa50d7c96c6f593c352a880f596c4e8454d97bfe..82e073184d3541f222488cdfba405f9710e9abde 100644 (file)
@@ -3,16 +3,21 @@
 
 #![warn(inline_fn_without_body)]
 #![allow(inline_always)]
+
 trait Foo {
     #[inline]
     fn default_inline();
 
-    #[inline(always)]
-    fn always_inline();
+    #[inline(always)]fn always_inline();
+
+    #[inline(never)]
+
+    fn never_inline();
 
     #[inline]
     fn has_body() {
     }
 }
 
-fn main() {}
+fn main() {
+}
index 1f4b4afb264694cb3f4104af240c60fb79b003f5..fd26013d11ea9049820d893cd1b4f77810a80fa2 100644 (file)
@@ -1,14 +1,27 @@
 error: use of `#[inline]` on trait method `default_inline` which has no body
- --> $DIR/inline_fn_without_body.rs:7:5
+ --> $DIR/inline_fn_without_body.rs:8:5
   |
-7 |     #[inline]
-  |     ^^^^^^^^^
+8 |       #[inline]
+  |  _____-^^^^^^^^
+9 | |     fn default_inline();
+  | |____- help: remove
   |
   = note: `-D inline-fn-without-body` implied by `-D warnings`
 
 error: use of `#[inline]` on trait method `always_inline` which has no body
-  --> $DIR/inline_fn_without_body.rs:10:5
+  --> $DIR/inline_fn_without_body.rs:11:5
    |
-10 |     #[inline(always)]
-   |     ^^^^^^^^^^^^^^^^^
+11 |     #[inline(always)]fn always_inline();
+   |     ^^^^^^^^^^^^^^^^^ help: remove
+
+error: use of `#[inline]` on trait method `never_inline` which has no body
+  --> $DIR/inline_fn_without_body.rs:13:5
+   |
+13 |       #[inline(never)]
+   |  _____-^^^^^^^^^^^^^^^
+14 | |
+15 | |     fn never_inline();
+   | |____- help: remove
+
+error: aborting due to 3 previous errors