aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/expr.rs16
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap17
-rw-r--r--crates/ra_hir/src/ty/tests.rs17
-rw-r--r--crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs5
-rw-r--r--crates/ra_syntax/src/ast.rs18
-rw-r--r--crates/ra_syntax/src/ast/generated.rs44
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---
2created: "2019-01-26T21:36:52.714121185+00:00"
3creator: [email protected]
4expression: "&result"
5source: 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]
288fn infer_in_elseif() {
289 check_inference(
290 "infer_in_elseif",
291 r#"
292struct Foo { field: i32 }
293fn main(foo: Foo) {
294 if true {
295
296 } else if false {
297 foo.field
298 }
299}
300"#,
301 )
302}
303
304#[test]
288fn infer_inherent_method() { 305fn 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)]
289pub enum ElseBranchFlavor<'a> {
290 Block(&'a Block),
291 IfExpr(&'a IfExpr),
292}
293
288impl IfExpr { 294impl 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
661impl DynTraitType {} 661impl DynTraitType {}
662 662
663// ElseBranch
664#[derive(Debug, PartialEq, Eq, Hash)]
665#[repr(transparent)]
666pub struct ElseBranch {
667 pub(crate) syntax: SyntaxNode,
668}
669unsafe impl TransparentNewType for ElseBranch {
670 type Repr = rowan::SyntaxNode<RaTypes>;
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq)]
674pub enum ElseBranchKind<'a> {
675 Block(&'a Block),
676 IfExpr(&'a IfExpr),
677}
678
679impl 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
690impl ToOwned for ElseBranch {
691 type Owned = TreeArc<ElseBranch>;
692 fn to_owned(&self) -> TreeArc<ElseBranch> { TreeArc::cast(self.syntax.to_owned()) }
693}
694
695impl 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
705impl ElseBranch {}
706
663// EnumDef 707// EnumDef
664#[derive(Debug, PartialEq, Eq, Hash)] 708#[derive(Debug, PartialEq, Eq, Hash)]
665#[repr(transparent)] 709#[repr(transparent)]