almost_complete_range
: Delay suggestion creation.
This commit is contained in:
parent
d2400a49a4
commit
5b30f6a1a3
@ -6,7 +6,6 @@ use rustc_errors::Applicability;
|
|||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::Span;
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -41,44 +40,68 @@ impl AlmostCompleteRange {
|
|||||||
}
|
}
|
||||||
impl EarlyLintPass for AlmostCompleteRange {
|
impl EarlyLintPass for AlmostCompleteRange {
|
||||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
|
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
|
||||||
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
|
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();
|
let ctxt = e.span.ctxt();
|
||||||
let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
|
if let Some(start) = walk_span_to_context(start.span, ctxt)
|
||||||
&& let Some(end) = walk_span_to_context(end.span, ctxt)
|
&& let Some(end) = walk_span_to_context(end.span, ctxt)
|
||||||
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
|
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
|
||||||
{
|
{
|
||||||
Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
|
diag.span_suggestion(
|
||||||
} else {
|
trim_span(cx.sess().source_map(), start.between(end)),
|
||||||
None
|
"use an inclusive range",
|
||||||
};
|
"..=".to_owned(),
|
||||||
check_range(cx, e.span, start, end, sugg);
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
|
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
|
||||||
if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
|
if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
|
||||||
&& matches!(kind.node, RangeEnd::Excluded)
|
&& 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) {
|
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 {
|
} else {
|
||||||
"..."
|
"...".to_owned()
|
||||||
};
|
},
|
||||||
check_range(cx, p.span, start, end, Some((kind.span, sugg)));
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_msrv_attr!(EarlyContext);
|
extract_msrv_attr!(EarlyContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
|
fn is_incomplete_range(start: &Expr, end: &Expr) -> bool {
|
||||||
if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
|
match (&start.peel_parens().kind, &end.peel_parens().kind) {
|
||||||
&& let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
|
(&ExprKind::Lit(start_lit), &ExprKind::Lit(end_lit)) => {
|
||||||
&& matches!(
|
matches!(
|
||||||
(
|
(LitKind::from_token_lit(start_lit), LitKind::from_token_lit(end_lit),),
|
||||||
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'a') | LitKind::Char('a')),
|
||||||
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
|
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||||
@ -90,12 +113,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
|
|||||||
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
|
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
&& !in_external_macro(cx.sess(), span)
|
},
|
||||||
{
|
_ => false,
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user