Skip to content

Commit cb2c479

Browse files
ark120202Perryvw
authored andcommitted
Improve string.replace implementation (#549)
1 parent 5d4ed09 commit cb2c479

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/lualib/StringReplace.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1-
function __TS__StringReplace(this: void, source: string, searchValue: string, replaceValue: string): string {
2-
return string.gsub(source, searchValue, replaceValue)[0];
1+
function __TS__StringReplace(
2+
this: void,
3+
source: string,
4+
searchValue: string,
5+
replaceValue: string | ((substring: string) => string)
6+
): string {
7+
[searchValue] = string.gsub(searchValue, "[%%%(%)%.%+%-%*%?%[%^%$]", "%%%1");
8+
9+
if (typeof replaceValue === "string") {
10+
[replaceValue] = string.gsub(replaceValue, "[%%%(%)%.%+%-%*%?%[%^%$]", "%%%1");
11+
const [result] = string.gsub(source, searchValue, replaceValue, 1);
12+
return result;
13+
} else {
14+
const [result] = string.gsub(
15+
source,
16+
searchValue,
17+
match => (replaceValue as (substring: string) => string)(match),
18+
1
19+
);
20+
return result;
21+
}
322
}
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
/** @luaIterator */
2-
interface GMatchResult extends Array<string> { }
2+
interface GMatchResult extends Array<string> {}
33

44
/** @noSelf */
55
declare namespace string {
66
/** @tupleReturn */
7-
function gsub(source: string, searchValue: string, replaceValue: string): [string, number];
8-
/** @tupleReturn */
9-
function gsub(source: string, searchValue: string, replaceValue: (...groups: string[]) => string): [string, number];
7+
function gsub(
8+
source: string,
9+
searchValue: string,
10+
replaceValue: string | ((...groups: string[]) => string),
11+
n?: number
12+
): [string, number];
1013

1114
function gmatch(haystack: string, pattern: string): GMatchResult;
1215
}

test/unit/string.spec.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,25 @@ test.each([
7979
{ inp: "hello test", searchValue: "hello", replaceValue: "" },
8080
{ inp: "hello test", searchValue: "test", replaceValue: "" },
8181
{ inp: "hello test", searchValue: "test", replaceValue: "world" },
82+
{ inp: "hello test", searchValue: "test", replaceValue: "%world" },
83+
{ inp: "hello %test", searchValue: "test", replaceValue: "world" },
84+
{ inp: "hello %test", searchValue: "%test", replaceValue: "world" },
85+
{ inp: "hello test", searchValue: "test", replaceValue: (): string => "a" },
86+
{ inp: "hello test", searchValue: "test", replaceValue: (): string => "%a" },
87+
{ inp: "aaa", searchValue: "a", replaceValue: "b" },
8288
])("string.replace (%p)", ({ inp, searchValue, replaceValue }) => {
89+
const replaceValueString =
90+
typeof replaceValue === "string" ? JSON.stringify(replaceValue) : replaceValue.toString();
8391
const result = util.transpileAndExecute(
84-
`return "${inp}".replace("${searchValue}", "${replaceValue}");`,
92+
`return "${inp}".replace("${searchValue}", ${replaceValueString});`,
8593
);
8694

87-
expect(result).toBe(inp.replace(searchValue, replaceValue));
95+
// https://github.com/Microsoft/TypeScript/issues/22378
96+
if (typeof replaceValue === "string") {
97+
expect(result).toBe(inp.replace(searchValue, replaceValue));
98+
} else {
99+
expect(result).toBe(inp.replace(searchValue, replaceValue));
100+
}
88101
});
89102

90103
test.each([

0 commit comments

Comments
 (0)