Skip to content

Commit 9775cd8

Browse files
committed
use expr_sugg on various lints
1 parent b7d3b28 commit 9775cd8

File tree

10 files changed

+86
-129
lines changed

10 files changed

+86
-129
lines changed

clippy_lints/src/from_str_radix_10.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::sugg::Sugg;
33
use clippy_utils::ty::is_type_diagnostic_item;
44
use if_chain::if_chain;
55
use rustc_errors::Applicability;
@@ -76,20 +76,17 @@ impl LateLintPass<'tcx> for FromStrRadix10 {
7676
&arguments[0]
7777
};
7878

79-
let sugg = Sugg::hir_with_applicability(
80-
cx,
81-
expr,
82-
"<string>",
83-
&mut Applicability::MachineApplicable
84-
).maybe_par();
85-
79+
let mut app = Applicability::MachineApplicable;
8680
span_lint_and_sugg(
8781
cx,
8882
FROM_STR_RADIX_10,
8983
exp.span,
9084
"this call to `from_str_radix` can be replaced with a call to `str::parse`",
9185
"try",
92-
format!("{}.parse::<{}>()", sugg, prim_ty.name_str()),
86+
expr_sugg!(
87+
cx, &mut app, exp.span.ctxt(),
88+
$expr(expr).parse::<$ident(prim_ty.name_str())>()
89+
).into_string(),
9390
Applicability::MaybeIncorrect
9491
);
9592
}

clippy_lints/src/methods/bytes_nth.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::snippet_with_applicability;
33
use clippy_utils::ty::is_type_diagnostic_item;
44
use rustc_errors::Applicability;
55
use rustc_hir::Expr;
@@ -17,18 +17,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
1717
} else {
1818
return;
1919
};
20-
let mut applicability = Applicability::MachineApplicable;
20+
let mut app = Applicability::MachineApplicable;
2121
span_lint_and_sugg(
2222
cx,
2323
BYTES_NTH,
2424
expr.span,
25-
&format!("called `.byte().nth()` on a `{}`", caller_type),
25+
&format!("called `.bytes().nth()` on a `{}`", caller_type),
2626
"try",
27-
format!(
28-
"{}.as_bytes().get({})",
29-
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
30-
snippet_with_applicability(cx, n_arg.span, "..", &mut applicability)
31-
),
32-
applicability,
27+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).as_bytes().get($expr(n_arg))).into_string(),
28+
app,
3329
);
3430
}

clippy_lints/src/methods/iter_count.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::utils::derefs_to_slice;
2+
use clippy_macros::expr_sugg;
23
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::ty::is_type_diagnostic_item;
55
use rustc_errors::Applicability;
66
use rustc_hir::Expr;
@@ -32,17 +32,14 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
3232
} else {
3333
return;
3434
};
35-
let mut applicability = Applicability::MachineApplicable;
35+
let mut app = Applicability::MachineApplicable;
3636
span_lint_and_sugg(
3737
cx,
3838
ITER_COUNT,
3939
expr.span,
4040
&format!("called `.{}().count()` on a `{}`", iter_method, caller_type),
4141
"try",
42-
format!(
43-
"{}.len()",
44-
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
45-
),
46-
applicability,
42+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).len()).into_string(),
43+
app,
4744
);
4845
}

clippy_lints/src/methods/iter_nth_zero.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::consts::{constant, Constant};
23
use clippy_utils::diagnostics::span_lint_and_sugg;
34
use clippy_utils::is_trait_method;
4-
use clippy_utils::source::snippet_with_applicability;
55
use if_chain::if_chain;
66
use rustc_errors::Applicability;
77
use rustc_hir as hir;
@@ -15,15 +15,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &h
1515
if is_trait_method(cx, expr, sym::Iterator);
1616
if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
1717
then {
18-
let mut applicability = Applicability::MachineApplicable;
18+
let mut app = Applicability::MachineApplicable;
1919
span_lint_and_sugg(
2020
cx,
2121
ITER_NTH_ZERO,
2222
expr.span,
2323
"called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
2424
"try calling `.next()` instead of `.nth(0)`",
25-
format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)),
26-
applicability,
25+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).next()).into_string(),
26+
app,
2727
);
2828
}
2929
}

clippy_lints/src/methods/option_as_ref_deref.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
23
use clippy_utils::source::snippet;
34
use clippy_utils::ty::is_type_diagnostic_item;
@@ -99,22 +100,15 @@ pub(super) fn check<'tcx>(
99100
format!(".as_ref().map({})", snippet(cx, map_arg.span, ".."))
100101
};
101102
let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
102-
let hint = format!("{}.{}()", snippet(cx, as_ref_recv.span, ".."), method_hint);
103+
let mut app = Applicability::MachineApplicable;
104+
let hint = expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(as_ref_recv).$ident(method_hint)()).into_string();
103105
let suggestion = format!("try using {} instead", method_hint);
104106

105107
let msg = format!(
106108
"called `{0}` on an Option value. This can be done more directly \
107109
by calling `{1}` instead",
108110
current_method, hint
109111
);
110-
span_lint_and_sugg(
111-
cx,
112-
OPTION_AS_REF_DEREF,
113-
expr.span,
114-
&msg,
115-
&suggestion,
116-
hint,
117-
Applicability::MachineApplicable,
118-
);
112+
span_lint_and_sugg(cx, OPTION_AS_REF_DEREF, expr.span, &msg, &suggestion, hint, app);
119113
}
120114
}
Lines changed: 47 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::snippet;
3-
use clippy_utils::ty::is_type_diagnostic_item;
4-
use clippy_utils::{is_lang_ctor, single_segment_path};
3+
use clippy_utils::is_lang_ctor;
4+
use clippy_utils::source::snippet_with_context;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_hir::LangItem::{OptionNone, OptionSome};
88
use rustc_lint::LateContext;
9+
use rustc_middle::ty;
910
use rustc_span::symbol::sym;
1011

1112
use super::OPTION_MAP_OR_NONE;
@@ -18,10 +19,10 @@ fn reduce_unit_expression<'a>(
1819
expr: &'a hir::Expr<'_>,
1920
) -> Option<(&'a hir::Expr<'a>, &'a [hir::Expr<'a>])> {
2021
match expr.kind {
21-
hir::ExprKind::Call(func, arg_char) => Some((func, arg_char)),
22+
hir::ExprKind::Call(func, args) => Some((func, args)),
2223
hir::ExprKind::Block(block, _) => {
2324
match (block.stmts, block.expr) {
24-
(&[], Some(inner_expr)) => {
25+
(&[], Some(inner_expr)) if inner_expr.span.ctxt() == expr.span.ctxt() => {
2526
// If block only contains an expression,
2627
// reduce `|x| { x + 1 }` to `|x| x + 1`
2728
reduce_unit_expression(cx, inner_expr)
@@ -41,87 +42,66 @@ pub(super) fn check<'tcx>(
4142
def_arg: &'tcx hir::Expr<'_>,
4243
map_arg: &'tcx hir::Expr<'_>,
4344
) {
44-
let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
45-
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
46-
4745
// There are two variants of this `map_or` lint:
4846
// (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
4947
// (2) using `map_or` as a combinator instead of `and_then`
5048
//
5149
// (For this lint) we don't care if any other type calls `map_or`
52-
if !is_option && !is_result {
53-
return;
54-
}
55-
56-
let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
57-
is_lang_ctor(cx, qpath, OptionNone)
58-
} else {
59-
return;
60-
};
6150

62-
if !default_arg_is_none {
63-
// nothing to lint!
51+
if !matches!(&def_arg.kind, hir::ExprKind::Path(qpath) if is_lang_ctor(cx, qpath, OptionNone)) {
52+
// Only lint when `None` is the default argument.
6453
return;
6554
}
6655

67-
let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
68-
is_lang_ctor(cx, qpath, OptionSome)
69-
} else {
70-
false
56+
let recv_ty_did = match cx.typeck_results().expr_ty(recv).kind() {
57+
ty::Adt(adt, _) => adt.did,
58+
_ => return,
7159
};
72-
73-
if is_option {
74-
let self_snippet = snippet(cx, recv.span, "..");
75-
if_chain! {
76-
if let hir::ExprKind::Closure(_, _, id, span, _) = map_arg.kind;
77-
let arg_snippet = snippet(cx, span, "..");
78-
let body = cx.tcx.hir().body(id);
79-
if let Some((func, arg_char)) = reduce_unit_expression(cx, &body.value);
80-
if arg_char.len() == 1;
81-
if let hir::ExprKind::Path(ref qpath) = func.kind;
82-
if let Some(segment) = single_segment_path(qpath);
83-
if segment.ident.name == sym::Some;
60+
let mut app = Applicability::MachineApplicable;
61+
let (lint_name, msg, instead, hint) = match cx.tcx.get_diagnostic_name(recv_ty_did) {
62+
Some(sym::Option) => {
63+
if_chain! {
64+
if let hir::ExprKind::Closure(_, _, id, closure_arg_span, _) = map_arg.kind;
65+
let body = cx.tcx.hir().body(id);
66+
if let Some((func, [arg])) = reduce_unit_expression(cx, &body.value);
67+
if let hir::ExprKind::Path(qpath) = &func.kind;
68+
if is_lang_ctor(cx, qpath, OptionSome);
8469
then {
85-
let func_snippet = snippet(cx, arg_char[0].span, "..");
86-
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
87-
`map(..)` instead";
70+
let self_snippet = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
71+
let arg_snippet = snippet_with_context(cx, closure_arg_span, expr.span.ctxt(), "..", &mut app).0;
72+
let func_snippet = snippet_with_context(cx, arg.span, expr.span.ctxt(), "..", &mut app).0;
8873
return span_lint_and_sugg(
8974
cx,
9075
OPTION_MAP_OR_NONE,
9176
expr.span,
92-
msg,
77+
"called `map_or(None, ..)` on an `Option` value. This can be done more \
78+
directly by calling `map(..)` instead",
9379
"try using `map` instead",
94-
format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
80+
format!("{}.map({} {})", self_snippet, arg_snippet, func_snippet),
9581
Applicability::MachineApplicable,
9682
);
9783
}
84+
}
9885

99-
}
86+
(
87+
OPTION_MAP_OR_NONE,
88+
"called `map_or(None, ..)` on an `Option` value. This can be done more directly by \
89+
calling `and_then(..)` instead",
90+
"try using `and_then` instead",
91+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).and_then($expr(map_arg))).into_string(),
92+
)
93+
},
94+
Some(sym::Result) if matches!(&map_arg.kind, hir::ExprKind::Path(qpath) if is_lang_ctor(cx, qpath, OptionSome)) => {
95+
(
96+
RESULT_MAP_OR_INTO_OPTION,
97+
"called `map_or(None, Some)` on a `Result` value. This can be done more directly by \
98+
calling `ok()` instead",
99+
"try using `ok` instead",
100+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).ok()).into_string(),
101+
)
102+
},
103+
_ => return,
104+
};
100105

101-
let func_snippet = snippet(cx, map_arg.span, "..");
102-
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
103-
`and_then(..)` instead";
104-
return span_lint_and_sugg(
105-
cx,
106-
OPTION_MAP_OR_NONE,
107-
expr.span,
108-
msg,
109-
"try using `and_then` instead",
110-
format!("{0}.and_then({1})", self_snippet, func_snippet),
111-
Applicability::MachineApplicable,
112-
);
113-
} else if f_arg_is_some {
114-
let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \
115-
`ok()` instead";
116-
let self_snippet = snippet(cx, recv.span, "..");
117-
return span_lint_and_sugg(
118-
cx,
119-
RESULT_MAP_OR_INTO_OPTION,
120-
expr.span,
121-
msg,
122-
"try using `ok` instead",
123-
format!("{0}.ok()", self_snippet),
124-
Applicability::MachineApplicable,
125-
);
126-
}
106+
span_lint_and_sugg(cx, lint_name, expr.span, msg, instead, hint, app);
127107
}

clippy_lints/src/methods/or_fun_call.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use clippy_macros::expr_sugg;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
23
use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
3-
use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite};
4+
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
45
use clippy_utils::ty::{implements_trait, match_type};
56
use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths};
67
use if_chain::if_chain;
@@ -51,18 +52,15 @@ pub(super) fn check<'tcx>(
5152
|| (matches!(path, sym::new) && implements_default(arg, default_trait_id));
5253

5354
then {
54-
let mut applicability = Applicability::MachineApplicable;
55+
let mut app = Applicability::MachineApplicable;
5556
span_lint_and_sugg(
5657
cx,
5758
OR_FUN_CALL,
5859
span,
5960
&format!("use of `{}` followed by a call to `{}`", name, path),
6061
"try this",
61-
format!(
62-
"{}.unwrap_or_default()",
63-
snippet_with_applicability(cx, self_expr.span, "..", &mut applicability)
64-
),
65-
applicability,
62+
expr_sugg!(cx, &mut app, span.ctxt(), $expr(self_expr).unwrap_or_default()).into_string(),
63+
app,
6664
);
6765

6866
true

clippy_lints/src/methods/unwrap_or_else_default.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
//! Lint for `some_result_or_option.unwrap_or_else(Default::default)`
22
33
use super::UNWRAP_OR_ELSE_DEFAULT;
4-
use clippy_utils::{
5-
diagnostics::span_lint_and_sugg, is_default_equivalent_call, source::snippet_with_applicability,
6-
ty::is_type_diagnostic_item,
7-
};
4+
use clippy_macros::expr_sugg;
5+
use clippy_utils::{diagnostics::span_lint_and_sugg, is_default_equivalent_call, ty::is_type_diagnostic_item};
86
use rustc_errors::Applicability;
97
use rustc_hir as hir;
108
use rustc_lint::LateContext;
@@ -27,19 +25,16 @@ pub(super) fn check<'tcx>(
2725
if is_option || is_result;
2826
if is_default_equivalent_call(cx, u_arg);
2927
then {
30-
let mut applicability = Applicability::MachineApplicable;
28+
let mut app = Applicability::MachineApplicable;
3129

3230
span_lint_and_sugg(
3331
cx,
3432
UNWRAP_OR_ELSE_DEFAULT,
3533
expr.span,
3634
"use of `.unwrap_or_else(..)` to construct default value",
3735
"try",
38-
format!(
39-
"{}.unwrap_or_default()",
40-
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
41-
),
42-
applicability,
36+
expr_sugg!(cx, &mut app, expr.span.ctxt(), $expr(recv).unwrap_or_default()).into_string(),
37+
app,
4338
);
4439
}
4540
}

clippy_lints/src/strlen_on_c_strings.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ impl LateLintPass<'tcx> for StrlenOnCStrings {
6464

6565
let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
6666
let mut app = Applicability::MachineApplicable;
67-
let app = &mut app;
6867
let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) {
6968
"as_bytes"
7069
} else if is_type_diagnostic_item(cx, ty, sym::CStr) {
@@ -79,8 +78,9 @@ impl LateLintPass<'tcx> for StrlenOnCStrings {
7978
span,
8079
"using `libc::strlen` on a `CString` or `CStr` value",
8180
"try this",
82-
expr_sugg!(cx, app, ctxt, $snip(self_arg).$ident(method_name)().len()).for_expr_position(cx, expr),
83-
*app,
81+
expr_sugg!(cx, &mut app, ctxt, $expr(self_arg).$ident(method_name)().len())
82+
.for_expr_position(cx, expr),
83+
app,
8484
);
8585
}
8686
}

0 commit comments

Comments
 (0)