diff --git a/src/language-js/parentheses/needs-parentheses.js b/src/language-js/parentheses/needs-parentheses.js
index 052064cd8..c091aa8ce 100644
--- a/src/language-js/parentheses/needs-parentheses.js
+++ b/src/language-js/parentheses/needs-parentheses.js
@@ -134,14 +134,13 @@ function needsParentheses(path, options) {
break;
case "ExportDefaultDeclaration":
- return (
- // `export default function` or `export default class` can't be followed by
- // anything after. So an expression like `export default (function(){}).toString()`
- // needs to be followed by a parentheses
- shouldWrapFunctionForExportDefault(path, options) ||
- // `export default (foo, bar)` also needs parentheses
- node.type === "SequenceExpression"
- );
+ // `export default function` or `export default class` can't be followed by
+ // anything after. So an expression like `export default (function(){}).toString()`
+ // needs to be followed by a parentheses
+ if (shouldWrapFunctionForExportDefault(path, options)) {
+ return true;
+ }
+ break;
case "Decorator":
if (
@@ -771,6 +770,8 @@ function needsParentheses(path, options) {
return key === "callee";
case "TaggedTemplateExpression":
return true; // This is basically a kind of IIFE.
+ case "ExportDefaultDeclaration":
+ return key === "declaration";
default:
return false;
}
@@ -817,6 +818,8 @@ function needsParentheses(path, options) {
switch (parent.type) {
case "NewExpression":
return key === "callee";
+ case "ExportDefaultDeclaration":
+ return key === "declaration";
default:
return false;
}
diff --git a/tests/format/js/export-default/parentheses/__snapshots__/format.test.js.snap b/tests/format/js/export-default/parentheses/__snapshots__/format.test.js.snap
new file mode 100644
index 000000000..df1584c6d
--- /dev/null
+++ b/tests/format/js/export-default/parentheses/__snapshots__/format.test.js.snap
@@ -0,0 +1,586 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`snippet: #0 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a++);
+=====================================output=====================================
+export default a++;
+
+================================================================================
+`;
+
+exports[`snippet: #0 format 2`] = `
+====================================options=====================================
+parsers: ["babel", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (await a);
+=====================================output=====================================
+export default await a;
+
+================================================================================
+`;
+
+exports[`snippet: #1 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a++).toString();
+=====================================output=====================================
+export default (a++).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #1 format 2`] = `
+====================================options=====================================
+parsers: ["babel", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (await a).toString();
+=====================================output=====================================
+export default (await a).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #2 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a++)?.toString();
+=====================================output=====================================
+export default (a++)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #2 format 2`] = `
+====================================options=====================================
+parsers: ["babel", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (await a)?.toString();
+=====================================output=====================================
+export default (await a)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #3 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (++ a);
+=====================================output=====================================
+export default ++a;
+
+================================================================================
+`;
+
+exports[`snippet: #4 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (++ a).toString();
+=====================================output=====================================
+export default (++a).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #5 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (++ a)?.toString();
+=====================================output=====================================
+export default (++a)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #6 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (+a);
+=====================================output=====================================
+export default +a;
+
+================================================================================
+`;
+
+exports[`snippet: #7 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (+a)?.toString();
+=====================================output=====================================
+export default (+a)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #8 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (function this_is_a_expression_not_a_declaration() {});
+=====================================output=====================================
+export default (function this_is_a_expression_not_a_declaration() {});
+
+================================================================================
+`;
+
+exports[`snippet: #9 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (function this_is_a_expression_not_a_declaration() {}).toString();
+=====================================output=====================================
+export default (function this_is_a_expression_not_a_declaration() {}.toString());
+
+================================================================================
+`;
+
+exports[`snippet: #10 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (class this_is_a_expression_not_a_declaration {});
+=====================================output=====================================
+export default (class this_is_a_expression_not_a_declaration {});
+
+================================================================================
+`;
+
+exports[`snippet: #11 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (class this_is_a_expression_not_a_declaration {}).toString();
+=====================================output=====================================
+export default (class this_is_a_expression_not_a_declaration {}.toString());
+
+================================================================================
+`;
+
+exports[`snippet: #12 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (class this_is_a_expression_not_a_declaration {})?.toString();
+=====================================output=====================================
+export default (class this_is_a_expression_not_a_declaration {}?.toString());
+
+================================================================================
+`;
+
+exports[`snippet: #13 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a in b);
+=====================================output=====================================
+export default a in b;
+
+================================================================================
+`;
+
+exports[`snippet: #14 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a in b).toString();
+=====================================output=====================================
+export default (a in b).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #15 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a in b)?.toString();
+=====================================output=====================================
+export default (a in b)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #16 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a || b);
+=====================================output=====================================
+export default a || b;
+
+================================================================================
+`;
+
+exports[`snippet: #17 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a || b).toString();
+=====================================output=====================================
+export default (a || b).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #18 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a || b)?.toString();
+=====================================output=====================================
+export default (a || b)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #19 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a , b);
+=====================================output=====================================
+export default (a, b);
+
+================================================================================
+`;
+
+exports[`snippet: #20 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a , b)?.toString();
+=====================================output=====================================
+export default (a, b)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #21 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (1.);
+=====================================output=====================================
+export default 1;
+
+================================================================================
+`;
+
+exports[`snippet: #22 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (1.).toString();
+=====================================output=====================================
+export default (1).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #23 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (1.)?.toString();
+=====================================output=====================================
+export default (1)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #24 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a = b);
+=====================================output=====================================
+export default (a = b);
+
+================================================================================
+`;
+
+exports[`snippet: #25 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a = b).toString();
+=====================================output=====================================
+export default (a = b).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #26 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a = b)?.toString();
+=====================================output=====================================
+export default (a = b)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #27 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a += b);
+=====================================output=====================================
+export default (a += b);
+
+================================================================================
+`;
+
+exports[`snippet: #28 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a += b).toString();
+=====================================output=====================================
+export default (a += b).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #29 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a += b)?.toString();
+=====================================output=====================================
+export default (a += b)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #30 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a ? b : c);
+=====================================output=====================================
+export default (a ? b : c);
+
+================================================================================
+`;
+
+exports[`snippet: #31 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a ? b : c).toString();
+=====================================output=====================================
+export default (a ? b : c).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #32 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a ? b : c)?.toString();
+=====================================output=====================================
+export default (a ? b : c)?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #33 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (() =>{});
+=====================================output=====================================
+export default () => {};
+
+================================================================================
+`;
+
+exports[`snippet: #34 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (() =>{}).toString();
+=====================================output=====================================
+export default (() => {}).toString();
+
+================================================================================
+`;
+
+exports[`snippet: #35 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (() =>{})?.toString();
+=====================================output=====================================
+export default (() => {})?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #36 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a\`\`);
+=====================================output=====================================
+export default a\`\`;
+
+================================================================================
+`;
+
+exports[`snippet: #37 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a\`\`).toString();
+=====================================output=====================================
+export default a\`\`.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #38 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default (a\`\`)?.toString();
+=====================================output=====================================
+export default a\`\`?.toString();
+
+================================================================================
+`;
+
+exports[`snippet: #39 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default ();
+=====================================output=====================================
+export default ();
+
+================================================================================
+`;
+
+exports[`snippet: #40 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default ().toString();
+=====================================output=====================================
+export default ().toString();
+
+================================================================================
+`;
+
+exports[`snippet: #41 format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+export default ()?.toString();
+=====================================output=====================================
+export default ()?.toString();
+
+================================================================================
+`;
diff --git a/tests/format/js/export-default/parentheses/format.test.js b/tests/format/js/export-default/parentheses/format.test.js
new file mode 100644
index 000000000..2e078d5a0
--- /dev/null
+++ b/tests/format/js/export-default/parentheses/format.test.js
@@ -0,0 +1,85 @@
+const snippets = [
+ "export default (a++);",
+ "export default (a++).toString();",
+ "export default (a++)?.toString();",
+
+ "export default (++ a);",
+ "export default (++ a).toString();",
+ "export default (++ a)?.toString();",
+
+ "export default (+a);",
+ "export default (+a)?.toString();",
+
+ "export default (function this_is_a_expression_not_a_declaration() {});",
+ "export default (function this_is_a_expression_not_a_declaration() {}).toString();",
+
+ "export default (class this_is_a_expression_not_a_declaration {});",
+ "export default (class this_is_a_expression_not_a_declaration {}).toString();",
+ "export default (class this_is_a_expression_not_a_declaration {})?.toString();",
+
+ "export default (a in b);",
+ "export default (a in b).toString();",
+ "export default (a in b)?.toString();",
+
+ "export default (a || b);",
+ "export default (a || b).toString();",
+ "export default (a || b)?.toString();",
+
+ "export default (a , b);",
+ "export default (a , b)?.toString();",
+
+ "export default (1.);",
+ "export default (1.).toString();",
+ "export default (1.)?.toString();",
+
+ "export default (a = b);",
+ "export default (a = b).toString();",
+ "export default (a = b)?.toString();",
+
+ "export default (a += b);",
+ "export default (a += b).toString();",
+ "export default (a += b)?.toString();",
+
+ "export default (a ? b : c);",
+ "export default (a ? b : c).toString();",
+ "export default (a ? b : c)?.toString();",
+
+ "export default (() =>{});",
+ "export default (() =>{}).toString();",
+ "export default (() =>{})?.toString();",
+
+ "export default (a``);",
+ "export default (a``).toString();",
+ "export default (a``)?.toString();",
+
+ "export default ();",
+ "export default ().toString();",
+ "export default ()?.toString();",
+];
+
+runFormatTest(
+ {
+ snippets,
+ importMeta: import.meta,
+ },
+ ["babel", "flow", "typescript"],
+);
+
+const snippetsWithTla = [
+ "export default (await a);",
+ "export default (await a).toString();",
+ "export default (await a)?.toString();",
+];
+
+runFormatTest(
+ {
+ snippets: snippetsWithTla,
+ importMeta: import.meta,
+ },
+ [
+ "babel",
+ // TODO: enable when it supports TLA
+ // "flow",
+ "typescript",
+ ],
+);