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
2 changes: 1 addition & 1 deletion src/Compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function compileFilesWithOptions(fileNames: string[], options: CompilerOp
});

// Copy lualib to target dir
if (options.luaLibImport === LuaLibImportKind.Require) {
if (options.luaLibImport === LuaLibImportKind.Require || options.luaLibImport === LuaLibImportKind.Always) {
fs.copyFileSync(
path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"),
path.join(options.outDir, "lualib_bundle.lua")
Expand Down
50 changes: 40 additions & 10 deletions src/Transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ export enum LuaLibFeature {
}

export enum LuaLibImportKind {
None = "none",
Always = "always",
Inline = "inline",
Require = "require",
None = "none",
}

interface ExportInfo {
Expand Down Expand Up @@ -140,6 +141,11 @@ export abstract class LuaTranspiler {
}

public importLuaLibFeature(feature: LuaLibFeature): void {
// Add additional lib requirements
if (feature === LuaLibFeature.Map || feature === LuaLibFeature.Set) {
this.luaLibFeatureSet.add(LuaLibFeature.InstanceOf);
}

// TODO inline imported features in output i option set
this.luaLibFeatureSet.add(feature);
}
Expand Down Expand Up @@ -177,18 +183,17 @@ export abstract class LuaTranspiler {
"-- https://github.com/Perryvw/TypescriptToLua\n";
}
let result = header;
if (this.options.luaLibImport === LuaLibImportKind.Require) {

// Transpile content first to gather some info on dependencies
let fileStatements = "";
this.exportStack.push([]);
this.sourceFile.statements.forEach(s => fileStatements += this.transpileNode(s));

if ((this.options.luaLibImport === LuaLibImportKind.Require && this.luaLibFeatureSet.size > 0)
|| this.options.luaLibImport === LuaLibImportKind.Always) {
// require helper functions
result += `require("lualib_bundle")\n`;
}
if (this.isModule) {
// Shadow exports if it already exists
result += "local exports = exports or {}\n";
}

// Transpile content statements
this.exportStack.push([]);
this.sourceFile.statements.forEach(s => result += this.transpileNode(s));

// Inline lualib features
if (this.options.luaLibImport === LuaLibImportKind.Inline) {
Expand All @@ -199,6 +204,14 @@ export abstract class LuaTranspiler {
}
}

if (this.isModule) {
// Shadow exports if it already exists
result += "local exports = exports or {}\n";
}

// Add file systems after imports since order matters in Lua
result += fileStatements;

// Exports
result += this.makeExports();

Expand Down Expand Up @@ -935,6 +948,8 @@ export abstract class LuaTranspiler {
const name = this.transpileExpression(node.expression);
const params = node.arguments ? this.transpileArguments(node.arguments, ts.createTrue()) : "true";

this.checkForLuaLibType(this.checker.getTypeAtLocation(node));

return `${name}.new(${params})`;
}

Expand Down Expand Up @@ -1146,6 +1161,8 @@ export abstract class LuaTranspiler {
}
}

this.checkForLuaLibType(type);

// Do not output path for member only enums
if (tsHelper.isCompileMembersOnlyEnum(type, this.checker)) {
return property;
Expand Down Expand Up @@ -1673,4 +1690,17 @@ export abstract class LuaTranspiler {

return result;
}

public checkForLuaLibType(type: ts.Type): void {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming of this function seems a bit of to me. As it checks for the time, but also adds the feature.

if (type.symbol) {
switch (this.checker.getFullyQualifiedName(type.symbol)) {
case "Map":
this.importLuaLibFeature(LuaLibFeature.Map);
return;
case "Set":
this.importLuaLibFeature(LuaLibFeature.Set);
return;
}
}
}
}
21 changes: 18 additions & 3 deletions test/runner.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { TestRunner, TestSet } from "alsatian";
import { TapBark } from "tap-bark";

import * as fs from "fs";
import * as path from "path";

// create test set
const testSet = TestSet.create();

Expand All @@ -10,6 +13,12 @@ testSet.addTestsFromFiles("./test/**/*.spec.ts");
// create a test runner
const testRunner = new TestRunner();

// Copy lualib to project root
fs.copyFileSync(
path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"),
"lualib_bundle.lua"
);

// setup the output
testRunner.outputStream
// this will use alsatian's default output if you remove this
Expand All @@ -19,8 +28,14 @@ testRunner.outputStream
.pipe(process.stdout);

// run the test set
testRunner.run(testSet);
testRunner.run(testSet)
// this will be called after all tests have been run
// .then((results) => done())
.then(result => {
// Remove lualib bundle again
fs.unlinkSync("lualib_bundle.lua");
})
// this will be called if there was a problem
// .catch((error) => doSomethingWith(error));
.catch(error => {
// Remove lualib bundle again
fs.unlinkSync("lualib_bundle.lua");
});
8 changes: 3 additions & 5 deletions test/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { Expect } from "alsatian";

import { CompilerOptions } from "../../src/CommandLineParser";
import { createTranspiler } from "../../src/Compiler";
import { LuaTarget, LuaTranspiler, TranspileError } from "../../src/Transpiler";
import { LuaLibImportKind, LuaTarget, LuaTranspiler, TranspileError } from "../../src/Transpiler";

import {lauxlib, lua, lualib, to_jsstring, to_luastring } from "fengari";

const fs = require("fs");

const libSource = fs.readFileSync(path.join(path.dirname(require.resolve("typescript")), "lib.es6.d.ts")).toString();

export function transpileString(str: string, options: CompilerOptions = { luaLibImport: "none", luaTarget: LuaTarget.Lua53 }): string {
export function transpileString(str: string, options: CompilerOptions = { luaLibImport: LuaLibImportKind.Require, luaTarget: LuaTarget.Lua53 }): string {
const compilerHost = {
directoryExists: () => true,
fileExists: (fileName): boolean => true,
Expand Down Expand Up @@ -114,8 +114,6 @@ export function transpileAndExecute(ts: string): any {
return executeLua(transpileString(ts));
}

const tslualib = fs.readFileSync("dist/lualib/lualib_bundle.lua") + "\n";

const jsonlib = fs.readFileSync("test/src/json.lua") + "\n";

export const minimalTestLib = tslualib + jsonlib;
export const minimalTestLib = jsonlib;
50 changes: 50 additions & 0 deletions test/unit/lualib/inlining.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Expect, Test, TestCase } from "alsatian";
import * as util from "../../src/util";

import { LuaLibImportKind, LuaTarget } from "../../../src/Transpiler";

export class InliningTests {
@Test("map constructor")
public mapConstructor(): void {
const lua = util.transpileString(`let mymap = new Map(); return mymap.size;`,
{ luaLibImport: LuaLibImportKind.Inline, luaTarget: LuaTarget.Lua53 });
const result = util.executeLua(lua);

Expect(result).toBe(0);
}

@Test("map foreach keys")
public mapForEachKeys(): void {
const lua = util.transpileString(
`let mymap = new Map([[5, 2],[6, 3],[7, 4]]);
let count = 0;
mymap.forEach((value, key) => { count += key; });
return count;`,
{ luaLibImport: LuaLibImportKind.Inline, luaTarget: LuaTarget.Lua53 });

const result = util.executeLua(lua);
Expect(result).toBe(18);
}

@Test("set constructor")
public setConstructor(): void {
const lua = util.transpileString(`class abc {} let def = new abc(); let myset = new Set(); return myset.size;`,
{ luaLibImport: LuaLibImportKind.Inline, luaTarget: LuaTarget.Lua53 });
const result = util.executeLua(lua);

Expect(result).toBe(0);
}

@Test("set foreach keys")
public setForEachKeys(): void {
const lua = util.transpileString(
`let myset = new Set([2, 3, 4]);
let count = 0;
myset.forEach((value, key) => { count += key; });
return count;`,
{ luaLibImport: LuaLibImportKind.Inline, luaTarget: LuaTarget.Lua53 });

const result = util.executeLua(lua);
Expect(result).toBe(9);
}
}
34 changes: 17 additions & 17 deletions test/unit/lualib/map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import * as util from "../../src/util";

export class MapTests {
@Test("map constructor")
public mapConstructor() {
public mapConstructor(): void {
const lua = util.transpileString(`let mymap = new Map(); return mymap.size;`);
const result = util.executeLua(lua);

Expect(result).toBe(0);
}

@Test("map iterable constructor")
public mapIterableConstructor() {
public mapIterableConstructor(): void {
const lua = util.transpileString(`let mymap = new Map([["a", "c"],["b", "d"]]);
return mymap.has("a") && mymap.has("b");`);
const result = util.executeLua(lua);
Expand All @@ -20,7 +20,7 @@ export class MapTests {
}

@Test("map iterable constructor map")
public mapIterableConstructor2() {
public mapIterableConstructor2(): void {
const lua = util.transpileString(`let mymap = new Map(new Map([["a", "c"],["b", "d"]]));
return mymap.has("a") && mymap.has("b");`);
const result = util.executeLua(lua);
Expand All @@ -29,7 +29,7 @@ export class MapTests {
}

@Test("map clear")
public mapClear() {
public mapClear(): void {
const mapTS = `let mymap = new Map([["a", "c"],["b", "d"]]); mymap.clear();`;
const lua = util.transpileString(mapTS + `return mymap.size;`);
const size = util.executeLua(lua);
Expand All @@ -41,15 +41,15 @@ export class MapTests {
}

@Test("map delete")
public mapDelete() {
public mapDelete(): void {
const mapTS = `let mymap = new Map([["a", "c"],["b", "d"]]); mymap.delete("a");`;
const lua = util.transpileString(mapTS + `return mymap.has("b") && !mymap.has("a");`);
const contains = util.executeLua(lua);
Expect(contains).toBe(true);
}

@Test("map entries")
public mapEntries() {
public mapEntries(): void {
const lua = util.transpileString(`let mymap = new Map([[5, 2],[6, 3],[7, 4]]);
let count = 0;
for (var [key, value] of mymap.entries()) { count += key + value; }
Expand All @@ -59,7 +59,7 @@ export class MapTests {
}

@Test("map foreach")
public mapForEach() {
public mapForEach(): void {
const lua = util.transpileString(
`let mymap = new Map([["a", 2],["b", 3],["c", 4]]);
let count = 0;
Expand All @@ -72,7 +72,7 @@ export class MapTests {
}

@Test("map foreach keys")
public mapForEachKeys() {
public mapForEachKeys(): void {
const lua = util.transpileString(
`let mymap = new Map([[5, 2],[6, 3],[7, 4]]);
let count = 0;
Expand All @@ -85,42 +85,42 @@ export class MapTests {
}

@Test("map get")
public mapGet() {
public mapGet(): void {
const lua = util.transpileString(`let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("a");`);
const result = util.executeLua(lua);
Expect(result).toBe("c");
}

@Test("map get missing")
public mapGetMissing() {
public mapGetMissing(): void {
const lua = util.transpileString(`let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("c");`);
const result = util.executeLua(lua);
Expect(result).toBe(null);
}

@Test("map has")
public mapHas() {
public mapHas(): void {
const lua = util.transpileString(`let mymap = new Map([["a", "c"]]); return mymap.has("a");`);
const contains = util.executeLua(lua);
Expect(contains).toBe(true);
}

@Test("map has false")
public mapHasFalse() {
public mapHasFalse(): void {
const lua = util.transpileString(`let mymap = new Map(); return mymap.has("a");`);
const contains = util.executeLua(lua);
Expect(contains).toBe(false);
}

@Test("map has null")
public mapHasNull() {
public mapHasNull(): void {
const lua = util.transpileString(`let mymap = new Map([["a", "c"]]); return mymap.has(null);`);
const contains = util.executeLua(lua);
Expect(contains).toBe(false);
}

@Test("map keys")
public mapKeys() {
public mapKeys(): void {
const lua = util.transpileString(`let mymap = new Map([[5, 2],[6, 3],[7, 4]]);
let count = 0;
for (var key of mymap.keys()) { count += key; }
Expand All @@ -130,7 +130,7 @@ export class MapTests {
}

@Test("map set")
public mapSet() {
public mapSet(): void {
const mapTS = `let mymap = new Map(); mymap.set("a", 5);`;
const lua = util.transpileString(mapTS + `return mymap.has("a");`);
const has = util.executeLua(lua);
Expand All @@ -142,7 +142,7 @@ export class MapTests {
}

@Test("map values")
public mapValues() {
public mapValues(): void {
const lua = util.transpileString(`let mymap = new Map([[5, 2],[6, 3],[7, 4]]);
let count = 0;
for (var value of mymap.values()) { count += value; }
Expand All @@ -152,7 +152,7 @@ export class MapTests {
}

@Test("map size")
public mapSize() {
public mapSize(): void {
Expect(util.transpileAndExecute(`let m = new Map(); return m.size;`)).toBe(0);
Expect(util.transpileAndExecute(`let m = new Map(); m.set(1,3); return m.size;`)).toBe(1);
Expect(util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); return m.size;`)).toBe(2);
Expand Down
Loading