fix: Improve diagnostic ranges for macro_calls!

We used to point to the entire macro call including its token tree if we couldn't upmap the diagnostic to the input
This generally makes things very noisy as the entire macro call will turn red on errors.
Instead, we now macro the path and `!` (bang) token as the error source range which is a lot nicer on the eyes.
This commit is contained in:
Lukas Wirth 2025-07-03 13:32:46 +02:00
parent 661e7d2ac2
commit 2480a42ff4
12 changed files with 71 additions and 49 deletions

View file

@ -242,8 +242,8 @@ macro_rules! outer {
fn f() {
outer!();
} //^^^^^^^^ error: leftover tokens
//^^^^^^^^ error: Syntax Error in Expansion: expected expression
} //^^^^^^ error: leftover tokens
//^^^^^^ error: Syntax Error in Expansion: expected expression
"#,
)
}

View file

@ -66,7 +66,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let current_module =
ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module());
let range = InFile::new(d.file, d.field_list_parent.text_range())
.original_node_file_range_rooted(ctx.sema.db);
.original_node_file_range_rooted_opt(ctx.sema.db)?;
let build_text_edit = |new_syntax: &SyntaxNode, old_syntax| {
let edit = {

View file

@ -77,6 +77,7 @@ fn quickfix_for_redundant_assoc_item(
redundant_item_def: String,
range: TextRange,
) -> Option<Vec<Assist>> {
let file_id = d.file_id.file_id()?;
let add_assoc_item_def = |builder: &mut SourceChangeBuilder| -> Option<()> {
let db = ctx.sema.db;
let root = db.parse_or_expand(d.file_id);
@ -90,12 +91,14 @@ fn quickfix_for_redundant_assoc_item(
let trait_def = d.trait_.source(db)?.value;
let l_curly = trait_def.assoc_item_list()?.l_curly_token()?.text_range();
let where_to_insert =
hir::InFile::new(d.file_id, l_curly).original_node_file_range_rooted(db).range;
hir::InFile::new(d.file_id, l_curly).original_node_file_range_rooted_opt(db)?;
if where_to_insert.file_id != file_id {
return None;
}
builder.insert(where_to_insert.end(), redundant_item_def);
builder.insert(where_to_insert.range.end(), redundant_item_def);
Some(())
};
let file_id = d.file_id.file_id()?;
let mut source_change_builder = SourceChangeBuilder::new(file_id.file_id(ctx.sema.db));
add_assoc_item_def(&mut source_change_builder)?;

View file

@ -120,8 +120,7 @@ fn assoc_func_fix(
let call = ast::MethodCallExpr::cast(expr.syntax().clone())?;
let range = InFile::new(expr_ptr.file_id, call.syntax().text_range())
.original_node_file_range_rooted(db)
.range;
.original_node_file_range_rooted_opt(db)?;
let receiver = call.receiver()?;
let receiver_type = &ctx.sema.type_of_expr(&receiver)?.original;
@ -174,18 +173,16 @@ fn assoc_func_fix(
let assoc_func_call_expr_string = make::expr_call(assoc_func_path, args).to_string();
let file_id = ctx.sema.original_range_opt(call.receiver()?.syntax())?.file_id;
Some(Assist {
id: AssistId::quick_fix("method_call_to_assoc_func_call_fix"),
label: Label::new(format!(
"Use associated func call instead: `{assoc_func_call_expr_string}`"
)),
group: None,
target: range,
target: range.range,
source_change: Some(SourceChange::from_text_edit(
file_id.file_id(ctx.sema.db),
TextEdit::replace(range, assoc_func_call_expr_string),
range.file_id.file_id(ctx.sema.db),
TextEdit::replace(range.range, assoc_func_call_expr_string),
)),
command: None,
})
@ -300,7 +297,7 @@ macro_rules! m {
}
fn main() {
m!(());
// ^^^^^^ error: no method `foo` on type `()`
// ^^ error: no method `foo` on type `()`
}
"#,
);