diff options
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 107 |
1 files changed, 69 insertions, 38 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 1936348fb..a636ec77d 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -136,23 +136,35 @@ struct Import { | |||
136 | } | 136 | } |
137 | 137 | ||
138 | impl Import { | 138 | impl Import { |
139 | fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self { | 139 | fn from_use( |
140 | db: &dyn DefDatabase, | ||
141 | krate: CrateId, | ||
142 | tree: &ItemTree, | ||
143 | id: ItemTreeId<item_tree::Import>, | ||
144 | ) -> Self { | ||
140 | let it = &tree[id.value]; | 145 | let it = &tree[id.value]; |
146 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | ||
141 | let visibility = &tree[it.visibility]; | 147 | let visibility = &tree[it.visibility]; |
142 | Self { | 148 | Self { |
143 | path: it.path.clone(), | 149 | path: it.path.clone(), |
144 | alias: it.alias.clone(), | 150 | alias: it.alias.clone(), |
145 | visibility: visibility.clone(), | 151 | visibility: visibility.clone(), |
146 | is_glob: it.is_glob, | 152 | is_glob: it.is_glob, |
147 | is_prelude: it.is_prelude, | 153 | is_prelude: attrs.by_key("prelude_import").exists(), |
148 | is_extern_crate: false, | 154 | is_extern_crate: false, |
149 | is_macro_use: false, | 155 | is_macro_use: false, |
150 | source: ImportSource::Import(id), | 156 | source: ImportSource::Import(id), |
151 | } | 157 | } |
152 | } | 158 | } |
153 | 159 | ||
154 | fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self { | 160 | fn from_extern_crate( |
161 | db: &dyn DefDatabase, | ||
162 | krate: CrateId, | ||
163 | tree: &ItemTree, | ||
164 | id: ItemTreeId<item_tree::ExternCrate>, | ||
165 | ) -> Self { | ||
155 | let it = &tree[id.value]; | 166 | let it = &tree[id.value]; |
167 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | ||
156 | let visibility = &tree[it.visibility]; | 168 | let visibility = &tree[it.visibility]; |
157 | Self { | 169 | Self { |
158 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 170 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), |
@@ -161,7 +173,7 @@ impl Import { | |||
161 | is_glob: false, | 173 | is_glob: false, |
162 | is_prelude: false, | 174 | is_prelude: false, |
163 | is_extern_crate: true, | 175 | is_extern_crate: true, |
164 | is_macro_use: it.is_macro_use, | 176 | is_macro_use: attrs.by_key("macro_use").exists(), |
165 | source: ImportSource::ExternCrate(id), | 177 | source: ImportSource::ExternCrate(id), |
166 | } | 178 | } |
167 | } | 179 | } |
@@ -221,17 +233,20 @@ impl DefCollector<'_> { | |||
221 | let item_tree = self.db.item_tree(file_id.into()); | 233 | let item_tree = self.db.item_tree(file_id.into()); |
222 | let module_id = self.def_map.root; | 234 | let module_id = self.def_map.root; |
223 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | 235 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; |
224 | let mut root_collector = ModCollector { | 236 | if item_tree |
225 | def_collector: &mut *self, | 237 | .top_level_attrs(self.db, self.def_map.krate) |
226 | macro_depth: 0, | 238 | .cfg() |
227 | module_id, | 239 | .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) |
228 | file_id: file_id.into(), | ||
229 | item_tree: &item_tree, | ||
230 | mod_dir: ModDir::root(), | ||
231 | }; | ||
232 | if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg)) | ||
233 | { | 240 | { |
234 | root_collector.collect(item_tree.top_level_items()); | 241 | ModCollector { |
242 | def_collector: &mut *self, | ||
243 | macro_depth: 0, | ||
244 | module_id, | ||
245 | file_id: file_id.into(), | ||
246 | item_tree: &item_tree, | ||
247 | mod_dir: ModDir::root(), | ||
248 | } | ||
249 | .collect(item_tree.top_level_items()); | ||
235 | } | 250 | } |
236 | 251 | ||
237 | // main name resolution fixed-point loop. | 252 | // main name resolution fixed-point loop. |
@@ -905,6 +920,8 @@ struct ModCollector<'a, 'b> { | |||
905 | 920 | ||
906 | impl ModCollector<'_, '_> { | 921 | impl ModCollector<'_, '_> { |
907 | fn collect(&mut self, items: &[ModItem]) { | 922 | fn collect(&mut self, items: &[ModItem]) { |
923 | let krate = self.def_collector.def_map.krate; | ||
924 | |||
908 | // Note: don't assert that inserted value is fresh: it's simply not true | 925 | // Note: don't assert that inserted value is fresh: it's simply not true |
909 | // for macros. | 926 | // for macros. |
910 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); | 927 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); |
@@ -921,11 +938,16 @@ impl ModCollector<'_, '_> { | |||
921 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 938 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
922 | // any other items. | 939 | // any other items. |
923 | for item in items { | 940 | for item in items { |
924 | let attrs = self.item_tree.attrs((*item).into()); | 941 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into()); |
925 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { | 942 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { |
926 | if let ModItem::ExternCrate(id) = item { | 943 | if let ModItem::ExternCrate(id) = item { |
927 | let import = self.item_tree[*id].clone(); | 944 | let import = self.item_tree[*id].clone(); |
928 | if import.is_macro_use { | 945 | let attrs = self.item_tree.attrs( |
946 | self.def_collector.db, | ||
947 | krate, | ||
948 | ModItem::from(*id).into(), | ||
949 | ); | ||
950 | if attrs.by_key("macro_use").exists() { | ||
929 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | 951 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); |
930 | } | 952 | } |
931 | } | 953 | } |
@@ -933,7 +955,7 @@ impl ModCollector<'_, '_> { | |||
933 | } | 955 | } |
934 | 956 | ||
935 | for &item in items { | 957 | for &item in items { |
936 | let attrs = self.item_tree.attrs(item.into()); | 958 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into()); |
937 | if let Some(cfg) = attrs.cfg() { | 959 | if let Some(cfg) = attrs.cfg() { |
938 | if !self.is_cfg_enabled(&cfg) { | 960 | if !self.is_cfg_enabled(&cfg) { |
939 | self.emit_unconfigured_diagnostic(item, &cfg); | 961 | self.emit_unconfigured_diagnostic(item, &cfg); |
@@ -946,11 +968,13 @@ impl ModCollector<'_, '_> { | |||
946 | 968 | ||
947 | let mut def = None; | 969 | let mut def = None; |
948 | match item { | 970 | match item { |
949 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), | 971 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs), |
950 | ModItem::Import(import_id) => { | 972 | ModItem::Import(import_id) => { |
951 | self.def_collector.unresolved_imports.push(ImportDirective { | 973 | self.def_collector.unresolved_imports.push(ImportDirective { |
952 | module_id: self.module_id, | 974 | module_id: self.module_id, |
953 | import: Import::from_use( | 975 | import: Import::from_use( |
976 | self.def_collector.db, | ||
977 | krate, | ||
954 | &self.item_tree, | 978 | &self.item_tree, |
955 | InFile::new(self.file_id, import_id), | 979 | InFile::new(self.file_id, import_id), |
956 | ), | 980 | ), |
@@ -961,6 +985,8 @@ impl ModCollector<'_, '_> { | |||
961 | self.def_collector.unresolved_imports.push(ImportDirective { | 985 | self.def_collector.unresolved_imports.push(ImportDirective { |
962 | module_id: self.module_id, | 986 | module_id: self.module_id, |
963 | import: Import::from_extern_crate( | 987 | import: Import::from_extern_crate( |
988 | self.def_collector.db, | ||
989 | krate, | ||
964 | &self.item_tree, | 990 | &self.item_tree, |
965 | InFile::new(self.file_id, import_id), | 991 | InFile::new(self.file_id, import_id), |
966 | ), | 992 | ), |
@@ -975,7 +1001,11 @@ impl ModCollector<'_, '_> { | |||
975 | 1001 | ||
976 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | 1002 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it |
977 | // to define builtin macros, so we support at least that part. | 1003 | // to define builtin macros, so we support at least that part. |
978 | let attrs = self.item_tree.attrs(ModItem::from(id).into()); | 1004 | let attrs = self.item_tree.attrs( |
1005 | self.def_collector.db, | ||
1006 | krate, | ||
1007 | ModItem::from(id).into(), | ||
1008 | ); | ||
979 | if attrs.by_key("rustc_builtin_macro").exists() { | 1009 | if attrs.by_key("rustc_builtin_macro").exists() { |
980 | let krate = self.def_collector.def_map.krate; | 1010 | let krate = self.def_collector.def_map.krate; |
981 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | 1011 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) |
@@ -1012,7 +1042,7 @@ impl ModCollector<'_, '_> { | |||
1012 | ModItem::Function(id) => { | 1042 | ModItem::Function(id) => { |
1013 | let func = &self.item_tree[id]; | 1043 | let func = &self.item_tree[id]; |
1014 | 1044 | ||
1015 | self.collect_proc_macro_def(&func.name, attrs); | 1045 | self.collect_proc_macro_def(&func.name, &attrs); |
1016 | 1046 | ||
1017 | def = Some(DefData { | 1047 | def = Some(DefData { |
1018 | id: FunctionLoc { | 1048 | id: FunctionLoc { |
@@ -1032,7 +1062,7 @@ impl ModCollector<'_, '_> { | |||
1032 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1062 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1033 | // in which case we don't add the invocation, just a single attribute | 1063 | // in which case we don't add the invocation, just a single attribute |
1034 | // macro invocation | 1064 | // macro invocation |
1035 | self.collect_derives(attrs, it.ast_id.upcast()); | 1065 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1036 | 1066 | ||
1037 | def = Some(DefData { | 1067 | def = Some(DefData { |
1038 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1068 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1049,7 +1079,7 @@ impl ModCollector<'_, '_> { | |||
1049 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1079 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1050 | // in which case we don't add the invocation, just a single attribute | 1080 | // in which case we don't add the invocation, just a single attribute |
1051 | // macro invocation | 1081 | // macro invocation |
1052 | self.collect_derives(attrs, it.ast_id.upcast()); | 1082 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1053 | 1083 | ||
1054 | def = Some(DefData { | 1084 | def = Some(DefData { |
1055 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1085 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1066,7 +1096,7 @@ impl ModCollector<'_, '_> { | |||
1066 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1096 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1067 | // in which case we don't add the invocation, just a single attribute | 1097 | // in which case we don't add the invocation, just a single attribute |
1068 | // macro invocation | 1098 | // macro invocation |
1069 | self.collect_derives(attrs, it.ast_id.upcast()); | 1099 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1070 | 1100 | ||
1071 | def = Some(DefData { | 1101 | def = Some(DefData { |
1072 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1102 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1259,20 +1289,20 @@ impl ModCollector<'_, '_> { | |||
1259 | } | 1289 | } |
1260 | 1290 | ||
1261 | fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) { | 1291 | fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) { |
1262 | for derive_subtree in attrs.by_key("derive").tt_values() { | 1292 | for derive in attrs.by_key("derive").attrs() { |
1263 | // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree | 1293 | match derive.parse_derive() { |
1264 | for tt in &derive_subtree.token_trees { | 1294 | Some(derive_macros) => { |
1265 | let ident = match &tt { | 1295 | for path in derive_macros { |
1266 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, | 1296 | let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); |
1267 | tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok | 1297 | self.def_collector |
1268 | _ => continue, // anything else would be an error (which we currently ignore) | 1298 | .unexpanded_attribute_macros |
1269 | }; | 1299 | .push(DeriveDirective { module_id: self.module_id, ast_id }); |
1270 | let path = ModPath::from_tt_ident(ident); | 1300 | } |
1271 | 1301 | } | |
1272 | let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); | 1302 | None => { |
1273 | self.def_collector | 1303 | // FIXME: diagnose |
1274 | .unexpanded_attribute_macros | 1304 | log::debug!("malformed derive: {:?}", derive); |
1275 | .push(DeriveDirective { module_id: self.module_id, ast_id }); | 1305 | } |
1276 | } | 1306 | } |
1277 | } | 1307 | } |
1278 | } | 1308 | } |
@@ -1303,8 +1333,9 @@ impl ModCollector<'_, '_> { | |||
1303 | } | 1333 | } |
1304 | 1334 | ||
1305 | fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { | 1335 | fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { |
1336 | let krate = self.def_collector.def_map.krate; | ||
1306 | let mac = &self.item_tree[id]; | 1337 | let mac = &self.item_tree[id]; |
1307 | let attrs = self.item_tree.attrs(ModItem::from(id).into()); | 1338 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); |
1308 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | 1339 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); |
1309 | 1340 | ||
1310 | let export_attr = attrs.by_key("macro_export"); | 1341 | let export_attr = attrs.by_key("macro_export"); |