Repository: intellij-rust/intellij-rust
Issue: "Lift return out" produces invalid code for "else if"

## Environment

* **IntelliJ Rust plugin version:** 0.2.114.SNAPSHOT-193-dev
* **Rust toolchain version:** 1.41.0-nightly (99b89533d 2019-12-16) x86_64-apple-darwin
* **IDE name and version:** CLion 2019.3 (CL-193.5233.103)
* **Operating system:** macOS 10.15

## Problem description

"Lift return out of 'if'" intention action (from #4172) may produce an invalid code in case of `else if` construction.

## Steps to reproduce

Consider

```rust
fn get_char(n: u32) -> char {
    if n == 0 {
        return 'a'
    } else if n == 1 {
        return 'b'
    } else {
        return 'c'
    }
}
```

Plugin suggests to lift out return from the second if resulting in

```rust
fn get_char(n: u32) -> char {
    if n == 0 {
        return 'a'
    } else return if n == 1 {
        'b'
    } else {
        'c'
    }
}
```

Changed files:
src/test/kotlin/org/rust/ide/inspections/RsLiftInspectionTest.kt, src/main/kotlin/org/rust/ide/inspections/RsLiftInspection.kt

diff --git a/src/main/kotlin/org/rust/ide/inspections/RsLiftInspection.kt b/src/main/kotlin/org/rust/ide/inspections/RsLiftInspection.kt
index 4d27e524d..6291ed931 100644
--- a/src/main/kotlin/org/rust/ide/inspections/RsLiftInspection.kt
+++ b/src/main/kotlin/org/rust/ide/inspections/RsLiftInspection.kt
@@ -19,6 +19,7 @@ class RsLiftInspection : RsLocalInspectionTool() {
     override fun buildVisitor(holder: RsProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor? {
         return object : RsVisitor() {
             override fun visitIfExpr(o: RsIfExpr) {
+                if (o.parent is RsElseBranch) return
                 checkExpr(o, o.`if`)
             }
 
@@ -91,7 +92,12 @@ private fun RsExpr.getFoldableReturns(): List<FoldableElement>? {
             }
             is RsIfExpr -> {
                 if (block?.collectFoldableReturns() != true) return false
-                if (elseBranch?.block?.collectFoldableReturns() != true) return false
+                val elseIf = elseBranch?.ifExpr
+                if (elseIf != null) {
+                    if (!elseIf.collectFoldableReturns()) return false
+                } else {
+                    if (elseBranch?.block?.collectFoldableReturns() != true) return false
+                }
             }
             is RsMatchExpr -> {
                 val arms = matchBody?.matchArmList ?: return false
diff --git a/src/test/kotlin/org/rust/ide/inspections/RsLiftInspectionTest.kt b/src/test/kotlin/org/rust/ide/inspections/RsLiftInspectionTest.kt
index e18dd5b3c..44406a9f2 100644
--- a/src/test/kotlin/org/rust/ide/inspections/RsLiftInspectionTest.kt
+++ b/src/test/kotlin/org/rust/ide/inspections/RsLiftInspectionTest.kt
@@ -74,6 +74,44 @@ class RsLiftInspectionTest : RsInspectionsTestBase(RsLiftInspection::class) {
         }
     """, checkWeakWarn = true, testmark = RsLiftInspection.Testmarks.insideRetExpr)
 
+    fun `test lift return in else if`() = checkFixIsUnavailable("Lift return out of 'if'", """
+        fn get_char(n: u32) -> char {
+            /*weak_warning descr="Return can be lifted out of 'if'"*/if/*weak_warning**/ n == 0 {
+                return 'a'
+            } else /*caret*/if n == 1 {
+                return 'b'
+            } else {
+                return 'c'
+            }
+        }
+    """, checkWeakWarn = true)
+
+    fun `test lift return in if with else if`() = checkFixByText("Lift return out of 'if'", """
+        fn get_char(n: u32) -> char {
+            /*weak_warning descr="Return can be lifted out of 'if'"*/if/*caret*//*weak_warning**/ n == 0 {
+                return 'a'
+            } else if n == 1 {
+                return 'b'
+            } else if n == 2 {
+                return 'c'
+            } else {
+                return 'd'
+            }
+        }
+    """, """
+        fn get_char(n: u32) -> char {
+            return if n == 0 {
+                'a'
+            } else if n == 1 {
+                'b'
+            } else if n == 2 {
+                'c'
+            } else {
+                'd'
+            }
+        }
+    """, checkWeakWarn = true)
+
     fun `test lift return in match 1`() = checkFixByText("Lift return out of 'match'", """
         fn foo(x: bool) -> i32 {
             /*weak_warning descr="Return can be lifted out of 'match'"*/match/*caret*//*weak_warning**/ x {