Repository: jlongster/prettier
Pull request #342 (2017-01-19 22:23:53)

Introduce --parser/parser option and deprecate --flow-parser/useFlowParser
The previous API was inconsistent. The new one is

```js
--parser flow
--parser babylon

{parser: 'flow'}
{parser: 'babylon'}
```

if we ever want to add new parsers in the future it'll allow that more easily.

I put a console.log in parser.js in both functions and tested that the test suite worked both with and without the change in run_spec. I also tested that both the previous and new command line options are working.

At some point in the future we'll likely want to get rid of the old api but might as well keep supporting it so we don't break anyone for now.


Patch:
diff --git a/README.md b/README.md
index c924af50a..7928dc7a9 100644
--- a/README.md
+++ b/README.md
@@ -139,9 +139,6 @@ prettier.format(source, {
   // Number of spaces it should use per tab
   tabWidth: 2,
 
-  // Use the flow parser instead of babylon
-  useFlowParser: false,
-
   // If true, will use single instead of double quotes
   singleQuote: false,
 
@@ -149,7 +146,10 @@ prettier.format(source, {
   trailingComma: false,
 
   // Controls the printing of spaces inside array and objects
-  bracketSpacing: true
+  bracketSpacing: true,
+
+  // Which parser to use. Valid options are 'flow' and 'babylon'
+  parser: 'babylon'
 });
 ```
 
@@ -197,7 +197,7 @@ including non-standardized ones. By default it uses the
 [babylon](https://github.com/babel/babylon) parser with all language
 features enabled, but you can also use
 [flow](https://github.com/facebook/flow) parser with the
-`useFlowParser` API or `--flow-parser` CLI option.
+`parser` API or `--parser` CLI option.
 
 All of JSX and Flow syntax is supported. In fact, the test suite in
 `tests` *is* the entire Flow test suite and they all pass.
diff --git a/bin/prettier.js b/bin/prettier.js
index 57e5dd80f..c3b76ca16 100755
--- a/bin/prettier.js
+++ b/bin/prettier.js
@@ -10,13 +10,21 @@ const argv = minimist(process.argv.slice(2), {
   boolean: [
     "write",
     "stdin",
-    "flow-parser",
     "bracket-spacing",
     "single-quote",
     "trailing-comma",
-    "version"
+    "version",
+
+    // Deprecated in 0.0.10
+    "flow-parser"
+  ],
+  string: [
+    "parser"
   ],
-  default: { "bracket-spacing": true }
+  default: {
+    "bracket-spacing": true,
+    parser: "babylon",
+  }
 });
 
 if (argv["version"]) {
@@ -32,24 +40,37 @@ if (!filenames.length && !stdin) {
   console.log(
     "Usage: prettier [opts] [filename ...]\n\n" +
       "Available options:\n" +
-      "  --write              Edit the file in-place (beware!)\n" +
-      "  --stdin              Read input from stdin\n" +
-      "  --print-width <int>  Specify the length of line that the printer will wrap on. Defaults to 80.\n" +
-      "  --tab-width <int>    Specify the number of spaces per indentation-level. Defaults to 2.\n" +
-      "  --flow-parser        Use the flow parser instead of babylon\n" +
-      "  --single-quote       Use single quotes instead of double\n" +
-      "  --trailing-comma     Print trailing commas wherever possible\n" +
-      "  --bracket-spacing    Put spaces between brackets. Defaults to true, set false to turn off"
+      "  --write                  Edit the file in-place (beware!)\n" +
+      "  --stdin                  Read input from stdin\n" +
+      "  --print-width <int>      Specify the length of line that the printer will wrap on. Defaults to 80.\n" +
+      "  --tab-width <int>        Specify the number of spaces per indentation-level. Defaults to 2.\n" +
+      "  --parser <flow|babylon>  Specify which parse to use. Defaults to babylon\n" +
+      "  --single-quote           Use single quotes instead of double\n" +
+      "  --trailing-comma         Print trailing commas wherever possible\n" +
+      "  --bracket-spacing        Put spaces between brackets. Defaults to true, set false to turn off"
   );
   process.exit(1);
 }
 
+function getParser() {
+  // For backward compatibility. Deprecated in 0.0.10
+  if (argv["flow-parser"]) {
+    return "flow";
+  }
+
+  if (argv["parser"] === "flow") {
+    return "flow";
+  }
+
+  return "babylon";
+}
+
 function format(input) {
   return jscodefmt.format(input, {
     printWidth: argv["print-width"],
     tabWidth: argv["tab-width"],
     bracketSpacing: argv["bracket-spacing"],
-    useFlowParser: argv["flow-parser"],
+    parser: getParser(),
     singleQuote: argv["single-quote"],
     trailingComma: argv["trailing-comma"]
   });
diff --git a/index.js b/index.js
index 2826a29ed..19c4b183b 100644
--- a/index.js
+++ b/index.js
@@ -8,7 +8,7 @@ const normalizeOptions = require("./src/options").normalize;
 const parser = require("./src/parser");
 
 function parse(text, opts) {
-  if (opts.useFlowParser) {
+  if (opts.parser === 'flow') {
     return parser.parseWithFlow(text, opts.filename);
   }
   return parser.parseWithBabylon(text);
diff --git a/src/options.js b/src/options.js
index bd41a001d..ca6856c67 100644
--- a/src/options.js
+++ b/src/options.js
@@ -10,17 +10,27 @@ var defaults = {
   // Controls the printing of trailing commas wherever possible
   trailingComma: false,
   // Controls the printing of spaces inside array and objects
-  bracketSpacing: true
+  bracketSpacing: true,
+  // Which parser to use. Valid options are 'flow' and 'babylon'
+  parser: 'babylon'
 };
 
 // Copy options and fill in default values.
 function normalize(options) {
   const normalized = Object.assign({}, options || {});
+
+  // For backward compatibility. Deprecated in 0.0.10
+  if ('useFlowParser' in normalized) {
+    normalized.parser = normalized.useFlowParser ? 'flow' : 'babylon';
+    delete normalized.useFlowParser;
+  }
+
   Object.keys(defaults).forEach(k => {
     if (normalized[k] == null) {
       normalized[k] = defaults[k];
     }
   });
+
   return normalized;
 };
 
diff --git a/src/printer.js b/src/printer.js
index 82635eecd..176cbd1f7 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -1580,7 +1580,7 @@ function printPropertyKey(path, options, print) {
       isIdentifierName(node.value) &&
       // There's a bug in the flow parser where it throws if there are
       // unquoted unicode literals as keys. Let's quote them for now.
-      (!options.useFlowParser || node.value.match(/[a-zA-Z0-9$_]/))
+      (options.parser !== 'flow' || node.value.match(/[a-zA-Z0-9$_]/))
   ) {
     // 'a' -> a
     return node.value;
@@ -1823,9 +1823,9 @@ function printExportDeclaration(path, options, print) {
 
     if (
       decl.type === "ExportDefaultDeclaration" &&
-        (decl.declaration.type == "Identifier" ||
-          decl.declaration.type === "CallExpression" ||
-          typeIsFunction(decl.declaration.type))
+        (decl.declaration.type !== "ClassDeclaration" &&
+          decl.declaration.type !== "FunctionDeclaration" &&
+          decl.declaration.type !== "FunctionExpression")
     ) {
       parts.push(";");
     }
@@ -2055,7 +2055,7 @@ function printJSXChildren(path, options, print) {
         // correctly escaped (since it parsed).
         // We really want to use value and re-escape it ourself when possible
         // though.
-        const value = options.useFlowParser ?
+        const value = options.parser === 'flow' ?
           child.raw :
           util.htmlEscapeInsideAngleBracket(child.value);
 
@@ -2331,7 +2331,7 @@ function nodeStr(node, options) {
   // Workaround a bug in the Javascript version of the flow parser where
   // astral unicode characters like \uD801\uDC28 are incorrectly parsed as
   // a sequence of \uFFFD.
-  if (options.useFlowParser && result.indexOf("\\uFFFD") !== -1) {
+  if (options.parser === 'flow' && result.indexOf("\\uFFFD") !== -1) {
     return node.raw;
   }
 


Test patch:
diff --git a/tests/array_spread/jsfmt.spec.js b/tests/array_spread/jsfmt.spec.js
index fc83bcab9..d5ec770a9 100644
--- a/tests/array_spread/jsfmt.spec.js
+++ b/tests/array_spread/jsfmt.spec.js
@@ -1,2 +1,2 @@
 run_spec(__dirname);
-run_spec(__dirname, {useFlowParser: false});
+run_spec(__dirname, {parser: 'babylon'});
diff --git a/tests/comments/jsfmt.spec.js b/tests/comments/jsfmt.spec.js
index fc83bcab9..d5ec770a9 100644
--- a/tests/comments/jsfmt.spec.js
+++ b/tests/comments/jsfmt.spec.js
@@ -1,2 +1,2 @@
 run_spec(__dirname);
-run_spec(__dirname, {useFlowParser: false});
+run_spec(__dirname, {parser: 'babylon'});
diff --git a/tests/es6modules/__snapshots__/jsfmt.spec.js.snap b/tests/es6modules/__snapshots__/jsfmt.spec.js.snap
index efd59b9c1..6d3b824a2 100644
--- a/tests/es6modules/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/es6modules/__snapshots__/jsfmt.spec.js.snap
@@ -324,7 +324,7 @@ export var str = \'asdf\';
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 /* @flow */
 
-export default 42
+export default 42;
 export var str = \"asdf\";
 "
 `;
@@ -1366,7 +1366,7 @@ exports[`test export_default_function_expression.js 1`] = `
 "export default (function() {});
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 export default function() {
-};
+}
 "
 `;
 
diff --git a/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap b/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap
index 39cb63395..e67223f96 100644
--- a/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap
@@ -102,7 +102,7 @@ export default 42;
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 /* @flow */
 
-export default 42
+export default 42;
 "
 `;
 
diff --git a/tests/jsx_escape/jsfmt.spec.js b/tests/jsx_escape/jsfmt.spec.js
index fc83bcab9..d5ec770a9 100644
--- a/tests/jsx_escape/jsfmt.spec.js
+++ b/tests/jsx_escape/jsfmt.spec.js
@@ -1,2 +1,2 @@
 run_spec(__dirname);
-run_spec(__dirname, {useFlowParser: false});
+run_spec(__dirname, {parser: 'babylon'});
diff --git a/tests_config/run_spec.js b/tests_config/run_spec.js
index 43e3cdd41..6aacda4fa 100644
--- a/tests_config/run_spec.js
+++ b/tests_config/run_spec.js
@@ -82,7 +82,7 @@ function parse(string) {
 function prettyprint(src, filename, options) {
   return prettier.format(src, Object.assign({
     filename,
-    useFlowParser: true,
+    parser: 'flow',
     printWidth: 80,
   }, options));
 }