Skip to content

Commit 3dd5e27

Browse files
author
Jonas Schievink
committed
Shrink diagnostic spans for errors inside macros
1 parent 67f548d commit 3dd5e27

File tree

4 files changed

+59
-15
lines changed

4 files changed

+59
-15
lines changed

crates/hir_expand/src/lib.rs

+53-8
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,53 @@ impl MacroCallKind {
350350
}
351351
}
352352

353+
/// Returns the original file range that best describes the location of this macro call.
354+
///
355+
/// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
356+
/// get the whole `ast::MacroCall`, attribute macros get the attribute's range, and derives
357+
/// get only the specific derive that is being referred to.
358+
pub fn original_call_range(self, db: &dyn db::AstDatabase) -> FileRange {
359+
let mut kind = self;
360+
loop {
361+
match kind.file_id().0 {
362+
HirFileIdRepr::MacroFile(file) => {
363+
kind = db.lookup_intern_macro_call(file.macro_call_id).kind;
364+
}
365+
_ => break,
366+
}
367+
}
368+
369+
// `call_id` is now the outermost macro call, so its location is in a real file.
370+
let file_id = match kind.file_id().0 {
371+
HirFileIdRepr::FileId(it) => it,
372+
HirFileIdRepr::MacroFile(_) => unreachable!("encountered unexpected macro file"),
373+
};
374+
let range = match kind {
375+
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
376+
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
377+
// FIXME: should be the range of the macro name, not the whole derive
378+
ast_id
379+
.to_node(db)
380+
.doc_comments_and_attrs()
381+
.nth(derive_attr_index as usize)
382+
.expect("missing derive")
383+
.expect_right("derive is a doc comment?")
384+
.syntax()
385+
.text_range()
386+
}
387+
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => ast_id
388+
.to_node(db)
389+
.doc_comments_and_attrs()
390+
.nth(invoc_attr_index as usize)
391+
.expect("missing attribute")
392+
.expect_right("attribute macro is a doc comment?")
393+
.syntax()
394+
.text_range(),
395+
};
396+
397+
FileRange { range, file_id }
398+
}
399+
353400
fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> {
354401
match self {
355402
MacroCallKind::FnLike { ast_id, .. } => {
@@ -623,15 +670,13 @@ impl<'a> InFile<&'a SyntaxNode> {
623670
}
624671

625672
// Fall back to whole macro call.
626-
let mut node = self.cloned();
627-
while let Some(call_node) = node.file_id.call_node(db) {
628-
node = call_node;
673+
match self.file_id.0 {
674+
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
675+
HirFileIdRepr::MacroFile(mac_file) => {
676+
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
677+
loc.kind.original_call_range(db)
678+
}
629679
}
630-
631-
let orig_file = node.file_id.original_file(db);
632-
assert_eq!(node.file_id, orig_file.into());
633-
634-
FileRange { file_id: orig_file, range: node.value.text_range() }
635680
}
636681

637682
/// Attempts to map the syntax node back up its macro calls.

crates/proc_macro_srv/src/abis/abi_1_56/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl Abi {
5151
&proc_macro::bridge::server::SameThread,
5252
rustc_server::Rustc::default(),
5353
parsed_body,
54-
false,
54+
true,
5555
);
5656
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
5757
}
@@ -62,7 +62,7 @@ impl Abi {
6262
&proc_macro::bridge::server::SameThread,
6363
rustc_server::Rustc::default(),
6464
parsed_body,
65-
false,
65+
true,
6666
);
6767
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
6868
}
@@ -74,7 +74,7 @@ impl Abi {
7474
rustc_server::Rustc::default(),
7575
parsed_attributes,
7676
parsed_body,
77-
false,
77+
true,
7878
);
7979
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
8080
}

crates/proc_macro_srv/src/abis/abi_1_58/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl Abi {
5151
&proc_macro::bridge::server::SameThread,
5252
rustc_server::Rustc::default(),
5353
parsed_body,
54-
false,
54+
true,
5555
);
5656
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
5757
}
@@ -62,7 +62,7 @@ impl Abi {
6262
&proc_macro::bridge::server::SameThread,
6363
rustc_server::Rustc::default(),
6464
parsed_body,
65-
false,
65+
true,
6666
);
6767
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
6868
}
@@ -74,7 +74,7 @@ impl Abi {
7474
rustc_server::Rustc::default(),
7575
parsed_attributes,
7676
parsed_body,
77-
false,
77+
true,
7878
);
7979
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
8080
}

crates/syntax/src/ast/node_ext.rs

-1
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ impl ast::HasLoopBody for ast::ForExpr {
772772
}
773773

774774
impl ast::HasAttrs for ast::AnyHasDocComments {}
775-
impl ast::HasDocComments for ast::Item {}
776775

777776
impl From<ast::Adt> for ast::Item {
778777
fn from(it: ast::Adt) -> Self {

0 commit comments

Comments
 (0)