diff options
author | Edwin Cheng <[email protected]> | 2020-03-18 09:47:59 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2020-03-25 11:50:12 +0000 |
commit | 34dc8d25c1e461cc311d6d4404f74502513cd3ae (patch) | |
tree | 00aab26b07c1cd42dfa350eeddc6c41e5bea178b /crates/ra_hir_def | |
parent | e2dd17f75b1bb5e1185acff66211e74430177592 (diff) |
Add basic custom derive lowering
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 60 |
2 files changed, 57 insertions, 8 deletions
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 516dd773e..b3e811671 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -475,6 +475,9 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | |||
475 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 475 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
476 | ) -> Option<MacroCallId> { | 476 | ) -> Option<MacroCallId> { |
477 | let def = resolver(self.path.clone())?; | 477 | let def = resolver(self.path.clone())?; |
478 | Some(def.as_lazy_macro(db.upcast(), MacroCallKind::Attr(self.ast_id)).into()) | 478 | Some( |
479 | def.as_lazy_macro(db.upcast(), MacroCallKind::Attr(self.ast_id, self.path.to_string())) | ||
480 | .into(), | ||
481 | ) | ||
479 | } | 482 | } |
480 | } | 483 | } |
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::{ | |||
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; |
@@ -238,6 +239,18 @@ impl DefCollector<'_> { | |||
238 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); | 239 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); |
239 | } | 240 | } |
240 | 241 | ||
242 | /// Define a proc macro | ||
243 | /// | ||
244 | /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. | ||
245 | /// And unconditionally exported. | ||
246 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | ||
247 | self.update( | ||
248 | self.def_map.root, | ||
249 | &[(name, PerNs::macros(macro_, Visibility::Public))], | ||
250 | Visibility::Public, | ||
251 | ); | ||
252 | } | ||
253 | |||
241 | /// Import macros from `#[macro_use] extern crate`. | 254 | /// Import macros from `#[macro_use] extern crate`. |
242 | fn import_macros_from_extern_crate( | 255 | fn import_macros_from_extern_crate( |
243 | &mut self, | 256 | &mut self, |
@@ -537,8 +550,9 @@ impl DefCollector<'_> { | |||
537 | true | 550 | true |
538 | }); | 551 | }); |
539 | attribute_macros.retain(|directive| { | 552 | attribute_macros.retain(|directive| { |
540 | if let Some(call_id) = | 553 | if let Some(call_id) = directive |
541 | directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) | 554 | .ast_id |
555 | .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path)) | ||
542 | { | 556 | { |
543 | resolved.push((directive.module_id, call_id, 0)); | 557 | resolved.push((directive.module_id, call_id, 0)); |
544 | res = ReachedFixedPoint::No; | 558 | res = ReachedFixedPoint::No; |
@@ -562,9 +576,11 @@ impl DefCollector<'_> { | |||
562 | res | 576 | res |
563 | } | 577 | } |
564 | 578 | ||
565 | fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> { | 579 | fn resolve_attribute_macro( |
566 | // FIXME this is currently super hacky, just enough to support the | 580 | &self, |
567 | // built-in derives | 581 | directive: &DeriveDirective, |
582 | path: &ModPath, | ||
583 | ) -> Option<MacroDefId> { | ||
568 | if let Some(name) = path.as_ident() { | 584 | if let Some(name) = path.as_ident() { |
569 | // FIXME this should actually be handled with the normal name | 585 | // FIXME this should actually be handled with the normal name |
570 | // resolution; the std lib defines built-in stubs for the derives, | 586 | // resolution; the std lib defines built-in stubs for the derives, |
@@ -573,7 +589,15 @@ impl DefCollector<'_> { | |||
573 | return Some(def_id); | 589 | return Some(def_id); |
574 | } | 590 | } |
575 | } | 591 | } |
576 | None | 592 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
593 | self.db, | ||
594 | ResolveMode::Other, | ||
595 | directive.module_id, | ||
596 | &path, | ||
597 | BuiltinShadowMode::Module, | ||
598 | ); | ||
599 | |||
600 | resolved_res.resolved_def.take_macros() | ||
577 | } | 601 | } |
578 | 602 | ||
579 | fn collect_macro_expansion( | 603 | fn collect_macro_expansion( |
@@ -776,8 +800,8 @@ impl ModCollector<'_, '_> { | |||
776 | // FIXME: check attrs to see if this is an attribute macro invocation; | 800 | // 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 | 801 | // in which case we don't add the invocation, just a single attribute |
778 | // macro invocation | 802 | // macro invocation |
779 | |||
780 | self.collect_derives(attrs, def); | 803 | self.collect_derives(attrs, def); |
804 | self.collect_proc_macro(attrs); | ||
781 | 805 | ||
782 | let name = def.name.clone(); | 806 | let name = def.name.clone(); |
783 | let container = ContainerId::ModuleId(module); | 807 | let container = ContainerId::ModuleId(module); |
@@ -854,6 +878,28 @@ impl ModCollector<'_, '_> { | |||
854 | } | 878 | } |
855 | } | 879 | } |
856 | 880 | ||
881 | fn collect_proc_macro(&mut self, attrs: &Attrs) { | ||
882 | if let Some(derive_subtree) = attrs.by_key("proc_macro_derive").tt_values().next() { | ||
883 | if let Some(tt) = derive_subtree.token_trees.get(0) { | ||
884 | let ident = match &tt { | ||
885 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, | ||
886 | _ => return, // anything else would be an error (which we currently ignore) | ||
887 | }; | ||
888 | let name = ident.as_name(); | ||
889 | let krate = self.def_collector.def_map.krate; | ||
890 | let expander = ProcMacroExpander::new(krate); | ||
891 | |||
892 | let macro_id = MacroDefId { | ||
893 | ast_id: None, | ||
894 | krate: Some(krate), | ||
895 | kind: MacroDefKind::ProcMacro(expander), | ||
896 | }; | ||
897 | |||
898 | self.def_collector.define_proc_macro(name.clone(), macro_id); | ||
899 | } | ||
900 | } | ||
901 | } | ||
902 | |||
857 | fn collect_macro(&mut self, mac: &raw::MacroData) { | 903 | fn collect_macro(&mut self, mac: &raw::MacroData) { |
858 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 904 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
859 | 905 | ||