Skip to content

Remove snippet_with_macro_callsite #10434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions clippy_lints/src/default.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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>>()
Expand Down
17 changes: 9 additions & 8 deletions clippy_lints/src/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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 {
Expand Down
32 changes: 19 additions & 13 deletions clippy_lints/src/loops/same_item_push.rs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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);
}
}
_ => {},
Expand All @@ -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),
_ => {},
}
}
Expand All @@ -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>,
}
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
12 changes: 3 additions & 9 deletions clippy_lints/src/matches/manual_unwrap_or.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,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,
Expand All @@ -49,7 +43,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
format!(
"{suggestion}.unwrap_or({reindented_or_body})",
),
Applicability::MachineApplicable,
app,
);
}
}
Expand Down
20 changes: 11 additions & 9 deletions clippy_lints/src/matches/match_bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
28 changes: 22 additions & 6 deletions clippy_lints/src/matches/match_ref_pats.rs
Original file line number Diff line number Diff line change
@@ -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>>,
Expand All @@ -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";
}
Expand Down
Loading