From 26ee6d99c72255250400b227e3b3deabf5a0f0fc Mon Sep 17 00:00:00 2001 From: Perryvw Date: Fri, 8 Nov 2024 18:18:00 +0100 Subject: [PATCH 1/2] Fix LuaMultiReturn not being recognized inside more complicated iterable types --- package-lock.json | 2 +- .../visitors/language-extensions/iterable.ts | 10 +++++-- test/unit/language-extensions/multi.spec.ts | 28 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f76e67fd3..bbb009d47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "typescript-to-lua", - "version": "1.26.2", + "version": "1.27.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/src/transformation/visitors/language-extensions/iterable.ts b/src/transformation/visitors/language-extensions/iterable.ts index 5d96f409e..0ad600558 100644 --- a/src/transformation/visitors/language-extensions/iterable.ts +++ b/src/transformation/visitors/language-extensions/iterable.ts @@ -62,8 +62,14 @@ export function transformForOfIterableStatement( statement: ts.ForOfStatement, block: lua.Block ): lua.Statement { - const type = context.checker.getTypeAtLocation(statement.expression); - if (type.aliasTypeArguments?.length === 2 && isMultiReturnType(type.aliasTypeArguments[0])) { + const hasBindingPattern = + ts.isVariableDeclarationList(statement.initializer) && + statement.initializer.declarations.length > 0 && + ts.isArrayBindingPattern(statement.initializer.declarations[0].name); + const bindingPatternType = + hasBindingPattern && context.checker.getTypeAtLocation(statement.initializer.declarations[0].name); + + if (bindingPatternType && isMultiReturnType(bindingPatternType)) { const luaIterator = context.transformExpression(statement.expression); return transformForOfMultiIterableStatement( context, diff --git a/test/unit/language-extensions/multi.spec.ts b/test/unit/language-extensions/multi.spec.ts index 8282ef4fc..72b330887 100644 --- a/test/unit/language-extensions/multi.spec.ts +++ b/test/unit/language-extensions/multi.spec.ts @@ -373,3 +373,31 @@ describe("LuaMultiReturn returns all values even when indexed with [0] #1411", ( .expectToEqual(1); }); }); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1591 +test("LuaMultiReturn in LuaIterable (#1591)", () => { + const lua = util.testModule` + type IterableAlias = LuaIterable>; + + declare const iterable: IterableAlias; + + for (const [a, b] of iterable) {} + ` + .withLanguageExtensions() + .getMainLuaCodeChunk(); + + expect(lua).toContain("a, b"); +}); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1591 +test("LuaMultiReturn in LuaIterable intersection (#1591)", () => { + const lua = util.testModule` + declare function iterator(): { a: string } & LuaIterable>; + + for (const [a, b] of iterator()) {} + ` + .withLanguageExtensions() + .getMainLuaCodeChunk(); + + expect(lua).toContain("a, b"); +}); From f1d9f99fcab1cab246aa14b09864f890f1663620 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Fri, 8 Nov 2024 19:08:03 +0100 Subject: [PATCH 2/2] Fix it in a way that doesn't break other stuff --- .../visitors/language-extensions/iterable.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/transformation/visitors/language-extensions/iterable.ts b/src/transformation/visitors/language-extensions/iterable.ts index 0ad600558..ee1ded7be 100644 --- a/src/transformation/visitors/language-extensions/iterable.ts +++ b/src/transformation/visitors/language-extensions/iterable.ts @@ -62,14 +62,13 @@ export function transformForOfIterableStatement( statement: ts.ForOfStatement, block: lua.Block ): lua.Statement { - const hasBindingPattern = - ts.isVariableDeclarationList(statement.initializer) && - statement.initializer.declarations.length > 0 && - ts.isArrayBindingPattern(statement.initializer.declarations[0].name); - const bindingPatternType = - hasBindingPattern && context.checker.getTypeAtLocation(statement.initializer.declarations[0].name); + const iteratedExpressionType = context.checker.getTypeAtLocation(statement.expression); + const iterableType = + iteratedExpressionType.isIntersection() && + iteratedExpressionType.types.find(t => t.symbol.escapedName === "Iterable"); + const iterableTypeArguments = (iterableType as ts.TypeReference)?.typeArguments; - if (bindingPatternType && isMultiReturnType(bindingPatternType)) { + if (iterableTypeArguments && iterableTypeArguments.length > 0 && isMultiReturnType(iterableTypeArguments[0])) { const luaIterator = context.transformExpression(statement.expression); return transformForOfMultiIterableStatement( context,