Repository: jlongster/prettier (js)

Issue:
Invalid binary + and ++ for a member expression
```js
+ ++x.a
```

outputs

```js
+++x.a
```

which is invalid

https://jlongster.github.io/prettier/#%7B%22content%22%3A%22%2B%20%2B%2Bx.a%22%2C%22options%22%3A%7B%22printWidth%22%3A80%2C%22tabWidth%22%3A2%2C%22singleQuote%22%3Afalse%2C%22trailingComma%22%3Afalse%2C%22bracketSpacing%22%3Atrue%2C%22doc%22%3Afalse%7D%7D

Pull request description:
Fix +++x
Fixes #379

Patch:
diff --git a/src/fast-path.js b/src/fast-path.js
index 733500b64..89a955529 100644
--- a/src/fast-path.js
+++ b/src/fast-path.js
@@ -245,6 +245,13 @@ FPp.needsParens = function(assumeExpressionContext) {
         case "NewExpression":
           return true;
 
+        case "UnaryExpression":
+          if (node.prefix &&
+            ((node.operator === '++' && parent.operator === '+') ||
+              (node.operator === '--' && parent.operator === '-'))) {
+            return true;
+          }
+
         return false;
       }
 
diff --git a/src/printer.js b/src/printer.js
index 1f7f503d4..8b197e5b9 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -613,6 +613,9 @@ function genericPrintNoParens(path, options, print) {
       if (n.elements.length === 0) {
         parts.push("[]");
       } else {
+        const lastElem = util.getLast(n.elements);
+        const canHaveTrailingComma = !(lastElem && lastElem.type === "RestElement");
+
         // JavaScript allows you to have empty elements in an array which
         // changes its length based on the number of commas. The algorithm
         // is that if the last argument is null, we need to force insert
@@ -623,7 +626,7 @@ function genericPrintNoParens(path, options, print) {
         //
         // Note that util.getLast returns null if the array is empty, but
         // we already check for an empty array just above so we are safe
-        const needsForcedTrailingComma = util.getLast(n.elements) === null;
+        const needsForcedTrailingComma = canHaveTrailingComma && lastElem === null;
 
         parts.push(
           multilineGroup(
@@ -637,7 +640,11 @@ function genericPrintNoParens(path, options, print) {
                 ])
               ),
               needsForcedTrailingComma ? "," : "",
-              ifBreak(!needsForcedTrailingComma && options.trailingComma ? "," : ""),
+              ifBreak(
+                canHaveTrailingComma &&
+                !needsForcedTrailingComma &&
+                options.trailingComma ? "," : ""
+              ),
               options.bracketSpacing ? line : softline,
               "]"
             ])


Test patch:
diff --git a/tests/rest/__snapshots__/jsfmt.spec.js.snap b/tests/rest/__snapshots__/jsfmt.spec.js.snap
index aaf012afd..362d5b2a6 100644
--- a/tests/rest/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/rest/__snapshots__/jsfmt.spec.js.snap
@@ -13,7 +13,9 @@ function f(
 
 declare class C { f(...superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong): void; }
 
-[superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong,,]
+[superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong,,];
+
+[veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLong, ...a] = [];
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 declare class C {
   f(
@@ -38,5 +40,10 @@ declare class C {
   superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong,
   ,
 ];
+
+[
+  veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLong,
+  ...a
+] = [];
 "
 `;
diff --git a/tests/rest/trailing-commas.js b/tests/rest/trailing-commas.js
index 8fabb7268..ab3e69284 100644
--- a/tests/rest/trailing-commas.js
+++ b/tests/rest/trailing-commas.js
@@ -12,4 +12,6 @@ function f(
 
 declare class C { f(...superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong): void; }
 
-[superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong,,]
+[superSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperSuperLong,,];
+
+[veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLong, ...a] = [];
diff --git a/tests/unary/__snapshots__/jsfmt.spec.js.snap b/tests/unary/__snapshots__/jsfmt.spec.js.snap
index e05030511..6a0b95b95 100644
--- a/tests/unary/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/unary/__snapshots__/jsfmt.spec.js.snap
@@ -1,3 +1,42 @@
+exports[`test series.js 1`] = `
+"1 + ++x;
+1 + x++;
+
++ ++x;
++ x++;
+
+x++ + 1;
+++x + 1;
+
+1 - --x;
+1 - x--;
+
+- --x;
+- x--;
+
+x-- - 1;
+--x - 1;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 + ++x;
+1 + x++;
+
++(++x);
++x++;
+
+x++ + 1;
+++x + 1;
+
+1 - --x;
+1 - x--;
+
+-(--x);
+-x--;
+
+x-- - 1;
+--x - 1;
+"
+`;
+
 exports[`test unary.js 1`] = `
 "/* @flow */
 
diff --git a/tests/unary/series.js b/tests/unary/series.js
new file mode 100644
index 000000000..9b4db0a4b
--- /dev/null
+++ b/tests/unary/series.js
@@ -0,0 +1,17 @@
+1 + ++x;
+1 + x++;
+
++ ++x;
++ x++;
+
+x++ + 1;
+++x + 1;
+
+1 - --x;
+1 - x--;
+
+- --x;
+- x--;
+
+x-- - 1;
+--x - 1;