diff options
author | cynecx <[email protected]> | 2021-04-17 16:38:38 +0100 |
---|---|---|
committer | cynecx <[email protected]> | 2021-04-17 16:38:45 +0100 |
commit | 7ed42a3a527b2c39826cfeb3626521c11abb25f0 (patch) | |
tree | 81c956d98c4990b0555540ad9cc1c94efa68deac /crates/hir_def | |
parent | 14918a3870d568778473f0a5697a547b85acf20a (diff) |
hir_def: refactor expand_macro_type and cleanups
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/body.rs | 72 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 78 |
2 files changed, 30 insertions, 120 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 44ae13643..8a9b936ea 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -19,7 +19,7 @@ use hir_expand::{ | |||
19 | use la_arena::{Arena, ArenaMap}; | 19 | use la_arena::{Arena, ArenaMap}; |
20 | use profile::Count; | 20 | use profile::Count; |
21 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
22 | use syntax::{ast, AstNode, AstPtr, SyntaxNode}; | 22 | use syntax::{ast, AstNode, AstPtr}; |
23 | 23 | ||
24 | pub use lower::LowerCtx; | 24 | pub use lower::LowerCtx; |
25 | 25 | ||
@@ -98,14 +98,11 @@ impl Expander { | |||
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | fn enter_expand_intern( | 101 | pub(crate) fn enter_expand<T: ast::AstNode>( |
102 | &mut self, | 102 | &mut self, |
103 | db: &dyn DefDatabase, | 103 | db: &dyn DefDatabase, |
104 | macro_call: ast::MacroCall, | 104 | macro_call: ast::MacroCall, |
105 | ) -> Result< | 105 | ) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> { |
106 | ExpandResult<Option<(SyntaxNode, impl FnMut(&dyn DefDatabase) -> Mark + '_)>>, | ||
107 | UnresolvedMacro, | ||
108 | > { | ||
109 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { | 106 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { |
110 | cov_mark::hit!(your_stack_belongs_to_me); | 107 | cov_mark::hit!(your_stack_belongs_to_me); |
111 | return Ok(ExpandResult::str_err( | 108 | return Ok(ExpandResult::str_err( |
@@ -150,55 +147,6 @@ impl Expander { | |||
150 | } | 147 | } |
151 | }; | 148 | }; |
152 | 149 | ||
153 | let this = self; | ||
154 | |||
155 | let advance_state = move |db: &dyn DefDatabase| { | ||
156 | this.recursion_limit += 1; | ||
157 | let mark = Mark { | ||
158 | file_id: this.current_file_id, | ||
159 | ast_id_map: mem::take(&mut this.ast_id_map), | ||
160 | bomb: DropBomb::new("expansion mark dropped"), | ||
161 | }; | ||
162 | this.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); | ||
163 | this.current_file_id = file_id; | ||
164 | this.ast_id_map = db.ast_id_map(file_id); | ||
165 | mark | ||
166 | }; | ||
167 | |||
168 | Ok(ExpandResult { value: Some((raw_node, advance_state)), err }) | ||
169 | } | ||
170 | |||
171 | pub(crate) fn enter_expand_raw( | ||
172 | &mut self, | ||
173 | db: &dyn DefDatabase, | ||
174 | macro_call: ast::MacroCall, | ||
175 | ) -> Result<ExpandResult<Option<(Mark, SyntaxNode)>>, UnresolvedMacro> { | ||
176 | let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? { | ||
177 | ExpandResult { value: Some((raw_node, advance_state)), err } => { | ||
178 | (raw_node, advance_state, err) | ||
179 | } | ||
180 | ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }), | ||
181 | }; | ||
182 | |||
183 | log::debug!("macro expansion {:#?}", raw_node); | ||
184 | |||
185 | let mark = advance_state(db); | ||
186 | |||
187 | Ok(ExpandResult { value: Some((mark, raw_node)), err }) | ||
188 | } | ||
189 | |||
190 | pub(crate) fn enter_expand<T: ast::AstNode>( | ||
191 | &mut self, | ||
192 | db: &dyn DefDatabase, | ||
193 | macro_call: ast::MacroCall, | ||
194 | ) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> { | ||
195 | let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? { | ||
196 | ExpandResult { value: Some((raw_node, advance_state)), err } => { | ||
197 | (raw_node, advance_state, err) | ||
198 | } | ||
199 | ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }), | ||
200 | }; | ||
201 | |||
202 | let node = match T::cast(raw_node) { | 150 | let node = match T::cast(raw_node) { |
203 | Some(it) => it, | 151 | Some(it) => it, |
204 | None => { | 152 | None => { |
@@ -209,7 +157,15 @@ impl Expander { | |||
209 | 157 | ||
210 | log::debug!("macro expansion {:#?}", node.syntax()); | 158 | log::debug!("macro expansion {:#?}", node.syntax()); |
211 | 159 | ||
212 | let mark = advance_state(db); | 160 | self.recursion_limit += 1; |
161 | let mark = Mark { | ||
162 | file_id: self.current_file_id, | ||
163 | ast_id_map: mem::take(&mut self.ast_id_map), | ||
164 | bomb: DropBomb::new("expansion mark dropped"), | ||
165 | }; | ||
166 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); | ||
167 | self.current_file_id = file_id; | ||
168 | self.ast_id_map = db.ast_id_map(file_id); | ||
213 | 169 | ||
214 | Ok(ExpandResult { value: Some((mark, node)), err }) | 170 | Ok(ExpandResult { value: Some((mark, node)), err }) |
215 | } | 171 | } |
@@ -234,6 +190,10 @@ impl Expander { | |||
234 | &self.cfg_expander.cfg_options | 190 | &self.cfg_expander.cfg_options |
235 | } | 191 | } |
236 | 192 | ||
193 | pub(crate) fn current_file_id(&self) -> HirFileId { | ||
194 | self.current_file_id | ||
195 | } | ||
196 | |||
237 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 197 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
238 | let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene); | 198 | let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene); |
239 | Path::from_src(path, &ctx) | 199 | Path::from_src(path, &ctx) |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 0832371c0..cf8a584ab 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -1,9 +1,8 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | use std::borrow::Cow; | ||
4 | 3 | ||
5 | use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile}; | 4 | use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile}; |
6 | use syntax::{algo::SyntaxRewriter, ast, AstNode, SyntaxKind, SyntaxNode}; | 5 | use syntax::ast; |
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{ |
9 | body::{Expander, LowerCtx}, | 8 | body::{Expander, LowerCtx}, |
@@ -207,16 +206,6 @@ impl TypeRef { | |||
207 | TypeRef::Tuple(Vec::new()) | 206 | TypeRef::Tuple(Vec::new()) |
208 | } | 207 | } |
209 | 208 | ||
210 | pub fn has_macro_calls(&self) -> bool { | ||
211 | let mut has_macro_call = false; | ||
212 | self.walk(&mut |ty_ref| { | ||
213 | if let TypeRef::Macro(_) = ty_ref { | ||
214 | has_macro_call |= true | ||
215 | } | ||
216 | }); | ||
217 | has_macro_call | ||
218 | } | ||
219 | |||
220 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { | 209 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { |
221 | go(self, f); | 210 | go(self, f); |
222 | 211 | ||
@@ -315,68 +304,29 @@ impl TypeBound { | |||
315 | } | 304 | } |
316 | } | 305 | } |
317 | 306 | ||
318 | pub fn expand_type_ref<'a>( | 307 | pub fn expand_macro_type( |
319 | db: &dyn DefDatabase, | 308 | db: &dyn DefDatabase, |
320 | module_id: ModuleId, | 309 | module_id: ModuleId, |
321 | type_ref: &'a TypeRef, | 310 | macro_type: &TypeRef, |
322 | ) -> Option<Cow<'a, TypeRef>> { | 311 | ) -> Option<TypeRef> { |
323 | let macro_call = match type_ref { | 312 | let macro_call = match macro_type { |
324 | TypeRef::Macro(macro_call) => macro_call, | 313 | TypeRef::Macro(macro_call) => macro_call, |
325 | _ => return Some(Cow::Borrowed(type_ref)), | 314 | _ => panic!("expected TypeRef::Macro"), |
326 | }; | 315 | }; |
327 | 316 | ||
328 | let file_id = macro_call.file_id; | 317 | let file_id = macro_call.file_id; |
329 | let macro_call = macro_call.to_node(db.upcast()); | 318 | let macro_call = macro_call.to_node(db.upcast()); |
330 | 319 | ||
331 | let mut expander = Expander::new(db, file_id, module_id); | 320 | let mut expander = Expander::new(db, file_id, module_id); |
332 | let expanded = expand(db, &mut expander, ¯o_call, true)?; | 321 | let (file_id, expanded) = match expander.enter_expand::<ast::Type>(db, macro_call.clone()) { |
333 | 322 | Ok(ExpandResult { value: Some((mark, expanded)), .. }) => { | |
334 | let node = ast::Type::cast(expanded)?; | 323 | let file_id = expander.current_file_id(); |
335 | |||
336 | let ctx = LowerCtx::new(db, file_id); | ||
337 | return Some(Cow::Owned(TypeRef::from_ast(&ctx, node))); | ||
338 | |||
339 | fn expand( | ||
340 | db: &dyn DefDatabase, | ||
341 | expander: &mut Expander, | ||
342 | macro_call: &ast::MacroCall, | ||
343 | expect_type: bool, | ||
344 | ) -> Option<SyntaxNode> { | ||
345 | let (mark, mut expanded) = match expander.enter_expand_raw(db, macro_call.clone()) { | ||
346 | Ok(ExpandResult { value: Some((mark, expanded)), .. }) => (mark, expanded), | ||
347 | _ => return None, | ||
348 | }; | ||
349 | |||
350 | if expect_type && !ast::Type::can_cast(expanded.kind()) { | ||
351 | expander.exit(db, mark); | 324 | expander.exit(db, mark); |
352 | return None; | 325 | (file_id, expanded) |
353 | } | ||
354 | |||
355 | if ast::MacroType::can_cast(expanded.kind()) { | ||
356 | expanded = expanded.first_child()?; // MACRO_CALL | ||
357 | } | 326 | } |
327 | _ => return None, | ||
328 | }; | ||
358 | 329 | ||
359 | let mut rewriter = SyntaxRewriter::default(); | 330 | let ctx = LowerCtx::new(db, file_id); |
360 | 331 | return Some(TypeRef::from_ast(&ctx, expanded)); | |
361 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); | ||
362 | for child in children { | ||
363 | if let Some(new_node) = expand(db, expander, &child, false) { | ||
364 | if expanded == *child.syntax() { | ||
365 | expanded = new_node; | ||
366 | } else { | ||
367 | let parent = child.syntax().parent(); | ||
368 | let old_node = match &parent { | ||
369 | Some(node) if node.kind() == SyntaxKind::MACRO_TYPE => node, | ||
370 | _ => child.syntax(), | ||
371 | }; | ||
372 | rewriter.replace(old_node, &new_node) | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | expander.exit(db, mark); | ||
378 | |||
379 | let res = rewriter.rewrite(&expanded); | ||
380 | Some(res) | ||
381 | } | ||
382 | } | 332 | } |