aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-11-08 20:00:27 +0000
committerEdwin Cheng <[email protected]>2019-11-08 20:26:28 +0000
commitd01e0abdb57c5be340934cb51e2f6b1a2e6c0373 (patch)
tree837abe3c0c20d35040fd8f21c34e093e16cd09db
parent62ed93db13877888379ea38c843729419bdf99d0 (diff)
Refactor and simpfily
-rw-r--r--crates/ra_hir_expand/src/db.rs80
-rw-r--r--crates/ra_hir_expand/src/lib.rs40
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs5
-rw-r--r--crates/ra_ide_api/src/status.rs4
-rw-r--r--crates/ra_mbe/src/lib.rs2
5 files changed, 42 insertions, 89 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}
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 63ba17158..1a1d6bdd4 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -20,7 +20,6 @@ use ra_syntax::{
20}; 20};
21 21
22use crate::ast_id_map::FileAstId; 22use crate::ast_id_map::FileAstId;
23use std::sync::Arc;
24 23
25/// Input to the analyzer is a set of files, where each file is identified by 24/// Input to the analyzer is a set of files, where each file is identified by
26/// `FileId` and contains source code. However, another source of source code in 25/// `FileId` and contains source code. However, another source of source code in
@@ -69,19 +68,29 @@ impl HirFileId {
69 } 68 }
70 69
71 /// Return expansion information if it is a macro-expansion file 70 /// Return expansion information if it is a macro-expansion file
72 pub fn parent_expansion( 71 pub fn parent_expansion(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
73 self,
74 db: &dyn db::AstDatabase,
75 ) -> Option<((HirFileId, HirFileId), Arc<ExpansionInfo>)> {
76 match self.0 { 72 match self.0 {
77 HirFileIdRepr::FileId(_) => None, 73 HirFileIdRepr::FileId(_) => None,
78 HirFileIdRepr::MacroFile(macro_file) => { 74 HirFileIdRepr::MacroFile(macro_file) => {
79 let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id); 75 let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
80 76
81 let def_file = loc.def.ast_id.file_id; 77 let arg_range = loc.ast_id.to_node(db).token_tree()?.syntax().text_range();
78 let def_range = loc.def.ast_id.to_node(db).token_tree()?.syntax().text_range();
79
80 let macro_def = db.macro_def(loc.def)?;
81 let shift = macro_def.0.shift();
82 let rev_map = db.parse_macro(macro_file)?.1;
83
84 let arg_token_map = db.macro_arg(macro_file.macro_call_id)?.1;
85 let def_token_map = macro_def.1;
86
87 let arg_map = rev_map.map_ranges(&arg_token_map, arg_range, shift);
88 let def_map = rev_map.map_ranges(&def_token_map, def_range, 0);
89
82 let arg_file = loc.ast_id.file_id; 90 let arg_file = loc.ast_id.file_id;
91 let def_file = loc.def.ast_id.file_id;
83 92
84 db.macro_expansion_info(macro_file).map(|ex| ((arg_file, def_file), ex)) 93 Some(ExpansionInfo { arg_file, def_file, arg_map, def_map })
85 } 94 }
86 } 95 }
87 } 96 }
@@ -134,25 +143,24 @@ impl MacroCallId {
134#[derive(Debug, Clone, PartialEq, Eq)] 143#[derive(Debug, Clone, PartialEq, Eq)]
135/// ExpansionInfo mainly describes how to map text range between src and expanded macro 144/// ExpansionInfo mainly describes how to map text range between src and expanded macro
136pub struct ExpansionInfo { 145pub struct ExpansionInfo {
137 pub arg_map: Vec<(TextRange, TextRange)>, 146 pub(crate) arg_file: HirFileId,
138 pub def_map: Vec<(TextRange, TextRange)>, 147 pub(crate) def_file: HirFileId,
148
149 pub(crate) arg_map: Vec<(TextRange, TextRange)>,
150 pub(crate) def_map: Vec<(TextRange, TextRange)>,
139} 151}
140 152
141impl ExpansionInfo { 153impl ExpansionInfo {
142 pub fn find_range( 154 pub fn find_range(&self, from: TextRange) -> Option<(HirFileId, TextRange)> {
143 &self,
144 from: TextRange,
145 (arg_file_id, def_file_id): (HirFileId, HirFileId),
146 ) -> Option<(HirFileId, TextRange)> {
147 for (src, dest) in &self.arg_map { 155 for (src, dest) in &self.arg_map {
148 if src.is_subrange(&from) { 156 if src.is_subrange(&from) {
149 return Some((arg_file_id, *dest)); 157 return Some((self.arg_file, *dest));
150 } 158 }
151 } 159 }
152 160
153 for (src, dest) in &self.def_map { 161 for (src, dest) in &self.def_map {
154 if src.is_subrange(&from) { 162 if src.is_subrange(&from) {
155 return Some((def_file_id, *dest)); 163 return Some((self.def_file, *dest));
156 } 164 }
157 } 165 }
158 166
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index b9e3132f4..b77e19231 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -37,7 +37,7 @@ fn find_range_from_node(
37 let text_range = node.text_range(); 37 let text_range = node.text_range();
38 let (file_id, text_range) = src 38 let (file_id, text_range) = src
39 .parent_expansion(db) 39 .parent_expansion(db)
40 .and_then(|(files, expansion_info)| expansion_info.find_range(text_range, files)) 40 .and_then(|expansion_info| expansion_info.find_range(text_range))
41 .unwrap_or((src, text_range)); 41 .unwrap_or((src, text_range));
42 42
43 // FIXME: handle recursive macro generated macro 43 // FIXME: handle recursive macro generated macro
@@ -139,7 +139,6 @@ impl NavigationTarget {
139 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 139 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
140 let src = module.definition_source(db); 140 let src = module.definition_source(db);
141 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 141 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
142
143 match src.ast { 142 match src.ast {
144 ModuleSource::SourceFile(node) => { 143 ModuleSource::SourceFile(node) => {
145 let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); 144 let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());
@@ -324,9 +323,7 @@ impl NavigationTarget {
324 ) -> NavigationTarget { 323 ) -> NavigationTarget {
325 //FIXME: use `_` instead of empty string 324 //FIXME: use `_` instead of empty string
326 let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); 325 let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
327
328 let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1); 326 let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1);
329
330 let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax()); 327 let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax());
331 328
332 NavigationTarget::from_syntax( 329 NavigationTarget::from_syntax(
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index f91f16c8e..1bb27eb85 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -94,10 +94,10 @@ impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStat
94 } 94 }
95} 95}
96 96
97impl FromIterator<TableEntry<MacroFile, Option<Parse<SyntaxNode>>>> for SyntaxTreeStats { 97impl<M> FromIterator<TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>> for SyntaxTreeStats {
98 fn from_iter<T>(iter: T) -> SyntaxTreeStats 98 fn from_iter<T>(iter: T) -> SyntaxTreeStats
99 where 99 where
100 T: IntoIterator<Item = TableEntry<MacroFile, Option<Parse<SyntaxNode>>>>, 100 T: IntoIterator<Item = TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>>,
101 { 101 {
102 let mut res = SyntaxTreeStats::default(); 102 let mut res = SyntaxTreeStats::default();
103 for entry in iter { 103 for entry in iter {
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index a0f1a6881..70a289f09 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -32,7 +32,7 @@ pub enum ExpandError {
32 32
33pub use crate::syntax_bridge::{ 33pub use crate::syntax_bridge::{
34 ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items, 34 ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
35 token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, TokenMap, 35 token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, RevTokenMap, TokenMap,
36}; 36};
37 37
38/// This struct contains AST for a single `macro_rules` definition. What might 38/// This struct contains AST for a single `macro_rules` definition. What might