Skip to content

Commit 06e6927

Browse files
committed
ineffective_open_options: refactor, don't use method_call
1 parent dcc7906 commit 06e6927

File tree

1 file changed

+41
-47
lines changed

1 file changed

+41
-47
lines changed
Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
use crate::methods::method_call;
21
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::{peel_blocks, sym};
2+
use clippy_utils::ty::is_type_diagnostic_item;
3+
use clippy_utils::{peel_blocks, peel_hir_expr_while, sym};
44
use rustc_ast::LitKind;
55
use rustc_errors::Applicability;
66
use rustc_hir::{Expr, ExprKind};
77
use rustc_lint::{LateContext, LateLintPass};
8-
use rustc_middle::ty;
98
use rustc_session::declare_lint_pass;
10-
use rustc_span::{BytePos, Span};
9+
use rustc_span::BytePos;
1110

1211
declare_clippy_lint! {
1312
/// ### What it does
@@ -43,53 +42,48 @@ declare_clippy_lint! {
4342

4443
declare_lint_pass!(IneffectiveOpenOptions => [INEFFECTIVE_OPEN_OPTIONS]);
4544

46-
fn index_if_arg_is_boolean(args: &[Expr<'_>], call_span: Span) -> Option<Span> {
47-
if let [arg] = args
48-
&& let ExprKind::Lit(lit) = peel_blocks(arg).kind
49-
&& lit.node == LitKind::Bool(true)
50-
{
51-
// The `.` is not included in the span so we cheat a little bit to include it as well.
52-
Some(call_span.with_lo(call_span.lo() - BytePos(1)))
53-
} else {
54-
None
55-
}
56-
}
57-
5845
impl<'tcx> LateLintPass<'tcx> for IneffectiveOpenOptions {
5946
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
60-
let Some((sym::open, mut receiver, [_arg], _, _)) = method_call(expr) else {
61-
return;
62-
};
63-
let receiver_ty = cx.typeck_results().expr_ty(receiver);
64-
match receiver_ty.peel_refs().kind() {
65-
ty::Adt(adt, _) if cx.tcx.is_diagnostic_item(sym::FsOpenOptions, adt.did()) => {},
66-
_ => return,
67-
}
68-
69-
let mut append = None;
70-
let mut write = None;
47+
if let ExprKind::MethodCall(name, recv, [_], _) = expr.kind
48+
&& name.ident.name == sym::open
49+
&& !expr.span.from_expansion()
50+
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::FsOpenOptions)
51+
{
52+
let mut append = false;
53+
let mut write = None;
54+
peel_hir_expr_while(recv, |e| {
55+
if let ExprKind::MethodCall(name, recv, args, call_span) = e.kind
56+
&& !e.span.from_expansion()
57+
{
58+
if let [arg] = args
59+
&& let ExprKind::Lit(lit) = peel_blocks(arg).kind
60+
&& matches!(lit.node, LitKind::Bool(true))
61+
&& !arg.span.from_expansion()
62+
&& !lit.span.from_expansion()
63+
{
64+
match name.ident.name {
65+
sym::append => append = true,
66+
sym::write => write = Some(call_span.with_lo(call_span.lo() - BytePos(1))),
67+
_ => {},
68+
}
69+
}
70+
Some(recv)
71+
} else {
72+
None
73+
}
74+
});
7175

72-
while let Some((name, recv, args, _, span)) = method_call(receiver) {
73-
if name == sym::append {
74-
append = index_if_arg_is_boolean(args, span);
75-
} else if name == sym::write {
76-
write = index_if_arg_is_boolean(args, span);
76+
if append && let Some(write_span) = write {
77+
span_lint_and_sugg(
78+
cx,
79+
INEFFECTIVE_OPEN_OPTIONS,
80+
write_span,
81+
"unnecessary use of `.write(true)` because there is `.append(true)`",
82+
"remove `.write(true)`",
83+
String::new(),
84+
Applicability::MachineApplicable,
85+
);
7786
}
78-
receiver = recv;
79-
}
80-
81-
if let Some(write_span) = write
82-
&& append.is_some()
83-
{
84-
span_lint_and_sugg(
85-
cx,
86-
INEFFECTIVE_OPEN_OPTIONS,
87-
write_span,
88-
"unnecessary use of `.write(true)` because there is `.append(true)`",
89-
"remove `.write(true)`",
90-
String::new(),
91-
Applicability::MachineApplicable,
92-
);
9387
}
9488
}
9589
}

0 commit comments

Comments
 (0)