mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 23:20:39 +00:00
Auto merge of #11111 - Alexendoo:regex-def-paths, r=giraffate
Fix regex lints for regex 1.9.0 regex 1.9.0 was [just released](https://blog.burntsushi.net/regex-internals/), which changes where the types are defined. Instead of updating the definitions to the ones in 1.9.0 this PR uses [`def_path_def_ids`](https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/fn.def_path_def_ids.html) on the canonical paths so that we don't have to worry about third party crate internals This means that it still works with older regex versions too, and will for any future layout changes. I tested it with 1.8.4 and 1.9.0 changelog: [`INVALID_REGEX`], [`TRIVIAL_REGEX`]: now works with regex 1.9.0
This commit is contained in:
commit
dd8e44c5a2
3 changed files with 53 additions and 27 deletions
|
@ -722,7 +722,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
|
||||
store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
|
||||
store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
|
||||
store.register_late_pass(|_| Box::new(regex::Regex));
|
||||
store.register_late_pass(|_| Box::<regex::Regex>::default());
|
||||
let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
|
||||
store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone())));
|
||||
store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
|
||||
|
|
|
@ -3,12 +3,12 @@ use std::fmt::Display;
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{match_def_path, paths};
|
||||
use if_chain::if_chain;
|
||||
use clippy_utils::{def_path_def_ids, path_def_id, paths};
|
||||
use rustc_ast::ast::{LitKind, StrStyle};
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -55,26 +55,52 @@ declare_clippy_lint! {
|
|||
"trivial regular expressions"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
|
||||
#[derive(Copy, Clone)]
|
||||
enum RegexKind {
|
||||
Unicode,
|
||||
UnicodeSet,
|
||||
Bytes,
|
||||
BytesSet,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Regex {
|
||||
definitions: DefIdMap<RegexKind>,
|
||||
}
|
||||
|
||||
impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Regex {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
// We don't use `match_def_path` here because that relies on matching the exact path, which changed
|
||||
// between regex 1.8 and 1.9
|
||||
//
|
||||
// `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform
|
||||
// the operation once and store the results
|
||||
let mut resolve = |path, kind| {
|
||||
for id in def_path_def_ids(cx, path) {
|
||||
self.definitions.insert(id, kind);
|
||||
}
|
||||
};
|
||||
|
||||
resolve(&paths::REGEX_NEW, RegexKind::Unicode);
|
||||
resolve(&paths::REGEX_BUILDER_NEW, RegexKind::Unicode);
|
||||
resolve(&paths::REGEX_SET_NEW, RegexKind::UnicodeSet);
|
||||
resolve(&paths::REGEX_BYTES_NEW, RegexKind::Bytes);
|
||||
resolve(&paths::REGEX_BYTES_BUILDER_NEW, RegexKind::Bytes);
|
||||
resolve(&paths::REGEX_BYTES_SET_NEW, RegexKind::BytesSet);
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::Call(fun, [arg]) = expr.kind;
|
||||
if let ExprKind::Path(ref qpath) = fun.kind;
|
||||
if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||
then {
|
||||
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
|
||||
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
|
||||
check_regex(cx, arg, true);
|
||||
} else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) ||
|
||||
match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) {
|
||||
check_regex(cx, arg, false);
|
||||
} else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) {
|
||||
check_set(cx, arg, true);
|
||||
} else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) {
|
||||
check_set(cx, arg, false);
|
||||
}
|
||||
if let ExprKind::Call(fun, [arg]) = expr.kind
|
||||
&& let Some(def_id) = path_def_id(cx, fun)
|
||||
&& let Some(regex_kind) = self.definitions.get(&def_id)
|
||||
{
|
||||
match regex_kind {
|
||||
RegexKind::Unicode => check_regex(cx, arg, true),
|
||||
RegexKind::UnicodeSet => check_set(cx, arg, true),
|
||||
RegexKind::Bytes => check_regex(cx, arg, false),
|
||||
RegexKind::BytesSet => check_set(cx, arg, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,12 +94,12 @@ pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
|
|||
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
|
||||
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
||||
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
|
||||
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
|
||||
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
|
||||
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
|
||||
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
|
||||
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
|
||||
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
|
||||
pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
|
||||
pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
|
||||
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
|
||||
pub const REGEX_BYTES_SET_NEW: [&str; 4] = ["regex", "bytes", "RegexSet", "new"];
|
||||
pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
|
||||
pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
|
||||
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
|
||||
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
|
||||
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
|
||||
|
|
Loading…
Reference in a new issue