Skip to content

Commit 8f60f9f

Browse files
authored
Allow MultiReturn to be typed as any (TypeScriptToLua#1327)
1 parent e545192 commit 8f60f9f

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

src/transformation/visitors/language-extensions/multi.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ export function isMultiReturnType(type: ts.Type): boolean {
1414
}
1515

1616
export function canBeMultiReturnType(type: ts.Type): boolean {
17-
return isMultiReturnType(type) || (type.isUnion() && type.types.some(t => canBeMultiReturnType(t)));
17+
return (
18+
(type.flags & ts.TypeFlags.Any) !== 0 ||
19+
isMultiReturnType(type) ||
20+
(type.isUnion() && type.types.some(t => canBeMultiReturnType(t)))
21+
);
1822
}
1923

2024
export function isMultiFunctionCall(context: TransformationContext, expression: ts.CallExpression): boolean {

src/transformation/visitors/return.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,37 @@ function transformExpressionsInReturn(
2323
): lua.Expression[] {
2424
const expressionType = context.checker.getTypeAtLocation(node);
2525

26-
if (ts.isCallExpression(node)) {
26+
// skip type assertions
27+
// don't skip parenthesis as it may arise confusion with lua behavior (where parenthesis are significant)
28+
const innerNode = ts.skipOuterExpressions(node, ts.OuterExpressionKinds.Assertions);
29+
30+
if (ts.isCallExpression(innerNode)) {
2731
// $multi(...)
28-
if (isMultiFunctionCall(context, node)) {
32+
if (isMultiFunctionCall(context, innerNode)) {
2933
// Don't allow $multi to be implicitly cast to something other than LuaMultiReturn
3034
const type = context.checker.getContextualType(node);
3135
if (type && !canBeMultiReturnType(type)) {
32-
context.diagnostics.push(invalidMultiFunctionReturnType(node));
36+
context.diagnostics.push(invalidMultiFunctionReturnType(innerNode));
3337
}
3438

35-
let returnValues = transformArguments(context, node.arguments);
39+
let returnValues = transformArguments(context, innerNode.arguments);
3640
if (insideTryCatch) {
3741
returnValues = [wrapInTable(...returnValues)]; // Wrap results when returning inside try/catch
3842
}
3943
return returnValues;
4044
}
4145

4246
// Force-wrap LuaMultiReturn when returning inside try/catch
43-
if (insideTryCatch && returnsMultiType(context, node) && !shouldMultiReturnCallBeWrapped(context, node)) {
47+
if (
48+
insideTryCatch &&
49+
returnsMultiType(context, innerNode) &&
50+
!shouldMultiReturnCallBeWrapped(context, innerNode)
51+
) {
4452
return [wrapInTable(context.transformExpression(node))];
4553
}
46-
} else if (isInMultiReturnFunction(context, node) && isMultiReturnType(expressionType)) {
54+
} else if (isInMultiReturnFunction(context, innerNode) && isMultiReturnType(expressionType)) {
4755
// Unpack objects typed as LuaMultiReturn
48-
return [createUnpackCall(context, context.transformExpression(node), node)];
56+
return [createUnpackCall(context, context.transformExpression(innerNode), innerNode)];
4957
}
5058

5159
return [context.transformExpression(node)];

test/unit/language-extensions/multi.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,36 @@ test("forward $multi call in ArrowFunction body", () => {
184184
.expectToEqual([1, 2]);
185185
});
186186

187+
test("$multi call in function typed as any", () => {
188+
util.testFunction`
189+
function foo(): any { return $multi(1, 2); }
190+
return foo()
191+
`
192+
.withLanguageExtensions()
193+
.expectToHaveNoDiagnostics()
194+
.expectToEqual(1);
195+
});
196+
197+
test("$multi call cast to any", () => {
198+
util.testFunction`
199+
function foo() { return $multi(1, 2) as any; }
200+
return foo()
201+
`
202+
.withLanguageExtensions()
203+
.expectToHaveNoDiagnostics()
204+
.expectToEqual(1);
205+
});
206+
207+
test("$multi call cast to MultiReturn type", () => {
208+
util.testFunction`
209+
function foo() { return $multi(1, 2) as unknown as LuaMultiReturn<number[]>; }
210+
return foo()
211+
`
212+
.withLanguageExtensions()
213+
.expectToHaveNoDiagnostics()
214+
.expectToEqual(1);
215+
});
216+
187217
test.each(["0", "i"])("allow LuaMultiReturn numeric access (%s)", expression => {
188218
util.testFunction`
189219
${multiFunction}

0 commit comments

Comments
 (0)