This commit is contained in:
llogiq 2016-02-08 23:48:04 +01:00
parent ceb9a8bdd7
commit 6525471214
3 changed files with 20 additions and 26 deletions

View File

@ -257,6 +257,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
ranges::RANGE_STEP_BY_ZERO, ranges::RANGE_STEP_BY_ZERO,
ranges::RANGE_ZIP_WITH_LEN, ranges::RANGE_ZIP_WITH_LEN,
regex::INVALID_REGEX, regex::INVALID_REGEX,
regex::REGEX_MACRO,
regex::TRIVIAL_REGEX, regex::TRIVIAL_REGEX,
returns::LET_AND_RETURN, returns::LET_AND_RETURN,
returns::NEEDLESS_RETURN, returns::NEEDLESS_RETURN,

View File

@ -1,11 +1,11 @@
use regex_syntax; use regex_syntax;
use std::error::Error; use std::error::Error;
use std::collections::HashSet;
use syntax::ast::Lit_::LitStr; use syntax::ast::Lit_::LitStr;
use syntax::ast::NodeId;
use syntax::codemap::{Span, BytePos}; use syntax::codemap::{Span, BytePos};
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use rustc_front::hir::*; use rustc_front::hir::*;
use rustc_front::intravisit::{Visitor, walk_block, FnKind}; use rustc_front::intravisit::{Visitor, walk_expr};
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
use rustc::lint::*; use rustc::lint::*;
@ -48,7 +48,7 @@ declare_lint! {
/// **Example:** `regex!("foo|bar")` /// **Example:** `regex!("foo|bar")`
declare_lint! { declare_lint! {
pub REGEX_MACRO, pub REGEX_MACRO,
Allow, Warn,
"finds use of `regex!(_)`, suggests `Regex::new(_)` instead" "finds use of `regex!(_)`, suggests `Regex::new(_)` instead"
} }
@ -62,15 +62,9 @@ impl LintPass for RegexPass {
} }
impl LateLintPass for RegexPass { impl LateLintPass for RegexPass {
fn check_fn(&mut self, fn check_crate(&mut self, cx: &LateContext, krate: &Crate) {
cx: &LateContext, let mut visitor = RegexVisitor { cx: cx, spans: HashSet::new() };
_: FnKind, krate.visit_all_items(&mut visitor);
_: &FnDecl,
block: &Block,
_: Span,
_: NodeId) {
let mut visitor = RegexVisitor { cx: cx, last: BytePos(0) };
visitor.visit_block(block);
} }
@ -169,25 +163,23 @@ fn is_trivial_regex(s: &regex_syntax::Expr) -> Option<&'static str> {
struct RegexVisitor<'v, 't: 'v> { struct RegexVisitor<'v, 't: 'v> {
cx: &'v LateContext<'v, 't>, cx: &'v LateContext<'v, 't>,
last: BytePos spans: HashSet<Span>,
} }
impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> { impl<'v, 't: 'v> Visitor<'v> for RegexVisitor<'v, 't> {
fn visit_block(&mut self, block: &'v Block) { fn visit_expr(&mut self, expr: &'v Expr) {
if let Some(ref expr) = block.expr { if let Some(span) = is_expn_of(self.cx, expr.span, "regex") {
if let Some(span) = is_expn_of(self.cx, expr.span, "regex") { if self.spans.contains(&span) {
if span.lo == BytePos(0) || span.lo == self.last {
return;
}
span_lint(self.cx,
REGEX_MACRO,
span,
&format!("regex!(_): {:?}, {:?}", self.last, span.lo));
//"`regex!(_)` found. Use `Regex::new(_)`, which is faster for now.");
self.last = span.lo;
return; return;
} }
span_lint(self.cx,
REGEX_MACRO,
span,
"`regex!(_)` found. \
Please use `Regex::new(_)`, which is faster for now.");
self.spans.insert(span);
return;
} }
walk_block(self, block); walk_expr(self, expr);
} }
} }

View File

@ -9,6 +9,7 @@ use std::collections::HashMap;
#[test] #[test]
#[deny(mut_mut)] #[deny(mut_mut)]
#[allow(regex_macro)]
fn test_regex() { fn test_regex() {
let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$"); let pattern = regex!(r"^(?P<level>[#]+)\s(?P<title>.+)$");
assert!(pattern.is_match("# headline")); assert!(pattern.is_match("# headline"));