diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index ab7587e97..66bb194d5 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3162,6 +3162,8 @@ export class LuaTransformer { // If the function being called is of type owner.func, get the type of owner const ownerType = this.checker.getTypeAtLocation(node.expression.expression); + const signature = this.checker.getResolvedSignature(node); + if (tsHelper.isStandardLibraryType(ownerType, "Math", this.program)) { return this.transformMathCallExpression(node); } @@ -3173,7 +3175,7 @@ export class LuaTransformer { if (tsHelper.isStandardLibraryType(ownerType, "StringConstructor", this.program)) { return tstl.createCallExpression( this.transformStringExpression(node.expression.name), - this.transformArguments(node.arguments), + this.transformArguments(node.arguments, signature), node ); } @@ -3207,8 +3209,6 @@ export class LuaTransformer { return this.transformFunctionCallExpression(node); } - const signature = this.checker.getResolvedSignature(node); - // Get the type of the function if (node.expression.expression.kind === ts.SyntaxKind.SuperKeyword) { // Super calls take the format of super.call(self,...) @@ -3292,7 +3292,8 @@ export class LuaTransformer { public transformArguments( params: ts.NodeArray, - sig?: ts.Signature, context?: T + sig?: ts.Signature, + context?: T ): tstl.Expression[] { const parameters: tstl.Expression[] = []; @@ -3387,7 +3388,8 @@ export class LuaTransformer { // Transpile a Math._ property public transformMathCallExpression(node: ts.CallExpression): tstl.Expression { const expression = node.expression as ts.PropertyAccessExpression; - const params = this.transformArguments(node.arguments); + const signature = this.checker.getResolvedSignature(node); + const params = this.transformArguments(node.arguments, signature); const expressionName = expression.name.escapedText as string; switch (expressionName) { // math.tan(x / y) @@ -3546,7 +3548,8 @@ export class LuaTransformer { public transformStringCallExpression(node: ts.CallExpression): tstl.Expression { const expression = node.expression as ts.PropertyAccessExpression; - const params = this.transformArguments(node.arguments); + const signature = this.checker.getResolvedSignature(node); + const params = this.transformArguments(node.arguments, signature); const caller = this.transformExpression(expression.expression); const expressionName = expression.name.escapedText as string; @@ -3690,6 +3693,7 @@ export class LuaTransformer { // Transpile an Object._ property public transformObjectCallExpression(expression: ts.CallExpression): ExpressionVisitResult { const method = expression.expression as ts.PropertyAccessExpression; + const signature = this.checker.getResolvedSignature(expression); const parameters = this.transformArguments(expression.arguments); const caller = this.transformExpression(expression.expression); const methodName = method.name.escapedText; @@ -3715,6 +3719,7 @@ export class LuaTransformer { public transformConsoleCallExpression(expression: ts.CallExpression): ExpressionVisitResult { const method = expression.expression as ts.PropertyAccessExpression; const methodName = method.name.escapedText; + const signature = this.checker.getResolvedSignature(expression); switch (methodName) { case "log": @@ -3725,7 +3730,7 @@ export class LuaTransformer { tstl.createTableIndexExpression( tstl.createIdentifier("string"), tstl.createStringLiteral("format")), - this.transformArguments(expression.arguments) + this.transformArguments(expression.arguments, signature) ); return tstl.createCallExpression( tstl.createIdentifier("print"), @@ -3735,10 +3740,10 @@ export class LuaTransformer { // print([arguments]) return tstl.createCallExpression( tstl.createIdentifier("print"), - this.transformArguments(expression.arguments) + this.transformArguments(expression.arguments, signature) ); case "assert": - const args = this.transformArguments(expression.arguments); + const args = this.transformArguments(expression.arguments, signature); if (expression.arguments.length > 1 && this.isStringFormatTemplate(expression.arguments[1])) { // assert([condition], string.format([arguments])) @@ -3766,7 +3771,7 @@ export class LuaTransformer { tstl.createTableIndexExpression( tstl.createIdentifier("string"), tstl.createStringLiteral("format")), - this.transformArguments(expression.arguments) + this.transformArguments(expression.arguments, signature) ); const debugTracebackCall = tstl.createCallExpression( tstl.createTableIndexExpression( @@ -3784,7 +3789,7 @@ export class LuaTransformer { tstl.createTableIndexExpression( tstl.createIdentifier("debug"), tstl.createStringLiteral("traceback")), - this.transformArguments(expression.arguments) + this.transformArguments(expression.arguments, signature) ); return tstl.createCallExpression( tstl.createIdentifier("print"), @@ -3806,7 +3811,8 @@ export class LuaTransformer { // Transpile a Symbol._ property public transformSymbolCallExpression(expression: ts.CallExpression): tstl.CallExpression { const method = expression.expression as ts.PropertyAccessExpression; - const parameters = this.transformArguments(expression.arguments); + const signature = this.checker.getResolvedSignature(expression); + const parameters = this.transformArguments(expression.arguments, signature); const methodName = method.name.escapedText; switch (methodName) { @@ -3827,7 +3833,8 @@ export class LuaTransformer { public transformArrayCallExpression(node: ts.CallExpression): tstl.CallExpression { const expression = node.expression as ts.PropertyAccessExpression; - const params = this.transformArguments(node.arguments); + const signature = this.checker.getResolvedSignature(node); + const params = this.transformArguments(node.arguments, signature); const caller = this.transformExpression(expression.expression); const expressionName = expression.name.escapedText; switch (expressionName) { @@ -3888,7 +3895,8 @@ export class LuaTransformer { if (tsHelper.getFunctionContextType(callerType, this.checker, this.program) === ContextType.Void) { throw TSTLErrors.UnsupportedSelfFunctionConversion(node); } - const params = this.transformArguments(node.arguments); + const signature = this.checker.getResolvedSignature(node); + const params = this.transformArguments(node.arguments, signature); const caller = this.transformExpression(expression.expression); const expressionName = expression.name.escapedText; switch (expressionName) { diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index 257dc2b2d..5b27f33d1 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -663,6 +663,29 @@ export class AssignmentTests { Expect(() => util.transpileString(code, undefined, false)).toThrowError(TranspileError, err.message); } + @Test("Valid lua lib function argument") + public validLuaLibFunctionArgument(): void { + const code = + `let result = ""; + function foo(this: any, value: string) { result += value; } + const a = ['foo', 'bar']; + a.forEach(foo); + return result;`; + Expect(util.transpileAndExecute(code)).toBe("foobar"); + } + + @Test("Invalid lua lib function argument") + public invalidLuaLibFunctionArgument(testFunction: TestFunction, functionType: string, isSelfConversion: boolean) + : void + { + const code = + `declare function foo(this: void, value: string): void; + declare const a: string[]; + a.forEach(foo);`; + const err = TSTLErrors.UnsupportedSelfFunctionConversion(undefined, "callbackfn"); + Expect(() => util.transpileString(code, undefined, false)).toThrowError(TranspileError, err.message); + } + @TestCases(validTestFunctionCasts) @Test("Valid function argument with cast") public validFunctionArgumentWithCast(testFunction: TestFunction, castedFunction: string): void { diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index e0d2df5b0..aa14e0404 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -493,6 +493,7 @@ export class ExpressionTests { const transformer = util.makeTestTransformer(); const mockNode: any = { + kind: ts.SyntaxKind.CallExpression, arguments: [], caller: ts.createLiteral(false), expression: {name: ts.createIdentifier("unknownFunction"), expression: ts.createLiteral(false)},