typescript-to-lua 1.0.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/CompilerOptions.d.ts +4 -3
  3. package/dist/LuaAST.d.ts +1 -0
  4. package/dist/LuaAST.js +14 -6
  5. package/dist/LuaLib.d.ts +4 -3
  6. package/dist/LuaLib.js +6 -5
  7. package/dist/LuaPrinter.d.ts +15 -4
  8. package/dist/LuaPrinter.js +81 -29
  9. package/dist/cli/diagnostics.js +2 -2
  10. package/dist/cli/parse.d.ts +1 -1
  11. package/dist/cli/parse.js +14 -0
  12. package/dist/cli/report.js +1 -1
  13. package/dist/cli/tsconfig.js +4 -4
  14. package/dist/lualib/ArrayFlat.lua +1 -1
  15. package/dist/lualib/ArrayFlatMap.lua +1 -1
  16. package/dist/lualib/ArrayIsArray.lua +1 -1
  17. package/dist/lualib/ArrayReduce.lua +7 -1
  18. package/dist/lualib/ArrayReduceRight.lua +7 -1
  19. package/dist/lualib/ArraySetLength.lua +1 -1
  20. package/dist/lualib/ArraySplice.lua +5 -5
  21. package/dist/lualib/Await.lua +43 -19
  22. package/dist/lualib/CloneDescriptor.lua +7 -7
  23. package/dist/lualib/Decorate.lua +1 -1
  24. package/dist/lualib/DelegatedYield.lua +1 -3
  25. package/dist/lualib/Delete.lua +6 -6
  26. package/dist/lualib/Error.lua +47 -44
  27. package/dist/lualib/Generator.lua +1 -5
  28. package/dist/lualib/InstanceOf.lua +1 -1
  29. package/dist/lualib/InstanceOfObject.lua +1 -1
  30. package/dist/lualib/Map.lua +130 -134
  31. package/dist/lualib/Number.lua +1 -1
  32. package/dist/lualib/NumberIsFinite.lua +1 -1
  33. package/dist/lualib/NumberToString.lua +3 -5
  34. package/dist/lualib/ObjectDefineProperty.lua +40 -8
  35. package/dist/lualib/ParseFloat.lua +9 -5
  36. package/dist/lualib/ParseInt.lua +15 -3
  37. package/dist/lualib/Promise.lua +44 -26
  38. package/dist/lualib/Set.lua +119 -123
  39. package/dist/lualib/SetDescriptor.lua +7 -1
  40. package/dist/lualib/SourceMapTraceBack.lua +19 -9
  41. package/dist/lualib/SparseArrayNew.lua +5 -0
  42. package/dist/lualib/SparseArrayPush.lua +9 -0
  43. package/dist/lualib/SparseArraySpread.lua +4 -0
  44. package/dist/lualib/StringAccess.lua +1 -1
  45. package/dist/lualib/StringCharCodeAt.lua +1 -1
  46. package/dist/lualib/StringEndsWith.lua +2 -2
  47. package/dist/lualib/StringPadEnd.lua +2 -2
  48. package/dist/lualib/StringPadStart.lua +2 -2
  49. package/dist/lualib/StringReplace.lua +12 -11
  50. package/dist/lualib/StringReplaceAll.lua +35 -0
  51. package/dist/lualib/StringSlice.lua +2 -2
  52. package/dist/lualib/StringSplit.lua +3 -3
  53. package/dist/lualib/StringStartsWith.lua +1 -1
  54. package/dist/lualib/StringSubstr.lua +1 -1
  55. package/dist/lualib/StringSubstring.lua +2 -2
  56. package/dist/lualib/Symbol.lua +3 -5
  57. package/dist/lualib/WeakMap.lua +40 -42
  58. package/dist/lualib/WeakSet.lua +36 -38
  59. package/dist/lualib/lualib_bundle.lua +876 -745
  60. package/dist/transformation/builtins/array.js +29 -30
  61. package/dist/transformation/builtins/console.js +2 -2
  62. package/dist/transformation/builtins/function.js +14 -12
  63. package/dist/transformation/builtins/global.js +8 -8
  64. package/dist/transformation/builtins/index.d.ts +1 -1
  65. package/dist/transformation/builtins/index.js +69 -36
  66. package/dist/transformation/builtins/math.js +4 -4
  67. package/dist/transformation/builtins/number.js +7 -7
  68. package/dist/transformation/builtins/object.d.ts +2 -1
  69. package/dist/transformation/builtins/object.js +12 -13
  70. package/dist/transformation/builtins/promise.js +9 -9
  71. package/dist/transformation/builtins/string.js +32 -31
  72. package/dist/transformation/builtins/symbol.js +3 -3
  73. package/dist/transformation/context/context.d.ts +12 -0
  74. package/dist/transformation/context/context.js +105 -6
  75. package/dist/transformation/index.js +1 -1
  76. package/dist/transformation/utils/annotations.d.ts +1 -3
  77. package/dist/transformation/utils/annotations.js +0 -2
  78. package/dist/transformation/utils/assignment-validation.js +8 -7
  79. package/dist/transformation/utils/diagnostics.d.ts +9 -0
  80. package/dist/transformation/utils/diagnostics.js +8 -5
  81. package/dist/transformation/utils/export.d.ts +3 -2
  82. package/dist/transformation/utils/export.js +14 -7
  83. package/dist/transformation/utils/function-context.js +8 -8
  84. package/dist/transformation/utils/language-extensions.d.ts +2 -0
  85. package/dist/transformation/utils/language-extensions.js +7 -1
  86. package/dist/transformation/utils/lua-ast.d.ts +0 -1
  87. package/dist/transformation/utils/lua-ast.js +25 -35
  88. package/dist/transformation/utils/lualib.js +1 -1
  89. package/dist/transformation/utils/preceding-statements.d.ts +3 -0
  90. package/dist/transformation/utils/preceding-statements.js +11 -0
  91. package/dist/transformation/utils/safe-names.d.ts +4 -2
  92. package/dist/transformation/utils/safe-names.js +13 -7
  93. package/dist/transformation/utils/scope.d.ts +9 -1
  94. package/dist/transformation/utils/scope.js +78 -40
  95. package/dist/transformation/utils/symbols.js +6 -6
  96. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  97. package/dist/transformation/utils/typescript/index.js +16 -1
  98. package/dist/transformation/utils/typescript/nodes.d.ts +2 -0
  99. package/dist/transformation/utils/typescript/nodes.js +21 -1
  100. package/dist/transformation/utils/typescript/types.d.ts +3 -1
  101. package/dist/transformation/utils/typescript/types.js +40 -13
  102. package/dist/transformation/visitors/access.d.ts +3 -0
  103. package/dist/transformation/visitors/access.js +74 -47
  104. package/dist/transformation/visitors/async-await.js +5 -4
  105. package/dist/transformation/visitors/binary-expression/assignments.d.ts +3 -2
  106. package/dist/transformation/visitors/binary-expression/assignments.js +86 -77
  107. package/dist/transformation/visitors/binary-expression/bit.js +4 -4
  108. package/dist/transformation/visitors/binary-expression/compound.d.ts +5 -4
  109. package/dist/transformation/visitors/binary-expression/compound.js +69 -71
  110. package/dist/transformation/visitors/binary-expression/destructuring-assignments.d.ts +2 -2
  111. package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +65 -36
  112. package/dist/transformation/visitors/binary-expression/index.d.ts +3 -1
  113. package/dist/transformation/visitors/binary-expression/index.js +84 -42
  114. package/dist/transformation/visitors/block.js +6 -6
  115. package/dist/transformation/visitors/break-continue.js +2 -2
  116. package/dist/transformation/visitors/call.d.ts +3 -2
  117. package/dist/transformation/visitors/call.js +130 -143
  118. package/dist/transformation/visitors/class/decorators.js +3 -3
  119. package/dist/transformation/visitors/class/index.js +43 -39
  120. package/dist/transformation/visitors/class/members/accessors.js +6 -6
  121. package/dist/transformation/visitors/class/members/constructor.js +7 -7
  122. package/dist/transformation/visitors/class/members/fields.js +6 -6
  123. package/dist/transformation/visitors/class/members/method.js +6 -6
  124. package/dist/transformation/visitors/class/new.js +14 -16
  125. package/dist/transformation/visitors/class/setup.js +11 -11
  126. package/dist/transformation/visitors/class/utils.js +2 -2
  127. package/dist/transformation/visitors/conditional.js +36 -43
  128. package/dist/transformation/visitors/delete.js +8 -4
  129. package/dist/transformation/visitors/enum.js +8 -8
  130. package/dist/transformation/visitors/errors.js +35 -33
  131. package/dist/transformation/visitors/expression-list.d.ts +7 -0
  132. package/dist/transformation/visitors/expression-list.js +120 -0
  133. package/dist/transformation/visitors/expression-statement.js +10 -6
  134. package/dist/transformation/visitors/function.d.ts +2 -0
  135. package/dist/transformation/visitors/function.js +80 -33
  136. package/dist/transformation/visitors/identifier.js +26 -22
  137. package/dist/transformation/visitors/index.js +2 -2
  138. package/dist/transformation/visitors/language-extensions/iterable.js +7 -7
  139. package/dist/transformation/visitors/language-extensions/multi.d.ts +1 -1
  140. package/dist/transformation/visitors/language-extensions/multi.js +3 -3
  141. package/dist/transformation/visitors/language-extensions/operators.js +6 -6
  142. package/dist/transformation/visitors/language-extensions/pairsIterable.d.ts +5 -0
  143. package/dist/transformation/visitors/language-extensions/pairsIterable.js +53 -0
  144. package/dist/transformation/visitors/language-extensions/range.js +6 -6
  145. package/dist/transformation/visitors/language-extensions/table.js +5 -5
  146. package/dist/transformation/visitors/literal.d.ts +1 -2
  147. package/dist/transformation/visitors/literal.js +87 -57
  148. package/dist/transformation/visitors/loops/do-while.js +35 -9
  149. package/dist/transformation/visitors/loops/for-in.js +4 -4
  150. package/dist/transformation/visitors/loops/for-of.js +17 -13
  151. package/dist/transformation/visitors/loops/for.js +28 -8
  152. package/dist/transformation/visitors/loops/utils.d.ts +1 -0
  153. package/dist/transformation/visitors/loops/utils.js +26 -10
  154. package/dist/transformation/visitors/modules/export.js +14 -15
  155. package/dist/transformation/visitors/modules/import.js +10 -10
  156. package/dist/transformation/visitors/namespace.js +13 -13
  157. package/dist/transformation/visitors/optional-chaining.d.ts +16 -0
  158. package/dist/transformation/visitors/optional-chaining.js +172 -0
  159. package/dist/transformation/visitors/return.d.ts +1 -0
  160. package/dist/transformation/visitors/return.js +40 -26
  161. package/dist/transformation/visitors/sourceFile.js +12 -9
  162. package/dist/transformation/visitors/spread.js +23 -16
  163. package/dist/transformation/visitors/switch.js +63 -20
  164. package/dist/transformation/visitors/template.js +10 -7
  165. package/dist/transformation/visitors/typeof.js +4 -2
  166. package/dist/transformation/visitors/typescript.js +1 -1
  167. package/dist/transformation/visitors/unary-expression.js +9 -9
  168. package/dist/transformation/visitors/variable-declaration.js +55 -32
  169. package/dist/transformation/visitors/void.d.ts +6 -0
  170. package/dist/transformation/visitors/void.js +20 -0
  171. package/dist/transpilation/bundle.d.ts +3 -0
  172. package/dist/transpilation/bundle.js +52 -10
  173. package/dist/transpilation/diagnostics.js +3 -3
  174. package/dist/transpilation/index.js +2 -2
  175. package/dist/transpilation/output-collector.js +2 -2
  176. package/dist/transpilation/plugins.js +1 -1
  177. package/dist/transpilation/resolve.js +20 -13
  178. package/dist/transpilation/transformers.js +45 -25
  179. package/dist/transpilation/transpile.js +6 -6
  180. package/dist/transpilation/transpiler.js +8 -8
  181. package/dist/transpilation/utils.js +5 -3
  182. package/dist/tstl.js +8 -8
  183. package/dist/utils.js +2 -2
  184. package/language-extensions/index.d.ts +11 -1
  185. package/package.json +15 -12
  186. package/dist/lualib/OptionalChainAccess.lua +0 -6
  187. package/dist/lualib/OptionalFunctionCall.lua +0 -6
  188. package/dist/lualib/OptionalMethodCall.lua +0 -11
  189. package/dist/transformation/utils/transform.d.ts +0 -8
  190. package/dist/transformation/utils/transform.js +0 -14
  191. package/dist/transformation/visitors/jsx/jsx.d.ts +0 -9
  192. package/dist/transformation/visitors/jsx/jsx.js +0 -237
  193. package/dist/transformation/visitors/jsx/xhtml.d.ts +0 -3
  194. package/dist/transformation/visitors/jsx/xhtml.js +0 -260
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformBinaryExpressionStatement = exports.transformBinaryExpression = exports.transformBinaryOperation = void 0;
3
+ exports.transformBinaryExpressionStatement = exports.transformBinaryExpression = exports.transformBinaryOperation = exports.createShortCircuitBinaryExpressionPrecedingStatements = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../../LuaAST");
6
6
  const lua_ast_1 = require("../../utils/lua-ast");
@@ -11,7 +11,11 @@ const assignments_1 = require("./assignments");
11
11
  const bit_1 = require("./bit");
12
12
  const compound_1 = require("./compound");
13
13
  const utils_1 = require("../../../utils");
14
- const transform_1 = require("../../utils/transform");
14
+ const expression_list_1 = require("../expression-list");
15
+ const preceding_statements_1 = require("../../utils/preceding-statements");
16
+ const isShortCircuitOperator = (value) => value === ts.SyntaxKind.AmpersandAmpersandToken ||
17
+ value === ts.SyntaxKind.BarBarToken ||
18
+ value === ts.SyntaxKind.QuestionQuestionToken;
15
19
  const simpleOperatorsToLua = {
16
20
  [ts.SyntaxKind.AmpersandAmpersandToken]: lua.SyntaxKind.AndOperator,
17
21
  [ts.SyntaxKind.BarBarToken]: lua.SyntaxKind.OrOperator,
@@ -30,43 +34,77 @@ const simpleOperatorsToLua = {
30
34
  [ts.SyntaxKind.ExclamationEqualsToken]: lua.SyntaxKind.InequalityOperator,
31
35
  [ts.SyntaxKind.ExclamationEqualsEqualsToken]: lua.SyntaxKind.InequalityOperator,
32
36
  };
33
- function transformBinaryOperation(context, left, right, operator, node) {
34
- if (bit_1.isBitOperator(operator)) {
35
- return bit_1.transformBinaryBitOperation(context, node, left, right, operator);
37
+ function transformBinaryOperationWithNoPrecedingStatements(context, left, right, operator, node) {
38
+ if ((0, bit_1.isBitOperator)(operator)) {
39
+ return (0, bit_1.transformBinaryBitOperation)(context, node, left, right, operator);
36
40
  }
37
41
  if (operator === ts.SyntaxKind.QuestionQuestionToken) {
38
- utils_1.assert(ts.isBinaryExpression(node));
39
- return transformNullishCoalescingExpression(context, node, left, right);
42
+ (0, utils_1.assert)(ts.isBinaryExpression(node));
43
+ return transformNullishCoalescingOperationNoPrecedingStatements(context, node, left, right);
40
44
  }
41
45
  let luaOperator = simpleOperatorsToLua[operator];
42
46
  // Check if we need to use string concat operator
43
47
  if (operator === ts.SyntaxKind.PlusToken && ts.isBinaryExpression(node)) {
44
48
  const typeLeft = context.checker.getTypeAtLocation(node.left);
45
49
  const typeRight = context.checker.getTypeAtLocation(node.right);
46
- const isLeftString = typescript_1.isStringType(context, typeLeft);
47
- const isRightString = typescript_1.isStringType(context, typeRight);
50
+ const isLeftString = (0, typescript_1.isStringType)(context, typeLeft);
51
+ const isRightString = (0, typescript_1.isStringType)(context, typeRight);
48
52
  if (isLeftString || isRightString) {
49
- left = isLeftString ? left : lua_ast_1.wrapInToStringForConcat(left);
50
- right = isRightString ? right : lua_ast_1.wrapInToStringForConcat(right);
53
+ left = isLeftString ? left : (0, lua_ast_1.wrapInToStringForConcat)(left);
54
+ right = isRightString ? right : (0, lua_ast_1.wrapInToStringForConcat)(right);
51
55
  luaOperator = lua.SyntaxKind.ConcatOperator;
52
56
  }
53
57
  }
54
58
  return lua.createBinaryExpression(left, right, luaOperator, node);
55
59
  }
60
+ function createShortCircuitBinaryExpressionPrecedingStatements(context, lhs, rhs, rightPrecedingStatements, operator, node) {
61
+ const conditionIdentifier = context.createTempNameForLuaExpression(lhs);
62
+ const assignmentStatement = lua.createVariableDeclarationStatement(conditionIdentifier, lhs, node === null || node === void 0 ? void 0 : node.left);
63
+ let condition;
64
+ switch (operator) {
65
+ case ts.SyntaxKind.BarBarToken:
66
+ condition = lua.createUnaryExpression(lua.cloneIdentifier(conditionIdentifier), lua.SyntaxKind.NotOperator, node);
67
+ break;
68
+ case ts.SyntaxKind.AmpersandAmpersandToken:
69
+ condition = lua.cloneIdentifier(conditionIdentifier);
70
+ break;
71
+ case ts.SyntaxKind.QuestionQuestionToken:
72
+ condition = lua.createBinaryExpression(lua.cloneIdentifier(conditionIdentifier), lua.createNilLiteral(), lua.SyntaxKind.EqualityOperator, node);
73
+ break;
74
+ }
75
+ const ifStatement = lua.createIfStatement(condition, lua.createBlock([...rightPrecedingStatements, lua.createAssignmentStatement(conditionIdentifier, rhs)]), undefined, node === null || node === void 0 ? void 0 : node.left);
76
+ return [[assignmentStatement, ifStatement], conditionIdentifier];
77
+ }
78
+ exports.createShortCircuitBinaryExpressionPrecedingStatements = createShortCircuitBinaryExpressionPrecedingStatements;
79
+ function transformShortCircuitBinaryExpression(context, node, operator) {
80
+ const lhs = context.transformExpression(node.left);
81
+ const [rightPrecedingStatements, rhs] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(node.right));
82
+ return transformBinaryOperation(context, lhs, rhs, rightPrecedingStatements, operator, node);
83
+ }
84
+ function transformBinaryOperation(context, left, right, rightPrecedingStatements, operator, node) {
85
+ if (rightPrecedingStatements.length > 0 && isShortCircuitOperator(operator)) {
86
+ (0, utils_1.assert)(ts.isBinaryExpression(node));
87
+ return createShortCircuitBinaryExpressionPrecedingStatements(context, left, right, rightPrecedingStatements, operator, node);
88
+ }
89
+ return [
90
+ rightPrecedingStatements,
91
+ transformBinaryOperationWithNoPrecedingStatements(context, left, right, operator, node),
92
+ ];
93
+ }
56
94
  exports.transformBinaryOperation = transformBinaryOperation;
57
95
  const transformBinaryExpression = (node, context) => {
58
96
  const operator = node.operatorToken.kind;
59
- const typeOfResult = typeof_1.transformTypeOfBinaryExpression(context, node);
97
+ const typeOfResult = (0, typeof_1.transformTypeOfBinaryExpression)(context, node);
60
98
  if (typeOfResult) {
61
99
  return typeOfResult;
62
100
  }
63
- if (compound_1.isCompoundAssignmentToken(operator)) {
64
- const token = compound_1.unwrapCompoundAssignmentToken(operator);
65
- return compound_1.transformCompoundAssignmentExpression(context, node, node.left, node.right, token, false);
101
+ if ((0, compound_1.isCompoundAssignmentToken)(operator)) {
102
+ const token = (0, compound_1.unwrapCompoundAssignmentToken)(operator);
103
+ return (0, compound_1.transformCompoundAssignmentExpression)(context, node, node.left, node.right, token, false);
66
104
  }
67
105
  switch (operator) {
68
106
  case ts.SyntaxKind.EqualsToken:
69
- return assignments_1.transformAssignmentExpression(context, node);
107
+ return (0, assignments_1.transformAssignmentExpression)(context, node);
70
108
  case ts.SyntaxKind.InKeyword: {
71
109
  const lhs = context.transformExpression(node.left);
72
110
  const rhs = context.transformExpression(node.right);
@@ -77,20 +115,31 @@ const transformBinaryExpression = (node, context) => {
77
115
  const lhs = context.transformExpression(node.left);
78
116
  const rhs = context.transformExpression(node.right);
79
117
  const rhsType = context.checker.getTypeAtLocation(node.right);
80
- if (typescript_1.isStandardLibraryType(context, rhsType, "ObjectConstructor")) {
81
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.InstanceOfObject, node, lhs);
118
+ if ((0, typescript_1.isStandardLibraryType)(context, rhsType, "ObjectConstructor")) {
119
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.InstanceOfObject, node, lhs);
82
120
  }
83
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.InstanceOf, node, lhs, rhs);
121
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.InstanceOf, node, lhs, rhs);
84
122
  }
85
123
  case ts.SyntaxKind.CommaToken: {
86
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => ({
87
- statements: context.transformStatements(ts.factory.createExpressionStatement(node.left)),
88
- result: context.transformExpression(node.right),
89
- }), node);
124
+ const statements = context.transformStatements(ts.factory.createExpressionStatement(node.left));
125
+ const [precedingStatements, result] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(node.right));
126
+ statements.push(...precedingStatements);
127
+ context.addPrecedingStatements(statements);
128
+ return result;
129
+ }
130
+ case ts.SyntaxKind.QuestionQuestionToken:
131
+ case ts.SyntaxKind.AmpersandAmpersandToken:
132
+ case ts.SyntaxKind.BarBarToken: {
133
+ const [precedingStatements, result] = transformShortCircuitBinaryExpression(context, node, operator);
134
+ context.addPrecedingStatements(precedingStatements);
135
+ return result;
90
136
  }
91
- default:
92
- return transformBinaryOperation(context, context.transformExpression(node.left), context.transformExpression(node.right), operator, node);
93
137
  }
138
+ let [precedingStatements, [lhs, rhs]] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => (0, expression_list_1.transformOrderedExpressions)(context, [node.left, node.right]));
139
+ let result;
140
+ [precedingStatements, result] = transformBinaryOperation(context, lhs, rhs, precedingStatements, operator, node);
141
+ context.addPrecedingStatements(precedingStatements);
142
+ return result;
94
143
  };
95
144
  exports.transformBinaryExpression = transformBinaryExpression;
96
145
  function transformBinaryExpressionStatement(context, node) {
@@ -98,13 +147,13 @@ function transformBinaryExpressionStatement(context, node) {
98
147
  if (!ts.isBinaryExpression(expression))
99
148
  return;
100
149
  const operator = expression.operatorToken.kind;
101
- if (compound_1.isCompoundAssignmentToken(operator)) {
150
+ if ((0, compound_1.isCompoundAssignmentToken)(operator)) {
102
151
  // +=, -=, etc...
103
- const token = compound_1.unwrapCompoundAssignmentToken(operator);
104
- return compound_1.transformCompoundAssignmentStatement(context, expression, expression.left, expression.right, token);
152
+ const token = (0, compound_1.unwrapCompoundAssignmentToken)(operator);
153
+ return (0, compound_1.transformCompoundAssignmentStatement)(context, expression, expression.left, expression.right, token);
105
154
  }
106
155
  else if (operator === ts.SyntaxKind.EqualsToken) {
107
- return assignments_1.transformAssignmentStatement(context, expression);
156
+ return (0, assignments_1.transformAssignmentStatement)(context, expression);
108
157
  }
109
158
  else if (operator === ts.SyntaxKind.CommaToken) {
110
159
  const statements = [
@@ -115,21 +164,14 @@ function transformBinaryExpressionStatement(context, node) {
115
164
  }
116
165
  }
117
166
  exports.transformBinaryExpressionStatement = transformBinaryExpressionStatement;
118
- function transformNullishCoalescingExpression(context, node, transformedLeft, transformedRight) {
167
+ function transformNullishCoalescingOperationNoPrecedingStatements(context, node, transformedLeft, transformedRight) {
119
168
  const lhsType = context.checker.getTypeAtLocation(node.left);
120
169
  // Check if we can take a shortcut to 'lhs or rhs' if the left-hand side cannot be 'false'.
121
- const typeCanBeFalse = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Boolean)) !== 0 ||
122
- (type.flags & ts.TypeFlags.BooleanLiteral & ts.TypeFlags.PossiblyFalsy) !== 0;
123
- if (typescript_1.typeCanSatisfy(context, lhsType, typeCanBeFalse)) {
124
- // lhs can be false, transform to IIFE
125
- const lhsIdentifier = lua.createIdentifier("____lhs");
126
- const nilComparison = lua.createBinaryExpression(lua.cloneIdentifier(lhsIdentifier), lua.createNilLiteral(), lua.SyntaxKind.EqualityOperator);
127
- // if ____ == nil then return rhs else return ____ end
128
- const ifStatement = lua.createIfStatement(nilComparison, lua.createBlock([lua.createReturnStatement([transformedRight])]), lua.createBlock([lua.createReturnStatement([lua.cloneIdentifier(lhsIdentifier)])]));
129
- // (function(lhs') if lhs' == nil then return rhs else return lhs' end)(lhs)
130
- return lua.createCallExpression(lua.createFunctionExpression(lua.createBlock([ifStatement]), [lhsIdentifier]), [
131
- transformedLeft,
132
- ]);
170
+ if ((0, typescript_1.canBeFalsyWhenNotNull)(context, lhsType)) {
171
+ // reuse logic from case with preceding statements
172
+ const [precedingStatements, result] = createShortCircuitBinaryExpressionPrecedingStatements(context, transformedLeft, transformedRight, [], ts.SyntaxKind.QuestionQuestionToken, node);
173
+ context.addPrecedingStatements(precedingStatements);
174
+ return result;
133
175
  }
134
176
  else {
135
177
  // lhs or rhs
@@ -9,16 +9,16 @@ function transformBlockOrStatement(context, statement) {
9
9
  }
10
10
  exports.transformBlockOrStatement = transformBlockOrStatement;
11
11
  function transformScopeBlock(context, node, scopeType) {
12
- scope_1.pushScope(context, scopeType);
13
- const statements = scope_1.performHoisting(context, context.transformStatements(node.statements));
14
- const scope = scope_1.popScope(context);
12
+ (0, scope_1.pushScope)(context, scopeType);
13
+ const statements = (0, scope_1.performHoisting)(context, context.transformStatements(node.statements));
14
+ const scope = (0, scope_1.popScope)(context);
15
15
  return [lua.createBlock(statements, node), scope];
16
16
  }
17
17
  exports.transformScopeBlock = transformScopeBlock;
18
18
  const transformBlock = (node, context) => {
19
- scope_1.pushScope(context, scope_1.ScopeType.Block);
20
- const statements = scope_1.performHoisting(context, context.transformStatements(node.statements));
21
- scope_1.popScope(context);
19
+ (0, scope_1.pushScope)(context, scope_1.ScopeType.Block);
20
+ const statements = (0, scope_1.performHoisting)(context, context.transformStatements(node.statements));
21
+ (0, scope_1.popScope)(context);
22
22
  return lua.createDoStatement(statements, node);
23
23
  };
24
24
  exports.transformBlock = transformBlock;
@@ -13,9 +13,9 @@ exports.transformBreakStatement = transformBreakStatement;
13
13
  const transformContinueStatement = (statement, context) => {
14
14
  var _a;
15
15
  if (context.luaTarget === CompilerOptions_1.LuaTarget.Universal || context.luaTarget === CompilerOptions_1.LuaTarget.Lua51) {
16
- context.diagnostics.push(diagnostics_1.unsupportedForTarget(statement, "Continue statement", CompilerOptions_1.LuaTarget.Lua51));
16
+ context.diagnostics.push((0, diagnostics_1.unsupportedForTarget)(statement, "Continue statement", CompilerOptions_1.LuaTarget.Lua51));
17
17
  }
18
- const scope = scope_1.findScope(context, scope_1.ScopeType.Loop);
18
+ const scope = (0, scope_1.findScope)(context, scope_1.ScopeType.Loop);
19
19
  if (scope) {
20
20
  scope.loopContinued = true;
21
21
  }
@@ -4,7 +4,8 @@ import { FunctionVisitor, TransformationContext } from "../context";
4
4
  export declare type PropertyCallExpression = ts.CallExpression & {
5
5
  expression: ts.PropertyAccessExpression;
6
6
  };
7
- export declare function flattenSpreadExpressions(context: TransformationContext, expressions: readonly ts.Expression[]): lua.Expression[];
7
+ export declare function validateArguments(context: TransformationContext, params: readonly ts.Expression[], signature?: ts.Signature): void;
8
8
  export declare function transformArguments(context: TransformationContext, params: readonly ts.Expression[], signature?: ts.Signature, callContext?: ts.Expression): lua.Expression[];
9
- export declare function transformContextualCallExpression(context: TransformationContext, node: ts.CallExpression | ts.TaggedTemplateExpression, args: ts.Expression[] | ts.NodeArray<ts.Expression>, signature?: ts.Signature): lua.CallExpression | lua.MethodCallExpression;
9
+ export declare function transformCallAndArguments(context: TransformationContext, callExpression: ts.Expression, params: readonly ts.Expression[], signature?: ts.Signature, callContext?: ts.Expression): [lua.Expression, lua.Expression[]];
10
+ export declare function transformContextualCallExpression(context: TransformationContext, node: ts.CallExpression | ts.TaggedTemplateExpression, args: ts.Expression[] | ts.NodeArray<ts.Expression>, signature?: ts.Signature): lua.Expression;
10
11
  export declare const transformCallExpression: FunctionVisitor<ts.CallExpression>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformCallExpression = exports.transformContextualCallExpression = exports.transformArguments = exports.flattenSpreadExpressions = void 0;
3
+ exports.transformCallExpression = exports.transformContextualCallExpression = exports.transformCallAndArguments = exports.transformArguments = exports.validateArguments = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../LuaAST");
6
6
  const builtins_1 = require("../builtins");
@@ -8,7 +8,6 @@ const annotations_1 = require("../utils/annotations");
8
8
  const assignment_validation_1 = require("../utils/assignment-validation");
9
9
  const function_context_1 = require("../utils/function-context");
10
10
  const lua_ast_1 = require("../utils/lua-ast");
11
- const lualib_1 = require("../utils/lualib");
12
11
  const safe_names_1 = require("../utils/safe-names");
13
12
  const typescript_1 = require("../utils/typescript");
14
13
  const access_1 = require("./access");
@@ -16,116 +15,97 @@ const multi_1 = require("./language-extensions/multi");
16
15
  const operators_1 = require("./language-extensions/operators");
17
16
  const table_1 = require("./language-extensions/table");
18
17
  const diagnostics_1 = require("../utils/diagnostics");
19
- const transform_1 = require("../utils/transform");
20
- function getExpressionsBeforeAndAfterFirstSpread(expressions) {
21
- // [a, b, ...c, d, ...e] --> [a, b] and [...c, d, ...e]
22
- const index = expressions.findIndex(ts.isSpreadElement);
23
- const hasSpreadElement = index !== -1;
24
- const before = hasSpreadElement ? expressions.slice(0, index) : expressions;
25
- const after = hasSpreadElement ? expressions.slice(index) : [];
26
- return [before, after];
27
- }
28
- function transformSpreadableExpressionsIntoArrayConcatArguments(context, expressions) {
29
- // [...array, a, b, ...tuple()] --> [ [...array], [a, b], [...tuple()] ]
30
- // chunk non-spread arguments together so they don't concat
31
- const chunks = [];
32
- for (const [index, expression] of expressions.entries()) {
33
- if (ts.isSpreadElement(expression)) {
34
- chunks.push([expression]);
35
- const next = expressions[index + 1];
36
- if (next && !ts.isSpreadElement(next)) {
37
- chunks.push([]);
38
- }
39
- }
40
- else {
41
- let lastChunk = chunks[chunks.length - 1];
42
- if (!lastChunk) {
43
- lastChunk = [];
44
- chunks.push(lastChunk);
45
- }
46
- lastChunk.push(expression);
18
+ const expression_list_1 = require("./expression-list");
19
+ const preceding_statements_1 = require("../utils/preceding-statements");
20
+ const optional_chaining_1 = require("./optional-chaining");
21
+ function validateArguments(context, params, signature) {
22
+ if (!signature || signature.parameters.length < params.length) {
23
+ return;
24
+ }
25
+ for (const [index, param] of params.entries()) {
26
+ const signatureParameter = signature.parameters[index];
27
+ const paramType = context.checker.getTypeAtLocation(param);
28
+ if (signatureParameter.valueDeclaration !== undefined) {
29
+ const signatureType = context.checker.getTypeAtLocation(signatureParameter.valueDeclaration);
30
+ (0, assignment_validation_1.validateAssignment)(context, param, paramType, signatureType, signatureParameter.name);
47
31
  }
48
32
  }
49
- return chunks.map(chunk => lua_ast_1.wrapInTable(...chunk.map(expression => context.transformExpression(expression))));
50
33
  }
51
- function flattenSpreadExpressions(context, expressions) {
52
- const [preSpreadExpressions, postSpreadExpressions] = getExpressionsBeforeAndAfterFirstSpread(expressions);
53
- const transformedPreSpreadExpressions = preSpreadExpressions.map(a => context.transformExpression(a));
54
- // Nothing special required
55
- if (postSpreadExpressions.length === 0) {
56
- return transformedPreSpreadExpressions;
57
- }
58
- // Only one spread element at the end? Will work as expected
59
- if (postSpreadExpressions.length === 1) {
60
- return [...transformedPreSpreadExpressions, context.transformExpression(postSpreadExpressions[0])];
61
- }
62
- // Use Array.concat and unpack the result of that as the last Expression
63
- const concatArguments = transformSpreadableExpressionsIntoArrayConcatArguments(context, postSpreadExpressions);
64
- const lastExpression = lua_ast_1.createUnpackCall(context, lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.ArrayConcat, undefined, ...concatArguments));
65
- return [...transformedPreSpreadExpressions, lastExpression];
66
- }
67
- exports.flattenSpreadExpressions = flattenSpreadExpressions;
34
+ exports.validateArguments = validateArguments;
68
35
  function transformArguments(context, params, signature, callContext) {
69
- const parameters = flattenSpreadExpressions(context, params);
70
- // Add context as first param if present
36
+ validateArguments(context, params, signature);
37
+ return (0, expression_list_1.transformExpressionList)(context, callContext ? [callContext, ...params] : params);
38
+ }
39
+ exports.transformArguments = transformArguments;
40
+ function transformCallWithArguments(context, callExpression, transformedArguments, argPrecedingStatements, callContext) {
41
+ let call = context.transformExpression(callExpression);
42
+ let transformedContext;
71
43
  if (callContext) {
72
- parameters.unshift(context.transformExpression(callContext));
73
- }
74
- if (signature && signature.parameters.length >= params.length) {
75
- for (const [index, param] of params.entries()) {
76
- const signatureParameter = signature.parameters[index];
77
- const paramType = context.checker.getTypeAtLocation(param);
78
- if (signatureParameter.valueDeclaration !== undefined) {
79
- const signatureType = context.checker.getTypeAtLocation(signatureParameter.valueDeclaration);
80
- assignment_validation_1.validateAssignment(context, param, paramType, signatureType, signatureParameter.name);
81
- }
44
+ transformedContext = context.transformExpression(callContext);
45
+ }
46
+ if (argPrecedingStatements.length > 0) {
47
+ if (transformedContext) {
48
+ transformedContext = (0, expression_list_1.moveToPrecedingTemp)(context, transformedContext, callContext);
82
49
  }
50
+ call = (0, expression_list_1.moveToPrecedingTemp)(context, call, callExpression);
51
+ context.addPrecedingStatements(argPrecedingStatements);
83
52
  }
84
- return parameters;
53
+ if (transformedContext) {
54
+ transformedArguments.unshift(transformedContext);
55
+ }
56
+ return [call, transformedArguments];
85
57
  }
86
- exports.transformArguments = transformArguments;
87
- function transformElementAccessCall(context, left, args, signature) {
88
- const transformedArguments = transformArguments(context, args, signature, ts.factory.createIdentifier("____self"));
58
+ function transformCallAndArguments(context, callExpression, params, signature, callContext) {
59
+ const [argPrecedingStatements, transformedArguments] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => transformArguments(context, params, signature, callContext));
60
+ return transformCallWithArguments(context, callExpression, transformedArguments, argPrecedingStatements);
61
+ }
62
+ exports.transformCallAndArguments = transformCallAndArguments;
63
+ function transformElementAccessCall(context, left, transformedArguments, argPrecedingStatements) {
89
64
  // Cache left-side if it has effects
90
- // (function() local ____self = context; return ____self[argument](parameters); end)()
91
- const argument = ts.isElementAccessExpression(left)
92
- ? access_1.transformElementAccessArgument(context, left)
93
- : lua.createStringLiteral(left.name.text);
94
- const selfIdentifier = lua.createIdentifier("____self");
65
+ // local ____self = context; return ____self[argument](parameters);
66
+ const selfIdentifier = lua.createIdentifier(context.createTempName("self"));
95
67
  const callContext = context.transformExpression(left.expression);
96
68
  const selfAssignment = lua.createVariableDeclarationStatement(selfIdentifier, callContext);
97
- const index = lua.createTableIndexExpression(selfIdentifier, argument);
98
- const callExpression = lua.createCallExpression(index, transformedArguments);
99
- return { statements: selfAssignment, result: callExpression };
69
+ context.addPrecedingStatements(selfAssignment);
70
+ const argument = ts.isElementAccessExpression(left)
71
+ ? (0, access_1.transformElementAccessArgument)(context, left)
72
+ : lua.createStringLiteral(left.name.text);
73
+ let index = lua.createTableIndexExpression(selfIdentifier, argument);
74
+ if (argPrecedingStatements.length > 0) {
75
+ // Cache index in temp if args had preceding statements
76
+ index = (0, expression_list_1.moveToPrecedingTemp)(context, index);
77
+ context.addPrecedingStatements(argPrecedingStatements);
78
+ }
79
+ return lua.createCallExpression(index, [selfIdentifier, ...transformedArguments]);
100
80
  }
101
81
  function transformContextualCallExpression(context, node, args, signature) {
82
+ if (ts.isOptionalChain(node)) {
83
+ return (0, optional_chaining_1.transformOptionalChain)(context, node);
84
+ }
102
85
  const left = ts.isCallExpression(node) ? node.expression : node.tag;
103
- if (ts.isPropertyAccessExpression(left) && ts.isIdentifier(left.name) && safe_names_1.isValidLuaIdentifier(left.name.text)) {
86
+ let [argPrecedingStatements, transformedArguments] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => transformArguments(context, args, signature));
87
+ if (ts.isPropertyAccessExpression(left) &&
88
+ ts.isIdentifier(left.name) &&
89
+ (0, safe_names_1.isValidLuaIdentifier)(left.name.text, context.options) &&
90
+ argPrecedingStatements.length === 0) {
104
91
  // table:name()
105
92
  const table = context.transformExpression(left.expression);
106
- if (ts.isOptionalChain(node)) {
107
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalMethodCall, node, table, lua.createStringLiteral(left.name.text, left.name), lua.createBooleanLiteral(node.questionDotToken !== undefined), // Require method is present if no ?.() call
108
- ...transformArguments(context, args, signature));
109
- }
110
- else {
111
- return lua.createMethodCallExpression(table, lua.createIdentifier(left.name.text, left.name), transformArguments(context, args, signature), node);
112
- }
93
+ return lua.createMethodCallExpression(table, lua.createIdentifier(left.name.text, left.name), transformedArguments, node);
113
94
  }
114
95
  else if (ts.isElementAccessExpression(left) || ts.isPropertyAccessExpression(left)) {
115
- if (typescript_1.isExpressionWithEvaluationEffect(left.expression)) {
116
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => transformElementAccessCall(context, left, args, signature), node);
96
+ if ((0, typescript_1.isExpressionWithEvaluationEffect)(left.expression)) {
97
+ return transformElementAccessCall(context, left, transformedArguments, argPrecedingStatements);
117
98
  }
118
99
  else {
119
- const callContext = context.transformExpression(left.expression);
120
- const expression = context.transformExpression(left);
121
- const transformedArguments = transformArguments(context, args, signature);
122
- return lua.createCallExpression(expression, [callContext, ...transformedArguments]);
100
+ let expression;
101
+ [expression, transformedArguments] = transformCallWithArguments(context, left, transformedArguments, argPrecedingStatements, left.expression);
102
+ return lua.createCallExpression(expression, transformedArguments, node);
123
103
  }
124
104
  }
125
105
  else if (ts.isIdentifier(left)) {
126
106
  const callContext = context.isStrict ? ts.factory.createNull() : ts.factory.createIdentifier("_G");
127
- const transformedArguments = transformArguments(context, args, signature, callContext);
128
- const expression = context.transformExpression(left);
107
+ let expression;
108
+ [expression, transformedArguments] = transformCallWithArguments(context, left, transformedArguments, argPrecedingStatements, callContext);
129
109
  return lua.createCallExpression(expression, transformedArguments, node);
130
110
  }
131
111
  else {
@@ -141,76 +121,90 @@ function transformPropertyCall(context, node) {
141
121
  return lua.createCallExpression(context.transformExpression(node.expression), parameters);
142
122
  }
143
123
  const signatureDeclaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration();
144
- if (!signatureDeclaration || function_context_1.getDeclarationContextType(context, signatureDeclaration) !== function_context_1.ContextType.Void) {
124
+ if (!signatureDeclaration || (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void) {
145
125
  // table:name()
146
126
  return transformContextualCallExpression(context, node, node.arguments, signature);
147
127
  }
148
128
  else {
149
129
  // table.name()
150
- const callPath = context.transformExpression(node.expression);
151
- const parameters = transformArguments(context, node.arguments, signature);
152
- if (ts.isOptionalChain(node)) {
153
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalFunctionCall, node, callPath, ...parameters);
154
- }
155
- else {
156
- return lua.createCallExpression(callPath, parameters, node);
157
- }
130
+ const [callPath, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature);
131
+ return lua.createCallExpression(callPath, parameters, node);
158
132
  }
159
133
  }
160
134
  function transformElementCall(context, node) {
161
135
  const signature = context.checker.getResolvedSignature(node);
162
136
  const signatureDeclaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration();
163
- if (!signatureDeclaration || function_context_1.getDeclarationContextType(context, signatureDeclaration) !== function_context_1.ContextType.Void) {
137
+ if (!signatureDeclaration || (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void) {
164
138
  // A contextual parameter must be given to this call expression
165
139
  return transformContextualCallExpression(context, node, node.arguments, signature);
166
140
  }
167
141
  else {
168
142
  // No context
169
- const expression = context.transformExpression(node.expression);
170
- const parameters = transformArguments(context, node.arguments, signature);
143
+ const [expression, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature);
171
144
  return lua.createCallExpression(expression, parameters);
172
145
  }
173
146
  }
174
147
  const transformCallExpression = (node, context) => {
175
- const wrapResultInTable = multi_1.isMultiReturnCall(context, node) && multi_1.shouldMultiReturnCallBeWrapped(context, node);
176
- const wrapResultInOptional = ts.isOptionalChain(node);
177
- const builtinResult = builtins_1.transformBuiltinCallExpression(context, node);
148
+ if (ts.isOptionalChain(node)) {
149
+ return (0, optional_chaining_1.transformOptionalChain)(context, node);
150
+ }
151
+ const optionalContinuation = ts.isIdentifier(node.expression)
152
+ ? (0, optional_chaining_1.getOptionalContinuationData)(node.expression)
153
+ : undefined;
154
+ const wrapResultInTable = (0, multi_1.isMultiReturnCall)(context, node) && (0, multi_1.shouldMultiReturnCallBeWrapped)(context, node);
155
+ const builtinResult = (0, builtins_1.transformBuiltinCallExpression)(context, node, optionalContinuation !== undefined);
178
156
  if (builtinResult) {
179
- return wrapResultInTable ? lua_ast_1.wrapInTable(builtinResult) : builtinResult;
157
+ if (optionalContinuation) {
158
+ context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(node));
159
+ }
160
+ return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(builtinResult) : builtinResult;
180
161
  }
181
- if (annotations_1.isTupleReturnCall(context, node)) {
182
- context.diagnostics.push(diagnostics_1.annotationRemoved(node, annotations_1.AnnotationKind.TupleReturn));
162
+ if ((0, annotations_1.isTupleReturnCall)(context, node)) {
163
+ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.TupleReturn));
183
164
  }
184
- if (operators_1.isOperatorMapping(context, node)) {
185
- return operators_1.transformOperatorMappingExpression(context, node);
165
+ if ((0, operators_1.isOperatorMapping)(context, node)) {
166
+ if (optionalContinuation) {
167
+ context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(node));
168
+ return lua.createNilLiteral();
169
+ }
170
+ return (0, operators_1.transformOperatorMappingExpression)(context, node);
186
171
  }
187
- if (table_1.isTableDeleteCall(context, node)) {
188
- context.diagnostics.push(diagnostics_1.invalidTableDeleteExpression(node));
189
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => ({ statements: table_1.transformTableDeleteExpression(context, node), result: lua.createNilLiteral() }), node);
172
+ if ((0, table_1.isTableDeleteCall)(context, node)) {
173
+ context.diagnostics.push((0, diagnostics_1.invalidTableDeleteExpression)(node));
174
+ context.addPrecedingStatements((0, table_1.transformTableDeleteExpression)(context, node));
175
+ return lua.createNilLiteral();
190
176
  }
191
- if (table_1.isTableGetCall(context, node)) {
192
- return table_1.transformTableGetExpression(context, node);
177
+ if ((0, table_1.isTableGetCall)(context, node)) {
178
+ if (optionalContinuation) {
179
+ context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(node));
180
+ return lua.createNilLiteral();
181
+ }
182
+ return (0, table_1.transformTableGetExpression)(context, node);
193
183
  }
194
- if (table_1.isTableHasCall(context, node)) {
195
- return table_1.transformTableHasExpression(context, node);
184
+ if ((0, table_1.isTableHasCall)(context, node)) {
185
+ if (optionalContinuation) {
186
+ context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(node));
187
+ return lua.createNilLiteral();
188
+ }
189
+ return (0, table_1.transformTableHasExpression)(context, node);
196
190
  }
197
- if (table_1.isTableSetCall(context, node)) {
198
- context.diagnostics.push(diagnostics_1.invalidTableSetExpression(node));
199
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => ({ statements: table_1.transformTableSetExpression(context, node), result: lua.createNilLiteral() }), node);
191
+ if ((0, table_1.isTableSetCall)(context, node)) {
192
+ context.diagnostics.push((0, diagnostics_1.invalidTableSetExpression)(node));
193
+ context.addPrecedingStatements((0, table_1.transformTableSetExpression)(context, node));
194
+ return lua.createNilLiteral();
200
195
  }
201
196
  if (ts.isPropertyAccessExpression(node.expression)) {
202
197
  const ownerType = context.checker.getTypeAtLocation(node.expression.expression);
203
- const annotations = annotations_1.getTypeAnnotations(ownerType);
198
+ const annotations = (0, annotations_1.getTypeAnnotations)(ownerType);
204
199
  if (annotations.has(annotations_1.AnnotationKind.LuaTable)) {
205
- context.diagnostics.push(diagnostics_1.annotationRemoved(node, annotations_1.AnnotationKind.LuaTable));
200
+ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.LuaTable));
206
201
  }
207
202
  const result = transformPropertyCall(context, node);
208
- // transformPropertyCall already wraps optional so no need to do so here
209
- return wrapResultInTable ? lua_ast_1.wrapInTable(result) : result;
203
+ return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(result) : result;
210
204
  }
211
205
  if (ts.isElementAccessExpression(node.expression)) {
212
206
  const result = transformElementCall(context, node);
213
- return wrapIfRequired(context, wrapResultInTable, wrapResultInOptional, result, node);
207
+ return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(result) : result;
214
208
  }
215
209
  const signature = context.checker.getResolvedSignature(node);
216
210
  // Handle super calls properly
@@ -218,31 +212,24 @@ const transformCallExpression = (node, context) => {
218
212
  const parameters = transformArguments(context, node.arguments, signature, ts.factory.createThis());
219
213
  return lua.createCallExpression(lua.createTableIndexExpression(context.transformExpression(ts.factory.createSuper()), lua.createStringLiteral("____constructor")), parameters);
220
214
  }
221
- const callPath = context.transformExpression(node.expression);
222
215
  const signatureDeclaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration();
223
- let parameters = [];
224
- if (signatureDeclaration && function_context_1.getDeclarationContextType(context, signatureDeclaration) === function_context_1.ContextType.Void) {
225
- parameters = transformArguments(context, node.arguments, signature);
216
+ let callPath;
217
+ let parameters;
218
+ const isContextualCall = !signatureDeclaration || (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void;
219
+ if (!isContextualCall) {
220
+ [callPath, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature);
226
221
  }
227
222
  else {
228
- const callContext = context.isStrict ? ts.factory.createNull() : ts.factory.createIdentifier("_G");
229
- parameters = transformArguments(context, node.arguments, signature, callContext);
223
+ // if is optionalContinuation, context will be handled by transformOptionalChain.
224
+ const useGlobalContext = !context.isStrict && optionalContinuation === undefined;
225
+ const callContext = useGlobalContext ? ts.factory.createIdentifier("_G") : ts.factory.createNull();
226
+ [callPath, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature, callContext);
230
227
  }
231
228
  const callExpression = lua.createCallExpression(callPath, parameters, node);
232
- return wrapIfRequired(context, wrapResultInTable, wrapResultInOptional, callExpression, node);
229
+ if (optionalContinuation && isContextualCall) {
230
+ optionalContinuation.contextualCall = callExpression;
231
+ }
232
+ return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(callExpression) : callExpression;
233
233
  };
234
234
  exports.transformCallExpression = transformCallExpression;
235
- function wrapIfRequired(context, shouldWrapInTable, shouldWrapOptional, call, node) {
236
- const wrappedOptional = shouldWrapOptional ? wrapOptionalCall(context, call, node) : call;
237
- return shouldWrapInTable ? lua_ast_1.wrapInTable(wrappedOptional) : wrappedOptional;
238
- }
239
- function wrapOptionalCall(context, call, node) {
240
- if (lua.isMethodCallExpression(call)) {
241
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalMethodCall, node, call.prefixExpression, lua.createStringLiteral(call.name.text), lua.createBooleanLiteral(node.questionDotToken !== undefined), // Require method is present if no ?.() call
242
- ...call.params);
243
- }
244
- else {
245
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalFunctionCall, node, call.expression, ...call.params);
246
- }
247
- }
248
235
  //# sourceMappingURL=call.js.map