about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2021-03-06 17:46:50 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2021-03-11 19:40:24 +0900
commit2561b7ea062f0c07f27d9ebdf0c355ab29a4edf9 (patch)
tree6f16adb75b7e4f617795e7cef98a9bdf1c7c184f
parent0c8d143515a19b04a404765ecb8145a183dc2186 (diff)
downloadrust-2561b7ea062f0c07f27d9ebdf0c355ab29a4edf9.tar.gz
rust-2561b7ea062f0c07f27d9ebdf0c355ab29a4edf9.zip
move from_iter_insteam_of_collect to its own module
-rw-r--r--clippy_lints/src/methods/from_iter_instead_of_collect.rs67
-rw-r--r--clippy_lints/src/methods/mod.rs62
2 files changed, 69 insertions, 60 deletions
diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
new file mode 100644
index 00000000000..e50d0a33400
--- /dev/null
+++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -0,0 +1,67 @@
+use crate::utils::{get_trait_def_id, implements_trait, paths, span_lint_and_sugg, sugg};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::ty::Ty;
+
+use super::FROM_ITER_INSTEAD_OF_COLLECT;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+    let ty = cx.typeck_results().expr_ty(expr);
+    let arg_ty = cx.typeck_results().expr_ty(&args[0]);
+
+    if_chain! {
+        if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR);
+        if let Some(iter_id) = get_trait_def_id(cx, &paths::ITERATOR);
+
+        if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]);
+        then {
+            // `expr` implements `FromIterator` trait
+            let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par();
+            let turbofish = extract_turbofish(cx, expr, ty);
+            let sugg = format!("{}.collect::<{}>()", iter_expr, turbofish);
+            span_lint_and_sugg(
+                cx,
+                FROM_ITER_INSTEAD_OF_COLLECT,
+                expr.span,
+                "usage of `FromIterator::from_iter`",
+                "use `.collect()` instead of `::from_iter()`",
+                sugg,
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+}
+
+fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String {
+    if_chain! {
+        let call_site = expr.span.source_callsite();
+        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
+        let snippet_split = snippet.split("::").collect::<Vec<_>>();
+        if let Some((_, elements)) = snippet_split.split_last();
+
+        then {
+            // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
+            if let Some(type_specifier) = snippet_split.iter().find(|e| e.starts_with('<') && e.ends_with('>')) {
+                // remove the type specifier from the path elements
+                let without_ts = elements.iter().filter_map(|e| {
+                    if e == type_specifier { None } else { Some((*e).to_string()) }
+                }).collect::<Vec<_>>();
+                // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
+                format!("{}{}", without_ts.join("::"), type_specifier)
+            } else {
+                // type is not explicitly specified so wildcards are needed
+                // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
+                let ty_str = ty.to_string();
+                let start = ty_str.find('<').unwrap_or(0);
+                let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
+                let nb_wildcard = ty_str[start..end].split(',').count();
+                let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
+                format!("{}<{}>", elements.join("::"), wildcards)
+            }
+        } else {
+            ty.to_string()
+        }
+    }
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 28e2d896e6c..9a0ef6c01c1 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -5,6 +5,7 @@ mod expect_used;
 mod filetype_is_file;
 mod filter_map_identity;
 mod filter_next;
+mod from_iter_instead_of_collect;
 mod get_unwrap;
 mod implicit_clone;
 mod inefficient_to_string;
@@ -1761,7 +1762,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             hir::ExprKind::Call(ref func, ref args) => {
                 if let hir::ExprKind::Path(path) = &func.kind {
                     if match_qpath(path, &["from_iter"]) {
-                        lint_from_iter(cx, expr, args);
+                        from_iter_instead_of_collect::check(cx, expr, args);
                     }
                 }
             },
@@ -3440,65 +3441,6 @@ fn is_bool(ty: &hir::Ty<'_>) -> bool {
     }
 }
 
-fn lint_from_iter(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-    let ty = cx.typeck_results().expr_ty(expr);
-    let arg_ty = cx.typeck_results().expr_ty(&args[0]);
-
-    if_chain! {
-        if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR);
-        if let Some(iter_id) = get_trait_def_id(cx, &paths::ITERATOR);
-
-        if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]);
-        then {
-            // `expr` implements `FromIterator` trait
-            let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par();
-            let turbofish = extract_turbofish(cx, expr, ty);
-            let sugg = format!("{}.collect::<{}>()", iter_expr, turbofish);
-            span_lint_and_sugg(
-                cx,
-                FROM_ITER_INSTEAD_OF_COLLECT,
-                expr.span,
-                "usage of `FromIterator::from_iter`",
-                "use `.collect()` instead of `::from_iter()`",
-                sugg,
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-}
-
-fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String {
-    if_chain! {
-        let call_site = expr.span.source_callsite();
-        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
-        let snippet_split = snippet.split("::").collect::<Vec<_>>();
-        if let Some((_, elements)) = snippet_split.split_last();
-
-        then {
-            // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
-            if let Some(type_specifier) = snippet_split.iter().find(|e| e.starts_with('<') && e.ends_with('>')) {
-                // remove the type specifier from the path elements
-                let without_ts = elements.iter().filter_map(|e| {
-                    if e == type_specifier { None } else { Some((*e).to_string()) }
-                }).collect::<Vec<_>>();
-                // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
-                format!("{}{}", without_ts.join("::"), type_specifier)
-            } else {
-                // type is not explicitly specified so wildcards are needed
-                // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
-                let ty_str = ty.to_string();
-                let start = ty_str.find('<').unwrap_or(0);
-                let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
-                let nb_wildcard = ty_str[start..end].split(',').count();
-                let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
-                format!("{}<{}>", elements.join("::"), wildcards)
-            }
-        } else {
-            ty.to_string()
-        }
-    }
-}
-
 fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
     expected.constness == actual.constness
         && expected.unsafety == actual.unsafety