diff options
author | Edwin Cheng <[email protected]> | 2021-03-27 05:44:54 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2021-03-27 05:44:54 +0000 |
commit | a193666361f6ea9725b927a35f5baf77da713c0a (patch) | |
tree | fa916fcc7e5031df796f42521fb74d775ebdec59 /crates/hir_def/src | |
parent | c8066ebd1781a6f6f536abe3494477bd69df795a (diff) |
Basic Support Macro 2.0
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 102 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/macros.rs | 22 |
2 files changed, 85 insertions, 39 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d8fabe49b..d58135ec9 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -25,8 +25,8 @@ use crate::{ | |||
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | item_scope::{ImportType, PerNsGlobImports}, | 26 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 27 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, | 28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
29 | StructDefKind, | 29 | ModKind, StructDefKind, |
30 | }, | 30 | }, |
31 | macro_call_as_call_id, | 31 | macro_call_as_call_id, |
32 | nameres::{ | 32 | nameres::{ |
@@ -395,7 +395,7 @@ impl DefCollector<'_> { | |||
395 | /// macro_rules! foo { () => {} } | 395 | /// macro_rules! foo { () => {} } |
396 | /// use foo as bar; | 396 | /// use foo as bar; |
397 | /// ``` | 397 | /// ``` |
398 | fn define_macro( | 398 | fn define_macro_rules( |
399 | &mut self, | 399 | &mut self, |
400 | module_id: LocalModuleId, | 400 | module_id: LocalModuleId, |
401 | name: Name, | 401 | name: Name, |
@@ -430,6 +430,21 @@ impl DefCollector<'_> { | |||
430 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); | 430 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); |
431 | } | 431 | } |
432 | 432 | ||
433 | /// Define a macro 2.0 macro | ||
434 | /// | ||
435 | /// The scoped of macro 2.0 macro is equal to normal function | ||
436 | fn define_macro_def( | ||
437 | &mut self, | ||
438 | module_id: LocalModuleId, | ||
439 | name: Name, | ||
440 | macro_: MacroDefId, | ||
441 | vis: &RawVisibility, | ||
442 | ) { | ||
443 | let vis = | ||
444 | self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public); | ||
445 | self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named); | ||
446 | } | ||
447 | |||
433 | /// Define a proc macro | 448 | /// Define a proc macro |
434 | /// | 449 | /// |
435 | /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. | 450 | /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. |
@@ -1067,40 +1082,7 @@ impl ModCollector<'_, '_> { | |||
1067 | } | 1082 | } |
1068 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 1083 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
1069 | ModItem::MacroRules(id) => self.collect_macro_rules(id), | 1084 | ModItem::MacroRules(id) => self.collect_macro_rules(id), |
1070 | ModItem::MacroDef(id) => { | 1085 | ModItem::MacroDef(id) => self.collect_macro_def(id), |
1071 | let mac = &self.item_tree[id]; | ||
1072 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
1073 | |||
1074 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
1075 | // to define builtin macros, so we support at least that part. | ||
1076 | let attrs = self.item_tree.attrs( | ||
1077 | self.def_collector.db, | ||
1078 | krate, | ||
1079 | ModItem::from(id).into(), | ||
1080 | ); | ||
1081 | if attrs.by_key("rustc_builtin_macro").exists() { | ||
1082 | let krate = self.def_collector.def_map.krate; | ||
1083 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
1084 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
1085 | if let Some(macro_id) = macro_id { | ||
1086 | let vis = self | ||
1087 | .def_collector | ||
1088 | .def_map | ||
1089 | .resolve_visibility( | ||
1090 | self.def_collector.db, | ||
1091 | self.module_id, | ||
1092 | &self.item_tree[mac.visibility], | ||
1093 | ) | ||
1094 | .unwrap_or(Visibility::Public); | ||
1095 | self.def_collector.update( | ||
1096 | self.module_id, | ||
1097 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
1098 | vis, | ||
1099 | ImportType::Named, | ||
1100 | ); | ||
1101 | } | ||
1102 | } | ||
1103 | } | ||
1104 | ModItem::Impl(imp) => { | 1086 | ModItem::Impl(imp) => { |
1105 | let module = self.def_collector.def_map.module_id(self.module_id); | 1087 | let module = self.def_collector.def_map.module_id(self.module_id); |
1106 | let impl_id = | 1088 | let impl_id = |
@@ -1420,7 +1402,7 @@ impl ModCollector<'_, '_> { | |||
1420 | if attrs.by_key("rustc_builtin_macro").exists() { | 1402 | if attrs.by_key("rustc_builtin_macro").exists() { |
1421 | let krate = self.def_collector.def_map.krate; | 1403 | let krate = self.def_collector.def_map.krate; |
1422 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1404 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { |
1423 | self.def_collector.define_macro( | 1405 | self.def_collector.define_macro_rules( |
1424 | self.module_id, | 1406 | self.module_id, |
1425 | mac.name.clone(), | 1407 | mac.name.clone(), |
1426 | macro_id, | 1408 | macro_id, |
@@ -1436,7 +1418,49 @@ impl ModCollector<'_, '_> { | |||
1436 | kind: MacroDefKind::Declarative(ast_id), | 1418 | kind: MacroDefKind::Declarative(ast_id), |
1437 | local_inner: is_local_inner, | 1419 | local_inner: is_local_inner, |
1438 | }; | 1420 | }; |
1439 | self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); | 1421 | self.def_collector.define_macro_rules( |
1422 | self.module_id, | ||
1423 | mac.name.clone(), | ||
1424 | macro_id, | ||
1425 | is_export, | ||
1426 | ); | ||
1427 | } | ||
1428 | |||
1429 | fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>) { | ||
1430 | let krate = self.def_collector.def_map.krate; | ||
1431 | let mac = &self.item_tree[id]; | ||
1432 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
1433 | |||
1434 | // Case 1: bulitin macros | ||
1435 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); | ||
1436 | if attrs.by_key("rustc_builtin_macro").exists() { | ||
1437 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
1438 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
1439 | |||
1440 | if let Some(macro_id) = macro_id { | ||
1441 | self.def_collector.define_macro_def( | ||
1442 | self.module_id, | ||
1443 | mac.name.clone(), | ||
1444 | macro_id, | ||
1445 | &self.item_tree[mac.visibility], | ||
1446 | ); | ||
1447 | } | ||
1448 | return; | ||
1449 | } | ||
1450 | |||
1451 | // Case 2: normal `macro` | ||
1452 | let macro_id = MacroDefId { | ||
1453 | krate: self.def_collector.def_map.krate, | ||
1454 | kind: MacroDefKind::Declarative(ast_id), | ||
1455 | local_inner: false, | ||
1456 | }; | ||
1457 | |||
1458 | self.def_collector.define_macro_def( | ||
1459 | self.module_id, | ||
1460 | mac.name.clone(), | ||
1461 | macro_id, | ||
1462 | &self.item_tree[mac.visibility], | ||
1463 | ); | ||
1440 | } | 1464 | } |
1441 | 1465 | ||
1442 | fn collect_macro_call(&mut self, mac: &MacroCall) { | 1466 | fn collect_macro_call(&mut self, mac: &MacroCall) { |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 6d3cb8d7a..9986e99e4 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -837,3 +837,25 @@ fn collects_derive_helpers() { | |||
837 | _ => unreachable!(), | 837 | _ => unreachable!(), |
838 | } | 838 | } |
839 | } | 839 | } |
840 | |||
841 | #[test] | ||
842 | fn resolve_macro_def() { | ||
843 | check( | ||
844 | r#" | ||
845 | //- /lib.rs | ||
846 | pub macro structs($($i:ident),*) { | ||
847 | $(struct $i { field: u32 } )* | ||
848 | } | ||
849 | |||
850 | structs!(Foo); | ||
851 | |||
852 | //- /nested.rs | ||
853 | structs!(Bar, Baz); | ||
854 | "#, | ||
855 | expect![[r#" | ||
856 | crate | ||
857 | Foo: t | ||
858 | structs: m | ||
859 | "#]], | ||
860 | ); | ||
861 | } | ||