fix: use snippet_with_context for spans that are likely to contain macro expns
This commit is contained in:
parent
1566879798
commit
4d79522905
4 changed files with 131 additions and 26 deletions
|
|
@ -1,11 +1,11 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::source::{snippet, snippet_with_context};
|
||||
use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt, sym};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Closure, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
|
||||
use std::borrow::{Borrow, Cow};
|
||||
|
||||
|
|
@ -88,33 +88,42 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
|
|||
&& let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
|
||||
&& let ExprKind::Path(..) = recv.kind
|
||||
{
|
||||
let and_then_snippets =
|
||||
get_and_then_snippets(cx, call_cx.span, call_lint.span, call_sp.span, call_msg.span);
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let expr_ctxt = expr.span.ctxt();
|
||||
let and_then_snippets = get_and_then_snippets(
|
||||
cx,
|
||||
expr_ctxt,
|
||||
call_cx.span,
|
||||
call_lint.span,
|
||||
call_sp.span,
|
||||
call_msg.span,
|
||||
&mut app,
|
||||
);
|
||||
let mut sle = SpanlessEq::new(cx).deny_side_effects();
|
||||
match ps.ident.name {
|
||||
sym::span_suggestion if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
suggest_suggestion(
|
||||
cx,
|
||||
expr,
|
||||
&and_then_snippets,
|
||||
&span_suggestion_snippets(cx, span_call_args),
|
||||
);
|
||||
let snippets = span_suggestion_snippets(cx, expr_ctxt, span_call_args, &mut app);
|
||||
suggest_suggestion(cx, expr, &and_then_snippets, &snippets, app);
|
||||
},
|
||||
sym::span_help if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
|
||||
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
|
||||
let help_snippet =
|
||||
snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0;
|
||||
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true, app);
|
||||
},
|
||||
sym::span_note if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
|
||||
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
|
||||
let note_snippet =
|
||||
snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0;
|
||||
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true, app);
|
||||
},
|
||||
sym::help => {
|
||||
let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
|
||||
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false);
|
||||
let help_snippet =
|
||||
snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0;
|
||||
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false, app);
|
||||
},
|
||||
sym::note => {
|
||||
let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
|
||||
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false);
|
||||
let note_snippet =
|
||||
snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0;
|
||||
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false, app);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
|
@ -131,15 +140,17 @@ struct AndThenSnippets {
|
|||
|
||||
fn get_and_then_snippets(
|
||||
cx: &LateContext<'_>,
|
||||
expr_ctxt: SyntaxContext,
|
||||
cx_span: Span,
|
||||
lint_span: Span,
|
||||
span_span: Span,
|
||||
msg_span: Span,
|
||||
app: &mut Applicability,
|
||||
) -> AndThenSnippets {
|
||||
let cx_snippet = snippet(cx, cx_span, "cx");
|
||||
let lint_snippet = snippet(cx, lint_span, "..");
|
||||
let span_snippet = snippet(cx, span_span, "span");
|
||||
let msg_snippet = snippet(cx, msg_span, r#""...""#);
|
||||
let msg_snippet = snippet_with_context(cx, msg_span, expr_ctxt, r#""...""#, app).0;
|
||||
|
||||
AndThenSnippets {
|
||||
cx: cx_snippet,
|
||||
|
|
@ -155,9 +166,14 @@ struct SpanSuggestionSnippets {
|
|||
applicability: Cow<'static, str>,
|
||||
}
|
||||
|
||||
fn span_suggestion_snippets<'hir>(cx: &LateContext<'_>, span_call_args: &'hir [Expr<'hir>]) -> SpanSuggestionSnippets {
|
||||
let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
|
||||
let sugg_snippet = snippet(cx, span_call_args[2].span, "..");
|
||||
fn span_suggestion_snippets<'hir>(
|
||||
cx: &LateContext<'_>,
|
||||
expr_ctxt: SyntaxContext,
|
||||
span_call_args: &'hir [Expr<'hir>],
|
||||
app: &mut Applicability,
|
||||
) -> SpanSuggestionSnippets {
|
||||
let help_snippet = snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, app).0;
|
||||
let sugg_snippet = snippet_with_context(cx, span_call_args[2].span, expr_ctxt, "..", app).0;
|
||||
let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable");
|
||||
|
||||
SpanSuggestionSnippets {
|
||||
|
|
@ -172,6 +188,7 @@ fn suggest_suggestion(
|
|||
expr: &Expr<'_>,
|
||||
and_then_snippets: &AndThenSnippets,
|
||||
span_suggestion_snippets: &SpanSuggestionSnippets,
|
||||
app: Applicability,
|
||||
) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
|
@ -189,7 +206,7 @@ fn suggest_suggestion(
|
|||
span_suggestion_snippets.sugg,
|
||||
span_suggestion_snippets.applicability
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +216,7 @@ fn suggest_help(
|
|||
and_then_snippets: &AndThenSnippets,
|
||||
help: &str,
|
||||
with_span: bool,
|
||||
app: Applicability,
|
||||
) {
|
||||
let option_span = if with_span {
|
||||
format!("Some({})", and_then_snippets.span)
|
||||
|
|
@ -216,7 +234,7 @@ fn suggest_help(
|
|||
"span_lint_and_help({}, {}, {}, {}, {}, {help})",
|
||||
and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span,
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -226,6 +244,7 @@ fn suggest_note(
|
|||
and_then_snippets: &AndThenSnippets,
|
||||
note: &str,
|
||||
with_span: bool,
|
||||
app: Applicability,
|
||||
) {
|
||||
let note_span = if with_span {
|
||||
format!("Some({})", and_then_snippets.span)
|
||||
|
|
@ -243,6 +262,6 @@ fn suggest_note(
|
|||
"span_lint_and_note({}, {}, {}, {}, {note_span}, {note})",
|
||||
and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg,
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,15 @@ impl EarlyLintPass for Pass {
|
|||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
db.help(help_msg).help(help_msg);
|
||||
});
|
||||
|
||||
// Issue #15880
|
||||
#[expect(clippy::disallowed_names)]
|
||||
let foo = "foo";
|
||||
span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable);
|
||||
span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"));
|
||||
span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"));
|
||||
span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"));
|
||||
span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,35 @@ impl EarlyLintPass for Pass {
|
|||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
db.help(help_msg).help(help_msg);
|
||||
});
|
||||
|
||||
// Issue #15880
|
||||
#[expect(clippy::disallowed_names)]
|
||||
let foo = "foo";
|
||||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
//~^ collapsible_span_lint_calls
|
||||
db.span_suggestion(
|
||||
expr.span,
|
||||
format!("try using {foo}"),
|
||||
format!("{foo}.use"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
//~^ collapsible_span_lint_calls
|
||||
db.span_help(expr.span, format!("try using {foo}"));
|
||||
});
|
||||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
//~^ collapsible_span_lint_calls
|
||||
db.help(format!("try using {foo}"));
|
||||
});
|
||||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
//~^ collapsible_span_lint_calls
|
||||
db.span_note(expr.span, format!("required because of {foo}"));
|
||||
});
|
||||
span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
//~^ collapsible_span_lint_calls
|
||||
db.note(format!("required because of {foo}"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,5 +49,53 @@ LL | | db.note(note_msg);
|
|||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: this call is collapsible
|
||||
--> tests/ui-internal/collapsible_span_lint_calls.rs:72:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | |
|
||||
LL | | db.span_suggestion(
|
||||
LL | | expr.span,
|
||||
... |
|
||||
LL | | );
|
||||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable)`
|
||||
|
||||
error: this call is collapsible
|
||||
--> tests/ui-internal/collapsible_span_lint_calls.rs:81:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | |
|
||||
LL | | db.span_help(expr.span, format!("try using {foo}"));
|
||||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"))`
|
||||
|
||||
error: this call is collapsible
|
||||
--> tests/ui-internal/collapsible_span_lint_calls.rs:85:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | |
|
||||
LL | | db.help(format!("try using {foo}"));
|
||||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"))`
|
||||
|
||||
error: this call is collapsible
|
||||
--> tests/ui-internal/collapsible_span_lint_calls.rs:89:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | |
|
||||
LL | | db.span_note(expr.span, format!("required because of {foo}"));
|
||||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"))`
|
||||
|
||||
error: this call is collapsible
|
||||
--> tests/ui-internal/collapsible_span_lint_calls.rs:93:9
|
||||
|
|
||||
LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
|
||||
LL | |
|
||||
LL | | db.note(format!("required because of {foo}"));
|
||||
LL | | });
|
||||
| |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}"))`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue