diff --git a/src/fast-path.js b/src/fast-path.js index e2af664f0..74e994d07 100644 --- a/src/fast-path.js +++ b/src/fast-path.js @@ -192,12 +192,26 @@ FPp.needsParens = function(assumeExpressionContext) { return false; } - // Add parens around a `class` that extends an expression (it should - // parse correctly, even if it's invalid) + // Add parens around the extends clause of a class. It is needed for almost + // all expressions. if ( parent.type === "ClassDeclaration" && - parent.superClass === node && - node.type === "AwaitExpression" + parent.superClass === node && ( + node.type === "ArrowFunctionExpression" || + node.type === "AssignmentExpression" || + node.type === "AwaitExpression" || + node.type === "BinaryExpression" || + node.type === "ConditionalExpression" || + node.type === "LogicalExpression" || + node.type === "NewExpression" || + node.type === "ObjectExpression" || + node.type === "ParenthesizedExpression" || + node.type === "SequenceExpression" || + node.type === "TaggedTemplateExpression" || + node.type === "UnaryExpression" || + node.type === "UpdateExpression" || + node.type === "YieldExpression" + ) ) { return true; } diff --git a/tests/class_extends/__snapshots__/jsfmt.spec.js.snap b/tests/class_extends/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..fe29f87d4 --- /dev/null +++ b/tests/class_extends/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,116 @@ +exports[`test extends.js 1`] = ` +"// \"ArrowFunctionExpression\" +class a extends (() => {}) {} + +// \"AssignmentExpression\" +class a extends (b = c) {} + +// \"AwaitExpression\" +async function f() { + class a extends (await b) {} +} + +// \"BinaryExpression\" +class a extends (b + c) {} + +// \"CallExpression\" +class a extends b() {} + +// \"ClassExpression\" +class a extends class {} {} + +// \"ConditionalExpression\" +class a extends (b ? c : d) {} + +// \"FunctionExpression\" +class a extends (function() {}) {} + +// \"LogicalExpression\" +class a extends (b || c) {} + +// \"MemberExpression\" +class a extends b.c {} + +// \"NewExpression\" +class a extends (new B()) {} + +// \"ObjectExpression\" +class a extends ({}) {} + +// \"SequenceExpression\" +class a extends (b, c) {} + +// \"TaggedTemplateExpression\" +class a extends \`\` {} + +// \"UnaryExpression\" +class a extends (void b) {} + +// \"UpdateExpression\" +class a extends (++b) {} + +// \"YieldExpression\" +function* f() { + // Flow has a bug parsing it. + // class a extends (yield 1) {} +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// \"ArrowFunctionExpression\" +class a extends (() => { +}) {} + +// \"AssignmentExpression\" +class a extends (b = c) {} + +// \"AwaitExpression\" +async function f() { + class a extends (await b) {} +} + +// \"BinaryExpression\" +class a extends (b + c) {} + +// \"CallExpression\" +class a extends b() {} + +// \"ClassExpression\" +class a extends class {} {} + +// \"ConditionalExpression\" +class a extends (b ? c : d) {} + +// \"FunctionExpression\" +class a extends function() { +} {} + +// \"LogicalExpression\" +class a extends (b || c) {} + +// \"MemberExpression\" +class a extends b.c {} + +// \"NewExpression\" +class a extends (new B()) {} + +// \"ObjectExpression\" +class a extends ({}) {} + +// \"SequenceExpression\" +class a extends (b, c) {} + +// \"TaggedTemplateExpression\" +class a extends \`\` {} + +// \"UnaryExpression\" +class a extends (void b) {} + +// \"UpdateExpression\" +class a extends (++b) {} + +// \"YieldExpression\" +function* f() { + // Flow has a bug parsing it. + // class a extends (yield 1) {} +} +" +`; diff --git a/tests/class_extends/extends.js b/tests/class_extends/extends.js new file mode 100644 index 000000000..6debb835b --- /dev/null +++ b/tests/class_extends/extends.js @@ -0,0 +1,55 @@ +// "ArrowFunctionExpression" +class a extends (() => {}) {} + +// "AssignmentExpression" +class a extends (b = c) {} + +// "AwaitExpression" +async function f() { + class a extends (await b) {} +} + +// "BinaryExpression" +class a extends (b + c) {} + +// "CallExpression" +class a extends b() {} + +// "ClassExpression" +class a extends class {} {} + +// "ConditionalExpression" +class a extends (b ? c : d) {} + +// "FunctionExpression" +class a extends (function() {}) {} + +// "LogicalExpression" +class a extends (b || c) {} + +// "MemberExpression" +class a extends b.c {} + +// "NewExpression" +class a extends (new B()) {} + +// "ObjectExpression" +class a extends ({}) {} + +// "SequenceExpression" +class a extends (b, c) {} + +// "TaggedTemplateExpression" +class a extends `` {} + +// "UnaryExpression" +class a extends (void b) {} + +// "UpdateExpression" +class a extends (++b) {} + +// "YieldExpression" +function* f() { + // Flow has a bug parsing it. + // class a extends (yield 1) {} +} diff --git a/tests/class_extends/jsfmt.spec.js b/tests/class_extends/jsfmt.spec.js new file mode 100644 index 000000000..989047bcc --- /dev/null +++ b/tests/class_extends/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname);