Skip to content

Commit 4910922

Browse files
authored
Module resolution should ignore functions that look like requires but are not (#1066)
* Module resolution should ignore functions that look like requires but are not * fix prettier * Escape special characters in require regex
1 parent d470199 commit 4910922

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/transpilation/resolve.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,19 +274,26 @@ function isBuildModeLibrary(program: ts.Program) {
274274
function findRequiredPaths(code: string): string[] {
275275
// Find all require("<path>") paths in a lua code string
276276
const paths: string[] = [];
277-
const pattern = /require\("(.+)"\)/g;
277+
const pattern = /(^|\s|;|=)require\("(.+)"\)/g;
278278
// eslint-disable-next-line @typescript-eslint/ban-types
279279
let match: RegExpExecArray | null;
280280
while ((match = pattern.exec(code))) {
281-
paths.push(match[1]);
281+
paths.push(match[2]);
282282
}
283283

284284
return paths;
285285
}
286286

287287
function replaceRequireInCode(file: ProcessedFile, originalRequire: string, newRequire: string): void {
288288
const requirePath = formatPathToLuaPath(newRequire.replace(".lua", ""));
289-
file.code = file.code.replace(`require("${originalRequire}")`, `require("${requirePath}")`);
289+
290+
// Escape special characters to prevent the regex from breaking...
291+
const escapedRequire = originalRequire.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
292+
293+
file.code = file.code.replace(
294+
new RegExp(`(^|\\s|;|=)require\\("${escapedRequire}"\\)`),
295+
`$1require("${requirePath}")`
296+
);
290297
}
291298

292299
function replaceRequireInSourceMap(file: ProcessedFile, originalRequire: string, newRequire: string): void {

test/transpile/module-resolution.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ test("module resolution should not try to resolve @noResolution annotation", ()
329329
.expectToHaveNoDiagnostics();
330330
});
331331

332+
// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1062
332333
test("module resolution should not rewrite @NoResolution requires in library mode", () => {
333334
const { transpiledFiles } = util.testModule`
334335
import * as json from "json";
@@ -351,6 +352,40 @@ test("module resolution should not rewrite @NoResolution requires in library mod
351352
expect(transpiledFiles[0].lua).toContain('require("@NoResolution:');
352353
});
353354

355+
// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1050
356+
test("module resolution should not try to resolve resolve-like functions", () => {
357+
util.testModule`
358+
function custom_require(this: void, value: string) {
359+
return value;
360+
}
361+
362+
namespace ns {
363+
export function require(this: void, value: string) {
364+
return value;
365+
}
366+
}
367+
368+
class MyClass {
369+
require(value: string) {
370+
return value;
371+
}
372+
}
373+
const inst = new MyClass();
374+
375+
export const result = [
376+
custom_require("value 1"),
377+
ns.require("value 2"),
378+
inst.require("value 3")
379+
];
380+
381+
`
382+
.expectToHaveNoDiagnostics()
383+
.expectToEqual({
384+
result: ["value 1", "value 2", "value 3"],
385+
});
386+
});
387+
388+
// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1050
354389
test("module resolution uses baseURL to resolve imported files", () => {
355390
util.testModule`
356391
import { foo } from "dep1";

0 commit comments

Comments
 (0)