diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 06c49fe1f..b216b7e88 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -1490,29 +1490,9 @@ export abstract class LuaTranspiler { if (!node.body) { return ""; } let result = ""; - const identifier = node.name; - const methodName = this.transpileIdentifier(identifier); - const parameters = node.parameters; - const body = node.body; + const methodName = this.transpileIdentifier(node.name); - // Build parameter string - const paramNames: string[] = []; - - let spreadIdentifier = ""; - - // Only push parameter name to paramName array if it isn't a spread parameter - for (const param of parameters) { - const paramName = this.transpileIdentifier(param.name as ts.Identifier); - - // This parameter is a spread parameter (...param) - if (!param.dotDotDotToken) { - paramNames.push(paramName); - } else { - spreadIdentifier = paramName; - // Push the spread operator into the paramNames array - paramNames.push("..."); - } - } + const [paramNames, spreadIdentifier] = this.transpileParameters(node.parameters); let prefix = this.accessPrefix(node); @@ -1524,13 +1504,7 @@ export abstract class LuaTranspiler { result += this.indent + prefix + `function ${methodName}(${paramNames.join(",")})\n`; this.pushIndent(); - - // Push spread operator here - if (spreadIdentifier !== "") { - result += this.indent + `local ${spreadIdentifier} = { ... }\n`; - } - - result += this.transpileBlock(body); + result += this.transpileFunctionBody(node.parameters, node.body, spreadIdentifier); this.popIndent(); // Close function block @@ -1541,21 +1515,10 @@ export abstract class LuaTranspiler { return result; } - public transpileMethodDeclaration(node: ts.MethodDeclaration, callPath: string): string { - // Don't transpile methods without body (overload declarations) - if (!node.body) { return ""; } - - let result = ""; - const identifier = node.name as ts.Identifier; - let methodName = this.transpileIdentifier(identifier); - if (methodName === "toString") { - methodName = "__tostring"; - } - const parameters = node.parameters; - const body = node.body; - + // Transpile a list of parameters, returns a list of transpiled parameters and an optional spread identifier + public transpileParameters(parameters: ts.NodeArray): [string[], string] { // Build parameter string - const paramNames: string[] = ["self"]; + const paramNames: string[] = []; let spreadIdentifier = ""; @@ -1572,21 +1535,49 @@ export abstract class LuaTranspiler { paramNames.push("..."); } } - // Parameters with default values - const defaultValueParams = node.parameters.filter(declaration => declaration.initializer !== undefined); - // Build function header - result += this.indent + `function ${callPath}${methodName}(${paramNames.join(",")})\n`; + return [paramNames, spreadIdentifier]; + } - this.pushIndent(); + public transpileFunctionBody(parameters: ts.NodeArray, + body: ts.Block, + spreadIdentifier: string = "" + ): string { + let result = ""; + + // Add default parameters + const defaultValueParams = parameters.filter(declaration => declaration.initializer !== undefined); + result += this.transpileParameterDefaultValues(defaultValueParams); // Push spread operator here if (spreadIdentifier !== "") { result += this.indent + `local ${spreadIdentifier} = { ... }\n`; } - result += this.transpileParameterDefaultValues(defaultValueParams); result += this.transpileBlock(body); + + return result; + } + + public transpileMethodDeclaration(node: ts.MethodDeclaration, callPath: string): string { + // Don't transpile methods without body (overload declarations) + if (!node.body) { return ""; } + + let result = ""; + let methodName = this.transpileIdentifier(node.name as ts.Identifier); + if (methodName === "toString") { + methodName = "__tostring"; + } + + const [paramNames, spreadIdentifier] = this.transpileParameters(node.parameters); + + const selfParamNames = ["self"].concat(paramNames); + + // Build function header + result += this.indent + `function ${callPath}${methodName}(${selfParamNames.join(",")})\n`; + + this.pushIndent(); + result += this.transpileFunctionBody(node.parameters, node.body, spreadIdentifier); this.popIndent(); // Close function block diff --git a/test/unit/functions.spec.ts b/test/unit/functions.spec.ts index f370cbd83..1a236dd47 100644 --- a/test/unit/functions.spec.ts +++ b/test/unit/functions.spec.ts @@ -97,6 +97,19 @@ export class FunctionTests { Expect(result).toBe(3); } + @Test("Function default parameter") + public functionDefaultParameter(): void { + // Transpile + const lua = util.transpileString(`function abc(defaultParam: string = "abc") { return defaultParam; }\n + return abc() + abc("def");`); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe("abcdef"); + } + @TestCase([], 7) @TestCase([5], 9) @TestCase([1, 2], 3)