Skip to content

Commit f6020fb

Browse files
committed
Auto merge of rust-lang#13042 - Jarcho:almost_range, r=Manishearth
`almost_complete_range`: Delay suggestion creation. Does less work when the lint doesn't trigger. changelog: none
2 parents 510cfe3 + 5b30f6a commit f6020fb

File tree

1 file changed

+61
-43
lines changed

1 file changed

+61
-43
lines changed

clippy_lints/src/almost_complete_range.rs

+61-43
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
66
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
77
use rustc_middle::lint::in_external_macro;
88
use rustc_session::impl_lint_pass;
9-
use rustc_span::Span;
109

1110
declare_clippy_lint! {
1211
/// ### What it does
@@ -41,61 +40,80 @@ impl AlmostCompleteRange {
4140
}
4241
impl EarlyLintPass for AlmostCompleteRange {
4342
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
44-
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
45-
let ctxt = e.span.ctxt();
46-
let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
47-
&& let Some(end) = walk_span_to_context(end.span, ctxt)
48-
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
49-
{
50-
Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
51-
} else {
52-
None
53-
};
54-
check_range(cx, e.span, start, end, sugg);
43+
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind
44+
&& is_incomplete_range(start, end)
45+
&& !in_external_macro(cx.sess(), e.span)
46+
{
47+
span_lint_and_then(
48+
cx,
49+
ALMOST_COMPLETE_RANGE,
50+
e.span,
51+
"almost complete ascii range",
52+
|diag| {
53+
let ctxt = e.span.ctxt();
54+
if let Some(start) = walk_span_to_context(start.span, ctxt)
55+
&& let Some(end) = walk_span_to_context(end.span, ctxt)
56+
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
57+
{
58+
diag.span_suggestion(
59+
trim_span(cx.sess().source_map(), start.between(end)),
60+
"use an inclusive range",
61+
"..=".to_owned(),
62+
Applicability::MaybeIncorrect,
63+
);
64+
}
65+
},
66+
);
5567
}
5668
}
5769

5870
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
5971
if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
6072
&& matches!(kind.node, RangeEnd::Excluded)
73+
&& is_incomplete_range(start, end)
74+
&& !in_external_macro(cx.sess(), p.span)
6175
{
62-
let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
63-
"..="
64-
} else {
65-
"..."
66-
};
67-
check_range(cx, p.span, start, end, Some((kind.span, sugg)));
76+
span_lint_and_then(
77+
cx,
78+
ALMOST_COMPLETE_RANGE,
79+
p.span,
80+
"almost complete ascii range",
81+
|diag| {
82+
diag.span_suggestion(
83+
kind.span,
84+
"use an inclusive range",
85+
if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
86+
"..=".to_owned()
87+
} else {
88+
"...".to_owned()
89+
},
90+
Applicability::MaybeIncorrect,
91+
);
92+
},
93+
);
6894
}
6995
}
7096

7197
extract_msrv_attr!(EarlyContext);
7298
}
7399

74-
fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
75-
if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
76-
&& let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
77-
&& matches!(
78-
(
79-
LitKind::from_token_lit(start_token_lit),
80-
LitKind::from_token_lit(end_token_lit),
81-
),
82-
(
83-
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
84-
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
85-
) | (
86-
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
87-
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
88-
) | (
89-
Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
90-
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
100+
fn is_incomplete_range(start: &Expr, end: &Expr) -> bool {
101+
match (&start.peel_parens().kind, &end.peel_parens().kind) {
102+
(&ExprKind::Lit(start_lit), &ExprKind::Lit(end_lit)) => {
103+
matches!(
104+
(LitKind::from_token_lit(start_lit), LitKind::from_token_lit(end_lit),),
105+
(
106+
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
107+
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
108+
) | (
109+
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
110+
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
111+
) | (
112+
Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
113+
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
114+
)
91115
)
92-
)
93-
&& !in_external_macro(cx.sess(), span)
94-
{
95-
span_lint_and_then(cx, ALMOST_COMPLETE_RANGE, span, "almost complete ascii range", |diag| {
96-
if let Some((span, sugg)) = sugg {
97-
diag.span_suggestion(span, "use an inclusive range", sugg, Applicability::MaybeIncorrect);
98-
}
99-
});
116+
},
117+
_ => false,
100118
}
101119
}

0 commit comments

Comments
 (0)