Rustup to syntax::errors changes

This commit is contained in:
Manish Goregaokar
2016-01-01 02:09:03 +05:30
parent 70486b3006
commit 1605ef6ed4
13 changed files with 110 additions and 71 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "clippy" name = "clippy"
version = "0.0.33" version = "0.0.34"
authors = [ authors = [
"Manish Goregaokar <manishsmail@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>", "Andre Bogus <bogusandre@gmail.com>",

View File

@@ -9,7 +9,7 @@ use syntax::attr::*;
use syntax::ast::Attribute; use syntax::ast::Attribute;
use rustc_front::intravisit::{Visitor, walk_expr}; use rustc_front::intravisit::{Visitor, walk_expr};
use utils::{in_macro, LimitStack}; use utils::{in_macro, LimitStack, span_help_and_lint};
/// **What it does:** It `Warn`s on methods with high cyclomatic complexity /// **What it does:** It `Warn`s on methods with high cyclomatic complexity
/// ///
@@ -59,8 +59,8 @@ impl CyclomaticComplexity {
} else { } else {
let rust_cc = cc + divergence - narms; let rust_cc = cc + divergence - narms;
if rust_cc > self.limit.limit() { if rust_cc > self.limit.limit() {
cx.span_lint_help(CYCLOMATIC_COMPLEXITY, span, span_help_and_lint(cx, CYCLOMATIC_COMPLEXITY, span,
&format!("The function has a cyclomatic complexity of {}.", rust_cc), &format!("The function has a cyclomatic complexity of {}", rust_cc),
"You could split it up into multiple smaller functions"); "You could split it up into multiple smaller functions");
} }
} }
@@ -140,8 +140,9 @@ fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) {
#[cfg(not(feature="debugging"))] #[cfg(not(feature="debugging"))]
fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) { fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, span: Span) {
if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow { if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow {
cx.sess().span_note(span, &format!("Clippy encountered a bug calculating cyclomatic complexity \ cx.sess().span_note_without_error(span,
(hide this message with `#[allow(cyclomatic_complexity)]`): \ &format!("Clippy encountered a bug calculating cyclomatic complexity \
cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div)); (hide this message with `#[allow(cyclomatic_complexity)]`): \
cc = {}, arms = {}, div = {}. Please file a bug report.", cc, narms, div));
} }
} }

View File

@@ -84,9 +84,9 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
} }
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span,
"redundant closure found", "redundant closure found",
|| { |db| {
if let Some(snippet) = snippet_opt(cx, caller.span) { if let Some(snippet) = snippet_opt(cx, caller.span) {
cx.sess().span_suggestion(expr.span, db.span_suggestion(expr.span,
"remove closure as shown:", "remove closure as shown:",
snippet); snippet);
} }

View File

@@ -135,7 +135,7 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name,
has_is_empty(cx, &args[0]) { has_is_empty(cx, &args[0]) {
span_lint(cx, LEN_ZERO, span, &format!( span_lint(cx, LEN_ZERO, span, &format!(
"consider replacing the len comparison with `{}{}.is_empty()`", "consider replacing the len comparison with `{}{}.is_empty()`",
op, snippet(cx, args[0].span, "_"))) op, snippet(cx, args[0].span, "_")));
} }
} }
} }

View File

@@ -37,7 +37,7 @@ impl LateLintPass for MinMaxPass {
(_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (), (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (),
_ => { _ => {
span_lint(cx, MIN_MAX, expr.span, span_lint(cx, MIN_MAX, expr.span,
"this min/max combination leads to constant result") "this min/max combination leads to constant result");
} }
} }
} }

View File

@@ -30,8 +30,8 @@ impl LateLintPass for MutMut {
} }
fn check_ty(&mut self, cx: &LateContext, ty: &Ty) { fn check_ty(&mut self, cx: &LateContext, ty: &Ty) {
unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT, unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| { span_lint(cx, MUT_MUT,
ty.span, "generally you want to avoid `&mut &mut _` if possible")) ty.span, "generally you want to avoid `&mut &mut _` if possible"); });
} }
} }
@@ -52,12 +52,12 @@ fn check_expr_mut(cx: &LateContext, expr: &Expr) {
cx.tcx.expr_ty(e).sty { cx.tcx.expr_ty(e).sty {
span_lint(cx, MUT_MUT, expr.span, span_lint(cx, MUT_MUT, expr.span,
"this expression mutably borrows a mutable reference. \ "this expression mutably borrows a mutable reference. \
Consider reborrowing") Consider reborrowing");
} }
}, },
|_| { |_| {
span_lint(cx, MUT_MUT, expr.span, span_lint(cx, MUT_MUT, expr.span,
"generally you want to avoid `&mut &mut _` if possible") "generally you want to avoid `&mut &mut _` if possible");
} }
) )
}) })

View File

@@ -63,7 +63,7 @@ impl LateLintPass for MutexAtomic {
ty::TyInt(t) if t != ast::TyIs => ty::TyInt(t) if t != ast::TyIs =>
span_lint(cx, MUTEX_INTEGER, expr.span, &msg), span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
_ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg) _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg)
} };
} }
} }
} }

View File

@@ -33,21 +33,27 @@ impl EarlyLintPass for Precedence {
if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node { if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node {
if !is_bit_op(op) { return; } if !is_bit_op(op) { return; }
match (is_arith_expr(left), is_arith_expr(right)) { match (is_arith_expr(left), is_arith_expr(right)) {
(true, true) => span_lint(cx, PRECEDENCE, expr.span, (true, true) => {
span_lint(cx, PRECEDENCE, expr.span,
&format!("operator precedence can trip the unwary. \ &format!("operator precedence can trip the unwary. \
Consider parenthesizing your expression:\ Consider parenthesizing your expression:\
`({}) {} ({})`", snippet(cx, left.span, ".."), `({}) {} ({})`", snippet(cx, left.span, ".."),
op.to_string(), snippet(cx, right.span, ".."))), op.to_string(), snippet(cx, right.span, "..")));
(true, false) => span_lint(cx, PRECEDENCE, expr.span, },
(true, false) => {
span_lint(cx, PRECEDENCE, expr.span,
&format!("operator precedence can trip the unwary. \ &format!("operator precedence can trip the unwary. \
Consider parenthesizing your expression:\ Consider parenthesizing your expression:\
`({}) {} {}`", snippet(cx, left.span, ".."), `({}) {} {}`", snippet(cx, left.span, ".."),
op.to_string(), snippet(cx, right.span, ".."))), op.to_string(), snippet(cx, right.span, "..")));
(false, true) => span_lint(cx, PRECEDENCE, expr.span, },
(false, true) => {
span_lint(cx, PRECEDENCE, expr.span,
&format!("operator precedence can trip the unwary. \ &format!("operator precedence can trip the unwary. \
Consider parenthesizing your expression:\ Consider parenthesizing your expression:\
`{} {} ({})`", snippet(cx, left.span, ".."), `{} {} ({})`", snippet(cx, left.span, ".."),
op.to_string(), snippet(cx, right.span, ".."))), op.to_string(), snippet(cx, right.span, "..")));
},
_ => (), _ => (),
} }
} }
@@ -57,12 +63,13 @@ impl EarlyLintPass for Precedence {
if let Some(slf) = args.first() { if let Some(slf) = args.first() {
if let ExprLit(ref lit) = slf.node { if let ExprLit(ref lit) = slf.node {
match lit.node { match lit.node {
LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) => {
span_lint(cx, PRECEDENCE, expr.span, &format!( span_lint(cx, PRECEDENCE, expr.span, &format!(
"unary minus has lower precedence than \ "unary minus has lower precedence than \
method call. Consider adding parentheses \ method call. Consider adding parentheses \
to clarify your intent: -({})", to clarify your intent: -({})",
snippet(cx, rhs.span, ".."))), snippet(cx, rhs.span, "..")));
}
_ => () _ => ()
} }
} }

View File

@@ -75,9 +75,9 @@ impl ReturnPass {
if in_external_macro(cx, spans.1) {return;} if in_external_macro(cx, spans.1) {return;}
span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, span_lint_and_then(cx, NEEDLESS_RETURN, spans.0,
"unneeded return statement", "unneeded return statement",
|| { |db| {
if let Some(snippet) = snippet_opt(cx, spans.1) { if let Some(snippet) = snippet_opt(cx, spans.1) {
cx.sess().span_suggestion(spans.0, db.span_suggestion(spans.0,
"remove `return` as shown:", "remove `return` as shown:",
snippet); snippet);
} }
@@ -105,11 +105,11 @@ impl ReturnPass {
fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) { fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) {
if in_external_macro(cx, note_span) {return;} if in_external_macro(cx, note_span) {return;}
span_lint(cx, LET_AND_RETURN, lint_span, let mut db = span_lint(cx, LET_AND_RETURN, lint_span,
"returning the result of a let binding from a block. \ "returning the result of a let binding from a block. \
Consider returning the expression directly."); Consider returning the expression directly.");
if cx.current_level(LET_AND_RETURN) != Level::Allow { if cx.current_level(LET_AND_RETURN) != Level::Allow {
cx.sess().span_note(note_span, db.span_note(note_span,
"this expression can be directly returned"); "this expression can be directly returned");
} }
} }

View File

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

View File

@@ -75,13 +75,13 @@ impl LateLintPass for StringAdd {
} }
span_lint(cx, STRING_ADD, e.span, span_lint(cx, STRING_ADD, e.span,
"you added something to a string. \ "you added something to a string. \
Consider using `String::push_str()` instead") Consider using `String::push_str()` instead");
} }
} else if let ExprAssign(ref target, ref src) = e.node { } else if let ExprAssign(ref target, ref src) = e.node {
if is_string(cx, target) && is_add(cx, src, target) { if is_string(cx, target) && is_add(cx, src, target) {
span_lint(cx, STRING_ADD_ASSIGN, e.span, span_lint(cx, STRING_ADD_ASSIGN, e.span,
"you assigned the result of adding something to this string. \ "you assigned the result of adding something to this string. \
Consider using `String::push_str()` instead") Consider using `String::push_str()` instead");
} }
} }
} }

View File

@@ -8,10 +8,12 @@ use rustc::middle::ty;
use std::borrow::Cow; use std::borrow::Cow;
use syntax::ast::Lit_::*; use syntax::ast::Lit_::*;
use syntax::ast; use syntax::ast;
use syntax::errors::DiagnosticBuilder;
use syntax::ptr::P; use syntax::ptr::P;
use rustc::session::Session; use rustc::session::Session;
use std::str::FromStr; use std::str::FromStr;
use std::ops::{Deref, DerefMut};
pub type MethodArgs = HirVec<P<Expr>>; pub type MethodArgs = HirVec<P<Expr>>;
@@ -307,63 +309,91 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
} else { None } } else { None }
} }
#[cfg(not(feature="structured_logging"))] pub struct DiagnosticWrapper<'a>(pub DiagnosticBuilder<'a>);
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
cx.span_lint(lint, sp, msg); impl<'a> Drop for DiagnosticWrapper<'a> {
if cx.current_level(lint) != Level::Allow { fn drop(&mut self) {
cx.sess().fileline_help(sp, &format!("for further information visit \ self.0.emit();
https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower()))
} }
} }
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
}
}
#[cfg(not(feature="structured_logging"))]
pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint,
sp: Span, msg: &str) -> DiagnosticWrapper<'a> {
let mut db = cx.struct_span_lint(lint, sp, msg);
if cx.current_level(lint) != Level::Allow {
db.fileline_help(sp, &format!("for further information visit \
https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower()));
}
DiagnosticWrapper(db)
}
#[cfg(feature="structured_logging")] #[cfg(feature="structured_logging")]
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint,
sp: Span, msg: &str) -> DiagnosticWrapper<'a> {
// lint.name / lint.desc is can give details of the lint // lint.name / lint.desc is can give details of the lint
// cx.sess().codemap() has all these nice functions for line/column/snippet details // cx.sess().codemap() has all these nice functions for line/column/snippet details
// http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string
cx.span_lint(lint, sp, msg); let mut db = cx.struct_span_lint(lint, sp, msg);
if cx.current_level(lint) != Level::Allow { if cx.current_level(lint) != Level::Allow {
cx.sess().fileline_help(sp, &format!("for further information visit \ db.fileline_help(sp, &format!("for further information visit \
https://github.com/Manishearth/rust-clippy/wiki#{}", https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower())) lint.name_lower()));
} }
DiagnosticWrapper(db)
} }
pub fn span_help_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span,
msg: &str, help: &str) { msg: &str, help: &str) -> DiagnosticWrapper<'a> {
cx.span_lint(lint, span, msg); let mut db = cx.struct_span_lint(lint, span, msg);
if cx.current_level(lint) != Level::Allow { if cx.current_level(lint) != Level::Allow {
cx.sess().fileline_help(span, &format!("{}\nfor further information \ db.fileline_help(span, &format!("{}\nfor further information \
visit https://github.com/Manishearth/rust-clippy/wiki#{}", visit https://github.com/Manishearth/rust-clippy/wiki#{}",
help, lint.name_lower())) help, lint.name_lower()));
} }
DiagnosticWrapper(db)
} }
pub fn span_note_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span, pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span,
msg: &str, note_span: Span, note: &str) { msg: &str, note_span: Span, note: &str) -> DiagnosticWrapper<'a> {
cx.span_lint(lint, span, msg); let mut db = cx.struct_span_lint(lint, span, msg);
if cx.current_level(lint) != Level::Allow { if cx.current_level(lint) != Level::Allow {
if note_span == span { if note_span == span {
cx.sess().fileline_note(note_span, note) db.fileline_note(note_span, note);
} else { } else {
cx.sess().span_note(note_span, note) db.span_note(note_span, note);
} }
cx.sess().fileline_help(span, &format!("for further information visit \ db.fileline_help(span, &format!("for further information visit \
https://github.com/Manishearth/rust-clippy/wiki#{}", https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower())) lint.name_lower()));
} }
DiagnosticWrapper(db)
} }
pub fn span_lint_and_then<T: LintContext, F>(cx: &T, lint: &'static Lint, sp: Span, pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span,
msg: &str, f: F) where F: Fn() { msg: &str, f: F) -> DiagnosticWrapper<'a> where F: Fn(&mut DiagnosticWrapper) {
cx.span_lint(lint, sp, msg); let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
if cx.current_level(lint) != Level::Allow { if cx.current_level(lint) != Level::Allow {
f(); f(&mut db);
cx.sess().fileline_help(sp, &format!("for further information visit \ db.fileline_help(sp, &format!("for further information visit \
https://github.com/Manishearth/rust-clippy/wiki#{}", https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower())) lint.name_lower()));
} }
db
} }
/// return the base type for references and raw pointers /// return the base type for references and raw pointers

View File

@@ -4,7 +4,8 @@
#![deny(cyclomatic_complexity)] #![deny(cyclomatic_complexity)]
#![allow(unused)] #![allow(unused)]
fn main() { //~ ERROR: The function has a cyclomatic complexity of 28.
fn main() { //~ERROR The function has a cyclomatic complexity of 28
if true { if true {
println!("a"); println!("a");
} }