diff options
author | Florian Diebold <[email protected]> | 2020-03-08 10:02:14 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-03-08 10:10:48 +0000 |
commit | afdf08e964345ac4a884a5630772611ba81f6969 (patch) | |
tree | b72b06310a3cd9bcec2234b0f38ff93eb6a8feb0 | |
parent | f617455d10084da30a13cc49ffdd6b86c6049ba1 (diff) |
Move hypothetical expansion to hir_expand
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 43 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 6 |
4 files changed, 43 insertions, 39 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 56bd763c7..3782a9984 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -12,8 +12,7 @@ use hir_expand::ExpansionInfo; | |||
12 | use ra_db::{FileId, FileRange}; | 12 | use ra_db::{FileId, FileRange}; |
13 | use ra_prof::profile; | 13 | use ra_prof::profile; |
14 | use ra_syntax::{ | 14 | use ra_syntax::{ |
15 | algo::{self, skip_trivia_token}, | 15 | algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, |
16 | ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, | ||
17 | }; | 16 | }; |
18 | use rustc_hash::{FxHashMap, FxHashSet}; | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
19 | 18 | ||
@@ -74,7 +73,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
74 | pub fn expand_hypothetical( | 73 | pub fn expand_hypothetical( |
75 | &self, | 74 | &self, |
76 | actual_macro_call: &ast::MacroCall, | 75 | actual_macro_call: &ast::MacroCall, |
77 | hypothetical_call: &ast::MacroCall, | 76 | hypothetical_args: &ast::TokenTree, |
78 | token_to_map: SyntaxToken, | 77 | token_to_map: SyntaxToken, |
79 | ) -> Option<(SyntaxNode, SyntaxToken)> { | 78 | ) -> Option<(SyntaxNode, SyntaxToken)> { |
80 | let macro_call = | 79 | let macro_call = |
@@ -82,24 +81,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
82 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 81 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
83 | let macro_call_id = macro_call | 82 | let macro_call_id = macro_call |
84 | .as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?; | 83 | .as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?; |
85 | let macro_file = macro_call_id.as_file().macro_file().unwrap(); | 84 | hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map) |
86 | let (tt, tmap_1) = | ||
87 | hir_expand::syntax_node_to_token_tree(hypothetical_call.token_tree().unwrap().syntax()) | ||
88 | .unwrap(); | ||
89 | let range = token_to_map | ||
90 | .text_range() | ||
91 | .checked_sub(hypothetical_call.token_tree().unwrap().syntax().text_range().start())?; | ||
92 | let token_id = tmap_1.token_by_range(range)?; | ||
93 | let macro_def = hir_expand::db::expander(self.db, macro_call_id)?; | ||
94 | let (node, tmap_2) = hir_expand::db::parse_macro_with_arg( | ||
95 | self.db, | ||
96 | macro_file, | ||
97 | Some(std::sync::Arc::new((tt, tmap_1))), | ||
98 | )?; | ||
99 | let token_id = macro_def.0.map_id_down(token_id); | ||
100 | let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; | ||
101 | let token = algo::find_covering_element(&node.syntax_node(), range).into_token()?; | ||
102 | Some((node.syntax_node(), token)) | ||
103 | } | 85 | } |
104 | 86 | ||
105 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | 87 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { |
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index f5c8bc22f..29dde3d80 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -72,6 +72,30 @@ pub trait AstDatabase: SourceDatabase { | |||
72 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | 72 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; |
73 | } | 73 | } |
74 | 74 | ||
75 | /// This expands the given macro call, but with different arguments. This is | ||
76 | /// used for completion, where we want to see what 'would happen' if we insert a | ||
77 | /// token. The `token_to_map` mapped down into the expansion, with the mapped | ||
78 | /// token returned. | ||
79 | pub fn expand_hypothetical( | ||
80 | db: &impl AstDatabase, | ||
81 | actual_macro_call: MacroCallId, | ||
82 | hypothetical_args: &ra_syntax::ast::TokenTree, | ||
83 | token_to_map: ra_syntax::SyntaxToken, | ||
84 | ) -> Option<(SyntaxNode, ra_syntax::SyntaxToken)> { | ||
85 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; | ||
86 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap(); | ||
87 | let range = | ||
88 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | ||
89 | let token_id = tmap_1.token_by_range(range)?; | ||
90 | let macro_def = expander(db, actual_macro_call)?; | ||
91 | let (node, tmap_2) = | ||
92 | parse_macro_with_arg(db, macro_file, Some(std::sync::Arc::new((tt, tmap_1))))?; | ||
93 | let token_id = macro_def.0.map_id_down(token_id); | ||
94 | let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; | ||
95 | let token = ra_syntax::algo::find_covering_element(&node.syntax_node(), range).into_token()?; | ||
96 | Some((node.syntax_node(), token)) | ||
97 | } | ||
98 | |||
75 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | 99 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { |
76 | let map = | 100 | let map = |
77 | db.parse_or_expand(file_id).map_or_else(AstIdMap::default, |it| AstIdMap::from_source(&it)); | 101 | db.parse_or_expand(file_id).map_or_else(AstIdMap::default, |it| AstIdMap::from_source(&it)); |
@@ -133,10 +157,7 @@ pub(crate) fn macro_expand( | |||
133 | macro_expand_with_arg(db, id, None) | 157 | macro_expand_with_arg(db, id, None) |
134 | } | 158 | } |
135 | 159 | ||
136 | pub fn expander( | 160 | fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
137 | db: &dyn AstDatabase, | ||
138 | id: MacroCallId, | ||
139 | ) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | ||
140 | let lazy_id = match id { | 161 | let lazy_id = match id { |
141 | MacroCallId::LazyMacro(id) => id, | 162 | MacroCallId::LazyMacro(id) => id, |
142 | MacroCallId::EagerMacro(_id) => { | 163 | MacroCallId::EagerMacro(_id) => { |
@@ -149,7 +170,7 @@ pub fn expander( | |||
149 | Some(macro_rules) | 170 | Some(macro_rules) |
150 | } | 171 | } |
151 | 172 | ||
152 | pub(crate) fn macro_expand_with_arg( | 173 | fn macro_expand_with_arg( |
153 | db: &dyn AstDatabase, | 174 | db: &dyn AstDatabase, |
154 | id: MacroCallId, | 175 | id: MacroCallId, |
155 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, | 176 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, |
@@ -158,7 +179,9 @@ pub(crate) fn macro_expand_with_arg( | |||
158 | MacroCallId::LazyMacro(id) => id, | 179 | MacroCallId::LazyMacro(id) => id, |
159 | MacroCallId::EagerMacro(id) => { | 180 | MacroCallId::EagerMacro(id) => { |
160 | if arg.is_some() { | 181 | if arg.is_some() { |
161 | return Err("hypothetical macro expansion not implemented for eager macro".to_owned()); | 182 | return Err( |
183 | "hypothetical macro expansion not implemented for eager macro".to_owned() | ||
184 | ); | ||
162 | } else { | 185 | } else { |
163 | return Ok(db.lookup_intern_eager_expansion(id).subtree); | 186 | return Ok(db.lookup_intern_eager_expansion(id).subtree); |
164 | } | 187 | } |
@@ -225,13 +248,15 @@ pub fn parse_macro_with_arg( | |||
225 | .collect::<Vec<_>>() | 248 | .collect::<Vec<_>>() |
226 | .join("\n"); | 249 | .join("\n"); |
227 | 250 | ||
228 | eprintln!( | 251 | log::warn!( |
229 | "fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}", | 252 | "fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}", |
230 | err, node.value, parents | 253 | err, |
254 | node.value, | ||
255 | parents | ||
231 | ); | 256 | ); |
232 | } | 257 | } |
233 | _ => { | 258 | _ => { |
234 | eprintln!("fail on macro_parse: (reason: {})", err); | 259 | log::warn!("fail on macro_parse: (reason: {})", err); |
235 | } | 260 | } |
236 | } | 261 | } |
237 | }) | 262 | }) |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 92f3902dd..3fce73e8a 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -157,13 +157,6 @@ impl HirFileId { | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | } | 159 | } |
160 | |||
161 | pub fn macro_file(self) -> Option<MacroFile> { | ||
162 | match self.0 { | ||
163 | HirFileIdRepr::FileId(_) => None, | ||
164 | HirFileIdRepr::MacroFile(m) => Some(m), | ||
165 | } | ||
166 | } | ||
167 | } | 160 | } |
168 | 161 | ||
169 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -303,7 +296,7 @@ pub struct ExpansionInfo { | |||
303 | exp_map: Arc<mbe::TokenMap>, | 296 | exp_map: Arc<mbe::TokenMap>, |
304 | } | 297 | } |
305 | 298 | ||
306 | pub use mbe::{syntax_node_to_token_tree, Origin}; | 299 | pub use mbe::Origin; |
307 | use ra_parser::FragmentKind; | 300 | use ra_parser::FragmentKind; |
308 | 301 | ||
309 | impl ExpansionInfo { | 302 | impl ExpansionInfo { |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index e7a8c78d0..40535c09e 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -119,11 +119,15 @@ impl<'a> CompletionContext<'a> { | |||
119 | { | 119 | { |
120 | break; | 120 | break; |
121 | } | 121 | } |
122 | let hypothetical_args = match macro_call_with_fake_ident.token_tree() { | ||
123 | Some(tt) => tt, | ||
124 | None => break, | ||
125 | }; | ||
122 | if let (Some(actual_expansion), Some(hypothetical_expansion)) = ( | 126 | if let (Some(actual_expansion), Some(hypothetical_expansion)) = ( |
123 | ctx.sema.expand(&actual_macro_call), | 127 | ctx.sema.expand(&actual_macro_call), |
124 | ctx.sema.expand_hypothetical( | 128 | ctx.sema.expand_hypothetical( |
125 | &actual_macro_call, | 129 | &actual_macro_call, |
126 | ¯o_call_with_fake_ident, | 130 | &hypothetical_args, |
127 | fake_ident_token, | 131 | fake_ident_token, |
128 | ), | 132 | ), |
129 | ) { | 133 | ) { |