Skip to content

Commit 9f7739a

Browse files
authored
Merge pull request #43 from Perryvw/string-constructor-fix
Added Tests for while loop & string functions
2 parents 11a2c11 + c36222f commit 9f7739a

File tree

6 files changed

+165
-21
lines changed

6 files changed

+165
-21
lines changed

src/Transpiler.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,11 @@ export class LuaTranspiler {
561561
case ts.SyntaxKind.PlusToken:
562562
// Replace string + with ..
563563
const typeLeft = this.checker.getTypeAtLocation(node.left);
564+
const typeRight = this.checker.getTypeAtLocation(node.right);
564565
if (typeLeft.flags & ts.TypeFlags.String || ts.isStringLiteral(node.left))
565566
return lhs + ".." + rhs;
567+
if (typeRight.flags & ts.TypeFlags.String || ts.isStringLiteral(node.right))
568+
return lhs + ".." + rhs;
566569
default:
567570
result = lhs + this.transpileOperator(node.operatorToken) + rhs;
568571
}
@@ -647,28 +650,27 @@ export class LuaTranspiler {
647650
transpileCallExpression(node: ts.CallExpression): string {
648651
// Check for calls on primitives to override
649652
if (ts.isPropertyAccessExpression(node.expression)) {
650-
const type = this.checker.getTypeAtLocation(node.expression.expression);
651-
switch (type.flags) {
652-
case ts.TypeFlags.String:
653-
case ts.TypeFlags.StringLiteral:
654-
return this.transpileStringCallExpression(node);
655-
case ts.TypeFlags.Object:
656-
if (tsEx.isArrayType(type))
657-
return this.transpileArrayCallExpression(node);
658-
}
659-
660653
const expType = this.checker.getTypeAtLocation(node.expression.expression);
661654

662655
if (expType.symbol && expType.symbol.escapedName == "Math") {
663656
const params = this.transpileArguments(node.arguments);
664657
return this.transpileMathExpression(node.expression.name) + `(${params})`;
665658
}
666659

667-
if (ts.isIdentifier(node.expression) && node.expression.escapedText == "String") {
660+
if (this.transpileExpression((node.expression as ts.PropertyAccessExpression).expression) === "String") {
668661
const params = this.transpileArguments(node.arguments);
669662
return this.transpileStringExpression(node.expression.name) + `(${params})`;
670663
}
671664

665+
switch (expType.flags) {
666+
case ts.TypeFlags.String:
667+
case ts.TypeFlags.StringLiteral:
668+
return this.transpileStringCallExpression(node);
669+
case ts.TypeFlags.Object:
670+
if (tsEx.isArrayType(expType))
671+
return this.transpileArrayCallExpression(node);
672+
}
673+
672674
// Include context parameter if present
673675
let callPath = (expType && expType.symbol) ? `${expType.symbol.name}.${node.expression.name.escapedText}` : this.transpileExpression(node.expression);
674676
let params = this.transpileArguments(node.arguments, node.expression.expression);
@@ -694,7 +696,7 @@ export class LuaTranspiler {
694696
const caller = this.transpileExpression(expression.expression);
695697
switch (expression.name.escapedText) {
696698
case "replace":
697-
return `string.sub(${caller},${params})`;
699+
return `string.gsub(${caller},${params})`;
698700
case "indexOf":
699701
if (node.arguments.length == 1) {
700702
return `(string.find(${caller},${params},1,true) or 0)-1`;
@@ -707,7 +709,7 @@ export class LuaTranspiler {
707709
} else {
708710
const arg1 = this.transpileExpression(node.arguments[0]);
709711
const arg2 = this.transpileExpression(node.arguments[1]);
710-
return `string.sub(${caller},${arg1}+1,${arg2}+1)`;
712+
return `string.sub(${caller},${arg1}+1,${arg2})`;
711713
}
712714
default:
713715
throw new TranspileError("Unsupported string function: " + expression.name.escapedText, node);

test/integration/lua/loops.spec.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,31 @@ const deepEqual = require('deep-equal')
55

66
export class LuaLoopTests {
77

8+
@TestCase([0, 1, 2, 3], [1, 2, 3, 4])
9+
@Test("while")
10+
public while(inp: number[], expected: number[]) {
11+
// Transpile
12+
let lua = util.transpileString(
13+
`let arrTest = ${JSON.stringify(inp)};
14+
let i = 0;
15+
while (i < arrTest.length) {
16+
arrTest[i] = arrTest[i] + 1;
17+
i++;
18+
}
19+
return JSONStringify(arrTest);`
20+
, util.dummyTypes.Array
21+
);
22+
23+
// Execute
24+
let result = util.executeLua(lua);
25+
26+
// Assert
27+
Expect(result).toBe(JSON.stringify(expected));
28+
}
29+
830
@TestCase([0, 1, 2, 3], [1, 2, 3, 4])
931
@Test("for")
10-
public for<T>(inp: T[], expected: T[]) {
32+
public for(inp: number[], expected: number[]) {
1133
// Transpile
1234
let lua = util.transpileString(
1335
`let arrTest = ${JSON.stringify(inp)};
@@ -27,7 +49,7 @@ export class LuaLoopTests {
2749

2850
@TestCase({ ['test1']: 0, ['test2']: 1, ['test3']: 2 }, { ['test1']: 1, ['test2']: 2, ['test3']: 3 })
2951
@Test("forin[Object]")
30-
public forinObject<T>(inp: any, expected: any) {
52+
public forinObject(inp: any, expected: any) {
3153
// Transpile
3254
let lua = util.transpileString(
3355
`let objTest = ${JSON.stringify(inp)};
@@ -45,9 +67,9 @@ export class LuaLoopTests {
4567
Expect(deepEqual(JSON.parse(result), expected)).toBe(true);
4668
}
4769

48-
@TestCase([1,2,3])
70+
@TestCase([1, 2, 3])
4971
@Test("forin[Array]")
50-
public forinArray<T>(inp: T[]) {
72+
public forinArray(inp: number[]) {
5173
// Transpile & Assert
5274
Expect(() => {
5375
let lua = util.transpileString(
@@ -60,9 +82,9 @@ export class LuaLoopTests {
6082
}).toThrowError(Error, "Iterating over arrays with 'for in' is not allowed.");
6183
}
6284

63-
@TestCase([0,1,2], [1,2,3])
85+
@TestCase([0, 1, 2], [1, 2, 3])
6486
@Test("forof")
65-
public forof<T>(inp: any, expected: any) {
87+
public forof(inp: any, expected: any) {
6688
// Transpile
6789
let lua = util.transpileString(
6890
`let objTest = ${JSON.stringify(inp)};
@@ -80,4 +102,5 @@ export class LuaLoopTests {
80102
// Assert
81103
Expect(result).toBe(JSON.stringify(expected));
82104
}
105+
83106
}

test/integration/lua/lualib.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,5 +168,4 @@ export class LuaLibArrayTests {
168168
let joinedInp = inp.join(seperator);
169169
Expect(result).toBe(joinedInp);
170170
}
171-
172171
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Expect, Test, TestCase, IgnoreTest } from "alsatian";
2+
import * as util from "../../src/util"
3+
4+
export class StringTests {
5+
6+
@TestCase([])
7+
@TestCase([65])
8+
@TestCase([65, 66])
9+
@TestCase([65, 66, 67])
10+
@Test("String.fromCharCode")
11+
public stringFromCharcode(inp: number[], expected: string) {
12+
// Transpile
13+
let lua = util.transpileString(
14+
`return String.fromCharCode(${inp.toString()})`,
15+
util.dummyTypes.String
16+
);
17+
18+
// Execute
19+
let result = util.executeLua(lua);
20+
21+
// Assert
22+
Expect(result).toBe(String.fromCharCode(...inp));
23+
}
24+
25+
@TestCase("hello test", "", "")
26+
@TestCase("hello test", " ", "")
27+
@TestCase("hello test", "hello", "")
28+
@TestCase("hello test", "test", "")
29+
@TestCase("hello test", "test", "world")
30+
@Test("string.replace")
31+
public replace<T>(inp: string, searchValue: string, replaceValue: string) {
32+
// Transpile
33+
let lua = util.transpileString(
34+
`return "${inp}".replace("${searchValue}", "${replaceValue}")`,
35+
util.dummyTypes.String
36+
);
37+
38+
// Execute
39+
let result = util.executeLua(lua);
40+
41+
// Assert
42+
Expect(result).toBe(inp.replace(searchValue, replaceValue));
43+
}
44+
45+
@TestCase(["", ""], "")
46+
@TestCase(["hello", "test"], "hellotest")
47+
@TestCase(["hello", "test", "bye"], "hellotestbye")
48+
@TestCase(["hello", 42], "hello42")
49+
@TestCase([42, "hello"], "42hello")
50+
@Test("string.concat[+]")
51+
public concat(inp: any[], expected: string) {
52+
// Transpile
53+
let lua = util.transpileString(
54+
`return '${inp.join("' + '")}'`,
55+
util.dummyTypes.String
56+
);
57+
58+
// Execute
59+
let result = util.executeLua(lua);
60+
61+
// Assert
62+
Expect(result).toBe(expected);
63+
}
64+
65+
@TestCase("hello test", new RegExp("123", "g"), "")
66+
@IgnoreTest()
67+
@Test("string.replace[Regex]")
68+
public replaceRegex(inp: string, searchValue: string, replaceValue: string) {
69+
// Transpile
70+
let lua = util.transpileString(
71+
`return "${inp}".replace("${searchValue}", "${replaceValue}")`,
72+
util.dummyTypes.String
73+
);
74+
75+
// Execute
76+
let result = util.executeLua(lua);
77+
78+
// Assert
79+
Expect(result).toBe(inp.replace(searchValue, replaceValue));
80+
}
81+
82+
@TestCase("hello test", "")
83+
@TestCase("hello test", "t")
84+
@TestCase("hello test", "h")
85+
@Test("string.indexOf")
86+
public indexOf(inp: string, searchValue: string) {
87+
// Transpile
88+
let lua = util.transpileString(
89+
`return "${inp}".indexOf("${searchValue}")`,
90+
util.dummyTypes.String
91+
);
92+
93+
// Execute
94+
let result = util.executeLua(lua);
95+
96+
// Assert
97+
Expect(result).toBe(inp.indexOf(searchValue));
98+
}
99+
100+
@TestCase("hello test", 0)
101+
@TestCase("hello test", 1)
102+
@TestCase("hello test", 1, 2)
103+
@TestCase("hello test", 1, 5)
104+
@Test("string.substring")
105+
public substring(inp: string, start: number, end?: number) {
106+
// Transpile
107+
let paramStr = end ? `${start}, ${end}` : `${start}`;
108+
let lua = util.transpileString(
109+
`return "${inp}".substring(${paramStr})`,
110+
util.dummyTypes.String
111+
);
112+
113+
// Execute
114+
let result = util.executeLua(lua);
115+
116+
// Assert
117+
Expect(result).toBe(inp.substring(start, end));
118+
}
119+
}

test/src/util.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export namespace dummyTypes {
99
export const Array = { flags: ts.TypeFlags.Object, symbol: { escapedName: "Array" } };
1010
export const Object = { flags: ts.TypeFlags.Object, symbol: { escapedName: "Object" } };
1111
export const Number = { flags: ts.TypeFlags.Number, symbol: { escapedName: "Number" } };
12+
export const String = { flags: ts.TypeFlags.String, symbol: { escapedName: "String" } };
1213
}
1314

1415
export function transpileString(str: string, dummyType: any = dummyTypes.None): string {

test/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
"experimentalDecorators": true
44
},
55
"exclude": ["integration/testfiles/*"]
6-
}
6+
}

0 commit comments

Comments
 (0)