Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/LuaPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,25 @@ export class LuaPrinter {
return this.createSourceNode(expression, chunks);
}

private canStripParenthesis(expression: tstl.Expression): boolean {
return (
tstl.isParenthesizedExpression(expression) ||
tstl.isTableIndexExpression(expression) ||
tstl.isCallExpression(expression) ||
tstl.isMethodCallExpression(expression) ||
tstl.isIdentifier(expression) ||
tstl.isNilLiteral(expression) ||
tstl.isNumericLiteral(expression) ||
tstl.isBooleanLiteral(expression)
);
}

public printParenthesizedExpression(expression: tstl.ParenthesizedExpression): SourceNode {
return this.createSourceNode(expression, ["(", this.printExpression(expression.innerExpression), ")"]);
const innerExpression = this.printExpression(expression.innerExpression);
if (this.canStripParenthesis(expression.innerExpression)) {
return this.createSourceNode(expression, innerExpression);
}
return this.createSourceNode(expression, ["(", innerExpression, ")"]);
}

public printCallExpression(expression: tstl.CallExpression): SourceNode {
Expand Down
5 changes: 0 additions & 5 deletions src/LuaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3432,11 +3432,6 @@ export class LuaTransformer {
}

public transformParenthesizedExpression(expression: ts.ParenthesizedExpression): ExpressionVisitResult {
if (ts.isAssertionExpression(expression.expression)) {
// Strip parenthesis from casts
return this.transformExpression(expression.expression);
}

return tstl.createParenthesizedExpression(this.transformExpression(expression.expression), expression);
}

Expand Down
4 changes: 2 additions & 2 deletions test/translation/__snapshots__/transformation.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ exports[`Transformation (tryCatch) 1`] = `
local ____TS_try, er = pcall(function()
local a = 42
end)
if not (____TS_try) then
if not ____TS_try then
local b = \\"fail\\"
end
end"
Expand All @@ -591,7 +591,7 @@ exports[`Transformation (tryCatchFinally) 1`] = `
local ____TS_try, er = pcall(function()
local a = 42
end)
if not (____TS_try) then
if not ____TS_try then
local b = \\"fail\\"
end
do
Expand Down
63 changes: 63 additions & 0 deletions test/unit/expressions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,66 @@ test.each([
`;
expect(util.transpileAndExecute(code)).toBe(1);
});

test("binary expression with 'as' type assertion wrapped in parenthesis", () => {
expect(util.transpileAndExecute("return 2 * (3 - 2 as number);")).toBe(2);
});

test.each([
"(x as any).foo;",
"(y.x as any).foo;",
"(y['x'] as any).foo;",
"(z() as any).foo;",
"(y.z() as any).foo;",
"(<any>x).foo;",
"(<any>y.x).foo;",
"(<any>y['x']).foo;",
"(<any>z()).foo;",
"(<any>y.z()).foo;",
"(x as unknown as any).foo;",
"(<unknown>x as any).foo;",
"((x as unknown) as any).foo;",
"((<unknown>x) as any).foo;",
])("'as' type assertion should strip parenthesis (%p)", expression => {
const code = `
declare let x: unknown;
declare let y: { x: unknown; z(this: void): unknown; };
declare function z(this: void): unknown;
${expression}`;

const lua = util.transpileString(code, undefined, false);
expect(lua).not.toMatch(/\(.+\)/);
});

test.each([
"(x + 1 as any).foo;",
"(!x as any).foo;",
"(x ** 2 as any).foo;",
"(x < 2 as any).foo;",
"(x in y as any).foo;",
"(<any>x + 1).foo;",
"(<any>!x).foo;",
"(x + 1 as unknown as any).foo;",
"((x + 1 as unknown) as any).foo;",
"(!x as unknown as any).foo;",
"((!x as unknown) as any).foo;",
"(<unknown>!x as any).foo;",
"((<unknown>!x) as any).foo;",
])("'as' type assertion should not strip parenthesis (%p)", expression => {
const code = `
declare let x: number;
declare let y: {};
${expression}`;

const lua = util.transpileString(code, undefined, false);
expect(lua).toMatch(/\(.+\)/);
});

test("not operator precedence (%p)", () => {
const code = `
const a = true;
const b = false;
return !a && b;`;

expect(util.transpileAndExecute(code)).toBe(false);
});