diff options
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 4c3993ff0..42c0f0536 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -16,10 +16,10 @@ use hir_expand::{ | |||
16 | proc_macro::ProcMacroExpander, | 16 | proc_macro::ProcMacroExpander, |
17 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 17 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
18 | }; | 18 | }; |
19 | use rustc_hash::FxHashMap; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
20 | use rustc_hash::FxHashSet; | ||
21 | use syntax::ast; | 20 | use syntax::ast; |
22 | use test_utils::mark; | 21 | use test_utils::mark; |
22 | use tt::{Leaf, TokenTree}; | ||
23 | 23 | ||
24 | use crate::{ | 24 | use crate::{ |
25 | attr::Attrs, | 25 | attr::Attrs, |
@@ -281,6 +281,25 @@ impl DefCollector<'_> { | |||
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | fn resolve_proc_macro(&mut self, name: &Name) { | ||
285 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { | ||
286 | Some((_, expander)) => MacroDefId { | ||
287 | ast_id: None, | ||
288 | krate: Some(self.def_map.krate), | ||
289 | kind: MacroDefKind::ProcMacro(*expander), | ||
290 | local_inner: false, | ||
291 | }, | ||
292 | None => MacroDefId { | ||
293 | ast_id: None, | ||
294 | krate: Some(self.def_map.krate), | ||
295 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), | ||
296 | local_inner: false, | ||
297 | }, | ||
298 | }; | ||
299 | |||
300 | self.define_proc_macro(name.clone(), macro_def); | ||
301 | } | ||
302 | |||
284 | /// Define a macro with `macro_rules`. | 303 | /// Define a macro with `macro_rules`. |
285 | /// | 304 | /// |
286 | /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`, | 305 | /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`, |
@@ -917,6 +936,9 @@ impl ModCollector<'_, '_> { | |||
917 | } | 936 | } |
918 | ModItem::Function(id) => { | 937 | ModItem::Function(id) => { |
919 | let func = &self.item_tree[id]; | 938 | let func = &self.item_tree[id]; |
939 | |||
940 | self.collect_proc_macro_def(&func.name, attrs); | ||
941 | |||
920 | def = Some(DefData { | 942 | def = Some(DefData { |
921 | id: FunctionLoc { | 943 | id: FunctionLoc { |
922 | container: container.into(), | 944 | container: container.into(), |
@@ -1177,6 +1199,30 @@ impl ModCollector<'_, '_> { | |||
1177 | } | 1199 | } |
1178 | } | 1200 | } |
1179 | 1201 | ||
1202 | /// If `attrs` registers a procedural macro, collects its definition. | ||
1203 | fn collect_proc_macro_def(&mut self, func_name: &Name, attrs: &Attrs) { | ||
1204 | // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere | ||
1205 | // FIXME: distinguish the type of macro | ||
1206 | let macro_name = if attrs.by_key("proc_macro").exists() | ||
1207 | || attrs.by_key("proc_macro_attribute").exists() | ||
1208 | { | ||
1209 | func_name.clone() | ||
1210 | } else { | ||
1211 | let derive = attrs.by_key("proc_macro_derive"); | ||
1212 | if let Some(arg) = derive.tt_values().next() { | ||
1213 | if let [TokenTree::Leaf(Leaf::Ident(trait_name))] = &*arg.token_trees { | ||
1214 | trait_name.as_name() | ||
1215 | } else { | ||
1216 | return; | ||
1217 | } | ||
1218 | } else { | ||
1219 | return; | ||
1220 | } | ||
1221 | }; | ||
1222 | |||
1223 | self.def_collector.resolve_proc_macro(¯o_name); | ||
1224 | } | ||
1225 | |||
1180 | fn collect_macro(&mut self, mac: &MacroCall) { | 1226 | fn collect_macro(&mut self, mac: &MacroCall) { |
1181 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1227 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
1182 | 1228 | ||