More strict macro check
This commit is contained in:
15
src/attrs.rs
15
src/attrs.rs
@@ -3,7 +3,7 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use syntax::codemap::ExpnInfo;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::{in_macro, match_path, span_lint};
|
||||
|
||||
@@ -21,22 +21,19 @@ impl LintPass for AttrPass {
|
||||
|
||||
fn check_item(&mut self, cx: &Context, item: &Item) {
|
||||
if is_relevant_item(item) {
|
||||
cx.sess().codemap().with_expn_info(item.span.expn_id,
|
||||
|info| check_attrs(cx, info, &item.ident, &item.attrs))
|
||||
check_attrs(cx, item.span, &item.ident, &item.attrs)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
|
||||
if is_relevant_impl(item) {
|
||||
cx.sess().codemap().with_expn_info(item.span.expn_id,
|
||||
|info| check_attrs(cx, info, &item.ident, &item.attrs))
|
||||
check_attrs(cx, item.span, &item.ident, &item.attrs)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
|
||||
if is_relevant_trait(item) {
|
||||
cx.sess().codemap().with_expn_info(item.span.expn_id,
|
||||
|info| check_attrs(cx, info, &item.ident, &item.attrs))
|
||||
check_attrs(cx, item.span, &item.ident, &item.attrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,9 +86,9 @@ fn is_relevant_expr(expr: &Expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_attrs(cx: &Context, info: Option<&ExpnInfo>, ident: &Ident,
|
||||
fn check_attrs(cx: &Context, span: Span, ident: &Ident,
|
||||
attrs: &[Attribute]) {
|
||||
if in_macro(cx, info) { return; }
|
||||
if in_macro(cx, span) { return; }
|
||||
|
||||
for attr in attrs {
|
||||
if let MetaList(ref inline, ref values) = attr.node.value.node {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::{Spanned, ExpnInfo};
|
||||
use syntax::codemap::Spanned;
|
||||
|
||||
use utils::{in_macro, span_help_and_lint, snippet, snippet_block};
|
||||
|
||||
@@ -34,14 +34,13 @@ impl LintPass for CollapsibleIf {
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
|
||||
cx.sess().codemap().with_expn_info(expr.span.expn_id,
|
||||
|info| check_expr_expd(cx, expr, info))
|
||||
if !in_macro(cx, expr.span) {
|
||||
check_if(cx, expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_expd(cx: &Context, e: &Expr, info: Option<&ExpnInfo>) {
|
||||
if in_macro(cx, info) { return; }
|
||||
|
||||
fn check_if(cx: &Context, e: &Expr) {
|
||||
if let ExprIf(ref check, ref then, None) = e.node {
|
||||
if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) =
|
||||
single_stmt_of_block(then) {
|
||||
|
||||
@@ -2,9 +2,9 @@ use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use consts::{constant, is_negative};
|
||||
use consts::{constant_simple, is_negative};
|
||||
use consts::Constant::ConstantInt;
|
||||
use utils::{span_lint, snippet, in_external_macro};
|
||||
use utils::{span_lint, snippet, in_macro};
|
||||
|
||||
declare_lint! { pub IDENTITY_OP, Warn,
|
||||
"using identity operations, e.g. `x + 0` or `y / 1`" }
|
||||
@@ -18,6 +18,7 @@ impl LintPass for IdentityOp {
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, e: &Expr) {
|
||||
if in_macro(cx, e.span) { return; }
|
||||
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
|
||||
match cmp.node {
|
||||
BiAdd | BiBitOr | BiBitXor => {
|
||||
@@ -44,20 +45,16 @@ impl LintPass for IdentityOp {
|
||||
|
||||
|
||||
fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) {
|
||||
if let Some((c, needed_resolution)) = constant(cx, e) {
|
||||
if needed_resolution { return; } // skip linting w/ lookup for now
|
||||
if let ConstantInt(v, ty) = c {
|
||||
if let Some(ConstantInt(v, ty)) = constant_simple(e) {
|
||||
if match m {
|
||||
0 => v == 0,
|
||||
-1 => is_negative(ty) && v == 1,
|
||||
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, "..")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::ExpnInfo;
|
||||
use rustc::middle::ty::{TypeAndMut, TyRef};
|
||||
|
||||
use utils::{in_macro, span_lint};
|
||||
use utils::{in_external_macro, span_lint};
|
||||
|
||||
declare_lint!(pub MUT_MUT, Warn,
|
||||
"usage of double-mut refs, e.g. `&mut &mut ...` (either copy'n'paste error, \
|
||||
@@ -18,8 +17,7 @@ impl LintPass for MutMut {
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
|
||||
cx.sess().codemap().with_expn_info(expr.span.expn_id,
|
||||
|info| check_expr_expd(cx, expr, info))
|
||||
check_expr_mut(cx, expr)
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &Context, ty: &Ty) {
|
||||
@@ -28,8 +26,8 @@ impl LintPass for MutMut {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_expd(cx: &Context, expr: &Expr, info: Option<&ExpnInfo>) {
|
||||
if in_macro(cx, info) { return; }
|
||||
fn check_expr_mut(cx: &Context, expr: &Expr) {
|
||||
if in_external_macro(cx, expr.span) { return; }
|
||||
|
||||
fn unwrap_addr(expr : &Expr) -> Option<&Expr> {
|
||||
match expr.node {
|
||||
|
||||
@@ -6,7 +6,7 @@ use syntax::codemap::Span;
|
||||
use rustc_front::visit::{FnKind, Visitor, walk_ty};
|
||||
use rustc::middle::ty;
|
||||
|
||||
use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro};
|
||||
use utils::{match_type, snippet, span_lint, span_help_and_lint, in_macro, in_external_macro};
|
||||
use utils::{LL_PATH, VEC_PATH};
|
||||
|
||||
/// Handles all the linting of funky types
|
||||
@@ -321,7 +321,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) {
|
||||
}
|
||||
|
||||
fn check_type(cx: &Context, ty: &Ty) {
|
||||
if in_external_macro(cx, ty.span) { return; }
|
||||
if in_macro(cx, ty.span) { return; }
|
||||
let score = {
|
||||
let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
|
||||
visitor.visit_ty(ty);
|
||||
|
||||
21
src/utils.rs
21
src/utils.rs
@@ -14,9 +14,23 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"];
|
||||
pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
|
||||
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
||||
|
||||
/// returns true this expn_info was expanded by any macro
|
||||
pub fn in_macro(cx: &Context, span: Span) -> bool {
|
||||
cx.sess().codemap().with_expn_info(span.expn_id,
|
||||
|info| info.map_or(false, |i| {
|
||||
match i.callee.format {
|
||||
ExpnFormat::CompilerExpansion(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/// returns true if the macro that expanded the crate was outside of
|
||||
/// the current crate or was a compiler plugin
|
||||
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
|
||||
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
|
||||
/// invokes in_macro with the expansion info of the given span
|
||||
/// slightly heavy, try to use this after other checks have already happened
|
||||
fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
|
||||
// no ExpnInfo = no macro
|
||||
opt_info.map_or(false, |info| {
|
||||
match info.callee.format {
|
||||
@@ -43,11 +57,8 @@ 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))
|
||||
|info| in_macro_ext(cx, info))
|
||||
}
|
||||
|
||||
/// check if a DefId's path matches the given absolute type path
|
||||
|
||||
Reference in New Issue
Block a user