From 87c425a2920ed82d1937af3bf4875f311285c166 Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Thu, 4 Apr 2019 06:42:11 -0600 Subject: [PATCH 1/3] removing semi-colons, except where needed for disambiguation --- src/LuaPrinter.ts | 98 ++-- .../__snapshots__/transformation.spec.ts.snap | 524 +++++++++--------- test/unit/assignmentDestructuring.spec.ts | 6 +- test/unit/assignments/assignments.spec.ts | 22 +- .../compiler/configuration/options.spec.ts | 4 +- test/unit/console.spec.ts | 30 +- test/unit/enum.spec.ts | 8 +- test/unit/error.spec.ts | 2 +- test/unit/expressions.spec.ts | 112 ++-- test/unit/json.spec.ts | 2 +- test/unit/math.spec.ts | 18 +- test/unit/modules.spec.ts | 2 +- test/unit/objectLiteral.spec.ts | 12 +- test/unit/semicolons.spec.ts | 20 + test/unit/spreadElement.spec.ts | 8 +- 15 files changed, 462 insertions(+), 406 deletions(-) create mode 100644 test/unit/semicolons.spec.ts diff --git a/src/LuaPrinter.ts b/src/LuaPrinter.ts index 5538cca89..d3024b66d 100644 --- a/src/LuaPrinter.ts +++ b/src/LuaPrinter.ts @@ -107,7 +107,7 @@ export class LuaPrinter { const mapString = "{" + mapItems.join(",") + "}"; - return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString});`; + return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString})`; } private printImplementation( @@ -126,7 +126,7 @@ export class LuaPrinter { if ((this.options.luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) || this.options.luaLibImport === LuaLibImportKind.Always) { - header += `require("lualib_bundle");\n`; + header += `require("lualib_bundle")\n`; } // Inline lualib features else if (this.options.luaLibImport === LuaLibImportKind.Inline && luaLibFeatures.size > 0) @@ -172,10 +172,48 @@ export class LuaPrinter { } private printBlock(block: tstl.Block): SourceNode { - return this.createSourceNode( - block, - this.ignoreDeadStatements(block.statements).map(s => this.printStatement(s)) + return this.createSourceNode(block, this.printStatementArray(block.statements)); + } + + private statementMayRequireSemiColon(statement: tstl.Statement): boolean { + // Types of statements that could create ambiguous syntax if followed by parenthesis + return tstl.isVariableDeclarationStatement(statement) + || tstl.isAssignmentStatement(statement) + || tstl.isExpressionStatement(statement); + } + + private nodeStartsWithParenthesis(sourceNode: SourceNode): boolean { + let result: boolean | undefined; + sourceNode.walk(chunk => { + if (result === undefined) { + chunk = chunk.trimLeft(); // Ignore leading whitespace + + if (chunk.length > 0) { + result = chunk.startsWith("("); + } + } + }); + return result || false; + } + + private printStatementArray(statements: tstl.Statement[]): SourceChunk[] { + const statementNodes: SourceNode[] = []; + statements = this.removeDeadAndEmptyStatements(statements); + statements.forEach( + (s, i) => { + const node = this.printStatement(s); + + if (i > 0 + && this.statementMayRequireSemiColon(statements[i - 1]) + && this.nodeStartsWithParenthesis(node)) + { + statementNodes[i - 1].add(";"); + } + + statementNodes.push(node); + } ); + return statementNodes.length > 0 ? [...this.joinChunks("\n", statementNodes), "\n"] : []; } private printStatement(statement: tstl.Statement): SourceNode { @@ -214,13 +252,11 @@ export class LuaPrinter { private printDoStatement(statement: tstl.DoStatement): SourceNode { const chunks: SourceChunk[] = []; - if (statement.statements && statement.statements.length > 0) { - chunks.push(this.indent("do\n")); - this.pushIndent(); - chunks.push(...this.ignoreDeadStatements(statement.statements).map(s => this.printStatement(s))); - this.popIndent(); - chunks.push(this.indent("end\n")); - } + chunks.push(this.indent("do\n")); + this.pushIndent(); + chunks.push(...this.printStatementArray(statement.statements)); + this.popIndent(); + chunks.push(this.indent("end")); return this.concatNodes(...chunks); } @@ -233,7 +269,6 @@ export class LuaPrinter { if (tstl.isFunctionDefinition(statement)) { // Print all local functions as `local function foo()` instead of `local foo = function` to allow recursion chunks.push(this.printFunctionDefinition(statement)); - chunks.push("\n"); } else { chunks.push(...this.joinChunks(", ", statement.left.map(e => this.printExpression(e)))); @@ -242,7 +277,6 @@ export class LuaPrinter { chunks.push(" = "); chunks.push(...this.joinChunks(", ", statement.right.map(e => this.printExpression(e)))); } - chunks.push(";\n"); } return this.concatNodes(...chunks); @@ -260,7 +294,6 @@ export class LuaPrinter { const name = this.printExpression(statement.left[0]); if (tsHelper.isValidLuaFunctionDeclarationName(name.toString())) { chunks.push(this.printFunctionDefinition(statement)); - chunks.push("\n"); return this.createSourceNode(statement, chunks); } } @@ -268,7 +301,6 @@ export class LuaPrinter { chunks.push(...this.joinChunks(", ", statement.left.map(e => this.printExpression(e)))); chunks.push(" = "); chunks.push(...this.joinChunks(", ", statement.right.map(e => this.printExpression(e)))); - chunks.push(";\n"); return this.createSourceNode(statement, chunks); } @@ -292,10 +324,10 @@ export class LuaPrinter { this.pushIndent(); chunks.push(this.printBlock(statement.elseBlock)); this.popIndent(); - chunks.push(this.indent("end\n")); + chunks.push(this.indent("end")); } } else { - chunks.push(this.indent("end\n")); + chunks.push(this.indent("end")); } return this.concatNodes(...chunks); @@ -310,7 +342,7 @@ export class LuaPrinter { chunks.push(this.printBlock(statement.body)); this.popIndent(); - chunks.push(this.indent("end\n")); + chunks.push(this.indent("end")); return this.concatNodes(...chunks); } @@ -324,7 +356,7 @@ export class LuaPrinter { chunks.push(this.printBlock(statement.body)); this.popIndent(); - chunks.push(this.indent("until "), this.printExpression(statement.condtion), ";\n"); + chunks.push(this.indent("until "), this.printExpression(statement.condtion)); return this.concatNodes(...chunks); } @@ -347,7 +379,7 @@ export class LuaPrinter { chunks.push(this.printBlock(statement.body)); this.popIndent(); - chunks.push(this.indent("end\n")); + chunks.push(this.indent("end")); return this.concatNodes(...chunks); } @@ -363,38 +395,37 @@ export class LuaPrinter { this.pushIndent(); chunks.push(this.printBlock(statement.body)); this.popIndent(); - chunks.push(this.indent("end\n")); + chunks.push(this.indent("end")); return this.createSourceNode(statement, chunks); } private printGotoStatement(statement: tstl.GotoStatement): SourceNode { - return this.createSourceNode(statement, [this.indent("goto "), statement.label, ";\n"]); + return this.createSourceNode(statement, [this.indent("goto "), statement.label]); } private printLabelStatement(statement: tstl.LabelStatement): SourceNode { - return this.createSourceNode(statement, [this.indent("::"), statement.name, "::\n"]); + return this.createSourceNode(statement, [this.indent("::"), statement.name, "::"]); } private printReturnStatement(statement: tstl.ReturnStatement): SourceNode { if (!statement.expressions || statement.expressions.length === 0) { - return this.createSourceNode(statement, this.indent("return;\n")); + return this.createSourceNode(statement, this.indent("return")); } const chunks: SourceChunk[] = []; chunks.push(...this.joinChunks(", ", statement.expressions.map(e => this.printExpression(e)))); - chunks.push(";\n"); return this.createSourceNode(statement, [this.indent(), "return ", ...chunks]); } private printBreakStatement(statement: tstl.BreakStatement): SourceNode { - return this.createSourceNode(statement, this.indent("break;\n")); + return this.createSourceNode(statement, this.indent("break")); } private printExpressionStatement(statement: tstl.ExpressionStatement): SourceNode { - return this.concatNodes(this.indent(), this.printExpression(statement.expression), ";\n"); + return this.concatNodes(this.indent(), this.printExpression(statement.expression)); } // Expressions @@ -485,7 +516,6 @@ export class LuaPrinter { const returnNode: SourceChunk[] = [ "return ", ...this.joinChunks(", ", returnStatement.expressions.map(e => this.printExpression(e))), - ";", ]; chunks.push(this.createSourceNode(returnStatement, returnNode)); chunks.push(" end"); @@ -621,10 +651,16 @@ export class LuaPrinter { return LuaPrinter.operatorMap[kind]; } - private ignoreDeadStatements(statements: tstl.Statement[]): tstl.Statement[] { + private isEmptyStatement(statement: tstl.Statement): boolean { + return tstl.isDoStatement(statement) && (!statement.statements || statement.statements.length === 0); + } + + private removeDeadAndEmptyStatements(statements: tstl.Statement[]): tstl.Statement[] { const aliveStatements = []; for (const statement of statements) { - aliveStatements.push(statement); + if (!this.isEmptyStatement(statement)) { + aliveStatements.push(statement); + } if (tstl.isReturnStatement(statement)) { break; } diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index b0baaa3dd..af64e199c 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -1,20 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Transformation (callNamespace) 1`] = `"Namespace:myFunction();"`; +exports[`Transformation (callNamespace) 1`] = `"Namespace:myFunction()"`; exports[`Transformation (characterEscapeSequence) 1`] = ` -"local quoteInDoubleQuotes = \\"\\\\' \\\\' \\\\'\\"; -local quoteInTemplateString = \\"\\\\' \\\\' \\\\'\\"; -local doubleQuoteInQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\"; -local doubleQuoteInDoubleQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\"; -local doubleQuoteInTemplateString = \\"\\\\\\" \\\\\\" \\\\\\"\\"; -local backQuoteInQuotes = \\"\` \` \`\\"; -local backQuoteInDoubleQuotes = \\"\` \` \`\\"; -local backQuoteInTemplateString = \\"\` \` \`\\"; -local escapedCharsInQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\' \`\\"; -local escapedCharsInDoubleQUotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\'\\"; -local escapedCharsInTemplateString = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\' \`\\"; -local nonEmptyTemplateString = \\"Level 0: \\\\n\\\\t \\" .. tostring(\\"Level 1: \\\\n\\\\t\\\\t \\" .. tostring(\\"Level 3: \\\\n\\\\t\\\\t\\\\t \\" .. tostring(\\"Last level \\\\n --\\") .. \\" \\\\n --\\") .. \\" \\\\n --\\") .. \\" \\\\n --\\";" +"local quoteInDoubleQuotes = \\"\\\\' \\\\' \\\\'\\" +local quoteInTemplateString = \\"\\\\' \\\\' \\\\'\\" +local doubleQuoteInQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" +local doubleQuoteInDoubleQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" +local doubleQuoteInTemplateString = \\"\\\\\\" \\\\\\" \\\\\\"\\" +local backQuoteInQuotes = \\"\` \` \`\\" +local backQuoteInDoubleQuotes = \\"\` \` \`\\" +local backQuoteInTemplateString = \\"\` \` \`\\" +local escapedCharsInQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\' \`\\" +local escapedCharsInDoubleQUotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\'\\" +local escapedCharsInTemplateString = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" \\\\' \`\\" +local nonEmptyTemplateString = \\"Level 0: \\\\n\\\\t \\" .. tostring(\\"Level 1: \\\\n\\\\t\\\\t \\" .. tostring(\\"Level 3: \\\\n\\\\t\\\\t\\\\t \\" .. tostring(\\"Last level \\\\n --\\") .. \\" \\\\n --\\") .. \\" \\\\n --\\") .. \\" \\\\n --\\"" `; exports[`Transformation (classExtension1) 1`] = ` @@ -35,22 +35,22 @@ end" `; exports[`Transformation (classExtension4) 1`] = ` -"MyClass.test = \\"test\\"; -MyClass.testP = \\"testP\\"; +"MyClass.test = \\"test\\" +MyClass.testP = \\"testP\\" function MyClass.myFunction(self) end" `; exports[`Transformation (classPureAbstract) 1`] = ` -"ClassB = ClassB or {}; -ClassB.__index = ClassB; -ClassB.prototype = ClassB.prototype or {}; -ClassB.prototype.__index = ClassB.prototype; -ClassB.prototype.constructor = ClassB; +"ClassB = ClassB or {} +ClassB.__index = ClassB +ClassB.prototype = ClassB.prototype or {} +ClassB.prototype.__index = ClassB.prototype +ClassB.prototype.constructor = ClassB function ClassB.new(...) - local self = setmetatable({}, ClassB.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, ClassB.prototype) + self:____constructor(...) + return self end function ClassB.prototype.____constructor(self) end" @@ -58,170 +58,170 @@ end" exports[`Transformation (continue) 1`] = ` "do - local i = 0; + local i = 0 while i < 10 do do if i < 5 then - goto __continue1; + goto __continue1 end end ::__continue1:: - i = i + 1; + i = i + 1 end end" `; exports[`Transformation (continueConcurrent) 1`] = ` "do - local i = 0; + local i = 0 while i < 10 do do if i < 5 then - goto __continue1; + goto __continue1 end if i == 7 then - goto __continue1; + goto __continue1 end end ::__continue1:: - i = i + 1; + i = i + 1 end end" `; exports[`Transformation (continueNested) 1`] = ` "do - local i = 0; + local i = 0 while i < 5 do do if i % 2 == 0 then - goto __continue1; + goto __continue1 end do - local j = 0; + local j = 0 while j < 2 do do if j == 1 then - goto __continue3; + goto __continue3 end end ::__continue3:: - j = j + 1; + j = j + 1 end end end ::__continue1:: - i = i + 1; + i = i + 1 end end" `; exports[`Transformation (continueNestedConcurrent) 1`] = ` "do - local i = 0; + local i = 0 while i < 5 do do if i % 2 == 0 then - goto __continue1; + goto __continue1 end do - local j = 0; + local j = 0 while j < 2 do do if j == 1 then - goto __continue3; + goto __continue3 end end ::__continue3:: - j = j + 1; + j = j + 1 end end if i == 4 then - goto __continue1; + goto __continue1 end end ::__continue1:: - i = i + 1; + i = i + 1 end end" `; exports[`Transformation (do) 1`] = ` -"local e = 10; +"local e = 10 repeat - e = e - 1; -until not (e > 0);" + e = e - 1 +until not (e > 0)" `; exports[`Transformation (enum) 1`] = ` -"TestEnum = {}; -TestEnum.val1 = 0; -TestEnum[0] = \\"val1\\"; -TestEnum.val2 = 2; -TestEnum[2] = \\"val2\\"; -TestEnum.val3 = 3; -TestEnum[3] = \\"val3\\";" +"TestEnum = {} +TestEnum.val1 = 0 +TestEnum[0] = \\"val1\\" +TestEnum.val2 = 2 +TestEnum[2] = \\"val2\\" +TestEnum.val3 = 3 +TestEnum[3] = \\"val3\\"" `; exports[`Transformation (enumHeterogeneous) 1`] = ` -"TestEnum = {}; -TestEnum.val1 = 0; -TestEnum[0] = \\"val1\\"; -TestEnum.val2 = 3; -TestEnum[3] = \\"val2\\"; -TestEnum.val3 = \\"baz\\"; -TestEnum.baz = \\"val3\\";" +"TestEnum = {} +TestEnum.val1 = 0 +TestEnum[0] = \\"val1\\" +TestEnum.val2 = 3 +TestEnum[3] = \\"val2\\" +TestEnum.val3 = \\"baz\\" +TestEnum.baz = \\"val3\\"" `; exports[`Transformation (enumMembersOnly) 1`] = ` -"val1 = 0; -val2 = 2; -val3 = 3; -val4 = \\"bye\\"; -local a = val1;" +"val1 = 0 +val2 = 2 +val3 = 3 +val4 = \\"bye\\" +local a = val1" `; exports[`Transformation (enumString) 1`] = ` -"TestEnum = {}; -TestEnum.val1 = \\"foo\\"; -TestEnum.foo = \\"val1\\"; -TestEnum.val2 = \\"bar\\"; -TestEnum.bar = \\"val2\\"; -TestEnum.val3 = \\"baz\\"; -TestEnum.baz = \\"val3\\";" +"TestEnum = {} +TestEnum.val1 = \\"foo\\" +TestEnum.foo = \\"val1\\" +TestEnum.val2 = \\"bar\\" +TestEnum.bar = \\"val2\\" +TestEnum.val3 = \\"baz\\" +TestEnum.baz = \\"val3\\"" `; exports[`Transformation (exportStatement) 1`] = ` -"local exports = exports or {}; -local xyz = 4; -exports.xyz = xyz; -exports.uwv = xyz; +"local exports = exports or {} +local xyz = 4 +exports.xyz = xyz +exports.uwv = xyz do - local __TSTL_export = require(\\"xyz\\"); + local __TSTL_export = require(\\"xyz\\") for ____exportKey, ____exportValue in pairs(__TSTL_export) do - exports[____exportKey] = ____exportValue; + exports[____exportKey] = ____exportValue end end do - local __TSTL_xyz = require(\\"xyz\\"); - local abc = __TSTL_xyz.abc; - local def = __TSTL_xyz.def; - exports.abc = abc; - exports.def = def; + local __TSTL_xyz = require(\\"xyz\\") + local abc = __TSTL_xyz.abc + local def = __TSTL_xyz.def + exports.abc = abc + exports.def = def end do - local __TSTL_xyz = require(\\"xyz\\"); - local def = __TSTL_xyz.abc; - exports.def = def; + local __TSTL_xyz = require(\\"xyz\\") + local def = __TSTL_xyz.abc + exports.def = def end -return exports;" +return exports" `; exports[`Transformation (for) 1`] = ` "do - local i = 1; + local i = 1 while i <= 100 do - i = i + 1; + i = i + 1 end end" `; @@ -248,117 +248,117 @@ exports[`Transformation (forOf) 1`] = ` 8, 9, 10, -}; +} for ____TS_index = 1, #____TS_array do - local i = ____TS_array[____TS_index]; + local i = ____TS_array[____TS_index] end" `; exports[`Transformation (functionRestArguments) 1`] = ` "function varargsFunction(self, a, ...) - local b = ({...}); + local b = ({...}) end" `; exports[`Transformation (getSetAccessors) 1`] = ` -"require(\\"lualib_bundle\\"); -MyClass = MyClass or {}; -MyClass.__index = MyClass; -MyClass.prototype = MyClass.prototype or {}; -MyClass.prototype.____getters = {}; -MyClass.prototype.__index = __TS__Index(MyClass.prototype); -MyClass.prototype.____setters = {}; -MyClass.prototype.__newindex = __TS__NewIndex(MyClass.prototype); -MyClass.prototype.constructor = MyClass; +"require(\\"lualib_bundle\\") +MyClass = MyClass or {} +MyClass.__index = MyClass +MyClass.prototype = MyClass.prototype or {} +MyClass.prototype.____getters = {} +MyClass.prototype.__index = __TS__Index(MyClass.prototype) +MyClass.prototype.____setters = {} +MyClass.prototype.__newindex = __TS__NewIndex(MyClass.prototype) +MyClass.prototype.constructor = MyClass function MyClass.new(...) - local self = setmetatable({}, MyClass.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, MyClass.prototype) + self:____constructor(...) + return self end function MyClass.prototype.____constructor(self) end function MyClass.prototype.____getters.field(self) - return self._field + 4; + return self._field + 4 end function MyClass.prototype.____setters.field(self, v) - self._field = v * 2; + self._field = v * 2 end -local instance = MyClass.new(); -instance.field = 4; -local b = instance.field; -local c = (4 + instance.field) * 3;" +local instance = MyClass.new() +instance.field = 4 +local b = instance.field +local c = (4 + instance.field) * 3" `; exports[`Transformation (interfaceIndex) 1`] = ` -"local a = {}; -a.abc = \\"def\\";" +"local a = {} +a.abc = \\"def\\"" `; exports[`Transformation (methodRestArguments) 1`] = ` -"MyClass = MyClass or {}; -MyClass.__index = MyClass; -MyClass.prototype = MyClass.prototype or {}; -MyClass.prototype.__index = MyClass.prototype; -MyClass.prototype.constructor = MyClass; +"MyClass = MyClass or {} +MyClass.__index = MyClass +MyClass.prototype = MyClass.prototype or {} +MyClass.prototype.__index = MyClass.prototype +MyClass.prototype.constructor = MyClass function MyClass.new(...) - local self = setmetatable({}, MyClass.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, MyClass.prototype) + self:____constructor(...) + return self end function MyClass.prototype.____constructor(self) end function MyClass.prototype.varargsFunction(self, a, ...) - local b = ({...}); + local b = ({...}) end" `; exports[`Transformation (modulesChangedVariableExport) 1`] = ` -"local exports = exports or {}; -exports.foo = 1; -return exports;" +"local exports = exports or {} +exports.foo = 1 +return exports" `; exports[`Transformation (modulesClassExport) 1`] = ` -"local exports = exports or {}; -exports.TestClass = exports.TestClass or {}; -exports.TestClass.__index = exports.TestClass; -exports.TestClass.prototype = exports.TestClass.prototype or {}; -exports.TestClass.prototype.__index = exports.TestClass.prototype; -exports.TestClass.prototype.constructor = exports.TestClass; +"local exports = exports or {} +exports.TestClass = exports.TestClass or {} +exports.TestClass.__index = exports.TestClass +exports.TestClass.prototype = exports.TestClass.prototype or {} +exports.TestClass.prototype.__index = exports.TestClass.prototype +exports.TestClass.prototype.constructor = exports.TestClass function exports.TestClass.new(...) - local self = setmetatable({}, exports.TestClass.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, exports.TestClass.prototype) + self:____constructor(...) + return self end function exports.TestClass.prototype.____constructor(self) end -return exports;" +return exports" `; exports[`Transformation (modulesClassWithMemberExport) 1`] = ` -"local exports = exports or {}; -exports.TestClass = exports.TestClass or {}; -exports.TestClass.__index = exports.TestClass; -exports.TestClass.prototype = exports.TestClass.prototype or {}; -exports.TestClass.prototype.__index = exports.TestClass.prototype; -exports.TestClass.prototype.constructor = exports.TestClass; +"local exports = exports or {} +exports.TestClass = exports.TestClass or {} +exports.TestClass.__index = exports.TestClass +exports.TestClass.prototype = exports.TestClass.prototype or {} +exports.TestClass.prototype.__index = exports.TestClass.prototype +exports.TestClass.prototype.constructor = exports.TestClass function exports.TestClass.new(...) - local self = setmetatable({}, exports.TestClass.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, exports.TestClass.prototype) + self:____constructor(...) + return self end function exports.TestClass.prototype.____constructor(self) end function exports.TestClass.prototype.memberFunc(self) end -return exports;" +return exports" `; exports[`Transformation (modulesFunctionExport) 1`] = ` -"local exports = exports or {}; +"local exports = exports or {} function exports.publicFunc(self) end -return exports;" +return exports" `; exports[`Transformation (modulesFunctionNoExport) 1`] = ` @@ -366,116 +366,116 @@ exports[`Transformation (modulesFunctionNoExport) 1`] = ` end" `; -exports[`Transformation (modulesImportAll) 1`] = `"local Test = require(\\"test\\");"`; +exports[`Transformation (modulesImportAll) 1`] = `"local Test = require(\\"test\\")"`; exports[`Transformation (modulesImportNamed) 1`] = ` -"local __TSTL_test = require(\\"test\\"); -local TestClass = __TSTL_test.TestClass;" +"local __TSTL_test = require(\\"test\\") +local TestClass = __TSTL_test.TestClass" `; exports[`Transformation (modulesImportNamedSpecialChars) 1`] = ` -"local __TSTL_kebab_module = require(\\"kebab-module\\"); -local TestClass = __TSTL_kebab_module.TestClass; -local __TSTL_dollar_module = require(\\"dollar$module\\"); -local TestClass = __TSTL_dollar_module.TestClass; -local __TSTL_singlequote_module = require(\\"singlequote'module\\"); -local TestClass = __TSTL_singlequote_module.TestClass; -local __TSTL_hash_module = require(\\"hash#module\\"); -local TestClass = __TSTL_hash_module.TestClass; -local __TSTL_space_module = require(\\"space module\\"); -local TestClass = __TSTL_space_module.TestClass;" +"local __TSTL_kebab_module = require(\\"kebab-module\\") +local TestClass = __TSTL_kebab_module.TestClass +local __TSTL_dollar_module = require(\\"dollar$module\\") +local TestClass = __TSTL_dollar_module.TestClass +local __TSTL_singlequote_module = require(\\"singlequote'module\\") +local TestClass = __TSTL_singlequote_module.TestClass +local __TSTL_hash_module = require(\\"hash#module\\") +local TestClass = __TSTL_hash_module.TestClass +local __TSTL_space_module = require(\\"space module\\") +local TestClass = __TSTL_space_module.TestClass" `; exports[`Transformation (modulesImportRenamed) 1`] = ` -"local __TSTL_test = require(\\"test\\"); -local RenamedClass = __TSTL_test.TestClass;" +"local __TSTL_test = require(\\"test\\") +local RenamedClass = __TSTL_test.TestClass" `; exports[`Transformation (modulesImportRenamedSpecialChars) 1`] = ` -"local __TSTL_kebab_module = require(\\"kebab-module\\"); -local RenamedClass = __TSTL_kebab_module.TestClass; -local __TSTL_dollar_module = require(\\"dollar$module\\"); -local RenamedClass = __TSTL_dollar_module.TestClass; -local __TSTL_singlequote_module = require(\\"singlequote'module\\"); -local RenamedClass = __TSTL_singlequote_module.TestClass; -local __TSTL_hash_module = require(\\"hash#module\\"); -local RenamedClass = __TSTL_hash_module.TestClass; -local __TSTL_space_module = require(\\"space module\\"); -local RenamedClass = __TSTL_space_module.TestClass;" +"local __TSTL_kebab_module = require(\\"kebab-module\\") +local RenamedClass = __TSTL_kebab_module.TestClass +local __TSTL_dollar_module = require(\\"dollar$module\\") +local RenamedClass = __TSTL_dollar_module.TestClass +local __TSTL_singlequote_module = require(\\"singlequote'module\\") +local RenamedClass = __TSTL_singlequote_module.TestClass +local __TSTL_hash_module = require(\\"hash#module\\") +local RenamedClass = __TSTL_hash_module.TestClass +local __TSTL_space_module = require(\\"space module\\") +local RenamedClass = __TSTL_space_module.TestClass" `; -exports[`Transformation (modulesImportWithoutFromClause) 1`] = `"require(\\"test\\");"`; +exports[`Transformation (modulesImportWithoutFromClause) 1`] = `"require(\\"test\\")"`; exports[`Transformation (modulesNamespaceExport) 1`] = ` -"local exports = exports or {}; -exports.TestSpace = exports.TestSpace or {}; -local TestSpace = exports.TestSpace; -return exports;" +"local exports = exports or {} +exports.TestSpace = exports.TestSpace or {} +local TestSpace = exports.TestSpace +return exports" `; exports[`Transformation (modulesNamespaceExportEnum) 1`] = ` -"local exports = exports or {}; -exports.test = exports.test or {}; -local test = exports.test; +"local exports = exports or {} +exports.test = exports.test or {} +local test = exports.test do - test.TestEnum = {}; - test.TestEnum.foo = \\"foo\\"; - test.TestEnum.foo = \\"foo\\"; - test.TestEnum.bar = \\"bar\\"; - test.TestEnum.bar = \\"bar\\"; + test.TestEnum = {} + test.TestEnum.foo = \\"foo\\" + test.TestEnum.foo = \\"foo\\" + test.TestEnum.bar = \\"bar\\" + test.TestEnum.bar = \\"bar\\" end -return exports;" +return exports" `; exports[`Transformation (modulesNamespaceNestedWithMemberExport) 1`] = ` -"local exports = exports or {}; -exports.TestSpace = exports.TestSpace or {}; -local TestSpace = exports.TestSpace; +"local exports = exports or {} +exports.TestSpace = exports.TestSpace or {} +local TestSpace = exports.TestSpace do - TestSpace.TestNestedSpace = TestSpace.TestNestedSpace or {}; - local TestNestedSpace = TestSpace.TestNestedSpace; + TestSpace.TestNestedSpace = TestSpace.TestNestedSpace or {} + local TestNestedSpace = TestSpace.TestNestedSpace do function TestNestedSpace.innerFunc(self) end end end -return exports;" +return exports" `; -exports[`Transformation (modulesNamespaceNoExport) 1`] = `"TestSpace = TestSpace or {};"`; +exports[`Transformation (modulesNamespaceNoExport) 1`] = `"TestSpace = TestSpace or {}"`; exports[`Transformation (modulesNamespaceWithMemberExport) 1`] = ` -"local exports = exports or {}; -exports.TestSpace = exports.TestSpace or {}; -local TestSpace = exports.TestSpace; +"local exports = exports or {} +exports.TestSpace = exports.TestSpace or {} +local TestSpace = exports.TestSpace do function TestSpace.innerFunc(self) end end -return exports;" +return exports" `; exports[`Transformation (modulesNamespaceWithMemberNoExport) 1`] = ` -"local exports = exports or {}; -exports.TestSpace = exports.TestSpace or {}; -local TestSpace = exports.TestSpace; +"local exports = exports or {} +exports.TestSpace = exports.TestSpace or {} +local TestSpace = exports.TestSpace do local function innerFunc(self) end end -return exports;" +return exports" `; exports[`Transformation (modulesVariableExport) 1`] = ` -"local exports = exports or {}; -exports.foo = \\"bar\\"; -return exports;" +"local exports = exports or {} +exports.foo = \\"bar\\" +return exports" `; -exports[`Transformation (modulesVariableNoExport) 1`] = `"local foo = \\"bar\\";"`; +exports[`Transformation (modulesVariableNoExport) 1`] = `"local foo = \\"bar\\""`; exports[`Transformation (namespace) 1`] = ` -"myNamespace = myNamespace or {}; +"myNamespace = myNamespace or {} do local function nsMember(self) end @@ -483,48 +483,48 @@ end" `; exports[`Transformation (namespaceMerge) 1`] = ` -"MergedClass = MergedClass or {}; -MergedClass.__index = MergedClass; -MergedClass.prototype = MergedClass.prototype or {}; -MergedClass.prototype.__index = MergedClass.prototype; -MergedClass.prototype.constructor = MergedClass; +"MergedClass = MergedClass or {} +MergedClass.__index = MergedClass +MergedClass.prototype = MergedClass.prototype or {} +MergedClass.prototype.__index = MergedClass.prototype +MergedClass.prototype.constructor = MergedClass function MergedClass.new(...) - local self = setmetatable({}, MergedClass.prototype); - self:____constructor(...); - return self; + local self = setmetatable({}, MergedClass.prototype) + self:____constructor(...) + return self end function MergedClass.prototype.____constructor(self) self.propertyFunc = function() - end; + end end function MergedClass.staticMethodA(self) end function MergedClass.staticMethodB(self) - self:staticMethodA(); + self:staticMethodA() end function MergedClass.prototype.methodA(self) end function MergedClass.prototype.methodB(self) - self:methodA(); - self:propertyFunc(); + self:methodA() + self:propertyFunc() end -MergedClass = MergedClass or {}; +MergedClass = MergedClass or {} do function MergedClass.namespaceFunc(self) end end -local mergedClass = MergedClass.new(); -mergedClass:methodB(); -mergedClass:propertyFunc(); -MergedClass:staticMethodB(); -MergedClass:namespaceFunc();" +local mergedClass = MergedClass.new() +mergedClass:methodB() +mergedClass:propertyFunc() +MergedClass:staticMethodB() +MergedClass:namespaceFunc()" `; exports[`Transformation (namespaceNested) 1`] = ` -"myNamespace = myNamespace or {}; +"myNamespace = myNamespace or {} do - myNamespace.myNestedNamespace = myNamespace.myNestedNamespace or {}; - local myNestedNamespace = myNamespace.myNestedNamespace; + myNamespace.myNestedNamespace = myNamespace.myNestedNamespace or {} + local myNestedNamespace = myNamespace.myNestedNamespace do local function nsMember(self) end @@ -539,22 +539,22 @@ end" exports[`Transformation (returnDefault) 1`] = ` "function myFunc(self) - return; + return end" `; exports[`Transformation (shorthandPropertyAssignment) 1`] = ` -"local f; -f = function(____, x) return ({x = x}); end;" +"local f +f = function(____, x) return ({x = x}) end" `; exports[`Transformation (tryCatch) 1`] = ` "do local ____TS_try, er = pcall(function() - local a = 42; - end); + local a = 42 + end) if not (____TS_try) then - local b = \\"fail\\"; + local b = \\"fail\\" end end" `; @@ -562,13 +562,13 @@ end" exports[`Transformation (tryCatchFinally) 1`] = ` "do local ____TS_try, er = pcall(function() - local a = 42; - end); + local a = 42 + end) if not (____TS_try) then - local b = \\"fail\\"; + local b = \\"fail\\" end do - local c = \\"finally\\"; + local c = \\"finally\\" end end" `; @@ -576,56 +576,56 @@ end" exports[`Transformation (tryFinally) 1`] = ` "do pcall(function() - local a = 42; - end); + local a = 42 + end) do - local b = \\"finally\\"; + local b = \\"finally\\" end end" `; exports[`Transformation (tupleReturn) 1`] = ` "function tupleReturn(self) - return 0, \\"foobar\\"; -end -tupleReturn(_G); -noTupleReturn(_G); -local a, b = tupleReturn(_G); -local c, d = table.unpack(noTupleReturn(_G)); -a, b = tupleReturn(_G); -c, d = table.unpack(noTupleReturn(_G)); -local e = ({tupleReturn(_G)}); -local f = noTupleReturn(_G); -e = ({tupleReturn(_G)}); -f = noTupleReturn(_G); -foo(_G, ({tupleReturn(_G)})); -foo(_G, noTupleReturn(_G)); + return 0, \\"foobar\\" +end +tupleReturn(_G) +noTupleReturn(_G) +local a, b = tupleReturn(_G) +local c, d = table.unpack(noTupleReturn(_G)) +a, b = tupleReturn(_G) +c, d = table.unpack(noTupleReturn(_G)) +local e = ({tupleReturn(_G)}) +local f = noTupleReturn(_G) +e = ({tupleReturn(_G)}) +f = noTupleReturn(_G) +foo(_G, ({tupleReturn(_G)})) +foo(_G, noTupleReturn(_G)) function tupleReturnFromVar(self) local r = { 1, \\"baz\\", - }; - return table.unpack(r); + } + return table.unpack(r) end function tupleReturnForward(self) - return tupleReturn(_G); + return tupleReturn(_G) end function tupleNoForward(self) - return ({tupleReturn(_G)}); + return ({tupleReturn(_G)}) end function tupleReturnUnpack(self) - return table.unpack(tupleNoForward(_G)); + return table.unpack(tupleNoForward(_G)) end" `; exports[`Transformation (typeAssert) 1`] = ` -"local test1 = 10; -local test2 = 10;" +"local test1 = 10 +local test2 = 10" `; exports[`Transformation (while) 1`] = ` -"local d = 10; +"local d = 10 while d > 0 do - d = d - 1; + d = d - 1 end" `; diff --git a/test/unit/assignmentDestructuring.spec.ts b/test/unit/assignmentDestructuring.spec.ts index 41fb9899b..34ccacee5 100644 --- a/test/unit/assignmentDestructuring.spec.ts +++ b/test/unit/assignmentDestructuring.spec.ts @@ -10,7 +10,7 @@ test("Assignment destructuring [5.1]", () => { luaTarget: LuaTarget.Lua51, luaLibImport: LuaLibImportKind.None, }); - expect(lua).toBe(`local a, b = unpack(myFunc());`); + expect(lua).toBe(`local a, b = unpack(myFunc())`); }); test("Assignment destructuring [5.2]", () => { @@ -18,7 +18,7 @@ test("Assignment destructuring [5.2]", () => { luaTarget: LuaTarget.Lua52, luaLibImport: LuaLibImportKind.None, }); - expect(lua).toBe(`local a, b = table.unpack(myFunc());`); + expect(lua).toBe(`local a, b = table.unpack(myFunc())`); }); test("Assignment destructuring [JIT]", () => { @@ -26,7 +26,7 @@ test("Assignment destructuring [JIT]", () => { luaTarget: LuaTarget.LuaJIT, luaLibImport: LuaLibImportKind.None, }); - expect(lua).toBe(`local a, b = unpack(myFunc());`); + expect(lua).toBe(`local a, b = unpack(myFunc())`); }); test.each([ diff --git a/test/unit/assignments/assignments.spec.ts b/test/unit/assignments/assignments.spec.ts index 54f925d41..4e47bd849 100644 --- a/test/unit/assignments/assignments.spec.ts +++ b/test/unit/assignments/assignments.spec.ts @@ -10,8 +10,8 @@ test.each([ { inp: "false", out: "false" }, { inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` }, ])("Const assignment (%p)", ({ inp, out }) => { - const lua = util.transpileString(`const myvar = ${inp};`); - expect(lua).toBe(`local myvar = ${out};`); + const lua = util.transpileString(`const myvar = ${inp}`); + expect(lua).toBe(`local myvar = ${out}`); }); test.each([ @@ -22,8 +22,8 @@ test.each([ { inp: "false", out: "false" }, { inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` }, ])("Let assignment (%p)", ({ inp, out }) => { - const lua = util.transpileString(`let myvar = ${inp};`); - expect(lua).toBe(`local myvar = ${out};`); + const lua = util.transpileString(`let myvar = ${inp}`); + expect(lua).toBe(`local myvar = ${out}`); }); test.each([ @@ -34,8 +34,8 @@ test.each([ { inp: "false", out: "false" }, { inp: `{a:3,b:"4"}`, out: `{\n a = 3,\n b = "4",\n}` }, ])("Var assignment (%p)", ({ inp, out }) => { - const lua = util.transpileString(`var myvar = ${inp};`); - expect(lua).toBe(`myvar = ${out};`); + const lua = util.transpileString(`var myvar = ${inp}`); + expect(lua).toBe(`myvar = ${out}`); }); test.each(["var myvar;", "let myvar;", "const myvar = null;", "const myvar = undefined;"])( @@ -84,7 +84,7 @@ test("TupleReturn assignment", () => { `; const lua = util.transpileString(code); - expect(lua).toBe("local a, b = abc();"); + expect(lua).toBe("local a, b = abc()"); }); test("TupleReturn Single assignment", () => { @@ -96,7 +96,7 @@ test("TupleReturn Single assignment", () => { `; const lua = util.transpileString(code); - expect(lua).toBe("local a = ({abc()});\na = ({abc()});"); + expect(lua).toBe("local a = ({abc()})\na = ({abc()})"); }); test("TupleReturn interface assignment", () => { @@ -109,7 +109,7 @@ test("TupleReturn interface assignment", () => { `; const lua = util.transpileString(code); - expect(lua).toBe("local a, b = jkl:abc();"); + expect(lua).toBe("local a, b = jkl:abc()"); }); test("TupleReturn namespace assignment", () => { @@ -122,7 +122,7 @@ test("TupleReturn namespace assignment", () => { `; const lua = util.transpileString(code); - expect(lua).toBe("local a, b = def.abc();"); + expect(lua).toBe("local a, b = def.abc()"); }); test("TupleReturn method assignment", () => { @@ -135,7 +135,7 @@ test("TupleReturn method assignment", () => { `; const lua = util.transpileString(code); - expect(lua).toBe("local jkl = def.new();\nlocal a, b = jkl:abc();"); + expect(lua).toBe("local jkl = def.new()\nlocal a, b = jkl:abc()"); }); test("TupleReturn functional", () => { diff --git a/test/unit/compiler/configuration/options.spec.ts b/test/unit/compiler/configuration/options.spec.ts index 47bf9bedf..f723faa86 100644 --- a/test/unit/compiler/configuration/options.spec.ts +++ b/test/unit/compiler/configuration/options.spec.ts @@ -5,7 +5,7 @@ test.each([LuaTarget.LuaJIT, "jit", "JiT"])("Options luaTarget case-insensitive const options = { luaTarget: target as LuaTarget }; const result = util.transpileString("~a", options); - expect(result).toBe("bit.bnot(a);"); + expect(result).toBe("bit.bnot(a)"); }); test.each([LuaLibImportKind.None, "none", "NoNe"])( @@ -14,6 +14,6 @@ test.each([LuaLibImportKind.None, "none", "NoNe"])( const options = { luaLibImport: importKind as LuaLibImportKind }; const result = util.transpileString("const a = new Map();", options); - expect(result).toBe("local a = Map.new();"); + expect(result).toBe("local a = Map.new()"); }, ); diff --git a/test/unit/console.spec.ts b/test/unit/console.spec.ts index 5c9319045..5734b6440 100644 --- a/test/unit/console.spec.ts +++ b/test/unit/console.spec.ts @@ -3,54 +3,54 @@ import * as util from "../util"; const compilerOptions = { lib: ["lib.es2015.d.ts", "lib.dom.d.ts"] }; test.each([ - { inp: "console.log()", expected: "print();" }, - { inp: 'console.log("Hello")', expected: 'print("Hello");' }, + { inp: "console.log()", expected: "print()" }, + { inp: 'console.log("Hello")', expected: 'print("Hello")' }, { inp: 'console.log("Hello %s", "there")', - expected: 'print(string.format("Hello %s", "there"));', + expected: 'print(string.format("Hello %s", "there"))', }, { inp: 'console.log("Hello %%s", "there")', - expected: 'print(string.format("Hello %%s", "there"));', + expected: 'print(string.format("Hello %%s", "there"))', }, - { inp: 'console.log("Hello", "There")', expected: 'print("Hello", "There");' }, + { inp: 'console.log("Hello", "There")', expected: 'print("Hello", "There")' }, ])("console.log (%p)", ({ inp, expected }) => { expect(util.transpileString(inp, compilerOptions)).toBe(expected); }); test.each([ - { inp: "console.trace()", expected: "print(debug.traceback());" }, - { inp: 'console.trace("message")', expected: 'print(debug.traceback("message"));' }, + { inp: "console.trace()", expected: "print(debug.traceback())" }, + { inp: 'console.trace("message")', expected: 'print(debug.traceback("message"))' }, { inp: 'console.trace("Hello %s", "there")', - expected: 'print(debug.traceback(string.format("Hello %s", "there")));', + expected: 'print(debug.traceback(string.format("Hello %s", "there")))', }, { inp: 'console.trace("Hello %%s", "there")', - expected: 'print(debug.traceback(string.format("Hello %%s", "there")));', + expected: 'print(debug.traceback(string.format("Hello %%s", "there")))', }, { inp: 'console.trace("Hello", "there")', - expected: 'print(debug.traceback("Hello", "there"));', + expected: 'print(debug.traceback("Hello", "there"))', }, ])("console.trace (%p)", ({ inp, expected }) => { expect(util.transpileString(inp, compilerOptions)).toBe(expected); }); test.each([ - { inp: "console.assert(false)", expected: "assert(false);" }, - { inp: 'console.assert(false, "message")', expected: 'assert(false, "message");' }, + { inp: "console.assert(false)", expected: "assert(false)" }, + { inp: 'console.assert(false, "message")', expected: 'assert(false, "message")' }, { inp: 'console.assert(false, "message %s", "info")', - expected: 'assert(false, string.format("message %s", "info"));', + expected: 'assert(false, string.format("message %s", "info"))', }, { inp: 'console.assert(false, "message %%s", "info")', - expected: 'assert(false, string.format("message %%s", "info"));', + expected: 'assert(false, string.format("message %%s", "info"))', }, { inp: 'console.assert(false, "message", "more")', - expected: 'assert(false, "message", "more");', + expected: 'assert(false, "message", "more")', }, ])("console.assert (%p)", ({ inp, expected }) => { expect(util.transpileString(inp, compilerOptions)).toBe(expected); diff --git a/test/unit/enum.spec.ts b/test/unit/enum.spec.ts index cbb0fbe15..c067d04fb 100644 --- a/test/unit/enum.spec.ts +++ b/test/unit/enum.spec.ts @@ -11,7 +11,7 @@ test("Declare const enum", () => { const valueOne = TestEnum.MEMBER_ONE; `; - expect(util.transpileString(testCode)).toBe(`local valueOne = "test";`); + expect(util.transpileString(testCode)).toBe(`local valueOne = "test"`); }); test("Const enum", () => { @@ -24,7 +24,7 @@ test("Const enum", () => { const valueOne = TestEnum.MEMBER_TWO; `; - expect(util.transpileString(testCode)).toBe(`local valueOne = "test2";`); + expect(util.transpileString(testCode)).toBe(`local valueOne = "test2"`); }); test("Const enum without initializer", () => { @@ -37,7 +37,7 @@ test("Const enum without initializer", () => { const valueOne = TestEnum.MEMBER_TWO; `; - expect(util.transpileString(testCode)).toBe(`local valueOne = 1;`); + expect(util.transpileString(testCode)).toBe(`local valueOne = 1`); }); test("Const enum without initializer in some values", () => { @@ -51,7 +51,7 @@ test("Const enum without initializer in some values", () => { const valueOne = TestEnum.MEMBER_TWO; `; - expect(util.transpileString(testCode)).toBe(`local valueOne = 4;`); + expect(util.transpileString(testCode)).toBe(`local valueOne = 4`); }); test("Invalid heterogeneous enum", () => { diff --git a/test/unit/error.spec.ts b/test/unit/error.spec.ts index f91a22269..7adc5a29a 100644 --- a/test/unit/error.spec.ts +++ b/test/unit/error.spec.ts @@ -3,7 +3,7 @@ import * as util from "../util"; test("throwString", () => { const lua = util.transpileString(`throw "Some Error"`); - expect(lua).toBe(`error("Some Error");`); + expect(lua).toBe(`error("Some Error")`); }); test("throwError", () => { diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 072accf9b..37769c02c 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -4,23 +4,23 @@ import { TSTLErrors } from "../../src/TSTLErrors"; import * as util from "../util"; test.each([ - { input: "i++", lua: "i = i + 1;" }, - { input: "++i", lua: "i = i + 1;" }, - { input: "i--", lua: "i = i - 1;" }, - { input: "--i", lua: "i = i - 1;" }, - { input: "!a", lua: "not a;" }, - { input: "-a", lua: "-a;" }, - { input: "+a", lua: "a;" }, + { input: "i++", lua: "i = i + 1" }, + { input: "++i", lua: "i = i + 1" }, + { input: "i--", lua: "i = i - 1" }, + { input: "--i", lua: "i = i - 1" }, + { input: "!a", lua: "not a" }, + { input: "-a", lua: "-a" }, + { input: "+a", lua: "a" }, { input: "let a = delete tbl['test']", - lua: "local a = (function()\n tbl.test = nil;\n return true;\nend)();", + lua: "local a = (function()\n tbl.test = nil\n return true\nend)()", }, - { input: "delete tbl['test']", lua: "tbl.test = nil;" }, + { input: "delete tbl['test']", lua: "tbl.test = nil" }, { input: "let a = delete tbl.test", - lua: "local a = (function()\n tbl.test = nil;\n return true;\nend)();", + lua: "local a = (function()\n tbl.test = nil\n return true\nend)()", }, - { input: "delete tbl.test", lua: "tbl.test = nil;" }, + { input: "delete tbl.test", lua: "tbl.test = nil" }, ])("Unary expressions basic (%p)", ({ input, lua }) => { expect(util.transpileString(input)).toBe(lua); }); @@ -106,55 +106,55 @@ test.each([ }); test.each([ - { input: "~a", lua: "bit.bnot(a);" }, - { input: "a&b", lua: "bit.band(a, b);" }, - { input: "a&=b", lua: "a = bit.band(a, b);" }, - { input: "a|b", lua: "bit.bor(a, b);" }, - { input: "a|=b", lua: "a = bit.bor(a, b);" }, - { input: "a^b", lua: "bit.bxor(a, b);" }, - { input: "a^=b", lua: "a = bit.bxor(a, b);" }, - { input: "a<>b", lua: "bit.arshift(a, b);" }, - { input: "a>>=b", lua: "a = bit.arshift(a, b);" }, - { input: "a>>>b", lua: "bit.rshift(a, b);" }, - { input: "a>>>=b", lua: "a = bit.rshift(a, b);" }, + { input: "~a", lua: "bit.bnot(a)" }, + { input: "a&b", lua: "bit.band(a, b)" }, + { input: "a&=b", lua: "a = bit.band(a, b)" }, + { input: "a|b", lua: "bit.bor(a, b)" }, + { input: "a|=b", lua: "a = bit.bor(a, b)" }, + { input: "a^b", lua: "bit.bxor(a, b)" }, + { input: "a^=b", lua: "a = bit.bxor(a, b)" }, + { input: "a<>b", lua: "bit.arshift(a, b)" }, + { input: "a>>=b", lua: "a = bit.arshift(a, b)" }, + { input: "a>>>b", lua: "bit.rshift(a, b)" }, + { input: "a>>>=b", lua: "a = bit.rshift(a, b)" }, ])("Bitop [JIT] (%p)", ({ input, lua }) => { const options = { luaTarget: LuaTarget.LuaJIT, luaLibImport: LuaLibImportKind.None }; expect(util.transpileString(input, options)).toBe(lua); }); test.each([ - { input: "~a", lua: "bit32.bnot(a);" }, - { input: "a&b", lua: "bit32.band(a, b);" }, - { input: "a&=b", lua: "a = bit32.band(a, b);" }, - { input: "a|b", lua: "bit32.bor(a, b);" }, - { input: "a|=b", lua: "a = bit32.bor(a, b);" }, - { input: "a^b", lua: "bit32.bxor(a, b);" }, - { input: "a^=b", lua: "a = bit32.bxor(a, b);" }, - { input: "a<>b", lua: "bit32.arshift(a, b);" }, - { input: "a>>=b", lua: "a = bit32.arshift(a, b);" }, - { input: "a>>>b", lua: "bit32.rshift(a, b);" }, - { input: "a>>>=b", lua: "a = bit32.rshift(a, b);" }, + { input: "~a", lua: "bit32.bnot(a)" }, + { input: "a&b", lua: "bit32.band(a, b)" }, + { input: "a&=b", lua: "a = bit32.band(a, b)" }, + { input: "a|b", lua: "bit32.bor(a, b)" }, + { input: "a|=b", lua: "a = bit32.bor(a, b)" }, + { input: "a^b", lua: "bit32.bxor(a, b)" }, + { input: "a^=b", lua: "a = bit32.bxor(a, b)" }, + { input: "a<>b", lua: "bit32.arshift(a, b)" }, + { input: "a>>=b", lua: "a = bit32.arshift(a, b)" }, + { input: "a>>>b", lua: "bit32.rshift(a, b)" }, + { input: "a>>>=b", lua: "a = bit32.rshift(a, b)" }, ])("Bitop [5.2] (%p)", ({ input, lua }) => { const options = { luaTarget: LuaTarget.Lua52, luaLibImport: LuaLibImportKind.None }; expect(util.transpileString(input, options)).toBe(lua); }); test.each([ - { input: "~a", lua: "~a;" }, - { input: "a&b", lua: "a & b;" }, - { input: "a&=b", lua: "a = a & b;" }, - { input: "a|b", lua: "a | b;" }, - { input: "a|=b", lua: "a = a | b;" }, - { input: "a^b", lua: "a ~ b;" }, - { input: "a^=b", lua: "a = a ~ b;" }, - { input: "a<>>b", lua: "a >> b;" }, - { input: "a>>>=b", lua: "a = a >> b;" }, + { input: "~a", lua: "~a" }, + { input: "a&b", lua: "a & b" }, + { input: "a&=b", lua: "a = a & b" }, + { input: "a|b", lua: "a | b" }, + { input: "a|=b", lua: "a = a | b" }, + { input: "a^b", lua: "a ~ b" }, + { input: "a^=b", lua: "a = a ~ b" }, + { input: "a<>>b", lua: "a >> b" }, + { input: "a>>>=b", lua: "a = a >> b" }, ])("Bitop [5.3] (%p)", ({ input, lua }) => { const options = { luaTarget: LuaTarget.Lua53, luaLibImport: LuaLibImportKind.None }; expect(util.transpileString(input, options)).toBe(lua); @@ -176,12 +176,12 @@ test.each(["a>>b", "a>>=b"])("Unsupported bitop 5.3 (%p)", input => { }); test.each([ - { input: "1+1", lua: "1 + 1;" }, - { input: "-1+1", lua: "-1 + 1;" }, - { input: "1*30+4", lua: "1 * 30 + 4;" }, - { input: "1*(3+4)", lua: "1 * (3 + 4);" }, - { input: "1*(3+4*2)", lua: "1 * (3 + 4 * 2);" }, - { input: "10-(4+5)", lua: "10 - (4 + 5);" }, + { input: "1+1", lua: "1 + 1" }, + { input: "-1+1", lua: "-1 + 1" }, + { input: "1*30+4", lua: "1 * 30 + 4" }, + { input: "1*(3+4)", lua: "1 * (3 + 4)" }, + { input: "1*(3+4*2)", lua: "1 * (3 + 4 * 2)" }, + { input: "10-(4+5)", lua: "10 - (4 + 5)" }, ])("Binary expressions ordering parentheses (%p)", ({ input, lua }) => { expect(util.transpileString(input)).toBe(lua); }); @@ -208,11 +208,11 @@ test("Binary Comma Statement in For Loop", () => { }); test("Null Expression", () => { - expect(util.transpileString("null")).toBe("nil;"); + expect(util.transpileString("null")).toBe("nil"); }); test("Undefined Expression", () => { - expect(util.transpileString("undefined")).toBe("nil;"); + expect(util.transpileString("undefined")).toBe("nil"); }); test.each([ diff --git a/test/unit/json.spec.ts b/test/unit/json.spec.ts index db16d75ae..079188cba 100644 --- a/test/unit/json.spec.ts +++ b/test/unit/json.spec.ts @@ -13,7 +13,7 @@ test.each(["0", '""', "[]", '[1, "2", []]', '{ "a": "b" }', '{ "a": { "b": "c" } json => { const lua = util .transpileString(json, jsonOptions, false, "file.json") - .replace(/^return ([\s\S]+);$/, "return JSONStringify($1);"); + .replace(/^return ([\s\S]+)$/, "return JSONStringify($1)"); const result = util.executeLua(lua); expect(JSON.parse(result)).toEqual(JSON.parse(json)); diff --git a/test/unit/math.spec.ts b/test/unit/math.spec.ts index f44429f7f..7017df844 100644 --- a/test/unit/math.spec.ts +++ b/test/unit/math.spec.ts @@ -1,15 +1,15 @@ import * as util from "../util"; test.each([ - { inp: "Math.cos()", expected: "math.cos();" }, - { inp: "Math.sin()", expected: "math.sin();" }, - { inp: "Math.min()", expected: "math.min();" }, - { inp: "Math.atan2(2, 3)", expected: "math.atan(2 / 3);" }, - { inp: "Math.log2(3)", expected: `(math.log(3) / ${Math.LN2});` }, - { inp: "Math.log10(3)", expected: `(math.log(3) / ${Math.LN10});` }, - { inp: "Math.log1p(3)", expected: "math.log(1 + 3);" }, - { inp: "Math.round(3.3)", expected: "math.floor(3.3 + 0.5);" }, - { inp: "Math.PI", expected: "math.pi;" }, + { inp: "Math.cos()", expected: "math.cos()" }, + { inp: "Math.sin()", expected: "math.sin()" }, + { inp: "Math.min()", expected: "math.min()" }, + { inp: "Math.atan2(2, 3)", expected: "math.atan(2 / 3)" }, + { inp: "Math.log2(3)", expected: `(math.log(3) / ${Math.LN2})` }, + { inp: "Math.log10(3)", expected: `(math.log(3) / ${Math.LN10})` }, + { inp: "Math.log1p(3)", expected: "math.log(1 + 3)" }, + { inp: "Math.round(3.3)", expected: "math.floor(3.3 + 0.5)" }, + { inp: "Math.PI", expected: "math.pi" }, ])("Math (%p)", ({ inp, expected }) => { const lua = util.transpileString(inp); diff --git a/test/unit/modules.spec.ts b/test/unit/modules.spec.ts index c02f052de..1e5a05ec3 100644 --- a/test/unit/modules.spec.ts +++ b/test/unit/modules.spec.ts @@ -23,7 +23,7 @@ test("lualibRequireAlways", () => { luaTarget: LuaTarget.LuaJIT, }); - expect(lua).toBe(`require("lualib_bundle");`); + expect(lua).toBe(`require("lualib_bundle")`); }); test("Non-exported module", () => { diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index 3cc8ad2c2..a37ab815d 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -2,12 +2,12 @@ import * as util from "../util"; const fs = require("fs"); test.each([ - { inp: `{a:3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n};' }, - { inp: `{"a":3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n};' }, - { inp: `{["a"]:3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n};' }, - { inp: `{["a"+123]:3,b:"4"}`, out: '{\n ["a" .. 123] = 3,\n b = "4",\n};' }, - { inp: `{[myFunc()]:3,b:"4"}`, out: '{\n [myFunc(_G)] = 3,\n b = "4",\n};' }, - { inp: `{x}`, out: `{x = x};` }, + { inp: `{a:3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n}' }, + { inp: `{"a":3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n}' }, + { inp: `{["a"]:3,b:"4"}`, out: '{\n a = 3,\n b = "4",\n}' }, + { inp: `{["a"+123]:3,b:"4"}`, out: '{\n ["a" .. 123] = 3,\n b = "4",\n}' }, + { inp: `{[myFunc()]:3,b:"4"}`, out: '{\n [myFunc(_G)] = 3,\n b = "4",\n}' }, + { inp: `{x}`, out: `{x = x}` }, ])("Object Literal (%p)", ({ inp, out }) => { const lua = util.transpileString(`const myvar = ${inp};`); expect(lua).toBe(`local myvar = ${out}`); diff --git a/test/unit/semicolons.spec.ts b/test/unit/semicolons.spec.ts new file mode 100644 index 000000000..24145d24c --- /dev/null +++ b/test/unit/semicolons.spec.ts @@ -0,0 +1,20 @@ +import * as util from "../util"; + +test.each([ + "const a = 1; const b = a;", + "const a = 1; let b: number; b = a;", + "{}", + "function bar() {} bar();" +])( + "semicolon insertion (%p)", + leadingStatement => { + const code = ` + let result = ""; + function foo() { result = "foo"; } + ${leadingStatement} + (foo)(); + return result; + `; + expect(util.transpileAndExecute(code)).toEqual("foo"); + }, +); diff --git a/test/unit/spreadElement.spec.ts b/test/unit/spreadElement.spec.ts index 42559ec2a..af1a0fa87 100644 --- a/test/unit/spreadElement.spec.ts +++ b/test/unit/spreadElement.spec.ts @@ -15,23 +15,23 @@ test("Spread Element Lua 5.1", () => { // Cant test functional because our VM doesn't run on 5.1 const options = { luaTarget: LuaTarget.Lua51, luaLibImport: LuaLibImportKind.None }; const lua = util.transpileString(`[].push(...${JSON.stringify([1, 2, 3])});`, options); - expect(lua).toBe("__TS__ArrayPush({}, unpack({\n 1,\n 2,\n 3,\n}));"); + expect(lua).toBe("__TS__ArrayPush({}, unpack({\n 1,\n 2,\n 3,\n}))"); }); test("Spread Element Lua 5.2", () => { const options = { luaTarget: LuaTarget.Lua52, luaLibImport: LuaLibImportKind.None }; const lua = util.transpileString(`[...[0, 1, 2]]`, options); - expect(lua).toBe("{table.unpack({\n 0,\n 1,\n 2,\n})};"); + expect(lua).toBe("{table.unpack({\n 0,\n 1,\n 2,\n})}"); }); test("Spread Element Lua 5.3", () => { const options = { luaTarget: LuaTarget.Lua53, luaLibImport: LuaLibImportKind.None }; const lua = util.transpileString(`[...[0, 1, 2]]`, options); - expect(lua).toBe("{table.unpack({\n 0,\n 1,\n 2,\n})};"); + expect(lua).toBe("{table.unpack({\n 0,\n 1,\n 2,\n})}"); }); test("Spread Element Lua JIT", () => { const options = { luaTarget: "JiT" as LuaTarget, luaLibImport: LuaLibImportKind.None }; const lua = util.transpileString(`[...[0, 1, 2]]`, options); - expect(lua).toBe("{unpack({\n 0,\n 1,\n 2,\n})};"); + expect(lua).toBe("{unpack({\n 0,\n 1,\n 2,\n})}"); }); From 06774c992c95acd8c8dfe6621a41df81b2653250 Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Thu, 4 Apr 2019 06:50:16 -0600 Subject: [PATCH 2/3] fixed formatting in new test --- test/unit/semicolons.spec.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/test/unit/semicolons.spec.ts b/test/unit/semicolons.spec.ts index 24145d24c..7142fe548 100644 --- a/test/unit/semicolons.spec.ts +++ b/test/unit/semicolons.spec.ts @@ -1,20 +1,17 @@ import * as util from "../util"; test.each([ - "const a = 1; const b = a;", - "const a = 1; let b: number; b = a;", - "{}", - "function bar() {} bar();" -])( - "semicolon insertion (%p)", - leadingStatement => { - const code = ` + "const a = 1; const b = a;", + "const a = 1; let b: number; b = a;", + "{}", + "function bar() {} bar();", +])("semicolon insertion (%p)", leadingStatement => { + const code = ` let result = ""; function foo() { result = "foo"; } ${leadingStatement} (foo)(); return result; `; - expect(util.transpileAndExecute(code)).toEqual("foo"); - }, -); + expect(util.transpileAndExecute(code)).toEqual("foo"); +}); From ca1cf38c6345f83c08f5cb0b5ede5185d9ba6b0d Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Thu, 4 Apr 2019 15:51:27 -0600 Subject: [PATCH 3/3] added semicolons to manually printed statements which could be followed by parenthesis --- src/LuaPrinter.ts | 4 ++-- test/translation/__snapshots__/transformation.spec.ts.snap | 2 +- test/unit/modules.spec.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LuaPrinter.ts b/src/LuaPrinter.ts index d3024b66d..f4a68dcdc 100644 --- a/src/LuaPrinter.ts +++ b/src/LuaPrinter.ts @@ -107,7 +107,7 @@ export class LuaPrinter { const mapString = "{" + mapItems.join(",") + "}"; - return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString})`; + return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString});`; } private printImplementation( @@ -126,7 +126,7 @@ export class LuaPrinter { if ((this.options.luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) || this.options.luaLibImport === LuaLibImportKind.Always) { - header += `require("lualib_bundle")\n`; + header += `require("lualib_bundle");\n`; } // Inline lualib features else if (this.options.luaLibImport === LuaLibImportKind.Inline && luaLibFeatures.size > 0) diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index af64e199c..e6105793d 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -261,7 +261,7 @@ end" `; exports[`Transformation (getSetAccessors) 1`] = ` -"require(\\"lualib_bundle\\") +"require(\\"lualib_bundle\\"); MyClass = MyClass or {} MyClass.__index = MyClass MyClass.prototype = MyClass.prototype or {} diff --git a/test/unit/modules.spec.ts b/test/unit/modules.spec.ts index 1e5a05ec3..c02f052de 100644 --- a/test/unit/modules.spec.ts +++ b/test/unit/modules.spec.ts @@ -23,7 +23,7 @@ test("lualibRequireAlways", () => { luaTarget: LuaTarget.LuaJIT, }); - expect(lua).toBe(`require("lualib_bundle")`); + expect(lua).toBe(`require("lualib_bundle");`); }); test("Non-exported module", () => {