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.rs80
1 files changed, 14 insertions, 66 deletions
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index 1eaf8bf30..e6d2e8d9d 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -8,22 +8,10 @@ use ra_prof::profile;
8use ra_syntax::{AstNode, Parse, SyntaxNode}; 8use ra_syntax::{AstNode, Parse, SyntaxNode};
9 9
10use crate::{ 10use crate::{
11 ast_id_map::AstIdMap, ExpansionInfo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, 11 ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
12 MacroDefId, MacroFile, MacroFileKind, 12 MacroFile, MacroFileKind,
13}; 13};
14 14
15#[derive(Debug, PartialEq, Eq, Clone)]
16pub struct ParseMacroWithInfo {
17 pub parsed: Parse<SyntaxNode>,
18 pub expansion_info: Arc<ExpansionInfo>,
19}
20
21#[derive(Debug, PartialEq, Eq, Clone)]
22pub struct MacroExpandInfo {
23 pub arg_map: Arc<mbe::TokenMap>,
24 pub def_map: Arc<mbe::TokenMap>,
25}
26
27// FIXME: rename to ExpandDatabase 15// FIXME: rename to ExpandDatabase
28#[salsa::query_group(AstDatabaseStorage)] 16#[salsa::query_group(AstDatabaseStorage)]
29pub trait AstDatabase: SourceDatabase { 17pub trait AstDatabase: SourceDatabase {
@@ -36,14 +24,11 @@ pub trait AstDatabase: SourceDatabase {
36 fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId; 24 fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
37 fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>; 25 fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>;
38 fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>; 26 fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>;
39 fn parse_macro(&self, macro_file: MacroFile) -> Option<Parse<SyntaxNode>>; 27 fn parse_macro(
40 fn parse_macro_with_info(&self, macro_file: MacroFile) -> Option<ParseMacroWithInfo>;
41 fn macro_expand(
42 &self, 28 &self,
43 macro_call: MacroCallId, 29 macro_file: MacroFile,
44 ) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String>; 30 ) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)>;
45 31 fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>;
46 fn macro_expansion_info(&self, macro_file: MacroFile) -> Option<Arc<ExpansionInfo>>;
47} 32}
48 33
49pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { 34pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
@@ -83,7 +68,7 @@ pub(crate) fn macro_arg(
83pub(crate) fn macro_expand( 68pub(crate) fn macro_expand(
84 db: &dyn AstDatabase, 69 db: &dyn AstDatabase,
85 id: MacroCallId, 70 id: MacroCallId,
86) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String> { 71) -> Result<Arc<tt::Subtree>, String> {
87 let loc = db.lookup_intern_macro(id); 72 let loc = db.lookup_intern_macro(id);
88 let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?; 73 let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
89 74
@@ -94,18 +79,14 @@ pub(crate) fn macro_expand(
94 if count > 65536 { 79 if count > 65536 {
95 return Err(format!("Total tokens count exceed limit : count = {}", count)); 80 return Err(format!("Total tokens count exceed limit : count = {}", count));
96 } 81 }
97 82 Ok(Arc::new(tt))
98 Ok((
99 Arc::new(tt),
100 MacroExpandInfo { arg_map: macro_arg.1.clone(), def_map: macro_rules.1.clone() },
101 ))
102} 83}
103 84
104pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { 85pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
105 match file_id.0 { 86 match file_id.0 {
106 HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), 87 HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
107 HirFileIdRepr::MacroFile(macro_file) => { 88 HirFileIdRepr::MacroFile(macro_file) => {
108 db.parse_macro(macro_file).map(|it| it.syntax_node()) 89 db.parse_macro(macro_file).map(|(it, _)| it.syntax_node())
109 } 90 }
110 } 91 }
111} 92}
@@ -113,15 +94,9 @@ pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Optio
113pub(crate) fn parse_macro( 94pub(crate) fn parse_macro(
114 db: &dyn AstDatabase, 95 db: &dyn AstDatabase,
115 macro_file: MacroFile, 96 macro_file: MacroFile,
116) -> Option<Parse<SyntaxNode>> { 97) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)> {
117 let _p = profile("parse_macro_query"); 98 let _p = profile("parse_macro_query");
118 db.parse_macro_with_info(macro_file).map(|r| r.parsed)
119}
120 99
121pub(crate) fn parse_macro_with_info(
122 db: &dyn AstDatabase,
123 macro_file: MacroFile,
124) -> Option<ParseMacroWithInfo> {
125 let macro_call_id = macro_file.macro_call_id; 100 let macro_call_id = macro_file.macro_call_id;
126 let tt = db 101 let tt = db
127 .macro_expand(macro_call_id) 102 .macro_expand(macro_call_id)
@@ -133,39 +108,12 @@ pub(crate) fn parse_macro_with_info(
133 }) 108 })
134 .ok()?; 109 .ok()?;
135 110
136 let (parsed, exp_map) = match macro_file.macro_file_kind { 111 match macro_file.macro_file_kind {
137 MacroFileKind::Items => { 112 MacroFileKind::Items => {
138 mbe::token_tree_to_items(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()? 113 mbe::token_tree_to_items(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
139 } 114 }
140 MacroFileKind::Expr => { 115 MacroFileKind::Expr => {
141 mbe::token_tree_to_expr(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()? 116 mbe::token_tree_to_expr(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
142 } 117 }
143 }; 118 }
144
145 let expand_info = tt.1;
146 let loc: MacroCallLoc = db.lookup_intern_macro(macro_call_id);
147
148 let arg_tt = loc.ast_id.to_node(db).token_tree();
149 let def_tt = loc.def.ast_id.to_node(db).token_tree();
150
151 let arg_range = arg_tt.map(|t| t.syntax().text_range());
152 let def_range = def_tt.map(|t| t.syntax().text_range());
153
154 let shift = db.macro_def(loc.def)?.0.shift();
155
156 let arg_map =
157 arg_range.map(|it| exp_map.map_ranges(&expand_info.arg_map, it, shift)).unwrap_or_default();
158 let def_map =
159 def_range.map(|it| exp_map.map_ranges(&expand_info.def_map, it, 0)).unwrap_or_default();
160
161 let info = ExpansionInfo { arg_map, def_map };
162
163 Some(ParseMacroWithInfo { parsed, expansion_info: Arc::new(info) })
164}
165
166pub(crate) fn macro_expansion_info(
167 db: &dyn AstDatabase,
168 macro_file: MacroFile,
169) -> Option<Arc<ExpansionInfo>> {
170 db.parse_macro_with_info(macro_file).map(|res| res.expansion_info.clone())
171} 119}