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
14 changes: 9 additions & 5 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
comment: off

coverage:
status:
patch: false
changes: false
project: false

comment: false
project:
default:
target: 95
threshold: null
base: auto
changes: off
patch: off
37 changes: 25 additions & 12 deletions src/Transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,17 @@ export abstract class LuaTranspiler {
// Transpile a block
public transpileBlock(block: ts.Block): string {
this.exportStack.push([]);
let result = block.statements.map(statement => this.transpileNode(statement)).join("");

let result = "";
for (const statement of block.statements) {
result += this.transpileNode(statement);

// Don't transpile any dead code after a return
if (ts.isReturnStatement(statement)) {
break;
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.

Please no breaks.

}
}

result += this.makeExports();

return result;
Expand Down Expand Up @@ -587,13 +597,14 @@ export abstract class LuaTranspiler {
this.pushIndent();

this.transpilingSwitch++;
clause.statements.forEach(statement => {
result += this.transpileNode(statement);
});
result += this.transpileBlock(ts.createBlock(clause.statements));
this.transpilingSwitch--;

let i = index + 1;
if (i < clauses.length && !tsHelper.containsStatement(clause.statements, ts.SyntaxKind.BreakStatement)) {
if (i < clauses.length
&& !tsHelper.containsStatement(clause.statements, ts.SyntaxKind.BreakStatement)
&& !tsHelper.containsStatement(clause.statements, ts.SyntaxKind.ReturnStatement)
) {
let nextClause = clauses[i];
while (i < clauses.length
&& ts.isCaseClause(nextClause)
Expand All @@ -605,8 +616,8 @@ export abstract class LuaTranspiler {

if (i !== index && nextClause) {
if (ts.isCaseClause(nextClause)) {
result += this.indent +
`${jumpTableName}[${this.transpileExpression(nextClause.expression, true)}]()\n`;
const nextValue = this.transpileExpression(nextClause.expression, true);
result += this.indent + `return ${jumpTableName}[${nextValue}]()\n`;
} else {
result += this.indent + `${jumpTableName}["____default${this.genVarCounter}"]()\n`;
}
Expand All @@ -619,11 +630,13 @@ export abstract class LuaTranspiler {

result += this.indent + `end\n`;
});
result += this.indent +
`if ${jumpTableName}[${expression}] then ${jumpTableName}[${expression}]()\n`;
result += this.indent +
`elseif ${jumpTableName}["____default${this.genVarCounter}"] ` +
`then ${jumpTableName}["____default${this.genVarCounter}"]() end\n`;
result += this.indent + `if ${jumpTableName}[${expression}] then\n`
+ this.indent + ` local ${jumpTableName}Return = ${jumpTableName}[${expression}]()\n`
+ this.indent + ` if ${jumpTableName}Return ~= nil then return ${jumpTableName}Return end\n`;
result += this.indent + `elseif ${jumpTableName}["____default${this.genVarCounter}"] then\n`
+ this.indent + ` local ${jumpTableName}Return = ${jumpTableName}["____default${this.genVarCounter}"]()\n`
+ this.indent + ` if ${jumpTableName}Return ~= nil then return ${jumpTableName}Return end\n`
+ this.indent + `end\n`;
result += this.indent +
"--------Switch statement end--------\n";

Expand Down
32 changes: 24 additions & 8 deletions test/unit/conditionals.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class LuaConditionalsTests {
@TestCase(0, 0)
@TestCase(1, 1)
@Test("if")
public if(inp: number, expected: number) {
public if(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let input = ${inp}
Expand All @@ -26,7 +26,7 @@ export class LuaConditionalsTests {
@TestCase(0, 0)
@TestCase(1, 1)
@Test("ifelse")
public ifelse(inp: number, expected: number) {
public ifelse(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let input = ${inp}
Expand All @@ -49,7 +49,7 @@ export class LuaConditionalsTests {
@TestCase(2, 2)
@TestCase(3, 3)
@Test("ifelseif")
public ifelseif(inp: number, expected: number) {
public ifelseif(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let input = ${inp}
Expand All @@ -75,7 +75,7 @@ export class LuaConditionalsTests {
@TestCase(2, 2)
@TestCase(3, 3)
@Test("ifelseifelse")
public ifelseifelse(inp: number, expected: number) {
public ifelseifelse(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let input = ${inp}
Expand All @@ -102,7 +102,7 @@ export class LuaConditionalsTests {
@TestCase(2, 2)
@TestCase(3, -1)
@Test("switch")
public switch(inp: number, expected: number) {
public switch(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let result = -1;
Expand Down Expand Up @@ -133,7 +133,7 @@ export class LuaConditionalsTests {
@TestCase(2, 2)
@TestCase(3, -2)
@Test("switchdefault")
public switchdefault(inp: number, expected: number) {
public switchdefault(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let result = -1;
Expand Down Expand Up @@ -170,7 +170,7 @@ export class LuaConditionalsTests {
@TestCase(5, 15)
@TestCase(7, -2)
@Test("switchfallthrough")
public switchfallthrough(inp: number, expected: number) {
public switchfallthrough(inp: number, expected: number): void {
/// Transpile
const lua = util.transpileString(
`let result = -1;
Expand Down Expand Up @@ -213,7 +213,7 @@ export class LuaConditionalsTests {
@TestCase(2, 2)
@TestCase(3, -2)
@Test("nestedSwitch")
public nestedSwitch(inp: number, expected: number) {
public nestedSwitch(inp: number, expected: number): void {
// Transpile
const lua = util.transpileString(
`let result = -1;
Expand Down Expand Up @@ -251,4 +251,20 @@ export class LuaConditionalsTests {
// Assert
Expect(result).toBe(expected);
}

@Test("If dead code after return")
public ifDeadCodeAfterReturn(): void {
const result = util.transpileAndExecute(
`if (true) { return 3; const b = 8; }`);

Expect(result).toBe(3);
}
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.

switch also use transpileblock irrc, but I think this is less important than the namespace test and probably not needed.


@Test("switch dead code after return")
public whileDeadCodeAfterReturn(): void {
const result = util.transpileAndExecute(
`switch ("abc") { case "def": return 4; let abc = 4; case "abc": return 5; let def = 6; }`);

Expect(result).toBe(5);
}
}
38 changes: 27 additions & 11 deletions test/unit/functions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as util from "../src/util";
export class FunctionTests {

@Test("Arrow Function Expression")
public arrowFunctionExpression() {
public arrowFunctionExpression(): void {
// Transpile
const lua = util.transpileString(`let add = (a, b) => a+b; return add(1,2);`);

Expand All @@ -25,7 +25,7 @@ export class FunctionTests {
@TestCase("b => a **= b", 100000)
@TestCase("b => a %= b", 0)
@Test("Arrow function assignment")
public arrowFunctionAssignment(lambda: string, expected: number) {
public arrowFunctionAssignment(lambda: string, expected: number): void {
// Transpile
const lua = util.transpileString(`let a = 10; let lambda = ${lambda};
lambda(5); return a;`);
Expand All @@ -41,7 +41,7 @@ export class FunctionTests {
@TestCase([5])
@TestCase([1, 2])
@Test("Arrow Default Values")
public arrowFunctionDefaultValues(inp: number[]) {
public arrowFunctionDefaultValues(inp: number[]): void {
// Default value is 3 for v1
const v1 = inp.length > 0 ? inp[0] : 3;
// Default value is 4 for v2
Expand All @@ -61,7 +61,7 @@ export class FunctionTests {
}

@Test("Function Expression")
public functionExpression() {
public functionExpression(): void {
// Transpile
const lua = util.transpileString(`let add = function(a, b) {return a+b}; return add(1,2);`);

Expand All @@ -76,7 +76,7 @@ export class FunctionTests {
@TestCase([5], 9)
@TestCase([1, 2], 3)
@Test("Arrow Default Values")
public functionExpressionDefaultValues(inp: number[]) {
public functionExpressionDefaultValues(inp: number[]): void {
// Default value is 3 for v1
const v1 = inp.length > 0 ? inp[0] : 3;
// Default value is 4 for v2
Expand All @@ -96,7 +96,7 @@ export class FunctionTests {
}

@Test("Class method call")
public classMethod() {
public classMethod(): void {
const returnValue = 4;
const source = `class TestClass {
public classMethod(): number { return ${returnValue}; }
Expand All @@ -116,7 +116,7 @@ export class FunctionTests {
}

@Test("Class dot method call void")
public classDotMethod() {
public classDotMethod(): void {
const returnValue = 4;
const source = `class TestClass {
public dotMethod: () => number = () => ${returnValue};
Expand All @@ -136,7 +136,7 @@ export class FunctionTests {
}

@Test("Class dot method call with parameter")
public classDotMethod2() {
public classDotMethod2(): void {
const returnValue = 4;
const source = `class TestClass {
public dotMethod: (x: number) => number = x => 3 * x;
Expand All @@ -156,7 +156,7 @@ export class FunctionTests {
}

@Test("Class static dot method")
public classDotMethodStatic() {
public classDotMethodStatic(): void {
const returnValue = 4;
const source = `class TestClass {
public static dotMethod: () => number = () => ${returnValue};
Expand All @@ -175,7 +175,7 @@ export class FunctionTests {
}

@Test("Class static dot method with parameter")
public classDotMethodStaticWithParameter() {
public classDotMethodStaticWithParameter(): void {
const returnValue = 4;
const source = `class TestClass {
public static dotMethod: (x: number) => number = x => 3 * x;
Expand All @@ -194,7 +194,7 @@ export class FunctionTests {
}

@Test("Invalid property access call transpilation")
public invalidPropertyCall() {
public invalidPropertyCall(): void {
const transpiler = util.makeTestTranspiler();

const mockObject: any = {
Expand All @@ -204,4 +204,20 @@ export class FunctionTests {
Expect(() => transpiler.transpilePropertyCall(mockObject as ts.CallExpression))
.toThrowError(Error, "Tried to transpile a non-property call as property call.");
}

@Test("Function dead code after return")
public functionDeadCodeAfterReturn(): void {
const result = util.transpileAndExecute(
`function abc() { return 3; const a = 5; } return abc();`);

Expect(result).toBe(3);
}

@Test("Method dead code after return")
public methodDeadCodeAfterReturn(): void {
const result = util.transpileAndExecute(
`class def { public static abc() { return 3; const a = 5; } } return def.abc();`);

Expect(result).toBe(3);
}
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.

namespaces also use transpire block a test would be nice.

Copy link
Copy Markdown
Member Author

@Perryvw Perryvw Jul 28, 2018

Choose a reason for hiding this comment

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

You cannot return from a namespace since it is not a function body.

}
Loading