Repository: prettier/prettier (JavaScript)
Date: 2017-01-23 04:28:14+00:00
Task type: Bug Fix

Issue:
Don't output trailing commas for flow in arguments array pattern
```js
a = ([s=1,]) => 1
```

throws with the flow parser (but not babylon) https://github.com/facebook/flow/issues/3247

We should workaround by not outputting trailing commas there.


Issue discussion:

Solution patch:
diff --git a/src/printer.js b/src/printer.js
index c7c2873ef2c4..cae7878ae7f9 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -609,12 +609,24 @@ function genericPrintNoParens(path, options, print) {
     case "Decorator":
       return concat([ "@", path.call(print, "expression") ]);
     case "ArrayExpression":
-    case "ArrayPattern":
+    case "ArrayPattern": {
       if (n.elements.length === 0) {
         parts.push("[]");
       } else {
         const lastElem = util.getLast(n.elements);
-        const canHaveTrailingComma = !(lastElem && lastElem.type === "RestElement");
+        let canHaveTrailingComma = !(lastElem && lastElem.type === "RestElement");
+
+        // There's a bug with flow 0.38 where trailing commas are triggering
+        // parse errors for array patterns in arguments of a function
+        const parent = path.getParentNode(0);
+        if (options.parser === 'flow' &&
+          n.type === "ArrayPattern" &&
+          parent && (
+          parent.type === 'FunctionExpression' ||
+          parent.type === 'FunctionDeclaration' ||
+          parent.type === 'ArrowFunctionExpression')) {
+          canHaveTrailingComma = false;
+        }
 
         // JavaScript allows you to have empty elements in an array which
         // changes its length based on the number of commas. The algorithm
@@ -655,6 +667,7 @@ function genericPrintNoParens(path, options, print) {
       if (n.typeAnnotation) parts.push(path.call(print, "typeAnnotation"));
 
       return concat(parts);
+    }
     case "SequenceExpression":
       return join(", ", path.map(print, "expressions"));
     case "ThisExpression":


Test patch:
diff --git a/tests/array_trailing_comma/__snapshots__/jsfmt.spec.js.snap b/tests/array_trailing_comma/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..5171c2359d55
--- /dev/null
+++ b/tests/array_trailing_comma/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,69 @@
+exports[`test trailing_comma.js 1`] = `
+"f = ([s=1]) => 1;
+function f([s=1]){};
+f = function([s=1]){};
+class c {a([s=1]){}}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+f = (
+  [
+    s = 1
+  ],
+) =>
+  1;
+function f(
+  [
+    s = 1
+  ],
+) {
+}
+f = function(
+  [
+    s = 1
+  ],
+) {
+};
+class c {
+  a(
+    [
+      s = 1
+    ],
+  ) {
+  }
+}
+"
+`;
+
+exports[`test trailing_comma.js 2`] = `
+"f = ([s=1]) => 1;
+function f([s=1]){};
+f = function([s=1]){};
+class c {a([s=1]){}}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+f = (
+  [
+    s = 1,
+  ],
+) =>
+  1;
+function f(
+  [
+    s = 1,
+  ],
+) {
+}
+f = function(
+  [
+    s = 1,
+  ],
+) {
+};
+class c {
+  a(
+    [
+      s = 1,
+    ],
+  ) {
+  }
+}
+"
+`;
diff --git a/tests/array_trailing_comma/jsfmt.spec.js b/tests/array_trailing_comma/jsfmt.spec.js
new file mode 100644
index 000000000000..cfda4f52c0eb
--- /dev/null
+++ b/tests/array_trailing_comma/jsfmt.spec.js
@@ -0,0 +1,2 @@
+run_spec(__dirname, {printWidth: 1, trailingComma: true});
+run_spec(__dirname, {printWidth: 1, trailingComma: true, parser: 'babylon'});
diff --git a/tests/array_trailing_comma/trailing_comma.js b/tests/array_trailing_comma/trailing_comma.js
new file mode 100644
index 000000000000..5b953b32f8de
--- /dev/null
+++ b/tests/array_trailing_comma/trailing_comma.js
@@ -0,0 +1,4 @@
+f = ([s=1]) => 1;
+function f([s=1]){};
+f = function([s=1]){};
+class c {a([s=1]){}}