diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 5b292c250..9c125f32f 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::{ | |||
7 | builtin_derive::find_builtin_derive, | 7 | builtin_derive::find_builtin_derive, |
8 | builtin_macro::find_builtin_macro, | 8 | builtin_macro::find_builtin_macro, |
9 | name::{name, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | proc_macro::ProcMacroExpander, | ||
10 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 11 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
11 | }; | 12 | }; |
12 | use ra_cfg::CfgOptions; | 13 | use ra_cfg::CfgOptions; |
@@ -64,6 +65,9 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
64 | unexpanded_attribute_macros: Vec::new(), | 65 | unexpanded_attribute_macros: Vec::new(), |
65 | mod_dirs: FxHashMap::default(), | 66 | mod_dirs: FxHashMap::default(), |
66 | cfg_options, | 67 | cfg_options, |
68 | |||
69 | // FIXME: pass proc-macro from crate-graph | ||
70 | proc_macros: Default::default(), | ||
67 | }; | 71 | }; |
68 | collector.collect(); | 72 | collector.collect(); |
69 | collector.finish() | 73 | collector.finish() |
@@ -122,6 +126,7 @@ struct DefCollector<'a> { | |||
122 | unexpanded_attribute_macros: Vec<DeriveDirective>, | 126 | unexpanded_attribute_macros: Vec<DeriveDirective>, |
123 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 127 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
124 | cfg_options: &'a CfgOptions, | 128 | cfg_options: &'a CfgOptions, |
129 | proc_macros: Vec<(Name, ProcMacroExpander)>, | ||
125 | } | 130 | } |
126 | 131 | ||
127 | impl DefCollector<'_> { | 132 | impl DefCollector<'_> { |
@@ -177,6 +182,24 @@ impl DefCollector<'_> { | |||
177 | for directive in unresolved_imports { | 182 | for directive in unresolved_imports { |
178 | self.record_resolved_import(&directive) | 183 | self.record_resolved_import(&directive) |
179 | } | 184 | } |
185 | |||
186 | // Record proc-macros | ||
187 | self.collect_proc_macro(); | ||
188 | } | ||
189 | |||
190 | fn collect_proc_macro(&mut self) { | ||
191 | let proc_macros = std::mem::take(&mut self.proc_macros); | ||
192 | for (name, expander) in proc_macros { | ||
193 | let krate = self.def_map.krate; | ||
194 | |||
195 | let macro_id = MacroDefId { | ||
196 | ast_id: None, | ||
197 | krate: Some(krate), | ||
198 | kind: MacroDefKind::CustomDerive(expander), | ||
199 | }; | ||
200 | |||
201 | self.define_proc_macro(name.clone(), macro_id); | ||
202 | } | ||
180 | } | 203 | } |
181 | 204 | ||
182 | /// Define a macro with `macro_rules`. | 205 | /// Define a macro with `macro_rules`. |
@@ -238,6 +261,18 @@ impl DefCollector<'_> { | |||
238 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); | 261 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); |
239 | } | 262 | } |
240 | 263 | ||
264 | /// Define a proc macro | ||
265 | /// | ||
266 | /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. | ||
267 | /// And unconditionally exported. | ||
268 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | ||
269 | self.update( | ||
270 | self.def_map.root, | ||
271 | &[(name, PerNs::macros(macro_, Visibility::Public))], | ||
272 | Visibility::Public, | ||
273 | ); | ||
274 | } | ||
275 | |||
241 | /// Import macros from `#[macro_use] extern crate`. | 276 | /// Import macros from `#[macro_use] extern crate`. |
242 | fn import_macros_from_extern_crate( | 277 | fn import_macros_from_extern_crate( |
243 | &mut self, | 278 | &mut self, |
@@ -537,8 +572,9 @@ impl DefCollector<'_> { | |||
537 | true | 572 | true |
538 | }); | 573 | }); |
539 | attribute_macros.retain(|directive| { | 574 | attribute_macros.retain(|directive| { |
540 | if let Some(call_id) = | 575 | if let Some(call_id) = directive |
541 | directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) | 576 | .ast_id |
577 | .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path)) | ||
542 | { | 578 | { |
543 | resolved.push((directive.module_id, call_id, 0)); | 579 | resolved.push((directive.module_id, call_id, 0)); |
544 | res = ReachedFixedPoint::No; | 580 | res = ReachedFixedPoint::No; |
@@ -562,9 +598,11 @@ impl DefCollector<'_> { | |||
562 | res | 598 | res |
563 | } | 599 | } |
564 | 600 | ||
565 | fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> { | 601 | fn resolve_attribute_macro( |
566 | // FIXME this is currently super hacky, just enough to support the | 602 | &self, |
567 | // built-in derives | 603 | directive: &DeriveDirective, |
604 | path: &ModPath, | ||
605 | ) -> Option<MacroDefId> { | ||
568 | if let Some(name) = path.as_ident() { | 606 | if let Some(name) = path.as_ident() { |
569 | // FIXME this should actually be handled with the normal name | 607 | // FIXME this should actually be handled with the normal name |
570 | // resolution; the std lib defines built-in stubs for the derives, | 608 | // resolution; the std lib defines built-in stubs for the derives, |
@@ -573,7 +611,15 @@ impl DefCollector<'_> { | |||
573 | return Some(def_id); | 611 | return Some(def_id); |
574 | } | 612 | } |
575 | } | 613 | } |
576 | None | 614 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
615 | self.db, | ||
616 | ResolveMode::Other, | ||
617 | directive.module_id, | ||
618 | &path, | ||
619 | BuiltinShadowMode::Module, | ||
620 | ); | ||
621 | |||
622 | resolved_res.resolved_def.take_macros() | ||
577 | } | 623 | } |
578 | 624 | ||
579 | fn collect_macro_expansion( | 625 | fn collect_macro_expansion( |
@@ -776,7 +822,6 @@ impl ModCollector<'_, '_> { | |||
776 | // FIXME: check attrs to see if this is an attribute macro invocation; | 822 | // FIXME: check attrs to see if this is an attribute macro invocation; |
777 | // in which case we don't add the invocation, just a single attribute | 823 | // in which case we don't add the invocation, just a single attribute |
778 | // macro invocation | 824 | // macro invocation |
779 | |||
780 | self.collect_derives(attrs, def); | 825 | self.collect_derives(attrs, def); |
781 | 826 | ||
782 | let name = def.name.clone(); | 827 | let name = def.name.clone(); |
@@ -955,6 +1000,7 @@ mod tests { | |||
955 | unexpanded_attribute_macros: Vec::new(), | 1000 | unexpanded_attribute_macros: Vec::new(), |
956 | mod_dirs: FxHashMap::default(), | 1001 | mod_dirs: FxHashMap::default(), |
957 | cfg_options: &CfgOptions::default(), | 1002 | cfg_options: &CfgOptions::default(), |
1003 | proc_macros: Default::default(), | ||
958 | }; | 1004 | }; |
959 | collector.collect(); | 1005 | collector.collect(); |
960 | collector.def_map | 1006 | collector.def_map |