aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-05-31 12:37:11 +0100
committerJonas Schievink <[email protected]>2021-06-03 17:09:21 +0100
commite5a2c6596ddd11b0d57042224ac7c1d7691ec33b (patch)
treef0476ad40103b5d3dea60f81fca32c63fe9618d7 /crates/hir_def/src
parent7f9c4a59d9a84cd8c734286937439b5cd215be27 (diff)
Expand procedural attribute macros
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/lib.rs40
-rw-r--r--crates/hir_def/src/nameres/collector.rs56
2 files changed, 90 insertions, 6 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 9aa95720a..987485acc 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -55,6 +55,7 @@ use std::{
55 sync::Arc, 55 sync::Arc,
56}; 56};
57 57
58use attr::Attr;
58use base_db::{impl_intern_key, salsa, CrateId}; 59use base_db::{impl_intern_key, salsa, CrateId};
59use hir_expand::{ 60use hir_expand::{
60 ast_id_map::FileAstId, 61 ast_id_map::FileAstId,
@@ -768,3 +769,42 @@ fn derive_macro_as_call_id(
768 .into(); 769 .into();
769 Ok(res) 770 Ok(res)
770} 771}
772
773fn attr_macro_as_call_id(
774 item_attr: &AstIdWithPath<ast::Item>,
775 macro_attr: &Attr,
776 db: &dyn db::DefDatabase,
777 krate: CrateId,
778 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
779) -> Result<MacroCallId, UnresolvedMacro> {
780 let def: MacroDefId = resolver(item_attr.path.clone())
781 .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
782 let last_segment = item_attr
783 .path
784 .segments()
785 .last()
786 .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
787 let mut arg = match &macro_attr.input {
788 Some(input) => match &**input {
789 attr::AttrInput::Literal(_) => tt::Subtree::default(),
790 attr::AttrInput::TokenTree(tt) => tt.clone(),
791 },
792 None => tt::Subtree::default(),
793 };
794 // The parentheses are always disposed here.
795 arg.delimiter = None;
796
797 let res = def
798 .as_lazy_macro(
799 db.upcast(),
800 krate,
801 MacroCallKind::Attr {
802 ast_id: item_attr.ast_id,
803 attr_name: last_segment.to_string(),
804 attr_args: arg,
805 invoc_attr_index: macro_attr.id.ast_index,
806 },
807 )
808 .into();
809 Ok(res)
810}
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 6b41921ae..874a4ebb1 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -23,7 +23,7 @@ use syntax::ast;
23 23
24use crate::{ 24use crate::{
25 attr::{Attr, AttrId, AttrInput, Attrs}, 25 attr::{Attr, AttrId, AttrInput, Attrs},
26 builtin_attr, 26 attr_macro_as_call_id, builtin_attr,
27 db::DefDatabase, 27 db::DefDatabase,
28 derive_macro_as_call_id, 28 derive_macro_as_call_id,
29 intern::Interned, 29 intern::Interned,
@@ -223,7 +223,7 @@ struct MacroDirective {
223enum MacroDirectiveKind { 223enum MacroDirectiveKind {
224 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, 224 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
225 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, 225 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
226 Attr { ast_id: AstIdWithPath<ast::Item>, attr: AttrId, mod_item: ModItem }, 226 Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
227} 227}
228 228
229struct DefData<'a> { 229struct DefData<'a> {
@@ -419,7 +419,7 @@ impl DefCollector<'_> {
419 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); 419 let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new());
420 let pos = unresolved_macros.iter().position(|directive| { 420 let pos = unresolved_macros.iter().position(|directive| {
421 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { 421 if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind {
422 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr); 422 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
423 423
424 let file_id = ast_id.ast_id.file_id; 424 let file_id = ast_id.ast_id.file_id;
425 let item_tree = self.db.file_item_tree(file_id); 425 let item_tree = self.db.file_item_tree(file_id);
@@ -1050,7 +1050,7 @@ impl DefCollector<'_> {
1050 let file_id = ast_id.ast_id.file_id; 1050 let file_id = ast_id.ast_id.file_id;
1051 let item_tree = self.db.file_item_tree(file_id); 1051 let item_tree = self.db.file_item_tree(file_id);
1052 let mod_dir = self.mod_dirs[&directive.module_id].clone(); 1052 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1053 self.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr); 1053 self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
1054 ModCollector { 1054 ModCollector {
1055 def_collector: &mut *self, 1055 def_collector: &mut *self,
1056 macro_depth: directive.depth, 1056 macro_depth: directive.depth,
@@ -1068,7 +1068,51 @@ impl DefCollector<'_> {
1068 } 1068 }
1069 1069
1070 // Not resolved to a derive helper, so try to resolve as a macro. 1070 // Not resolved to a derive helper, so try to resolve as a macro.
1071 // FIXME: not yet :) 1071 match attr_macro_as_call_id(
1072 ast_id,
1073 attr,
1074 self.db,
1075 self.def_map.krate,
1076 &resolver,
1077 ) {
1078 Ok(call_id) => {
1079 let loc: MacroCallLoc = self.db.lookup_intern_macro(call_id);
1080 if let MacroDefKind::ProcMacro(exp, ..) = &loc.def.kind {
1081 if exp.is_dummy() {
1082 // Proc macros that cannot be expanded are treated as not
1083 // resolved, in order to fall back later.
1084 self.def_map.diagnostics.push(
1085 DefDiagnostic::unresolved_proc_macro(
1086 directive.module_id,
1087 loc.kind,
1088 ),
1089 );
1090
1091 let file_id = ast_id.ast_id.file_id;
1092 let item_tree = self.db.file_item_tree(file_id);
1093 let mod_dir = self.mod_dirs[&directive.module_id].clone();
1094 self.skip_attrs
1095 .insert(InFile::new(file_id, *mod_item), attr.id);
1096 ModCollector {
1097 def_collector: &mut *self,
1098 macro_depth: directive.depth,
1099 module_id: directive.module_id,
1100 file_id,
1101 item_tree: &item_tree,
1102 mod_dir,
1103 }
1104 .collect(&[*mod_item]);
1105
1106 // Remove the macro directive.
1107 return false;
1108 }
1109 }
1110 resolved.push((directive.module_id, call_id, directive.depth));
1111 res = ReachedFixedPoint::No;
1112 return false;
1113 }
1114 Err(UnresolvedMacro { .. }) => (),
1115 }
1072 } 1116 }
1073 } 1117 }
1074 1118
@@ -1628,7 +1672,7 @@ impl ModCollector<'_, '_> {
1628 self.def_collector.unresolved_macros.push(MacroDirective { 1672 self.def_collector.unresolved_macros.push(MacroDirective {
1629 module_id: self.module_id, 1673 module_id: self.module_id,
1630 depth: self.macro_depth + 1, 1674 depth: self.macro_depth + 1,
1631 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.id, mod_item }, 1675 kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
1632 }); 1676 });
1633 1677
1634 return Err(()); 1678 return Err(());