Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/LuaLib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export enum LuaLibFeature {
Spread = "Spread",
StringConcat = "StringConcat",
StringEndsWith = "StringEndsWith",
StringPadEnd = "StringPadEnd",
StringPadStart = "StringPadStart",
StringReplace = "StringReplace",
StringSplit = "StringSplit",
StringStartsWith = "StringStartsWith",
Expand Down
9 changes: 9 additions & 0 deletions src/LuaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4106,6 +4106,15 @@ export class LuaTransformer {
return this.transformLuaLibFunction(LuaLibFeature.StringStartsWith, node, caller, ...params);
case "endsWith":
return this.transformLuaLibFunction(LuaLibFeature.StringEndsWith, node, caller, ...params);
case "repeat":
const math = tstl.createIdentifier("math");
const floor = tstl.createStringLiteral("floor");
const parameter = tstl.createCallExpression(tstl.createTableIndexExpression(math, floor), [params[0]]);
return this.createStringCall("rep", node, caller, parameter);
case "padStart":
return this.transformLuaLibFunction(LuaLibFeature.StringPadStart, node, caller, ...params);
case "padEnd":
return this.transformLuaLibFunction(LuaLibFeature.StringPadEnd, node, caller, ...params);
case "byte":
case "char":
case "dump":
Expand Down
18 changes: 18 additions & 0 deletions src/lualib/StringPadEnd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function __TS__StringPadEnd(this: string, maxLength: number, fillString = " "): string {
if (maxLength !== maxLength) maxLength = 0;
if (maxLength === -Infinity || maxLength === Infinity) {
// tslint:disable-next-line: no-string-throw
throw "Invalid string length";
}

if (this.length >= maxLength || fillString.length === 0) {
return this;
}

maxLength = maxLength - this.length;
if (maxLength > fillString.length) {
fillString += fillString.repeat(maxLength / fillString.length);
}

return this + fillString.slice(0, Math.floor(maxLength));
}
18 changes: 18 additions & 0 deletions src/lualib/StringPadStart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function __TS__StringPadStart(this: string, maxLength: number, fillString = " "): string {
if (maxLength !== maxLength) maxLength = 0;
if (maxLength === -Infinity || maxLength === Infinity) {
// tslint:disable-next-line: no-string-throw
throw "Invalid string length";
}

if (this.length >= maxLength || fillString.length === 0) {
return this;
}

maxLength = maxLength - this.length;
if (maxLength > fillString.length) {
fillString += fillString.repeat(maxLength / fillString.length);
}

return fillString.slice(0, Math.floor(maxLength)) + this;
}
16 changes: 5 additions & 11 deletions test/unit/numbers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,35 @@ const stringCases = ["-1", "0", "1", "1.5", "Infinity", "-Infinity"];
const restCases: any[] = [true, false, "", " ", "\t", "\n", "foo", {}];
const cases: any[] = [...numberCases, ...stringCases, ...restCases];

// TODO: Add more general utils to serialize values
const valueToString = (value: unknown) =>
value === Infinity || value === -Infinity || (typeof value === "number" && Number.isNaN(value))
? String(value)
: JSON.stringify(value);

describe("Number", () => {
test.each(cases)("constructor(%p)", value => {
const result = util.transpileAndExecute(`return Number(${valueToString(value)})`);
const result = util.transpileAndExecute(`return Number(${util.valueToString(value)})`);
expect(result).toBe(Number(value));
});

test.each(cases)("isNaN(%p)", value => {
const result = util.transpileAndExecute(`
return Number.isNaN(${valueToString(value)} as any)
return Number.isNaN(${util.valueToString(value)} as any)
`);

expect(result).toBe(Number.isNaN(value));
});

test.each(cases)("isFinite(%p)", value => {
const result = util.transpileAndExecute(`
return Number.isFinite(${valueToString(value)} as any)
return Number.isFinite(${util.valueToString(value)} as any)
`);

expect(result).toBe(Number.isFinite(value));
});
});

test.each(cases)("isNaN(%p)", value => {
const result = util.transpileAndExecute(`return isNaN(${valueToString(value)} as any)`);
const result = util.transpileAndExecute(`return isNaN(${util.valueToString(value)} as any)`);
expect(result).toBe(isNaN(value));
});

test.each(cases)("isFinite(%p)", value => {
const result = util.transpileAndExecute(`return isFinite(${valueToString(value)} as any)`);
const result = util.transpileAndExecute(`return isFinite(${util.valueToString(value)} as any)`);
expect(result).toBe(isFinite(value));
});
56 changes: 47 additions & 9 deletions test/unit/string.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ test.each([
expect(result).toBe(`${a} ${b} test ${c}`);
});

test.each([
{ input: "abcd", index: 3 },
{ input: "abcde", index: 3 },
{ input: "abcde", index: 0 },
{ input: "a", index: 0 },
])("string index (%p)", ({ input, index }) => {
const result = util.transpileAndExecute(`return "${input}"[${index}];`);

expect(result).toBe(input[index]);
});

test.each([
{ inp: "hello test", searchValue: "", replaceValue: "" },
{ inp: "hello test", searchValue: " ", replaceValue: "" },
Expand Down Expand Up @@ -290,7 +301,7 @@ test.each<{ inp: string; args: Parameters<string["startsWith"]> }>([
{ inp: "hello test", args: ["test"] },
{ inp: "hello test", args: ["test", 6] },
])("string.startsWith (%p)", ({ inp, args }) => {
const argsString = args.map(arg => JSON.stringify(arg)).join(", ");
const argsString = util.valuesToString(args);
const result = util.transpileAndExecute(`return "${inp}".startsWith(${argsString})`);

expect(result).toBe(inp.startsWith(...args));
Expand All @@ -302,19 +313,46 @@ test.each<{ inp: string; args: Parameters<string["endsWith"]> }>([
{ inp: "hello test", args: ["hello"] },
{ inp: "hello test", args: ["hello", 5] },
])("string.endsWith (%p)", ({ inp, args }) => {
const argsString = args.map(arg => JSON.stringify(arg)).join(", ");
const argsString = util.valuesToString(args);
const result = util.transpileAndExecute(`return "${inp}".endsWith(${argsString})`);

expect(result).toBe(inp.endsWith(...args));
});

test.each([
{ input: "abcd", index: 3 },
{ input: "abcde", index: 3 },
{ input: "abcde", index: 0 },
{ input: "a", index: 0 },
])("string index (%p)", ({ input, index }) => {
const result = util.transpileAndExecute(`return "${input}"[${index}];`);
{ inp: "hello test", count: 0 },
{ inp: "hello test", count: 1 },
{ inp: "hello test", count: 2 },
{ inp: "hello test", count: 1.1 },
{ inp: "hello test", count: 1.5 },
{ inp: "hello test", count: 1.9 },
])("string.repeat (%p)", ({ inp, count }) => {
const result = util.transpileAndExecute(`return "${inp}".repeat(${count})`);

expect(result).toBe(inp.repeat(count));
});

expect(result).toBe(input[index]);
const padCases = [
{ inp: "foo", maxLength: 0 },
{ inp: "foo", maxLength: 3 },
{ inp: "foo", maxLength: 5 },
{ inp: "foo", maxLength: 4, fillString: " " },
{ inp: "foo", maxLength: 10, fillString: " " },
{ inp: "foo", maxLength: 5, fillString: "1234" },
{ inp: "foo", maxLength: 5.9, fillString: "1234" },
{ inp: "foo", maxLength: NaN },
];

test.each(padCases)("string.padStart (%p)", ({ inp, maxLength, fillString }) => {
const argsString = util.valuesToString([maxLength, fillString]);
const result = util.transpileAndExecute(`return "${inp}".padStart(${argsString})`);

expect(result).toBe(inp.padStart(maxLength, fillString));
});

test.each(padCases)("string.padEnd (%p)", ({ inp, maxLength, fillString }) => {
const argsString = util.valuesToString([maxLength, fillString]);
const result = util.transpileAndExecute(`return "${inp}".padEnd(${argsString})`);

expect(result).toBe(inp.padEnd(maxLength, fillString));
});
7 changes: 7 additions & 0 deletions test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,10 @@ export function expectToBeDefined<T>(subject: T | null | undefined): subject is
expect(subject).toBeDefined();
return true; // If this was false the expect would have thrown an error
}

export const valueToString = (value: unknown) =>
value === Infinity || value === -Infinity || (typeof value === "number" && Number.isNaN(value))
? String(value)
: JSON.stringify(value);

export const valuesToString = (values: Array<unknown>) => values.map(valueToString).join(", ");