Repository: prettier/prettier (JavaScript)

Issue:
Unary `+` parameter triggers overeager breaking of method chain
**Prettier 2.7.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEAzCEAUB9AhgSgDoAjXAJ0yIBs44ZKBuAHSnSwFoCTzLCa7GLNpgDUXUhWq16+BiAA0ICAAcYAS2gBnZKHJkIAdwAK5BNpS4qB3AE9ti4mVxgA1nQDKuALZwAMmqg4ZFRLTTgHJ1cPZWcAgHNkGDIAV3CQOC9iOAATbJzfXCg45Nw4uAAxCDIvXBh1IuQQXGSYCAUQAAsYLyoAdQ61eE0YsDh3M0G1ADdBm0awTXsQALCyGCMnOJrg0LSAK00AD3d4mgBFZIh4HaowxRiyVcbSLKp25TIAmF61bJgO5AADgADPd9GFek5lI0PnBVlMgooAI6XeAbFTmJqadiBHI5dpkOAotSEjalbZIEK3NJhLxqRIpGmnOAXK5BSm7RQwXDEH5-AFIABMXKcaio8QAwhAvBT0poAKztZJhAAqPPMVLuICmqQAklA8rB3GBPqoAIIG9wwGw0G5hAC+9qAA)
<!-- prettier-ignore -->
```sh
--parser babel
```

**Input:**
<!-- prettier-ignore -->
```jsx
foo(_a).bar().leet();
foo(-a).bar().leet();
foo(+a).bar().leet();
```

**Output:**
<!-- prettier-ignore -->
```jsx
foo(_a).bar().leet();
foo(-a).bar().leet();
foo(+a)
  .bar()
  .leet();

```

**Expected behavior:**
```jsx
foo(_a).bar().leet();
foo(-a).bar().leet();
foo(+a).bar().leet();
```


Hints:
I have looked into this issue.
It seems that the Doc created by prettier is different for `+` parameter and other cases.
This Doc is created at the end of `printMemberChain` function in `src/language-js/print/member-chain.js`

https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/print/member-chain.js#L387-L405

In the above process, `isSimpleCallArgument` function is used in the if statement.
But, `+` unary expression does not appear to be properly processed in this function.

https://github.com/prettier/prettier/blob/a043ac0d733c4d53f980aa73807a63fc914f23bd/src/language-js/utils/index.js#L886-L891

I added `node.operator === "+"` in the above if state as a trial, and the output seemed to be expected.
(So, if you like, maybe I can send a PR about this issue.)
> So, if you like, maybe I can send a PR about this issue.

@t-mangoe Go ahead!
@sosukesuzuki
Thanks for your comment. I will send a PR.

Patch:
diff --git a/src/language-js/utils/index.js b/src/language-js/utils/index.js
--- a/src/language-js/utils/index.js
+++ b/src/language-js/utils/index.js
@@ -883,9 +883,26 @@ function isSimpleCallArgument(node, depth) {
     );
   }
 
+  const targetUnaryExpressionOperators = {
+    "!": true,
+    "-": true,
+    "+": true,
+    "~": true,
+  };
   if (
     node.type === "UnaryExpression" &&
-    (node.operator === "!" || node.operator === "-")
+    targetUnaryExpressionOperators[node.operator]
+  ) {
+    return isSimpleCallArgument(node.argument, depth);
+  }
+
+  const targetUpdateExpressionOperators = {
+    "++": true,
+    "--": true,
+  };
+  if (
+    node.type === "UpdateExpression" &&
+    targetUpdateExpressionOperators[node.operator]
   ) {
     return isSimpleCallArgument(node.argument, depth);
   }


Test patch:
diff --git a/tests/format/js/method-chain/13018.js b/tests/format/js/method-chain/13018.js
new file mode 100644
--- /dev/null
+++ b/tests/format/js/method-chain/13018.js
@@ -0,0 +1,8 @@
+foo(_a).bar().leet();
+foo(-a).bar().leet();
+foo(+a).bar().leet();
+foo(~a).bar().leet();
+foo(++a).bar().leet();
+foo(--a).bar().leet();
+foo(a++).bar().leet();
+foo(a--).bar().leet();
diff --git a/tests/format/js/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/method-chain/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/js/method-chain/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/js/method-chain/__snapshots__/jsfmt.spec.js.snap
@@ -1,5 +1,33 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`13018.js format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+foo(_a).bar().leet();
+foo(-a).bar().leet();
+foo(+a).bar().leet();
+foo(~a).bar().leet();
+foo(++a).bar().leet();
+foo(--a).bar().leet();
+foo(a++).bar().leet();
+foo(a--).bar().leet();
+
+=====================================output=====================================
+foo(_a).bar().leet();
+foo(-a).bar().leet();
+foo(+a).bar().leet();
+foo(~a).bar().leet();
+foo(++a).bar().leet();
+foo(--a).bar().leet();
+foo(a++).bar().leet();
+foo(a--).bar().leet();
+
+================================================================================
+`;
+
 exports[`bracket_0.js format 1`] = `
 ====================================options=====================================
 parsers: ["babel", "flow", "typescript"]