aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-03-08 10:02:14 +0000
committerFlorian Diebold <[email protected]>2020-03-08 10:10:48 +0000
commitafdf08e964345ac4a884a5630772611ba81f6969 (patch)
treeb72b06310a3cd9bcec2234b0f38ff93eb6a8feb0
parentf617455d10084da30a13cc49ffdd6b86c6049ba1 (diff)
Move hypothetical expansion to hir_expand
-rw-r--r--crates/ra_hir/src/semantics.rs24
-rw-r--r--crates/ra_hir_expand/src/db.rs43
-rw-r--r--crates/ra_hir_expand/src/lib.rs9
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs6
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;
12use ra_db::{FileId, FileRange}; 12use ra_db::{FileId, FileRange};
13use ra_prof::profile; 13use ra_prof::profile;
14use ra_syntax::{ 14use 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};
18use rustc_hash::{FxHashMap, FxHashSet}; 17use 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.
79pub 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
75pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { 99pub(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
136pub fn expander( 160fn 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
152pub(crate) fn macro_expand_with_arg( 173fn 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
306pub use mbe::{syntax_node_to_token_tree, Origin}; 299pub use mbe::Origin;
307use ra_parser::FragmentKind; 300use ra_parser::FragmentKind;
308 301
309impl ExpansionInfo { 302impl 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 &macro_call_with_fake_ident, 130 &hypothetical_args,
127 fake_ident_token, 131 fake_ident_token,
128 ), 132 ),
129 ) { 133 ) {