Repository: intellij-rust/intellij-rust
Issue: "Remove braces from single expression" doesn't insert a comma

* [Recorded demonstration of bug](https://imgur.com/a/bTvBi)

Expected result:
```rust
match panic::catch_unwind(|| (f)(msg, args)) {
	Ok(inner) => inner,
	Err(err) => Err(CommandError(format!("{:?}", err)))
}
```

(Note the comma after `Ok(inner) => inner`)

Changed files:
src/test/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntentionTest.kt, src/main/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntention.kt

diff --git a/src/main/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntention.kt b/src/main/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntention.kt
index cbac99462..8ac2b4136 100644
--- a/src/main/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntention.kt
+++ b/src/main/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntention.kt
@@ -10,8 +10,10 @@ import com.intellij.openapi.project.Project
 import com.intellij.psi.PsiElement
 import org.rust.lang.core.psi.RsBlockExpr
 import org.rust.lang.core.psi.RsExpr
-import org.rust.lang.core.psi.ext.getNextNonCommentSibling
+import org.rust.lang.core.psi.RsMatchArm
+import org.rust.lang.core.psi.RsPsiFactory
 import org.rust.lang.core.psi.ext.ancestorStrict
+import org.rust.lang.core.psi.ext.getNextNonCommentSibling
 
 class UnwrapSingleExprIntention : RsElementBaseIntentionAction<RsBlockExpr>() {
     override fun getText() = "Remove braces from single expression"
@@ -30,7 +32,11 @@ class UnwrapSingleExprIntention : RsElementBaseIntentionAction<RsBlockExpr>() {
 
     override fun invoke(project: Project, editor: Editor, ctx: RsBlockExpr) {
         val blockBody = ctx.block.expr ?: return
-        val relativeCaretPosition = editor.caretModel.offset - blockBody.textOffset
+        val parent = ctx.parent
+        if (parent is RsMatchArm && parent.comma == null) {
+            parent.add(RsPsiFactory(project).createComma())
+        }
+        val relativeCaretPosition = Math.min(Math.max(editor.caretModel.offset - blockBody.textOffset, 0), blockBody.textLength)
 
         val offset = (ctx.replace(blockBody) as RsExpr).textOffset
         editor.caretModel.moveToOffset(offset + relativeCaretPosition)
diff --git a/src/test/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntentionTest.kt
index aa1c5ef5d..eeae366a6 100644
--- a/src/test/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntentionTest.kt
+++ b/src/test/kotlin/org/rust/ide/intentions/UnwrapSingleExprIntentionTest.kt
@@ -5,110 +5,140 @@
 
 package org.rust.ide.intentions
 
-import org.intellij.lang.annotations.Language
-import org.rust.lang.RsFileType
-import org.rust.lang.RsTestBase
-
-class UnwrapSingleExprIntentionTest : RsTestBase() {
-    fun `test available lambda unwrap braces single expression`() = doAvailableTest(
-        """
+class UnwrapSingleExprIntentionTest : RsIntentionTestBase(UnwrapSingleExprIntention()) {
+    fun `test available lambda unwrap braces single expression`() = doAvailableTest("""
         fn main() {
             {
-                4<caret>2
+                4/*caret*/2
             }
         }
-        """
-        ,
-        """
+    """, """
         fn main() {
-            4<caret>2
+            4/*caret*/2
         }
-        """
-    )
+    """)
 
-    fun `test available lambda unwrap braces`() = doAvailableTest(
-        """
+    fun `test available lambda unwrap braces`() = doAvailableTest("""
         fn main() {
-            |x| { x *<caret> x }
+            |x| { x */*caret*/ x }
         }
-        """
-        ,
-        """
+    """, """
         fn main() {
-            |x| x *<caret> x
+            |x| x */*caret*/ x
         }
-        """
-    )
+    """)
 
-    fun `test available unwrap braces single expression if`() = doAvailableTest(
-        """
+    fun `test available unwrap braces single expression if`() = doAvailableTest("""
         fn main() {
             let a = {
                 if (true) {
                     42
-                } else<caret> {
+                } else/*caret*/ {
                     43
                 }
             };
         }
-        """
-        ,
-        """
+    """, """
         fn main() {
             let a = if (true) {
                 42
-            } else<caret> {
+            } else/*caret*/ {
                 43
             };
         }
-        """
-    )
+    """)
 
-    fun `test available lambda unwrap braces single statement`() = doUnavailableTest(
-        """
+    fun `test available lambda unwrap braces single statement`() = doUnavailableTest("""
         fn main() {
             {
-                <caret>42;
+                /*caret*/42;
             }
         }
-        """
-    )
+    """)
 
-    fun `test unavailable unwrap braces`() = doUnavailableTest(
-        """
+    fun `test unavailable unwrap braces`() = doUnavailableTest("""
         fn main() {
-            |x| { let a = 3; x *<caret> a
+            |x| { let a = 3; x */*caret*/ a
             }
-        """
-    )
+    """)
 
-    fun `test unavailable unwrap braces let`() = doUnavailableTest(
-        """
+    fun `test unavailable unwrap braces let`() = doUnavailableTest("""
         fn main() {
             {
-                <caret>let a = 5;
+                /*caret*/let a = 5;
             }
         }
-        """
-    )
+    """)
+
+    fun `test unavailable unwrap braces unsafe`() = doUnavailableTest("""
+        fn main() {
+            let wellThen = unsafe/*caret*/ { magic() };
+        }
+    """)
 
-    fun `test unavailable unwrap braces unsafe`() = doUnavailableTest(
-        """
+    fun `test available unwrap braces single expression match`() = doAvailableTest("""
+        fn main() {
+            match x {
+                0 => {
+                    prin/*caret*/tln!("x = 0")
+                }
+            }
+        }
+    """, """
+        fn main() {
+            match x {
+                0 => prin/*caret*/tln!("x = 0"),
+            }
+        }
+    """)
+
+    fun `test available unwrap braces match with caret before`() = doAvailableTest("""
+        fn main() {
+            match x {
+                0 => /*caret*/{
+                    println!("x = 0")
+                }
+            }
+        }
+    """, """
         fn main() {
-            let wellThen = unsafe<caret> { magic() };
+            match x {
+                0 => /*caret*/println!("x = 0"),
+            }
         }
-        """
-    )
+    """)
 
-    private fun doAvailableTest(@Language("Rust") before: String, @Language("Rust") after: String) {
-        myFixture.configureByText(RsFileType, before)
-        myFixture.launchAction(UnwrapSingleExprIntention())
-        myFixture.checkResult(after)
-    }
+    fun `test available unwrap braces match with caret after`() = doAvailableTest("""
+        fn main() {
+            match x {
+                0 => {
+                    println!("x = 0")
+                }/*caret*/
+            }
+        }
+    """, """
+        fn main() {
+            match x {
+                0 => println!("x = 0")/*caret*/,
+            }
+        }
+    """)
 
-    private fun doUnavailableTest(@Language("Rust") before: String) {
-        myFixture.configureByText(RsFileType, before)
-        myFixture.launchAction(UnwrapSingleExprIntention())
-        myFixture.checkResult(before)
-    }
+    fun `test available unwrap braces multiple expression match`() = doAvailableTest("""
+        fn main() {
+            match x {
+                0 => /*caret*/{
+                    println!("x = 0")
+                }
+                _ => println!("x != 0")
+            }
+        }
+    """, """
+        fn main() {
+            match x {
+                0 => /*caret*/println!("x = 0"),
+                _ => println!("x != 0")
+            }
+        }
+    """)
 }