diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/lib.rs | 40 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 56 |
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 | ||
58 | use attr::Attr; | ||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 59 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 60 | use 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 | |||
773 | fn 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 ¯o_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 | ||
24 | use crate::{ | 24 | use 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 { | |||
223 | enum MacroDirectiveKind { | 223 | enum 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 | ||
229 | struct DefData<'a> { | 229 | struct 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(()); |