Skip to content

Commit b7d1ec0

Browse files
committed
Drop support for VariableDeclarations, support only ReturnStatements
1 parent 19b735c commit b7d1ec0

File tree

6 files changed

+24
-221
lines changed

6 files changed

+24
-221
lines changed

src/transformation/utils/diagnostics.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -130,27 +130,5 @@ export const unsupportedVarDeclaration = createDiagnosticFactory(
130130
export const unknownHelperKind = createDiagnosticFactory((kind: string) => `Unknown helper kind "${kind}".`);
131131

132132
export const unsupportedMultiHelperFunctionPosition = createDiagnosticFactory(
133-
"The $multi() function cannot be used here."
134-
);
135-
136-
export const invalidMultiReturnToNonArrayBindingPattern = createDiagnosticFactory(
137-
"Expected an array destructuring pattern."
138-
);
139-
140-
export const invalidMultiReturnToNonArrayLiteral = createDiagnosticFactory("Expected an array literal.");
141-
142-
export const invalidMultiReturnToEmptyPatternOrArrayLiteral = createDiagnosticFactory(
143-
"There must be one or more elements specified here."
144-
);
145-
146-
export const invalidMultiReturnArrayBindingPatternElementInitializer = createDiagnosticFactory(
147-
"This array binding pattern cannot have initializers."
148-
);
149-
150-
export const invalidMultiReturnArrayLiteralElementInitializer = createDiagnosticFactory(
151-
"This array literal pattern cannot have initializers."
152-
);
153-
154-
export const unsupportedMultiFunctionAssignment = createDiagnosticFactory(
155-
"Omitted expressions and BindingElements are expected here."
133+
"The $multi() function can only be used in a return statement."
156134
);

src/transformation/visitors/expression-statement.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,8 @@ import { transformBinaryExpressionStatement } from "./binary-expression";
55
import { transformDeleteExpressionStatement } from "./delete";
66
import { transformLuaTableExpressionStatement } from "./lua-table";
77
import { transformUnaryExpressionStatement } from "./unary-expression";
8-
import { transformMultiHelperDestructuringAssignmentStatement } from "./helpers/multi";
98

109
export const transformExpressionStatement: FunctionVisitor<ts.ExpressionStatement> = (node, context) => {
11-
const multiResult = transformMultiHelperDestructuringAssignmentStatement(context, node);
12-
if (multiResult) {
13-
return multiResult;
14-
}
15-
1610
const luaTableResult = transformLuaTableExpressionStatement(context, node);
1711
if (luaTableResult) {
1812
return luaTableResult;

src/transformation/visitors/helpers/multi.ts

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,8 @@ import * as lua from "../../../LuaAST";
33
import * as helpers from "../../utils/helpers";
44
import { isNonNull } from "../../../utils";
55
import { TransformationContext } from "../../context";
6-
import { transformAssignmentLeftHandSideExpression } from "../binary-expression/assignments";
7-
import { transformIdentifier } from "../identifier";
86
import { transformArguments } from "../call";
9-
import { getDependenciesOfSymbol, createExportedIdentifier } from "../../utils/export";
10-
import { createLocalOrExportedOrGlobalDeclaration } from "../../utils/lua-ast";
11-
import {
12-
invalidMultiReturnArrayBindingPatternElementInitializer,
13-
invalidMultiReturnArrayLiteralElementInitializer,
14-
invalidMultiReturnToEmptyPatternOrArrayLiteral,
15-
invalidMultiReturnToNonArrayBindingPattern,
16-
invalidMultiReturnToNonArrayLiteral,
17-
unsupportedMultiFunctionAssignment,
18-
unsupportedMultiHelperFunctionPosition,
19-
} from "../../../transformation/utils/diagnostics";
7+
import { unsupportedMultiHelperFunctionPosition } from "../../../transformation/utils/diagnostics";
208

219
const isMultiHelperDeclaration = (context: TransformationContext) => (declaration: ts.Declaration): boolean =>
2210
helpers.getHelperFileKind(context, declaration.getSourceFile()) === helpers.HelperKind.Multi;
@@ -52,102 +40,6 @@ export function transformMultiHelperReturnStatement(
5240
return lua.createReturnStatement(expressions, statement);
5341
}
5442

55-
function transformMultiHelperCallArguments(
56-
context: TransformationContext,
57-
expression: ts.CallExpression
58-
): lua.Expression[] | lua.Expression {
59-
if (!isMultiHelperCallSignature(context, expression)) {
60-
return context.transformExpression(expression);
61-
}
62-
63-
if (expression.arguments.length === 0) {
64-
return lua.createNilLiteral(expression);
65-
}
66-
67-
return expression.arguments.map(e => context.transformExpression(e));
68-
}
69-
70-
export function transformMultiHelperVariableDeclaration(
71-
context: TransformationContext,
72-
declaration: ts.VariableDeclaration
73-
): lua.Statement[] | undefined {
74-
if (!declaration.initializer) return;
75-
if (!isMultiReturnCall(context, declaration.initializer)) return;
76-
77-
if (!ts.isArrayBindingPattern(declaration.name)) {
78-
context.diagnostics.push(invalidMultiReturnToNonArrayBindingPattern(declaration.name));
79-
return [];
80-
}
81-
82-
if (declaration.name.elements.length < 1) {
83-
context.diagnostics.push(invalidMultiReturnToEmptyPatternOrArrayLiteral(declaration.name));
84-
return [];
85-
}
86-
87-
const leftIdentifiers: lua.Identifier[] = [];
88-
89-
for (const element of declaration.name.elements) {
90-
if (ts.isBindingElement(element)) {
91-
if (element.initializer) {
92-
context.diagnostics.push(invalidMultiReturnArrayBindingPatternElementInitializer(element));
93-
} else if (ts.isIdentifier(element.name)) {
94-
leftIdentifiers.push(transformIdentifier(context, element.name));
95-
} else {
96-
context.diagnostics.push(unsupportedMultiFunctionAssignment(element));
97-
}
98-
} else if (ts.isOmittedExpression(element)) {
99-
leftIdentifiers.push(lua.createAnonymousIdentifier(element));
100-
}
101-
}
102-
103-
const rightExpressions = transformMultiHelperCallArguments(context, declaration.initializer);
104-
return createLocalOrExportedOrGlobalDeclaration(context, leftIdentifiers, rightExpressions, declaration);
105-
}
106-
107-
export function transformMultiHelperDestructuringAssignmentStatement(
108-
context: TransformationContext,
109-
statement: ts.ExpressionStatement
110-
): lua.Statement[] | undefined {
111-
if (!ts.isBinaryExpression(statement.expression)) return;
112-
if (statement.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return;
113-
if (!isMultiReturnCall(context, statement.expression.right)) return;
114-
115-
if (!ts.isArrayLiteralExpression(statement.expression.left)) {
116-
context.diagnostics.push(invalidMultiReturnToNonArrayLiteral(statement.expression.left));
117-
return [];
118-
}
119-
120-
if (statement.expression.left.elements.some(ts.isBinaryExpression)) {
121-
context.diagnostics.push(invalidMultiReturnArrayLiteralElementInitializer(statement.expression.left));
122-
return [];
123-
}
124-
125-
if (statement.expression.left.elements.length < 1) {
126-
context.diagnostics.push(invalidMultiReturnToEmptyPatternOrArrayLiteral(statement.expression.left));
127-
return [];
128-
}
129-
130-
const transformLeft = (expression: ts.Expression): lua.AssignmentLeftHandSideExpression =>
131-
ts.isOmittedExpression(expression)
132-
? lua.createAnonymousIdentifier(expression)
133-
: transformAssignmentLeftHandSideExpression(context, expression);
134-
135-
const leftIdentifiers = statement.expression.left.elements.map(transformLeft);
136-
137-
const rightExpressions = transformMultiHelperCallArguments(context, statement.expression.right);
138-
139-
const trailingStatements = statement.expression.left.elements.flatMap(expression => {
140-
const symbol = context.checker.getSymbolAtLocation(expression);
141-
const dependentSymbols = symbol ? getDependenciesOfSymbol(context, symbol) : [];
142-
return dependentSymbols.map(symbol => {
143-
const identifierToAssign = createExportedIdentifier(context, lua.createIdentifier(symbol.name));
144-
return lua.createAssignmentStatement(identifierToAssign, transformLeft(expression));
145-
});
146-
});
147-
148-
return [lua.createAssignmentStatement(leftIdentifiers, rightExpressions, statement), ...trailingStatements];
149-
}
150-
15143
export function findMultiHelperAssignmentViolations(
15244
context: TransformationContext,
15345
node: ts.ObjectLiteralExpression

src/transformation/visitors/variable-declaration.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { createLocalOrExportedOrGlobalDeclaration, createUnpackCall } from "../u
1010
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
1111
import { transformIdentifier } from "./identifier";
1212
import { transformPropertyName } from "./literal";
13-
import { transformMultiHelperVariableDeclaration } from "./helpers/multi";
1413

1514
export function transformArrayBindingElement(
1615
context: TransformationContext,
@@ -218,11 +217,6 @@ export function transformVariableDeclaration(
218217
context: TransformationContext,
219218
statement: ts.VariableDeclaration
220219
): lua.Statement[] {
221-
const result = transformMultiHelperVariableDeclaration(context, statement);
222-
if (result) {
223-
return result;
224-
}
225-
226220
if (statement.initializer && statement.type) {
227221
const initializerType = context.checker.getTypeAtLocation(statement.initializer);
228222
const varType = context.checker.getTypeFromTypeNode(statement.type);

test/unit/helpers/__snapshots__/multi.spec.ts.snap

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,28 @@
22

33
exports[`invalid $multi call ($multi()): code 1`] = `"____(_G)"`;
44

5-
exports[`invalid $multi call ($multi()): diagnostics 1`] = `"main.ts(2,9): error TSTL: The $multi() function cannot be used here."`;
5+
exports[`invalid $multi call ($multi()): diagnostics 1`] = `"main.ts(2,9): error TSTL: The $multi() function can only be used in a return statement."`;
66

77
exports[`invalid $multi call ($multi): code 1`] = `"local ____ = ____"`;
88

9-
exports[`invalid $multi call ($multi): diagnostics 1`] = `"main.ts(2,9): error TSTL: The $multi() function cannot be used here."`;
10-
11-
exports[`invalid $multi call (([a] = $multi(1)) => {}): code 1`] = `
12-
"local function ____(____, ____bindingPattern0)
13-
if ____bindingPattern0 == nil then
14-
____bindingPattern0 = ____(_G, 1)
15-
end
16-
local a = ____bindingPattern0[1]
17-
end"
18-
`;
19-
20-
exports[`invalid $multi call (([a] = $multi(1)) => {}): diagnostics 1`] = `"main.ts(2,16): error TSTL: The $multi() function cannot be used here."`;
9+
exports[`invalid $multi call ($multi): diagnostics 1`] = `"main.ts(2,9): error TSTL: The $multi() function can only be used in a return statement."`;
2110

2211
exports[`invalid $multi call (({ $multi });): code 1`] = `"local ____ = nil"`;
2312

24-
exports[`invalid $multi call (({ $multi });): diagnostics 1`] = `"main.ts(2,12): error TSTL: The $multi() function cannot be used here."`;
25-
26-
exports[`invalid $multi call ([] = $multi()): code 1`] = `""`;
27-
28-
exports[`invalid $multi call ([] = $multi()): diagnostics 1`] = `"main.ts(2,9): error TSTL: There must be one or more elements specified here."`;
29-
30-
exports[`invalid $multi call (const [] = $multi();): code 1`] = `""`;
13+
exports[`invalid $multi call (({ $multi });): diagnostics 1`] = `"main.ts(2,12): error TSTL: The $multi() function can only be used in a return statement."`;
3114

32-
exports[`invalid $multi call (const [] = $multi();): diagnostics 1`] = `"main.ts(2,15): error TSTL: There must be one or more elements specified here."`;
33-
34-
exports[`invalid $multi call (const [a = 0] = $multi()): code 1`] = `""`;
35-
36-
exports[`invalid $multi call (const [a = 0] = $multi()): diagnostics 1`] = `"main.ts(2,16): error TSTL: This array binding pattern cannot have initializers."`;
37-
38-
exports[`invalid $multi call (const {} = $multi();): code 1`] = `""`;
15+
exports[`invalid $multi call ([] = $multi()): code 1`] = `
16+
" = table.unpack(
17+
____(_G)
18+
)"
19+
`;
3920

40-
exports[`invalid $multi call (const {} = $multi();): diagnostics 1`] = `"main.ts(2,15): error TSTL: Expected an array destructuring pattern."`;
21+
exports[`invalid $multi call ([] = $multi()): diagnostics 1`] = `"main.ts(2,14): error TSTL: The $multi() function can only be used in a return statement."`;
4122

42-
exports[`invalid $multi call (const a = $multi();): code 1`] = `""`;
23+
exports[`invalid $multi call (const [] = $multi();): code 1`] = `
24+
"____ = table.unpack(
25+
____(_G)
26+
)"
27+
`;
4328

44-
exports[`invalid $multi call (const a = $multi();): diagnostics 1`] = `"main.ts(2,15): error TSTL: Expected an array destructuring pattern."`;
29+
exports[`invalid $multi call (const [] = $multi();): diagnostics 1`] = `"main.ts(2,20): error TSTL: The $multi() function can only be used in a return statement."`;

test/unit/helpers/multi.spec.ts

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,34 @@
11
import * as path from "path";
22
import * as util from "../../util";
33
import * as tstl from "../../../src";
4-
import {
5-
unsupportedMultiHelperFunctionPosition,
6-
invalidMultiReturnToNonArrayBindingPattern,
7-
invalidMultiReturnArrayBindingPatternElementInitializer,
8-
invalidMultiReturnToEmptyPatternOrArrayLiteral,
9-
} from "../../../src/transformation/utils/diagnostics";
4+
import { unsupportedMultiHelperFunctionPosition } from "../../../src/transformation/utils/diagnostics";
105

116
const multiProjectOptions: tstl.CompilerOptions = {
127
types: [path.resolve(__dirname, "../../../helpers")],
138
};
149

1510
test.each<[string, any]>([
16-
["let a; [a] = $multi();", undefined],
17-
["const [a] = $multi();", undefined],
18-
["const [a] = $multi(1);", 1],
19-
["const ar = [1]; const [a] = $multi(...ar);", 1],
20-
["const _ = null, [a] = $multi(1);", 1],
21-
["let a; for (const [a] = $multi(1, 2); false; 1) {}", undefined],
22-
["let a; for ([a] = $multi(1, 2); false; 1) {}", 1],
11+
["return $multi();", undefined],
12+
["return $multi(1);", 1],
13+
["const ar = [1]; return $multi(...ar);", 1],
2314
])("valid $multi call and assign (%s)", (statement, result) => {
24-
util.testModule`
15+
util.testFunction`
2516
${statement}
26-
export { a };
2717
`
2818
.setOptions(multiProjectOptions)
29-
.setReturnExport("a")
3019
.expectToEqual(result);
3120
});
3221

3322
test.each<[string, number[]]>([
3423
["$multi", [unsupportedMultiHelperFunctionPosition.code]],
3524
["$multi()", [unsupportedMultiHelperFunctionPosition.code]],
3625
["({ $multi });", [unsupportedMultiHelperFunctionPosition.code]],
37-
["[] = $multi()", [invalidMultiReturnToEmptyPatternOrArrayLiteral.code]],
38-
["const [] = $multi();", [invalidMultiReturnToEmptyPatternOrArrayLiteral.code]],
39-
["const a = $multi();", [invalidMultiReturnToNonArrayBindingPattern.code]],
40-
["const {} = $multi();", [invalidMultiReturnToNonArrayBindingPattern.code]],
41-
["([a] = $multi(1)) => {}", [unsupportedMultiHelperFunctionPosition.code]],
42-
["const [a = 0] = $multi()", [invalidMultiReturnArrayBindingPatternElementInitializer.code]],
26+
["[] = $multi()", [unsupportedMultiHelperFunctionPosition.code]],
27+
["const [] = $multi();", [unsupportedMultiHelperFunctionPosition.code]],
4328
])("invalid $multi call (%s)", (statement, diagnostics) => {
4429
util.testModule`
4530
${statement}
4631
`
4732
.setOptions(multiProjectOptions)
4833
.expectDiagnosticsToMatchSnapshot(diagnostics);
4934
});
50-
51-
test.each<[string, any]>([
52-
["return $multi();", undefined],
53-
["return $multi(1);", 1],
54-
])("valid $multi call return statement (%s)", (statement, result) => {
55-
util.testModule`
56-
export const [a] = (function() {
57-
${statement}
58-
})();
59-
`
60-
.setOptions(multiProjectOptions)
61-
.setReturnExport("a")
62-
.expectToEqual(result);
63-
});
64-
65-
test("$multi helper call with destructuring assignment side effects", () => {
66-
util.testModule`
67-
let a;
68-
export { a };
69-
[a] = $multi(1);
70-
`
71-
.setOptions(multiProjectOptions)
72-
.setReturnExport("a")
73-
.expectToEqual(1);
74-
});

0 commit comments

Comments
 (0)