Repository: intellij-rust/intellij-rust
Issue: Remove dbg! action doesn't save brackets when they needs

## Environment

* **IntelliJ Rust plugin version:**
0.3.130.3337-202
* **Rust toolchain version:**
rustc 1.46.0 (04488afe3 2020-08-24)
* **IDE name and version:**
CLion 2020.2.1
* **Operating system:**
Arch Linux

## Problem description
Action `Remove dbg!` works incorrectly in the case where `dbg!` macro call is important for  the priority of operations.

## Steps to reproduce
- Write the following code.
```rust
fn main() {
    assert_eq!(dbg!(1 + 1) * 2, 4);
}
```
- `Alt-Enter` -> `Remove dbg!`
- expected: `(1 + 1) * 2`
- actual: `1 + 1 * 2`


Changed files:
src/test/kotlin/org/rust/ide/intentions/RemoveDbgIntentionTest.kt, src/main/kotlin/org/rust/ide/intentions/RemoveDbgIntention.kt

diff --git a/src/main/kotlin/org/rust/ide/intentions/RemoveDbgIntention.kt b/src/main/kotlin/org/rust/ide/intentions/RemoveDbgIntention.kt
index 17cd46954..d85feffc6 100644
--- a/src/main/kotlin/org/rust/ide/intentions/RemoveDbgIntention.kt
+++ b/src/main/kotlin/org/rust/ide/intentions/RemoveDbgIntention.kt
@@ -9,7 +9,10 @@ import com.intellij.openapi.editor.Editor
 import com.intellij.openapi.project.Project
 import com.intellij.psi.PsiDocumentManager
 import com.intellij.psi.PsiElement
+import org.rust.lang.core.psi.RsBinaryExpr
+import org.rust.lang.core.psi.RsDotExpr
 import org.rust.lang.core.psi.RsMacroCall
+import org.rust.lang.core.psi.RsPsiFactory
 import org.rust.lang.core.psi.ext.*
 import kotlin.math.max
 import kotlin.math.min
@@ -42,8 +45,14 @@ class RemoveDbgIntention : RsElementBaseIntentionAction<RsMacroCall>() {
 
     override fun invoke(project: Project, editor: Editor, ctx: RsMacroCall) {
         val expr = ctx.exprMacroArgument?.expr ?: return
-        val cursorOffsetToExpr = max(0, editor.caretModel.offset - expr.startOffset)
-        val newExpr = ctx.replaceWithExpr(expr)
+        var cursorOffsetToExpr = max(0, editor.caretModel.offset - expr.startOffset)
+        val parent = ctx.parent.parent
+        val newExpr = if (expr is RsBinaryExpr && (parent is RsBinaryExpr || parent is RsDotExpr)) {
+            cursorOffsetToExpr += 1
+            ctx.replaceWithExpr(RsPsiFactory(project).createExpression("(${expr.text})"))
+        } else {
+            ctx.replaceWithExpr(expr)
+        }
         PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
         editor.caretModel.moveToOffset(min(newExpr.startOffset + cursorOffsetToExpr, newExpr.endOffset))
     }
diff --git a/src/test/kotlin/org/rust/ide/intentions/RemoveDbgIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/RemoveDbgIntentionTest.kt
index 5cd8f9655..2f6eeb977 100644
--- a/src/test/kotlin/org/rust/ide/intentions/RemoveDbgIntentionTest.kt
+++ b/src/test/kotlin/org/rust/ide/intentions/RemoveDbgIntentionTest.kt
@@ -48,7 +48,7 @@ class RemoveDbgIntentionTest : RsIntentionTestBase(RemoveDbgIntention::class) {
         fn f1(a: usize, b: usize) {}
 
         fn test() {
-            f1(1 + (3 + 1/*caret*/) * 2), dbg!(10));
+            f1(1 + ((3 + 1/*caret*/) * 2)), dbg!(10));
         }
     """)
 
@@ -97,6 +97,25 @@ class RemoveDbgIntentionTest : RsIntentionTestBase(RemoveDbgIntention::class) {
         }
     """)
 
+    fun `test remove dbg! with binary expr`() = doAvailableTest("""
+        fn main() {
+            assert_eq!(dbg!(/*caret*/1 + 1) * 2, 4);
+        }
+    """, """
+        fn main() {
+            assert_eq!((/*caret*/1 + 1) * 2, 4);
+        }
+    """)
+
+    fun `test remove dbg! with dot expr`() = doAvailableTest("""
+        fn main() {
+            assert_eq!(dbg!(1i32 - 2/*caret*/).abs(), 1);
+        }
+    """, """
+        fn main() {
+            assert_eq!((1i32 - 2/*caret*/).abs(), 1);
+        }
+    """)
 
     fun `test cursor in dbg!`() = doAvailableTest("""
         fn test() {