aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2020-03-18 09:47:59 +0000
committerEdwin Cheng <[email protected]>2020-03-25 11:50:12 +0000
commit34dc8d25c1e461cc311d6d4404f74502513cd3ae (patch)
tree00aab26b07c1cd42dfa350eeddc6c41e5bea178b /crates/ra_hir_def
parente2dd17f75b1bb5e1185acff66211e74430177592 (diff)
Add basic custom derive lowering
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/lib.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs60
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};
12use ra_cfg::CfgOptions; 13use 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