diff options
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 121 |
1 files changed, 85 insertions, 36 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 85cc342c4..b114a6fe4 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -26,7 +26,8 @@ use crate::{ | |||
26 | db::DefDatabase, | 26 | db::DefDatabase, |
27 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
28 | item_tree::{ | 28 | item_tree::{ |
29 | self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, |
30 | StructDefKind, | ||
30 | }, | 31 | }, |
31 | nameres::{ | 32 | nameres::{ |
32 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 33 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
@@ -220,17 +221,20 @@ impl DefCollector<'_> { | |||
220 | let item_tree = self.db.item_tree(file_id.into()); | 221 | let item_tree = self.db.item_tree(file_id.into()); |
221 | let module_id = self.def_map.root; | 222 | let module_id = self.def_map.root; |
222 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | 223 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; |
223 | let mut root_collector = ModCollector { | 224 | if item_tree |
224 | def_collector: &mut *self, | 225 | .top_level_attrs(self.db, self.def_map.krate) |
225 | macro_depth: 0, | 226 | .cfg() |
226 | module_id, | 227 | .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) |
227 | file_id: file_id.into(), | ||
228 | item_tree: &item_tree, | ||
229 | mod_dir: ModDir::root(), | ||
230 | }; | ||
231 | if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg)) | ||
232 | { | 228 | { |
233 | root_collector.collect(item_tree.top_level_items()); | 229 | ModCollector { |
230 | def_collector: &mut *self, | ||
231 | macro_depth: 0, | ||
232 | module_id, | ||
233 | file_id: file_id.into(), | ||
234 | item_tree: &item_tree, | ||
235 | mod_dir: ModDir::root(), | ||
236 | } | ||
237 | .collect(item_tree.top_level_items()); | ||
234 | } | 238 | } |
235 | 239 | ||
236 | // main name resolution fixed-point loop. | 240 | // main name resolution fixed-point loop. |
@@ -309,13 +313,13 @@ impl DefCollector<'_> { | |||
309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { | 313 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { |
310 | Some((_, expander)) => MacroDefId { | 314 | Some((_, expander)) => MacroDefId { |
311 | ast_id: None, | 315 | ast_id: None, |
312 | krate: Some(self.def_map.krate), | 316 | krate: self.def_map.krate, |
313 | kind: MacroDefKind::ProcMacro(*expander), | 317 | kind: MacroDefKind::ProcMacro(*expander), |
314 | local_inner: false, | 318 | local_inner: false, |
315 | }, | 319 | }, |
316 | None => MacroDefId { | 320 | None => MacroDefId { |
317 | ast_id: None, | 321 | ast_id: None, |
318 | krate: Some(self.def_map.krate), | 322 | krate: self.def_map.krate, |
319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), | 323 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), |
320 | local_inner: false, | 324 | local_inner: false, |
321 | }, | 325 | }, |
@@ -784,14 +788,6 @@ impl DefCollector<'_> { | |||
784 | directive: &DeriveDirective, | 788 | directive: &DeriveDirective, |
785 | path: &ModPath, | 789 | path: &ModPath, |
786 | ) -> Option<MacroDefId> { | 790 | ) -> Option<MacroDefId> { |
787 | if let Some(name) = path.as_ident() { | ||
788 | // FIXME this should actually be handled with the normal name | ||
789 | // resolution; the std lib defines built-in stubs for the derives, | ||
790 | // but these are new-style `macro`s, which we don't support yet | ||
791 | if let Some(def_id) = find_builtin_derive(name) { | ||
792 | return Some(def_id); | ||
793 | } | ||
794 | } | ||
795 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 791 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 792 | self.db, |
797 | ResolveMode::Other, | 793 | ResolveMode::Other, |
@@ -912,6 +908,8 @@ struct ModCollector<'a, 'b> { | |||
912 | 908 | ||
913 | impl ModCollector<'_, '_> { | 909 | impl ModCollector<'_, '_> { |
914 | fn collect(&mut self, items: &[ModItem]) { | 910 | fn collect(&mut self, items: &[ModItem]) { |
911 | let krate = self.def_collector.def_map.krate; | ||
912 | |||
915 | // Note: don't assert that inserted value is fresh: it's simply not true | 913 | // Note: don't assert that inserted value is fresh: it's simply not true |
916 | // for macros. | 914 | // for macros. |
917 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); | 915 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); |
@@ -928,7 +926,7 @@ impl ModCollector<'_, '_> { | |||
928 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 926 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
929 | // any other items. | 927 | // any other items. |
930 | for item in items { | 928 | for item in items { |
931 | let attrs = self.item_tree.attrs((*item).into()); | 929 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into()); |
932 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { | 930 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { |
933 | if let ModItem::ExternCrate(id) = item { | 931 | if let ModItem::ExternCrate(id) = item { |
934 | let import = self.item_tree[*id].clone(); | 932 | let import = self.item_tree[*id].clone(); |
@@ -940,7 +938,7 @@ impl ModCollector<'_, '_> { | |||
940 | } | 938 | } |
941 | 939 | ||
942 | for &item in items { | 940 | for &item in items { |
943 | let attrs = self.item_tree.attrs(item.into()); | 941 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into()); |
944 | if let Some(cfg) = attrs.cfg() { | 942 | if let Some(cfg) = attrs.cfg() { |
945 | if !self.is_cfg_enabled(&cfg) { | 943 | if !self.is_cfg_enabled(&cfg) { |
946 | self.emit_unconfigured_diagnostic(item, &cfg); | 944 | self.emit_unconfigured_diagnostic(item, &cfg); |
@@ -953,7 +951,7 @@ impl ModCollector<'_, '_> { | |||
953 | 951 | ||
954 | let mut def = None; | 952 | let mut def = None; |
955 | match item { | 953 | match item { |
956 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), | 954 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs), |
957 | ModItem::Import(import_id) => { | 955 | ModItem::Import(import_id) => { |
958 | self.def_collector.unresolved_imports.push(ImportDirective { | 956 | self.def_collector.unresolved_imports.push(ImportDirective { |
959 | module_id: self.module_id, | 957 | module_id: self.module_id, |
@@ -975,7 +973,41 @@ impl ModCollector<'_, '_> { | |||
975 | }) | 973 | }) |
976 | } | 974 | } |
977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 975 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), | 976 | ModItem::MacroRules(id) => self.collect_macro_rules(id), |
977 | ModItem::MacroDef(id) => { | ||
978 | let mac = &self.item_tree[id]; | ||
979 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
980 | |||
981 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
982 | // to define builtin macros, so we support at least that part. | ||
983 | let attrs = self.item_tree.attrs( | ||
984 | self.def_collector.db, | ||
985 | krate, | ||
986 | ModItem::from(id).into(), | ||
987 | ); | ||
988 | if attrs.by_key("rustc_builtin_macro").exists() { | ||
989 | let krate = self.def_collector.def_map.krate; | ||
990 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
991 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
992 | if let Some(macro_id) = macro_id { | ||
993 | let vis = self | ||
994 | .def_collector | ||
995 | .def_map | ||
996 | .resolve_visibility( | ||
997 | self.def_collector.db, | ||
998 | self.module_id, | ||
999 | &self.item_tree[mac.visibility], | ||
1000 | ) | ||
1001 | .unwrap_or(Visibility::Public); | ||
1002 | self.def_collector.update( | ||
1003 | self.module_id, | ||
1004 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
1005 | vis, | ||
1006 | ImportType::Named, | ||
1007 | ); | ||
1008 | } | ||
1009 | } | ||
1010 | } | ||
979 | ModItem::Impl(imp) => { | 1011 | ModItem::Impl(imp) => { |
980 | let module = ModuleId { | 1012 | let module = ModuleId { |
981 | krate: self.def_collector.def_map.krate, | 1013 | krate: self.def_collector.def_map.krate, |
@@ -989,7 +1021,7 @@ impl ModCollector<'_, '_> { | |||
989 | ModItem::Function(id) => { | 1021 | ModItem::Function(id) => { |
990 | let func = &self.item_tree[id]; | 1022 | let func = &self.item_tree[id]; |
991 | 1023 | ||
992 | self.collect_proc_macro_def(&func.name, attrs); | 1024 | self.collect_proc_macro_def(&func.name, &attrs); |
993 | 1025 | ||
994 | def = Some(DefData { | 1026 | def = Some(DefData { |
995 | id: FunctionLoc { | 1027 | id: FunctionLoc { |
@@ -1009,7 +1041,7 @@ impl ModCollector<'_, '_> { | |||
1009 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1041 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1010 | // in which case we don't add the invocation, just a single attribute | 1042 | // in which case we don't add the invocation, just a single attribute |
1011 | // macro invocation | 1043 | // macro invocation |
1012 | self.collect_derives(attrs, it.ast_id.upcast()); | 1044 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1013 | 1045 | ||
1014 | def = Some(DefData { | 1046 | def = Some(DefData { |
1015 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1047 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1026,7 +1058,7 @@ impl ModCollector<'_, '_> { | |||
1026 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1058 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1027 | // in which case we don't add the invocation, just a single attribute | 1059 | // in which case we don't add the invocation, just a single attribute |
1028 | // macro invocation | 1060 | // macro invocation |
1029 | self.collect_derives(attrs, it.ast_id.upcast()); | 1061 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1030 | 1062 | ||
1031 | def = Some(DefData { | 1063 | def = Some(DefData { |
1032 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1064 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1043,7 +1075,7 @@ impl ModCollector<'_, '_> { | |||
1043 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1075 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1044 | // in which case we don't add the invocation, just a single attribute | 1076 | // in which case we don't add the invocation, just a single attribute |
1045 | // macro invocation | 1077 | // macro invocation |
1046 | self.collect_derives(attrs, it.ast_id.upcast()); | 1078 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1047 | 1079 | ||
1048 | def = Some(DefData { | 1080 | def = Some(DefData { |
1049 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1081 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1279,18 +1311,35 @@ impl ModCollector<'_, '_> { | |||
1279 | self.def_collector.resolve_proc_macro(¯o_name); | 1311 | self.def_collector.resolve_proc_macro(¯o_name); |
1280 | } | 1312 | } |
1281 | 1313 | ||
1282 | fn collect_macro_rules(&mut self, mac: &MacroRules) { | 1314 | fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { |
1283 | let ast_id = InFile::new(self.file_id, mac.ast_id); | 1315 | let krate = self.def_collector.def_map.krate; |
1316 | let mac = &self.item_tree[id]; | ||
1317 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); | ||
1318 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
1319 | |||
1320 | let export_attr = attrs.by_key("macro_export"); | ||
1321 | |||
1322 | let is_export = export_attr.exists(); | ||
1323 | let is_local_inner = if is_export { | ||
1324 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
1325 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
1326 | ident.text.contains("local_inner_macros") | ||
1327 | } | ||
1328 | _ => false, | ||
1329 | }) | ||
1330 | } else { | ||
1331 | false | ||
1332 | }; | ||
1284 | 1333 | ||
1285 | // Case 1: builtin macros | 1334 | // Case 1: builtin macros |
1286 | if mac.is_builtin { | 1335 | if attrs.by_key("rustc_builtin_macro").exists() { |
1287 | let krate = self.def_collector.def_map.krate; | 1336 | let krate = self.def_collector.def_map.krate; |
1288 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1337 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { |
1289 | self.def_collector.define_macro( | 1338 | self.def_collector.define_macro( |
1290 | self.module_id, | 1339 | self.module_id, |
1291 | mac.name.clone(), | 1340 | mac.name.clone(), |
1292 | macro_id, | 1341 | macro_id, |
1293 | mac.is_export, | 1342 | is_export, |
1294 | ); | 1343 | ); |
1295 | return; | 1344 | return; |
1296 | } | 1345 | } |
@@ -1299,11 +1348,11 @@ impl ModCollector<'_, '_> { | |||
1299 | // Case 2: normal `macro_rules!` macro | 1348 | // Case 2: normal `macro_rules!` macro |
1300 | let macro_id = MacroDefId { | 1349 | let macro_id = MacroDefId { |
1301 | ast_id: Some(ast_id), | 1350 | ast_id: Some(ast_id), |
1302 | krate: Some(self.def_collector.def_map.krate), | 1351 | krate: self.def_collector.def_map.krate, |
1303 | kind: MacroDefKind::Declarative, | 1352 | kind: MacroDefKind::Declarative, |
1304 | local_inner: mac.is_local_inner, | 1353 | local_inner: is_local_inner, |
1305 | }; | 1354 | }; |
1306 | self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export); | 1355 | self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); |
1307 | } | 1356 | } |
1308 | 1357 | ||
1309 | fn collect_macro_call(&mut self, mac: &MacroCall) { | 1358 | fn collect_macro_call(&mut self, mac: &MacroCall) { |