Skip to content

Commit 3193953

Browse files
committed
Outfile progress
1 parent d9a996f commit 3193953

File tree

3 files changed

+248
-12
lines changed

3 files changed

+248
-12
lines changed

src/LuaTransformer.ts

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,40 @@ export class LuaTransformer {
141141
)
142142
);
143143

144-
// return exports
145-
statements.push(tstl.createReturnStatement([this.createExportsIdentifier()]));
144+
if (this.options.outFile) {
145+
// module = module or {}
146+
statements.unshift(
147+
tstl.createAssignmentStatement(
148+
this.createModulesIdentifier(),
149+
tstl.createBinaryExpression(
150+
this.createModulesIdentifier(),
151+
tstl.createTableExpression(),
152+
tstl.SyntaxKind.OrOperator
153+
)
154+
)
155+
);
156+
157+
// module["sourceFile"] = exports
158+
statements.push(
159+
tstl.createAssignmentStatement(
160+
tstl.createTableIndexExpression(
161+
this.createModulesIdentifier(),
162+
tstl.createStringLiteral(this.getExportPath(this.currentSourceFile))
163+
),
164+
this.createExportsIdentifier()
165+
)
166+
);
167+
} else {
168+
// return exports
169+
statements.push(tstl.createReturnStatement([this.createExportsIdentifier()]));
170+
}
146171
}
147172
}
148173

174+
if (this.options.outFile) {
175+
return [tstl.createBlock([tstl.createDoStatement(statements)], node), this.luaLibFeatureSet];
176+
}
177+
149178
return [tstl.createBlock(statements, node), this.luaLibFeatureSet];
150179
}
151180

@@ -455,12 +484,20 @@ export class LuaTransformer {
455484
}
456485
}
457486

458-
protected createModuleRequire(moduleSpecifier: ts.StringLiteral, resolveModule = true): tstl.CallExpression {
487+
protected createModuleRequire(
488+
moduleSpecifier: ts.StringLiteral,
489+
resolveModule = true
490+
): tstl.CallExpression | tstl.TableIndexExpression {
459491
const modulePathString = resolveModule
460492
? this.getImportPath(moduleSpecifier.text.replace(new RegExp('"', "g"), ""), moduleSpecifier)
461493
: moduleSpecifier.text;
462494
const modulePath = tstl.createStringLiteral(modulePathString);
463-
return tstl.createCallExpression(tstl.createIdentifier("require"), [modulePath], moduleSpecifier);
495+
496+
if (this.options.outFile) {
497+
return tstl.createTableIndexExpression(this.createModulesIdentifier(), modulePath);
498+
} else {
499+
return tstl.createCallExpression(tstl.createIdentifier("require"), [modulePath], moduleSpecifier);
500+
}
464501
}
465502

466503
protected validateClassElement(element: ts.ClassElement): void {
@@ -4902,21 +4939,24 @@ export class LuaTransformer {
49024939
}
49034940
}
49044941

4905-
protected getAbsoluteImportPath(relativePath: string): string {
4942+
protected getAbsoluteImportPath(relativePath: string, directoryPath: string): string {
49064943
if (relativePath.charAt(0) !== "." && this.options.baseUrl) {
49074944
return path.resolve(this.options.baseUrl, relativePath);
49084945
}
49094946

4910-
if (this.currentSourceFile === undefined) {
4911-
throw TSTLErrors.MissingSourceFile();
4912-
}
4913-
4914-
return path.resolve(path.dirname(this.currentSourceFile.fileName), relativePath);
4947+
return path.resolve(directoryPath, relativePath);
49154948
}
49164949

49174950
protected getImportPath(relativePath: string, node: ts.Node): string {
49184951
const rootDir = this.options.rootDir ? path.resolve(this.options.rootDir) : path.resolve(".");
4919-
const absoluteImportPath = path.format(path.parse(this.getAbsoluteImportPath(relativePath)));
4952+
4953+
if (this.currentSourceFile === undefined) {
4954+
throw TSTLErrors.MissingSourceFile();
4955+
}
4956+
4957+
const absoluteImportPath = path.format(
4958+
path.parse(this.getAbsoluteImportPath(relativePath, path.dirname(this.currentSourceFile.fileName)))
4959+
);
49204960
const absoluteRootDirPath = path.format(path.parse(rootDir));
49214961
if (absoluteImportPath.includes(absoluteRootDirPath)) {
49224962
return this.formatPathToLuaPath(absoluteImportPath.replace(absoluteRootDirPath, "").slice(1));
@@ -4929,6 +4969,18 @@ export class LuaTransformer {
49294969
}
49304970
}
49314971

4972+
protected getExportPath(sourceFile: ts.SourceFile): string {
4973+
const rootDir = this.options.rootDir ? path.resolve(this.options.rootDir) : path.resolve(".");
4974+
4975+
if (this.currentSourceFile === undefined) {
4976+
throw TSTLErrors.MissingSourceFile();
4977+
}
4978+
4979+
const absolutePath = path.resolve(sourceFile.fileName.replace(/.ts$/, ""));
4980+
const absoluteRootDirPath = path.format(path.parse(rootDir));
4981+
return this.formatPathToLuaPath(absolutePath.replace(absoluteRootDirPath, "").slice(1));
4982+
}
4983+
49324984
protected formatPathToLuaPath(filePath: string): string {
49334985
filePath = filePath.replace(/\.json$/, "");
49344986
if (process.platform === "win32") {
@@ -4946,6 +4998,10 @@ export class LuaTransformer {
49464998
return tstl.createIdentifier("____exports");
49474999
}
49485000

5001+
protected createModulesIdentifier(): tstl.Identifier {
5002+
return tstl.createIdentifier("____modules");
5003+
}
5004+
49495005
protected createLocalOrExportedOrGlobalDeclaration(
49505006
lhs: tstl.Identifier | tstl.Identifier[],
49515007
rhs?: tstl.Expression | tstl.Expression[],

src/Transpile.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ export function transpile({
7878
try {
7979
const [luaAst, lualibFeatureSet] = transformer.transformSourceFile(sourceFile);
8080
if (!options.noEmit && !options.emitDeclarationOnly) {
81-
const [lua, sourceMap] = printer.print(luaAst, lualibFeatureSet, sourceFile.fileName);
81+
const [lua, sourceMap] = printer.print(
82+
luaAst,
83+
options.outFile ? undefined : lualibFeatureSet,
84+
sourceFile.fileName
85+
);
8286
updateTranspiledFile(sourceFile.fileName, { luaAst, lua, sourceMap });
8387
}
8488
} catch (err) {
@@ -140,5 +144,20 @@ export function transpile({
140144
transpiledFiles = [];
141145
}
142146

147+
if (options.outFile) {
148+
const lua = transpiledFiles.reduce((luaCode, transpiledFile) => {
149+
if (transpiledFile.luaAst && transpiledFile.lua) {
150+
luaCode += transpiledFile.lua;
151+
}
152+
return luaCode;
153+
}, "");
154+
transpiledFiles = [
155+
{
156+
fileName: options.outFile,
157+
lua,
158+
},
159+
];
160+
}
161+
143162
return { diagnostics, transpiledFiles };
144163
}

test/unit/outFile.spec.ts

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import * as util from "../util";
2+
import * as ts from "typescript";
3+
4+
const exportValueSource = `
5+
export const value = true;
6+
`;
7+
8+
const reexportValueSource = `
9+
export { value } from "./export";
10+
`;
11+
12+
test.each<[string, { [key: string]: string }]>([
13+
[
14+
"Import module -> main",
15+
{
16+
"main.ts": `
17+
import { value } from "./module";
18+
if (value !== true) {
19+
throw "Failed to import x";
20+
}
21+
`,
22+
"module.ts": exportValueSource,
23+
},
24+
],
25+
[
26+
"Import chain export -> reexport -> main",
27+
{
28+
"main.ts": `
29+
import { value } from "./reexport";
30+
if (value !== true) {
31+
throw "Failed to import value";
32+
}
33+
`,
34+
"reexport.ts": reexportValueSource,
35+
"export.ts": exportValueSource,
36+
},
37+
],
38+
[
39+
"Import chain with a different order",
40+
{
41+
"main.ts": `
42+
import { value } from "./reexport";
43+
if (value !== true) {
44+
throw "Failed to import value";
45+
}
46+
`,
47+
"export.ts": exportValueSource,
48+
"reexport.ts": reexportValueSource,
49+
},
50+
],
51+
[
52+
"Import diamond export -> reexport1 & reexport2 -> main",
53+
{
54+
"main.ts": `
55+
import { value as a } from "./reexport1";
56+
import { value as b } from "./reexport2";
57+
if (a !== true || b !== true) {
58+
throw "Failed to import a or b";
59+
}
60+
`,
61+
"export.ts": exportValueSource,
62+
"reexport1.ts": reexportValueSource,
63+
"reexport2.ts": reexportValueSource,
64+
},
65+
],
66+
[
67+
"Import diamond different order",
68+
{
69+
"reexport1.ts": reexportValueSource,
70+
"reexport2.ts": reexportValueSource,
71+
"export.ts": exportValueSource,
72+
"main.ts": `
73+
import { value as a } from "./reexport1";
74+
import { value as b } from "./reexport2";
75+
if (a !== true || b !== true) {
76+
throw "Failed to import a or b";
77+
}
78+
`,
79+
},
80+
],
81+
[
82+
"Modules in directories",
83+
{
84+
"main.ts": `
85+
import { value } from "./module/module";
86+
if (value !== true) {
87+
throw "Failed to import value";
88+
}
89+
`,
90+
"module/module.ts": `
91+
export const value = true;
92+
`,
93+
},
94+
],
95+
[
96+
"Modules aren't ordered by name",
97+
{
98+
"main.ts": `
99+
import { value } from "./a";
100+
if (value !== true) {
101+
throw "Failed to import value";
102+
}
103+
`,
104+
"a.ts": `
105+
export const value = true;
106+
`,
107+
},
108+
],
109+
[
110+
"Modules in directories",
111+
{
112+
"main/main.ts": `
113+
import { value } from "../module";
114+
if (value !== true) {
115+
throw "Failed to import value";
116+
}
117+
`,
118+
"module.ts": `
119+
export const value = true;
120+
`,
121+
},
122+
],
123+
[
124+
"Modules with the same name",
125+
{
126+
"main.ts": `
127+
import { value as libValue } from "./module/main";
128+
export const value = false;
129+
if (libValue !== true) {
130+
throw "Failed to import value";
131+
}
132+
`,
133+
"module/main.ts": `
134+
export const value = true;
135+
`,
136+
},
137+
],
138+
// [
139+
// "LuaLibs are usable",
140+
// {
141+
// "main.ts": `
142+
// const array = [1, 2, 3];
143+
// let total = 0;
144+
// array.forEach(num => {
145+
// total += num;
146+
// );
147+
// if (total !== 5) {
148+
// throw "Failed to use LuaLib";
149+
// }
150+
// `,
151+
// },
152+
// ],
153+
])("outFile tests (%s)", (_, files) => {
154+
const result = util.transpileString(files, { outFile: "main.lua", module: ts.ModuleKind.AMD }, false);
155+
try {
156+
util.executeLua(result);
157+
} catch {
158+
console.log(result);
159+
}
160+
expect(() => util.executeLua(result)).not.toThrow();
161+
});

0 commit comments

Comments
 (0)