More macro checks
This commit is contained in:
@@ -4,7 +4,7 @@ use syntax::codemap::Span;
|
|||||||
|
|
||||||
use consts::{constant, is_negative};
|
use consts::{constant, is_negative};
|
||||||
use consts::Constant::ConstantInt;
|
use consts::Constant::ConstantInt;
|
||||||
use utils::{span_lint, snippet};
|
use utils::{span_lint, snippet, in_external_macro};
|
||||||
|
|
||||||
declare_lint! { pub IDENTITY_OP, Warn,
|
declare_lint! { pub IDENTITY_OP, Warn,
|
||||||
"using identity operations, e.g. `x + 0` or `y / 1`" }
|
"using identity operations, e.g. `x + 0` or `y / 1`" }
|
||||||
@@ -53,6 +53,7 @@ fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) {
|
|||||||
1 => !is_negative(ty) && v == 1,
|
1 => !is_negative(ty) && v == 1,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
} {
|
} {
|
||||||
|
if in_external_macro(cx, e.span) {return;}
|
||||||
span_lint(cx, IDENTITY_OP, span, &format!(
|
span_lint(cx, IDENTITY_OP, span, &format!(
|
||||||
"the operation is ineffective. Consider reducing it to `{}`",
|
"the operation is ineffective. Consider reducing it to `{}`",
|
||||||
snippet(cx, arg, "..")));
|
snippet(cx, arg, "..")));
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use syntax::ast;
|
|||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use utils::{snippet, snippet_block, span_lint, span_help_and_lint};
|
use utils::{snippet, snippet_block};
|
||||||
|
use utils::{span_lint, span_help_and_lint, in_external_macro};
|
||||||
|
|
||||||
declare_lint!(pub SINGLE_MATCH, Warn,
|
declare_lint!(pub SINGLE_MATCH, Warn,
|
||||||
"a match statement with a single nontrivial arm (i.e, where the other arm \
|
"a match statement with a single nontrivial arm (i.e, where the other arm \
|
||||||
@@ -36,6 +37,7 @@ impl LintPass for MatchPass {
|
|||||||
// finally, we don't want any content in the second arm (unit or empty block)
|
// finally, we don't want any content in the second arm (unit or empty block)
|
||||||
is_unit_expr(&arms[1].body)
|
is_unit_expr(&arms[1].body)
|
||||||
{
|
{
|
||||||
|
if in_external_macro(cx, expr.span) {return;}
|
||||||
let body_code = snippet_block(cx, arms[0].body.span, "..");
|
let body_code = snippet_block(cx, arms[0].body.span, "..");
|
||||||
let body_code = if let ExprBlock(_) = arms[0].body.node {
|
let body_code = if let ExprBlock(_) = arms[0].body.node {
|
||||||
body_code
|
body_code
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use syntax::ast::*;
|
|||||||
use syntax::codemap::{Span, Spanned};
|
use syntax::codemap::{Span, Spanned};
|
||||||
use syntax::visit::FnKind;
|
use syntax::visit::FnKind;
|
||||||
|
|
||||||
use utils::{span_lint, snippet, match_path};
|
use utils::{span_lint, snippet, match_path, in_external_macro};
|
||||||
|
|
||||||
declare_lint!(pub NEEDLESS_RETURN, Warn,
|
declare_lint!(pub NEEDLESS_RETURN, Warn,
|
||||||
"using a return statement like `return expr;` where an expression would suffice");
|
"using a return statement like `return expr;` where an expression would suffice");
|
||||||
@@ -58,6 +58,7 @@ impl ReturnPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) {
|
fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) {
|
||||||
|
if in_external_macro(cx, spans.1) {return;}
|
||||||
span_lint(cx, NEEDLESS_RETURN, spans.0, &format!(
|
span_lint(cx, NEEDLESS_RETURN, spans.0, &format!(
|
||||||
"unneeded return statement. Consider using `{}` \
|
"unneeded return statement. Consider using `{}` \
|
||||||
without the return and trailing semicolon",
|
without the return and trailing semicolon",
|
||||||
@@ -84,6 +85,7 @@ impl ReturnPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) {
|
fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) {
|
||||||
|
if in_external_macro(cx, note_span) {return;}
|
||||||
span_lint(cx, LET_AND_RETURN, lint_span,
|
span_lint(cx, LET_AND_RETURN, lint_span,
|
||||||
"returning the result of a let binding. \
|
"returning the result of a let binding. \
|
||||||
Consider returning the expression directly.");
|
Consider returning the expression directly.");
|
||||||
|
|||||||
11
src/types.rs
11
src/types.rs
@@ -5,9 +5,8 @@ use syntax::ast_util::{is_comparison_binop, binop_to_string};
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::visit::{FnKind, Visitor, walk_ty};
|
use syntax::visit::{FnKind, Visitor, walk_ty};
|
||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
use syntax::codemap::ExpnInfo;
|
|
||||||
|
|
||||||
use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro};
|
use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro};
|
||||||
use utils::{LL_PATH, VEC_PATH};
|
use utils::{LL_PATH, VEC_PATH};
|
||||||
|
|
||||||
/// Handles all the linting of funky types
|
/// Handles all the linting of funky types
|
||||||
@@ -55,11 +54,11 @@ declare_lint!(pub LET_UNIT_VALUE, Warn,
|
|||||||
"creating a let binding to a value of unit type, which usually can't be used afterwards");
|
"creating a let binding to a value of unit type, which usually can't be used afterwards");
|
||||||
|
|
||||||
|
|
||||||
fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
|
fn check_let_unit(cx: &Context, decl: &Decl) {
|
||||||
if in_macro(cx, info) { return; }
|
|
||||||
if let DeclLocal(ref local) = decl.node {
|
if let DeclLocal(ref local) = decl.node {
|
||||||
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
|
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
|
||||||
if *bindtype == ty::TyTuple(vec![]) {
|
if *bindtype == ty::TyTuple(vec![]) {
|
||||||
|
if in_external_macro(cx, decl.span) { return; }
|
||||||
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
|
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
|
||||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||||
snippet(cx, local.pat.span, "..")));
|
snippet(cx, local.pat.span, "..")));
|
||||||
@@ -73,9 +72,7 @@ impl LintPass for LetPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_decl(&mut self, cx: &Context, decl: &Decl) {
|
fn check_decl(&mut self, cx: &Context, decl: &Decl) {
|
||||||
cx.sess().codemap().with_expn_info(
|
check_let_unit(cx, decl)
|
||||||
decl.span.expn_id,
|
|
||||||
|info| check_let_unit(cx, decl, info));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/utils.rs
11
src/utils.rs
@@ -1,6 +1,6 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::codemap::{ExpnInfo, Span};
|
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
|
||||||
use rustc::ast_map::Node::NodeExpr;
|
use rustc::ast_map::Node::NodeExpr;
|
||||||
use rustc::middle::def_id::DefId;
|
use rustc::middle::def_id::DefId;
|
||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
@@ -18,6 +18,14 @@ pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "Linke
|
|||||||
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
|
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
|
||||||
// no ExpnInfo = no macro
|
// no ExpnInfo = no macro
|
||||||
opt_info.map_or(false, |info| {
|
opt_info.map_or(false, |info| {
|
||||||
|
if info.callee.format == ExpnFormat::CompilerExpansion {
|
||||||
|
if info.callee.name == "closure expansion" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if info.callee.format == ExpnFormat::MacroAttribute {
|
||||||
|
// these are all plugins
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// no span for the callee = external macro
|
// no span for the callee = external macro
|
||||||
info.callee.span.map_or(true, |span| {
|
info.callee.span.map_or(true, |span| {
|
||||||
// no snippet = external macro or compiler-builtin expansion
|
// no snippet = external macro or compiler-builtin expansion
|
||||||
@@ -31,6 +39,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// invokes in_macro with the expansion info of the given span
|
/// invokes in_macro with the expansion info of the given span
|
||||||
|
/// slightly heavy, try to use this after other checks have already happened
|
||||||
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
|
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
|
||||||
cx.sess().codemap().with_expn_info(span.expn_id,
|
cx.sess().codemap().with_expn_info(span.expn_id,
|
||||||
|info| in_macro(cx, info))
|
|info| in_macro(cx, info))
|
||||||
|
|||||||
Reference in New Issue
Block a user