Add more expression to 'in_value'

When completing some expressions, it is almost always expected to have a non unit value

- ArrayExpr
- ParenExpr
- BreakExpr
- ReturnExpr
- PrefixExpr
- FormatArgsArg
- RecordExprField
- BinExpr (rhs only)
- IndexExpr (inside index only)

Example
---
```rust
fn main() {
    return $0;
}
```

**Before this PR**

```rust
fn main() {
    return if $1 {
        $0
    };
}
```

**After this PR**

```rust
fn main() {
    return if $1 {
        $2
    } else {
        $0
    };
}
```
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 6162d98..eab2b90 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -532,6 +532,146 @@
     }
 
     #[test]
+    fn if_completion_in_format() {
+        check_edit(
+            "if",
+            r#"
+//- minicore: fmt
+fn main() {
+    format_args!("{}", $0);
+}
+"#,
+            r#"
+fn main() {
+    format_args!("{}", if $1 {
+    $2
+} else {
+    $0
+});
+}
+"#,
+        );
+
+        check_edit(
+            "if",
+            r#"
+//- minicore: fmt
+fn main() {
+    format_args!("{}", if$0);
+}
+"#,
+            r#"
+fn main() {
+    format_args!("{}", if $1 {
+    $2
+} else {
+    $0
+});
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn if_completion_in_value_expected_expressions() {
+        check_edit(
+            "if",
+            r#"
+fn main() {
+    2 + $0;
+}
+"#,
+            r#"
+fn main() {
+    2 + if $1 {
+    $2
+} else {
+    $0
+};
+}
+"#,
+        );
+
+        check_edit(
+            "if",
+            r#"
+fn main() {
+    -$0;
+}
+"#,
+            r#"
+fn main() {
+    -if $1 {
+    $2
+} else {
+    $0
+};
+}
+"#,
+        );
+
+        check_edit(
+            "if",
+            r#"
+fn main() {
+    return $0;
+}
+"#,
+            r#"
+fn main() {
+    return if $1 {
+    $2
+} else {
+    $0
+};
+}
+"#,
+        );
+
+        check_edit(
+            "if",
+            r#"
+fn main() {
+    loop {
+        break $0;
+    }
+}
+"#,
+            r#"
+fn main() {
+    loop {
+        break if $1 {
+    $2
+} else {
+    $0
+};
+    }
+}
+"#,
+        );
+
+        check_edit(
+            "if",
+            r#"
+struct Foo { x: i32 }
+fn main() {
+    Foo { x: $0 }
+}
+"#,
+            r#"
+struct Foo { x: i32 }
+fn main() {
+    Foo { x: if $1 {
+    $2
+} else {
+    $0
+} }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn completes_let_in_block() {
         check_edit(
             "let",
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index b3d9ff0..d6d3978 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1012,6 +1012,25 @@
             .and_then(|next| next.first_token())
             .is_some_and(|token| token.kind() == SyntaxKind::ELSE_KW)
     };
+    let is_in_value = |it: &SyntaxNode| {
+        let Some(node) = it.parent() else { return false };
+        let kind = node.kind();
+        ast::LetStmt::can_cast(kind)
+            || ast::ArgList::can_cast(kind)
+            || ast::ArrayExpr::can_cast(kind)
+            || ast::ParenExpr::can_cast(kind)
+            || ast::BreakExpr::can_cast(kind)
+            || ast::ReturnExpr::can_cast(kind)
+            || ast::PrefixExpr::can_cast(kind)
+            || ast::FormatArgsArg::can_cast(kind)
+            || ast::RecordExprField::can_cast(kind)
+            || ast::BinExpr::cast(node.clone())
+                .and_then(|expr| expr.rhs())
+                .is_some_and(|expr| expr.syntax() == it)
+            || ast::IndexExpr::cast(node)
+                .and_then(|expr| expr.index())
+                .is_some_and(|expr| expr.syntax() == it)
+    };
 
     // We do not want to generate path completions when we are sandwiched between an item decl signature and its body.
     // ex. trait Foo $0 {}
@@ -1307,7 +1326,7 @@
             .and_then(ast::LetStmt::cast)
             .is_some_and(|it| it.semicolon_token().is_none())
             || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw;
-        let in_value = it.parent().and_then(Either::<ast::LetStmt, ast::ArgList>::cast).is_some();
+        let in_value = is_in_value(it);
         let impl_ = fetch_immediate_impl_or_trait(sema, original_file, expr.syntax())
             .and_then(Either::left);