Merge pull request #1046 from oli-obk/unify_span_lint_usage

use span_lint_and_then instead of adding to the `DiagnosticWrapper`
This commit is contained in:
llogiq 2016-06-27 17:20:03 +02:00 committed by GitHub
commit 5aea20da7f
4 changed files with 85 additions and 104 deletions

View File

@ -536,13 +536,14 @@ fn check_unwrap_or_default(cx: &LateContext, name: &str, fun: &hir::Expr, self_e
};
if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) {
span_lint(cx,
span_lint_and_then(cx,
OR_FUN_CALL,
span,
&format!("use of `{}` followed by a call to `{}`", name, path))
.span_suggestion(span,
"try this",
format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")));
&format!("use of `{}` followed by a call to `{}`", name, path),
|db| {
db.span_suggestion(span, "try this",
format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")));
});
return true;
}
}
@ -590,10 +591,11 @@ fn check_general_case(cx: &LateContext, name: &str, fun: &hir::Expr, self_expr:
(false, true) => snippet(cx, fun.span, ".."),
};
span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name))
.span_suggestion(span,
"try this",
format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg));
span_lint_and_then(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name), |db| {
db.span_suggestion(span,
"try this",
format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg));
});
}
if args.len() == 2 {
@ -621,15 +623,14 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) {
fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) {
if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty {
if let ty::TyRef(..) = inner.sty {
let mut db = span_lint(cx,
CLONE_DOUBLE_REF,
expr.span,
"using `clone` on a double-reference; \
this will copy the reference instead of cloning \
the inner type");
if let Some(snip) = snippet_opt(cx, arg.span) {
db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip));
}
span_lint_and_then(cx,
CLONE_DOUBLE_REF,
expr.span,
"using `clone` on a double-reference; \
this will copy the reference instead of cloning the inner type",
|db| if let Some(snip) = snippet_opt(cx, arg.span) {
db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip));
});
}
}
}
@ -641,13 +642,14 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
}
let arg_ty = cx.tcx.expr_ty(&args[1]);
if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) {
span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice")
.span_suggestion(expr.span,
"try this",
format!("{}.extend_from_slice({}{})",
snippet(cx, args[0].span, "_"),
r,
snippet(cx, span, "_")));
span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
db.span_suggestion(expr.span,
"try this",
format!("{}.extend_from_slice({}{})",
snippet(cx, args[0].span, "_"),
r,
snippet(cx, span, "_")));
});
}
}

View File

@ -6,7 +6,7 @@
use syntax::ast;
use syntax::codemap::Span;
use utils::paths;
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint};
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
/// **What it does:** This lints about type with a `fn new() -> Self` method
/// and no implementation of
@ -112,24 +112,26 @@ fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &h
!implements_trait(cx, self_ty, default_trait_id, Vec::new())
], {
if can_derive_default(self_ty, cx, default_trait_id) {
span_lint(cx,
NEW_WITHOUT_DEFAULT_DERIVE, span,
&format!("you should consider deriving a \
`Default` implementation for `{}`",
self_ty)).
span_suggestion(span,
"try this",
"#[derive(Default)]".into());
span_lint_and_then(cx,
NEW_WITHOUT_DEFAULT_DERIVE, span,
&format!("you should consider deriving a \
`Default` implementation for `{}`",
self_ty),
|db| {
db.span_suggestion(span, "try this", "#[derive(Default)]".into());
});
} else {
span_lint(cx,
NEW_WITHOUT_DEFAULT, span,
&format!("you should consider adding a \
`Default` implementation for `{}`",
self_ty)).
span_suggestion(span,
"try this",
format!("impl Default for {} {{ fn default() -> \
Self {{ {}::new() }} }}", self_ty, self_ty));
span_lint_and_then(cx,
NEW_WITHOUT_DEFAULT, span,
&format!("you should consider adding a \
`Default` implementation for `{}`",
self_ty),
|db| {
db.span_suggestion(span,
"try this",
format!("impl Default for {} {{ fn default() -> \
Self {{ {}::new() }} }}", self_ty, self_ty));
});
}
}}
}

View File

@ -5,7 +5,7 @@
use rustc::hir::intravisit::{Visitor, FnKind};
use std::ops::Deref;
use syntax::codemap::Span;
use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper};
use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint_and_then};
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability.
///
@ -197,49 +197,46 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span)
where T: Deref<Target = Expr>
{
fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) {
if cx.current_level(lint) != Level::Allow {
db.span_note(span, "previous binding is here");
}
}
if let Some(ref expr) = *init {
if is_self_shadow(name, expr) {
let db = span_lint(cx,
span_lint_and_then(cx,
SHADOW_SAME,
span,
&format!("`{}` is shadowed by itself in `{}`",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")));
note_orig(cx, db, SHADOW_SAME, prev_span);
snippet(cx, expr.span, "..")),
|db| { db.span_note(prev_span, "previous binding is here"); },
);
} else if contains_self(name, expr) {
let db = span_note_and_lint(cx,
SHADOW_REUSE,
pattern_span,
&format!("`{}` is shadowed by `{}` which reuses the original value",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
expr.span,
"initialization happens here");
note_orig(cx, db, SHADOW_REUSE, prev_span);
span_lint_and_then(cx,
SHADOW_REUSE,
pattern_span,
&format!("`{}` is shadowed by `{}` which reuses the original value",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
|db| {
db.span_note(expr.span, "initialization happens here");
db.span_note(prev_span, "previous binding is here");
});
} else {
let db = span_note_and_lint(cx,
SHADOW_UNRELATED,
pattern_span,
&format!("`{}` is shadowed by `{}`",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
expr.span,
"initialization happens here");
note_orig(cx, db, SHADOW_UNRELATED, prev_span);
span_lint_and_then(cx,
SHADOW_UNRELATED,
pattern_span,
&format!("`{}` is shadowed by `{}`",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
|db| {
db.span_note(expr.span, "initialization happens here");
db.span_note(prev_span, "previous binding is here");
});
}
} else {
let db = span_lint(cx,
span_lint_and_then(cx,
SHADOW_UNRELATED,
span,
&format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")));
note_orig(cx, db, SHADOW_UNRELATED, prev_span);
&format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")),
|db| { db.span_note(prev_span, "previous binding is here"); });
}
}

View File

@ -12,7 +12,6 @@
use std::borrow::Cow;
use std::env;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use syntax::ast::{self, LitKind, RangeLimits};
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
@ -453,71 +452,52 @@ fn drop(&mut self) {
}
}
impl<'a> DerefMut for DiagnosticWrapper<'a> {
fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> {
&mut self.0
}
}
impl<'a> Deref for DiagnosticWrapper<'a> {
type Target = DiagnosticBuilder<'a>;
fn deref(&self) -> &DiagnosticBuilder<'a> {
&self.0
}
}
impl<'a> DiagnosticWrapper<'a> {
fn wiki_link(&mut self, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() {
self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}",
self.0.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower()));
}
}
}
pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> {
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
if cx.current_level(lint) != Level::Allow {
db.wiki_link(lint);
}
db
}
pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str)
-> DiagnosticWrapper<'a> {
// FIXME: needless lifetime doesn't trigger here
pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
if cx.current_level(lint) != Level::Allow {
db.help(help);
db.0.help(help);
db.wiki_link(lint);
}
db
}
pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span,
note: &str)
-> DiagnosticWrapper<'a> {
note: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
if cx.current_level(lint) != Level::Allow {
if note_span == span {
db.note(note);
db.0.note(note);
} else {
db.span_note(note_span, note);
db.0.span_note(note_span, note);
}
db.wiki_link(lint);
}
db
}
pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
-> DiagnosticWrapper<'a>
where F: FnOnce(&mut DiagnosticWrapper)
where F: FnOnce(&mut DiagnosticBuilder<'a>)
{
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
if cx.current_level(lint) != Level::Allow {
f(&mut db);
f(&mut db.0);
db.wiki_link(lint);
}
db
}
/// Return the base type for references and raw pointers.