diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 0df3f10ed..86f680583 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -2396,6 +2396,10 @@ export class LuaTransformer { return this.transformBinaryBitOperation(tsOriginal, left, right, operator); default: const luaOperator = this.transformBinaryOperator(operator, tsOriginal); + if (luaOperator === tstl.SyntaxKind.ConcatOperator) { + left = this.wrapInToStringForConcat(left); + right = this.wrapInToStringForConcat(right); + } return tstl.createBinaryExpression(left, right, luaOperator, tsOriginal); } } @@ -4091,8 +4095,7 @@ export class LuaTransformer { } expression.templateSpans.forEach(span => { - const expr = this.transformExpression(span.expression); - parts.push(tstl.createCallExpression(tstl.createIdentifier("tostring"), [expr])); + parts.push(this.wrapInToStringForConcat(this.transformExpression(span.expression))); const text = tsHelper.escapeString(span.literal.text); if (text.length > 0) { @@ -4487,7 +4490,13 @@ export class LuaTransformer { private wrapInFunctionCall(expression: tstl.Expression): tstl.FunctionExpression { const returnStatement = tstl.createReturnStatement([expression]); - return tstl.createFunctionExpression(tstl.createBlock([returnStatement])); + return tstl.createFunctionExpression( + tstl.createBlock([returnStatement]), + undefined, + undefined, + undefined, + tstl.FunctionExpressionFlags.Inline + ); } private wrapInTable(...expressions: tstl.Expression[]): tstl.ParenthesizedExpression { @@ -4495,6 +4504,16 @@ export class LuaTransformer { return tstl.createParenthesizedExpression(tstl.createTableExpression(fields)); } + private wrapInToStringForConcat(expression: tstl.Expression): tstl.Expression { + if (tstl.isStringLiteral(expression) + || tstl.isNumericLiteral(expression) + || (tstl.isBinaryExpression(expression) && expression.operator === tstl.SyntaxKind.ConcatOperator)) + { + return expression; + } + return tstl.createCallExpression(tstl.createIdentifier("tostring"), [expression]); + } + private expressionPlusOne(expression: tstl.Expression): tstl.BinaryExpression { if (tstl.isBinaryExpression(expression)) { expression = tstl.createParenthesizedExpression(expression); diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index b0baaa3dd..2a8c00c78 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -14,7 +14,7 @@ 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 nonEmptyTemplateString = \\"Level 0: \\\\n\\\\t \\" .. \\"Level 1: \\\\n\\\\t\\\\t \\" .. \\"Level 3: \\\\n\\\\t\\\\t\\\\t \\" .. \\"Last level \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\";" `; exports[`Transformation (classExtension1) 1`] = ` diff --git a/test/unit/string.spec.ts b/test/unit/string.spec.ts index 2b7cd4362..dfb494c62 100644 --- a/test/unit/string.spec.ts +++ b/test/unit/string.spec.ts @@ -34,14 +34,41 @@ test.each([ { a: "test", b: "hello", c: "bye" }, { a: "test", b: 42, c: "bye" }, { a: "test", b: 42, c: 12 }, + { a: "test", b: 42, c: true }, + { a: false, b: 42, c: 12 }, ])("Template Strings (%p)", ({ a, b, c }) => { - const a1 = typeof a === "string" ? "'" + a + "'" : a; - const b1 = typeof b === "string" ? "'" + b + "'" : b; - const c1 = typeof c === "string" ? "'" + c + "'" : c; + const a1 = typeof a === "string" ? `'${a}'` : a; + const b1 = typeof b === "string" ? `'${b}'` : b; + const c1 = typeof c === "string" ? `'${c}'` : c; - const result = util.transpileAndExecute( - "let a = " + a1 + "; let b = " + b1 + "; let c = " + c1 + "; return `${a} ${b} test ${c}`;", - ); + const result = util.transpileAndExecute(` + let a = ${a1}; + let b = ${b1}; + let c = ${c1}; + return \`${a} ${b} test ${c}\`; + `); + + expect(result).toBe(`${a} ${b} test ${c}`); +}); + +test.each([ + { a: 12, b: 23, c: 43 }, + { a: "test", b: "hello", c: "bye" }, + { a: "test", b: 42, c: "bye" }, + { a: "test", b: 42, c: 12 }, + { a: "test", b: 42, c: true }, + { a: false, b: 42, c: 12 }, +])("String Concat Operator (%p)", ({ a, b, c }) => { + const a1 = typeof a === "string" ? `'${a}'` : a; + const b1 = typeof b === "string" ? `'${b}'` : b; + const c1 = typeof c === "string" ? `'${c}'` : c; + + const result = util.transpileAndExecute(` + let a = ${a1}; + let b = ${b1}; + let c = ${c1}; + return a + " " + b + " test " + c; + `); expect(result).toBe(`${a} ${b} test ${c}`); });