Ensure expressions wrapped in parens (#12082)

This commit is contained in:
overlookmotel 2020-09-25 21:58:04 +01:00 committed by GitHub
parent 63d9f5397b
commit 1a074ee7e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 178 additions and 3 deletions

View File

@ -293,7 +293,7 @@ function isFirstInStatement(
let node = printStack[i]; let node = printStack[i];
i--; i--;
let parent = printStack[i]; let parent = printStack[i];
while (i > 0) { while (i >= 0) {
if ( if (
t.isExpressionStatement(parent, { expression: node }) || t.isExpressionStatement(parent, { expression: node }) ||
(considerDefaultExports && (considerDefaultExports &&

View File

@ -3,3 +3,5 @@ var foo = arr.map(v => ({
y: v.bar*2 y: v.bar*2
})); }));
var fn = () => ({}).key; var fn = () => ({}).key;
var fn2 = () => ({});
var fn3 = () => ({a} = {});

View File

@ -4,3 +4,9 @@ var foo = arr.map(v => ({
})); }));
var fn = () => ({}).key; var fn = () => ({}).key;
var fn2 = () => ({});
var fn3 = () => ({
a
} = {});

View File

@ -4,3 +4,4 @@ a = a || (a = {});
(a = b)(); (a = b)();
(a = b)?.(); (a = b)?.();
({a} = {});

View File

@ -3,3 +3,6 @@
a = a || (a = {}); a = a || (a = {});
(a = b)(); (a = b)();
(a = b)?.(); (a = b)?.();
({
a
} = {});

View File

@ -537,6 +537,169 @@ describe("programmatic generation", function () {
expect(output).toBe("(number & boolean)?"); expect(output).toBe("(number & boolean)?");
}); });
}); });
describe("object expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const objectExpression = t.objectExpression([]);
const output = generate(objectExpression).code;
expect(output).toBe("{}");
});
it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(t.objectExpression([]));
const output = generate(expressionStatement).code;
expect(output).toBe("({});");
});
it("wrapped in parentheses in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.objectExpression([]),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({})");
});
it("not wrapped in parentheses in conditional", () => {
const conditionalExpression = t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
);
const output = generate(conditionalExpression).code;
expect(output).toBe("{} ? true : false");
});
it("wrapped in parentheses in conditional in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}) ? true : false;");
});
it("wrapped in parentheses in conditional in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.conditionalExpression(
t.objectExpression([]),
t.booleanLiteral(true),
t.booleanLiteral(false),
),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({}) ? true : false");
});
it("not wrapped in parentheses in binary expression", () => {
const binaryExpression = t.binaryExpression(
"+",
t.objectExpression([]),
t.numericLiteral(1),
);
const output = generate(binaryExpression).code;
expect(output).toBe("{} + 1");
});
it("wrapped in parentheses in binary expression in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.binaryExpression("+", t.objectExpression([]), t.numericLiteral(1)),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}) + 1;");
});
it("wrapped in parentheses in binary expression in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.binaryExpression("+", t.objectExpression([]), t.numericLiteral(1)),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => ({}) + 1");
});
it("not wrapped in parentheses in sequence expression", () => {
const sequenceExpression = t.sequenceExpression([
t.objectExpression([]),
t.numericLiteral(1),
]);
const output = generate(sequenceExpression).code;
expect(output).toBe("{}, 1");
});
it("wrapped in parentheses in sequence expression in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.sequenceExpression([t.objectExpression([]), t.numericLiteral(1)]),
);
const output = generate(expressionStatement).code;
expect(output).toBe("({}), 1;");
});
it("wrapped in parentheses in sequence expression in arrow function", () => {
const arrowFunctionExpression = t.arrowFunctionExpression(
[],
t.sequenceExpression([t.objectExpression([]), t.numericLiteral(1)]),
);
const output = generate(arrowFunctionExpression).code;
expect(output).toBe("() => (({}), 1)");
});
});
describe("function expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const functionExpression = t.functionExpression(
null,
[],
t.blockStatement([]),
);
const output = generate(functionExpression).code;
expect(output).toBe("function () {}");
});
it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.functionExpression(null, [], t.blockStatement([])),
);
const output = generate(expressionStatement).code;
expect(output).toBe("(function () {});");
});
it("wrapped in parentheses in export default declaration", () => {
const exportDefaultDeclaration = t.exportDefaultDeclaration(
t.functionExpression(null, [], t.blockStatement([])),
);
const output = generate(exportDefaultDeclaration).code;
expect(output).toBe("export default (function () {});");
});
});
describe("class expressions", () => {
it("not wrapped in parentheses when standalone", () => {
const classExpression = t.classExpression(null, null, t.classBody([]));
const output = generate(classExpression).code;
expect(output).toBe("class {}");
});
it("wrapped in parentheses in expression statement", () => {
const expressionStatement = t.expressionStatement(
t.classExpression(null, null, t.classBody([])),
);
const output = generate(expressionStatement).code;
expect(output).toBe("(class {});");
});
it("wrapped in parentheses in export default declaration", () => {
const exportDefaultDeclaration = t.exportDefaultDeclaration(
t.classExpression(null, null, t.classBody([])),
);
const output = generate(exportDefaultDeclaration).code;
expect(output).toBe("export default (class {});");
});
});
}); });
describe("CodeGenerator", function () { describe("CodeGenerator", function () {