Auto merge of #13255 - Jarcho:get_src_display2, r=Manishearth
Remove more `snippet_opt` calls First commit is the same as #13244 changelog: none
This commit is contained in:
commit
1984752623
@ -1,6 +1,6 @@
|
||||
use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments};
|
||||
use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt};
|
||||
use rustc_ast::{AttrKind, AttrStyle};
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
||||
item.span.parent(),
|
||||
);
|
||||
|
||||
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
|
||||
if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) {
|
||||
let lines = snippet.split('\n').collect::<Vec<_>>();
|
||||
let lines = without_block_comments(lines);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{Attribute, NON_MINIMAL_CFG};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use rustc_ast::{MetaItemKind, NestedMetaItem};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
@ -29,8 +29,13 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
|
||||
meta.span,
|
||||
"unneeded sub `cfg` when there is only one condition",
|
||||
|diag| {
|
||||
if let Some(snippet) = snippet_opt(cx, list[0].span()) {
|
||||
diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
|
||||
if let Some(snippet) = list[0].span().get_source_text(cx) {
|
||||
diag.span_suggestion(
|
||||
meta.span,
|
||||
"try",
|
||||
snippet.to_owned(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
|
||||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, Level};
|
||||
@ -31,7 +32,7 @@ pub(super) fn check(
|
||||
return;
|
||||
}
|
||||
if nb_items == clippy_lints.len() {
|
||||
if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
|
||||
if let Some(snippet) = behind_cfg_attr.span.get_source_text(cx) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNNECESSARY_CLIPPY_CFG,
|
||||
@ -47,11 +48,7 @@ pub(super) fn check(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let snippet = clippy_lints
|
||||
.iter()
|
||||
.filter_map(|sp| snippet_opt(cx, *sp))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let snippet = clippy_lints.iter().filter_map(|sp| sp.get_source_text(cx)).join(",");
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
UNNECESSARY_CLIPPY_CFG,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
||||
use super::{Attribute, USELESS_ATTRIBUTE};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{first_line_of_span, snippet_opt};
|
||||
use clippy_utils::source::{first_line_of_span, SpanRangeExt};
|
||||
use rustc_ast::NestedMetaItem;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
@ -69,14 +69,14 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
|
||||
}
|
||||
let line_span = first_line_of_span(cx, attr.span);
|
||||
|
||||
if let Some(mut sugg) = snippet_opt(cx, line_span) {
|
||||
if sugg.contains("#[") {
|
||||
if let Some(src) = line_span.get_source_text(cx) {
|
||||
if src.contains("#[") {
|
||||
#[expect(clippy::collapsible_span_lint_calls)]
|
||||
span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
|
||||
sugg = sugg.replacen("#[", "#![", 1);
|
||||
diag.span_suggestion(
|
||||
line_span,
|
||||
"if you just forgot a `!`, use",
|
||||
sugg,
|
||||
src.replacen("#[", "#![", 1),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
&& let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity()
|
||||
&& let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next()
|
||||
&& let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind()
|
||||
&& let Some(recv) = snippet_opt(cx, receiver.span)
|
||||
&& let Some(recv) = receiver.span.get_source_text(cx)
|
||||
{
|
||||
// `as_mut_ptr` might not exist
|
||||
let applicability = Applicability::MaybeIncorrect;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
|
||||
use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
@ -68,8 +68,8 @@ fn check_fn(
|
||||
header_span,
|
||||
"this function can be simplified using the `async fn` syntax",
|
||||
|diag| {
|
||||
if let Some(vis_snip) = snippet_opt(cx, *vis_span)
|
||||
&& let Some(header_snip) = snippet_opt(cx, header_span)
|
||||
if let Some(vis_snip) = vis_span.get_source_text(cx)
|
||||
&& let Some(header_snip) = header_span.get_source_text(cx)
|
||||
&& let Some(ret_pos) = position_before_rarrow(&header_snip)
|
||||
&& let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
|
||||
{
|
||||
@ -190,6 +190,6 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
|
||||
Some((sugg, String::new()))
|
||||
} else {
|
||||
let sugg = "return the output of the future directly";
|
||||
snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
|
||||
output.span.get_source_text(cx).map(|src| (sugg, format!(" -> {src}")))
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
|
||||
/// match arms.
|
||||
fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
||||
if let Some(ff) = span.get_source_text(cx)
|
||||
if let Some(ff) = span.get_source_range(cx)
|
||||
&& let Some(text) = ff.as_str()
|
||||
{
|
||||
text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")
|
||||
|
@ -1,7 +1,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_self;
|
||||
use clippy_utils::ptr::get_spans;
|
||||
use clippy_utils::source::{snippet, snippet_opt};
|
||||
use clippy_utils::source::{snippet, SpanRangeExt};
|
||||
use clippy_utils::ty::{
|
||||
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
|
||||
};
|
||||
@ -242,8 +242,8 @@ fn check_fn(
|
||||
for (span, suggestion) in clone_spans {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
snippet_opt(cx, span)
|
||||
.map_or("change the call to".into(), |x| format!("change `{x}` to")),
|
||||
span.get_source_text(cx)
|
||||
.map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
|
||||
suggestion,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
@ -267,8 +267,8 @@ fn check_fn(
|
||||
for (span, suggestion) in clone_spans {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
snippet_opt(cx, span)
|
||||
.map_or("change the call to".into(), |x| format!("change `{x}` to")),
|
||||
span.get_source_text(cx)
|
||||
.map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
|
||||
suggestion,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::path_to_local_id;
|
||||
use clippy_utils::source::{snippet, snippet_opt};
|
||||
use clippy_utils::source::{snippet, SpanRangeExt};
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_ast::{LitKind, StrStyle};
|
||||
use rustc_errors::Applicability;
|
||||
@ -74,7 +74,7 @@ fn gen_pathbuf_from(&self, cx: &LateContext<'_>) -> Option<String> {
|
||||
&& let Some(arg) = self.arg
|
||||
&& let ExprKind::Lit(x) = arg.kind
|
||||
&& let LitKind::Str(_, StrStyle::Cooked) = x.node
|
||||
&& let Some(s) = snippet_opt(cx, arg.span)
|
||||
&& let Some(s) = arg.span.get_source_text(cx)
|
||||
{
|
||||
Some(format!(" = PathBuf::from({s});"))
|
||||
} else {
|
||||
@ -84,8 +84,8 @@ fn gen_pathbuf_from(&self, cx: &LateContext<'_>) -> Option<String> {
|
||||
|
||||
fn gen_pathbuf_join(&self, cx: &LateContext<'_>) -> Option<String> {
|
||||
let arg = self.arg?;
|
||||
let arg_str = snippet_opt(cx, arg.span)?;
|
||||
let init_val = snippet_opt(cx, self.init_val.span)?;
|
||||
let arg_str = arg.span.get_source_text(cx)?;
|
||||
let init_val = self.init_val.span.get_source_text(cx)?;
|
||||
Some(format!(" = {init_val}.join({arg_str});"))
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Checks for usage of `&Vec[_]` and `&String`.
|
||||
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::expr_sig;
|
||||
use clippy_utils::visitors::contains_unsafe_block;
|
||||
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
|
||||
@ -243,7 +243,7 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) {
|
||||
.chain(result.replacements.iter().map(|r| {
|
||||
(
|
||||
r.expr_span,
|
||||
format!("{}{}", snippet_opt(cx, r.self_span).unwrap(), r.replacement),
|
||||
format!("{}{}", r.self_span.get_source_text(cx).unwrap(), r.replacement),
|
||||
)
|
||||
}))
|
||||
.collect(),
|
||||
@ -372,7 +372,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
DerefTy::Path => f.write_str("Path"),
|
||||
DerefTy::Slice(hir_ty, ty) => {
|
||||
f.write_char('[')?;
|
||||
match hir_ty.and_then(|s| snippet_opt(self.0, s)) {
|
||||
match hir_ty.and_then(|s| s.get_source_text(self.0)) {
|
||||
Some(s) => f.write_str(&s)?,
|
||||
None => ty.fmt(f)?,
|
||||
}
|
||||
@ -413,6 +413,7 @@ fn display<'a>(&'a self, cx: &'a LateContext<'tcx>) -> DerefTyDisplay<'a, 'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
cx: &'cx LateContext<'tcx>,
|
||||
fn_sig: ty::FnSig<'tcx>,
|
||||
@ -488,8 +489,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
return None;
|
||||
}
|
||||
|
||||
let ty_name = snippet_opt(cx, ty.span()).unwrap_or_else(|| args.type_at(1).to_string());
|
||||
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
PTR_ARG,
|
||||
@ -500,7 +499,10 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
diag.span_suggestion(
|
||||
hir_ty.span,
|
||||
"change this to",
|
||||
format!("&{}{ty_name}", mutability.prefix_str()),
|
||||
match ty.span().get_source_text(cx) {
|
||||
Some(s) => format!("&{}{s}", mutability.prefix_str()),
|
||||
None => format!("&{}{}", mutability.prefix_str(), args.type_at(1)),
|
||||
},
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
@ -120,8 +120,8 @@ fn build_suggestion(
|
||||
receiver_expr: &Expr<'_>,
|
||||
cast_lhs_expr: &Expr<'_>,
|
||||
) -> Option<String> {
|
||||
let receiver = snippet_opt(cx, receiver_expr.span)?;
|
||||
let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?;
|
||||
let receiver = receiver_expr.span.get_source_text(cx)?;
|
||||
let cast_lhs = cast_lhs_expr.span.get_source_text(cx)?;
|
||||
Some(format!("{receiver}.{}({cast_lhs})", method.suggestion()))
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
|
||||
use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
|
||||
use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
|
||||
use rustc_errors::Applicability;
|
||||
@ -208,7 +208,7 @@ fn check_fn(
|
||||
.assert_crate_local()
|
||||
.lint_root;
|
||||
|
||||
if let Some(snip) = snippet_opt(cx, span)
|
||||
if let Some(snip) = span.get_source_text(cx)
|
||||
&& let Some(dot) = snip.rfind('.')
|
||||
{
|
||||
let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap()));
|
||||
|
@ -1,10 +1,10 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
|
||||
use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
|
||||
use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::BytePos;
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -56,11 +56,11 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg = if e.span.from_expansion() {
|
||||
if let Some(macro_source) = snippet_opt(cx, e.span) {
|
||||
if let Some(macro_source) = e.span.get_source_text(cx) {
|
||||
// Remove leading whitespace from the given span
|
||||
// e.g: ` $visitor` turns into `$visitor`
|
||||
let trim_leading_whitespaces = |span| {
|
||||
snippet_opt(cx, span)
|
||||
let trim_leading_whitespaces = |span: Span| {
|
||||
span.get_source_text(cx)
|
||||
.and_then(|snip| {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
snip.find(|c: char| !c.is_whitespace())
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::{def_path_def_ids, path_def_id, paths};
|
||||
use rustc_ast::ast::{LitKind, StrStyle};
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
@ -122,7 +122,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape
|
||||
};
|
||||
|
||||
if let Some((primary, auxiliary, kind)) = parts
|
||||
&& let Some(literal_snippet) = snippet_opt(cx, base)
|
||||
&& let Some(literal_snippet) = base.get_source_text(cx)
|
||||
&& let Some(inner) = literal_snippet.get(offset as usize..)
|
||||
// Only convert to native rustc spans if the parsed regex matches the
|
||||
// source snippet exactly, to ensure the span offsets are correct
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_context};
|
||||
use clippy_utils::source::{snippet_with_context, SpanRangeExt};
|
||||
use clippy_utils::sugg::has_enclosing_paren;
|
||||
use clippy_utils::visitors::{for_each_expr, Descend};
|
||||
use clippy_utils::{
|
||||
@ -250,20 +250,25 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
|
||||
|err| {
|
||||
err.span_label(local.span, "unnecessary `let` binding");
|
||||
|
||||
if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
|
||||
if binary_expr_needs_parentheses(initexpr) {
|
||||
if !has_enclosing_paren(&snippet) {
|
||||
snippet = format!("({snippet})");
|
||||
if let Some(src) = initexpr.span.get_source_text(cx) {
|
||||
let sugg = if binary_expr_needs_parentheses(initexpr) {
|
||||
if has_enclosing_paren(&src) {
|
||||
src.to_owned()
|
||||
} else {
|
||||
format!("({src})")
|
||||
}
|
||||
} else if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
|
||||
if !has_enclosing_paren(&snippet) {
|
||||
snippet = format!("({snippet})");
|
||||
if has_enclosing_paren(&src) {
|
||||
format!("{src} as _")
|
||||
} else {
|
||||
format!("({src}) as _")
|
||||
}
|
||||
snippet.push_str(" as _");
|
||||
}
|
||||
} else {
|
||||
src.to_owned()
|
||||
};
|
||||
err.multipart_suggestion(
|
||||
"return the expression directly",
|
||||
vec![(local.span, String::new()), (retexpr.span, snippet)],
|
||||
vec![(local.span, String::new()), (retexpr.span, sugg)],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
|
@ -2,7 +2,7 @@
|
||||
use clippy_utils::get_trait_def_id;
|
||||
use clippy_utils::higher::VecArgs;
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_ast::{LitIntType, LitKind, UintTy};
|
||||
use rustc_errors::Applicability;
|
||||
@ -92,12 +92,12 @@ fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
|
||||
if matches!(lang_item, LangItem::Range)
|
||||
&& let ty = cx.typeck_results().expr_ty(start.expr)
|
||||
&& let Some(snippet) = snippet_opt(cx, span)
|
||||
&& let Some(snippet) = span.get_source_text(cx)
|
||||
// `is_from_proc_macro` will skip any `vec![]`. Let's not!
|
||||
&& snippet.starts_with(suggested_type.starts_with())
|
||||
&& snippet.ends_with(suggested_type.ends_with())
|
||||
&& let Some(start_snippet) = snippet_opt(cx, start.span)
|
||||
&& let Some(end_snippet) = snippet_opt(cx, end.span)
|
||||
&& let Some(start_snippet) = start.span.get_source_text(cx)
|
||||
&& let Some(end_snippet) = end.span.get_source_text(cx)
|
||||
{
|
||||
let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx.tcx, &["core", "iter", "Step"])
|
||||
&& implements_trait(cx, ty, step_def_id, &[])
|
||||
|
@ -1,7 +1,7 @@
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
|
||||
use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use itertools::Itertools;
|
||||
@ -206,8 +206,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
||||
|
||||
let fixed_trait_snippet = unique_traits
|
||||
.iter()
|
||||
.filter_map(|b| snippet_opt(cx, b.span))
|
||||
.collect::<Vec<_>>()
|
||||
.filter_map(|b| b.span.get_source_text(cx))
|
||||
.join(" + ");
|
||||
|
||||
span_lint_and_sugg(
|
||||
@ -462,9 +461,8 @@ fn rollup_traits(
|
||||
|
||||
let traits = comparable_bounds
|
||||
.iter()
|
||||
.filter_map(|&(_, span)| snippet_opt(cx, span))
|
||||
.collect::<Vec<_>>();
|
||||
let traits = traits.join(" + ");
|
||||
.filter_map(|&(_, span)| span.get_source_text(cx))
|
||||
.join(" + ");
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{position_before_rarrow, snippet_opt};
|
||||
use clippy_utils::source::{position_before_rarrow, SpanRangeExt};
|
||||
use rustc_ast::visit::FnKind;
|
||||
use rustc_ast::{ast, ClosureBinder};
|
||||
use rustc_errors::Applicability;
|
||||
@ -128,15 +128,17 @@ fn is_unit_expr(expr: &ast::Expr) -> bool {
|
||||
|
||||
fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
|
||||
let (ret_span, appl) =
|
||||
snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| {
|
||||
position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
|
||||
(
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
})
|
||||
});
|
||||
span.with_hi(ty.span.hi())
|
||||
.get_source_text(cx)
|
||||
.map_or((ty.span, Applicability::MaybeIncorrect), |src| {
|
||||
position_before_rarrow(&src).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
|
||||
(
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
})
|
||||
});
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNUSED_UNIT,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use rustc_ast::ast::{Item, VisibilityKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
@ -82,9 +82,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if !in_external_macro(cx.sess(), item.span)
|
||||
&& let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind
|
||||
{
|
||||
if **path == kw::SelfLower
|
||||
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
|
||||
{
|
||||
if **path == kw::SelfLower && !is_from_proc_macro(cx, item.vis.span) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_PUB_SELF,
|
||||
@ -104,7 +102,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate)
|
||||
&& !*shorthand
|
||||
&& let [.., last] = &*path.segments
|
||||
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
|
||||
&& !is_from_proc_macro(cx, item.vis.span)
|
||||
{
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
@ -125,7 +123,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
|
||||
if *shorthand
|
||||
&& let [.., last] = &*path.segments
|
||||
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
|
||||
&& !is_from_proc_macro(cx, item.vis.span)
|
||||
{
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
@ -147,6 +145,6 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option<bool> {
|
||||
snippet_opt(cx, span).map(|s| !s.starts_with("pub"))
|
||||
fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> bool {
|
||||
!span.check_source_text(cx, |src| src.starts_with("pub"))
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::is_in_test;
|
||||
use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
|
||||
use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
|
||||
use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt};
|
||||
use rustc_ast::token::LitKind;
|
||||
use rustc_ast::{
|
||||
FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
|
||||
@ -397,7 +397,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma
|
||||
format!("using `{name}!()` with a format string that ends in a single newline"),
|
||||
|diag| {
|
||||
let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
|
||||
let Some(format_snippet) = snippet_opt(cx, format_string_span) else {
|
||||
let Some(format_snippet) = format_string_span.get_source_text(cx) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@ -492,7 +492,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
||||
&& let Some(arg) = format_args.arguments.by_index(index)
|
||||
&& let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind
|
||||
&& !arg.expr.span.from_expansion()
|
||||
&& let Some(value_string) = snippet_opt(cx, arg.expr.span)
|
||||
&& let Some(value_string) = arg.expr.span.get_source_text(cx)
|
||||
{
|
||||
let (replacement, replace_raw) = match lit.kind {
|
||||
LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) {
|
||||
@ -515,7 +515,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else {
|
||||
let Some(format_string_snippet) = format_args.span.get_source_text(cx) else {
|
||||
continue;
|
||||
};
|
||||
let format_string_is_raw = format_string_snippet.starts_with('r');
|
||||
|
@ -687,7 +687,7 @@ fn block(&self, block: &Block<'_>) -> Option<Constant<'tcx>> {
|
||||
if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
|
||||
&& let expr_lo = expr_span.lo()
|
||||
&& expr_lo >= span.lo
|
||||
&& let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx)
|
||||
&& let Some(src) = (span.lo..expr_lo).get_source_range(&self.tcx)
|
||||
&& let Some(src) = src.as_str()
|
||||
{
|
||||
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
|
||||
|
@ -1191,9 +1191,9 @@ fn eq_span_tokens(
|
||||
pred: impl Fn(TokenKind) -> bool,
|
||||
) -> bool {
|
||||
fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
|
||||
if let Some(lsrc) = left.get_source_text(cx)
|
||||
if let Some(lsrc) = left.get_source_range(cx)
|
||||
&& let Some(lsrc) = lsrc.as_str()
|
||||
&& let Some(rsrc) = right.get_source_text(cx)
|
||||
&& let Some(rsrc) = right.get_source_range(cx)
|
||||
&& let Some(rsrc) = rsrc.as_str()
|
||||
{
|
||||
let pred = |t: &(_, _)| pred(t.0);
|
||||
|
@ -16,7 +16,7 @@
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
use std::ops::{Deref, Index, Range};
|
||||
|
||||
pub trait HasSession {
|
||||
fn sess(&self) -> &Session;
|
||||
@ -94,10 +94,16 @@ fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
|
||||
}
|
||||
|
||||
pub trait SpanRangeExt: SpanRange {
|
||||
/// Attempts to get a handle to the source text. Returns `None` if either the span is malformed,
|
||||
/// or the source text is not accessible.
|
||||
fn get_source_text(self, cx: &impl HasSession) -> Option<SourceText> {
|
||||
get_source_range(cx.sess().source_map(), self.into_range()).and_then(SourceText::new)
|
||||
}
|
||||
|
||||
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
|
||||
/// extends through multiple files, or is malformed.
|
||||
fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> {
|
||||
get_source_text(cx.sess().source_map(), self.into_range())
|
||||
fn get_source_range(self, cx: &impl HasSession) -> Option<SourceFileRange> {
|
||||
get_source_range(cx.sess().source_map(), self.into_range())
|
||||
}
|
||||
|
||||
/// Calls the given function with the source text referenced and returns the value. Returns
|
||||
@ -144,21 +150,58 @@ fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
|
||||
fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> {
|
||||
trim_start(cx.sess().source_map(), self.into_range())
|
||||
}
|
||||
|
||||
/// Writes the referenced source text to the given writer. Will return `Err` if the source text
|
||||
/// could not be retrieved.
|
||||
fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result {
|
||||
write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
|
||||
}
|
||||
|
||||
/// Extracts the referenced source text as an owned string.
|
||||
fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> {
|
||||
self.with_source_text(cx, ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
impl<T: SpanRange> SpanRangeExt for T {}
|
||||
|
||||
fn get_source_text(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
|
||||
/// Handle to a range of text in a source file.
|
||||
pub struct SourceText(SourceFileRange);
|
||||
impl SourceText {
|
||||
/// Takes ownership of the source file handle if the source text is accessible.
|
||||
pub fn new(text: SourceFileRange) -> Option<Self> {
|
||||
if text.as_str().is_some() {
|
||||
Some(Self(text))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the source text.
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str().unwrap()
|
||||
}
|
||||
|
||||
/// Converts this into an owned string.
|
||||
pub fn to_owned(&self) -> String {
|
||||
self.as_str().to_owned()
|
||||
}
|
||||
}
|
||||
impl Deref for SourceText {
|
||||
type Target = str;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
impl AsRef<str> for SourceText {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
impl<T> Index<T> for SourceText
|
||||
where
|
||||
str: Index<T>,
|
||||
{
|
||||
type Output = <str as Index<T>>::Output;
|
||||
fn index(&self, idx: T) -> &Self::Output {
|
||||
&self.as_str()[idx]
|
||||
}
|
||||
}
|
||||
impl fmt::Display for SourceText {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_source_range(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
|
||||
let start = sm.lookup_byte_offset(sp.start);
|
||||
let end = sm.lookup_byte_offset(sp.end);
|
||||
if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
|
||||
@ -169,7 +212,7 @@ fn get_source_text(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange
|
||||
}
|
||||
|
||||
fn with_source_text<T>(sm: &SourceMap, sp: Range<BytePos>, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
|
||||
if let Some(src) = get_source_text(sm, sp)
|
||||
if let Some(src) = get_source_range(sm, sp)
|
||||
&& let Some(src) = src.as_str()
|
||||
{
|
||||
Some(f(src))
|
||||
@ -183,7 +226,7 @@ fn with_source_text_and_range<T>(
|
||||
sp: Range<BytePos>,
|
||||
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
|
||||
) -> Option<T> {
|
||||
if let Some(src) = get_source_text(sm, sp)
|
||||
if let Some(src) = get_source_range(sm, sp)
|
||||
&& let Some(text) = &src.sf.src
|
||||
{
|
||||
Some(f(text, src.range))
|
||||
@ -198,7 +241,7 @@ fn map_range(
|
||||
sp: Range<BytePos>,
|
||||
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
|
||||
) -> Option<Range<BytePos>> {
|
||||
if let Some(src) = get_source_text(sm, sp.clone())
|
||||
if let Some(src) = get_source_range(sm, sp.clone())
|
||||
&& let Some(text) = &src.sf.src
|
||||
&& let Some(range) = f(text, src.range.clone())
|
||||
{
|
||||
@ -232,13 +275,6 @@ fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
|
||||
.unwrap_or(sp)
|
||||
}
|
||||
|
||||
fn write_source_text_to(sm: &SourceMap, sp: Range<BytePos>, dst: &mut impl fmt::Write) -> fmt::Result {
|
||||
match with_source_text(sm, sp, |src| dst.write_str(src)) {
|
||||
Some(x) => x,
|
||||
None => Err(fmt::Error),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SourceFileRange {
|
||||
pub sf: Lrc<SourceFile>,
|
||||
pub range: Range<usize>,
|
||||
|
Loading…
Reference in New Issue
Block a user