mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Auto merge of #10434 - Jarcho:snip_context, r=dswij
Remove `snippet_with_macro_callsite` `snippet_with_context` is used instead to support nested macro calls. changelog: None
This commit is contained in:
commit
f19db28361
22 changed files with 200 additions and 193 deletions
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{has_drop, is_copy};
|
||||
use clippy_utils::{
|
||||
any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths,
|
||||
|
@ -160,6 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
}
|
||||
};
|
||||
|
||||
let init_ctxt = local.span.ctxt();
|
||||
|
||||
// find all "later statement"'s where the fields of the binding set as
|
||||
// Default::default() get reassigned, unless the reassignment refers to the original binding
|
||||
let mut first_assign = None;
|
||||
|
@ -169,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
// find out if and which field was set by this `consecutive_statement`
|
||||
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
|
||||
// interrupt and cancel lint if assign_rhs references the original binding
|
||||
if contains_name(binding_name, assign_rhs, cx) {
|
||||
if contains_name(binding_name, assign_rhs, cx) || init_ctxt != consecutive_statement.span.ctxt() {
|
||||
cancel_lint = true;
|
||||
break;
|
||||
}
|
||||
|
@ -204,11 +206,12 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
.iter()
|
||||
.all(|field| assigned_fields.iter().any(|(a, _)| a == &field.name));
|
||||
|
||||
let mut app = Applicability::Unspecified;
|
||||
let field_list = assigned_fields
|
||||
.into_iter()
|
||||
.map(|(field, rhs)| {
|
||||
// extract and store the assigned value for help message
|
||||
let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
|
||||
let value_snippet = snippet_with_context(cx, rhs.span, init_ctxt, "..", &mut app).0;
|
||||
format!("{field}: {value_snippet}")
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
@ -72,21 +74,20 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
|
|||
return;
|
||||
}
|
||||
|
||||
let ctxt = expr.span.ctxt();
|
||||
|
||||
if let Some(higher::If { cond, then, r#else: Some(els) }) = higher::If::hir(expr)
|
||||
&& let ExprKind::Block(then_block, _) = then.kind
|
||||
&& let Some(then_expr) = then_block.expr
|
||||
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
|
||||
&& then_expr.span.ctxt() == ctxt
|
||||
&& is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
|
||||
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
|
||||
&& !stmts_contains_early_return(then_block.stmts)
|
||||
{
|
||||
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
|
||||
let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
|
||||
format!("({cond_snip})")
|
||||
} else {
|
||||
cond_snip.into_owned()
|
||||
};
|
||||
let arg_snip = snippet_with_macro_callsite(cx, then_arg.span, "");
|
||||
let mut app = Applicability::Unspecified;
|
||||
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app).maybe_par().to_string();
|
||||
let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
|
||||
let mut method_body = if then_block.stmts.is_empty() {
|
||||
arg_snip.into_owned()
|
||||
} else {
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
use super::SAME_ITEM_PUSH;
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::path_to_local;
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::SyntaxContext;
|
||||
use std::iter::Iterator;
|
||||
|
||||
/// Detects for loop pushing the same item into a Vec
|
||||
|
@ -20,9 +22,10 @@ pub(super) fn check<'tcx>(
|
|||
body: &'tcx Expr<'_>,
|
||||
_: &'tcx Expr<'_>,
|
||||
) {
|
||||
fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>) {
|
||||
let vec_str = snippet_with_macro_callsite(cx, vec.span, "");
|
||||
let item_str = snippet_with_macro_callsite(cx, pushed_item.span, "");
|
||||
fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: SyntaxContext) {
|
||||
let mut app = Applicability::Unspecified;
|
||||
let vec_str = snippet_with_context(cx, vec.span, ctxt, "", &mut app).0;
|
||||
let item_str = snippet_with_context(cx, pushed_item.span, ctxt, "", &mut app).0;
|
||||
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -43,7 +46,7 @@ pub(super) fn check<'tcx>(
|
|||
walk_expr(&mut same_item_push_visitor, body);
|
||||
if_chain! {
|
||||
if same_item_push_visitor.should_lint();
|
||||
if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push;
|
||||
if let Some((vec, pushed_item, ctxt)) = same_item_push_visitor.vec_push;
|
||||
let vec_ty = cx.typeck_results().expr_ty(vec);
|
||||
let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
|
||||
if cx
|
||||
|
@ -69,11 +72,11 @@ pub(super) fn check<'tcx>(
|
|||
then {
|
||||
match init.kind {
|
||||
// immutable bindings that are initialized with literal
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
// immutable bindings that are initialized with constant
|
||||
ExprKind::Path(ref path) => {
|
||||
if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
|
||||
emit_lint(cx, vec, pushed_item);
|
||||
emit_lint(cx, vec, pushed_item, ctxt);
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
|
@ -82,11 +85,11 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
},
|
||||
// constant
|
||||
Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item),
|
||||
Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +101,7 @@ struct SameItemPushVisitor<'a, 'tcx> {
|
|||
non_deterministic_expr: bool,
|
||||
multiple_pushes: bool,
|
||||
// this field holds the last vec push operation visited, which should be the only push seen
|
||||
vec_push: Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>,
|
||||
vec_push: Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)>,
|
||||
cx: &'a LateContext<'tcx>,
|
||||
used_locals: FxHashSet<HirId>,
|
||||
}
|
||||
|
@ -118,7 +121,7 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
|
|||
if_chain! {
|
||||
if !self.non_deterministic_expr;
|
||||
if !self.multiple_pushes;
|
||||
if let Some((vec, _)) = self.vec_push;
|
||||
if let Some((vec, _, _)) = self.vec_push;
|
||||
if let Some(hir_id) = path_to_local(vec);
|
||||
then {
|
||||
!self.used_locals.contains(&hir_id)
|
||||
|
@ -173,7 +176,10 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
|
|||
|
||||
// Given some statement, determine if that statement is a push on a Vec. If it is, return
|
||||
// the Vec being pushed into and the item being pushed
|
||||
fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> {
|
||||
fn get_vec_push<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
stmt: &'tcx Stmt<'_>,
|
||||
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)> {
|
||||
if_chain! {
|
||||
// Extract method being called
|
||||
if let StmtKind::Semi(semi_stmt) = &stmt.kind;
|
||||
|
@ -184,7 +190,7 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&
|
|||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
|
||||
if path.ident.name.as_str() == "push";
|
||||
then {
|
||||
return Some((self_expr, pushed_item))
|
||||
return Some((self_expr, pushed_item, semi_stmt.span.ctxt()))
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -32,14 +32,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
|
|||
let reindented_or_body =
|
||||
reindent_multiline(or_body_snippet.into(), true, Some(indent));
|
||||
|
||||
let suggestion = if scrutinee.span.from_expansion() {
|
||||
// we don't want parentheses around macro, e.g. `(some_macro!()).unwrap_or(0)`
|
||||
sugg::Sugg::hir_with_macro_callsite(cx, scrutinee, "..")
|
||||
}
|
||||
else {
|
||||
sugg::Sugg::hir(cx, scrutinee, "..").maybe_par()
|
||||
};
|
||||
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par();
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_UNWRAP_OR, expr.span,
|
||||
|
@ -48,7 +42,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
|
|||
format!(
|
||||
"{suggestion}.unwrap_or({reindented_or_body})",
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ use rustc_middle::ty;
|
|||
|
||||
use super::MATCH_BOOL;
|
||||
|
||||
pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
||||
pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
||||
// Type of expression is `bool`.
|
||||
if *cx.typeck_results().expr_ty(ex).kind() == ty::Bool {
|
||||
if *cx.typeck_results().expr_ty(scrutinee).kind() == ty::Bool {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
MATCH_BOOL,
|
||||
|
@ -36,24 +36,26 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
|
|||
};
|
||||
|
||||
if let Some((true_expr, false_expr)) = exprs {
|
||||
let mut app = Applicability::HasPlaceholders;
|
||||
let ctxt = expr.span.ctxt();
|
||||
let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) {
|
||||
(false, false) => Some(format!(
|
||||
"if {} {} else {}",
|
||||
snippet(cx, ex.span, "b"),
|
||||
expr_block(cx, true_expr, None, "..", Some(expr.span)),
|
||||
expr_block(cx, false_expr, None, "..", Some(expr.span))
|
||||
snippet(cx, scrutinee.span, "b"),
|
||||
expr_block(cx, true_expr, ctxt, "..", Some(expr.span), &mut app),
|
||||
expr_block(cx, false_expr, ctxt, "..", Some(expr.span), &mut app)
|
||||
)),
|
||||
(false, true) => Some(format!(
|
||||
"if {} {}",
|
||||
snippet(cx, ex.span, "b"),
|
||||
expr_block(cx, true_expr, None, "..", Some(expr.span))
|
||||
snippet(cx, scrutinee.span, "b"),
|
||||
expr_block(cx, true_expr, ctxt, "..", Some(expr.span), &mut app)
|
||||
)),
|
||||
(true, false) => {
|
||||
let test = Sugg::hir(cx, ex, "..");
|
||||
let test = Sugg::hir(cx, scrutinee, "..");
|
||||
Some(format!(
|
||||
"if {} {}",
|
||||
!test,
|
||||
expr_block(cx, false_expr, None, "..", Some(expr.span))
|
||||
expr_block(cx, false_expr, ctxt, "..", Some(expr.span), &mut app)
|
||||
))
|
||||
},
|
||||
(true, true) => None,
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::source::{snippet, walk_span_to_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use core::iter::once;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
||||
use super::MATCH_REF_PATS;
|
||||
|
||||
pub(crate) fn check<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
|
||||
pub(crate) fn check<'a, 'b, I>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, pats: I, expr: &Expr<'_>)
|
||||
where
|
||||
'b: 'a,
|
||||
I: Clone + Iterator<Item = &'a Pat<'b>>,
|
||||
|
@ -17,13 +18,28 @@ where
|
|||
}
|
||||
|
||||
let (first_sugg, msg, title);
|
||||
let span = ex.span.source_callsite();
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind {
|
||||
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string()));
|
||||
let ctxt = expr.span.ctxt();
|
||||
let mut app = Applicability::Unspecified;
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = scrutinee.kind {
|
||||
if scrutinee.span.ctxt() != ctxt {
|
||||
return;
|
||||
}
|
||||
first_sugg = once((
|
||||
scrutinee.span,
|
||||
Sugg::hir_with_context(cx, inner, ctxt, "..", &mut app).to_string(),
|
||||
));
|
||||
msg = "try";
|
||||
title = "you don't need to add `&` to both the expression and the patterns";
|
||||
} else {
|
||||
first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, ex, "..").deref().to_string()));
|
||||
let Some(span) = walk_span_to_context(scrutinee.span, ctxt) else {
|
||||
return;
|
||||
};
|
||||
first_sugg = once((
|
||||
span,
|
||||
Sugg::hir_with_context(cx, scrutinee, ctxt, "..", &mut app)
|
||||
.deref()
|
||||
.to_string(),
|
||||
));
|
||||
msg = "instead of prefixing all patterns with `&`, you can dereference the expression";
|
||||
title = "you don't need to add `&` to all patterns";
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::macros::HirNode;
|
||||
use clippy_utils::source::{indent_of, snippet, snippet_block, snippet_with_applicability};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_applicability};
|
||||
use clippy_utils::{get_parent_expr, is_refutable, peel_blocks};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Arm, Expr, ExprKind, Node, PatKind};
|
||||
|
@ -24,21 +23,25 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
let matched_vars = ex.span;
|
||||
let bind_names = arms[0].pat.span;
|
||||
let match_body = peel_blocks(arms[0].body);
|
||||
let mut snippet_body = if match_body.span.from_expansion() {
|
||||
Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string()
|
||||
} else {
|
||||
snippet_block(cx, match_body.span, "..", Some(expr.span)).to_string()
|
||||
};
|
||||
let mut app = Applicability::MaybeIncorrect;
|
||||
let (snippet_body, from_macro) = snippet_block_with_context(
|
||||
cx,
|
||||
match_body.span,
|
||||
arms[0].span.ctxt(),
|
||||
"..",
|
||||
Some(expr.span),
|
||||
&mut app,
|
||||
);
|
||||
let mut snippet_body = snippet_body.to_string();
|
||||
|
||||
// Do we need to add ';' to suggestion ?
|
||||
if let ExprKind::Block(block, _) = match_body.kind {
|
||||
if matches!(match_body.kind, ExprKind::Block(..)) {
|
||||
// macro + expr_ty(body) == ()
|
||||
if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() {
|
||||
if from_macro && cx.typeck_results().expr_ty(match_body).is_unit() {
|
||||
snippet_body.push(';');
|
||||
}
|
||||
}
|
||||
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
match arms[0].pat.kind {
|
||||
PatKind::Binding(..) | PatKind::Tuple(_, _) | PatKind::Struct(..) => {
|
||||
let (target_span, sugg) = match opt_parent_assign_span(cx, ex) {
|
||||
|
@ -48,7 +51,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
(ex, expr),
|
||||
(bind_names, matched_vars),
|
||||
&snippet_body,
|
||||
&mut applicability,
|
||||
&mut app,
|
||||
Some(span),
|
||||
true,
|
||||
);
|
||||
|
@ -60,7 +63,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
"this assignment could be simplified",
|
||||
"consider removing the `match` expression",
|
||||
sugg,
|
||||
applicability,
|
||||
app,
|
||||
);
|
||||
|
||||
return;
|
||||
|
@ -69,10 +72,10 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
span,
|
||||
format!(
|
||||
"let {} = {};\n{}let {} = {snippet_body};",
|
||||
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, bind_names, "..", &mut app),
|
||||
snippet_with_applicability(cx, matched_vars, "..", &mut app),
|
||||
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
|
||||
snippet_with_applicability(cx, pat_span, "..", &mut applicability)
|
||||
snippet_with_applicability(cx, pat_span, "..", &mut app)
|
||||
),
|
||||
),
|
||||
None => {
|
||||
|
@ -81,7 +84,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
(ex, expr),
|
||||
(bind_names, matched_vars),
|
||||
&snippet_body,
|
||||
&mut applicability,
|
||||
&mut app,
|
||||
None,
|
||||
true,
|
||||
);
|
||||
|
@ -96,7 +99,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
"this match could be written as a `let` statement",
|
||||
"consider using a `let` statement",
|
||||
sugg,
|
||||
applicability,
|
||||
app,
|
||||
);
|
||||
},
|
||||
PatKind::Wild => {
|
||||
|
@ -106,7 +109,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
(ex, expr),
|
||||
(bind_names, matched_vars),
|
||||
&snippet_body,
|
||||
&mut applicability,
|
||||
&mut app,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
@ -118,7 +121,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
|||
"this match could be replaced by its scrutinee and body",
|
||||
"consider using the scrutinee and body instead",
|
||||
sugg,
|
||||
applicability,
|
||||
app,
|
||||
);
|
||||
} else {
|
||||
span_lint_and_sugg(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::REDUNDANT_PATTERN_MATCHING;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::source::{snippet, walk_span_to_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
|
||||
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
|
||||
|
@ -150,22 +150,25 @@ fn find_sugg_for_if_let<'tcx>(
|
|||
// if/while let ... = ... { ... }
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
let expr_span = expr.span;
|
||||
let ctxt = expr.span.ctxt();
|
||||
|
||||
// if/while let ... = ... { ... }
|
||||
// ^^^
|
||||
let op_span = result_expr.span.source_callsite();
|
||||
// ^^^
|
||||
let Some(res_span) = walk_span_to_context(result_expr.span.source_callsite(), ctxt) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// if/while let ... = ... { ... }
|
||||
// ^^^^^^^^^^^^^^^^^^^
|
||||
let span = expr_span.until(op_span.shrink_to_hi());
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^
|
||||
let span = expr_span.until(res_span.shrink_to_hi());
|
||||
|
||||
let app = if needs_drop {
|
||||
let mut app = if needs_drop {
|
||||
Applicability::MaybeIncorrect
|
||||
} else {
|
||||
Applicability::MachineApplicable
|
||||
};
|
||||
|
||||
let sugg = Sugg::hir_with_macro_callsite(cx, result_expr, "_")
|
||||
let sugg = Sugg::hir_with_context(cx, result_expr, ctxt, "_", &mut app)
|
||||
.maybe_par()
|
||||
.to_string();
|
||||
|
||||
|
|
|
@ -67,8 +67,10 @@ fn report_single_pattern(
|
|||
els: Option<&Expr<'_>>,
|
||||
) {
|
||||
let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH };
|
||||
let ctxt = expr.span.ctxt();
|
||||
let mut app = Applicability::HasPlaceholders;
|
||||
let els_str = els.map_or(String::new(), |els| {
|
||||
format!(" else {}", expr_block(cx, els, None, "..", Some(expr.span)))
|
||||
format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
|
||||
});
|
||||
|
||||
let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat);
|
||||
|
@ -103,7 +105,7 @@ fn report_single_pattern(
|
|||
// PartialEq for different reference counts may not exist.
|
||||
"&".repeat(ref_count_diff),
|
||||
snippet(cx, arms[0].pat.span, ".."),
|
||||
expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
|
||||
expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
|
||||
);
|
||||
(msg, sugg)
|
||||
} else {
|
||||
|
@ -112,21 +114,13 @@ fn report_single_pattern(
|
|||
"if let {} = {} {}{els_str}",
|
||||
snippet(cx, arms[0].pat.span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
|
||||
expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
|
||||
);
|
||||
(msg, sugg)
|
||||
}
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
lint,
|
||||
expr.span,
|
||||
msg,
|
||||
"try this",
|
||||
sugg,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
span_lint_and_sugg(cx, lint, expr.span, msg, "try this", sugg, app);
|
||||
}
|
||||
|
||||
fn check_opt_like<'a>(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{contains_return, BIND_INSTEAD_OF_MAP};
|
||||
use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
|
||||
use clippy_utils::source::{snippet, snippet_with_context};
|
||||
use clippy_utils::{peel_blocks, visitors::find_all_ret_expressions};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -76,11 +76,8 @@ pub(crate) trait BindInsteadOfMap {
|
|||
if !contains_return(inner_expr);
|
||||
if let Some(msg) = Self::lint_msg(cx);
|
||||
then {
|
||||
let some_inner_snip = if inner_expr.span.from_expansion() {
|
||||
snippet_with_macro_callsite(cx, inner_expr.span, "_")
|
||||
} else {
|
||||
snippet(cx, inner_expr.span, "_")
|
||||
};
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0;
|
||||
|
||||
let closure_args_snip = snippet(cx, closure_args_span, "..");
|
||||
let option_snip = snippet(cx, recv.span, "..");
|
||||
|
@ -92,7 +89,7 @@ pub(crate) trait BindInsteadOfMap {
|
|||
&msg,
|
||||
"try this",
|
||||
note,
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
true
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::paths;
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, match_type};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
@ -33,7 +33,9 @@ pub(super) fn check(
|
|||
return;
|
||||
};
|
||||
|
||||
let snippet = snippet_with_macro_callsite(cx, receiver.span, "..");
|
||||
// Sometimes unnecessary ::<_> after Rc/Arc/Weak
|
||||
let mut app = Applicability::Unspecified;
|
||||
let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -42,7 +44,7 @@ pub(super) fn check(
|
|||
"using `.clone()` on a ref-counted pointer",
|
||||
"try this",
|
||||
format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
|
||||
Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
|
||||
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::{contains_return, is_trait_item, last_path_segment};
|
||||
use if_chain::if_chain;
|
||||
|
@ -9,7 +9,6 @@ use rustc_hir as hir;
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::OR_FUN_CALL;
|
||||
|
||||
|
@ -111,37 +110,24 @@ pub(super) fn check<'tcx>(
|
|||
if poss.contains(&name);
|
||||
|
||||
then {
|
||||
let ctxt = span.ctxt();
|
||||
let mut app = Applicability::HasPlaceholders;
|
||||
let sugg = {
|
||||
let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) {
|
||||
(false, Some(fun_span)) => (fun_span, false),
|
||||
_ => (arg.span, true),
|
||||
};
|
||||
|
||||
let format_span = |span: Span| {
|
||||
let not_macro_argument_snippet = snippet_with_macro_callsite(cx, span, "..");
|
||||
let snip = if not_macro_argument_snippet == "vec![]" {
|
||||
let macro_expanded_snipped = snippet(cx, snippet_span, "..");
|
||||
match macro_expanded_snipped.strip_prefix("$crate::vec::") {
|
||||
Some(stripped) => Cow::Owned(stripped.to_owned()),
|
||||
None => macro_expanded_snipped,
|
||||
}
|
||||
} else {
|
||||
not_macro_argument_snippet
|
||||
};
|
||||
|
||||
snip.to_string()
|
||||
};
|
||||
|
||||
let snip = format_span(snippet_span);
|
||||
let snip = snippet_with_context(cx, snippet_span, ctxt, "..", &mut app).0;
|
||||
let snip = if use_lambda {
|
||||
let l_arg = if fn_has_arguments { "_" } else { "" };
|
||||
format!("|{l_arg}| {snip}")
|
||||
} else {
|
||||
snip
|
||||
snip.into_owned()
|
||||
};
|
||||
|
||||
if let Some(f) = second_arg {
|
||||
let f = format_span(f.span);
|
||||
let f = snippet_with_context(cx, f.span, ctxt, "..", &mut app).0;
|
||||
format!("{snip}, {f}")
|
||||
} else {
|
||||
snip
|
||||
|
@ -155,7 +141,7 @@ pub(super) fn check<'tcx>(
|
|||
&format!("use of `{name}` followed by a function call"),
|
||||
"try this",
|
||||
format!("{name}_{suffix}({sugg})"),
|
||||
Applicability::HasPlaceholders,
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_hir_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_opt};
|
||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_context};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
|
@ -181,20 +181,17 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
|
|||
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
|
||||
if let Some(init) = local.init;
|
||||
then {
|
||||
// use the macro callsite when the init span (but not the whole local span)
|
||||
// comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
|
||||
let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() {
|
||||
Sugg::hir_with_macro_callsite(cx, init, "..")
|
||||
} else {
|
||||
Sugg::hir(cx, init, "..")
|
||||
};
|
||||
let ctxt = local.span.ctxt();
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let sugg_init = Sugg::hir_with_context(cx, init, ctxt, "..", &mut app);
|
||||
let (mutopt, initref) = if mutabl == Mutability::Mut {
|
||||
("mut ", sugg_init.mut_addr())
|
||||
} else {
|
||||
("", sugg_init.addr())
|
||||
};
|
||||
let tyopt = if let Some(ty) = local.ty {
|
||||
format!(": &{mutopt}{ty}", ty=snippet(cx, ty.span, ".."))
|
||||
let ty_snip = snippet_with_context(cx, ty.span, ctxt, "_", &mut app).0;
|
||||
format!(": &{mutopt}{ty_snip}")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
@ -212,7 +209,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
|
|||
"let {name}{tyopt} = {initref};",
|
||||
name=snippet(cx, name.span, ".."),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
app,
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -340,18 +340,11 @@ fn suggest_bool_comparison<'a, 'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
expr: &Expr<'_>,
|
||||
mut applicability: Applicability,
|
||||
mut app: Applicability,
|
||||
message: &str,
|
||||
conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>,
|
||||
) {
|
||||
let hint = if expr.span.from_expansion() {
|
||||
if applicability != Applicability::Unspecified {
|
||||
applicability = Applicability::MaybeIncorrect;
|
||||
}
|
||||
Sugg::hir_with_macro_callsite(cx, expr, "..")
|
||||
} else {
|
||||
Sugg::hir_with_applicability(cx, expr, "..", &mut applicability)
|
||||
};
|
||||
let hint = Sugg::hir_with_context(cx, expr, e.span.ctxt(), "..", &mut app);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BOOL_COMPARISON,
|
||||
|
@ -359,7 +352,7 @@ fn suggest_bool_comparison<'a, 'tcx>(
|
|||
message,
|
||||
"try simplifying it as shown",
|
||||
conv_hint(hint).to_string(),
|
||||
applicability,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use rustc_hir::{
|
|||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::SyntaxContext;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
@ -95,10 +96,10 @@ struct OptionOccurrence {
|
|||
none_expr: String,
|
||||
}
|
||||
|
||||
fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
|
||||
fn format_option_in_sugg(cond_sugg: Sugg<'_>, as_ref: bool, as_mut: bool) -> String {
|
||||
format!(
|
||||
"{}{}",
|
||||
Sugg::hir_with_macro_callsite(cx, cond_expr, "..").maybe_par(),
|
||||
cond_sugg.maybe_par(),
|
||||
if as_mut {
|
||||
".as_mut()"
|
||||
} else if as_ref {
|
||||
|
@ -111,6 +112,7 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo
|
|||
|
||||
fn try_get_option_occurrence<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
ctxt: SyntaxContext,
|
||||
pat: &Pat<'tcx>,
|
||||
expr: &Expr<'_>,
|
||||
if_then: &'tcx Expr<'_>,
|
||||
|
@ -160,11 +162,23 @@ fn try_get_option_occurrence<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut app = Applicability::Unspecified;
|
||||
return Some(OptionOccurrence {
|
||||
option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
|
||||
option: format_option_in_sugg(
|
||||
Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app),
|
||||
as_ref,
|
||||
as_mut,
|
||||
),
|
||||
method_sugg: method_sugg.to_string(),
|
||||
some_expr: format!("|{capture_mut}{capture_name}| {}", Sugg::hir_with_macro_callsite(cx, some_body, "..")),
|
||||
none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir_with_macro_callsite(cx, none_body, "..")),
|
||||
some_expr: format!(
|
||||
"|{capture_mut}{capture_name}| {}",
|
||||
Sugg::hir_with_context(cx, some_body, ctxt, "..", &mut app),
|
||||
),
|
||||
none_expr: format!(
|
||||
"{}{}",
|
||||
if method_sugg == "map_or" { "" } else { "|| " },
|
||||
Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +208,7 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
|
|||
}) = higher::IfLet::hir(cx, expr)
|
||||
{
|
||||
if !is_else_clause(cx.tcx, expr) {
|
||||
return try_get_option_occurrence(cx, let_pat, let_expr, if_then, if_else);
|
||||
return try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, let_expr, if_then, if_else);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -203,7 +217,7 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
|
|||
fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurrence> {
|
||||
if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind {
|
||||
if let Some((let_pat, if_then, if_else)) = try_convert_match(cx, arms) {
|
||||
return try_get_option_occurrence(cx, let_pat, ex, if_then, if_else);
|
||||
return try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, ex, if_then, if_else);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::rustc_lint::LintContext;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Block, ExprKind};
|
||||
|
@ -44,7 +43,8 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
|
|||
if let Some(expr) = block.expr;
|
||||
let t_expr = cx.typeck_results().expr_ty(expr);
|
||||
if t_expr.is_unit();
|
||||
if let snippet = snippet_with_macro_callsite(cx, expr.span, "}");
|
||||
let mut app = Applicability::MaybeIncorrect;
|
||||
if let snippet = snippet_with_context(cx, expr.span, block.span.ctxt(), "}", &mut app).0;
|
||||
if !snippet.ends_with('}') && !snippet.ends_with(';');
|
||||
if cx.sess().source_map().is_multiline(block.span);
|
||||
then {
|
||||
|
@ -52,17 +52,14 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
|
|||
if let ExprKind::DropTemps(..) = &expr.kind {
|
||||
return;
|
||||
}
|
||||
|
||||
let sugg = sugg::Sugg::hir_with_macro_callsite(cx, expr, "..");
|
||||
let suggestion = format!("{sugg};");
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SEMICOLON_IF_NOTHING_RETURNED,
|
||||
expr.span.source_callsite(),
|
||||
"consider adding a `;` to the last statement for consistent formatting",
|
||||
"add a `;` here",
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
format!("{snippet};"),
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::get_parent_node;
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -52,12 +52,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
|||
"this let-binding has unit value",
|
||||
|diag| {
|
||||
if let Some(expr) = &local.init {
|
||||
let snip = snippet_with_macro_callsite(cx, expr.span, "()");
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let snip = snippet_with_context(cx, expr.span, local.span.ctxt(), "()", &mut app).0;
|
||||
diag.span_suggestion(
|
||||
local.span,
|
||||
"omit the `let` binding",
|
||||
format!("{snip};"),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
app,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
|
||||
use clippy_utils::source::{snippet, snippet_with_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
|
||||
use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths};
|
||||
|
@ -68,15 +68,16 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
|
|||
let a = cx.typeck_results().expr_ty(e);
|
||||
let b = cx.typeck_results().expr_ty(recv);
|
||||
if same_type_and_consts(a, b) {
|
||||
let sugg = snippet_with_macro_callsite(cx, recv.span, "<expr>").to_string();
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let sugg = snippet_with_context(cx, recv.span, e.span.ctxt(), "<expr>", &mut app).0;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
&format!("useless conversion to the same type: `{b}`"),
|
||||
"consider removing `.into()`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
sugg.into_owned(),
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +166,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
|
|||
if same_type_and_consts(a, b);
|
||||
|
||||
then {
|
||||
let sugg = Sugg::hir_with_macro_callsite(cx, arg, "<expr>").maybe_par();
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "<expr>", &mut app).maybe_par();
|
||||
let sugg_msg =
|
||||
format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
|
||||
span_lint_and_sugg(
|
||||
|
@ -175,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
|
|||
&format!("useless conversion to the same type: `{b}`"),
|
||||
&sugg_msg,
|
||||
sugg.to_string(),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
app,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,24 +12,21 @@ use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
|
|||
use std::borrow::Cow;
|
||||
|
||||
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
|
||||
/// Also takes an `Option<String>` which can be put inside the braces.
|
||||
pub fn expr_block<'a, T: LintContext>(
|
||||
pub fn expr_block<T: LintContext>(
|
||||
cx: &T,
|
||||
expr: &Expr<'_>,
|
||||
option: Option<String>,
|
||||
default: &'a str,
|
||||
outer: SyntaxContext,
|
||||
default: &str,
|
||||
indent_relative_to: Option<Span>,
|
||||
) -> Cow<'a, str> {
|
||||
let code = snippet_block(cx, expr.span, default, indent_relative_to);
|
||||
let string = option.unwrap_or_default();
|
||||
if expr.span.from_expansion() {
|
||||
Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
|
||||
app: &mut Applicability,
|
||||
) -> String {
|
||||
let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app);
|
||||
if from_macro {
|
||||
format!("{{ {code} }}")
|
||||
} else if let ExprKind::Block(_, _) = expr.kind {
|
||||
Cow::Owned(format!("{code}{string}"))
|
||||
} else if string.is_empty() {
|
||||
Cow::Owned(format!("{{ {code} }}"))
|
||||
format!("{code}")
|
||||
} else {
|
||||
Cow::Owned(format!("{{\n{code};\n{string}\n}}"))
|
||||
format!("{{ {code} }}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,12 +226,6 @@ fn snippet_with_applicability_sess<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
/// Same as `snippet`, but should only be used when it's clear that the input span is
|
||||
/// not a macro argument.
|
||||
pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||
snippet(cx, span.source_callsite(), default)
|
||||
}
|
||||
|
||||
/// Converts a span to a code snippet. Returns `None` if not available.
|
||||
pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
|
||||
snippet_opt_sess(cx.sess(), span)
|
||||
|
@ -303,6 +294,19 @@ pub fn snippet_block_with_applicability<'a>(
|
|||
reindent_multiline(snip, true, indent)
|
||||
}
|
||||
|
||||
pub fn snippet_block_with_context<'a>(
|
||||
cx: &impl LintContext,
|
||||
span: Span,
|
||||
outer: SyntaxContext,
|
||||
default: &'a str,
|
||||
indent_relative_to: Option<Span>,
|
||||
app: &mut Applicability,
|
||||
) -> (Cow<'a, str>, bool) {
|
||||
let (snip, from_macro) = snippet_with_context(cx, span, outer, default, app);
|
||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
||||
(reindent_multiline(snip, true, indent), from_macro)
|
||||
}
|
||||
|
||||
/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
|
||||
/// will result in the macro call, rather then the expansion, if the span is from a child context.
|
||||
/// If the span is not from a child context, it will be used directly instead.
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
//! Contains utility functions to generate suggestions.
|
||||
#![deny(clippy::missing_docs_in_private_items)]
|
||||
|
||||
use crate::source::{
|
||||
snippet, snippet_opt, snippet_with_applicability, snippet_with_context, snippet_with_macro_callsite,
|
||||
};
|
||||
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
|
||||
use crate::ty::expr_sig;
|
||||
use crate::{get_parent_expr_for_hir, higher};
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
|
@ -89,12 +87,6 @@ impl<'a> Sugg<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Same as `hir`, but will use the pre expansion span if the `expr` was in a macro.
|
||||
pub fn hir_with_macro_callsite(cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str) -> Self {
|
||||
let get_snippet = |span| snippet_with_macro_callsite(cx, span, default);
|
||||
Self::hir_from_snippet(expr, get_snippet)
|
||||
}
|
||||
|
||||
/// Same as `hir`, but first walks the span up to the given context. This will result in the
|
||||
/// macro call, rather then the expansion, if the span is from a child context. If the span is
|
||||
/// not from a child context, it will be used directly instead.
|
||||
|
|
|
@ -69,8 +69,8 @@ fn issue5504() {
|
|||
}
|
||||
|
||||
fn try_result_opt() -> Result<i32, i32> {
|
||||
while (r#try!(result_opt())).is_some() {}
|
||||
if (r#try!(result_opt())).is_some() {}
|
||||
while r#try!(result_opt()).is_some() {}
|
||||
if r#try!(result_opt()).is_some() {}
|
||||
Ok(42)
|
||||
}
|
||||
|
||||
|
|
|
@ -88,13 +88,13 @@ error: redundant pattern matching, consider using `is_some()`
|
|||
--> $DIR/redundant_pattern_matching_result.rs:84:19
|
||||
|
|
||||
LL | while let Some(_) = r#try!(result_opt()) {}
|
||||
| ----------^^^^^^^----------------------- help: try this: `while (r#try!(result_opt())).is_some()`
|
||||
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:85:16
|
||||
|
|
||||
LL | if let Some(_) = r#try!(result_opt()) {}
|
||||
| -------^^^^^^^----------------------- help: try this: `if (r#try!(result_opt())).is_some()`
|
||||
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:91:12
|
||||
|
|
Loading…
Reference in a new issue