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
6 changes: 3 additions & 3 deletions src/transpilation/output-collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface TranspiledFile {
jsSourceMap?: string;
}

export function createEmitOutputCollector() {
export function createEmitOutputCollector(luaExtension = ".lua") {
const files: TranspiledFile[] = [];
const writeFile: ts.WriteFileCallback = (fileName, data, _bom, _onError, sourceFiles = []) => {
let file = files.find(f => intersection(f.sourceFiles, sourceFiles).length > 0);
Expand All @@ -25,9 +25,9 @@ export function createEmitOutputCollector() {
file.sourceFiles = union(file.sourceFiles, sourceFiles);
}

if (fileName.endsWith(".lua")) {
if (fileName.endsWith(luaExtension)) {
file.lua = data;
} else if (fileName.endsWith(".lua.map")) {
} else if (fileName.endsWith(`${luaExtension}.map`)) {
file.luaSourceMap = data;
} else if (fileName.endsWith(".js")) {
file.js = data;
Expand Down
38 changes: 28 additions & 10 deletions src/transpilation/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class ResolutionContext {
// Remove @NoResolution prefix if not building in library mode
if (!isBuildModeLibrary(this.program)) {
const path = required.requirePath.replace("@NoResolution:", "");
replaceRequireInCode(file, required, path);
replaceRequireInSourceMap(file, required, path);
replaceRequireInCode(file, required, path, this.options.extension);
replaceRequireInSourceMap(file, required, path, this.options.extension);
}

// Skip
Expand Down Expand Up @@ -88,8 +88,8 @@ class ResolutionContext {
// Figure out resolved require path and dependency output path
if (shouldRewriteRequires(dependencyPath, this.program)) {
const resolvedRequire = getEmitPathRelativeToOutDir(dependencyPath, this.program);
replaceRequireInCode(file, required, resolvedRequire);
replaceRequireInSourceMap(file, required, resolvedRequire);
replaceRequireInCode(file, required, resolvedRequire, this.options.extension);
replaceRequireInSourceMap(file, required, resolvedRequire, this.options.extension);
}
}

Expand Down Expand Up @@ -117,8 +117,8 @@ class ResolutionContext {

private couldNotResolveImport(required: LuaRequire, file: ProcessedFile): void {
const fallbackRequire = fallbackResolve(required, getSourceDir(this.program), path.dirname(file.fileName));
replaceRequireInCode(file, required, fallbackRequire);
replaceRequireInSourceMap(file, required, fallbackRequire);
replaceRequireInCode(file, required, fallbackRequire, this.options.extension);
replaceRequireInSourceMap(file, required, fallbackRequire, this.options.extension);

this.diagnostics.push(
couldNotResolveRequire(required.requirePath, path.relative(getProjectRoot(this.program), file.fileName))
Expand Down Expand Up @@ -310,16 +310,26 @@ function isBuildModeLibrary(program: ts.Program) {
return program.getCompilerOptions().buildMode === BuildMode.Library;
}

function replaceRequireInCode(file: ProcessedFile, originalRequire: LuaRequire, newRequire: string): void {
const requirePath = formatPathToLuaPath(newRequire.replace(".lua", ""));
function replaceRequireInCode(
file: ProcessedFile,
originalRequire: LuaRequire,
newRequire: string,
extension: string | undefined
): void {
const requirePath = requirePathForFile(newRequire, extension);
file.code = file.code =
file.code.substring(0, originalRequire.from) +
`require("${requirePath}")` +
file.code.substring(originalRequire.to + 1);
}

function replaceRequireInSourceMap(file: ProcessedFile, originalRequire: LuaRequire, newRequire: string): void {
const requirePath = formatPathToLuaPath(newRequire.replace(".lua", ""));
function replaceRequireInSourceMap(
file: ProcessedFile,
originalRequire: LuaRequire,
newRequire: string,
extension?: string | undefined
): void {
const requirePath = requirePathForFile(newRequire, extension);
if (file.sourceMapNode) {
replaceInSourceMap(
file.sourceMapNode,
Expand All @@ -330,6 +340,14 @@ function replaceRequireInSourceMap(file: ProcessedFile, originalRequire: LuaRequ
}
}

function requirePathForFile(filePath: string, extension = ".lua"): string {
if (filePath.endsWith(extension)) {
return formatPathToLuaPath(filePath.substring(0, filePath.length - extension.length));
} else {
return formatPathToLuaPath(filePath);
}
}

function replaceInSourceMap(node: SourceNode, parent: SourceNode, require: string, resolvedRequire: string): boolean {
if ((!node.children || node.children.length === 0) && node.toString() === require) {
parent.children = [new SourceNode(node.line, node.column, node.source, [resolvedRequire])];
Expand Down
8 changes: 8 additions & 0 deletions test/transpile/module-resolution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ describe("module resolution with sourceDir", () => {
.setOptions({ luaBundle: "bundle.lua", luaBundleEntry: mainFile })
.expectToEqual(expectedResult);
});

// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1394
test("can resolve files with non-standard extension (#1394)", () => {
util.testProject(path.join(projectPath, "tsconfig.json"))
.setMainFileName(path.join(projectPath, "src", "main.ts"))
.setOptions({ outDir: "tstl-out", extension: ".script" })
.expectToEqual(expectedResult);
});
});

describe("module resolution project with lua sources", () => {
Expand Down
11 changes: 7 additions & 4 deletions test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export abstract class TestBuilder {
public getLuaResult(): tstl.TranspileVirtualProjectResult {
const program = this.getProgram();
const preEmitDiagnostics = ts.getPreEmitDiagnostics(program);
const collector = createEmitOutputCollector();
const collector = createEmitOutputCollector(this.options.extension);
const { diagnostics: transpileDiagnostics } = new tstl.Transpiler({ emitHost: this.getEmitHost() }).emit({
program,
customTransformers: this.customTransformers,
Expand Down Expand Up @@ -277,7 +277,7 @@ export abstract class TestBuilder {
const program = this.getProgram();
program.getCompilerOptions().module = ts.ModuleKind.CommonJS;

const collector = createEmitOutputCollector();
const collector = createEmitOutputCollector(this.options.extension);
const { diagnostics } = program.emit(undefined, collector.writeFile);
return { transpiledFiles: collector.files, diagnostics: [...diagnostics] };
}
Expand Down Expand Up @@ -468,7 +468,10 @@ end)());`;
}

private injectLuaFile(state: LuaState, lua: Lua, lauxlib: LauxLib, fileName: string, fileContent: string) {
const modName = formatPathToLuaPath(fileName.replace(".lua", ""));
const extension = this.options.extension ?? ".lua";
const modName = fileName.endsWith(extension)
? formatPathToLuaPath(fileName.substring(0, fileName.length - extension.length))
: fileName;
if (this.options.luaTarget === tstl.LuaTarget.Lua50) {
// Adding source Lua to the _LOADED cache will allow require to find it
lua.lua_getglobal(state, "_LOADED");
Expand Down Expand Up @@ -610,7 +613,7 @@ class ProjectTestBuilder extends ModuleTestBuilder {
@memoize
public getLuaResult(): tstl.TranspileVirtualProjectResult {
// Override getLuaResult to use transpileProject with tsconfig.json instead
const collector = createEmitOutputCollector();
const collector = createEmitOutputCollector(this.options.extension);
const { diagnostics } = transpileProject(this.tsConfig, this.options, collector.writeFile);

return { diagnostics: [...diagnostics], transpiledFiles: collector.files };
Expand Down