-
-
Notifications
You must be signed in to change notification settings - Fork 185
SpreadAssignment support #693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b1979e8
92aab34
6874c2f
54c76fa
ae6090b
088621c
b4e44f7
c990cc5
66abf4f
c808963
b460656
635c96a
afdf28c
fc0de2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3836,7 +3836,8 @@ export class LuaTransformer { | |
| } | ||
|
|
||
| public transformObjectLiteral(expression: ts.ObjectLiteralExpression): ExpressionVisitResult { | ||
| const properties: tstl.TableFieldExpression[] = []; | ||
| let properties: tstl.TableFieldExpression[] = []; | ||
| const tableExpressions: tstl.Expression[] = []; | ||
| // Add all property assignments | ||
| expression.properties.forEach(element => { | ||
| const name = element.name ? this.transformPropertyName(element.name) : undefined; | ||
|
|
@@ -3853,12 +3854,46 @@ export class LuaTransformer { | |
| } else if (ts.isMethodDeclaration(element)) { | ||
| const expression = this.transformFunctionExpression(element); | ||
| properties.push(tstl.createTableFieldExpression(expression, name, element)); | ||
| } else if (ts.isSpreadAssignment(element)) { | ||
| // Create a table for preceding properties to preserve property order | ||
| // { x: 0, ...{ y: 2 }, y: 1, z: 2 } --> __TS__ObjectAssign({x = 0}, {y = 2}, {y = 1, z = 2}) | ||
| if (properties.length > 0) { | ||
| const tableExpression = tstl.createTableExpression(properties, expression); | ||
| tableExpressions.push(tableExpression); | ||
| } | ||
| properties = []; | ||
|
|
||
| const type = this.checker.getTypeAtLocation(element.expression); | ||
| let tableExpression: tstl.Expression; | ||
| if (type && tsHelper.isArrayType(type, this.checker, this.program)) { | ||
| tableExpression = this.transformLuaLibFunction( | ||
| LuaLibFeature.ArrayToObject, | ||
| element.expression, | ||
| this.transformExpression(element.expression) | ||
| ); | ||
| } else { | ||
| tableExpression = this.transformExpression(element.expression); | ||
| } | ||
| tableExpressions.push(tableExpression); | ||
| } else { | ||
| throw TSTLErrors.UnsupportedKind("object literal element", element.kind, expression); | ||
| } | ||
| }); | ||
|
|
||
| return tstl.createTableExpression(properties, expression); | ||
| if (tableExpressions.length === 0) { | ||
| return tstl.createTableExpression(properties, expression); | ||
| } else { | ||
| if (properties.length > 0) { | ||
| const tableExpression = tstl.createTableExpression(properties, expression); | ||
| tableExpressions.push(tableExpression); | ||
| } | ||
|
|
||
| if (tableExpressions[0].kind !== tstl.SyntaxKind.TableExpression) { | ||
| tableExpressions.unshift(tstl.createTableExpression(undefined, expression)); | ||
| } | ||
|
|
||
| return this.transformLuaLibFunction(LuaLibFeature.ObjectAssign, expression, ...tableExpressions); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really good edge cases, thanks! |
||
| } | ||
| } | ||
|
|
||
| public transformOmittedExpression(node: ts.OmittedExpression): ExpressionVisitResult { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| function __TS__ArrayToObject(this: void, array: any[]): object { | ||
| const object: Record<number, any> = {}; | ||
| for (let i = 0; i < array.length; i += 1) { | ||
| object[i] = array[i]; | ||
| } | ||
| return object; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,13 @@ | ||
| function __TS__Spread<T>(this: void, iterable: Iterable<T>): T[] { | ||
| const arr: T[] = []; | ||
| for (const item of iterable) { | ||
| arr[arr.length] = item; | ||
| function __TS__Spread<T>(this: void, iterable: string | Iterable<T>): T[] { | ||
| const arr = []; | ||
| if (typeof iterable === "string") { | ||
| for (let i = 0; i < iterable.length; i += 1) { | ||
| arr[arr.length] = iterable[i]; | ||
| } | ||
| } else { | ||
| for (const item of iterable) { | ||
| arr[arr.length] = item; | ||
| } | ||
| } | ||
| return (table.unpack || unpack)(arr); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| const xy = { ...{ x: 0, y: 1 } }; | ||
| const xyz = { ...{ x: 0, y: 1 }, z: 2 }; | ||
| const xyz2 = { z: 2, ...{ x: 0, y: 1 } }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,3 +64,51 @@ test("Spread Element Iterable", () => { | |
| return JSONStringify(arr)`; | ||
| expect(JSON.parse(util.transpileAndExecute(code))).toEqual([1, 2, 4, 8, 16, 32, 64, 128, 256]); | ||
| }); | ||
|
|
||
| test.each(["", "string", "string with spaces", "string 1 2 3"])('Spread Element String "%s"', str => { | ||
| const code = ` | ||
| const arr = [..."${str}"]; | ||
| return JSONStringify(arr)`; | ||
| expect(JSON.parse(util.transpileAndExecute(code))).toEqual([...str]); | ||
| }); | ||
|
|
||
| test.each([ | ||
| "{ value: false, ...{ value: true } }", | ||
| "{ ...{ value: false }, value: true }", | ||
| "{ ...{ value: false }, value: false, ...{ value: true } }", | ||
Perryvw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "{ ...{ x: true, y: true } }", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need a single-property test if we have a multi-property one? |
||
| "{ x: true, ...{ y: true, z: true } }", | ||
| "{ ...{ x: true }, ...{ y: true, z: true } }", | ||
| ])('SpreadAssignment "%s"', expression => { | ||
| const code = `return JSONStringify(${expression});`; | ||
| expect(JSON.parse(util.transpileAndExecute(code))).toEqual(eval(`(${expression})`)); | ||
| }); | ||
|
|
||
| test("SpreadAssignment Destructure", () => { | ||
| const code = `let obj = { x: 0, y: 1, z: 2 };`; | ||
| const luaCode = ` | ||
| ${code} | ||
| return JSONStringify({ a: 0, ...obj, b: 1, c: 2 });`; | ||
| const jsCode = ` | ||
| ${code} | ||
| ({ a: 0, ...obj, b: 1, c: 2 })`; | ||
| expect(JSON.parse(util.transpileAndExecute(luaCode))).toStrictEqual(eval(jsCode)); | ||
| }); | ||
|
|
||
| test("SpreadAssignment No Mutation", () => { | ||
| const code = ` | ||
| const obj: { x: number, y: number, z?: number } = { x: 0, y: 1 }; | ||
| const merge = { ...obj, z: 2 }; | ||
| return obj.z;`; | ||
| expect(util.transpileAndExecute(code)).toBe(undefined); | ||
| }); | ||
|
|
||
| test.each([ | ||
| "function spread() { return [0, 1, 2] } const object = { ...spread() };", | ||
| "const object = { ...[0, 1, 2] };", | ||
| ])('SpreadAssignment Array "%s"', expressionToCreateObject => { | ||
| const code = ` | ||
| ${expressionToCreateObject} | ||
| return JSONStringify([object[0], object[1], object[2]]);`; | ||
| expect(JSON.parse(util.transpileAndExecute(code))).toEqual([0, 1, 2]); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.