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 From 8afb445357f621eb5b4aada6041eb2a1afd41ee6 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 24 Mar 2020 03:45:52 +0800 Subject: Rename to CustomDerive --- crates/ra_hir_def/src/nameres/collector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 76be71a30..1dcf5a309 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -892,7 +892,7 @@ impl ModCollector<'_, '_> { let macro_id = MacroDefId { ast_id: None, krate: Some(krate), - kind: MacroDefKind::ProcMacro(expander), + kind: MacroDefKind::CustomDerive(expander), }; self.def_collector.define_proc_macro(name.clone(), macro_id); -- cgit v1.2.3 From 2adc9a8d5f8f7686a125a478330c67a2d46fba98 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 25 Mar 2020 20:14:22 +0800 Subject: Remove collect proc_macro definitions --- crates/ra_hir_def/src/nameres/collector.rs | 46 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 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 1dcf5a309..9c125f32f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -65,6 +65,9 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), cfg_options, + + // FIXME: pass proc-macro from crate-graph + proc_macros: Default::default(), }; collector.collect(); collector.finish() @@ -123,6 +126,7 @@ struct DefCollector<'a> { unexpanded_attribute_macros: Vec, mod_dirs: FxHashMap, cfg_options: &'a CfgOptions, + proc_macros: Vec<(Name, ProcMacroExpander)>, } impl DefCollector<'_> { @@ -178,6 +182,24 @@ impl DefCollector<'_> { for directive in unresolved_imports { self.record_resolved_import(&directive) } + + // Record proc-macros + self.collect_proc_macro(); + } + + fn collect_proc_macro(&mut self) { + let proc_macros = std::mem::take(&mut self.proc_macros); + for (name, expander) in proc_macros { + let krate = self.def_map.krate; + + let macro_id = MacroDefId { + ast_id: None, + krate: Some(krate), + kind: MacroDefKind::CustomDerive(expander), + }; + + self.define_proc_macro(name.clone(), macro_id); + } } /// Define a macro with `macro_rules`. @@ -801,7 +823,6 @@ impl ModCollector<'_, '_> { // 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); @@ -878,28 +899,6 @@ 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::CustomDerive(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()); @@ -1001,6 +1000,7 @@ mod tests { unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), cfg_options: &CfgOptions::default(), + proc_macros: Default::default(), }; collector.collect(); collector.def_map -- cgit v1.2.3