Skip to content

Commit 0f8c96c

Browse files
bors[bot]Jonas Schievink
and
Jonas Schievink
authored
Merge #11238
11238: fix: shrink the span of errors from attribute macros and derives r=jonas-schievink a=jonas-schievink Some procedural macros tend to get very large invocations, for example RTIC's, leading to issues like rtic-rs/rtic#582, where almost the entire screen is underlined while editing incomplete code in the macro. This PR shrinks the spans of errors from attribute macros and derives to point only at the attribute, which also matches rustc more closely. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents ca8bd3e + 3dd5e27 commit 0f8c96c

File tree

6 files changed

+71
-20
lines changed

6 files changed

+71
-20
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/generated/nodes.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ pub struct MacroCall {
162162
pub(crate) syntax: SyntaxNode,
163163
}
164164
impl ast::HasAttrs for MacroCall {}
165+
impl ast::HasDocComments for MacroCall {}
165166
impl MacroCall {
166167
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
167168
pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
@@ -259,6 +260,7 @@ pub struct ExternBlock {
259260
pub(crate) syntax: SyntaxNode,
260261
}
261262
impl ast::HasAttrs for ExternBlock {}
263+
impl ast::HasDocComments for ExternBlock {}
262264
impl ExternBlock {
263265
pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
264266
pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
@@ -270,6 +272,7 @@ pub struct ExternCrate {
270272
}
271273
impl ast::HasAttrs for ExternCrate {}
272274
impl ast::HasVisibility for ExternCrate {}
275+
impl ast::HasDocComments for ExternCrate {}
273276
impl ExternCrate {
274277
pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
275278
pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
@@ -1543,6 +1546,7 @@ pub enum Item {
15431546
Use(Use),
15441547
}
15451548
impl ast::HasAttrs for Item {}
1549+
impl ast::HasDocComments for Item {}
15461550

15471551
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15481552
pub enum Stmt {
@@ -1597,6 +1601,7 @@ pub enum AssocItem {
15971601
TypeAlias(TypeAlias),
15981602
}
15991603
impl ast::HasAttrs for AssocItem {}
1604+
impl ast::HasDocComments for AssocItem {}
16001605

16011606
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16021607
pub enum ExternItem {
@@ -1606,6 +1611,7 @@ pub enum ExternItem {
16061611
TypeAlias(TypeAlias),
16071612
}
16081613
impl ast::HasAttrs for ExternItem {}
1614+
impl ast::HasDocComments for ExternItem {}
16091615

16101616
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16111617
pub enum GenericParam {
@@ -3902,10 +3908,9 @@ impl AnyHasDocComments {
39023908
impl AstNode for AnyHasDocComments {
39033909
fn can_cast(kind: SyntaxKind) -> bool {
39043910
match kind {
3905-
SOURCE_FILE | CONST | ENUM | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC
3906-
| STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => {
3907-
true
3908-
}
3911+
MACRO_CALL | SOURCE_FILE | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL
3912+
| MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION
3913+
| USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => true,
39093914
_ => false,
39103915
}
39113916
}

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 {

crates/syntax/src/tests/sourcegen_ast.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -793,9 +793,11 @@ fn extract_struct_traits(ast: &mut AstSrc) {
793793
"Const",
794794
"TypeAlias",
795795
"Impl",
796+
"ExternBlock",
797+
"ExternCrate",
798+
"MacroCall",
796799
"MacroRules",
797800
"MacroDef",
798-
"Macro",
799801
"Use",
800802
];
801803

0 commit comments

Comments
 (0)