aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src/db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand/src/db.rs')
-rw-r--r--crates/ra_hir_expand/src/db.rs66
1 files changed, 52 insertions, 14 deletions
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index 8e46fa177..2e12e126f 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -6,17 +6,18 @@ use mbe::MacroRules;
6use ra_db::{salsa, SourceDatabase}; 6use ra_db::{salsa, SourceDatabase};
7use ra_parser::FragmentKind; 7use ra_parser::FragmentKind;
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{AstNode, Parse, SyntaxNode}; 9use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode};
10 10
11use crate::{ 11use crate::{
12 ast_id_map::AstIdMap, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, 12 ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr,
13 MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, MacroFileKind, 13 MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile,
14}; 14};
15 15
16#[derive(Debug, Clone, Eq, PartialEq)] 16#[derive(Debug, Clone, Eq, PartialEq)]
17pub enum TokenExpander { 17pub enum TokenExpander {
18 MacroRules(mbe::MacroRules), 18 MacroRules(mbe::MacroRules),
19 Builtin(BuiltinFnLikeExpander), 19 Builtin(BuiltinFnLikeExpander),
20 BuiltinDerive(BuiltinDeriveExpander),
20} 21}
21 22
22impl TokenExpander { 23impl TokenExpander {
@@ -29,6 +30,7 @@ impl TokenExpander {
29 match self { 30 match self {
30 TokenExpander::MacroRules(it) => it.expand(tt), 31 TokenExpander::MacroRules(it) => it.expand(tt),
31 TokenExpander::Builtin(it) => it.expand(db, id, tt), 32 TokenExpander::Builtin(it) => it.expand(db, id, tt),
33 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt),
32 } 34 }
33 } 35 }
34 36
@@ -36,13 +38,15 @@ impl TokenExpander {
36 match self { 38 match self {
37 TokenExpander::MacroRules(it) => it.map_id_down(id), 39 TokenExpander::MacroRules(it) => it.map_id_down(id),
38 TokenExpander::Builtin(..) => id, 40 TokenExpander::Builtin(..) => id,
41 TokenExpander::BuiltinDerive(..) => id,
39 } 42 }
40 } 43 }
41 44
42 pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { 45 pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) {
43 match self { 46 match self {
44 TokenExpander::MacroRules(it) => it.map_id_up(id), 47 TokenExpander::MacroRules(it) => it.map_id_up(id),
45 TokenExpander::Builtin(..) => (id, mbe::Origin::Def), 48 TokenExpander::Builtin(..) => (id, mbe::Origin::Call),
49 TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call),
46 } 50 }
47 } 51 }
48} 52}
@@ -76,7 +80,7 @@ pub(crate) fn macro_def(
76) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 80) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
77 match id.kind { 81 match id.kind {
78 MacroDefKind::Declarative => { 82 MacroDefKind::Declarative => {
79 let macro_call = id.ast_id.to_node(db); 83 let macro_call = id.ast_id?.to_node(db);
80 let arg = macro_call.token_tree()?; 84 let arg = macro_call.token_tree()?;
81 let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { 85 let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
82 log::warn!("fail on macro_def to token tree: {:#?}", arg); 86 log::warn!("fail on macro_def to token tree: {:#?}", arg);
@@ -89,7 +93,10 @@ pub(crate) fn macro_def(
89 Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) 93 Some(Arc::new((TokenExpander::MacroRules(rules), tmap)))
90 } 94 }
91 MacroDefKind::BuiltIn(expander) => { 95 MacroDefKind::BuiltIn(expander) => {
92 Some(Arc::new((TokenExpander::Builtin(expander.clone()), mbe::TokenMap::default()))) 96 Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default())))
97 }
98 MacroDefKind::BuiltInDerive(expander) => {
99 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default())))
93 } 100 }
94 } 101 }
95} 102}
@@ -99,9 +106,8 @@ pub(crate) fn macro_arg(
99 id: MacroCallId, 106 id: MacroCallId,
100) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { 107) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> {
101 let loc = db.lookup_intern_macro(id); 108 let loc = db.lookup_intern_macro(id);
102 let macro_call = loc.ast_id.to_node(db); 109 let arg = loc.kind.arg(db)?;
103 let arg = macro_call.token_tree()?; 110 let (tt, tmap) = mbe::syntax_node_to_token_tree(&arg)?;
104 let (tt, tmap) = mbe::ast_to_token_tree(&arg)?;
105 Some(Arc::new((tt, tmap))) 111 Some(Arc::new((tt, tmap)))
106} 112}
107 113
@@ -148,11 +154,43 @@ pub(crate) fn parse_macro(
148 }) 154 })
149 .ok()?; 155 .ok()?;
150 156
151 let fragment_kind = match macro_file.macro_file_kind { 157 let fragment_kind = to_fragment_kind(db, macro_call_id);
152 MacroFileKind::Items => FragmentKind::Items, 158
153 MacroFileKind::Expr => FragmentKind::Expr,
154 MacroFileKind::Statements => FragmentKind::Statements,
155 };
156 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; 159 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?;
157 Some((parse, Arc::new(rev_token_map))) 160 Some((parse, Arc::new(rev_token_map)))
158} 161}
162
163/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
164/// FIXME: Not completed
165fn to_fragment_kind(db: &dyn AstDatabase, macro_call_id: MacroCallId) -> FragmentKind {
166 let syn = db.lookup_intern_macro(macro_call_id).kind.node(db).value;
167
168 let parent = match syn.parent() {
169 Some(it) => it,
170 None => {
171 // FIXME:
172 // If it is root, which means the parent HirFile
173 // MacroKindFile must be non-items
174 // return expr now.
175 return FragmentKind::Expr;
176 }
177 };
178
179 match parent.kind() {
180 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
181 LET_STMT => {
182 // FIXME: Handle Pattern
183 FragmentKind::Expr
184 }
185 // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that
186 EXPR_STMT | BLOCK => FragmentKind::Expr,
187 ARG_LIST => FragmentKind::Expr,
188 TRY_EXPR => FragmentKind::Expr,
189 TUPLE_EXPR => FragmentKind::Expr,
190 ITEM_LIST => FragmentKind::Items,
191 _ => {
192 // Unknown , Just guess it is `Items`
193 FragmentKind::Items
194 }
195 }
196}