diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 68f3e3ae61f..1c52ed57955 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1383,27 +1383,19 @@ impl Function { db.function_data(self.id).has_body() } - pub fn as_proc_macro(self, _db: &dyn HirDatabase) -> Option { - // let function_data = db.function_data(self.id); - // let attrs = &function_data.attrs; - // if !(attrs.is_proc_macro() - // || attrs.is_proc_macro_attribute() - // || attrs.is_proc_macro_derive()) - // { - // return None; - // } - // let loc = self.id.lookup(db.upcast()); - // let krate = loc.krate(db); - // let def_map = db.crate_def_map(krate.into()); - // let ast_id = - // InFile::new(loc.id.file_id(), loc.id.item_tree(db.upcast())[loc.id.value].ast_id); - - // let mut exported_proc_macros = def_map.exported_proc_macros(); - // exported_proc_macros - // .find(|&(id, _)| matches!(id.kind, MacroDefKind::ProcMacro(_, _, id) if id == ast_id)) - // .map(|(id, _)| Macro { id }) - // FIXME - None + pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option { + let function_data = db.function_data(self.id); + let attrs = &function_data.attrs; + // FIXME: Store this in FunctionData flags? + if !(attrs.is_proc_macro() + || attrs.is_proc_macro_attribute() + || attrs.is_proc_macro_derive()) + { + return None; + } + let loc = self.id.lookup(db.upcast()); + let def_map = db.crate_def_map(loc.krate(db).into()); + def_map.fn_as_proc_macro(loc.id).map(|id| Macro { id: id.into() }) } /// A textual representation of the HIR of this function for debugging purposes. diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 5cef7ecb374..bb3a34a7c1e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -332,6 +332,7 @@ impl MacroRulesData { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ProcMacroData { pub name: Name, + // FIXME: Record deriver helper here? } impl ProcMacroData { @@ -343,7 +344,17 @@ impl ProcMacroData { let item_tree = loc.id.item_tree(db); let makro = &item_tree[loc.id.value]; - Arc::new(ProcMacroData { name: makro.name.clone() }) + let name = if let Some(def) = item_tree + .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) + .parse_proc_macro_decl(&makro.name) + { + def.name + } else { + // eeeh... + stdx::never!("proc macro declaration is not a proc macro"); + makro.name.clone() + }; + Arc::new(ProcMacroData { name }) } } diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index cb4c5a9f552..279784952d3 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -70,12 +70,12 @@ use syntax::{ast, SmolStr}; use crate::{ db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, - item_tree::TreeId, + item_tree::{self, ItemTreeId, TreeId}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, visibility::Visibility, - AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, + AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, ProcMacroId, }; /// Contains the results of (early) name resolution. @@ -102,6 +102,7 @@ pub struct DefMap { /// Side table for resolving derive helpers. exported_derives: FxHashMap>, + fn_proc_macro_mapping: FxHashMap, ProcMacroId>, /// Custom attributes registered with `#![register_attr]`. registered_attrs: Vec, @@ -271,6 +272,7 @@ impl DefMap { recursion_limit: None, extern_prelude: FxHashMap::default(), exported_derives: FxHashMap::default(), + fn_proc_macro_mapping: FxHashMap::default(), prelude: None, root, modules, @@ -300,6 +302,11 @@ impl DefMap { self.root } + // FIXME: This is an odd interface.... + pub fn fn_as_proc_macro(&self, id: ItemTreeId) -> Option { + self.fn_proc_macro_mapping.get(&id).copied() + } + pub(crate) fn krate(&self) -> CrateId { self.krate } @@ -453,6 +460,7 @@ impl DefMap { modules, registered_attrs, registered_tools, + fn_proc_macro_mapping, block: _, edition: _, recursion_limit: _, @@ -467,6 +475,7 @@ impl DefMap { modules.shrink_to_fit(); registered_attrs.shrink_to_fit(); registered_tools.shrink_to_fit(); + fn_proc_macro_mapping.shrink_to_fit(); for (_, module) in modules.iter_mut() { module.children.shrink_to_fit(); module.scope.shrink_to_fit(); diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 59ed617888c..a8928d07e79 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -570,6 +570,7 @@ impl DefCollector<'_> { .exported_derives .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers); } + self.def_map.fn_proc_macro_mapping.insert(id, proc_macro_id); } /// Define a macro with `macro_rules`. diff --git a/crates/hir_def/src/nameres/proc_macro.rs b/crates/hir_def/src/nameres/proc_macro.rs index 920df7cec20..5089ef2d817 100644 --- a/crates/hir_def/src/nameres/proc_macro.rs +++ b/crates/hir_def/src/nameres/proc_macro.rs @@ -6,13 +6,13 @@ use tt::{Leaf, TokenTree}; use crate::attr::Attrs; #[derive(Debug, PartialEq, Eq)] -pub(super) struct ProcMacroDef { - pub(super) name: Name, - pub(super) kind: ProcMacroKind, +pub struct ProcMacroDef { + pub name: Name, + pub kind: ProcMacroKind, } #[derive(Debug, PartialEq, Eq)] -pub(super) enum ProcMacroKind { +pub enum ProcMacroKind { CustomDerive { helpers: Box<[Name]> }, FnLike, Attr, @@ -30,7 +30,7 @@ impl ProcMacroKind { impl Attrs { #[rustfmt::skip] - pub(super) fn parse_proc_macro_decl(&self, func_name: &Name) -> Option { + pub fn parse_proc_macro_decl(&self, func_name: &Name) -> Option { if self.is_proc_macro() { Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::FnLike }) } else if self.is_proc_macro_attribute() { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e7fad48080d..2ec7802394f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -4151,7 +4151,7 @@ struct Foo; *Copy* ```rust - test + test::foo ``` ```rust