mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
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 https://github.com/rtic-rs/cortex-m-rtic/issues/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 <jonas.schievink@ferrous-systems.com>
This commit is contained in:
commit
0f8c96c926
@ -350,6 +350,53 @@ impl MacroCallKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the original file range that best describes the location of this macro call.
|
||||
///
|
||||
/// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
|
||||
/// get the whole `ast::MacroCall`, attribute macros get the attribute's range, and derives
|
||||
/// get only the specific derive that is being referred to.
|
||||
pub fn original_call_range(self, db: &dyn db::AstDatabase) -> FileRange {
|
||||
let mut kind = self;
|
||||
loop {
|
||||
match kind.file_id().0 {
|
||||
HirFileIdRepr::MacroFile(file) => {
|
||||
kind = db.lookup_intern_macro_call(file.macro_call_id).kind;
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
// `call_id` is now the outermost macro call, so its location is in a real file.
|
||||
let file_id = match kind.file_id().0 {
|
||||
HirFileIdRepr::FileId(it) => it,
|
||||
HirFileIdRepr::MacroFile(_) => unreachable!("encountered unexpected macro file"),
|
||||
};
|
||||
let range = match kind {
|
||||
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
|
||||
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
|
||||
// FIXME: should be the range of the macro name, not the whole derive
|
||||
ast_id
|
||||
.to_node(db)
|
||||
.doc_comments_and_attrs()
|
||||
.nth(derive_attr_index as usize)
|
||||
.expect("missing derive")
|
||||
.expect_right("derive is a doc comment?")
|
||||
.syntax()
|
||||
.text_range()
|
||||
}
|
||||
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => ast_id
|
||||
.to_node(db)
|
||||
.doc_comments_and_attrs()
|
||||
.nth(invoc_attr_index as usize)
|
||||
.expect("missing attribute")
|
||||
.expect_right("attribute macro is a doc comment?")
|
||||
.syntax()
|
||||
.text_range(),
|
||||
};
|
||||
|
||||
FileRange { range, file_id }
|
||||
}
|
||||
|
||||
fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> {
|
||||
match self {
|
||||
MacroCallKind::FnLike { ast_id, .. } => {
|
||||
@ -623,15 +670,13 @@ impl<'a> InFile<&'a SyntaxNode> {
|
||||
}
|
||||
|
||||
// Fall back to whole macro call.
|
||||
let mut node = self.cloned();
|
||||
while let Some(call_node) = node.file_id.call_node(db) {
|
||||
node = call_node;
|
||||
match self.file_id.0 {
|
||||
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
|
||||
HirFileIdRepr::MacroFile(mac_file) => {
|
||||
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
|
||||
loc.kind.original_call_range(db)
|
||||
}
|
||||
}
|
||||
|
||||
let orig_file = node.file_id.original_file(db);
|
||||
assert_eq!(node.file_id, orig_file.into());
|
||||
|
||||
FileRange { file_id: orig_file, range: node.value.text_range() }
|
||||
}
|
||||
|
||||
/// Attempts to map the syntax node back up its macro calls.
|
||||
|
@ -51,7 +51,7 @@ impl Abi {
|
||||
&proc_macro::bridge::server::SameThread,
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
@ -62,7 +62,7 @@ impl Abi {
|
||||
&proc_macro::bridge::server::SameThread,
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
@ -74,7 +74,7 @@ impl Abi {
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_attributes,
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ impl Abi {
|
||||
&proc_macro::bridge::server::SameThread,
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
@ -62,7 +62,7 @@ impl Abi {
|
||||
&proc_macro::bridge::server::SameThread,
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
@ -74,7 +74,7 @@ impl Abi {
|
||||
rustc_server::Rustc::default(),
|
||||
parsed_attributes,
|
||||
parsed_body,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ pub struct MacroCall {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl ast::HasAttrs for MacroCall {}
|
||||
impl ast::HasDocComments for MacroCall {}
|
||||
impl MacroCall {
|
||||
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
|
||||
pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
|
||||
@ -259,6 +260,7 @@ pub struct ExternBlock {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl ast::HasAttrs for ExternBlock {}
|
||||
impl ast::HasDocComments for ExternBlock {}
|
||||
impl ExternBlock {
|
||||
pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
|
||||
pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
|
||||
@ -270,6 +272,7 @@ pub struct ExternCrate {
|
||||
}
|
||||
impl ast::HasAttrs for ExternCrate {}
|
||||
impl ast::HasVisibility for ExternCrate {}
|
||||
impl ast::HasDocComments for ExternCrate {}
|
||||
impl ExternCrate {
|
||||
pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
|
||||
pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
|
||||
@ -1543,6 +1546,7 @@ pub enum Item {
|
||||
Use(Use),
|
||||
}
|
||||
impl ast::HasAttrs for Item {}
|
||||
impl ast::HasDocComments for Item {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Stmt {
|
||||
@ -1597,6 +1601,7 @@ pub enum AssocItem {
|
||||
TypeAlias(TypeAlias),
|
||||
}
|
||||
impl ast::HasAttrs for AssocItem {}
|
||||
impl ast::HasDocComments for AssocItem {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ExternItem {
|
||||
@ -1606,6 +1611,7 @@ pub enum ExternItem {
|
||||
TypeAlias(TypeAlias),
|
||||
}
|
||||
impl ast::HasAttrs for ExternItem {}
|
||||
impl ast::HasDocComments for ExternItem {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum GenericParam {
|
||||
@ -3902,10 +3908,9 @@ impl AnyHasDocComments {
|
||||
impl AstNode for AnyHasDocComments {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
SOURCE_FILE | CONST | ENUM | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC
|
||||
| STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => {
|
||||
true
|
||||
}
|
||||
MACRO_CALL | SOURCE_FILE | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL
|
||||
| MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION
|
||||
| USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -772,7 +772,6 @@ impl ast::HasLoopBody for ast::ForExpr {
|
||||
}
|
||||
|
||||
impl ast::HasAttrs for ast::AnyHasDocComments {}
|
||||
impl ast::HasDocComments for ast::Item {}
|
||||
|
||||
impl From<ast::Adt> for ast::Item {
|
||||
fn from(it: ast::Adt) -> Self {
|
||||
|
@ -793,9 +793,11 @@ fn extract_struct_traits(ast: &mut AstSrc) {
|
||||
"Const",
|
||||
"TypeAlias",
|
||||
"Impl",
|
||||
"ExternBlock",
|
||||
"ExternCrate",
|
||||
"MacroCall",
|
||||
"MacroRules",
|
||||
"MacroDef",
|
||||
"Macro",
|
||||
"Use",
|
||||
];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user