diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/has_source.rs | 4 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 20 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 29 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 19 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 5 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/syntax/src/ast.rs | 4 | ||||
-rw-r--r-- | crates/syntax/src/ast/generated/nodes.rs | 36 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 54 | ||||
-rw-r--r-- | crates/syntax/src/display.rs | 18 |
13 files changed, 194 insertions, 25 deletions
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 107ad0690..ecf3194c6 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..d499ae340 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -157,7 +157,7 @@ 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: Some(krate), ast_id, kind, local_inner: false }) |
162 | } | 162 | } |
163 | 163 | ||
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bdba4c33e..e4bf5603c 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 | ||
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..c2f741060 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -976,6 +976,33 @@ impl ModCollector<'_, '_> { | |||
976 | } | 976 | } |
977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), | 978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), |
979 | ModItem::MacroDef(id) => { | ||
980 | let mac = &self.item_tree[id]; | ||
981 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
982 | |||
983 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
984 | // to define builtin macros, so we support at least that part. | ||
985 | if mac.is_builtin { | ||
986 | let krate = self.def_collector.def_map.krate; | ||
987 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | ||
988 | let vis = self | ||
989 | .def_collector | ||
990 | .def_map | ||
991 | .resolve_visibility( | ||
992 | self.def_collector.db, | ||
993 | self.module_id, | ||
994 | &self.item_tree[mac.visibility], | ||
995 | ) | ||
996 | .unwrap_or(Visibility::Public); | ||
997 | self.def_collector.update( | ||
998 | self.module_id, | ||
999 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
1000 | vis, | ||
1001 | ImportType::Named, | ||
1002 | ); | ||
1003 | } | ||
1004 | } | ||
1005 | } | ||
979 | ModItem::Impl(imp) => { | 1006 | ModItem::Impl(imp) => { |
980 | let module = ModuleId { | 1007 | let module = ModuleId { |
981 | krate: self.def_collector.def_map.krate, | 1008 | krate: self.def_collector.def_map.krate, |
@@ -1280,7 +1307,7 @@ impl ModCollector<'_, '_> { | |||
1280 | } | 1307 | } |
1281 | 1308 | ||
1282 | fn collect_macro_rules(&mut self, mac: &MacroRules) { | 1309 | fn collect_macro_rules(&mut self, mac: &MacroRules) { |
1283 | let ast_id = InFile::new(self.file_id, mac.ast_id); | 1310 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); |
1284 | 1311 | ||
1285 | // Case 1: builtin macros | 1312 | // Case 1: builtin macros |
1286 | if mac.is_builtin { | 1313 | if mac.is_builtin { |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index bd9223825..df82cf8e6 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -63,7 +63,7 @@ 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 | ||
@@ -515,16 +515,19 @@ 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 { |
@@ -532,7 +535,7 @@ mod tests { | |||
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: Some(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 | ||
@@ -553,12 +556,12 @@ mod tests { | |||
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: Some(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/lib.rs b/crates/hir_expand/src/lib.rs index ae3086a95..55f026c7b 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 | ||
@@ -228,7 +231,7 @@ pub struct MacroDefId { | |||
228 | // (which will probably require touching this code), we can instead use | 231 | // (which will probably require touching this code), we can instead use |
229 | // that (and also remove the hacks for resolving built-in derives). | 232 | // that (and also remove the hacks for resolving built-in derives). |
230 | pub krate: Option<CrateId>, | 233 | pub krate: Option<CrateId>, |
231 | pub ast_id: Option<AstId<ast::MacroRules>>, | 234 | pub ast_id: Option<AstId<ast::Macro>>, |
232 | pub kind: MacroDefKind, | 235 | pub kind: MacroDefKind, |
233 | 236 | ||
234 | pub local_inner: bool, | 237 | pub local_inner: bool, |
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 | } |