diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 7676bf2ff..88f9c3aa4 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3138,6 +3138,10 @@ export class LuaTransformer { return this.transformObjectCallExpression(node); } + if (ownerType.symbol && ownerType.symbol.escapedName === "Console") { + return this.transformConsoleCallExpression(node); + } + if (ownerType.symbol && ownerType.symbol.escapedName === "SymbolConstructor") { return this.transformSymbolCallExpression(node); } @@ -3666,6 +3670,97 @@ export class LuaTransformer { } } + public transformConsoleCallExpression(expression: ts.CallExpression): ExpressionVisitResult { + const method = expression.expression as ts.PropertyAccessExpression; + const methodName = method.name.escapedText; + + switch (methodName) { + case "log": + if (expression.arguments.length > 0 + && this.isStringFormatTemplate(expression.arguments[0])) { + // print(string.format([arguments])) + const stringFormatCall = tstl.createCallExpression( + tstl.createTableIndexExpression( + tstl.createIdentifier("string"), + tstl.createStringLiteral("format")), + this.transformArguments(expression.arguments) + ); + return tstl.createCallExpression( + tstl.createIdentifier("print"), + [stringFormatCall] + ); + } + // print([arguments]) + return tstl.createCallExpression( + tstl.createIdentifier("print"), + this.transformArguments(expression.arguments) + ); + case "assert": + const args = this.transformArguments(expression.arguments); + if (expression.arguments.length > 1 + && this.isStringFormatTemplate(expression.arguments[1])) { + // assert([condition], string.format([arguments])) + const stringFormatCall = tstl.createCallExpression( + tstl.createTableIndexExpression( + tstl.createIdentifier("string"), + tstl.createStringLiteral("format")), + args.slice(1) + ); + return tstl.createCallExpression( + tstl.createIdentifier("assert"), + [args[0], stringFormatCall] + ); + } + // assert() + return tstl.createCallExpression( + tstl.createIdentifier("assert"), + args + ); + case "trace": + if (expression.arguments.length > 0 + && this.isStringFormatTemplate(expression.arguments[0])) { + // print(debug.traceback(string.format([arguments]))) + const stringFormatCall = tstl.createCallExpression( + tstl.createTableIndexExpression( + tstl.createIdentifier("string"), + tstl.createStringLiteral("format")), + this.transformArguments(expression.arguments) + ); + const debugTracebackCall = tstl.createCallExpression( + tstl.createTableIndexExpression( + tstl.createIdentifier("debug"), + tstl.createStringLiteral("traceback")), + [stringFormatCall] + ); + return tstl.createCallExpression( + tstl.createIdentifier("print"), + [debugTracebackCall] + ); + } + // print(debug.traceback([arguments]))) + const debugTracebackCall = tstl.createCallExpression( + tstl.createTableIndexExpression( + tstl.createIdentifier("debug"), + tstl.createStringLiteral("traceback")), + this.transformArguments(expression.arguments) + ); + return tstl.createCallExpression( + tstl.createIdentifier("print"), + [debugTracebackCall] + ); + default: + throw TSTLErrors.UnsupportedForTarget( + `console property ${methodName}`, + this.options.luaTarget, + expression + ); + } + } + + private isStringFormatTemplate(expression: ts.Expression): boolean { + return ts.isStringLiteral(expression) && expression.text.match(/\%/g) !== null; + } + // Transpile a Symbol._ property public transformSymbolCallExpression(expression: ts.CallExpression): tstl.CallExpression { const method = expression.expression as ts.PropertyAccessExpression; diff --git a/test/unit/console.spec.ts b/test/unit/console.spec.ts new file mode 100644 index 000000000..b7d0a689e --- /dev/null +++ b/test/unit/console.spec.ts @@ -0,0 +1,48 @@ +import { Expect, Test, TestCase, IgnoreTest, FocusTest } from "alsatian"; +import * as util from "../src/util"; + +export class ConsoleTests { + + @TestCase("console.log()", "print();") + @TestCase('console.log("Hello")', 'print("Hello");') + @TestCase('console.log("Hello %s", "there")', 'print(string.format("Hello %s", "there"));') + @TestCase('console.log("Hello %%s", "there")', 'print(string.format("Hello %%s", "there"));') + @TestCase('console.log("Hello", "There")', 'print("Hello", "There");') + @Test("console.log") + public testConsoleLog(inp: string, expected: string): void { + // Transpile + const lua = util.transpileString(inp); + + // Assert + Expect(lua).toBe(expected); + } + + @TestCase("console.trace()", "print(debug.traceback());") + @TestCase('console.trace("message")', 'print(debug.traceback("message"));') + @TestCase('console.trace("Hello %s", "there")', 'print(debug.traceback(string.format("Hello %s", "there")));') + @TestCase('console.trace("Hello %%s", "there")', 'print(debug.traceback(string.format("Hello %%s", "there")));') + @TestCase('console.trace("Hello", "there")', 'print(debug.traceback("Hello", "there"));') + @Test("console.trace") + public testConsoleTrace(inp: string, expected: string): void { + // Transpile + const lua = util.transpileString(inp); + + // Assert + Expect(lua).toBe(expected); + } + + @TestCase("console.assert(false)", "assert(false);") + @TestCase('console.assert(false, "message")', 'assert(false, "message");') + @TestCase('console.assert(false, "message %s", "info")', 'assert(false, string.format("message %s", "info"));') + @TestCase('console.assert(false, "message %%s", "info")', 'assert(false, string.format("message %%s", "info"));') + @TestCase('console.assert(false, "message", "more")', 'assert(false, "message", "more");') + @Test("console.assert") + public testConsoleAssert(inp: string, expected: string): void { + // Transpile + const lua = util.transpileString(inp); + + // Assert + Expect(lua).toBe(expected); + } + +} \ No newline at end of file