diff options
author | Edwin Cheng <[email protected]> | 2019-11-08 20:00:27 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-11-08 20:26:28 +0000 |
commit | d01e0abdb57c5be340934cb51e2f6b1a2e6c0373 (patch) | |
tree | 837abe3c0c20d35040fd8f21c34e093e16cd09db | |
parent | 62ed93db13877888379ea38c843729419bdf99d0 (diff) |
Refactor and simpfily
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 80 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 40 | ||||
-rw-r--r-- | crates/ra_ide_api/src/display/navigation_target.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/status.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 2 |
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; | |||
8 | use ra_syntax::{AstNode, Parse, SyntaxNode}; | 8 | use ra_syntax::{AstNode, Parse, SyntaxNode}; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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)] | ||
16 | pub struct ParseMacroWithInfo { | ||
17 | pub parsed: Parse<SyntaxNode>, | ||
18 | pub expansion_info: Arc<ExpansionInfo>, | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, PartialEq, Eq, Clone)] | ||
22 | pub 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)] |
29 | pub trait AstDatabase: SourceDatabase { | 17 | pub 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 | ||
49 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | 34 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { |
@@ -83,7 +68,7 @@ pub(crate) fn macro_arg( | |||
83 | pub(crate) fn macro_expand( | 68 | pub(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 | ||
104 | pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { | 85 | pub(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 | |||
113 | pub(crate) fn parse_macro( | 94 | pub(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 | ||
121 | pub(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 | |||
166 | pub(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 | ||
22 | use crate::ast_id_map::FileAstId; | 22 | use crate::ast_id_map::FileAstId; |
23 | use 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 |
136 | pub struct ExpansionInfo { | 145 | pub 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 | ||
141 | impl ExpansionInfo { | 153 | impl 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 | ||
97 | impl FromIterator<TableEntry<MacroFile, Option<Parse<SyntaxNode>>>> for SyntaxTreeStats { | 97 | impl<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 | ||
33 | pub use crate::syntax_bridge::{ | 33 | pub 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 |