diff --git a/lib/fast-path.ts b/lib/fast-path.ts index 925cbaac..e08c39b1 100644 --- a/lib/fast-path.ts +++ b/lib/fast-path.ts @@ -355,6 +355,17 @@ FPp.needsParens = function (assumeExpressionContext) { if (!parent) return false; + // Wrap e.g. `-1` in parentheses inside `(-1) ** 2`. + if ( + node.type === "UnaryExpression" && + parent.type === "BinaryExpression" && + name === "left" && + parent.left === node && + parent.operator === "**" + ) { + return true; + } + switch (node.type) { case "UnaryExpression": case "SpreadElement": diff --git a/test/printer.ts b/test/printer.ts index a0fc12f9..9b117cde 100644 --- a/test/printer.ts +++ b/test/printer.ts @@ -2031,6 +2031,27 @@ describe("printer", function () { assert.strictEqual(pretty, code); }); + for (const operator of ["-", "+", "~", "!", "typeof", "void"] as const) { + it(`adds parenthesis around '${operator}' unary expression in exponentiation expression`, function () { + const code = `(${ + /[a-z]/.test(operator) ? `${operator} ` : operator + }a) ** 2;`; + const ast = b.program([ + b.expressionStatement( + b.binaryExpression( + "**", + b.unaryExpression(operator, b.identifier("a"), true), + b.literal(2), + ), + ), + ]); + + const printer = new Printer(); + const pretty = printer.print(ast).code; + assert.strictEqual(pretty, code); + }); + } + it("prints flow object type internal slots correctly", function () { const code = [ "type MyObjectType = {",