Skip to content

Commit 51a125e

Browse files
tomblindPerryvw
authored andcommitted
updated call & table expression formatting (#639)
* updated call/table expression formatting Arguments/fields will now only be split into multiple lines if one or more has evaluation side-effects that would be beneficial for a debugger to step on. * moved isSimpleExpression to tsHelper
1 parent d9a996f commit 51a125e

File tree

9 files changed

+150
-93
lines changed

9 files changed

+150
-93
lines changed

src/LuaAST.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ export function createTableFieldExpression(
677677
tsOriginal?: ts.Node,
678678
parent?: Node
679679
): TableFieldExpression {
680-
const expression = createNode(SyntaxKind.TableExpression, tsOriginal, parent) as TableFieldExpression;
680+
const expression = createNode(SyntaxKind.TableFieldExpression, tsOriginal, parent) as TableFieldExpression;
681681
setParent(value, expression);
682682
expression.value = value;
683683
setParent(key, expression);

src/LuaPrinter.ts

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -571,17 +571,8 @@ export class LuaPrinter {
571571

572572
chunks.push("{");
573573

574-
if (expression.fields && expression.fields.length > 0) {
575-
if (expression.fields.length === 1) {
576-
// Inline tables with only one entry
577-
chunks.push(this.printTableFieldExpression(expression.fields[0]));
578-
} else {
579-
chunks.push("\n");
580-
this.pushIndent();
581-
expression.fields.forEach(f => chunks.push(this.indent(), this.printTableFieldExpression(f), ",\n"));
582-
this.popIndent();
583-
chunks.push(this.indent());
584-
}
574+
if (expression.fields) {
575+
chunks.push(...this.printExpressionList(expression.fields));
585576
}
586577

587578
chunks.push("}");
@@ -632,30 +623,33 @@ export class LuaPrinter {
632623
public printCallExpression(expression: tstl.CallExpression): SourceNode {
633624
const chunks = [];
634625

635-
const parameterChunks =
636-
expression.params !== undefined ? expression.params.map(e => this.printExpression(e)) : [];
626+
chunks.push(this.printExpression(expression.expression), "(");
637627

638-
chunks.push(this.printExpression(expression.expression), "(", ...this.joinChunks(", ", parameterChunks), ")");
628+
if (expression.params) {
629+
chunks.push(...this.printExpressionList(expression.params));
630+
}
631+
632+
chunks.push(")");
639633

640634
return this.createSourceNode(expression, chunks);
641635
}
642636

643637
public printMethodCallExpression(expression: tstl.MethodCallExpression): SourceNode {
644-
const prefix = this.printExpression(expression.prefixExpression);
638+
const chunks = [];
645639

646-
const parameterChunks =
647-
expression.params !== undefined ? expression.params.map(e => this.printExpression(e)) : [];
640+
const prefix = this.printExpression(expression.prefixExpression);
648641

649642
const name = this.printIdentifier(expression.name);
650643

651-
return this.createSourceNode(expression, [
652-
prefix,
653-
":",
654-
name,
655-
"(",
656-
...this.joinChunks(", ", parameterChunks),
657-
")",
658-
]);
644+
chunks.push(prefix, ":", name, "(");
645+
646+
if (expression.params) {
647+
chunks.push(...this.printExpressionList(expression.params));
648+
}
649+
650+
chunks.push(")");
651+
652+
return this.createSourceNode(expression, chunks);
659653
}
660654

661655
public printIdentifier(expression: tstl.Identifier): SourceNode {
@@ -715,6 +709,25 @@ export class LuaPrinter {
715709
return result;
716710
}
717711

712+
protected printExpressionList(expressions: tstl.Expression[]): SourceChunk[] {
713+
const chunks: SourceChunk[] = [];
714+
715+
if (expressions.every(e => tsHelper.isSimpleExpression(e))) {
716+
chunks.push(...this.joinChunks(", ", expressions.map(e => this.printExpression(e))));
717+
} else {
718+
chunks.push("\n");
719+
this.pushIndent();
720+
expressions.forEach((p, i) => {
721+
const tail = i < expressions.length - 1 ? ",\n" : "\n";
722+
chunks.push(this.indent(), this.printExpression(p), tail);
723+
});
724+
this.popIndent();
725+
chunks.push(this.indent());
726+
}
727+
728+
return chunks;
729+
}
730+
718731
// The key difference between this and SourceNode.toStringWithSourceMap() is that SourceNodes with null line/column
719732
// will not generate 'empty' mappings in the source map that point to nothing in the original TS.
720733
private buildSourceMap(sourceFile: string, sourceRoot: string, rootSourceNode: SourceNode): SourceMapGenerator {

src/TSHelper.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as ts from "typescript";
22
import { Decorator, DecoratorKind } from "./Decorator";
3+
import * as tstl from "./LuaAST";
34

45
export enum ContextType {
56
None,
@@ -835,3 +836,39 @@ export function isArrayLengthAssignment(
835836

836837
return name === "length";
837838
}
839+
840+
// Returns true if expression contains no function calls
841+
export function isSimpleExpression(expression: tstl.Expression): boolean {
842+
switch (expression.kind) {
843+
case tstl.SyntaxKind.CallExpression:
844+
case tstl.SyntaxKind.MethodCallExpression:
845+
case tstl.SyntaxKind.FunctionExpression:
846+
return false;
847+
848+
case tstl.SyntaxKind.TableExpression:
849+
const tableExpression = expression as tstl.TableExpression;
850+
return !tableExpression.fields || tableExpression.fields.every(e => isSimpleExpression(e));
851+
852+
case tstl.SyntaxKind.TableFieldExpression:
853+
const fieldExpression = expression as tstl.TableFieldExpression;
854+
return (
855+
(!fieldExpression.key || isSimpleExpression(fieldExpression.key)) &&
856+
isSimpleExpression(fieldExpression.value)
857+
);
858+
859+
case tstl.SyntaxKind.TableIndexExpression:
860+
const indexExpression = expression as tstl.TableIndexExpression;
861+
return isSimpleExpression(indexExpression.table) && isSimpleExpression(indexExpression.index);
862+
863+
case tstl.SyntaxKind.UnaryExpression:
864+
return isSimpleExpression((expression as tstl.UnaryExpression).operand);
865+
866+
case tstl.SyntaxKind.BinaryExpression:
867+
const binaryExpression = expression as tstl.BinaryExpression;
868+
return isSimpleExpression(binaryExpression.left) && isSimpleExpression(binaryExpression.right);
869+
870+
case tstl.SyntaxKind.ParenthesizedExpression:
871+
return isSimpleExpression((expression as tstl.ParenthesizedExpression).innerExpression);
872+
}
873+
return true;
874+
}

test/translation/__snapshots__/transformation.spec.ts.snap

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -228,28 +228,12 @@ end"
228228
`;
229229

230230
exports[`Transformation (forIn) 1`] = `
231-
"for i in pairs({
232-
a = 1,
233-
b = 2,
234-
c = 3,
235-
d = 4,
236-
}) do
231+
"for i in pairs({a = 1, b = 2, c = 3, d = 4}) do
237232
end"
238233
`;
239234

240235
exports[`Transformation (forOf) 1`] = `
241-
"for ____, i in ipairs({
242-
1,
243-
2,
244-
3,
245-
4,
246-
5,
247-
6,
248-
7,
249-
8,
250-
9,
251-
10,
252-
}) do
236+
"for ____, i in ipairs({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) do
253237
end"
254238
`;
255239

@@ -577,9 +561,11 @@ f = function(____, x) return ({x = x}) end"
577561

578562
exports[`Transformation (tryCatch) 1`] = `
579563
"do
580-
local ____TS_try, er = pcall(function()
581-
local a = 42
582-
end)
564+
local ____TS_try, er = pcall(
565+
function()
566+
local a = 42
567+
end
568+
)
583569
if not ____TS_try then
584570
local b = \\"fail\\"
585571
end
@@ -588,9 +574,11 @@ end"
588574

589575
exports[`Transformation (tryCatchFinally) 1`] = `
590576
"do
591-
local ____TS_try, er = pcall(function()
592-
local a = 42
593-
end)
577+
local ____TS_try, er = pcall(
578+
function()
579+
local a = 42
580+
end
581+
)
594582
if not ____TS_try then
595583
local b = \\"fail\\"
596584
end
@@ -602,9 +590,11 @@ end"
602590

603591
exports[`Transformation (tryFinally) 1`] = `
604592
"do
605-
pcall(function()
606-
local a = 42
607-
end)
593+
pcall(
594+
function()
595+
local a = 42
596+
end
597+
)
608598
do
609599
local b = \\"finally\\"
610600
end
@@ -618,30 +608,47 @@ end
618608
tupleReturn(_G)
619609
noTupleReturn(_G)
620610
local a, b = tupleReturn(_G)
621-
local c, d = table.unpack(noTupleReturn(_G))
611+
local c, d = table.unpack(
612+
noTupleReturn(_G)
613+
)
622614
a, b = tupleReturn(_G)
623-
c, d = table.unpack(noTupleReturn(_G))
624-
local e = ({tupleReturn(_G)})
615+
c, d = table.unpack(
616+
noTupleReturn(_G)
617+
)
618+
local e = ({
619+
tupleReturn(_G)
620+
})
625621
local f = noTupleReturn(_G)
626-
e = ({tupleReturn(_G)})
622+
e = ({
623+
tupleReturn(_G)
624+
})
627625
f = noTupleReturn(_G)
628-
foo(_G, ({tupleReturn(_G)}))
629-
foo(_G, noTupleReturn(_G))
626+
foo(
627+
_G,
628+
({
629+
tupleReturn(_G)
630+
})
631+
)
632+
foo(
633+
_G,
634+
noTupleReturn(_G)
635+
)
630636
function tupleReturnFromVar(self)
631-
local r = {
632-
1,
633-
\\"baz\\",
634-
}
637+
local r = {1, \\"baz\\"}
635638
return table.unpack(r)
636639
end
637640
function tupleReturnForward(self)
638641
return tupleReturn(_G)
639642
end
640643
function tupleNoForward(self)
641-
return ({tupleReturn(_G)})
644+
return ({
645+
tupleReturn(_G)
646+
})
642647
end
643648
function tupleReturnUnpack(self)
644-
return table.unpack(tupleNoForward(_G))
649+
return table.unpack(
650+
tupleNoForward(_G)
651+
)
645652
end"
646653
`;
647654

test/unit/assignmentDestructuring.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@ test("Assignment destructuring [5.1]", () => {
1010
luaTarget: tstl.LuaTarget.Lua51,
1111
luaLibImport: tstl.LuaLibImportKind.None,
1212
});
13-
expect(lua).toBe(`local a, b = unpack(myFunc())`);
13+
expect(lua).toBe(`local a, b = unpack(\n myFunc()\n)`);
1414
});
1515

1616
test("Assignment destructuring [5.2]", () => {
1717
const lua = util.transpileString(assignmentDestruturingTs, {
1818
luaTarget: tstl.LuaTarget.Lua52,
1919
luaLibImport: tstl.LuaLibImportKind.None,
2020
});
21-
expect(lua).toBe(`local a, b = table.unpack(myFunc())`);
21+
expect(lua).toBe(`local a, b = table.unpack(\n myFunc()\n)`);
2222
});
2323

2424
test("Assignment destructuring [JIT]", () => {
2525
const lua = util.transpileString(assignmentDestruturingTs, {
2626
luaTarget: tstl.LuaTarget.LuaJIT,
2727
luaLibImport: tstl.LuaLibImportKind.None,
2828
});
29-
expect(lua).toBe(`local a, b = unpack(myFunc())`);
29+
expect(lua).toBe(`local a, b = unpack(\n myFunc()\n)`);
3030
});
3131

3232
test.each([

test/unit/assignments/assignments.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import * as util from "../../util";
44
test.each([
55
{ inp: `"abc"`, out: `"abc"` },
66
{ inp: "3", out: "3" },
7-
{ inp: "[1,2,3]", out: "{\n 1,\n 2,\n 3,\n}" },
7+
{ inp: "[1,2,3]", out: "{1, 2, 3}" },
88
{ inp: "true", out: "true" },
99
{ inp: "false", out: "false" },
10-
{ inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` },
10+
{ inp: `{a:3,b:"4"}`, out: `{a = 3, b = "4"}` },
1111
])("Const assignment (%p)", ({ inp, out }) => {
1212
const lua = util.transpileString(`const myvar = ${inp}`);
1313
expect(lua).toBe(`local myvar = ${out}`);
@@ -16,10 +16,10 @@ test.each([
1616
test.each([
1717
{ inp: `"abc"`, out: `"abc"` },
1818
{ inp: "3", out: "3" },
19-
{ inp: "[1,2,3]", out: "{\n 1,\n 2,\n 3,\n}" },
19+
{ inp: "[1,2,3]", out: "{1, 2, 3}" },
2020
{ inp: "true", out: "true" },
2121
{ inp: "false", out: "false" },
22-
{ inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` },
22+
{ inp: `{a:3,b:"4"}`, out: `{a = 3, b = "4"}` },
2323
])("Let assignment (%p)", ({ inp, out }) => {
2424
const lua = util.transpileString(`let myvar = ${inp}`);
2525
expect(lua).toBe(`local myvar = ${out}`);
@@ -28,10 +28,10 @@ test.each([
2828
test.each([
2929
{ inp: `"abc"`, out: `"abc"` },
3030
{ inp: "3", out: "3" },
31-
{ inp: "[1,2,3]", out: "{\n 1,\n 2,\n 3,\n}" },
31+
{ inp: "[1,2,3]", out: "{1, 2, 3}" },
3232
{ inp: "true", out: "true" },
3333
{ inp: "false", out: "false" },
34-
{ inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` },
34+
{ inp: `{a:3,b:"4"}`, out: `{a = 3, b = "4"}` },
3535
])("Var assignment (%p)", ({ inp, out }) => {
3636
const lua = util.transpileString(`var myvar = ${inp}`);
3737
expect(lua).toBe(`myvar = ${out}`);
@@ -95,7 +95,7 @@ test("TupleReturn Single assignment", () => {
9595
`;
9696

9797
const lua = util.transpileString(code);
98-
expect(lua).toBe("local a = ({abc()})\na = ({abc()})");
98+
expect(lua).toBe("local a = ({\n abc()\n})\na = ({\n abc()\n})");
9999
});
100100

101101
test("TupleReturn interface assignment", () => {

0 commit comments

Comments
 (0)