aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/type_ref.rs
diff options
context:
space:
mode:
authorcynecx <[email protected]>2021-04-17 16:38:38 +0100
committercynecx <[email protected]>2021-04-17 16:38:45 +0100
commit7ed42a3a527b2c39826cfeb3626521c11abb25f0 (patch)
tree81c956d98c4990b0555540ad9cc1c94efa68deac /crates/hir_def/src/type_ref.rs
parent14918a3870d568778473f0a5697a547b85acf20a (diff)
hir_def: refactor expand_macro_type and cleanups
Diffstat (limited to 'crates/hir_def/src/type_ref.rs')
-rw-r--r--crates/hir_def/src/type_ref.rs78
1 files changed, 14 insertions, 64 deletions
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.
3use std::borrow::Cow;
4 3
5use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile}; 4use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile};
6use syntax::{algo::SyntaxRewriter, ast, AstNode, SyntaxKind, SyntaxNode}; 5use syntax::ast;
7 6
8use crate::{ 7use 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
318pub fn expand_type_ref<'a>( 307pub 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, &macro_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}