Replace more uses of `snippet_opt`.

This commit is contained in:
Jason Newcomb 2024-08-21 14:04:04 -04:00
parent a83146aea9
commit 9450b4af48
20 changed files with 125 additions and 109 deletions

View File

@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_const_context;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability;
@ -34,7 +34,7 @@ pub(super) fn check(
diag.help("an `as` cast can become silently lossy if the types change in the future");
let mut applicability = Applicability::MachineApplicable;
let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability);
let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else {
let Some(ty) = hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt()).get_source_text(cx) else {
return;
};
match cast_to_hir.kind {

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::{snippet_opt, SpanRangeExt};
use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
use rustc_ast::{LitFloatType, LitIntType, LitKind};
@ -104,7 +104,7 @@ pub(super) fn check<'tcx>(
let literal_str = &cast_str;
if let LitKind::Int(n, _) = lit.node
&& let Some(src) = snippet_opt(cx, cast_expr.span)
&& let Some(src) = cast_expr.span.get_source_text(cx)
&& cast_to.is_floating_point()
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
&& let from_nbits = 128 - n.get().leading_zeros()
@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(
| LitKind::Float(_, LitFloatType::Suffixed(_))
if cast_from.kind() == cast_to.kind() =>
{
if let Some(src) = snippet_opt(cx, cast_expr.span) {
if let Some(src) = cast_expr.span.get_source_text(cx) {
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
return true;
@ -253,7 +253,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
let res = cx.qpath_res(&qpath, expr.hir_id);
// Function call
if let Res::Def(DefKind::Fn, def_id) = res {
let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else {
let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else {
return ControlFlow::Continue(());
};
// This is the worst part of this entire function. This is the only way I know of to

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability, Ty, TyKind};
@ -20,7 +20,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>
let sugg = if let TyKind::Infer = mut_ty.ty.kind {
format!("{std_or_core}::{sugg_fn}()")
} else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
} else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) {
format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
} else {
return;

View File

@ -12,7 +12,7 @@ use rustc_span::{sym, Span};
use clippy_utils::attrs::is_proc_macro;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_must_use_ty;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{return_ty, trait_ref_of_method};
@ -155,7 +155,7 @@ fn check_must_use_candidate<'tcx>(
return;
}
span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
if let Some(snippet) = snippet_opt(cx, fn_span) {
if let Some(snippet) = fn_span.get_source_text(cx) {
diag.span_suggestion(
fn_span,
"add the attribute",

View File

@ -1,12 +1,11 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::SpanRangeExt;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_span::Span;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet_opt;
use super::TOO_MANY_LINES;
pub(super) fn check_fn(
@ -22,57 +21,57 @@ pub(super) fn check_fn(
return;
}
let Some(code_snippet) = snippet_opt(cx, body.value.span) else {
return;
};
let mut line_count: u64 = 0;
let mut in_comment = false;
let mut code_in_line;
let too_many = body.value.span.check_source_text(cx, |src| {
let mut in_comment = false;
let mut code_in_line;
let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
&& code_snippet.as_bytes().first().copied() == Some(b'{')
&& code_snippet.as_bytes().last().copied() == Some(b'}')
{
// Removing the braces from the enclosing block
&code_snippet[1..code_snippet.len() - 1]
} else {
&code_snippet
}
.trim() // Remove leading and trailing blank lines
.lines();
let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
&& src.as_bytes().first().copied() == Some(b'{')
&& src.as_bytes().last().copied() == Some(b'}')
{
// Removing the braces from the enclosing block
&src[1..src.len() - 1]
} else {
src
}
.trim() // Remove leading and trailing blank lines
.lines();
for mut line in function_lines {
code_in_line = false;
loop {
line = line.trim_start();
if line.is_empty() {
for mut line in function_lines {
code_in_line = false;
loop {
line = line.trim_start();
if line.is_empty() {
break;
}
if in_comment {
if let Some(i) = line.find("*/") {
line = &line[i + 2..];
in_comment = false;
continue;
}
} else {
let multi_idx = line.find("/*").unwrap_or(line.len());
let single_idx = line.find("//").unwrap_or(line.len());
code_in_line |= multi_idx > 0 && single_idx > 0;
// Implies multi_idx is below line.len()
if multi_idx < single_idx {
line = &line[multi_idx + 2..];
in_comment = true;
continue;
}
}
break;
}
if in_comment {
if let Some(i) = line.find("*/") {
line = &line[i + 2..];
in_comment = false;
continue;
}
} else {
let multi_idx = line.find("/*").unwrap_or(line.len());
let single_idx = line.find("//").unwrap_or(line.len());
code_in_line |= multi_idx > 0 && single_idx > 0;
// Implies multi_idx is below line.len()
if multi_idx < single_idx {
line = &line[multi_idx + 2..];
in_comment = true;
continue;
}
if code_in_line {
line_count += 1;
}
break;
}
if code_in_line {
line_count += 1;
}
}
line_count > too_many_lines_threshold
});
if line_count > too_many_lines_threshold {
if too_many {
span_lint(
cx,
TOO_MANY_LINES,

View File

@ -1,6 +1,6 @@
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
@ -67,11 +67,11 @@ fn check_and_lint<'tcx>(
&& path_to_local_id(peel_blocks(then_expr), binding_hir_id)
&& cx.typeck_results().expr_adjustments(then_expr).is_empty()
&& let Some(ty_name) = find_type_name(cx, ty)
&& let Some(or_body_snippet) = snippet_opt(cx, else_expr.span)
&& let Some(or_body_snippet) = else_expr.span.get_source_text(cx)
&& let Some(indent) = indent_of(cx, expr.span)
&& ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
{
lint(cx, expr, let_expr, ty_name, or_body_snippet, indent);
lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent);
}
}
@ -110,7 +110,7 @@ fn lint<'tcx>(
expr: &Expr<'tcx>,
scrutinee: &'tcx Expr<'_>,
ty_name: &str,
or_body_snippet: String,
or_body_snippet: &str,
indent: usize,
) {
let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent));

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
use clippy_utils::ty::is_type_lang_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@ -49,10 +49,12 @@ pub(super) fn check<'tcx>(
"case-sensitive file extension comparison",
|diag| {
diag.help("consider using a case-insensitive comparison instead");
if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
if !cx.typeck_results().expr_ty(recv).is_ref() {
recv_source = format!("&{recv_source}");
}
if let Some(recv_source) = recv.span.get_source_text(cx) {
let recv_source = if cx.typeck_results().expr_ty(recv).is_ref() {
recv_source.to_owned()
} else {
format!("&{recv_source}")
};
let suggestion_source = reindent_multiline(
format!(

View File

@ -1,7 +1,7 @@
use super::FILTER_MAP_BOOL_THEN;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::paths::BOOL_THEN;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_copy;
use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
use rustc_errors::Applicability;
@ -42,9 +42,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
.iter()
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
.count()
&& let Some(param_snippet) = snippet_opt(cx, param.span)
&& let Some(filter) = snippet_opt(cx, recv.span)
&& let Some(map) = snippet_opt(cx, then_body.span)
&& let Some(param_snippet) = param.span.get_source_text(cx)
&& let Some(filter) = recv.span.get_source_text(cx)
&& let Some(map) = then_body.span.get_source_text(cx)
{
span_lint_and_sugg(
cx,

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_path_diagnostic_item, sugg};
use rustc_errors::Applicability;
@ -39,7 +39,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
}
let call_site = expr.span.source_callsite();
if let Some(snippet) = snippet_opt(cx, call_site)
if let Some(snippet) = call_site.get_source_text(cx)
&& let snippet_split = snippet.split("::").collect::<Vec<_>>()
&& let Some((_, elements)) = snippet_split.split_last()
{

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::expr_or_init;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
join_arg.span,
"argument to `Path::join` starts with a path separator",
|diag| {
let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string());
let arg_str = snippet(cx, spanned.span, "..");
let no_separator = if sym_str.starts_with('/') {
arg_str.replacen('/', "", 1)

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
use rustc_errors::Applicability;
@ -23,11 +23,11 @@ pub(super) fn check<'tcx>(
&& let ExprKind::Call(err_path, [err_arg]) = or_expr.kind
&& is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr)
&& is_ok_wrapping(cx, map_expr)
&& let Some(recv_snippet) = snippet_opt(cx, recv.span)
&& let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span)
&& let Some(recv_snippet) = recv.span.get_source_text(cx)
&& let Some(err_arg_snippet) = err_arg.span.get_source_text(cx)
&& let Some(indent) = indent_of(cx, expr.span)
{
let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4));
let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4));
span_lint_and_sugg(
cx,
MANUAL_OK_OR,

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_from_proc_macro, is_trait_method};
use rustc_errors::Applicability;
@ -31,13 +31,15 @@ pub(super) fn check<'tcx>(
&& let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id)
&& let ExprKind::Closure(closure) = acc.kind
&& !is_from_proc_macro(cx, expr)
&& let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span))
&& let Some(args_snip) = closure
.fn_arg_span
.and_then(|fn_arg_span| fn_arg_span.get_source_text(cx))
{
let init_snip = rest
.is_empty()
.then_some(first.span)
.and_then(|span| snippet_opt(cx, span))
.unwrap_or("...".to_owned());
.and_then(|span| span.get_source_text(cx))
.map_or_else(|| "...".to_owned(), |src| src.to_owned());
span_lint_and_sugg(
cx,

View File

@ -7,7 +7,7 @@ use rustc_span::Span;
use super::utils::get_last_chain_binding_hir_id;
use super::NEEDLESS_CHARACTER_ITERATION;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
@ -35,7 +35,7 @@ fn handle_expr(
&& path_to_local_id(receiver, first_param)
&& let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
&& *char_arg_ty.kind() == ty::Char
&& let Some(snippet) = snippet_opt(cx, before_chars)
&& let Some(snippet) = before_chars.get_source_text(cx)
{
span_lint_and_sugg(
cx,
@ -79,7 +79,7 @@ fn handle_expr(
&& let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
&& match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"])
&& path_to_local_id(peels_expr_ref(arg), first_param)
&& let Some(snippet) = snippet_opt(cx, before_chars)
&& let Some(snippet) = before_chars.get_source_text(cx)
{
span_lint_and_sugg(
cx,

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::path_res;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::local_used_after_expr;
use rustc_errors::Applicability;
@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name
expr.span,
"derefed type is same as origin",
"try",
snippet_opt(cx, recv.span).unwrap(),
recv.span.get_source_text(cx).unwrap().to_owned(),
Applicability::MachineApplicable,
);
}

View File

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
use itertools::Itertools;
use rustc_ast::LitKind;
@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
_ => return,
}
&& !is_from_proc_macro(cx, expr)
&& let Some(scrutinee_snip) = snippet_opt(cx, scrutinee.span)
&& let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx)
{
// Normalize the char using `map` so `join` doesn't use `Display`, if we don't then
// something like `r"\"` will become `'\'`, which is of course invalid

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::Applicability;
@ -38,11 +38,11 @@ pub(super) fn check(
return;
};
let both_calls_span = get_call_span.with_hi(call_span.hi());
if let Some(snippet) = snippet_opt(cx, both_calls_span)
&& let Some(arg_snippet) = snippet_opt(cx, arg.span)
if let Some(snippet) = both_calls_span.get_source_text(cx)
&& let Some(arg_snippet) = arg.span.get_source_text(cx)
{
let generics_snippet = if let Some(generics) = path.args
&& let Some(generics_snippet) = snippet_opt(cx, generics.span_ext)
&& let Some(generics_snippet) = generics.span_ext.get_source_text(cx)
{
format!("::{generics_snippet}")
} else {
@ -63,7 +63,7 @@ pub(super) fn check(
suggestion,
Applicability::MaybeIncorrect,
);
} else if let Some(caller_snippet) = snippet_opt(cx, get_caller.span) {
} else if let Some(caller_snippet) = get_caller.span.get_source_text(cx) {
let full_span = get_caller.span.with_hi(call_span.hi());
span_lint_and_then(

View File

@ -2,7 +2,7 @@ use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::source::{snippet, SpanRangeExt};
use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{
@ -133,7 +133,7 @@ fn check_addr_of_expr(
&& (*referent_ty != receiver_ty
|| (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty))
|| is_cow_into_owned(cx, method_name, method_def_id))
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
&& let Some(receiver_snippet) = receiver.span.get_source_text(cx)
{
if receiver_ty == target_ty && n_target_refs >= n_receiver_refs {
span_lint_and_sugg(
@ -167,7 +167,7 @@ fn check_addr_of_expr(
parent.span,
format!("unnecessary use of `{method_name}`"),
"use",
receiver_snippet,
receiver_snippet.to_owned(),
Applicability::MachineApplicable,
);
} else {
@ -217,7 +217,7 @@ fn check_into_iter_call_arg(
&& let parent_ty = cx.typeck_results().expr_ty(parent)
&& implements_trait(cx, parent_ty, iterator_trait_id, &[])
&& let Some(item_ty) = get_iterator_item_ty(cx, parent_ty)
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
&& let Some(receiver_snippet) = receiver.span.get_source_text(cx)
{
if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) {
return true;
@ -309,8 +309,8 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
if let Some(parent) = get_parent_expr(cx, expr)
&& let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent)
&& fn_name.as_str() == "split"
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
&& let Some(arg_snippet) = snippet_opt(cx, argument_expr.span)
&& let Some(receiver_snippet) = receiver.span.get_source_text(cx)
&& let Some(arg_snippet) = argument_expr.span.get_source_text(cx)
{
// We may end-up here because of an expression like `x.to_string().split(…)` where the type of `x`
// implements `AsRef<str>` but does not implement `Deref<Target = str>`. In this case, we have to
@ -405,7 +405,7 @@ fn check_other_call_arg<'tcx>(
None
}
&& can_change_type(cx, maybe_arg, receiver_ty)
&& let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
&& let Some(receiver_snippet) = receiver.span.get_source_text(cx)
{
span_lint_and_sugg(
cx,
@ -695,7 +695,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
&& let arg_ty = arg_ty.peel_refs()
// For now we limit this lint to `String` and `Vec`.
&& (is_str_and_string(cx, arg_ty, original_arg_ty) || is_slice_and_vec(cx, arg_ty, original_arg_ty))
&& let Some(snippet) = snippet_opt(cx, caller.span)
&& let Some(snippet) = caller.span.get_source_text(cx)
{
span_lint_and_sugg(
cx,
@ -706,7 +706,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
if original_arg_ty.is_array() {
format!("{snippet}.as_slice()")
} else {
snippet
snippet.to_owned()
},
Applicability::MaybeIncorrect,
);

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::source::{snippet, SpanRangeExt};
use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind};
@ -81,8 +81,14 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) {
// We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`.
// Fallback to `..` if we fail getting either snippet.
Some(ty_span) => snippet_opt(cx, elem.span)
.and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}")))
Some(ty_span) => elem
.span
.get_source_text(cx)
.and_then(|binding_name| {
ty_span
.get_source_text(cx)
.map(|ty_name| format!("{binding_name}: {ty_name}"))
})
.unwrap_or_else(|| "..".to_string()),
// Otherwise, we have no explicit type. We can replace with the binding name of the element.
None => snippet(cx, elem.span, "..").into_owned(),

View File

@ -5,7 +5,7 @@ use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_copy;
use clippy_utils::visitors::for_each_local_use_after_expr;
use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method};
@ -214,9 +214,11 @@ impl SuggestedType {
}
fn snippet(self, cx: &LateContext<'_>, args_span: Option<Span>, len_span: Option<Span>) -> String {
let maybe_args = args_span.and_then(|sp| snippet_opt(cx, sp)).unwrap_or_default();
let maybe_args = args_span
.and_then(|sp| sp.get_source_text(cx))
.map_or(String::new(), |x| x.to_owned());
let maybe_len = len_span
.and_then(|sp| snippet_opt(cx, sp).map(|s| format!("; {s}")))
.and_then(|sp| sp.get_source_text(cx).map(|s| format!("; {s}")))
.unwrap_or_default();
match self {

View File

@ -207,6 +207,7 @@ fn get_source_range(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRang
if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
return None;
}
sm.ensure_source_file_source_present(&start.sf);
let range = start.pos.to_usize()..end.pos.to_usize();
Some(SourceFileRange { sf: start.sf, range })
}
@ -283,7 +284,11 @@ impl SourceFileRange {
/// Attempts to get the text from the source file. This can fail if the source text isn't
/// loaded.
pub fn as_str(&self) -> Option<&str> {
self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
self.sf
.src
.as_ref()
.or_else(|| self.sf.external_src.get().and_then(|src| src.get_source()))
.and_then(|x| x.get(self.range.clone()))
}
}