Skip to content

Commit 777d62c

Browse files
authored
Destructuring nothing fix (#453)
* fixes for empty destructuring * cleanup * union destructuring test * removing duplicate test
1 parent d8a1898 commit 777d62c

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

src/LuaTransformer.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,9 @@ export class LuaTransformer {
16731673
throw TSTLErrors.ForbiddenEllipsisDestruction(statement);
16741674
}
16751675

1676-
const vars = statement.name.elements.map(e => this.transformArrayBindingElement(e));
1676+
const vars = statement.name.elements.length > 0
1677+
? statement.name.elements.map(e => this.transformArrayBindingElement(e))
1678+
: tstl.createAnnonymousIdentifier(statement.name);
16771679

16781680
// Don't unpack TupleReturn decorated functions
16791681
if (statement.initializer) {
@@ -2448,10 +2450,14 @@ export class LuaTransformer {
24482450

24492451
if (ts.isArrayLiteralExpression(expression.left)) {
24502452
// Destructuring assignment
2451-
const left = expression.left.elements.map(e => this.transformExpression(e));
2453+
const left = expression.left.elements.length > 0
2454+
? expression.left.elements.map(e => this.transformExpression(e))
2455+
: [tstl.createAnnonymousIdentifier(expression.left)];
24522456
let right: tstl.Expression[];
24532457
if (ts.isArrayLiteralExpression(expression.right)) {
2454-
right = expression.right.elements.map(e => this.transformExpression(e));
2458+
right = expression.right.elements.length > 0
2459+
? expression.right.elements.map(e => this.transformExpression(e))
2460+
: [tstl.createNilLiteral()];
24552461
} else if (tsHelper.isTupleReturnCall(expression.right, this.checker)) {
24562462
right = [this.transformExpression(expression.right)];
24572463
} else {
@@ -2479,16 +2485,20 @@ export class LuaTransformer {
24792485
if (ts.isArrayLiteralExpression(expression.left)) {
24802486
// Destructuring assignment
24812487
// (function() local ${tmps} = ${right}; ${left} = ${tmps}; return {${tmps}} end)()
2482-
const left = expression.left.elements.map(e => this.transformExpression(e));
2488+
const left = expression.left.elements.length > 0
2489+
? expression.left.elements.map(e => this.transformExpression(e))
2490+
: [tstl.createAnnonymousIdentifier(expression.left)];
24832491
let right: tstl.Expression[];
24842492
if (ts.isArrayLiteralExpression(expression.right)) {
2485-
right = expression.right.elements.map(e => this.transformExpression(e));
2493+
right = expression.right.elements.length > 0
2494+
? expression.right.elements.map(e => this.transformExpression(e))
2495+
: [tstl.createNilLiteral()];
24862496
} else if (tsHelper.isTupleReturnCall(expression.right, this.checker)) {
24872497
right = [this.transformExpression(expression.right)];
24882498
} else {
24892499
right = [this.createUnpackCall(this.transformExpression(expression.right), expression.right)];
24902500
}
2491-
const tmps = expression.left.elements.map((_, i) => tstl.createIdentifier(`____TS_tmp${i}`));
2501+
const tmps = left.map((_, i) => tstl.createIdentifier(`____TS_tmp${i}`));
24922502
const statements: tstl.Statement[] = [
24932503
tstl.createVariableDeclarationStatement(tmps, right),
24942504
tstl.createAssignmentStatement(left as tstl.IdentifierOrTableIndexExpression[], tmps),
@@ -4191,6 +4201,9 @@ export class LuaTransformer {
41914201

41924202
const fromTypeNode = this.checker.typeToTypeNode(fromType);
41934203
const toTypeNode = this.checker.typeToTypeNode(toType);
4204+
if (!fromTypeNode || !toTypeNode) {
4205+
return;
4206+
}
41944207

41954208
if ((ts.isArrayTypeNode(toTypeNode) || ts.isTupleTypeNode(toTypeNode))
41964209
&& (ts.isArrayTypeNode(fromTypeNode) || ts.isTupleTypeNode(fromTypeNode))) {

test/unit/assignmentDestructuring.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,27 @@ export class AssignmentDestructuringTests {
3737
// Assert
3838
Expect(lua).toBe(`local a, b = unpack(myFunc());`);
3939
}
40+
41+
@TestCase("function foo(): [] { return []; }; let [] = foo();")
42+
@TestCase("let [] = ['a', 'b', 'c'];")
43+
@TestCase("let [] = [];")
44+
@TestCase("let [] = [] = [];")
45+
@TestCase("function foo(): [] { return []; }; [] = foo();")
46+
@TestCase("[] = ['a', 'b', 'c'];")
47+
@TestCase("[] = [];")
48+
@TestCase("[] = [] = [];")
49+
@Test("Empty destructuring")
50+
public emptyDestructuring(code: string): void {
51+
Expect(() => util.transpileAndExecute(code)).not.toThrow();
52+
}
53+
54+
@Test("Union destructuring")
55+
public unionDestructuring(): void {
56+
const code =
57+
`function foo(): [string] | [] { return ["bar"]; }
58+
let x: string;
59+
[x] = foo();
60+
return x;`;
61+
Expect(util.transpileAndExecute(code)).toBe("bar");
62+
}
4063
}

0 commit comments

Comments
 (0)