diff --git a/src/transpilation/transformers.ts b/src/transpilation/transformers.ts index e043704b8..7b5aacddd 100644 --- a/src/transpilation/transformers.ts +++ b/src/transpilation/transformers.ts @@ -36,6 +36,7 @@ export function getTransformers( ...(transformersFromOptions.after ?? []), ...(customTransformers.after ?? []), + stripParenthesisExpressionsTransformer, luaTransformer, ], }; @@ -53,6 +54,30 @@ export const noImplicitSelfTransformer: ts.TransformerFactory = context => sourceFile => { + // Remove parenthesis expressions before transforming to Lua, so transpiler is not hindered by extra ParenthesizedExpression nodes + function unwrapParentheses(node: ts.Expression) { + while (ts.isParenthesizedExpression(node)) { + node = node.expression; + } + return node; + } + function visit(node: ts.Node): ts.Node { + // For now only call expressions strip their expressions of parentheses, there could be more cases where this is required + if (ts.isCallExpression(node)) { + return ts.factory.updateCallExpression( + node, + unwrapParentheses(node.expression), + node.typeArguments, + node.arguments + ); + } + + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(sourceFile, visit); +}; + function loadTransformersFromOptions(program: ts.Program, diagnostics: ts.Diagnostic[]): ts.CustomTransformers { const customTransformers: Required = { before: [], diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index f4c14df34..f9ab4fe61 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -761,3 +761,41 @@ test("constructor class name available with constructor", () => { .setReturnExport("className") .expectToEqual("MyClass"); }); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/959 +test("methods accessed via this index pass correct context", () => { + util.testModule` + class Example { + baz = 3; + foo() { + this["bar"]() + } + + bar() { + return this.baz; + } + } + + const inst = new Example(); + export const result = inst.foo(); + `.expectToMatchJsResult(); +}); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/959 +test.each(['(this["bar"])', '((((this["bar"]))))'])("methods in parentheses pass correct context %s", callPath => { + util.testModule` + class Example { + baz = 3; + foo() { + ${callPath}() + } + + bar() { + return this.baz; + } + } + + const inst = new Example(); + export const result = inst.foo(); + `.expectToMatchJsResult(); +});