diff options
Diffstat (limited to 'crates')
22 files changed, 284 insertions, 66 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 42dc35b76..9bfcd215a 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -970,7 +970,7 @@ impl MacroDef { | |||
970 | /// defines this macro. The reasons for this is that macros are expanded | 970 | /// defines this macro. The reasons for this is that macros are expanded |
971 | /// early, in `hir_expand`, where modules simply do not exist yet. | 971 | /// early, in `hir_expand`, where modules simply do not exist yet. |
972 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | 972 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { |
973 | let krate = self.id.krate?; | 973 | let krate = self.id.krate; |
974 | let module_id = db.crate_def_map(krate).root; | 974 | let module_id = db.crate_def_map(krate).root; |
975 | Some(Module::new(Crate { id: krate }, module_id)) | 975 | Some(Module::new(Crate { id: krate }, module_id)) |
976 | } | 976 | } |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 04845037f..11ae63c31 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -110,8 +110,8 @@ impl HasSource for TypeAlias { | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | impl HasSource for MacroDef { | 112 | impl HasSource for MacroDef { |
113 | type Ast = ast::MacroRules; | 113 | type Ast = ast::Macro; |
114 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> { | 114 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> { |
115 | InFile { | 115 | InFile { |
116 | file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, | 116 | file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, |
117 | value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), | 117 | value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), |
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index a333d7aea..3efca5baa 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -157,8 +157,8 @@ impl SourceToDefCtx<'_, '_> { | |||
157 | let file_id = src.file_id.original_file(self.db.upcast()); | 157 | let file_id = src.file_id.original_file(self.db.upcast()); |
158 | let krate = self.file_to_def(file_id)?.krate; | 158 | let krate = self.file_to_def(file_id)?.krate; |
159 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); | 159 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); |
160 | let ast_id = Some(AstId::new(src.file_id, file_ast_id)); | 160 | let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); |
161 | Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false }) | 161 | Some(MacroDefId { krate, ast_id, kind, local_inner: false }) |
162 | } | 162 | } |
163 | 163 | ||
164 | pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { | 164 | pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bdba4c33e..23e2fd764 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -772,7 +772,10 @@ impl ExprCollector<'_> { | |||
772 | | ast::Item::Module(_) | 772 | | ast::Item::Module(_) |
773 | | ast::Item::MacroCall(_) => return None, | 773 | | ast::Item::MacroCall(_) => return None, |
774 | ast::Item::MacroRules(def) => { | 774 | ast::Item::MacroRules(def) => { |
775 | return Some(Either::Right(def)); | 775 | return Some(Either::Right(ast::Macro::from(def))); |
776 | } | ||
777 | ast::Item::MacroDef(def) => { | ||
778 | return Some(Either::Right(ast::Macro::from(def))); | ||
776 | } | 779 | } |
777 | }; | 780 | }; |
778 | 781 | ||
@@ -800,7 +803,7 @@ impl ExprCollector<'_> { | |||
800 | } | 803 | } |
801 | Either::Right(e) => { | 804 | Either::Right(e) => { |
802 | let mac = MacroDefId { | 805 | let mac = MacroDefId { |
803 | krate: Some(self.expander.module.krate), | 806 | krate: self.expander.module.krate, |
804 | ast_id: Some(self.expander.ast_id(&e)), | 807 | ast_id: Some(self.expander.ast_id(&e)), |
805 | kind: MacroDefKind::Declarative, | 808 | kind: MacroDefKind::Declarative, |
806 | local_inner: false, | 809 | local_inner: false, |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index a8b3fe844..62ab3b2bd 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -363,7 +363,7 @@ impl ItemInNs { | |||
363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | 363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, |
364 | ModuleDefId::BuiltinType(_) => return None, | 364 | ModuleDefId::BuiltinType(_) => return None, |
365 | }, | 365 | }, |
366 | ItemInNs::Macros(id) => return id.krate, | 366 | ItemInNs::Macros(id) => return Some(id.krate), |
367 | }) | 367 | }) |
368 | } | 368 | } |
369 | } | 369 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 1c9babf37..8cd0b18cc 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -143,6 +143,7 @@ impl ItemTree { | |||
143 | mods, | 143 | mods, |
144 | macro_calls, | 144 | macro_calls, |
145 | macro_rules, | 145 | macro_rules, |
146 | macro_defs, | ||
146 | exprs, | 147 | exprs, |
147 | vis, | 148 | vis, |
148 | generics, | 149 | generics, |
@@ -164,6 +165,7 @@ impl ItemTree { | |||
164 | mods.shrink_to_fit(); | 165 | mods.shrink_to_fit(); |
165 | macro_calls.shrink_to_fit(); | 166 | macro_calls.shrink_to_fit(); |
166 | macro_rules.shrink_to_fit(); | 167 | macro_rules.shrink_to_fit(); |
168 | macro_defs.shrink_to_fit(); | ||
167 | exprs.shrink_to_fit(); | 169 | exprs.shrink_to_fit(); |
168 | 170 | ||
169 | vis.arena.shrink_to_fit(); | 171 | vis.arena.shrink_to_fit(); |
@@ -283,6 +285,7 @@ struct ItemTreeData { | |||
283 | mods: Arena<Mod>, | 285 | mods: Arena<Mod>, |
284 | macro_calls: Arena<MacroCall>, | 286 | macro_calls: Arena<MacroCall>, |
285 | macro_rules: Arena<MacroRules>, | 287 | macro_rules: Arena<MacroRules>, |
288 | macro_defs: Arena<MacroDef>, | ||
286 | exprs: Arena<Expr>, | 289 | exprs: Arena<Expr>, |
287 | 290 | ||
288 | vis: ItemVisibilities, | 291 | vis: ItemVisibilities, |
@@ -431,6 +434,7 @@ mod_items! { | |||
431 | Mod in mods -> ast::Module, | 434 | Mod in mods -> ast::Module, |
432 | MacroCall in macro_calls -> ast::MacroCall, | 435 | MacroCall in macro_calls -> ast::MacroCall, |
433 | MacroRules in macro_rules -> ast::MacroRules, | 436 | MacroRules in macro_rules -> ast::MacroRules, |
437 | MacroDef in macro_defs -> ast::MacroDef, | ||
434 | } | 438 | } |
435 | 439 | ||
436 | macro_rules! impl_index { | 440 | macro_rules! impl_index { |
@@ -640,7 +644,7 @@ pub struct MacroCall { | |||
640 | 644 | ||
641 | #[derive(Debug, Clone, Eq, PartialEq)] | 645 | #[derive(Debug, Clone, Eq, PartialEq)] |
642 | pub struct MacroRules { | 646 | pub struct MacroRules { |
643 | /// For `macro_rules!` declarations, this is the name of the declared macro. | 647 | /// The name of the declared macro. |
644 | pub name: Name, | 648 | pub name: Name, |
645 | /// Has `#[macro_export]`. | 649 | /// Has `#[macro_export]`. |
646 | pub is_export: bool, | 650 | pub is_export: bool, |
@@ -651,6 +655,16 @@ pub struct MacroRules { | |||
651 | pub ast_id: FileAstId<ast::MacroRules>, | 655 | pub ast_id: FileAstId<ast::MacroRules>, |
652 | } | 656 | } |
653 | 657 | ||
658 | /// "Macros 2.0" macro definition. | ||
659 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
660 | pub struct MacroDef { | ||
661 | pub name: Name, | ||
662 | pub visibility: RawVisibilityId, | ||
663 | /// Has `#[rustc_builtin_macro]`. | ||
664 | pub is_builtin: bool, | ||
665 | pub ast_id: FileAstId<ast::MacroDef>, | ||
666 | } | ||
667 | |||
654 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array | 668 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array |
655 | // lengths, but we don't do much with them yet. | 669 | // lengths, but we don't do much with them yet. |
656 | #[derive(Debug, Clone, Eq, PartialEq)] | 670 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -680,7 +694,8 @@ impl ModItem { | |||
680 | | ModItem::Trait(_) | 694 | | ModItem::Trait(_) |
681 | | ModItem::Impl(_) | 695 | | ModItem::Impl(_) |
682 | | ModItem::Mod(_) | 696 | | ModItem::Mod(_) |
683 | | ModItem::MacroRules(_) => None, | 697 | | ModItem::MacroRules(_) |
698 | | ModItem::MacroDef(_) => None, | ||
684 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), | 699 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), |
685 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), | 700 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), |
686 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), | 701 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), |
@@ -708,6 +723,7 @@ impl ModItem { | |||
708 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), | 723 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), |
709 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), | 724 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), |
710 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), | 725 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), |
726 | ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(), | ||
711 | } | 727 | } |
712 | } | 728 | } |
713 | } | 729 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index b39d7fb7a..1dc06a211 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -101,7 +101,8 @@ impl Ctx { | |||
101 | | ast::Item::ExternCrate(_) | 101 | | ast::Item::ExternCrate(_) |
102 | | ast::Item::Use(_) | 102 | | ast::Item::Use(_) |
103 | | ast::Item::MacroCall(_) | 103 | | ast::Item::MacroCall(_) |
104 | | ast::Item::MacroRules(_) => {} | 104 | | ast::Item::MacroRules(_) |
105 | | ast::Item::MacroDef(_) => {} | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | let attrs = Attrs::new(item, &self.hygiene); | 108 | let attrs = Attrs::new(item, &self.hygiene); |
@@ -122,6 +123,7 @@ impl Ctx { | |||
122 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), | 123 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), |
123 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), | 124 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
124 | ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), | 125 | ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), |
126 | ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into), | ||
125 | ast::Item::ExternBlock(ast) => { | 127 | ast::Item::ExternBlock(ast) => { |
126 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | 128 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) |
127 | } | 129 | } |
@@ -561,6 +563,18 @@ impl Ctx { | |||
561 | Some(id(self.data().macro_rules.alloc(res))) | 563 | Some(id(self.data().macro_rules.alloc(res))) |
562 | } | 564 | } |
563 | 565 | ||
566 | fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> { | ||
567 | let name = m.name().map(|it| it.as_name())?; | ||
568 | let attrs = Attrs::new(m, &self.hygiene); | ||
569 | |||
570 | let ast_id = self.source_ast_id_map.ast_id(m); | ||
571 | let visibility = self.lower_visibility(m); | ||
572 | |||
573 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
574 | let res = MacroDef { name, is_builtin, ast_id, visibility }; | ||
575 | Some(id(self.data().macro_defs.alloc(res))) | ||
576 | } | ||
577 | |||
564 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { | 578 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { |
565 | block.extern_item_list().map_or(Vec::new(), |list| { | 579 | block.extern_item_list().map_or(Vec::new(), |list| { |
566 | list.extern_items() | 580 | list.extern_items() |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 85cc342c4..785895277 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -309,13 +309,13 @@ impl DefCollector<'_> { | |||
309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { | 309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { |
310 | Some((_, expander)) => MacroDefId { | 310 | Some((_, expander)) => MacroDefId { |
311 | ast_id: None, | 311 | ast_id: None, |
312 | krate: Some(self.def_map.krate), | 312 | krate: self.def_map.krate, |
313 | kind: MacroDefKind::ProcMacro(*expander), | 313 | kind: MacroDefKind::ProcMacro(*expander), |
314 | local_inner: false, | 314 | local_inner: false, |
315 | }, | 315 | }, |
316 | None => MacroDefId { | 316 | None => MacroDefId { |
317 | ast_id: None, | 317 | ast_id: None, |
318 | krate: Some(self.def_map.krate), | 318 | krate: self.def_map.krate, |
319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), | 319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), |
320 | local_inner: false, | 320 | local_inner: false, |
321 | }, | 321 | }, |
@@ -784,14 +784,6 @@ impl DefCollector<'_> { | |||
784 | directive: &DeriveDirective, | 784 | directive: &DeriveDirective, |
785 | path: &ModPath, | 785 | path: &ModPath, |
786 | ) -> Option<MacroDefId> { | 786 | ) -> 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( | 787 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 788 | self.db, |
797 | ResolveMode::Other, | 789 | ResolveMode::Other, |
@@ -976,6 +968,35 @@ impl ModCollector<'_, '_> { | |||
976 | } | 968 | } |
977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 969 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), | 970 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), |
971 | ModItem::MacroDef(id) => { | ||
972 | let mac = &self.item_tree[id]; | ||
973 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
974 | |||
975 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
976 | // to define builtin macros, so we support at least that part. | ||
977 | if mac.is_builtin { | ||
978 | let krate = self.def_collector.def_map.krate; | ||
979 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
980 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
981 | if let Some(macro_id) = macro_id { | ||
982 | let vis = self | ||
983 | .def_collector | ||
984 | .def_map | ||
985 | .resolve_visibility( | ||
986 | self.def_collector.db, | ||
987 | self.module_id, | ||
988 | &self.item_tree[mac.visibility], | ||
989 | ) | ||
990 | .unwrap_or(Visibility::Public); | ||
991 | self.def_collector.update( | ||
992 | self.module_id, | ||
993 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
994 | vis, | ||
995 | ImportType::Named, | ||
996 | ); | ||
997 | } | ||
998 | } | ||
999 | } | ||
979 | ModItem::Impl(imp) => { | 1000 | ModItem::Impl(imp) => { |
980 | let module = ModuleId { | 1001 | let module = ModuleId { |
981 | krate: self.def_collector.def_map.krate, | 1002 | krate: self.def_collector.def_map.krate, |
@@ -1280,7 +1301,7 @@ impl ModCollector<'_, '_> { | |||
1280 | } | 1301 | } |
1281 | 1302 | ||
1282 | fn collect_macro_rules(&mut self, mac: &MacroRules) { | 1303 | fn collect_macro_rules(&mut self, mac: &MacroRules) { |
1283 | let ast_id = InFile::new(self.file_id, mac.ast_id); | 1304 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); |
1284 | 1305 | ||
1285 | // Case 1: builtin macros | 1306 | // Case 1: builtin macros |
1286 | if mac.is_builtin { | 1307 | if mac.is_builtin { |
@@ -1299,7 +1320,7 @@ impl ModCollector<'_, '_> { | |||
1299 | // Case 2: normal `macro_rules!` macro | 1320 | // Case 2: normal `macro_rules!` macro |
1300 | let macro_id = MacroDefId { | 1321 | let macro_id = MacroDefId { |
1301 | ast_id: Some(ast_id), | 1322 | ast_id: Some(ast_id), |
1302 | krate: Some(self.def_collector.def_map.krate), | 1323 | krate: self.def_collector.def_map.krate, |
1303 | kind: MacroDefKind::Declarative, | 1324 | kind: MacroDefKind::Declarative, |
1304 | local_inner: mac.is_local_inner, | 1325 | local_inner: mac.is_local_inner, |
1305 | }; | 1326 | }; |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 305fca0f9..6fe2ee78a 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -633,15 +633,44 @@ pub struct bar; | |||
633 | fn expand_derive() { | 633 | fn expand_derive() { |
634 | let map = compute_crate_def_map( | 634 | let map = compute_crate_def_map( |
635 | " | 635 | " |
636 | //- /main.rs | 636 | //- /main.rs crate:main deps:core |
637 | use core::*; | ||
638 | |||
637 | #[derive(Copy, Clone)] | 639 | #[derive(Copy, Clone)] |
638 | struct Foo; | 640 | struct Foo; |
641 | |||
642 | //- /core.rs crate:core | ||
643 | #[rustc_builtin_macro] | ||
644 | pub macro Copy {} | ||
645 | |||
646 | #[rustc_builtin_macro] | ||
647 | pub macro Clone {} | ||
639 | ", | 648 | ", |
640 | ); | 649 | ); |
641 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); | 650 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); |
642 | } | 651 | } |
643 | 652 | ||
644 | #[test] | 653 | #[test] |
654 | fn resolve_builtin_derive() { | ||
655 | check( | ||
656 | r#" | ||
657 | //- /main.rs crate:main deps:core | ||
658 | use core::*; | ||
659 | |||
660 | //- /core.rs crate:core | ||
661 | #[rustc_builtin_macro] | ||
662 | pub macro Clone {} | ||
663 | |||
664 | pub trait Clone {} | ||
665 | "#, | ||
666 | expect![[r#" | ||
667 | crate | ||
668 | Clone: t m | ||
669 | "#]], | ||
670 | ); | ||
671 | } | ||
672 | |||
673 | #[test] | ||
645 | fn macro_expansion_overflow() { | 674 | fn macro_expansion_overflow() { |
646 | mark::check!(macro_expansion_overflow); | 675 | mark::check!(macro_expansion_overflow); |
647 | check( | 676 | check( |
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index 988a60d56..ad378762a 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -8,7 +8,7 @@ use syntax::{ | |||
8 | match_ast, | 8 | match_ast, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind}; | 11 | use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind}; |
12 | 12 | ||
13 | macro_rules! register_builtin { | 13 | macro_rules! register_builtin { |
14 | ( $($trait:ident => $expand:ident),* ) => { | 14 | ( $($trait:ident => $expand:ident),* ) => { |
@@ -29,16 +29,15 @@ macro_rules! register_builtin { | |||
29 | }; | 29 | }; |
30 | expander(db, id, tt) | 30 | expander(db, id, tt) |
31 | } | 31 | } |
32 | } | ||
33 | |||
34 | pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> { | ||
35 | let kind = match ident { | ||
36 | $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )* | ||
37 | _ => return None, | ||
38 | }; | ||
39 | 32 | ||
40 | Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false }) | 33 | fn find_by_name(name: &name::Name) -> Option<Self> { |
34 | match name { | ||
35 | $( id if id == &name::name![$trait] => Some(BuiltinDeriveExpander::$trait), )* | ||
36 | _ => None, | ||
37 | } | ||
38 | } | ||
41 | } | 39 | } |
40 | |||
42 | }; | 41 | }; |
43 | } | 42 | } |
44 | 43 | ||
@@ -54,6 +53,20 @@ register_builtin! { | |||
54 | PartialEq => partial_eq_expand | 53 | PartialEq => partial_eq_expand |
55 | } | 54 | } |
56 | 55 | ||
56 | pub fn find_builtin_derive( | ||
57 | ident: &name::Name, | ||
58 | krate: CrateId, | ||
59 | ast_id: AstId<ast::Macro>, | ||
60 | ) -> Option<MacroDefId> { | ||
61 | let expander = BuiltinDeriveExpander::find_by_name(ident)?; | ||
62 | Some(MacroDefId { | ||
63 | krate, | ||
64 | ast_id: Some(ast_id), | ||
65 | kind: MacroDefKind::BuiltInDerive(expander), | ||
66 | local_inner: false, | ||
67 | }) | ||
68 | } | ||
69 | |||
57 | struct BasicAdtInfo { | 70 | struct BasicAdtInfo { |
58 | name: tt::Ident, | 71 | name: tt::Ident, |
59 | type_params: usize, | 72 | type_params: usize, |
@@ -261,7 +274,7 @@ mod tests { | |||
261 | use super::*; | 274 | use super::*; |
262 | 275 | ||
263 | fn expand_builtin_derive(s: &str, name: Name) -> String { | 276 | fn expand_builtin_derive(s: &str, name: Name) -> String { |
264 | let def = find_builtin_derive(&name).unwrap(); | 277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
265 | let fixture = format!( | 278 | let fixture = format!( |
266 | r#"//- /main.rs crate:main deps:core | 279 | r#"//- /main.rs crate:main deps:core |
267 | <|> | 280 | <|> |
@@ -283,7 +296,12 @@ mod tests { | |||
283 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); | 296 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); |
284 | 297 | ||
285 | let loc = MacroCallLoc { | 298 | let loc = MacroCallLoc { |
286 | def, | 299 | def: MacroDefId { |
300 | krate: CrateId(0), | ||
301 | ast_id: None, | ||
302 | kind: MacroDefKind::BuiltInDerive(expander), | ||
303 | local_inner: false, | ||
304 | }, | ||
287 | krate: CrateId(0), | 305 | krate: CrateId(0), |
288 | kind: MacroCallKind::Attr(attr_id, name.to_string()), | 306 | kind: MacroCallKind::Attr(attr_id, name.to_string()), |
289 | }; | 307 | }; |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index bd9223825..dddbbcdac 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -63,19 +63,19 @@ macro_rules! register_builtin { | |||
63 | pub fn find_builtin_macro( | 63 | pub fn find_builtin_macro( |
64 | ident: &name::Name, | 64 | ident: &name::Name, |
65 | krate: CrateId, | 65 | krate: CrateId, |
66 | ast_id: AstId<ast::MacroRules>, | 66 | ast_id: AstId<ast::Macro>, |
67 | ) -> Option<MacroDefId> { | 67 | ) -> Option<MacroDefId> { |
68 | let kind = find_by_name(ident)?; | 68 | let kind = find_by_name(ident)?; |
69 | 69 | ||
70 | match kind { | 70 | match kind { |
71 | Either::Left(kind) => Some(MacroDefId { | 71 | Either::Left(kind) => Some(MacroDefId { |
72 | krate: Some(krate), | 72 | krate, |
73 | ast_id: Some(ast_id), | 73 | ast_id: Some(ast_id), |
74 | kind: MacroDefKind::BuiltIn(kind), | 74 | kind: MacroDefKind::BuiltIn(kind), |
75 | local_inner: false, | 75 | local_inner: false, |
76 | }), | 76 | }), |
77 | Either::Right(kind) => Some(MacroDefId { | 77 | Either::Right(kind) => Some(MacroDefId { |
78 | krate: Some(krate), | 78 | krate, |
79 | ast_id: Some(ast_id), | 79 | ast_id: Some(ast_id), |
80 | kind: MacroDefKind::BuiltInEager(kind), | 80 | kind: MacroDefKind::BuiltInEager(kind), |
81 | local_inner: false, | 81 | local_inner: false, |
@@ -515,24 +515,27 @@ mod tests { | |||
515 | fn expand_builtin_macro(ra_fixture: &str) -> String { | 515 | fn expand_builtin_macro(ra_fixture: &str) -> String { |
516 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); | 516 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); |
517 | let parsed = db.parse(file_id); | 517 | let parsed = db.parse(file_id); |
518 | let macro_rules: Vec<_> = | 518 | let mut macro_rules: Vec<_> = |
519 | parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); | 519 | parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); |
520 | let macro_calls: Vec<_> = | 520 | let mut macro_calls: Vec<_> = |
521 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); | 521 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); |
522 | 522 | ||
523 | let ast_id_map = db.ast_id_map(file_id.into()); | 523 | let ast_id_map = db.ast_id_map(file_id.into()); |
524 | 524 | ||
525 | assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); | 525 | assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); |
526 | assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); | 526 | assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); |
527 | let expander = find_by_name(¯o_rules[0].name().unwrap().as_name()).unwrap(); | 527 | let macro_rules = ast::Macro::from(macro_rules.pop().unwrap()); |
528 | let macro_call = macro_calls.pop().unwrap(); | ||
529 | |||
530 | let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); | ||
528 | 531 | ||
529 | let krate = CrateId(0); | 532 | let krate = CrateId(0); |
530 | let file_id = match expander { | 533 | let file_id = match expander { |
531 | Either::Left(expander) => { | 534 | Either::Left(expander) => { |
532 | // the first one should be a macro_rules | 535 | // the first one should be a macro_rules |
533 | let def = MacroDefId { | 536 | let def = MacroDefId { |
534 | krate: Some(CrateId(0)), | 537 | krate: CrateId(0), |
535 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules[0]))), | 538 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), |
536 | kind: MacroDefKind::BuiltIn(expander), | 539 | kind: MacroDefKind::BuiltIn(expander), |
537 | local_inner: false, | 540 | local_inner: false, |
538 | }; | 541 | }; |
@@ -542,7 +545,7 @@ mod tests { | |||
542 | krate, | 545 | krate, |
543 | kind: MacroCallKind::FnLike(AstId::new( | 546 | kind: MacroCallKind::FnLike(AstId::new( |
544 | file_id.into(), | 547 | file_id.into(), |
545 | ast_id_map.ast_id(¯o_calls[0]), | 548 | ast_id_map.ast_id(¯o_call), |
546 | )), | 549 | )), |
547 | }; | 550 | }; |
548 | 551 | ||
@@ -552,13 +555,13 @@ mod tests { | |||
552 | Either::Right(expander) => { | 555 | Either::Right(expander) => { |
553 | // the first one should be a macro_rules | 556 | // the first one should be a macro_rules |
554 | let def = MacroDefId { | 557 | let def = MacroDefId { |
555 | krate: Some(krate), | 558 | krate, |
556 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules[0]))), | 559 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), |
557 | kind: MacroDefKind::BuiltInEager(expander), | 560 | kind: MacroDefKind::BuiltInEager(expander), |
558 | local_inner: false, | 561 | local_inner: false, |
559 | }; | 562 | }; |
560 | 563 | ||
561 | let args = macro_calls[0].token_tree().unwrap(); | 564 | let args = macro_call.token_tree().unwrap(); |
562 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; | 565 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; |
563 | 566 | ||
564 | let arg_id = db.intern_eager_expansion({ | 567 | let arg_id = db.intern_eager_expansion({ |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 11b5b98c8..4477d867f 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -129,7 +129,10 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | |||
129 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 129 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
130 | match id.kind { | 130 | match id.kind { |
131 | MacroDefKind::Declarative => { | 131 | MacroDefKind::Declarative => { |
132 | let macro_call = id.ast_id?.to_node(db); | 132 | let macro_call = match id.ast_id?.to_node(db) { |
133 | syntax::ast::Macro::MacroRules(mac) => mac, | ||
134 | syntax::ast::Macro::MacroDef(_) => return None, | ||
135 | }; | ||
133 | let arg = macro_call.token_tree()?; | 136 | let arg = macro_call.token_tree()?; |
134 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 137 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { |
135 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | 138 | log::warn!("fail on macro_def to token tree: {:#?}", arg); |
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 5d3fa0518..7ab0a5e52 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -29,8 +29,8 @@ impl Hygiene { | |||
29 | MacroCallId::LazyMacro(id) => { | 29 | MacroCallId::LazyMacro(id) => { |
30 | let loc = db.lookup_intern_macro(id); | 30 | let loc = db.lookup_intern_macro(id); |
31 | match loc.def.kind { | 31 | match loc.def.kind { |
32 | MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), | 32 | MacroDefKind::Declarative => (Some(loc.def.krate), loc.def.local_inner), |
33 | MacroDefKind::BuiltIn(_) => (loc.def.krate, false), | 33 | MacroDefKind::BuiltIn(_) => (Some(loc.def.krate), false), |
34 | MacroDefKind::BuiltInDerive(_) => (None, false), | 34 | MacroDefKind::BuiltInDerive(_) => (None, false), |
35 | MacroDefKind::BuiltInEager(_) => (None, false), | 35 | MacroDefKind::BuiltInEager(_) => (None, false), |
36 | MacroDefKind::ProcMacro(_) => (None, false), | 36 | MacroDefKind::ProcMacro(_) => (None, false), |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index ae3086a95..d486186e5 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -145,7 +145,10 @@ impl HirFileId { | |||
145 | let arg_tt = loc.kind.arg(db)?; | 145 | let arg_tt = loc.kind.arg(db)?; |
146 | 146 | ||
147 | let def = loc.def.ast_id.and_then(|id| { | 147 | let def = loc.def.ast_id.and_then(|id| { |
148 | let def_tt = id.to_node(db).token_tree()?; | 148 | let def_tt = match id.to_node(db) { |
149 | ast::Macro::MacroRules(mac) => mac.token_tree()?, | ||
150 | ast::Macro::MacroDef(_) => return None, | ||
151 | }; | ||
149 | Some(InFile::new(id.file_id, def_tt)) | 152 | Some(InFile::new(id.file_id, def_tt)) |
150 | }); | 153 | }); |
151 | 154 | ||
@@ -221,14 +224,8 @@ impl From<EagerMacroId> for MacroCallId { | |||
221 | 224 | ||
222 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 225 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
223 | pub struct MacroDefId { | 226 | pub struct MacroDefId { |
224 | // FIXME: krate and ast_id are currently optional because we don't have a | 227 | pub krate: CrateId, |
225 | // definition location for built-in derives. There is one, though: the | 228 | pub ast_id: Option<AstId<ast::Macro>>, |
226 | // standard library defines them. The problem is that it uses the new | ||
227 | // `macro` syntax for this, which we don't support yet. As soon as we do | ||
228 | // (which will probably require touching this code), we can instead use | ||
229 | // that (and also remove the hacks for resolving built-in derives). | ||
230 | pub krate: Option<CrateId>, | ||
231 | pub ast_id: Option<AstId<ast::MacroRules>>, | ||
232 | pub kind: MacroDefKind, | 229 | pub kind: MacroDefKind, |
233 | 230 | ||
234 | pub local_inner: bool, | 231 | pub local_inner: bool, |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index de97ec3c2..a7656b864 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -686,6 +686,8 @@ mod clone { | |||
686 | trait Clone { | 686 | trait Clone { |
687 | fn clone(&self) -> Self; | 687 | fn clone(&self) -> Self; |
688 | } | 688 | } |
689 | #[rustc_builtin_macro] | ||
690 | macro Clone {} | ||
689 | } | 691 | } |
690 | "#, | 692 | "#, |
691 | ); | 693 | ); |
@@ -702,6 +704,8 @@ mod clone { | |||
702 | trait Clone { | 704 | trait Clone { |
703 | fn clone(&self) -> Self; | 705 | fn clone(&self) -> Self; |
704 | } | 706 | } |
707 | #[rustc_builtin_macro] | ||
708 | macro Clone {} | ||
705 | } | 709 | } |
706 | #[derive(Clone)] | 710 | #[derive(Clone)] |
707 | pub struct S; | 711 | pub struct S; |
@@ -737,6 +741,8 @@ mod clone { | |||
737 | trait Clone { | 741 | trait Clone { |
738 | fn clone(&self) -> Self; | 742 | fn clone(&self) -> Self; |
739 | } | 743 | } |
744 | #[rustc_builtin_macro] | ||
745 | macro Clone {} | ||
740 | } | 746 | } |
741 | "#, | 747 | "#, |
742 | ); | 748 | ); |
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 529004878..68c628d31 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs | |||
@@ -221,6 +221,8 @@ struct Foo<|>; | |||
221 | mod marker { | 221 | mod marker { |
222 | trait Copy {} | 222 | trait Copy {} |
223 | } | 223 | } |
224 | #[rustc_builtin_macro] | ||
225 | macro Copy {} | ||
224 | "#, | 226 | "#, |
225 | ); | 227 | ); |
226 | } | 228 | } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 0569cf1e5..3530a5fdb 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -38,6 +38,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
38 | <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> | 38 | <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> |
39 | <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 39 | <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
40 | 40 | ||
41 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span> | ||
42 | <span class="keyword">macro</span> <span class="unresolved_reference declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> | ||
43 | |||
41 | <span class="comment">// Needed for function consuming vs normal</span> | 44 | <span class="comment">// Needed for function consuming vs normal</span> |
42 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span> | 45 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span> |
43 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span> | 46 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span> |
@@ -119,7 +122,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
119 | <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> | 122 | <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> |
120 | <span class="punctuation">}</span> | 123 | <span class="punctuation">}</span> |
121 | 124 | ||
122 | <span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="unresolved_reference">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 125 | <span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="macro">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
123 | 126 | ||
124 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 127 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
125 | <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 128 | <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 1dc018a16..f53d2c3ba 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -12,6 +12,9 @@ fn test_highlighting() { | |||
12 | use inner::{self as inner_mod}; | 12 | use inner::{self as inner_mod}; |
13 | mod inner {} | 13 | mod inner {} |
14 | 14 | ||
15 | #[rustc_builtin_macro] | ||
16 | macro Copy {} | ||
17 | |||
15 | // Needed for function consuming vs normal | 18 | // Needed for function consuming vs normal |
16 | pub mod marker { | 19 | pub mod marker { |
17 | #[lang = "copy"] | 20 | #[lang = "copy"] |
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 7844f9ed6..70c568ea1 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs | |||
@@ -19,8 +19,8 @@ pub use self::{ | |||
19 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, | 19 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, |
20 | generated::{nodes::*, tokens::*}, | 20 | generated::{nodes::*, tokens::*}, |
21 | node_ext::{ | 21 | node_ext::{ |
22 | AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, | 22 | AttrKind, FieldKind, Macro, NameOrNameRef, PathSegmentKind, SelfParamKind, |
23 | StructKind, TypeBoundKind, VisibilityKind, | 23 | SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, |
24 | }, | 24 | }, |
25 | token_ext::*, | 25 | token_ext::*, |
26 | traits::*, | 26 | traits::*, |
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 0ad75214f..6eae323f4 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs | |||
@@ -286,6 +286,18 @@ impl MacroRules { | |||
286 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } | 286 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } |
287 | } | 287 | } |
288 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 288 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
289 | pub struct MacroDef { | ||
290 | pub(crate) syntax: SyntaxNode, | ||
291 | } | ||
292 | impl ast::AttrsOwner for MacroDef {} | ||
293 | impl ast::NameOwner for MacroDef {} | ||
294 | impl ast::VisibilityOwner for MacroDef {} | ||
295 | impl MacroDef { | ||
296 | pub fn macro_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![macro]) } | ||
297 | pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
298 | pub fn body(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
299 | } | ||
300 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
289 | pub struct Module { | 301 | pub struct Module { |
290 | pub(crate) syntax: SyntaxNode, | 302 | pub(crate) syntax: SyntaxNode, |
291 | } | 303 | } |
@@ -1332,6 +1344,7 @@ pub enum Item { | |||
1332 | Impl(Impl), | 1344 | Impl(Impl), |
1333 | MacroCall(MacroCall), | 1345 | MacroCall(MacroCall), |
1334 | MacroRules(MacroRules), | 1346 | MacroRules(MacroRules), |
1347 | MacroDef(MacroDef), | ||
1335 | Module(Module), | 1348 | Module(Module), |
1336 | Static(Static), | 1349 | Static(Static), |
1337 | Struct(Struct), | 1350 | Struct(Struct), |
@@ -1689,6 +1702,17 @@ impl AstNode for MacroRules { | |||
1689 | } | 1702 | } |
1690 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1703 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1691 | } | 1704 | } |
1705 | impl AstNode for MacroDef { | ||
1706 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF } | ||
1707 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1708 | if Self::can_cast(syntax.kind()) { | ||
1709 | Some(Self { syntax }) | ||
1710 | } else { | ||
1711 | None | ||
1712 | } | ||
1713 | } | ||
1714 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
1715 | } | ||
1692 | impl AstNode for Module { | 1716 | impl AstNode for Module { |
1693 | fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } | 1717 | fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } |
1694 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1718 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -3086,6 +3110,9 @@ impl From<MacroCall> for Item { | |||
3086 | impl From<MacroRules> for Item { | 3110 | impl From<MacroRules> for Item { |
3087 | fn from(node: MacroRules) -> Item { Item::MacroRules(node) } | 3111 | fn from(node: MacroRules) -> Item { Item::MacroRules(node) } |
3088 | } | 3112 | } |
3113 | impl From<MacroDef> for Item { | ||
3114 | fn from(node: MacroDef) -> Item { Item::MacroDef(node) } | ||
3115 | } | ||
3089 | impl From<Module> for Item { | 3116 | impl From<Module> for Item { |
3090 | fn from(node: Module) -> Item { Item::Module(node) } | 3117 | fn from(node: Module) -> Item { Item::Module(node) } |
3091 | } | 3118 | } |
@@ -3111,7 +3138,7 @@ impl AstNode for Item { | |||
3111 | fn can_cast(kind: SyntaxKind) -> bool { | 3138 | fn can_cast(kind: SyntaxKind) -> bool { |
3112 | match kind { | 3139 | match kind { |
3113 | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES | 3140 | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES |
3114 | | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, | 3141 | | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, |
3115 | _ => false, | 3142 | _ => false, |
3116 | } | 3143 | } |
3117 | } | 3144 | } |
@@ -3125,6 +3152,7 @@ impl AstNode for Item { | |||
3125 | IMPL => Item::Impl(Impl { syntax }), | 3152 | IMPL => Item::Impl(Impl { syntax }), |
3126 | MACRO_CALL => Item::MacroCall(MacroCall { syntax }), | 3153 | MACRO_CALL => Item::MacroCall(MacroCall { syntax }), |
3127 | MACRO_RULES => Item::MacroRules(MacroRules { syntax }), | 3154 | MACRO_RULES => Item::MacroRules(MacroRules { syntax }), |
3155 | MACRO_DEF => Item::MacroDef(MacroDef { syntax }), | ||
3128 | MODULE => Item::Module(Module { syntax }), | 3156 | MODULE => Item::Module(Module { syntax }), |
3129 | STATIC => Item::Static(Static { syntax }), | 3157 | STATIC => Item::Static(Static { syntax }), |
3130 | STRUCT => Item::Struct(Struct { syntax }), | 3158 | STRUCT => Item::Struct(Struct { syntax }), |
@@ -3146,6 +3174,7 @@ impl AstNode for Item { | |||
3146 | Item::Impl(it) => &it.syntax, | 3174 | Item::Impl(it) => &it.syntax, |
3147 | Item::MacroCall(it) => &it.syntax, | 3175 | Item::MacroCall(it) => &it.syntax, |
3148 | Item::MacroRules(it) => &it.syntax, | 3176 | Item::MacroRules(it) => &it.syntax, |
3177 | Item::MacroDef(it) => &it.syntax, | ||
3149 | Item::Module(it) => &it.syntax, | 3178 | Item::Module(it) => &it.syntax, |
3150 | Item::Static(it) => &it.syntax, | 3179 | Item::Static(it) => &it.syntax, |
3151 | Item::Struct(it) => &it.syntax, | 3180 | Item::Struct(it) => &it.syntax, |
@@ -3615,6 +3644,11 @@ impl std::fmt::Display for MacroRules { | |||
3615 | std::fmt::Display::fmt(self.syntax(), f) | 3644 | std::fmt::Display::fmt(self.syntax(), f) |
3616 | } | 3645 | } |
3617 | } | 3646 | } |
3647 | impl std::fmt::Display for MacroDef { | ||
3648 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
3649 | std::fmt::Display::fmt(self.syntax(), f) | ||
3650 | } | ||
3651 | } | ||
3618 | impl std::fmt::Display for Module { | 3652 | impl std::fmt::Display for Module { |
3619 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 3653 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
3620 | std::fmt::Display::fmt(self.syntax(), f) | 3654 | std::fmt::Display::fmt(self.syntax(), f) |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index c59a29eab..40dec3c7f 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | use std::fmt; | 4 | use std::fmt; |
5 | 5 | ||
6 | use ast::AttrsOwner; | ||
6 | use itertools::Itertools; | 7 | use itertools::Itertools; |
7 | use parser::SyntaxKind; | 8 | use parser::SyntaxKind; |
8 | 9 | ||
@@ -31,6 +32,57 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { | |||
31 | node.green().children().next().and_then(|it| it.into_token()).unwrap().text() | 32 | node.green().children().next().and_then(|it| it.into_token()).unwrap().text() |
32 | } | 33 | } |
33 | 34 | ||
35 | pub enum Macro { | ||
36 | MacroRules(ast::MacroRules), | ||
37 | MacroDef(ast::MacroDef), | ||
38 | } | ||
39 | |||
40 | impl From<ast::MacroRules> for Macro { | ||
41 | fn from(it: ast::MacroRules) -> Self { | ||
42 | Macro::MacroRules(it) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | impl From<ast::MacroDef> for Macro { | ||
47 | fn from(it: ast::MacroDef) -> Self { | ||
48 | Macro::MacroDef(it) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl AstNode for Macro { | ||
53 | fn can_cast(kind: SyntaxKind) -> bool { | ||
54 | match kind { | ||
55 | SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF => true, | ||
56 | _ => false, | ||
57 | } | ||
58 | } | ||
59 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
60 | let res = match syntax.kind() { | ||
61 | SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }), | ||
62 | SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }), | ||
63 | _ => return None, | ||
64 | }; | ||
65 | Some(res) | ||
66 | } | ||
67 | fn syntax(&self) -> &SyntaxNode { | ||
68 | match self { | ||
69 | Macro::MacroRules(it) => it.syntax(), | ||
70 | Macro::MacroDef(it) => it.syntax(), | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | impl NameOwner for Macro { | ||
76 | fn name(&self) -> Option<ast::Name> { | ||
77 | match self { | ||
78 | Macro::MacroRules(mac) => mac.name(), | ||
79 | Macro::MacroDef(mac) => mac.name(), | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | impl AttrsOwner for Macro {} | ||
85 | |||
34 | #[derive(Debug, Clone, PartialEq, Eq)] | 86 | #[derive(Debug, Clone, PartialEq, Eq)] |
35 | pub enum AttrKind { | 87 | pub enum AttrKind { |
36 | Inner, | 88 | Inner, |
@@ -462,4 +514,6 @@ impl ast::DocCommentsOwner for ast::Const {} | |||
462 | impl ast::DocCommentsOwner for ast::TypeAlias {} | 514 | impl ast::DocCommentsOwner for ast::TypeAlias {} |
463 | impl ast::DocCommentsOwner for ast::Impl {} | 515 | impl ast::DocCommentsOwner for ast::Impl {} |
464 | impl ast::DocCommentsOwner for ast::MacroRules {} | 516 | impl ast::DocCommentsOwner for ast::MacroRules {} |
517 | impl ast::DocCommentsOwner for ast::MacroDef {} | ||
518 | impl ast::DocCommentsOwner for ast::Macro {} | ||
465 | impl ast::DocCommentsOwner for ast::Use {} | 519 | impl ast::DocCommentsOwner for ast::Use {} |
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs index d33bde30c..391647fc6 100644 --- a/crates/syntax/src/display.rs +++ b/crates/syntax/src/display.rs | |||
@@ -76,8 +76,20 @@ pub fn type_label(node: &ast::TypeAlias) -> String { | |||
76 | label.trim().to_owned() | 76 | label.trim().to_owned() |
77 | } | 77 | } |
78 | 78 | ||
79 | pub fn macro_label(node: &ast::MacroRules) -> String { | 79 | pub fn macro_label(node: &ast::Macro) -> String { |
80 | let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); | 80 | let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); |
81 | let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; | 81 | match node { |
82 | format!("{}macro_rules! {}", vis, name) | 82 | ast::Macro::MacroRules(node) => { |
83 | let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; | ||
84 | format!("{}macro_rules! {}", vis, name) | ||
85 | } | ||
86 | ast::Macro::MacroDef(node) => { | ||
87 | let mut s = String::new(); | ||
88 | if let Some(vis) = node.visibility() { | ||
89 | format_to!(s, "{} ", vis); | ||
90 | } | ||
91 | format_to!(s, "macro {}", name); | ||
92 | s | ||
93 | } | ||
94 | } | ||
83 | } | 95 | } |