From 34dc8d25c1e461cc311d6d4404f74502513cd3ae Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 18 Mar 2020 17:47:59 +0800 Subject: Add basic custom derive lowering --- crates/ra_hir_def/src/nameres/collector.rs | 60 ++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir_def/src/nameres') diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 5b292c250..76be71a30 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -7,6 +7,7 @@ use hir_expand::{ builtin_derive::find_builtin_derive, builtin_macro::find_builtin_macro, name::{name, AsName, Name}, + proc_macro::ProcMacroExpander, HirFileId, MacroCallId, MacroDefId, MacroDefKind, }; use ra_cfg::CfgOptions; @@ -238,6 +239,18 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); } + /// Define a proc macro + /// + /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. + /// And unconditionally exported. + fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { + self.update( + self.def_map.root, + &[(name, PerNs::macros(macro_, Visibility::Public))], + Visibility::Public, + ); + } + /// Import macros from `#[macro_use] extern crate`. fn import_macros_from_extern_crate( &mut self, @@ -537,8 +550,9 @@ impl DefCollector<'_> { true }); attribute_macros.retain(|directive| { - if let Some(call_id) = - directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) + if let Some(call_id) = directive + .ast_id + .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path)) { resolved.push((directive.module_id, call_id, 0)); res = ReachedFixedPoint::No; @@ -562,9 +576,11 @@ impl DefCollector<'_> { res } - fn resolve_attribute_macro(&self, path: &ModPath) -> Option { - // FIXME this is currently super hacky, just enough to support the - // built-in derives + fn resolve_attribute_macro( + &self, + directive: &DeriveDirective, + path: &ModPath, + ) -> Option { if let Some(name) = path.as_ident() { // FIXME this should actually be handled with the normal name // resolution; the std lib defines built-in stubs for the derives, @@ -573,7 +589,15 @@ impl DefCollector<'_> { return Some(def_id); } } - None + let resolved_res = self.def_map.resolve_path_fp_with_macro( + self.db, + ResolveMode::Other, + directive.module_id, + &path, + BuiltinShadowMode::Module, + ); + + resolved_res.resolved_def.take_macros() } fn collect_macro_expansion( @@ -776,8 +800,8 @@ impl ModCollector<'_, '_> { // FIXME: check attrs to see if this is an attribute macro invocation; // in which case we don't add the invocation, just a single attribute // macro invocation - self.collect_derives(attrs, def); + self.collect_proc_macro(attrs); let name = def.name.clone(); let container = ContainerId::ModuleId(module); @@ -854,6 +878,28 @@ impl ModCollector<'_, '_> { } } + fn collect_proc_macro(&mut self, attrs: &Attrs) { + if let Some(derive_subtree) = attrs.by_key("proc_macro_derive").tt_values().next() { + if let Some(tt) = derive_subtree.token_trees.get(0) { + let ident = match &tt { + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, + _ => return, // anything else would be an error (which we currently ignore) + }; + let name = ident.as_name(); + let krate = self.def_collector.def_map.krate; + let expander = ProcMacroExpander::new(krate); + + let macro_id = MacroDefId { + ast_id: None, + krate: Some(krate), + kind: MacroDefKind::ProcMacro(expander), + }; + + self.def_collector.define_proc_macro(name.clone(), macro_id); + } + } + } + fn collect_macro(&mut self, mac: &raw::MacroData) { let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); -- cgit v1.2.3