typescript-to-lua 1.11.1 → 1.12.1

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 (41) hide show
  1. package/dist/CompilerOptions.d.ts +2 -1
  2. package/dist/CompilerOptions.js +1 -0
  3. package/dist/LuaLib.d.ts +4 -0
  4. package/dist/LuaLib.js +69 -19
  5. package/dist/LuaPrinter.js +2 -1
  6. package/dist/lualib/5.0/ArraySlice.lua +2 -10
  7. package/dist/lualib/5.0/ArraySplice.lua +1 -5
  8. package/dist/lualib/5.0/ParseFloat.lua +1 -5
  9. package/dist/lualib/5.0/StringCharCodeAt.lua +1 -5
  10. package/dist/lualib/5.0/lualib_bundle.lua +5 -25
  11. package/dist/lualib/universal/ArraySlice.lua +2 -10
  12. package/dist/lualib/universal/ArraySplice.lua +1 -5
  13. package/dist/lualib/universal/ParseFloat.lua +1 -5
  14. package/dist/lualib/universal/SparseArraySpread.lua +1 -5
  15. package/dist/lualib/universal/StringCharCodeAt.lua +1 -5
  16. package/dist/lualib/universal/lualib_bundle.lua +6 -30
  17. package/dist/lualib-build/plugin.js +1 -1
  18. package/dist/transformation/builtins/array.js +1 -1
  19. package/dist/transformation/utils/diagnostics.d.ts +6 -0
  20. package/dist/transformation/utils/diagnostics.js +3 -1
  21. package/dist/transformation/utils/language-extensions.d.ts +4 -0
  22. package/dist/transformation/utils/language-extensions.js +66 -1
  23. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  24. package/dist/transformation/utils/typescript/index.js +5 -1
  25. package/dist/transformation/utils/typescript/types.js +0 -3
  26. package/dist/transformation/visitors/expression-statement.d.ts +2 -2
  27. package/dist/transformation/visitors/expression-statement.js +4 -5
  28. package/dist/transformation/visitors/identifier.js +3 -1
  29. package/dist/transformation/visitors/language-extensions/operators.js +9 -15
  30. package/dist/transformation/visitors/language-extensions/table.d.ts +2 -4
  31. package/dist/transformation/visitors/language-extensions/table.js +32 -38
  32. package/dist/transformation/visitors/optional-chaining.d.ts +2 -1
  33. package/dist/transformation/visitors/optional-chaining.js +78 -32
  34. package/dist/transformation/visitors/void.js +1 -1
  35. package/dist/transpilation/diagnostics.js +1 -1
  36. package/dist/transpilation/find-lua-requires.d.ts +6 -0
  37. package/dist/transpilation/find-lua-requires.js +145 -0
  38. package/dist/transpilation/resolve.js +17 -25
  39. package/dist/transpilation/transpiler.d.ts +1 -0
  40. package/dist/transpilation/transpiler.js +13 -3
  41. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
- import { FunctionVisitor, TransformationContext } from "../context";
3
+ import { FunctionVisitor } from "../context";
4
4
  export declare const transformExpressionStatement: FunctionVisitor<ts.ExpressionStatement>;
5
- export declare function transformExpressionToStatement(context: TransformationContext, expression: ts.Expression): lua.Statement | undefined;
5
+ export declare function wrapInStatement(result: lua.Expression): lua.Statement | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformExpressionToStatement = exports.transformExpressionStatement = void 0;
3
+ exports.wrapInStatement = exports.transformExpressionStatement = void 0;
4
4
  const lua = require("../../LuaAST");
5
5
  const context_1 = require("../context");
6
6
  const binary_expression_1 = require("./binary-expression");
@@ -14,11 +14,10 @@ const transformExpressionStatement = (node, context) => {
14
14
  if (binaryExpressionResult) {
15
15
  return binaryExpressionResult;
16
16
  }
17
- return transformExpressionToStatement(context, node.expression);
17
+ return wrapInStatement(context.transformExpression(node.expression));
18
18
  };
19
19
  exports.transformExpressionStatement = transformExpressionStatement;
20
- function transformExpressionToStatement(context, expression) {
21
- const result = context.transformExpression(expression);
20
+ function wrapInStatement(result) {
22
21
  const isTempVariable = lua.isIdentifier(result) && result.symbolId === context_1.tempSymbolId;
23
22
  if (isTempVariable) {
24
23
  return undefined;
@@ -34,5 +33,5 @@ function transformExpressionToStatement(context, expression) {
34
33
  // Assign expression statements to dummy to make sure they're legal Lua
35
34
  return lua.createVariableDeclarationStatement(lua.createAnonymousIdentifier(), result);
36
35
  }
37
- exports.transformExpressionToStatement = transformExpressionToStatement;
36
+ exports.wrapInStatement = wrapInStatement;
38
37
  //# sourceMappingURL=expression-statement.js.map
@@ -21,7 +21,9 @@ function transformIdentifier(context, identifier) {
21
21
  exports.transformIdentifier = transformIdentifier;
22
22
  function transformNonValueIdentifier(context, identifier, symbol) {
23
23
  if ((0, optional_chaining_1.isOptionalContinuation)(identifier)) {
24
- return lua.createIdentifier(identifier.text, undefined, context_1.tempSymbolId);
24
+ const result = lua.createIdentifier(identifier.text, undefined, context_1.tempSymbolId);
25
+ (0, optional_chaining_1.getOptionalContinuationData)(identifier).usedIdentifiers.push(result);
26
+ return result;
25
27
  }
26
28
  const extensionKind = symbol
27
29
  ? (0, language_extensions_1.getExtensionKindForSymbol)(context, symbol)
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.operatorExtensionTransformers = void 0;
4
- const ts = require("typescript");
5
4
  const lua = require("../../../LuaAST");
6
5
  const utils_1 = require("../../../utils");
7
6
  const CompilerOptions_1 = require("../../../CompilerOptions");
8
7
  const diagnostics_1 = require("../../utils/diagnostics");
9
8
  const language_extensions_1 = require("../../utils/language-extensions");
9
+ const expression_list_1 = require("../expression-list");
10
10
  const binaryOperatorMappings = new Map([
11
11
  [language_extensions_1.ExtensionKind.AdditionOperatorType, lua.SyntaxKind.AdditionOperator],
12
12
  [language_extensions_1.ExtensionKind.AdditionOperatorMethodType, lua.SyntaxKind.AdditionOperator],
@@ -76,26 +76,20 @@ for (const kind of unaryOperatorMappings.keys()) {
76
76
  function transformBinaryOperator(context, node, kind) {
77
77
  if (requiresLua53.has(kind))
78
78
  checkHasLua53(context, node, kind);
79
- let args = node.arguments;
80
- if (args.length === 1 &&
81
- (ts.isPropertyAccessExpression(node.expression) || ts.isElementAccessExpression(node.expression))) {
82
- args = [node.expression.expression, ...args];
83
- }
79
+ const args = (0, language_extensions_1.getBinaryCallExtensionArgs)(context, node, kind);
80
+ if (!args)
81
+ return lua.createNilLiteral();
82
+ const [left, right] = (0, expression_list_1.transformOrderedExpressions)(context, args);
84
83
  const luaOperator = binaryOperatorMappings.get(kind);
85
84
  (0, utils_1.assert)(luaOperator);
86
- return lua.createBinaryExpression(context.transformExpression(args[0]), context.transformExpression(args[1]), luaOperator);
85
+ return lua.createBinaryExpression(left, right, luaOperator);
87
86
  }
88
87
  function transformUnaryOperator(context, node, kind) {
89
88
  if (requiresLua53.has(kind))
90
89
  checkHasLua53(context, node, kind);
91
- let arg;
92
- if (node.arguments.length === 0 &&
93
- (ts.isPropertyAccessExpression(node.expression) || ts.isElementAccessExpression(node.expression))) {
94
- arg = node.expression.expression;
95
- }
96
- else {
97
- arg = node.arguments[0];
98
- }
90
+ const arg = (0, language_extensions_1.getUnaryCallExtensionArg)(context, node, kind);
91
+ if (!arg)
92
+ return lua.createNilLiteral();
99
93
  const luaOperator = unaryOperatorMappings.get(kind);
100
94
  (0, utils_1.assert)(luaOperator);
101
95
  return lua.createUnaryExpression(context.transformExpression(arg), luaOperator);
@@ -1,9 +1,7 @@
1
1
  import * as ts from "typescript";
2
2
  import { TransformationContext } from "../../context";
3
3
  import { ExtensionKind } from "../../utils/language-extensions";
4
- import { LanguageExtensionCallTransformer } from "./call-extension";
4
+ import { LanguageExtensionCallTransformerMap } from "./call-extension";
5
5
  export declare function isTableNewCall(context: TransformationContext, node: ts.NewExpression): boolean;
6
6
  export declare const tableNewExtensions: ExtensionKind[];
7
- export declare const tableExtensionTransformers: {
8
- [P in ExtensionKind]?: LanguageExtensionCallTransformer;
9
- };
7
+ export declare const tableExtensionTransformers: LanguageExtensionCallTransformerMap;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.tableExtensionTransformers = exports.tableNewExtensions = exports.isTableNewCall = void 0;
4
- const ts = require("typescript");
5
4
  const lua = require("../../../LuaAST");
6
5
  const language_extensions_1 = require("../../utils/language-extensions");
7
6
  const expression_list_1 = require("../expression-list");
@@ -19,62 +18,57 @@ exports.tableExtensionTransformers = {
19
18
  [language_extensions_1.ExtensionKind.TableHasMethodType]: transformTableHasExpression,
20
19
  [language_extensions_1.ExtensionKind.TableSetType]: transformTableSetExpression,
21
20
  [language_extensions_1.ExtensionKind.TableSetMethodType]: transformTableSetExpression,
22
- [language_extensions_1.ExtensionKind.TableAddKeyType]: transformTableAddExpression,
23
- [language_extensions_1.ExtensionKind.TableAddKeyMethodType]: transformTableAddExpression,
21
+ [language_extensions_1.ExtensionKind.TableAddKeyType]: transformTableAddKeyExpression,
22
+ [language_extensions_1.ExtensionKind.TableAddKeyMethodType]: transformTableAddKeyExpression,
24
23
  };
25
24
  function transformTableDeleteExpression(context, node, extensionKind) {
26
- const args = node.arguments.slice();
27
- if (extensionKind === language_extensions_1.ExtensionKind.TableDeleteMethodType &&
28
- (ts.isPropertyAccessExpression(node.expression) || ts.isElementAccessExpression(node.expression))) {
29
- // In case of method (no table argument), push method owner to front of args list
30
- args.unshift(node.expression.expression);
25
+ const args = (0, language_extensions_1.getBinaryCallExtensionArgs)(context, node, extensionKind);
26
+ if (!args) {
27
+ return lua.createNilLiteral();
31
28
  }
32
- const [table, accessExpression] = (0, expression_list_1.transformExpressionList)(context, args);
29
+ const [table, key] = (0, expression_list_1.transformOrderedExpressions)(context, args);
33
30
  // arg0[arg1] = nil
34
- context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, accessExpression), lua.createNilLiteral(), node));
31
+ context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, key), lua.createNilLiteral(), node));
35
32
  return lua.createBooleanLiteral(true);
36
33
  }
37
- function transformWithTableArgument(context, node) {
38
- if (ts.isPropertyAccessExpression(node.expression) || ts.isElementAccessExpression(node.expression)) {
39
- return (0, expression_list_1.transformExpressionList)(context, [node.expression.expression, ...node.arguments]);
40
- }
41
- // todo: report diagnostic?
42
- return [lua.createNilLiteral(), ...(0, expression_list_1.transformExpressionList)(context, node.arguments)];
43
- }
44
34
  function transformTableGetExpression(context, node, extensionKind) {
45
- const args = extensionKind === language_extensions_1.ExtensionKind.TableGetMethodType
46
- ? transformWithTableArgument(context, node)
47
- : (0, expression_list_1.transformExpressionList)(context, node.arguments);
48
- const [table, accessExpression] = args;
35
+ const args = (0, language_extensions_1.getBinaryCallExtensionArgs)(context, node, extensionKind);
36
+ if (!args) {
37
+ return lua.createNilLiteral();
38
+ }
39
+ const [table, key] = (0, expression_list_1.transformOrderedExpressions)(context, args);
49
40
  // arg0[arg1]
50
- return lua.createTableIndexExpression(table, accessExpression, node);
41
+ return lua.createTableIndexExpression(table, key, node);
51
42
  }
52
43
  function transformTableHasExpression(context, node, extensionKind) {
53
- const args = extensionKind === language_extensions_1.ExtensionKind.TableHasMethodType
54
- ? transformWithTableArgument(context, node)
55
- : (0, expression_list_1.transformExpressionList)(context, node.arguments);
56
- const [table, accessExpression] = args;
44
+ const args = (0, language_extensions_1.getBinaryCallExtensionArgs)(context, node, extensionKind);
45
+ if (!args) {
46
+ return lua.createNilLiteral();
47
+ }
48
+ const [table, key] = (0, expression_list_1.transformOrderedExpressions)(context, args);
57
49
  // arg0[arg1]
58
- const tableIndexExpression = lua.createTableIndexExpression(table, accessExpression);
50
+ const tableIndexExpression = lua.createTableIndexExpression(table, key);
59
51
  // arg0[arg1] ~= nil
60
52
  return lua.createBinaryExpression(tableIndexExpression, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator, node);
61
53
  }
62
54
  function transformTableSetExpression(context, node, extensionKind) {
63
- const args = extensionKind === language_extensions_1.ExtensionKind.TableSetMethodType
64
- ? transformWithTableArgument(context, node)
65
- : (0, expression_list_1.transformExpressionList)(context, node.arguments);
66
- const [table, accessExpression, value] = args;
55
+ const args = (0, language_extensions_1.getNaryCallExtensionArgs)(context, node, extensionKind, 3);
56
+ if (!args) {
57
+ return lua.createNilLiteral();
58
+ }
59
+ const [table, key, value] = (0, expression_list_1.transformOrderedExpressions)(context, args);
67
60
  // arg0[arg1] = arg2
68
- context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, accessExpression), value, node));
61
+ context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, key), value, node));
69
62
  return lua.createNilLiteral();
70
63
  }
71
- function transformTableAddExpression(context, node, extensionKind) {
72
- const args = extensionKind === language_extensions_1.ExtensionKind.TableAddKeyMethodType
73
- ? transformWithTableArgument(context, node)
74
- : (0, expression_list_1.transformExpressionList)(context, node.arguments);
75
- const [table, value] = args;
64
+ function transformTableAddKeyExpression(context, node, extensionKind) {
65
+ const args = (0, language_extensions_1.getNaryCallExtensionArgs)(context, node, extensionKind, 2);
66
+ if (!args) {
67
+ return lua.createNilLiteral();
68
+ }
69
+ const [table, key] = (0, expression_list_1.transformOrderedExpressions)(context, args);
76
70
  // arg0[arg1] = true
77
- context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, value), lua.createBooleanLiteral(true), node));
71
+ context.addPrecedingStatements(lua.createAssignmentStatement(lua.createTableIndexExpression(table, key), lua.createBooleanLiteral(true), node));
78
72
  return lua.createNilLiteral();
79
73
  }
80
74
  //# sourceMappingURL=table.js.map
@@ -8,9 +8,10 @@ export interface ExpressionWithThisValue {
8
8
  export declare function captureThisValue(context: TransformationContext, expression: lua.Expression, thisValueCapture: lua.Identifier, tsOriginal: ts.Node): lua.Expression;
9
9
  export interface OptionalContinuation {
10
10
  contextualCall?: lua.CallExpression;
11
+ usedIdentifiers: lua.Identifier[];
11
12
  }
12
13
  export declare function isOptionalContinuation(node: ts.Node): boolean;
13
14
  export declare function getOptionalContinuationData(identifier: ts.Identifier): OptionalContinuation | undefined;
14
15
  export declare function transformOptionalChain(context: TransformationContext, node: ts.OptionalChain): lua.Expression;
15
- export declare function transformOptionalChainWithCapture(context: TransformationContext, node: ts.OptionalChain, thisValueCapture: lua.Identifier | undefined, isDelete?: ts.DeleteExpression): ExpressionWithThisValue;
16
+ export declare function transformOptionalChainWithCapture(context: TransformationContext, tsNode: ts.OptionalChain, thisValueCapture: lua.Identifier | undefined, isDelete?: ts.DeleteExpression): ExpressionWithThisValue;
16
17
  export declare function transformOptionalDeleteExpression(context: TransformationContext, node: ts.DeleteExpression, innerExpression: ts.OptionalChain): lua.BooleanLiteral;
@@ -8,6 +8,8 @@ const utils_1 = require("../../utils");
8
8
  const preceding_statements_1 = require("../utils/preceding-statements");
9
9
  const access_1 = require("./access");
10
10
  const expression_list_1 = require("./expression-list");
11
+ const typescript_1 = require("../utils/typescript");
12
+ const expression_statement_1 = require("./expression-statement");
11
13
  function skipNonNullChains(chain) {
12
14
  while (ts.isNonNullChain(chain)) {
13
15
  chain = chain.expression;
@@ -39,7 +41,7 @@ function transformExpressionWithThisValueCapture(context, node, thisValueCapture
39
41
  }
40
42
  // returns thisValueCapture exactly if a temp variable was used.
41
43
  function captureThisValue(context, expression, thisValueCapture, tsOriginal) {
42
- if (!(0, expression_list_1.shouldMoveToTemp)(context, expression, tsOriginal) && !isOptionalContinuation(tsOriginal)) {
44
+ if (!(0, expression_list_1.shouldMoveToTemp)(context, expression, tsOriginal)) {
43
45
  return expression;
44
46
  }
45
47
  const tempAssignment = lua.createAssignmentStatement(thisValueCapture, expression, tsOriginal);
@@ -52,7 +54,9 @@ const optionalContinuations = new WeakMap();
52
54
  function createOptionalContinuationIdentifier(text, tsOriginal) {
53
55
  const identifier = ts.factory.createIdentifier(text);
54
56
  ts.setOriginalNode(identifier, tsOriginal);
55
- optionalContinuations.set(identifier, {});
57
+ optionalContinuations.set(identifier, {
58
+ usedIdentifiers: [],
59
+ });
56
60
  return identifier;
57
61
  }
58
62
  function isOptionalContinuation(node) {
@@ -67,12 +71,11 @@ function transformOptionalChain(context, node) {
67
71
  return transformOptionalChainWithCapture(context, node, undefined).expression;
68
72
  }
69
73
  exports.transformOptionalChain = transformOptionalChain;
70
- function transformOptionalChainWithCapture(context, node, thisValueCapture, isDelete) {
71
- var _a;
72
- const luaTemp = context.createTempNameForNode(node);
73
- const { expression: tsLeftExpression, chain } = flattenChain(node);
74
+ function transformOptionalChainWithCapture(context, tsNode, thisValueCapture, isDelete) {
75
+ const luaTempName = context.createTempName("opt");
76
+ const { expression: tsLeftExpression, chain } = flattenChain(tsNode);
74
77
  // build temp.b.c.d
75
- const tsTemp = createOptionalContinuationIdentifier(luaTemp.text, tsLeftExpression);
78
+ const tsTemp = createOptionalContinuationIdentifier(luaTempName, tsLeftExpression);
76
79
  let tsRightExpression = tsTemp;
77
80
  for (const link of chain) {
78
81
  if (ts.isPropertyAccessExpression(link)) {
@@ -96,21 +99,20 @@ function transformOptionalChainWithCapture(context, node, thisValueCapture, isDe
96
99
  // transform right expression first to check if thisValue capture is needed
97
100
  // capture and return thisValue if requested from outside
98
101
  let returnThisValue;
99
- const [rightPrecedingStatements, rightAssignment] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => {
100
- let result;
101
- if (thisValueCapture) {
102
- ({ expression: result, thisValue: returnThisValue } = transformExpressionWithThisValueCapture(context, tsRightExpression, thisValueCapture));
103
- }
104
- else {
105
- result = context.transformExpression(tsRightExpression);
102
+ const [rightPrecedingStatements, rightExpression] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => {
103
+ if (!thisValueCapture) {
104
+ return context.transformExpression(tsRightExpression);
106
105
  }
107
- return lua.createAssignmentStatement(luaTemp, result);
106
+ const { expression: result, thisValue } = transformExpressionWithThisValueCapture(context, tsRightExpression, thisValueCapture);
107
+ returnThisValue = thisValue;
108
+ return result;
108
109
  });
109
110
  // transform left expression, handle thisValue if needed by rightExpression
110
111
  const thisValueCaptureName = context.createTempName("this");
111
112
  const leftThisValueTemp = lua.createIdentifier(thisValueCaptureName, undefined, context_1.tempSymbolId);
112
113
  let capturedThisValue;
113
- const rightContextualCall = (_a = getOptionalContinuationData(tsTemp)) === null || _a === void 0 ? void 0 : _a.contextualCall;
114
+ const optionalContinuationData = getOptionalContinuationData(tsTemp);
115
+ const rightContextualCall = optionalContinuationData === null || optionalContinuationData === void 0 ? void 0 : optionalContinuationData.contextualCall;
114
116
  const [leftPrecedingStatements, leftExpression] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => {
115
117
  let result;
116
118
  if (rightContextualCall) {
@@ -146,22 +148,66 @@ function transformOptionalChainWithCapture(context, node, thisValueCapture, isDe
146
148
  }
147
149
  }
148
150
  }
149
- // <left preceding statements>
150
- // local temp = <left>
151
- // if temp ~= nil then
152
- // <right preceding statements>
153
- // temp = temp.b.c.d
154
- // end
155
- // return temp
156
- context.addPrecedingStatements([
157
- ...leftPrecedingStatements,
158
- lua.createVariableDeclarationStatement(luaTemp, leftExpression),
159
- lua.createIfStatement(lua.createBinaryExpression(luaTemp, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator), lua.createBlock([...rightPrecedingStatements, rightAssignment])),
160
- ]);
161
- return {
162
- expression: luaTemp,
163
- thisValue: returnThisValue,
164
- };
151
+ // evaluate optional chain
152
+ context.addPrecedingStatements(leftPrecedingStatements);
153
+ // try use existing variable instead of creating new one, if possible
154
+ let leftIdentifier;
155
+ const usedLuaIdentifiers = optionalContinuationData === null || optionalContinuationData === void 0 ? void 0 : optionalContinuationData.usedIdentifiers;
156
+ const reuseLeftIdentifier = usedLuaIdentifiers &&
157
+ usedLuaIdentifiers.length > 0 &&
158
+ lua.isIdentifier(leftExpression) &&
159
+ (rightPrecedingStatements.length === 0 || !(0, expression_list_1.shouldMoveToTemp)(context, leftExpression, tsLeftExpression));
160
+ if (reuseLeftIdentifier) {
161
+ leftIdentifier = leftExpression;
162
+ for (const usedIdentifier of usedLuaIdentifiers) {
163
+ usedIdentifier.text = leftIdentifier.text;
164
+ }
165
+ }
166
+ else {
167
+ leftIdentifier = lua.createIdentifier(luaTempName, undefined, context_1.tempSymbolId);
168
+ context.addPrecedingStatements(lua.createVariableDeclarationStatement(leftIdentifier, leftExpression));
169
+ }
170
+ if (!(0, typescript_1.expressionResultIsUsed)(tsNode) || isDelete) {
171
+ // if left ~= nil then
172
+ // <right preceding statements>
173
+ // <right expression>
174
+ // end
175
+ const innerExpression = (0, expression_statement_1.wrapInStatement)(rightExpression);
176
+ const innerStatements = rightPrecedingStatements;
177
+ if (innerExpression)
178
+ innerStatements.push(innerExpression);
179
+ context.addPrecedingStatements(lua.createIfStatement(lua.createBinaryExpression(leftIdentifier, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator), lua.createBlock(innerStatements)));
180
+ return { expression: lua.createNilLiteral(), thisValue: returnThisValue };
181
+ }
182
+ else if (rightPrecedingStatements.length === 0 &&
183
+ !(0, typescript_1.canBeFalsyWhenNotNull)(context, context.checker.getTypeAtLocation(tsLeftExpression))) {
184
+ // return a && a.b
185
+ return {
186
+ expression: lua.createBinaryExpression(leftIdentifier, rightExpression, lua.SyntaxKind.AndOperator, tsNode),
187
+ thisValue: returnThisValue,
188
+ };
189
+ }
190
+ else {
191
+ let resultIdentifier;
192
+ if (!reuseLeftIdentifier) {
193
+ // reuse temp variable for output
194
+ resultIdentifier = leftIdentifier;
195
+ }
196
+ else {
197
+ resultIdentifier = lua.createIdentifier(context.createTempName("opt_result"), undefined, context_1.tempSymbolId);
198
+ context.addPrecedingStatements(lua.createVariableDeclarationStatement(resultIdentifier));
199
+ }
200
+ // if left ~= nil then
201
+ // <right preceding statements>
202
+ // result = <right expression>
203
+ // end
204
+ // return result
205
+ context.addPrecedingStatements(lua.createIfStatement(lua.createBinaryExpression(leftIdentifier, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator), lua.createBlock([
206
+ ...rightPrecedingStatements,
207
+ lua.createAssignmentStatement(resultIdentifier, rightExpression),
208
+ ])));
209
+ return { expression: resultIdentifier, thisValue: returnThisValue };
210
+ }
165
211
  }
166
212
  exports.transformOptionalChainWithCapture = transformOptionalChainWithCapture;
167
213
  function transformOptionalDeleteExpression(context, node, innerExpression) {
@@ -8,7 +8,7 @@ const expression_statement_1 = require("./expression-statement");
8
8
  const transformVoidExpression = (node, context) => {
9
9
  // If content is a literal it is safe to replace the entire expression with nil
10
10
  if (!ts.isLiteralExpression(node.expression)) {
11
- const statements = (0, expression_statement_1.transformExpressionToStatement)(context, node.expression);
11
+ const statements = (0, expression_statement_1.wrapInStatement)(context.transformExpression(node.expression));
12
12
  if (statements)
13
13
  context.addPrecedingStatements(statements);
14
14
  }
@@ -17,7 +17,7 @@ exports.usingLuaBundleWithInlineMightGenerateDuplicateCode = (0, utils_1.createS
17
17
  messageText: "Using 'luaBundle' with 'luaLibImport: \"inline\"' might generate duplicate code. " +
18
18
  "It is recommended to use 'luaLibImport: \"require\"'.",
19
19
  }));
20
- exports.cannotBundleLibrary = createDiagnosticFactory(() => 'Cannot bundle probjects with"buildmode": "library". Projects including the library can still bundle (which will include external library files).');
20
+ exports.cannotBundleLibrary = createDiagnosticFactory(() => 'Cannot bundle projects with "buildmode": "library". Projects including the library can still bundle (which will include external library files).');
21
21
  exports.unsupportedJsxEmit = createDiagnosticFactory(() => 'JSX is only supported with "react" jsx option.');
22
22
  exports.pathsWithoutBaseUrl = createDiagnosticFactory(() => "When configuring 'paths' in tsconfig.json, the option 'baseUrl' must also be provided.");
23
23
  //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1,6 @@
1
+ export interface LuaRequire {
2
+ from: number;
3
+ to: number;
4
+ requirePath: string;
5
+ }
6
+ export declare function findLuaRequires(lua: string): LuaRequire[];
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findLuaRequires = void 0;
4
+ function findLuaRequires(lua) {
5
+ return findRequire(lua, 0);
6
+ }
7
+ exports.findLuaRequires = findLuaRequires;
8
+ function findRequire(lua, offset) {
9
+ const result = [];
10
+ while (offset < lua.length) {
11
+ const c = lua[offset];
12
+ if (c === "r" &&
13
+ (offset === 0 ||
14
+ isWhitespace(lua[offset - 1]) ||
15
+ lua[offset - 1] === "]" ||
16
+ lua[offset - 1] === "(" ||
17
+ lua[offset - 1] === "[")) {
18
+ const m = matchRequire(lua, offset);
19
+ if (m.matched) {
20
+ offset = m.match.to + 1;
21
+ result.push(m.match);
22
+ }
23
+ else {
24
+ offset = m.end;
25
+ }
26
+ }
27
+ else if (c === '"' || c === "'") {
28
+ offset = readString(lua, offset, c).offset; // Skip string and surrounding quotes
29
+ }
30
+ else if (c === "-" && offset + 1 < lua.length && lua[offset + 1] === "-") {
31
+ offset = skipComment(lua, offset);
32
+ }
33
+ else {
34
+ offset++;
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ function matchRequire(lua, offset) {
40
+ const start = offset;
41
+ for (const c of "require") {
42
+ if (offset > lua.length) {
43
+ return { matched: false, end: offset };
44
+ }
45
+ if (lua[offset] !== c) {
46
+ return { matched: false, end: offset };
47
+ }
48
+ offset++;
49
+ }
50
+ offset = skipWhitespace(lua, offset);
51
+ let hasParentheses = false;
52
+ if (offset > lua.length) {
53
+ return { matched: false, end: offset };
54
+ }
55
+ else {
56
+ if (lua[offset] === "(") {
57
+ hasParentheses = true;
58
+ offset++;
59
+ offset = skipWhitespace(lua, offset);
60
+ }
61
+ else if (lua[offset] === '"' || lua[offset] === "'") {
62
+ // require without parentheses
63
+ }
64
+ else {
65
+ // otherwise fail match
66
+ return { matched: false, end: offset };
67
+ }
68
+ }
69
+ if (offset > lua.length || (lua[offset] !== '"' && lua[offset] !== "'")) {
70
+ return { matched: false, end: offset };
71
+ }
72
+ const { value: requireString, offset: offsetAfterString } = readString(lua, offset, lua[offset]);
73
+ offset = offsetAfterString; // Skip string and surrounding quotes
74
+ if (hasParentheses) {
75
+ offset = skipWhitespace(lua, offset);
76
+ if (offset > lua.length || lua[offset] !== ")") {
77
+ return { matched: false, end: offset };
78
+ }
79
+ offset++;
80
+ }
81
+ return { matched: true, match: { from: start, to: offset - 1, requirePath: requireString } };
82
+ }
83
+ function readString(lua, offset, delimiter) {
84
+ expect(lua, offset, delimiter);
85
+ offset++;
86
+ let start = offset;
87
+ let result = "";
88
+ let escaped = false;
89
+ while (offset < lua.length && (lua[offset] !== delimiter || escaped)) {
90
+ if (lua[offset] === "\\" && !escaped) {
91
+ escaped = true;
92
+ }
93
+ else {
94
+ if (lua[offset] === delimiter) {
95
+ result += lua.slice(start, offset - 1);
96
+ start = offset;
97
+ }
98
+ escaped = false;
99
+ }
100
+ offset++;
101
+ }
102
+ if (offset < lua.length) {
103
+ expect(lua, offset, delimiter);
104
+ }
105
+ result += lua.slice(start, offset);
106
+ return { value: result, offset: offset + 1 };
107
+ }
108
+ function skipWhitespace(lua, offset) {
109
+ while (offset < lua.length && isWhitespace(lua[offset])) {
110
+ offset++;
111
+ }
112
+ return offset;
113
+ }
114
+ function isWhitespace(c) {
115
+ return c === " " || c === "\t" || c === "\r" || c === "\n";
116
+ }
117
+ function skipComment(lua, offset) {
118
+ expect(lua, offset, "-");
119
+ expect(lua, offset + 1, "-");
120
+ offset += 2;
121
+ if (offset + 1 < lua.length && lua[offset] === "[" && lua[offset + 1] === "[") {
122
+ return skipMultiLineComment(lua, offset);
123
+ }
124
+ else {
125
+ return skipSingleLineComment(lua, offset);
126
+ }
127
+ }
128
+ function skipMultiLineComment(lua, offset) {
129
+ while (offset < lua.length && !(lua[offset] === "]" && lua[offset - 1] === "]")) {
130
+ offset++;
131
+ }
132
+ return offset + 1;
133
+ }
134
+ function skipSingleLineComment(lua, offset) {
135
+ while (offset < lua.length && lua[offset] !== "\n") {
136
+ offset++;
137
+ }
138
+ return offset + 1;
139
+ }
140
+ function expect(lua, offset, char) {
141
+ if (lua[offset] !== char) {
142
+ throw new Error(`Expected ${char} at position ${offset} but found ${lua[offset]}`);
143
+ }
144
+ }
145
+ //# sourceMappingURL=find-lua-requires.js.map