aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-16 16:52:46 +0000
committerGitHub <[email protected]>2020-12-16 16:52:46 +0000
commit63bbdb31e5148c804bbf940963c9c8f3481ad258 (patch)
tree2732cd2c3878257d9b55447830bc824447332c98
parent423f3872246f1a67b49e248f3437cb46fdfc8138 (diff)
parentd34611633b3b2404188b9e12b08c5def589808c2 (diff)
Merge #6897
6897: Basic support for macros 2.0 r=jonas-schievink a=jonas-schievink This adds support for (built-in-only) macros 2.0, and removes some hacks used for builtin derives, which are declared via macros 2.0 in libcore. First steps for https://github.com/rust-analyzer/rust-analyzer/issues/2248. Blocked on https://github.com/rust-analyzer/ungrammar/pull/16. Co-authored-by: Jonas Schievink <[email protected]> Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r--Cargo.lock4
-rw-r--r--crates/hir/src/code_model.rs2
-rw-r--r--crates/hir/src/has_source.rs4
-rw-r--r--crates/hir/src/semantics/source_to_def.rs4
-rw-r--r--crates/hir_def/src/body/lower.rs7
-rw-r--r--crates/hir_def/src/item_scope.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs20
-rw-r--r--crates/hir_def/src/item_tree/lower.rs16
-rw-r--r--crates/hir_def/src/nameres/collector.rs45
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs31
-rw-r--r--crates/hir_expand/src/builtin_derive.rs40
-rw-r--r--crates/hir_expand/src/builtin_macro.rs27
-rw-r--r--crates/hir_expand/src/db.rs5
-rw-r--r--crates/hir_expand/src/hygiene.rs4
-rw-r--r--crates/hir_expand/src/lib.rs15
-rw-r--r--crates/hir_ty/src/tests/macros.rs6
-rw-r--r--crates/ide/src/goto_implementation.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html5
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs3
-rw-r--r--crates/syntax/src/ast.rs4
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs36
-rw-r--r--crates/syntax/src/ast/node_ext.rs54
-rw-r--r--crates/syntax/src/display.rs18
23 files changed, 286 insertions, 68 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ff2c33f45..e44b7d1d9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1827,9 +1827,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1827 1827
1828[[package]] 1828[[package]]
1829name = "ungrammar" 1829name = "ungrammar"
1830version = "1.2.2" 1830version = "1.3.0"
1831source = "registry+https://github.com/rust-lang/crates.io-index" 1831source = "registry+https://github.com/rust-lang/crates.io-index"
1832checksum = "873186a460627379e7e28880a0d33b729c205634f6f021321f50b323235e62d7" 1832checksum = "7311ee93faac43aa9da26b043eb244092a29a3078c79af9396f63f800cc3a59a"
1833 1833
1834[[package]] 1834[[package]]
1835name = "unicase" 1835name = "unicase"
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}
112impl HasSource for MacroDef { 112impl 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
436macro_rules! impl_index { 440macro_rules! impl_index {
@@ -640,7 +644,7 @@ pub struct MacroCall {
640 644
641#[derive(Debug, Clone, Eq, PartialEq)] 645#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules { 646pub 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)]
660pub 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;
633fn expand_derive() { 633fn 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]
654fn resolve_builtin_derive() {
655 check(
656 r#"
657//- /main.rs crate:main deps:core
658use core::*;
659
660//- /core.rs crate:core
661#[rustc_builtin_macro]
662pub macro Clone {}
663
664pub trait Clone {}
665"#,
666 expect![[r#"
667 crate
668 Clone: t m
669 "#]],
670 );
671}
672
673#[test]
645fn macro_expansion_overflow() { 674fn 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
11use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind}; 11use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind};
12 12
13macro_rules! register_builtin { 13macro_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
56pub 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
57struct BasicAdtInfo { 70struct 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 {
63pub fn find_builtin_macro( 63pub 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(&macro_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(&macro_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(&macro_rules[0]))), 538 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_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(&macro_calls[0]), 548 ast_id_map.ast_id(&macro_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(&macro_rules[0]))), 559 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_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> {
129fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 129fn 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)]
223pub struct MacroDefId { 226pub 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)]
707pub struct S; 711pub 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<|>;
221mod marker { 221mod marker {
222 trait Copy {} 222 trait Copy {}
223} 223}
224#[rustc_builtin_macro]
225macro 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">-&gt;</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">-&gt;</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() {
12use inner::{self as inner_mod}; 12use inner::{self as inner_mod};
13mod inner {} 13mod inner {}
14 14
15#[rustc_builtin_macro]
16macro Copy {}
17
15// Needed for function consuming vs normal 18// Needed for function consuming vs normal
16pub mod marker { 19pub 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)]
289pub struct MacroDef {
290 pub(crate) syntax: SyntaxNode,
291}
292impl ast::AttrsOwner for MacroDef {}
293impl ast::NameOwner for MacroDef {}
294impl ast::VisibilityOwner for MacroDef {}
295impl 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)]
289pub struct Module { 301pub 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}
1705impl 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}
1692impl AstNode for Module { 1716impl 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 {
3086impl From<MacroRules> for Item { 3110impl From<MacroRules> for Item {
3087 fn from(node: MacroRules) -> Item { Item::MacroRules(node) } 3111 fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
3088} 3112}
3113impl From<MacroDef> for Item {
3114 fn from(node: MacroDef) -> Item { Item::MacroDef(node) }
3115}
3089impl From<Module> for Item { 3116impl 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}
3647impl 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}
3618impl std::fmt::Display for Module { 3652impl 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
4use std::fmt; 4use std::fmt;
5 5
6use ast::AttrsOwner;
6use itertools::Itertools; 7use itertools::Itertools;
7use parser::SyntaxKind; 8use 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
35pub enum Macro {
36 MacroRules(ast::MacroRules),
37 MacroDef(ast::MacroDef),
38}
39
40impl From<ast::MacroRules> for Macro {
41 fn from(it: ast::MacroRules) -> Self {
42 Macro::MacroRules(it)
43 }
44}
45
46impl From<ast::MacroDef> for Macro {
47 fn from(it: ast::MacroDef) -> Self {
48 Macro::MacroDef(it)
49 }
50}
51
52impl 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
75impl 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
84impl AttrsOwner for Macro {}
85
34#[derive(Debug, Clone, PartialEq, Eq)] 86#[derive(Debug, Clone, PartialEq, Eq)]
35pub enum AttrKind { 87pub enum AttrKind {
36 Inner, 88 Inner,
@@ -462,4 +514,6 @@ impl ast::DocCommentsOwner for ast::Const {}
462impl ast::DocCommentsOwner for ast::TypeAlias {} 514impl ast::DocCommentsOwner for ast::TypeAlias {}
463impl ast::DocCommentsOwner for ast::Impl {} 515impl ast::DocCommentsOwner for ast::Impl {}
464impl ast::DocCommentsOwner for ast::MacroRules {} 516impl ast::DocCommentsOwner for ast::MacroRules {}
517impl ast::DocCommentsOwner for ast::MacroDef {}
518impl ast::DocCommentsOwner for ast::Macro {}
465impl ast::DocCommentsOwner for ast::Use {} 519impl 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
79pub fn macro_label(node: &ast::MacroRules) -> String { 79pub 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}