Skip to content

Commit fdf37fc

Browse files
ineffective_open_options: remove method_call use (#15271)
This is needed to split the lint crate. changelog: none
2 parents 8d6de0b + 104e265 commit fdf37fc

File tree

1 file changed

+51
-47
lines changed

1 file changed

+51
-47
lines changed
Lines changed: 51 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::source::SpanRangeExt;
3+
use clippy_utils::ty::is_type_diagnostic_item;
4+
use clippy_utils::{peel_blocks, peel_hir_expr_while, sym};
45
use rustc_ast::LitKind;
56
use rustc_errors::Applicability;
67
use rustc_hir::{Expr, ExprKind};
78
use rustc_lint::{LateContext, LateLintPass};
8-
use rustc_middle::ty;
99
use rustc_session::declare_lint_pass;
10-
use rustc_span::{BytePos, Span};
1110

1211
declare_clippy_lint! {
1312
/// ### What it does
@@ -43,53 +42,58 @@ 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
67+
if let Some(range) = call_span.map_range(cx, |_, text, range| {
68+
if text.get(..range.start)?.ends_with('.') {
69+
Some(range.start - 1..range.end)
70+
} else {
71+
None
72+
}
73+
}) =>
74+
{
75+
write = Some(call_span.with_lo(range.start));
76+
},
77+
_ => {},
78+
}
79+
}
80+
Some(recv)
81+
} else {
82+
None
83+
}
84+
});
7185

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);
86+
if append && let Some(write_span) = write {
87+
span_lint_and_sugg(
88+
cx,
89+
INEFFECTIVE_OPEN_OPTIONS,
90+
write_span,
91+
"unnecessary use of `.write(true)` because there is `.append(true)`",
92+
"remove `.write(true)`",
93+
String::new(),
94+
Applicability::MachineApplicable,
95+
);
7796
}
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-
);
9397
}
9498
}
9599
}

0 commit comments

Comments
 (0)