Skip to content

Commit e84072c

Browse files
committed
Split arg/method checking into its own function
1 parent 9a495f8 commit e84072c

File tree

1 file changed

+39
-38
lines changed

1 file changed

+39
-38
lines changed

clippy_lints/src/lines_filter_map_ok.rs

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -63,45 +63,46 @@ impl LateLintPass<'_> for LinesFilterMapOk {
6363
is_trait_method(cx, expr, sym::Iterator) &&
6464
let fm_method_str = fm_method.ident.as_str() &&
6565
matches!(fm_method_str, "filter_map" | "flat_map" | "flatten") &&
66-
is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines)
66+
is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines) &&
67+
should_lint(cx, fm_args, fm_method_str)
6768
{
68-
let lint = match fm_args {
69-
[] => fm_method_str == "flatten",
70-
[fm_arg] => {
71-
match &fm_arg.kind {
72-
// Detect `Result::ok`
73-
ExprKind::Path(qpath) =>
74-
cx.qpath_res(qpath, fm_arg.hir_id).opt_def_id().map(|did|
75-
match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)).unwrap_or_default(),
76-
// Detect `|x| x.ok()`
77-
ExprKind::Closure(Closure { body, .. }) =>
78-
if let Body { params: [param], value, .. } = cx.tcx.hir().body(*body) &&
79-
let ExprKind::MethodCall(method, receiver, [], _) = value.kind &&
80-
path_to_local_id(receiver, param.pat.hir_id) &&
81-
let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id)
82-
{
83-
is_diag_item_method(cx, method_did, sym::Result) && method.ident.as_str() == "ok"
84-
} else {
85-
false
86-
},
87-
_ => false,
88-
}
89-
}
90-
_ => false,
91-
};
92-
93-
if lint {
94-
span_lint_and_then(cx,
95-
LINES_FILTER_MAP_OK,
96-
fm_span,
97-
&format!("`{}()` will run forever if the iterator repeatedly produces an `Err`", fm_method.ident),
98-
|diag| {
99-
diag.span_note(
100-
fm_receiver.span,
101-
"this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error");
102-
diag.span_suggestion(fm_span, "replace with", "map_while(Result::ok)", Applicability::MaybeIncorrect);
103-
});
104-
}
69+
span_lint_and_then(cx,
70+
LINES_FILTER_MAP_OK,
71+
fm_span,
72+
&format!("`{}()` will run forever if the iterator repeatedly produces an `Err`", fm_method.ident),
73+
|diag| {
74+
diag.span_note(
75+
fm_receiver.span,
76+
"this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error");
77+
diag.span_suggestion(fm_span, "replace with", "map_while(Result::ok)", Applicability::MaybeIncorrect);
78+
});
10579
}
10680
}
10781
}
82+
83+
fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> bool {
84+
match args {
85+
[] => method_str == "flatten",
86+
[fm_arg] => {
87+
match &fm_arg.kind {
88+
// Detect `Result::ok`
89+
ExprKind::Path(qpath) =>
90+
cx.qpath_res(qpath, fm_arg.hir_id).opt_def_id().map(|did|
91+
match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)).unwrap_or_default(),
92+
// Detect `|x| x.ok()`
93+
ExprKind::Closure(Closure { body, .. }) =>
94+
if let Body { params: [param], value, .. } = cx.tcx.hir().body(*body) &&
95+
let ExprKind::MethodCall(method, receiver, [], _) = value.kind &&
96+
path_to_local_id(receiver, param.pat.hir_id) &&
97+
let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id)
98+
{
99+
is_diag_item_method(cx, method_did, sym::Result) && method.ident.as_str() == "ok"
100+
} else {
101+
false
102+
},
103+
_ => false,
104+
}
105+
},
106+
_ => false,
107+
}
108+
}

0 commit comments

Comments
 (0)