From 67f548d8e9f9034d94e82430867a9f65438bbeda Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 8 Jan 2022 15:01:26 +0100 Subject: [PATCH 1/2] Allow doc comments on all `Item`s --- crates/syntax/src/ast/generated/nodes.rs | 13 +++++++++---- crates/syntax/src/tests/sourcegen_ast.rs | 4 +++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 8e55afb949..09c5af210f 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -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 { support::child(&self.syntax) } pub fn excl_token(&self) -> Option { 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 { support::child(&self.syntax) } pub fn extern_item_list(&self) -> Option { 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 { support::token(&self.syntax, T![extern]) } pub fn crate_token(&self) -> Option { 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, } } diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs index ac928402f3..4a608da9ff 100644 --- a/crates/syntax/src/tests/sourcegen_ast.rs +++ b/crates/syntax/src/tests/sourcegen_ast.rs @@ -793,9 +793,11 @@ fn extract_struct_traits(ast: &mut AstSrc) { "Const", "TypeAlias", "Impl", + "ExternBlock", + "ExternCrate", + "MacroCall", "MacroRules", "MacroDef", - "Macro", "Use", ]; From 3dd5e273b6a86adb13a1b9d8677ff4116cbdb679 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 8 Jan 2022 15:38:50 +0100 Subject: [PATCH 2/2] Shrink diagnostic spans for errors inside macros --- crates/hir_expand/src/lib.rs | 61 ++++++++++++++++--- .../proc_macro_srv/src/abis/abi_1_56/mod.rs | 6 +- .../proc_macro_srv/src/abis/abi_1_58/mod.rs | 6 +- crates/syntax/src/ast/node_ext.rs | 1 - 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 5f190b8727..5e49d3f6af 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs @@ -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 { 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. diff --git a/crates/proc_macro_srv/src/abis/abi_1_56/mod.rs b/crates/proc_macro_srv/src/abis/abi_1_56/mod.rs index 96b71d3f21..ee1c2d4553 100644 --- a/crates/proc_macro_srv/src/abis/abi_1_56/mod.rs +++ b/crates/proc_macro_srv/src/abis/abi_1_56/mod.rs @@ -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); } diff --git a/crates/proc_macro_srv/src/abis/abi_1_58/mod.rs b/crates/proc_macro_srv/src/abis/abi_1_58/mod.rs index 4421382006..dd3fd8b642 100644 --- a/crates/proc_macro_srv/src/abis/abi_1_58/mod.rs +++ b/crates/proc_macro_srv/src/abis/abi_1_58/mod.rs @@ -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); } diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 470e9a04b3..705aa5edac 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -772,7 +772,6 @@ impl ast::HasLoopBody for ast::ForExpr { } impl ast::HasAttrs for ast::AnyHasDocComments {} -impl ast::HasDocComments for ast::Item {} impl From for ast::Item { fn from(it: ast::Adt) -> Self {