Skip to content

Commit da29936

Browse files
authored
Merge pull request #38 from Perryvw/lualib-integration
Lualib Integration & Import path resolving
2 parents 43dd4c4 + b47578f commit da29936

File tree

6 files changed

+53
-53
lines changed

6 files changed

+53
-53
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
*.js
22
node_modules/
3-
*.lua
4-
!json.lua
5-
!dist/lualib/*.lua
63

74
coverage/
85
.nyc*

dist/lualib/lib-typescript.d.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/Compiler.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,32 @@ function compile(fileNames: string[], options: ts.CompilerOptions): void {
3434
process.exit(1);
3535
}
3636

37+
if (!options.rootDir) {
38+
options.rootDir = process.cwd();
39+
}
40+
41+
if (!options.outDir) {
42+
options.outDir = options.rootDir;
43+
}
44+
45+
// Copy lualib to target dir
46+
// This isnt run in sync because copyFileSync wont report errors.
47+
fs.copyFile(path.resolve(__dirname, "../dist/lualib/typescript.lua"), path.join(options.outDir, "typescript_lualib.lua"), (err: NodeJS.ErrnoException) => {
48+
if (err) {
49+
console.log("ERROR: copying lualib to output.");
50+
}
51+
});
52+
3753
program.getSourceFiles().forEach(sourceFile => {
3854
if (!sourceFile.isDeclarationFile) {
3955
try {
4056
let rootDir = options.rootDir;
41-
if (!rootDir) {
42-
rootDir = process.cwd();
43-
}
4457

4558
// Transpile AST
4659
let lua = LuaTranspiler.transpileSourceFile(sourceFile, checker, options);
4760

4861
let outPath = sourceFile.fileName;
49-
if (options.outDir) {
62+
if (options.outDir !== options.rootDir) {
5063
outPath = path.join(options.outDir, sourceFile.fileName.replace(rootDir, ""));
5164
}
5265

src/Transpiler.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ export class TranspileError extends Error {
1616
export class LuaTranspiler {
1717
// Transpile a source file
1818
static transpileSourceFile(node: ts.SourceFile, checker: ts.TypeChecker, options: ts.CompilerOptions): string {
19-
let transpiler = new LuaTranspiler(checker, options);
19+
let transpiler = new LuaTranspiler(checker, options, node);
2020
let header = options.addHeader ? "--=======================================================================================\n"
2121
+ "-- Generated by TypescriptToLua transpiler https://github.com/Perryvw/TypescriptToLua \n"
2222
+ "-- Date: " + new Date().toDateString() + "\n"
2323
+ "--=======================================================================================\n"
2424
: "";
25-
let result = header
26-
transpiler.isModule = tsEx.isFileModule(node);
25+
let result = header;
26+
if (!options.dontRequireLualib) {
27+
// require helper functions
28+
result += `require("typescript_lualib")\n`;
29+
}
2730
if (transpiler.isModule) {
2831
// Shadow exports if it already exists
2932
result += "local exports = exports or {}\n";
@@ -43,16 +46,18 @@ export class LuaTranspiler {
4346
namespace: string[];
4447
importCount: number;
4548
isModule: boolean;
49+
sourceFile: ts.SourceFile;
4650

47-
constructor(checker: ts.TypeChecker, options: ts.CompilerOptions) {
51+
constructor(checker: ts.TypeChecker, options: ts.CompilerOptions, sourceFile: ts.SourceFile) {
4852
this.indent = "";
4953
this.checker = checker;
5054
this.options = options;
5155
this.genVarCounter = 0;
5256
this.transpilingSwitch = false;
5357
this.namespace = [];
5458
this.importCount = 0;
55-
this.isModule = false;
59+
this.sourceFile = sourceFile;
60+
this.isModule = tsEx.isFileModule(sourceFile);
5661
}
5762

5863
pushIndent(): void {
@@ -83,6 +88,16 @@ export class LuaTranspiler {
8388
return result;
8489
}
8590

91+
getImportPath(relativePath: string) {
92+
// Calculate absolute path to import
93+
let absolutePathToImport = path.resolve(path.dirname(this.sourceFile.fileName), relativePath);
94+
if (this.options.rootDir) {
95+
// Calculate path realtive to project root and replace path.sep with dots (lua doesn't know paths)
96+
return `"${absolutePathToImport.replace(this.options.rootDir, "").replace(new RegExp("\\\\|\/", "g"), ".").slice(1)}"`;
97+
}
98+
return `"${relativePath.replace(new RegExp("\\\\|\/", "g"), ".")}"`;
99+
}
100+
86101
// Transpile a block
87102
transpileBlock(node: ts.Node): string {
88103
let result = "";
@@ -152,16 +167,17 @@ export class LuaTranspiler {
152167
}
153168

154169
transpileImport(node: ts.ImportDeclaration): string {
155-
const importFile = this.transpileExpression(node.moduleSpecifier);
170+
const importPath = this.transpileExpression(node.moduleSpecifier);
156171
if (!node.importClause || !node.importClause.namedBindings) {
157172
throw new TranspileError("Default Imports are not supported, please use named imports instead!", node);
158173
}
159174

160175
const imports = node.importClause.namedBindings;
161176

162177
if (ts.isNamedImports(imports)) {
163-
let fileImportTable = path.basename(importFile.replace(new RegExp("\"", "g"), "")) + this.importCount
164-
let result = `local ${fileImportTable} = require(${importFile})\n`
178+
let importPathWithoutQuotes = importPath.replace(new RegExp("\"", "g"), "");
179+
let fileImportTable = path.basename(importPathWithoutQuotes) + this.importCount
180+
let result = `local ${fileImportTable} = require(${this.getImportPath(importPathWithoutQuotes)})\n`
165181
this.importCount++;
166182
imports.elements.forEach(element => {
167183
if (element.propertyName) {
@@ -375,9 +391,9 @@ export class LuaTranspiler {
375391
this.transpilingSwitch = false;
376392

377393
let i = index + 1;
378-
if (i < clauses.length && !tsEx.containsStatement(clause.statements, ts.SyntaxKind.BreakStatement)) {
394+
if (i < clauses.length && !tsEx.containsStatement(clause.statements, ts.SyntaxKind.BreakStatement))  {
379395
let nextClause = clauses[i];
380-
while(i < clauses.length
396+
while (i < clauses.length
381397
&& ts.isCaseClause(nextClause)
382398
&& nextClause.statements.length === 0
383399
) {

test/src/util.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ export namespace dummyTypes {
1111
export const Number = { flags: ts.TypeFlags.Number, symbol: { escapedName: "Number" } };
1212
}
1313

14-
export function transpileString(str: string, dummyType: any): string {
14+
export function transpileString(str: string, dummyType: any = dummyTypes.None): string {
1515
const dummyChecker = { getTypeAtLocation: function() { return dummyType; } }
16-
const file = ts.createSourceFile("temp.ts", str, ts.ScriptTarget.Latest);
17-
const result = LuaTranspiler.transpileSourceFile(file, dummyChecker, false);
16+
const file = ts.createSourceFile("____internal_test_file.tstl", str, ts.ScriptTarget.Latest);
17+
const options: ts.CompilerOptions = { dontRequireLualib: true };
18+
const result = LuaTranspiler.transpileSourceFile(file, dummyChecker, options);
1819
return result.trim();
1920
}
2021

test/unit/expressions.spec.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@ import { Expect, Test, TestCase } from "alsatian";
33
import * as ts from "typescript";
44
import {LuaTranspiler, TranspileError} from "../../dist/Transpiler";
55

6-
const dummyChecker = {getTypeAtLocation: function() {return {};}}
7-
function transpileString(str: string): string {
8-
const file = ts.createSourceFile("", str, ts.ScriptTarget.Latest);
9-
const result = LuaTranspiler.transpileSourceFile(file, dummyChecker, false);
10-
return result.trim();
11-
}
6+
import * as util from "../src/util";
127

138
export class ExpressionTests {
149

@@ -20,7 +15,7 @@ export class ExpressionTests {
2015
@TestCase("-a", "-a")
2116
@Test("Unary expressions basic")
2217
public unaryBasic(input: string, lua: string) {
23-
Expect(transpileString(input)).toBe(lua);
18+
Expect(util.transpileString(input)).toBe(lua);
2419
}
2520

2621
@TestCase("1+1", "1+1")
@@ -31,7 +26,7 @@ export class ExpressionTests {
3126
@TestCase("1==1", "1==1")
3227
@Test("Binary expressions basic")
3328
public binary(input: string, lua: string) {
34-
Expect(transpileString(input)).toBe(lua);
29+
Expect(util.transpileString(input)).toBe(lua);
3530
}
3631

3732
@TestCase("a+=b", "a=a+b")
@@ -50,7 +45,7 @@ export class ExpressionTests {
5045
@TestCase("a>>>=b", "a=bit.rshift(a,b)")
5146
@Test("Binary expressions overridden operators")
5247
public binaryOperatorOverride(input: string, lua: string) {
53-
Expect(transpileString(input)).toBe(lua);
48+
Expect(util.transpileString(input)).toBe(lua);
5449
}
5550

5651
@TestCase("1+1", "1+1")
@@ -60,13 +55,13 @@ export class ExpressionTests {
6055
@TestCase("1*(3+4*2)", "1*(3+(4*2))")
6156
@Test("Binary expressions ordering parentheses")
6257
public binaryParentheses(input: string, lua: string) {
63-
Expect(transpileString(input)).toBe(lua);
58+
Expect(util.transpileString(input)).toBe(lua);
6459
}
6560

6661
@TestCase("1 + a ? 3*a : c", "TS_ITE(1+a,function() return 3*a end,function() return c end)")
6762
@TestCase("a ? b : c", "TS_ITE(a,function() return b end,function() return c end)")
6863
@Test("Ternary operator")
6964
public conditional(input: string, lua: string) {
70-
Expect(transpileString(input)).toBe(lua);
65+
Expect(util.transpileString(input)).toBe(lua);
7166
}
7267
}

0 commit comments

Comments
 (0)