diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index d1fd6226e..e13a9a831 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -2683,6 +2683,8 @@ export class LuaTransformer { return this.transformArrayLiteral(expression as ts.ArrayLiteralExpression); case ts.SyntaxKind.ObjectLiteralExpression: return this.transformObjectLiteral(expression as ts.ObjectLiteralExpression); + case ts.SyntaxKind.OmittedExpression: + return this.transformOmittedExpression(expression as ts.OmittedExpression); case ts.SyntaxKind.DeleteExpression: return this.transformDeleteExpression(expression as ts.DeleteExpression); case ts.SyntaxKind.FunctionExpression: @@ -2909,7 +2911,7 @@ export class LuaTransformer { // Destructuring assignment const left = expression.left.elements.length > 0 - ? expression.left.elements.map(e => this.transformExpression(e)) + ? expression.left.elements.map(e => this.transformArrayBindingExpression(e)) : [tstl.createAnonymousIdentifier(expression.left)]; let right: tstl.Expression[]; if (ts.isArrayLiteralExpression(expression.right)) { @@ -3466,6 +3468,11 @@ export class LuaTransformer { return tstl.createTableExpression(properties, expression); } + public transformOmittedExpression(node: ts.OmittedExpression): ExpressionVisitResult { + const isWithinBindingAssignmentStatement = tsHelper.isWithinLiteralAssignmentStatement(node); + return isWithinBindingAssignmentStatement ? tstl.createAnonymousIdentifier() : tstl.createNilLiteral(node); + } + public transformDeleteExpression(expression: ts.DeleteExpression): ExpressionVisitResult { const lhs = this.transformExpression(expression.expression) as tstl.AssignmentLeftHandSideExpression; const assignment = tstl.createAssignmentStatement(lhs, tstl.createNilLiteral(), expression); @@ -4577,14 +4584,18 @@ export class LuaTransformer { } public transformArrayBindingElement(name: ts.ArrayBindingElement): ExpressionVisitResult { + return this.transformArrayBindingExpression(name as ts.Expression); + } + + public transformArrayBindingExpression(name: ts.Expression): ExpressionVisitResult { if (ts.isOmittedExpression(name)) { - return tstl.createIdentifier("__", name); + return this.transformOmittedExpression(name); } else if (ts.isIdentifier(name)) { return this.transformIdentifier(name); } else if (ts.isBindingElement(name) && ts.isIdentifier(name.name)) { return this.transformIdentifier(name.name); } else { - throw TSTLErrors.UnsupportedKind("array binding element", name.kind, name); + throw TSTLErrors.UnsupportedKind("array binding expression", name.kind, name); } } diff --git a/src/TSHelper.ts b/src/TSHelper.ts index aa21e8698..c6573521a 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -793,6 +793,19 @@ export function isEnumMember( } } +export function isWithinLiteralAssignmentStatement(node: ts.Node): boolean { + if (!node.parent) { + return false; + } + if (ts.isArrayLiteralExpression(node.parent) || ts.isObjectLiteralExpression(node.parent)) { + return isWithinLiteralAssignmentStatement(node.parent); + } else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { + return true; + } else { + return false; + } +} + export function moduleHasEmittedBody( statement: ts.ModuleDeclaration ): statement is ts.ModuleDeclaration & { body: ts.ModuleBlock | ts.ModuleDeclaration } { diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 44d3cb3d6..d3949620f 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -191,3 +191,22 @@ test.each([ `; expect(() => util.transpileAndExecute(code)).toThrowError(`invalid array length: ${result}`); }); + +test.each([0, 1, 2])("Array with OmittedExpression", index => { + const result = util.transpileAndExecute( + `const myarray = [1, , 2]; + return myarray[${index}];` + ); + + expect(result).toBe([1, , 2][index]); +}); + +test("OmittedExpression in Array Binding Assignment Statement", () => { + const result = util.transpileAndExecute( + `let a, c; + [a, , c] = [1, 2, 3]; + return a + c;` + ); + + expect(result).toBe(4); +});