Skip to content

Commit 7467b83

Browse files
committed
Suggest removing inline attributes
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.
1 parent 5f3c340 commit 7467b83

File tree

4 files changed

+64
-11
lines changed

4 files changed

+64
-11
lines changed

clippy_lints/src/inline_fn_without_body.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
use rustc::lint::*;
44
use rustc::hir::*;
55
use syntax::ast::{Attribute, Name};
6-
use utils::span_lint;
6+
use utils::span_lint_and_then;
7+
use utils::sugg::DiagnosticBuilderExt;
78

89
/// **What it does:** Checks for `#[inline]` on trait methods without bodies
910
///
@@ -51,11 +52,14 @@ fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) {
5152
continue;
5253
}
5354

54-
span_lint(
55+
span_lint_and_then(
5556
cx,
5657
INLINE_FN_WITHOUT_BODY,
5758
attr.span,
5859
&format!("use of `#[inline]` on trait method `{}` which has no body", name),
60+
|db| {
61+
db.suggest_remove_item(cx, attr.span, "remove");
62+
},
5963
);
6064
}
6165
}

clippy_lints/src/utils/sugg.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use syntax::print::pprust::token_to_string;
1515
use syntax::util::parser::AssocOp;
1616
use syntax::ast;
1717
use utils::{higher, snippet, snippet_opt};
18+
use syntax_pos::{BytePos, Pos};
1819

1920
/// A helper type to build suggestion correctly handling parenthesis.
2021
pub enum Sugg<'a> {
@@ -454,6 +455,19 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
454455
/// }");
455456
/// ```
456457
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
458+
459+
/// Suggest to completely remove an item.
460+
///
461+
/// This will remove an item and all following whitespace until the next non-whitespace
462+
/// character. This should work correctly if item is on the same indentation level as the
463+
/// following item.
464+
///
465+
/// # Example
466+
///
467+
/// ```rust,ignore
468+
/// db.suggest_remove_item(cx, item, "remove this")
469+
/// ```
470+
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str);
457471
}
458472

459473
impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
@@ -485,4 +499,21 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error
485499
self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent));
486500
}
487501
}
502+
503+
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) {
504+
let mut remove_span = item;
505+
let fmpos = cx.sess()
506+
.codemap()
507+
.lookup_byte_offset(remove_span.next_point().hi());
508+
509+
if let Some(ref src) = fmpos.fm.src {
510+
let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
511+
512+
if let Some(non_whitespace_offset) = non_whitespace_offset {
513+
remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset as u32))
514+
}
515+
}
516+
517+
self.span_suggestion(remove_span, msg, String::new());
518+
}
488519
}

tests/ui/inline_fn_without_body.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@
33

44
#![warn(inline_fn_without_body)]
55
#![allow(inline_always)]
6+
67
trait Foo {
78
#[inline]
89
fn default_inline();
910

10-
#[inline(always)]
11-
fn always_inline();
11+
#[inline(always)]fn always_inline();
12+
13+
#[inline(never)]
14+
15+
fn never_inline();
1216

1317
#[inline]
1418
fn has_body() {
1519
}
1620
}
1721

18-
fn main() {}
22+
fn main() {
23+
}
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
error: use of `#[inline]` on trait method `default_inline` which has no body
2-
--> $DIR/inline_fn_without_body.rs:7:5
2+
--> $DIR/inline_fn_without_body.rs:8:5
33
|
4-
7 | #[inline]
5-
| ^^^^^^^^^
4+
8 | #[inline]
5+
| _____-^^^^^^^^
6+
9 | | fn default_inline();
7+
| |____- help: remove
68
|
79
= note: `-D inline-fn-without-body` implied by `-D warnings`
810

911
error: use of `#[inline]` on trait method `always_inline` which has no body
10-
--> $DIR/inline_fn_without_body.rs:10:5
12+
--> $DIR/inline_fn_without_body.rs:11:5
1113
|
12-
10 | #[inline(always)]
13-
| ^^^^^^^^^^^^^^^^^
14+
11 | #[inline(always)]fn always_inline();
15+
| ^^^^^^^^^^^^^^^^^ help: remove
16+
17+
error: use of `#[inline]` on trait method `never_inline` which has no body
18+
--> $DIR/inline_fn_without_body.rs:13:5
19+
|
20+
13 | #[inline(never)]
21+
| _____-^^^^^^^^^^^^^^^
22+
14 | |
23+
15 | | fn never_inline();
24+
| |____- help: remove
25+
26+
error: aborting due to 3 previous errors
1427

0 commit comments

Comments
 (0)