Auto merge of #13042 - Jarcho:almost_range, r=Manishearth
`almost_complete_range`: Delay suggestion creation. Does less work when the lint doesn't trigger. changelog: none
This commit is contained in:
commit
f6020fbd44
@ -6,7 +6,6 @@ use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -41,61 +40,80 @@ impl AlmostCompleteRange {
|
||||
}
|
||||
impl EarlyLintPass for AlmostCompleteRange {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
|
||||
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
|
||||
let ctxt = e.span.ctxt();
|
||||
let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
|
||||
&& let Some(end) = walk_span_to_context(end.span, ctxt)
|
||||
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
|
||||
{
|
||||
Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
check_range(cx, e.span, start, end, sugg);
|
||||
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind
|
||||
&& is_incomplete_range(start, end)
|
||||
&& !in_external_macro(cx.sess(), e.span)
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
ALMOST_COMPLETE_RANGE,
|
||||
e.span,
|
||||
"almost complete ascii range",
|
||||
|diag| {
|
||||
let ctxt = e.span.ctxt();
|
||||
if let Some(start) = walk_span_to_context(start.span, ctxt)
|
||||
&& let Some(end) = walk_span_to_context(end.span, ctxt)
|
||||
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
|
||||
{
|
||||
diag.span_suggestion(
|
||||
trim_span(cx.sess().source_map(), start.between(end)),
|
||||
"use an inclusive range",
|
||||
"..=".to_owned(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
|
||||
if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
|
||||
&& matches!(kind.node, RangeEnd::Excluded)
|
||||
&& is_incomplete_range(start, end)
|
||||
&& !in_external_macro(cx.sess(), p.span)
|
||||
{
|
||||
let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
|
||||
"..="
|
||||
} else {
|
||||
"..."
|
||||
};
|
||||
check_range(cx, p.span, start, end, Some((kind.span, sugg)));
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
ALMOST_COMPLETE_RANGE,
|
||||
p.span,
|
||||
"almost complete ascii range",
|
||||
|diag| {
|
||||
diag.span_suggestion(
|
||||
kind.span,
|
||||
"use an inclusive range",
|
||||
if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
|
||||
"..=".to_owned()
|
||||
} else {
|
||||
"...".to_owned()
|
||||
},
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
||||
fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
|
||||
if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
|
||||
&& let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
|
||||
&& matches!(
|
||||
(
|
||||
LitKind::from_token_lit(start_token_lit),
|
||||
LitKind::from_token_lit(end_token_lit),
|
||||
),
|
||||
(
|
||||
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
|
||||
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||
) | (
|
||||
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
|
||||
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
|
||||
) | (
|
||||
Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
|
||||
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
|
||||
fn is_incomplete_range(start: &Expr, end: &Expr) -> bool {
|
||||
match (&start.peel_parens().kind, &end.peel_parens().kind) {
|
||||
(&ExprKind::Lit(start_lit), &ExprKind::Lit(end_lit)) => {
|
||||
matches!(
|
||||
(LitKind::from_token_lit(start_lit), LitKind::from_token_lit(end_lit),),
|
||||
(
|
||||
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
|
||||
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||
) | (
|
||||
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
|
||||
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
|
||||
) | (
|
||||
Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
|
||||
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
|
||||
)
|
||||
)
|
||||
)
|
||||
&& !in_external_macro(cx.sess(), span)
|
||||
{
|
||||
span_lint_and_then(cx, ALMOST_COMPLETE_RANGE, span, "almost complete ascii range", |diag| {
|
||||
if let Some((span, sugg)) = sugg {
|
||||
diag.span_suggestion(span, "use an inclusive range", sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
});
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user