diff options
-rw-r--r-- | crates/ra_assists/src/assists/add_explicit_type.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 20 |
4 files changed, 62 insertions, 8 deletions
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs index eeb4ff39f..2c602a79e 100644 --- a/crates/ra_assists/src/assists/add_explicit_type.rs +++ b/crates/ra_assists/src/assists/add_explicit_type.rs | |||
@@ -74,6 +74,24 @@ mod tests { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn add_explicit_type_works_for_macro_call() { | ||
78 | check_assist( | ||
79 | add_explicit_type, | ||
80 | "macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", | ||
81 | "macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }", | ||
82 | ); | ||
83 | } | ||
84 | |||
85 | #[test] | ||
86 | fn add_explicit_type_works_for_macro_call_recursive() { | ||
87 | check_assist( | ||
88 | add_explicit_type, | ||
89 | "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }", | ||
90 | "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|>: u64 = v!(); }", | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | #[test] | ||
77 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { | 95 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { |
78 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); | 96 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); |
79 | } | 97 | } |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 85b378483..2c422af8b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -215,8 +215,32 @@ impl SourceAnalyzer { | |||
215 | self.body_source_map.as_ref()?.node_pat(src) | 215 | self.body_source_map.as_ref()?.node_pat(src) |
216 | } | 216 | } |
217 | 217 | ||
218 | fn expand_expr( | ||
219 | &self, | ||
220 | db: &impl HirDatabase, | ||
221 | expr: InFile<&ast::Expr>, | ||
222 | ) -> Option<InFile<ast::Expr>> { | ||
223 | let macro_call = ast::MacroCall::cast(expr.value.syntax().clone())?; | ||
224 | let macro_file = | ||
225 | self.body_source_map.as_ref()?.node_macro_file(expr.with_value(¯o_call))?; | ||
226 | let expanded = db.parse_or_expand(macro_file)?; | ||
227 | let kind = expanded.kind(); | ||
228 | let expr = InFile::new(macro_file, ast::Expr::cast(expanded)?); | ||
229 | |||
230 | if ast::MacroCall::can_cast(kind) { | ||
231 | self.expand_expr(db, expr.as_ref()) | ||
232 | } else { | ||
233 | Some(expr) | ||
234 | } | ||
235 | } | ||
236 | |||
218 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { | 237 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
219 | let expr_id = self.expr_id(expr)?; | 238 | let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) { |
239 | self.body_source_map.as_ref()?.node_expr(expr.as_ref())? | ||
240 | } else { | ||
241 | self.expr_id(expr)? | ||
242 | }; | ||
243 | |||
220 | let ty = self.infer.as_ref()?[expr_id].clone(); | 244 | let ty = self.infer.as_ref()?[expr_id].clone(); |
221 | let environment = TraitEnvironment::lower(db, &self.resolver); | 245 | let environment = TraitEnvironment::lower(db, &self.resolver); |
222 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | 246 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index d3e4c50ae..142c52d35 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -163,6 +163,7 @@ pub struct BodySourceMap { | |||
163 | pat_map: FxHashMap<PatSource, PatId>, | 163 | pat_map: FxHashMap<PatSource, PatId>, |
164 | pat_map_back: ArenaMap<PatId, PatSource>, | 164 | pat_map_back: ArenaMap<PatId, PatSource>, |
165 | field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, | 165 | field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, |
166 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, | ||
166 | } | 167 | } |
167 | 168 | ||
168 | impl Body { | 169 | impl Body { |
@@ -237,6 +238,11 @@ impl BodySourceMap { | |||
237 | self.expr_map.get(&src).cloned() | 238 | self.expr_map.get(&src).cloned() |
238 | } | 239 | } |
239 | 240 | ||
241 | pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> { | ||
242 | let src = node.map(|it| AstPtr::new(it)); | ||
243 | self.expansions.get(&src).cloned() | ||
244 | } | ||
245 | |||
240 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { | 246 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { |
241 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | 247 | let src = node.map(|it| Either::Right(AstPtr::new(it))); |
242 | self.expr_map.get(&src).cloned() | 248 | self.expr_map.get(&src).cloned() |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index fc3a028e0..e656f9a41 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -446,14 +446,20 @@ where | |||
446 | } | 446 | } |
447 | } | 447 | } |
448 | // FIXME expand to statements in statement position | 448 | // FIXME expand to statements in statement position |
449 | ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { | 449 | ast::Expr::MacroCall(e) => { |
450 | Some((mark, expansion)) => { | 450 | let macro_call = self.expander.to_source(AstPtr::new(&e)); |
451 | let id = self.collect_expr(expansion); | 451 | match self.expander.enter_expand(self.db, e.clone()) { |
452 | self.expander.exit(self.db, mark); | 452 | Some((mark, expansion)) => { |
453 | id | 453 | self.source_map |
454 | .expansions | ||
455 | .insert(macro_call, self.expander.current_file_id); | ||
456 | let id = self.collect_expr(expansion); | ||
457 | self.expander.exit(self.db, mark); | ||
458 | id | ||
459 | } | ||
460 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
454 | } | 461 | } |
455 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | 462 | } |
456 | }, | ||
457 | 463 | ||
458 | // FIXME implement HIR for these: | 464 | // FIXME implement HIR for these: |
459 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 465 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |