More macro checks
This commit is contained in:
parent
7a1082d916
commit
9ebcd0bf29
@ -4,7 +4,7 @@ use syntax::codemap::Span;
|
||||
|
||||
use consts::{constant, is_negative};
|
||||
use consts::Constant::ConstantInt;
|
||||
use utils::{span_lint, snippet};
|
||||
use utils::{span_lint, snippet, in_external_macro};
|
||||
|
||||
declare_lint! { pub IDENTITY_OP, Warn,
|
||||
"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,
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
if in_external_macro(cx, e.span) {return;}
|
||||
span_lint(cx, IDENTITY_OP, span, &format!(
|
||||
"the operation is ineffective. Consider reducing it to `{}`",
|
||||
snippet(cx, arg, "..")));
|
||||
|
@ -3,7 +3,8 @@ use syntax::ast;
|
||||
use syntax::ast::*;
|
||||
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,
|
||||
"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)
|
||||
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 = if let ExprBlock(_) = arms[0].body.node {
|
||||
body_code
|
||||
|
@ -3,7 +3,7 @@ use syntax::ast::*;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
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,
|
||||
"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)) {
|
||||
if in_external_macro(cx, spans.1) {return;}
|
||||
span_lint(cx, NEEDLESS_RETURN, spans.0, &format!(
|
||||
"unneeded return statement. Consider using `{}` \
|
||||
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) {
|
||||
if in_external_macro(cx, note_span) {return;}
|
||||
span_lint(cx, LET_AND_RETURN, lint_span,
|
||||
"returning the result of a let binding. \
|
||||
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::visit::{FnKind, Visitor, walk_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};
|
||||
|
||||
/// 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");
|
||||
|
||||
|
||||
fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
|
||||
if in_macro(cx, info) { return; }
|
||||
fn check_let_unit(cx: &Context, decl: &Decl) {
|
||||
if let DeclLocal(ref local) = decl.node {
|
||||
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
|
||||
if *bindtype == ty::TyTuple(vec![]) {
|
||||
if in_external_macro(cx, decl.span) { return; }
|
||||
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
|
||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||
snippet(cx, local.pat.span, "..")));
|
||||
@ -73,9 +72,7 @@ impl LintPass for LetPass {
|
||||
}
|
||||
|
||||
fn check_decl(&mut self, cx: &Context, decl: &Decl) {
|
||||
cx.sess().codemap().with_expn_info(
|
||||
decl.span.expn_id,
|
||||
|info| check_let_unit(cx, decl, info));
|
||||
check_let_unit(cx, decl)
|
||||
}
|
||||
}
|
||||
|
||||
|
11
src/utils.rs
11
src/utils.rs
@ -1,6 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::codemap::{ExpnInfo, Span};
|
||||
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
|
||||
use rustc::ast_map::Node::NodeExpr;
|
||||
use rustc::middle::def_id::DefId;
|
||||
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 {
|
||||
// no ExpnInfo = no macro
|
||||
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
|
||||
info.callee.span.map_or(true, |span| {
|
||||
// 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
|
||||
/// slightly heavy, try to use this after other checks have already happened
|
||||
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
|
||||
cx.sess().codemap().with_expn_info(span.expn_id,
|
||||
|info| in_macro(cx, info))
|
||||
|
Loading…
Reference in New Issue
Block a user