diff options
-rw-r--r-- | crates/ra_hir/src/expr.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 18 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 44 |
6 files changed, 112 insertions, 5 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 29469af2c..60d997bbe 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -498,7 +498,13 @@ impl ExprCollector { | |||
498 | let then_branch = self.collect_block_opt(e.then_branch()); | 498 | let then_branch = self.collect_block_opt(e.then_branch()); |
499 | let else_branch = e | 499 | let else_branch = e |
500 | .else_branch() | 500 | .else_branch() |
501 | .map(|e| self.collect_block(e)) | 501 | .map(|b| match b { |
502 | ast::ElseBranchFlavor::Block(it) => self.collect_block(it), | ||
503 | ast::ElseBranchFlavor::IfExpr(elif) => { | ||
504 | let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap(); | ||
505 | self.collect_expr(expr) | ||
506 | } | ||
507 | }) | ||
502 | .unwrap_or_else(|| self.empty_block()); | 508 | .unwrap_or_else(|| self.empty_block()); |
503 | let placeholder_pat = self.pats.alloc(Pat::Missing); | 509 | let placeholder_pat = self.pats.alloc(Pat::Missing); |
504 | let arms = vec![ | 510 | let arms = vec![ |
@@ -521,7 +527,13 @@ impl ExprCollector { | |||
521 | } else { | 527 | } else { |
522 | let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); | 528 | let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); |
523 | let then_branch = self.collect_block_opt(e.then_branch()); | 529 | let then_branch = self.collect_block_opt(e.then_branch()); |
524 | let else_branch = e.else_branch().map(|e| self.collect_block(e)); | 530 | let else_branch = e.else_branch().map(|b| match b { |
531 | ast::ElseBranchFlavor::Block(it) => self.collect_block(it), | ||
532 | ast::ElseBranchFlavor::IfExpr(elif) => { | ||
533 | let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap(); | ||
534 | self.collect_expr(expr) | ||
535 | } | ||
536 | }); | ||
525 | self.alloc_expr( | 537 | self.alloc_expr( |
526 | Expr::If { | 538 | Expr::If { |
527 | condition, | 539 | condition, |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap new file mode 100644 index 000000000..6a435e5cf --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap | |||
@@ -0,0 +1,17 @@ | |||
1 | --- | ||
2 | created: "2019-01-26T21:36:52.714121185+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: "&result" | ||
5 | source: crates/ra_hir/src/ty/tests.rs | ||
6 | --- | ||
7 | [35; 38) 'foo': Foo | ||
8 | [45; 109) '{ ... } }': () | ||
9 | [51; 107) 'if tru... }': () | ||
10 | [54; 58) 'true': bool | ||
11 | [59; 67) '{ }': () | ||
12 | [73; 107) 'if fal... }': i32 | ||
13 | [76; 81) 'false': bool | ||
14 | [82; 107) '{ ... }': i32 | ||
15 | [92; 95) 'foo': Foo | ||
16 | [92; 101) 'foo.field': i32 | ||
17 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index e0b0689f8..e1165f682 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -285,6 +285,23 @@ fn test() { | |||
285 | } | 285 | } |
286 | 286 | ||
287 | #[test] | 287 | #[test] |
288 | fn infer_in_elseif() { | ||
289 | check_inference( | ||
290 | "infer_in_elseif", | ||
291 | r#" | ||
292 | struct Foo { field: i32 } | ||
293 | fn main(foo: Foo) { | ||
294 | if true { | ||
295 | |||
296 | } else if false { | ||
297 | foo.field | ||
298 | } | ||
299 | } | ||
300 | "#, | ||
301 | ) | ||
302 | } | ||
303 | |||
304 | #[test] | ||
288 | fn infer_inherent_method() { | 305 | fn infer_inherent_method() { |
289 | check_inference( | 306 | check_inference( |
290 | "infer_inherent_method", | 307 | "infer_inherent_method", |
diff --git a/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs b/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs index d64c34d54..71880b919 100644 --- a/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs +++ b/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs | |||
@@ -11,7 +11,10 @@ pub fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> { | |||
11 | let pat = cond.pat()?; | 11 | let pat = cond.pat()?; |
12 | let expr = cond.expr()?; | 12 | let expr = cond.expr()?; |
13 | let then_block = if_expr.then_branch()?; | 13 | let then_block = if_expr.then_branch()?; |
14 | let else_block = if_expr.else_branch()?; | 14 | let else_block = match if_expr.else_branch()? { |
15 | ast::ElseBranchFlavor::Block(it) => it, | ||
16 | ast::ElseBranchFlavor::IfExpr(_) => return None, | ||
17 | }; | ||
15 | 18 | ||
16 | ctx.build("replace with match", |edit| { | 19 | ctx.build("replace with match", |edit| { |
17 | let match_expr = build_match_expr(expr, pat, then_block, else_block); | 20 | let match_expr = build_match_expr(expr, pat, then_block, else_block); |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 00c60ebf3..ab3dd1b84 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -285,13 +285,27 @@ impl LetStmt { | |||
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
288 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
289 | pub enum ElseBranchFlavor<'a> { | ||
290 | Block(&'a Block), | ||
291 | IfExpr(&'a IfExpr), | ||
292 | } | ||
293 | |||
288 | impl IfExpr { | 294 | impl IfExpr { |
289 | pub fn then_branch(&self) -> Option<&Block> { | 295 | pub fn then_branch(&self) -> Option<&Block> { |
290 | self.blocks().nth(0) | 296 | self.blocks().nth(0) |
291 | } | 297 | } |
292 | pub fn else_branch(&self) -> Option<&Block> { | 298 | pub fn else_branch(&self) -> Option<ElseBranchFlavor> { |
293 | self.blocks().nth(1) | 299 | let res = match self.blocks().nth(1) { |
300 | Some(block) => ElseBranchFlavor::Block(block), | ||
301 | None => { | ||
302 | let elif: &IfExpr = child_opt(self)?; | ||
303 | ElseBranchFlavor::IfExpr(elif) | ||
304 | } | ||
305 | }; | ||
306 | Some(res) | ||
294 | } | 307 | } |
308 | |||
295 | fn blocks(&self) -> AstChildren<Block> { | 309 | fn blocks(&self) -> AstChildren<Block> { |
296 | children(self) | 310 | children(self) |
297 | } | 311 | } |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 3ace6533c..4f8723ae7 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -660,6 +660,50 @@ impl ToOwned for DynTraitType { | |||
660 | 660 | ||
661 | impl DynTraitType {} | 661 | impl DynTraitType {} |
662 | 662 | ||
663 | // ElseBranch | ||
664 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
665 | #[repr(transparent)] | ||
666 | pub struct ElseBranch { | ||
667 | pub(crate) syntax: SyntaxNode, | ||
668 | } | ||
669 | unsafe impl TransparentNewType for ElseBranch { | ||
670 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
671 | } | ||
672 | |||
673 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
674 | pub enum ElseBranchKind<'a> { | ||
675 | Block(&'a Block), | ||
676 | IfExpr(&'a IfExpr), | ||
677 | } | ||
678 | |||
679 | impl AstNode for ElseBranch { | ||
680 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
681 | match syntax.kind() { | ||
682 | | BLOCK | ||
683 | | IF_EXPR => Some(ElseBranch::from_repr(syntax.into_repr())), | ||
684 | _ => None, | ||
685 | } | ||
686 | } | ||
687 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
688 | } | ||
689 | |||
690 | impl ToOwned for ElseBranch { | ||
691 | type Owned = TreeArc<ElseBranch>; | ||
692 | fn to_owned(&self) -> TreeArc<ElseBranch> { TreeArc::cast(self.syntax.to_owned()) } | ||
693 | } | ||
694 | |||
695 | impl ElseBranch { | ||
696 | pub fn kind(&self) -> ElseBranchKind { | ||
697 | match self.syntax.kind() { | ||
698 | BLOCK => ElseBranchKind::Block(Block::cast(&self.syntax).unwrap()), | ||
699 | IF_EXPR => ElseBranchKind::IfExpr(IfExpr::cast(&self.syntax).unwrap()), | ||
700 | _ => unreachable!(), | ||
701 | } | ||
702 | } | ||
703 | } | ||
704 | |||
705 | impl ElseBranch {} | ||
706 | |||
663 | // EnumDef | 707 | // EnumDef |
664 | #[derive(Debug, PartialEq, Eq, Hash)] | 708 | #[derive(Debug, PartialEq, Eq, Hash)] |
665 | #[repr(transparent)] | 709 | #[repr(transparent)] |