Skip to content

Commit 8fb72f4

Browse files
ark120202Perryvw
authored andcommitted
Add array.flat and array.flatMap (#496)
1 parent a200793 commit 8fb72f4

File tree

6 files changed

+72
-0
lines changed

6 files changed

+72
-0
lines changed

src/LuaLib.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export enum LuaLibFeature {
1717
ArraySlice = "ArraySlice",
1818
ArraySome = "ArraySome",
1919
ArraySplice = "ArraySplice",
20+
ArrayFlat = "ArrayFlat",
21+
ArrayFlatMap = "ArrayFlatMap",
2022
ClassIndex = "ClassIndex",
2123
ClassNewIndex = "ClassNewIndex",
2224
FunctionApply = "FunctionApply",
@@ -42,6 +44,8 @@ export enum LuaLibFeature {
4244
}
4345

4446
const luaLibDependencies: {[lib in LuaLibFeature]?: LuaLibFeature[]} = {
47+
ArrayFlat: [LuaLibFeature.ArrayConcat],
48+
ArrayFlatMap: [LuaLibFeature.ArrayConcat],
4549
Iterator: [LuaLibFeature.Symbol],
4650
Map: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol],
4751
Set: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol],

src/LuaTransformer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3888,6 +3888,10 @@ export class LuaTransformer {
38883888
parameters,
38893889
node
38903890
);
3891+
case "flat":
3892+
return this.transformLuaLibFunction(LuaLibFeature.ArrayFlat, node, caller, ...params);
3893+
case "flatMap":
3894+
return this.transformLuaLibFunction(LuaLibFeature.ArrayFlatMap, node, caller, ...params);
38913895
default:
38923896
throw TSTLErrors.UnsupportedProperty("array", expressionName as string, node);
38933897
}

src/TSHelper.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const defaultArrayCallMethodNames = new Set<string>([
2525
"slice",
2626
"splice",
2727
"join",
28+
"flat",
29+
"flatMap",
2830
]);
2931

3032
const defaultArrayPropertyNames = new Set<string>([

src/lualib/ArrayFlat.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function __TS__ArrayFlat(this: void, array: any[], depth = 1): any[] {
2+
let result: any[] = [];
3+
for (const value of array) {
4+
if (depth > 0 && type(value) === "table" && 1 in value) {
5+
result = result.concat(__TS__ArrayFlat(value, depth - 1));
6+
} else {
7+
result[result.length] = value;
8+
}
9+
}
10+
11+
return result;
12+
}

src/lualib/ArrayFlatMap.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function __TS__ArrayFlatMap<T, U>(
2+
this: void,
3+
array: T[],
4+
callback: (value: T, index: number, array: T[]) => U | ReadonlyArray<U>
5+
): U[] {
6+
let result: U[] = [];
7+
for (let i = 0; i < array.length; i++) {
8+
const value = callback(array[i], i, array);
9+
if (type(value) === "table" && 1 in value) {
10+
result = result.concat(value);
11+
} else {
12+
result[result.length] = value as U;
13+
}
14+
}
15+
16+
return result;
17+
}

test/unit/lualib/lualib.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,39 @@ test.each([
377377
expect(result).toBe(JSON.stringify(array.sort(compareFn)));
378378
});
379379

380+
test.each([
381+
{ array: [1, [2, 3], 4], expected: [1, 2, 3, 4] },
382+
{ array: [1, [2, 3], 4], depth: 0, expected: [1, [2, 3], 4] },
383+
{ array: [1, [[2], [3]], 4], expected: [1, [2], [3], 4] },
384+
{ array: [1, [[[2], [3]]], 4], depth: Infinity, expected: [1, 2, 3, 4] },
385+
])("array.flat (%p)", ({ array, depth, expected }) => {
386+
// TODO: Remove once `Infinity` would be implemented
387+
const luaDepth = depth === Infinity ? "1 / 0" : depth;
388+
const result = util.transpileAndExecute(`
389+
return JSONStringify(${JSON.stringify(array)}.flat(${luaDepth}))
390+
`);
391+
392+
expect(JSON.parse(result)).toEqual(expected);
393+
});
394+
395+
test.each([
396+
{ array: [1, [2, 3], [4]], map: <T>(value: T) => value },
397+
{ array: [1, 2, 3], map: (v: number) => v * 2 },
398+
{ array: [1, 2, 3], map: (v: number) => [v, v * 2] },
399+
{ array: [1, 2, 3], map: (v: number) => [v, [v]] },
400+
{ array: [1, 2, 3], map: (v: number, i: number) => [v * 2 * i] },
401+
])("array.flatMap (%p)", ({ array, map }) => {
402+
const result = util.transpileAndExecute(`
403+
const array = ${JSON.stringify(array)};
404+
const result = array.flatMap(${map.toString()});
405+
return JSONStringify(result);
406+
`);
407+
408+
// TODO(node 12): array.flatMap(map)
409+
const expected = [].concat(...(array as any[]).map(map));
410+
expect(JSON.parse(result)).toEqual(expected);
411+
});
412+
380413
test.each([
381414
{ condition: "true", lhs: "4", rhs: "5", expected: 4 },
382415
{ condition: "false", lhs: "4", rhs: "5", expected: 5 },

0 commit comments

Comments
 (0)