From 9a1e408a3ffa8a8bf0cf2e4c4ce05cd4abbdfbf9 Mon Sep 17 00:00:00 2001
From: Stephen Scott
Date: Sun, 26 Nov 2017 15:51:48 -0700
Subject: [PATCH 1/9] Add option and specs (no implementation yet)
These new snapshots are from https://github.com/prettier/prettier/pull/2676
---
docs/options.md | 13 +
src/cli-constant.js | 17 +
src/options.js | 3 +-
.../__snapshots__/jsfmt.spec.js.snap | 95 ++++
tests/arrow-call/jsfmt.spec.js | 1 +
tests/arrows/__snapshots__/jsfmt.spec.js.snap | 510 ++++++++++++++++++
tests/arrows/arrow_function_expression.js | 4 +
tests/arrows/currying.js | 6 +
tests/arrows/jsfmt.spec.js | 7 +-
tests/arrows/parens.js | 15 +
.../__snapshots__/early-exit.js.snap | 24 +
11 files changed, 693 insertions(+), 2 deletions(-)
create mode 100644 tests/arrows/parens.js
diff --git a/docs/options.md b/docs/options.md
index 8a9cfee7a..b3d83cfd4 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -96,6 +96,19 @@ Put the `>` of a multi-line JSX element at the end of the last line instead of b
| ------- | ------------------------- | ---------------------------- |
| `false` | `--jsx-bracket-same-line` | `jsxBracketSameLine: ` |
+# Arrow Function Parentheses
+
+Include parentheses around a sole arrow function parameter.
+
+Valid options:
+
+* `"avoid"` - Omit parens when possible. Example: `x => x`
+* `"always"` - Always include parens. Example: `(x) => x`
+
+| Default | CLI Override | API Override |
+| --------- | --------------------------------------------------------- | ------------------------------------------------------- |
+| `"avoid"` | --arrow-function-parens | arrowFunctionParentheses: "" |
+
## Range
Format only a segment of a file.
diff --git a/src/cli-constant.js b/src/cli-constant.js
index 92ce7e371..376c718b9 100644
--- a/src/cli-constant.js
+++ b/src/cli-constant.js
@@ -77,6 +77,23 @@ const categoryOrder = [
* Note: The options below are sorted alphabetically.
*/
const detailedOptions = normalizeDetailedOptions({
+ "arrow-function-parentheses": {
+ type: "choice",
+ category: CATEGORY_FORMAT,
+ forwardToApi: true,
+ description: "Include parentheses around a sole arrow function parameter.",
+ default: "avoid",
+ choices: [
+ {
+ value: "avoid",
+ description: "Omit parens when possible. Example: `x => x`"
+ },
+ {
+ value: "always",
+ description: "Always include parens. Example: `(x) => x`"
+ }
+ ]
+ },
"bracket-spacing": {
type: "boolean",
category: CATEGORY_FORMAT,
diff --git a/src/options.js b/src/options.js
index 19c34ab80..87ba34028 100644
--- a/src/options.js
+++ b/src/options.js
@@ -21,7 +21,8 @@ const defaults = {
insertPragma: false,
requirePragma: false,
semi: true,
- proseWrap: true
+ proseWrap: true,
+ arrowFunctionParentheses: "avoid"
};
const exampleConfig = Object.assign({}, defaults, {
diff --git a/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap b/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
index 0597d87a7..006da744c 100644
--- a/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
@@ -189,3 +189,98 @@ const composition = (ViewComponent, ContainerComponent) =>
};
`;
+
+exports[`arrow_call.js 3`] = `
+const testResults = results.testResults.map(testResult =>
+ formatResult(testResult, formatter, reporter)
+);
+
+it('mocks regexp instances', () => {
+ expect(
+ () => moduleMocker.generateFromMetadata(moduleMocker.getMetadata(/a/)),
+ ).not.toThrow();
+});
+
+expect(() => asyncRequest({ url: "/test-endpoint" }))
+ .toThrowError(/Required parameter/);
+
+expect(() => asyncRequest({ url: "/test-endpoint-but-with-a-long-url" }))
+ .toThrowError(/Required parameter/);
+
+expect(() => asyncRequest({ url: "/test-endpoint-but-with-a-suuuuuuuuper-long-url" }))
+ .toThrowError(/Required parameter/);
+
+expect(() => asyncRequest({ type: "foo", url: "/test-endpoint" }))
+ .not.toThrowError();
+
+expect(() => asyncRequest({ type: "foo", url: "/test-endpoint-but-with-a-long-url" }))
+ .not.toThrowError();
+
+const a = Observable
+ .fromPromise(axiosInstance.post('/carts/mine'))
+ .map((response) => response.data)
+
+const b = Observable.fromPromise(axiosInstance.get(url))
+ .map((response) => response.data)
+
+func(
+ veryLoooooooooooooooooooooooongName,
+ veryLooooooooooooooooooooooooongName =>
+ veryLoooooooooooooooongName.something()
+);
+
+const composition = (ViewComponent, ContainerComponent) =>
+ class extends React.Component {
+ static propTypes = {};
+ };
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+const testResults = results.testResults.map(testResult =>
+ formatResult(testResult, formatter, reporter)
+);
+
+it("mocks regexp instances", () => {
+ expect(() =>
+ moduleMocker.generateFromMetadata(moduleMocker.getMetadata(/a/))
+ ).not.toThrow();
+});
+
+expect(() => asyncRequest({ url: "/test-endpoint" })).toThrowError(
+ /Required parameter/
+);
+
+expect(() =>
+ asyncRequest({ url: "/test-endpoint-but-with-a-long-url" })
+).toThrowError(/Required parameter/);
+
+expect(() =>
+ asyncRequest({ url: "/test-endpoint-but-with-a-suuuuuuuuper-long-url" })
+).toThrowError(/Required parameter/);
+
+expect(() =>
+ asyncRequest({ type: "foo", url: "/test-endpoint" })
+).not.toThrowError();
+
+expect(() =>
+ asyncRequest({ type: "foo", url: "/test-endpoint-but-with-a-long-url" })
+).not.toThrowError();
+
+const a = Observable.fromPromise(axiosInstance.post("/carts/mine")).map(
+ response => response.data
+);
+
+const b = Observable.fromPromise(axiosInstance.get(url)).map(
+ response => response.data
+);
+
+func(
+ veryLoooooooooooooooooooooooongName,
+ veryLooooooooooooooooooooooooongName =>
+ veryLoooooooooooooooongName.something()
+);
+
+const composition = (ViewComponent, ContainerComponent) =>
+ class extends React.Component {
+ static propTypes = {};
+ };
+
+`;
diff --git a/tests/arrow-call/jsfmt.spec.js b/tests/arrow-call/jsfmt.spec.js
index 4e02696c9..db45d9868 100644
--- a/tests/arrow-call/jsfmt.spec.js
+++ b/tests/arrow-call/jsfmt.spec.js
@@ -1,2 +1,3 @@
run_spec(__dirname, null, ["typescript"]);
run_spec(__dirname, { trailingComma: "all" }, ["typescript"]);
+run_spec(__dirname, { arrowFunctionParentheses: "always" }, ["typescript"]);
diff --git a/tests/arrows/__snapshots__/jsfmt.spec.js.snap b/tests/arrows/__snapshots__/jsfmt.spec.js.snap
index 065c38271..c4794e33f 100644
--- a/tests/arrows/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/arrows/__snapshots__/jsfmt.spec.js.snap
@@ -32,6 +32,10 @@ x => (y = z);
x => (y += z);
f(a => ({})) + 1;
(a => ({})) || 0;
+a = b => c;
+a = b => {
+ return c
+};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(a => {}).length;
typeof (() => {});
@@ -65,6 +69,86 @@ x => (y = z);
x => (y += z);
f(a => ({})) + 1;
(a => ({})) || 0;
+a = b => c;
+a = b => {
+ return c;
+};
+
+`;
+
+exports[`arrow_function_expression.js 2`] = `
+(a => {}).length
+typeof (() => {});
+export default (() => {})();
+(() => {})()\`\`;
+(() => {})\`\`;
+new (() => {});
+if ((() => {}) ? 1 : 0) {}
+let f = () => ({}())
+let a = () => ({} instanceof a);
+a = () => ({} && a);
+a = () => ({}() && a);
+a = () => ({} && a && b);
+a = () => ({} + a);
+a = () => ({}()() && a);
+a = () => ({}.b && a);
+a = () => ({}[b] && a);
+a = () => ({}\`\` && a);
+a = () => ({} = 0);
+a = () => ({}, a);
+a => a instanceof {};
+a => ({}().b && 0)
+a => ({}().c = 0)
+x => ({}()())
+x => ({}()\`\`)
+x => ({}().b);
+a = b => c;
+a = (b?) => c;
+x => (y = z);
+x => (y += z);
+f(a => ({})) + 1;
+(a => ({})) || 0;
+a = b => c;
+a = b => {
+ return c
+};
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(a => {}).length;
+typeof (() => {});
+export default (() => {})();
+(() => {})()\`\`;
+(() => {})\`\`;
+new (() => {})();
+if ((() => {}) ? 1 : 0) {
+}
+let f = () => ({}());
+let a = () => ({} instanceof a);
+a = () => ({} && a);
+a = () => ({}() && a);
+a = () => ({} && a && b);
+a = () => ({} + a);
+a = () => ({}()() && a);
+a = () => ({}.b && a);
+a = () => ({}[b] && a);
+a = () => ({}\`\` && a);
+a = () => ({} = 0);
+a = () => ({}, a);
+a => a instanceof {};
+a => ({}().b && 0);
+a => ({}().c = 0);
+x => ({}()());
+x => ({}()\`\`);
+x => ({}().b);
+a = b => c;
+a = (b?) => c;
+x => (y = z);
+x => (y += z);
+f(a => ({})) + 1;
+(a => ({})) || 0;
+a = b => c;
+a = b => {
+ return c;
+};
`;
@@ -75,6 +159,13 @@ a = () => ({} = this);
`;
+exports[`block_like.js 2`] = `
+a = () => ({} = this);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+a = () => ({} = this);
+
+`;
+
exports[`call.js 1`] = `
Seq(typeDef.interface.groups).forEach(group =>
Seq(group.members).forEach((member, memberName) =>
@@ -248,6 +339,179 @@ fooooooooooooooooooooooooooooooooooooooooooooooooooo(action => next =>
`;
+exports[`call.js 2`] = `
+Seq(typeDef.interface.groups).forEach(group =>
+ Seq(group.members).forEach((member, memberName) =>
+ markdownDoc(
+ member.doc,
+ { typePath: typePath.concat(memberName.slice(1)),
+ signatures: member.signatures }
+ )
+ )
+)
+
+const promiseFromCallback = fn =>
+ new Promise((resolve, reject) =>
+ fn((err, result) => {
+ if (err) return reject(err);
+ return resolve(result);
+ })
+ );
+
+runtimeAgent.getProperties(
+ objectId,
+ false, // ownProperties
+ false, // accessorPropertiesOnly
+ false, // generatePreview
+ (error, properties, internalProperties) => {
+ return 1
+ },
+);
+
+function render() {
+ return (
+
+ this.setState({progress: Math.round(100 * e.nativeEvent.loaded / e.nativeEvent.total)})}
+ />
+
+ );
+}
+
+function render() {
+ return (
+
+
+ this.setState({
+ progress: Math.round(
+ 100 * e.nativeEvent.loaded / e.nativeEvent.total,
+ ),
+ })}
+ />
+
+ );
+}
+
+function render() {
+ return (
+
+
+ this.setState({
+ progress: Math.round(
+ 100 * e.nativeEvent.loaded / e.nativeEvent.total,
+ ),
+ })}
+ />
+
+ );
+}
+
+jest.mock(
+ '../SearchSource',
+ () => class {
+ findMatchingTests(pattern) {
+ return {paths: []};
+ }
+ },
+);
+
+fooooooooooooooooooooooooooooooooooooooooooooooooooo(action => next =>
+ dispatch(action),
+);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Seq(typeDef.interface.groups).forEach(group =>
+ Seq(group.members).forEach((member, memberName) =>
+ markdownDoc(member.doc, {
+ typePath: typePath.concat(memberName.slice(1)),
+ signatures: member.signatures
+ })
+ )
+);
+
+const promiseFromCallback = fn =>
+ new Promise((resolve, reject) =>
+ fn((err, result) => {
+ if (err) return reject(err);
+ return resolve(result);
+ })
+ );
+
+runtimeAgent.getProperties(
+ objectId,
+ false, // ownProperties
+ false, // accessorPropertiesOnly
+ false, // generatePreview
+ (error, properties, internalProperties) => {
+ return 1;
+ }
+);
+
+function render() {
+ return (
+
+
+ this.setState({
+ progress: Math.round(
+ 100 * e.nativeEvent.loaded / e.nativeEvent.total
+ )
+ })
+ }
+ />
+
+ );
+}
+
+function render() {
+ return (
+
+
+ this.setState({
+ progress: Math.round(
+ 100 * e.nativeEvent.loaded / e.nativeEvent.total
+ )
+ })
+ }
+ />
+
+ );
+}
+
+function render() {
+ return (
+
+
+ this.setState({
+ progress: Math.round(
+ 100 * e.nativeEvent.loaded / e.nativeEvent.total
+ )
+ })
+ }
+ />
+
+ );
+}
+
+jest.mock(
+ "../SearchSource",
+ () =>
+ class {
+ findMatchingTests(pattern) {
+ return { paths: [] };
+ }
+ }
+);
+
+fooooooooooooooooooooooooooooooooooooooooooooooooooo(action => next =>
+ dispatch(action)
+);
+
+`;
+
exports[`comment.js 1`] = `
/**
* Curried function that ends with a BEM CSS Selector
@@ -313,11 +577,82 @@ export const bem = block =>
`;
+exports[`comment.js 2`] = `
+/**
+ * Curried function that ends with a BEM CSS Selector
+ *
+ * @param {String} block - the BEM Block you'd like to select.
+ * @returns {Function}
+ */
+export const bem = block =>
+ /**
+ * @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
+ * @returns {Function}
+ */
+ element =>
+ /**
+ * @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
+ * @returns {String}
+ */
+ modifier =>
+ [
+ ".",
+ css(block),
+ element ? \`__\${css(element)}\` : "",
+ modifier ? \`--\${css(modifier)}\` : ""
+ ].join("");
+
+ {info.item.widget.missingProp}}
+ data={data}
+/>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/**
+ * Curried function that ends with a BEM CSS Selector
+ *
+ * @param {String} block - the BEM Block you'd like to select.
+ * @returns {Function}
+ */
+export const bem = block =>
+ /**
+ * @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
+ * @returns {Function}
+ */
+ element =>
+ /**
+ * @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
+ * @returns {String}
+ */
+ modifier =>
+ [
+ ".",
+ css(block),
+ element ? \`__\${css(element)}\` : "",
+ modifier ? \`--\${css(modifier)}\` : ""
+ ].join("");
+
+ {info.item.widget.missingProp}}
+ data={data}
+/>;
+
+`;
+
exports[`currying.js 1`] = `
const fn = b => c => d => {
return 3;
};
+const foo = (a, b) => c => d => {
+ return 3;
+};
+
+const bar = a => b => c => a + b + c
+
const mw = store => next => action => {
return next(action)
}
@@ -330,6 +665,51 @@ const fn = b => c => d => {
return 3;
};
+const foo = (a, b) => c => d => {
+ return 3;
+};
+
+const bar = a => b => c => a + b + c;
+
+const mw = store => next => action => {
+ return next(action);
+};
+
+const middleware = options => (req, res, next) => {
+ // ...
+};
+
+`;
+
+exports[`currying.js 2`] = `
+const fn = b => c => d => {
+ return 3;
+};
+
+const foo = (a, b) => c => d => {
+ return 3;
+};
+
+const bar = a => b => c => a + b + c
+
+const mw = store => next => action => {
+ return next(action)
+}
+
+const middleware = options => (req, res, next) => {
+ // ...
+};
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+const fn = b => c => d => {
+ return 3;
+};
+
+const foo = (a, b) => c => d => {
+ return 3;
+};
+
+const bar = a => b => c => a + b + c;
+
const mw = store => next => action => {
return next(action);
};
@@ -350,6 +730,16 @@ veryLongCall(
`;
+exports[`long-call-no-args.js 2`] = `
+veryLongCall(VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_LONG_CONSTANT, () => {})
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+veryLongCall(
+ VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_VERY_LONG_CONSTANT,
+ () => {}
+);
+
+`;
+
exports[`long-contents.js 1`] = `
const foo = () => {
expect(arg1, arg2, arg3).toEqual({message: 'test', messageType: 'SMS', status: 'Unknown', created: '11/01/2017 13:36'});
@@ -366,6 +756,102 @@ const foo = () => {
`;
+exports[`long-contents.js 2`] = `
+const foo = () => {
+ expect(arg1, arg2, arg3).toEqual({message: 'test', messageType: 'SMS', status: 'Unknown', created: '11/01/2017 13:36'});
+};
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+const foo = () => {
+ expect(arg1, arg2, arg3).toEqual({
+ message: "test",
+ messageType: "SMS",
+ status: "Unknown",
+ created: "11/01/2017 13:36"
+ });
+};
+
+`;
+
+exports[`parens.js 1`] = `
+promise.then(
+ (result) => result,
+ (err) => err
+)
+
+promise.then(
+ (result) => { f(); return result },
+ (err) => { f(); return err }
+)
+
+foo(a => b)
+foo(a => { return b })
+foo(c, a => b)
+foo(c, a => b, d)
+foo(a => b, d)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+promise.then(result => result, err => err);
+
+promise.then(
+ result => {
+ f();
+ return result;
+ },
+ err => {
+ f();
+ return err;
+ }
+);
+
+foo(a => b);
+foo(a => {
+ return b;
+});
+foo(c, a => b);
+foo(c, a => b, d);
+foo(a => b, d);
+
+`;
+
+exports[`parens.js 2`] = `
+promise.then(
+ (result) => result,
+ (err) => err
+)
+
+promise.then(
+ (result) => { f(); return result },
+ (err) => { f(); return err }
+)
+
+foo(a => b)
+foo(a => { return b })
+foo(c, a => b)
+foo(c, a => b, d)
+foo(a => b, d)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+promise.then(result => result, err => err);
+
+promise.then(
+ result => {
+ f();
+ return result;
+ },
+ err => {
+ f();
+ return err;
+ }
+);
+
+foo(a => b);
+foo(a => {
+ return b;
+});
+foo(c, a => b);
+foo(c, a => b, d);
+foo(a => b, d);
+
+`;
+
exports[`short_body.js 1`] = `
const initializeSnapshotState = (
testFile: Path,
@@ -383,9 +869,33 @@ const initializeSnapshotState = (
`;
+exports[`short_body.js 2`] = `
+const initializeSnapshotState = (
+ testFile: Path,
+ update: boolean,
+ testPath: string,
+ expand: boolean,
+) => new SnapshotState(testFile, update, testPath, expand);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+const initializeSnapshotState = (
+ testFile: Path,
+ update: boolean,
+ testPath: string,
+ expand: boolean
+) => new SnapshotState(testFile, update, testPath, expand);
+
+`;
+
exports[`type_params.js 1`] = `
(a) => { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(a) => {};
`;
+
+exports[`type_params.js 2`] = `
+(a) => { }
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(a) => {};
+
+`;
diff --git a/tests/arrows/arrow_function_expression.js b/tests/arrows/arrow_function_expression.js
index 4e0071e03..ceae6d7ae 100644
--- a/tests/arrows/arrow_function_expression.js
+++ b/tests/arrows/arrow_function_expression.js
@@ -29,3 +29,7 @@ x => (y = z);
x => (y += z);
f(a => ({})) + 1;
(a => ({})) || 0;
+a = b => c;
+a = b => {
+ return c
+};
diff --git a/tests/arrows/currying.js b/tests/arrows/currying.js
index e1a4c7e2a..1e3b36d1f 100644
--- a/tests/arrows/currying.js
+++ b/tests/arrows/currying.js
@@ -2,6 +2,12 @@ const fn = b => c => d => {
return 3;
};
+const foo = (a, b) => c => d => {
+ return 3;
+};
+
+const bar = a => b => c => a + b + c
+
const mw = store => next => action => {
return next(action)
}
diff --git a/tests/arrows/jsfmt.spec.js b/tests/arrows/jsfmt.spec.js
index 6a6711aef..5db62db64 100644
--- a/tests/arrows/jsfmt.spec.js
+++ b/tests/arrows/jsfmt.spec.js
@@ -1 +1,6 @@
-run_spec(__dirname, { parser: "babylon" }, ["typescript"]);
+run_spec(__dirname, { parser: "babylon", arrowFunctionParentheses: "avoid" }, [
+ "typescript"
+]);
+run_spec(__dirname, { parser: "babylon", arrowFunctionParentheses: "always" }, [
+ "typescript"
+]);
diff --git a/tests/arrows/parens.js b/tests/arrows/parens.js
new file mode 100644
index 000000000..e9b5f424c
--- /dev/null
+++ b/tests/arrows/parens.js
@@ -0,0 +1,15 @@
+promise.then(
+ (result) => result,
+ (err) => err
+)
+
+promise.then(
+ (result) => { f(); return result },
+ (err) => { f(); return err }
+)
+
+foo(a => b)
+foo(a => { return b })
+foo(c, a => b)
+foo(c, a => b, d)
+foo(a => b, d)
diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap
index 681c3baed..35aced0cd 100644
--- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap
+++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap
@@ -1,5 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`show detailed usage with --help arrow-function-parentheses (stderr) 1`] = `""`;
+
+exports[`show detailed usage with --help arrow-function-parentheses (stdout) 1`] = `
+"--arrow-function-parentheses
+
+ Include parentheses around a sole arrow function parameter.
+
+Valid options:
+
+ avoid Omit parens when possible. Example: \`x => x\`
+ always Always include parens. Example: \`(x) => x\`
+
+Default: avoid
+"
+`;
+
+exports[`show detailed usage with --help arrow-function-parentheses (write) 1`] = `Array []`;
+
exports[`show detailed usage with --help bracket-spacing (stderr) 1`] = `""`;
exports[`show detailed usage with --help bracket-spacing (stdout) 1`] = `
@@ -477,6 +495,9 @@ Output options:
Format options:
+ --arrow-function-parentheses
+ Include parentheses around a sole arrow function parameter.
+ Defaults to avoid.
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
@@ -610,6 +631,9 @@ Output options:
Format options:
+ --arrow-function-parentheses
+ Include parentheses around a sole arrow function parameter.
+ Defaults to avoid.
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
From e4eb8a4065e47a50f27f2826ce480ade5c4bc38b Mon Sep 17 00:00:00 2001
From: Stephen Scott
Date: Sun, 26 Nov 2017 16:27:03 -0700
Subject: [PATCH 2/9] Add implementation for arrow parens option
Based on https://github.com/prettier/prettier/pull/2676
* Thread `path` and `options` through helpers so we don't need to add `needsParens` onto the AST node anymore (mutation)
* Pull test call detection logic out into helper method so it can be re-used for arrow function parens
* Add arrow function parens option implementation (avoid/always)
* Don't break arrow function parens around (done) in test call
---
src/printer.js | 124 +++++++---
.../__snapshots__/jsfmt.spec.js.snap | 8 +-
tests/arrows/__snapshots__/jsfmt.spec.js.snap | 72 +++---
.../__snapshots__/jsfmt.spec.js.snap | 211 ++++++++++++++++++
tests/test_declarations/jsfmt.spec.js | 1 +
tests/test_declarations/test_declarations.js | 4 +
6 files changed, 343 insertions(+), 77 deletions(-)
diff --git a/src/printer.js b/src/printer.js
index 4351710d3..645dd2f03 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -214,14 +214,6 @@ function genericPrint(path, options, printPath, args) {
needsParens = path.needsParens(options);
}
- if (node.type) {
- // HACK: ASI prevention in no-semi mode relies on knowledge of whether
- // or not a paren has been inserted (see `exprNeedsASIProtection()`).
- // For now, we're just passing that information by mutating the AST here,
- // but it would be nice to find a cleaner way to do this.
- node.needsParens = needsParens;
- }
-
const parts = [];
if (needsParens) {
parts.unshift("(");
@@ -501,7 +493,7 @@ function genericPrintNoParens(path, options, print, args) {
parts.push("async ");
}
- if (canPrintParamsWithoutParens(n)) {
+ if (shouldPrintParamsWithoutParens(path, options)) {
parts.push(path.call(print, "params", 0));
} else {
parts.push(
@@ -855,7 +847,6 @@ function genericPrintNoParens(path, options, print, args) {
case "NewExpression":
case "CallExpression": {
const isNew = n.type === "NewExpression";
- const unitTestRe = /^(f|x)?(it|describe|test)$/;
const optional = printOptionalToken(path);
if (
@@ -869,22 +860,7 @@ function genericPrintNoParens(path, options, print, args) {
isTemplateOnItsOwnLine(n.arguments[0], options.originalText)) ||
// Keep test declarations on a single line
// e.g. `it('long name', () => {`
- (!isNew &&
- ((n.callee.type === "Identifier" && unitTestRe.test(n.callee.name)) ||
- (n.callee.type === "MemberExpression" &&
- n.callee.object.type === "Identifier" &&
- n.callee.property.type === "Identifier" &&
- unitTestRe.test(n.callee.object.name) &&
- (n.callee.property.name === "only" ||
- n.callee.property.name === "skip"))) &&
- n.arguments.length === 2 &&
- (n.arguments[0].type === "StringLiteral" ||
- n.arguments[0].type === "TemplateLiteral" ||
- (n.arguments[0].type === "Literal" &&
- typeof n.arguments[0].value === "string")) &&
- (n.arguments[1].type === "FunctionExpression" ||
- n.arguments[1].type === "ArrowFunctionExpression") &&
- n.arguments[1].params.length <= 1)
+ (!isNew && isTestCall(n))
) {
return concat([
isNew ? "new " : "",
@@ -2873,11 +2849,9 @@ function printStatementSequence(path, options, print) {
!options.semi &&
!isClass &&
!isTheOnlyJSXElementInMarkdown(options, stmtPath) &&
- stmtNeedsASIProtection(stmtPath)
+ stmtNeedsASIProtection(stmtPath, options)
) {
if (stmt.comments && stmt.comments.some(comment => comment.leading)) {
- // Note: stmtNeedsASIProtection requires stmtPath to already be printed
- // as it reads needsParens which is mutated on the instance
parts.push(print(stmtPath, { needsSemi: true }));
} else {
parts.push(";", stmtPrinted);
@@ -3228,6 +3202,11 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) {
const parent = path.getParentNode();
+ // don't break in specs, eg; `it("should maintain parens around done even when long", (done) => {})`
+ if (parent.type === "CallExpression" && isTestCall(parent)) {
+ return concat([typeParams, "(", join(", ", printed), ")"]);
+ }
+
const flowTypeAnnotations = [
"AnyTypeAnnotation",
"NullLiteralTypeAnnotation",
@@ -3282,6 +3261,19 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) {
]);
}
+function shouldPrintParamsWithoutParens(path, options) {
+ if (options.arrowFunctionParentheses === "always") {
+ return false;
+ }
+
+ if (options.arrowFunctionParentheses === "avoid") {
+ const node = path.getValue();
+ return canPrintParamsWithoutParens(node);
+ }
+
+ return false;
+}
+
function canPrintParamsWithoutParens(node) {
return (
node.params.length === 1 &&
@@ -4683,15 +4675,43 @@ function getLeftSide(node) {
);
}
-function exprNeedsASIProtection(node) {
- // HACK: node.needsParens is added in `genericPrint()` for the sole purpose
- // of being used here. It'd be preferable to find a cleaner way to do this.
+function getLeftSidePathName(path, node) {
+ if (node.expressions) {
+ return ["expressions", 0];
+ }
+ if (node.left) {
+ return ["left"];
+ }
+ if (node.test) {
+ return ["test"];
+ }
+ if (node.callee) {
+ return ["callee"];
+ }
+ if (node.object) {
+ return ["object"];
+ }
+ if (node.tag) {
+ return ["tag"];
+ }
+ if (node.argument) {
+ return ["argument"];
+ }
+ if (node.expression) {
+ return ["expression"];
+ }
+ throw new Error("Unexpected node has no left side", node);
+}
+
+function exprNeedsASIProtection(path, options) {
+ const node = path.getValue();
+
const maybeASIProblem =
- node.needsParens ||
+ path.needsParens(options) ||
node.type === "ParenthesizedExpression" ||
node.type === "TypeCastExpression" ||
(node.type === "ArrowFunctionExpression" &&
- !canPrintParamsWithoutParens(node)) ||
+ !shouldPrintParamsWithoutParens(path, options)) ||
node.type === "ArrayExpression" ||
node.type === "ArrayPattern" ||
(node.type === "UnaryExpression" &&
@@ -4713,17 +4733,25 @@ function exprNeedsASIProtection(node) {
return false;
}
- return exprNeedsASIProtection(getLeftSide(node));
+ return path.call.apply(
+ path,
+ [childPath => exprNeedsASIProtection(childPath, options)].concat(
+ getLeftSidePathName(path, node)
+ )
+ );
}
-function stmtNeedsASIProtection(path) {
+function stmtNeedsASIProtection(path, options) {
const node = path.getNode();
if (node.type !== "ExpressionStatement") {
return false;
}
- return exprNeedsASIProtection(node.expression);
+ return path.call(
+ childPath => exprNeedsASIProtection(childPath, options),
+ "expression"
+ );
}
function classPropMayCauseASIProblems(path) {
@@ -4992,6 +5020,28 @@ function isObjectType(n) {
return n.type === "ObjectTypeAnnotation" || n.type === "TSTypeLiteral";
}
+// eg; `describe("some string", (done) => {})`
+function isTestCall(n) {
+ const unitTestRe = /^(f|x)?(it|describe|test)$/;
+ return (
+ ((n.callee.type === "Identifier" && unitTestRe.test(n.callee.name)) ||
+ (n.callee.type === "MemberExpression" &&
+ n.callee.object.type === "Identifier" &&
+ n.callee.property.type === "Identifier" &&
+ unitTestRe.test(n.callee.object.name) &&
+ (n.callee.property.name === "only" ||
+ n.callee.property.name === "skip"))) &&
+ n.arguments.length === 2 &&
+ (n.arguments[0].type === "StringLiteral" ||
+ n.arguments[0].type === "TemplateLiteral" ||
+ (n.arguments[0].type === "Literal" &&
+ typeof n.arguments[0].value === "string")) &&
+ (n.arguments[1].type === "FunctionExpression" ||
+ n.arguments[1].type === "ArrowFunctionExpression") &&
+ n.arguments[1].params.length <= 1
+ );
+}
+
function printAstToDoc(ast, options, addAlignmentSize) {
addAlignmentSize = addAlignmentSize || 0;
diff --git a/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap b/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
index 006da744c..92c455575 100644
--- a/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/arrow-call/__snapshots__/jsfmt.spec.js.snap
@@ -234,7 +234,7 @@ const composition = (ViewComponent, ContainerComponent) =>
static propTypes = {};
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-const testResults = results.testResults.map(testResult =>
+const testResults = results.testResults.map((testResult) =>
formatResult(testResult, formatter, reporter)
);
@@ -265,16 +265,16 @@ expect(() =>
).not.toThrowError();
const a = Observable.fromPromise(axiosInstance.post("/carts/mine")).map(
- response => response.data
+ (response) => response.data
);
const b = Observable.fromPromise(axiosInstance.get(url)).map(
- response => response.data
+ (response) => response.data
);
func(
veryLoooooooooooooooooooooooongName,
- veryLooooooooooooooooooooooooongName =>
+ (veryLooooooooooooooooooooooooongName) =>
veryLoooooooooooooooongName.something()
);
diff --git a/tests/arrows/__snapshots__/jsfmt.spec.js.snap b/tests/arrows/__snapshots__/jsfmt.spec.js.snap
index c4794e33f..e9786867e 100644
--- a/tests/arrows/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/arrows/__snapshots__/jsfmt.spec.js.snap
@@ -113,7 +113,7 @@ a = b => {
return c
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(a => {}).length;
+((a) => {}).length;
typeof (() => {});
export default (() => {})();
(() => {})()\`\`;
@@ -133,20 +133,20 @@ a = () => ({}[b] && a);
a = () => ({}\`\` && a);
a = () => ({} = 0);
a = () => ({}, a);
-a => a instanceof {};
-a => ({}().b && 0);
-a => ({}().c = 0);
-x => ({}()());
-x => ({}()\`\`);
-x => ({}().b);
-a = b => c;
+(a) => a instanceof {};
+(a) => ({}().b && 0);
+(a) => ({}().c = 0);
+(x) => ({}()());
+(x) => ({}()\`\`);
+(x) => ({}().b);
+a = (b) => c;
a = (b?) => c;
-x => (y = z);
-x => (y += z);
-f(a => ({})) + 1;
-(a => ({})) || 0;
-a = b => c;
-a = b => {
+(x) => (y = z);
+(x) => (y += z);
+f((a) => ({})) + 1;
+((a) => ({})) || 0;
+a = (b) => c;
+a = (b) => {
return c;
};
@@ -421,7 +421,7 @@ fooooooooooooooooooooooooooooooooooooooooooooooooooo(action => next =>
dispatch(action),
);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Seq(typeDef.interface.groups).forEach(group =>
+Seq(typeDef.interface.groups).forEach((group) =>
Seq(group.members).forEach((member, memberName) =>
markdownDoc(member.doc, {
typePath: typePath.concat(memberName.slice(1)),
@@ -430,7 +430,7 @@ Seq(typeDef.interface.groups).forEach(group =>
)
);
-const promiseFromCallback = fn =>
+const promiseFromCallback = (fn) =>
new Promise((resolve, reject) =>
fn((err, result) => {
if (err) return reject(err);
@@ -452,7 +452,7 @@ function render() {
return (
+ onProgress={(e) =>
this.setState({
progress: Math.round(
100 * e.nativeEvent.loaded / e.nativeEvent.total
@@ -468,7 +468,7 @@ function render() {
return (
+ onProgress={(e) =>
this.setState({
progress: Math.round(
100 * e.nativeEvent.loaded / e.nativeEvent.total
@@ -484,7 +484,7 @@ function render() {
return (
+ onProgress={(e) =>
this.setState({
progress: Math.round(
100 * e.nativeEvent.loaded / e.nativeEvent.total
@@ -506,7 +506,7 @@ jest.mock(
}
);
-fooooooooooooooooooooooooooooooooooooooooooooooooooo(action => next =>
+fooooooooooooooooooooooooooooooooooooooooooooooooooo((action) => (next) =>
dispatch(action)
);
@@ -615,17 +615,17 @@ export const bem = block =>
* @param {String} block - the BEM Block you'd like to select.
* @returns {Function}
*/
-export const bem = block =>
+export const bem = (block) =>
/**
* @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
* @returns {Function}
*/
- element =>
+ (element) =>
/**
* @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
* @returns {String}
*/
- modifier =>
+ (modifier) =>
[
".",
css(block),
@@ -700,21 +700,21 @@ const middleware = options => (req, res, next) => {
// ...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-const fn = b => c => d => {
+const fn = (b) => (c) => (d) => {
return 3;
};
-const foo = (a, b) => c => d => {
+const foo = (a, b) => (c) => (d) => {
return 3;
};
-const bar = a => b => c => a + b + c;
+const bar = (a) => (b) => (c) => a + b + c;
-const mw = store => next => action => {
+const mw = (store) => (next) => (action) => {
return next(action);
};
-const middleware = options => (req, res, next) => {
+const middleware = (options) => (req, res, next) => {
// ...
};
@@ -829,26 +829,26 @@ foo(c, a => b)
foo(c, a => b, d)
foo(a => b, d)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-promise.then(result => result, err => err);
+promise.then((result) => result, (err) => err);
promise.then(
- result => {
+ (result) => {
f();
return result;
},
- err => {
+ (err) => {
f();
return err;
}
);
-foo(a => b);
-foo(a => {
+foo((a) => b);
+foo((a) => {
return b;
});
-foo(c, a => b);
-foo(c, a => b, d);
-foo(a => b, d);
+foo(c, (a) => b);
+foo(c, (a) => b, d);
+foo((a) => b, d);
`;
diff --git a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
index 46df9e4ee..19debeed9 100644
--- a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
@@ -34,6 +34,10 @@ test(\`does something really long and complicated so I have to write a very long
console.log("hello!");
});
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
+ console.log("hello!");
+});
+
describe("does something really long and complicated so I have to write a very long name for the describe block", () => {
it("an example test", (done) => {
console.log("hello!");
@@ -123,6 +127,12 @@ test(\`does something really long and complicated so I have to write a very long
console.log("hello!");
});
+test("does something really long and complicated so I have to write a very long name for the test", <
+ T
+>(done) => {
+ console.log("hello!");
+});
+
describe("does something really long and complicated so I have to write a very long name for the describe block", () => {
it("an example test", done => {
console.log("hello!");
@@ -190,3 +200,204 @@ it.only.only(
);
`;
+
+exports[`test_declarations.js 2`] = `
+// Shouldn't break
+
+it("does something really long and complicated so I have to write a very long name for the test", () => {
+ console.log("hello!");
+});
+
+it("does something really long and complicated so I have to write a very long name for the test", function() {
+ console.log("hello!");
+});
+
+it(\`does something really long and complicated so I have to write a very long name for the test\`, function() {
+ console.log("hello!");
+});
+
+it(\`{foo + bar} does something really long and complicated so I have to write a very long name for the test\`, function() {
+ console.log("hello!");
+});
+
+it(\`handles
+ some
+ newlines
+ does something really long and complicated so I have to write a very long name for the test\`, () => {
+ console.log("hello!");
+})
+
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
+ console.log("hello!");
+});
+
+test(\`does something really long and complicated so I have to write a very long name for the test\`, (done) => {
+ console.log("hello!");
+});
+
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
+ console.log("hello!");
+});
+
+describe("does something really long and complicated so I have to write a very long name for the describe block", () => {
+ it("an example test", (done) => {
+ console.log("hello!");
+ });
+});
+
+describe(\`does something really long and complicated so I have to write a very long name for the describe block\`, () => {
+ it(\`an example test\`, (done) => {
+ console.log("hello!");
+ });
+});
+
+xdescribe("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+fdescribe("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+describe.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+describe.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+fit("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+xit("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+it.only("does something really long and complicated so I have to write a very long name for the test", () => {
+ console.log("hello!");
+});
+
+it.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {
+ console.log("hello!");
+});
+
+it.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+test.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+test.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+ftest("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+xtest("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+// Should break
+
+it.only("does something really long and complicated so I have to write a very long name for the test", 10, () => {
+ console.log("hello!");
+});
+
+it.only.only("does something really long and complicated so I have to write a very long name for the test", () => {
+ console.log("hello!");
+});
+
+it.only.only("does something really long and complicated so I have to write a very long name for the test", (a, b, c) => {
+ console.log("hello!");
+});
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Shouldn't break
+
+it("does something really long and complicated so I have to write a very long name for the test", () => {
+ console.log("hello!");
+});
+
+it("does something really long and complicated so I have to write a very long name for the test", function() {
+ console.log("hello!");
+});
+
+it(\`does something really long and complicated so I have to write a very long name for the test\`, function() {
+ console.log("hello!");
+});
+
+it(\`{foo + bar} does something really long and complicated so I have to write a very long name for the test\`, function() {
+ console.log("hello!");
+});
+
+it(\`handles
+ some
+ newlines
+ does something really long and complicated so I have to write a very long name for the test\`, () => {
+ console.log("hello!");
+});
+
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
+ console.log("hello!");
+});
+
+test(\`does something really long and complicated so I have to write a very long name for the test\`, (done) => {
+ console.log("hello!");
+});
+
+test("does something really long and complicated so I have to write a very long name for the test", <
+ T
+>(done) => {
+ console.log("hello!");
+});
+
+describe("does something really long and complicated so I have to write a very long name for the describe block", () => {
+ it("an example test", (done) => {
+ console.log("hello!");
+ });
+});
+
+describe(\`does something really long and complicated so I have to write a very long name for the describe block\`, () => {
+ it(\`an example test\`, (done) => {
+ console.log("hello!");
+ });
+});
+
+xdescribe("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+fdescribe("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+describe.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+describe.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+fit("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+xit("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+it.only("does something really long and complicated so I have to write a very long name for the test", () => {
+ console.log("hello!");
+});
+
+it.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {
+ console.log("hello!");
+});
+
+it.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+test.only(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+test.skip(\`does something really long and complicated so I have to write a very long name for the test\`, () => {});
+
+ftest("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+xtest("does something really long and complicated so I have to write a very long name for the describe block", () => {});
+
+// Should break
+
+it.only(
+ "does something really long and complicated so I have to write a very long name for the test",
+ 10,
+ () => {
+ console.log("hello!");
+ }
+);
+
+it.only.only(
+ "does something really long and complicated so I have to write a very long name for the test",
+ () => {
+ console.log("hello!");
+ }
+);
+
+it.only.only(
+ "does something really long and complicated so I have to write a very long name for the test",
+ (a, b, c) => {
+ console.log("hello!");
+ }
+);
+
+`;
diff --git a/tests/test_declarations/jsfmt.spec.js b/tests/test_declarations/jsfmt.spec.js
index 7580dfab0..e34fd7e40 100644
--- a/tests/test_declarations/jsfmt.spec.js
+++ b/tests/test_declarations/jsfmt.spec.js
@@ -1 +1,2 @@
run_spec(__dirname, null, ["typescript"]);
+run_spec(__dirname, { arrowFunctionParentheses: "always" }, ["typescript"]);
diff --git a/tests/test_declarations/test_declarations.js b/tests/test_declarations/test_declarations.js
index 165f40453..df3253b10 100644
--- a/tests/test_declarations/test_declarations.js
+++ b/tests/test_declarations/test_declarations.js
@@ -31,6 +31,10 @@ test(`does something really long and complicated so I have to write a very long
console.log("hello!");
});
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
+ console.log("hello!");
+});
+
describe("does something really long and complicated so I have to write a very long name for the describe block", () => {
it("an example test", (done) => {
console.log("hello!");
From a6c12ca7a97419557b14c3bbe3bc9e23abfdea52 Mon Sep 17 00:00:00 2001
From: Stephen Scott
Date: Sun, 26 Nov 2017 16:40:11 -0700
Subject: [PATCH 3/9] Inline type parameters in test callback
---
src/printer.js | 8 ++++++++
tests/test_declarations/__snapshots__/jsfmt.spec.js.snap | 8 ++------
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/printer.js b/src/printer.js
index 645dd2f03..1a95b3fc2 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -3519,7 +3519,15 @@ function printTypeParameters(path, options, print, paramsKey) {
return path.call(print, paramsKey);
}
+ const grandparent = path.getNode(2);
+
+ const isParameterInTestCall =
+ grandparent != null &&
+ grandparent.type === "CallExpression" &&
+ isTestCall(grandparent);
+
const shouldInline =
+ isParameterInTestCall ||
n[paramsKey].length === 0 ||
(n[paramsKey].length === 1 &&
(shouldHugType(n[paramsKey][0]) ||
diff --git a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
index 19debeed9..fc01c9636 100644
--- a/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/test_declarations/__snapshots__/jsfmt.spec.js.snap
@@ -127,9 +127,7 @@ test(\`does something really long and complicated so I have to write a very long
console.log("hello!");
});
-test("does something really long and complicated so I have to write a very long name for the test", <
- T
->(done) => {
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
console.log("hello!");
});
@@ -328,9 +326,7 @@ test(\`does something really long and complicated so I have to write a very long
console.log("hello!");
});
-test("does something really long and complicated so I have to write a very long name for the test", <
- T
->(done) => {
+test("does something really long and complicated so I have to write a very long name for the test", (done) => {
console.log("hello!");
});
From 6abdd2c6b77d46d9b645d93dd85b95847c26933d Mon Sep 17 00:00:00 2001
From: Suchipi Izumi
Date: Mon, 27 Nov 2017 21:52:49 -0700
Subject: [PATCH 4/9] PR feedback
---
docs/options.md | 8 ++++----
src/cli-constant.js | 2 +-
src/options.js | 2 +-
src/printer.js | 5 +++--
tests/arrow-call/jsfmt.spec.js | 2 +-
tests/arrows/jsfmt.spec.js | 4 ++--
tests/test_declarations/jsfmt.spec.js | 2 +-
7 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/docs/options.md b/docs/options.md
index b3d83cfd4..3f6ca94b8 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -96,7 +96,7 @@ Put the `>` of a multi-line JSX element at the end of the last line instead of b
| ------- | ------------------------- | ---------------------------- |
| `false` | `--jsx-bracket-same-line` | `jsxBracketSameLine: ` |
-# Arrow Function Parentheses
+## Arrow Function Parentheses
Include parentheses around a sole arrow function parameter.
@@ -105,9 +105,9 @@ Valid options:
* `"avoid"` - Omit parens when possible. Example: `x => x`
* `"always"` - Always include parens. Example: `(x) => x`
-| Default | CLI Override | API Override |
-| --------- | --------------------------------------------------------- | ------------------------------------------------------- |
-| `"avoid"` | --arrow-function-parens | arrowFunctionParentheses: "" |
+| Default | CLI Override | API Override |
+| --------- | ----------------------------------------------- | ----------------------------------------------- |
+| `"avoid"` | --arrow-parens | arrowParens: "" |
## Range
diff --git a/src/cli-constant.js b/src/cli-constant.js
index 376c718b9..018540694 100644
--- a/src/cli-constant.js
+++ b/src/cli-constant.js
@@ -77,7 +77,7 @@ const categoryOrder = [
* Note: The options below are sorted alphabetically.
*/
const detailedOptions = normalizeDetailedOptions({
- "arrow-function-parentheses": {
+ "arrow-parens": {
type: "choice",
category: CATEGORY_FORMAT,
forwardToApi: true,
diff --git a/src/options.js b/src/options.js
index 87ba34028..f0d963157 100644
--- a/src/options.js
+++ b/src/options.js
@@ -22,7 +22,7 @@ const defaults = {
requirePragma: false,
semi: true,
proseWrap: true,
- arrowFunctionParentheses: "avoid"
+ arrowParens: "avoid"
};
const exampleConfig = Object.assign({}, defaults, {
diff --git a/src/printer.js b/src/printer.js
index 1a95b3fc2..3ac29dfaa 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -3262,15 +3262,16 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) {
}
function shouldPrintParamsWithoutParens(path, options) {
- if (options.arrowFunctionParentheses === "always") {
+ if (options.arrowParens === "always") {
return false;
}
- if (options.arrowFunctionParentheses === "avoid") {
+ if (options.arrowParens === "avoid") {
const node = path.getValue();
return canPrintParamsWithoutParens(node);
}
+ // Fallback default; should be unreachable
return false;
}
diff --git a/tests/arrow-call/jsfmt.spec.js b/tests/arrow-call/jsfmt.spec.js
index db45d9868..d2d553f69 100644
--- a/tests/arrow-call/jsfmt.spec.js
+++ b/tests/arrow-call/jsfmt.spec.js
@@ -1,3 +1,3 @@
run_spec(__dirname, null, ["typescript"]);
run_spec(__dirname, { trailingComma: "all" }, ["typescript"]);
-run_spec(__dirname, { arrowFunctionParentheses: "always" }, ["typescript"]);
+run_spec(__dirname, { arrowParens: "always" }, ["typescript"]);
diff --git a/tests/arrows/jsfmt.spec.js b/tests/arrows/jsfmt.spec.js
index 5db62db64..460cdeae4 100644
--- a/tests/arrows/jsfmt.spec.js
+++ b/tests/arrows/jsfmt.spec.js
@@ -1,6 +1,6 @@
-run_spec(__dirname, { parser: "babylon", arrowFunctionParentheses: "avoid" }, [
+run_spec(__dirname, { parser: "babylon", arrowParens: "avoid" }, [
"typescript"
]);
-run_spec(__dirname, { parser: "babylon", arrowFunctionParentheses: "always" }, [
+run_spec(__dirname, { parser: "babylon", arrowParens: "always" }, [
"typescript"
]);
diff --git a/tests/test_declarations/jsfmt.spec.js b/tests/test_declarations/jsfmt.spec.js
index e34fd7e40..d5c0967c1 100644
--- a/tests/test_declarations/jsfmt.spec.js
+++ b/tests/test_declarations/jsfmt.spec.js
@@ -1,2 +1,2 @@
run_spec(__dirname, null, ["typescript"]);
-run_spec(__dirname, { arrowFunctionParentheses: "always" }, ["typescript"]);
+run_spec(__dirname, { arrowParens: "always" }, ["typescript"]);
From 41a9ababc3b4fdf6b95648078e0f0f2c08b293c9 Mon Sep 17 00:00:00 2001
From: Suchipi Izumi
Date: Mon, 27 Nov 2017 22:23:32 -0700
Subject: [PATCH 5/9] Add updated snapshot
Whoops, forgot this
---
.../__tests__/__snapshots__/early-exit.js.snap | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap
index 35aced0cd..3eafa6651 100644
--- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap
+++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`show detailed usage with --help arrow-function-parentheses (stderr) 1`] = `""`;
+exports[`show detailed usage with --help arrow-parens (stderr) 1`] = `""`;
-exports[`show detailed usage with --help arrow-function-parentheses (stdout) 1`] = `
-"--arrow-function-parentheses
+exports[`show detailed usage with --help arrow-parens (stdout) 1`] = `
+"--arrow-parens
Include parentheses around a sole arrow function parameter.
@@ -16,7 +16,7 @@ Default: avoid
"
`;
-exports[`show detailed usage with --help arrow-function-parentheses (write) 1`] = `Array []`;
+exports[`show detailed usage with --help arrow-parens (write) 1`] = `Array []`;
exports[`show detailed usage with --help bracket-spacing (stderr) 1`] = `""`;
@@ -495,7 +495,7 @@ Output options:
Format options:
- --arrow-function-parentheses
+ --arrow-parens
Include parentheses around a sole arrow function parameter.
Defaults to avoid.
--no-bracket-spacing Do not print spaces between brackets.
@@ -631,7 +631,7 @@ Output options:
Format options:
- --arrow-function-parentheses
+ --arrow-parens
Include parentheses around a sole arrow function parameter.
Defaults to avoid.
--no-bracket-spacing Do not print spaces between brackets.
From ac3f74e7a3697d4bc85de47b514f7925c2c99b22 Mon Sep 17 00:00:00 2001
From: Ika
Date: Wed, 29 Nov 2017 00:20:26 +0800
Subject: [PATCH 6/9] docs(options): add available version for `arrow-parens`
(#3339)
---
docs/options.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docs/options.md b/docs/options.md
index 3f6ca94b8..c4da1398c 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -98,6 +98,8 @@ Put the `>` of a multi-line JSX element at the end of the last line instead of b
## Arrow Function Parentheses
+_available in v1.9.0+_
+
Include parentheses around a sole arrow function parameter.
Valid options:
From e04f22975de10024ad9d98fc40b12c130b1b79f7 Mon Sep 17 00:00:00 2001
From: Lucas Azzola
Date: Wed, 29 Nov 2017 17:45:53 +1100
Subject: [PATCH 7/9] Change "preview" to "pr"
---
scripts/build/build-docs.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/build/build-docs.js b/scripts/build/build-docs.js
index 7db557996..f1ed25e07 100644
--- a/scripts/build/build-docs.js
+++ b/scripts/build/build-docs.js
@@ -28,7 +28,7 @@ const prettierPath = isPullRequest ? "dist" : "node_modules/prettier/";
if (isPullRequest) {
const pkg = require("../../package.json");
- pkg.version = `preview-${process.env.REVIEW_ID}`;
+ pkg.version = `pr-${process.env.REVIEW_ID}`;
pipe(JSON.stringify(pkg, null, 2)).to("package.json");
shell.exec("node scripts/build/build.js");
}
From fbbfa525171f36632ae879010cba92af9a5fd896 Mon Sep 17 00:00:00 2001
From: Ika
Date: Wed, 29 Nov 2017 19:13:38 +0800
Subject: [PATCH 8/9] fix(markdown): do not print linebreaks in heading (#3343)
---
src/printer-markdown.js | 3 ++-
tests/markdown_heading/__snapshots__/jsfmt.spec.js.snap | 7 +++++++
tests/markdown_heading/mixed.md | 1 +
3 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 tests/markdown_heading/mixed.md
diff --git a/src/printer-markdown.js b/src/printer-markdown.js
index 8ab137d4a..4a4912eba 100644
--- a/src/printer-markdown.js
+++ b/src/printer-markdown.js
@@ -40,7 +40,8 @@ const INLINE_NODE_TYPES = [
const INLINE_NODE_WRAPPER_TYPES = INLINE_NODE_TYPES.concat([
"tableCell",
- "paragraph"
+ "paragraph",
+ "heading"
]);
function genericPrint(path, options, print) {
diff --git a/tests/markdown_heading/__snapshots__/jsfmt.spec.js.snap b/tests/markdown_heading/__snapshots__/jsfmt.spec.js.snap
index 2da78763b..75fcf5d8b 100644
--- a/tests/markdown_heading/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/markdown_heading/__snapshots__/jsfmt.spec.js.snap
@@ -18,6 +18,13 @@ exports[`long-heading.md 1`] = `
`;
+exports[`mixed.md 1`] = `
+## LaraCart - Laravel Shopping Cart Package (http://laracart.lukepolo.com)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+## LaraCart - Laravel Shopping Cart Package (http://laracart.lukepolo.com)
+
+`;
+
exports[`setext.md 1`] = `
h1
===
diff --git a/tests/markdown_heading/mixed.md b/tests/markdown_heading/mixed.md
new file mode 100644
index 000000000..1e5bb8766
--- /dev/null
+++ b/tests/markdown_heading/mixed.md
@@ -0,0 +1 @@
+## LaraCart - Laravel Shopping Cart Package (http://laracart.lukepolo.com)
From 2032b70918eb4eaf3741397d08198394f776ef9e Mon Sep 17 00:00:00 2001
From: Lipis
Date: Wed, 29 Nov 2017 17:50:02 +0100
Subject: [PATCH 9/9] Add Twitter social button (#3288)
* Twitter Badges
* Update README.md
* Update README.md
* Update Footer.js
* Update README.md
* Update Footer.js
---
README.md | 3 +++
website/core/Footer.js | 13 ++++++-------
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 8e65d2096..c597877f3 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,9 @@
+
+
+
## Intro
diff --git a/website/core/Footer.js b/website/core/Footer.js
index 7bd0e9c08..609bb5c4a 100644
--- a/website/core/Footer.js
+++ b/website/core/Footer.js
@@ -56,13 +56,12 @@ class Footer extends React.Component {
Stack Overflow
Chat on Gitter
- {/*
- Twitter
- */}
+
+
+
More