typescript-to-lua 1.4.4 → 1.6.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 (48) hide show
  1. package/dist/CompilerOptions.d.ts +1 -0
  2. package/dist/cli/parse.js +5 -0
  3. package/dist/lualib/Await.lua +21 -34
  4. package/dist/lualib/Map.lua +4 -6
  5. package/dist/lualib/lualib_bundle.lua +25 -40
  6. package/dist/lualib-build/plugin.d.ts +1 -1
  7. package/dist/transformation/builtins/array.d.ts +2 -3
  8. package/dist/transformation/builtins/array.js +8 -10
  9. package/dist/transformation/builtins/console.d.ts +2 -2
  10. package/dist/transformation/builtins/console.js +8 -9
  11. package/dist/transformation/builtins/function.d.ts +1 -2
  12. package/dist/transformation/builtins/function.js +5 -6
  13. package/dist/transformation/builtins/index.js +22 -23
  14. package/dist/transformation/builtins/math.d.ts +1 -2
  15. package/dist/transformation/builtins/math.js +3 -4
  16. package/dist/transformation/builtins/number.d.ts +3 -3
  17. package/dist/transformation/builtins/number.js +10 -12
  18. package/dist/transformation/builtins/object.d.ts +2 -3
  19. package/dist/transformation/builtins/object.js +16 -17
  20. package/dist/transformation/builtins/promise.d.ts +1 -2
  21. package/dist/transformation/builtins/promise.js +5 -6
  22. package/dist/transformation/builtins/string.d.ts +2 -3
  23. package/dist/transformation/builtins/string.js +7 -9
  24. package/dist/transformation/builtins/symbol.d.ts +2 -2
  25. package/dist/transformation/builtins/symbol.js +6 -7
  26. package/dist/transformation/context/context.d.ts +2 -2
  27. package/dist/transformation/context/context.js +1 -1
  28. package/dist/transformation/utils/export.d.ts +1 -1
  29. package/dist/transformation/utils/function-context.js +7 -2
  30. package/dist/transformation/utils/lua-ast.d.ts +1 -1
  31. package/dist/transformation/utils/lua-ast.js +83 -1
  32. package/dist/transformation/visitors/async-await.d.ts +1 -1
  33. package/dist/transformation/visitors/async-await.js +7 -14
  34. package/dist/transformation/visitors/binary-expression/assignments.js +9 -23
  35. package/dist/transformation/visitors/binary-expression/compound.d.ts +4 -1
  36. package/dist/transformation/visitors/binary-expression/compound.js +10 -19
  37. package/dist/transformation/visitors/call.d.ts +1 -3
  38. package/dist/transformation/visitors/call.js +31 -16
  39. package/dist/transformation/visitors/errors.js +52 -11
  40. package/dist/transformation/visitors/expression-list.js +4 -1
  41. package/dist/transformation/visitors/function.js +1 -1
  42. package/dist/transformation/visitors/return.js +5 -4
  43. package/dist/transformation/visitors/variable-declaration.d.ts +1 -1
  44. package/dist/transformation/visitors/variable-declaration.js +11 -14
  45. package/dist/transpilation/index.js +9 -4
  46. package/dist/transpilation/resolve.js +1 -1
  47. package/dist/transpilation/transpiler.js +3 -2
  48. package/package.json +9 -9
@@ -5,41 +5,40 @@ const lua = require("../../LuaAST");
5
5
  const diagnostics_1 = require("../utils/diagnostics");
6
6
  const lualib_1 = require("../utils/lualib");
7
7
  const call_1 = require("../visitors/call");
8
- function transformObjectConstructorCall(context, expression) {
9
- const method = expression.expression;
10
- const args = (0, call_1.transformArguments)(context, expression.arguments);
11
- const methodName = method.name.text;
8
+ function transformObjectConstructorCall(context, node, calledMethod) {
9
+ const args = (0, call_1.transformArguments)(context, node.arguments);
10
+ const methodName = calledMethod.name.text;
12
11
  switch (methodName) {
13
12
  case "assign":
14
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectAssign, expression, ...args);
13
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectAssign, node, ...args);
15
14
  case "defineProperty":
16
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectDefineProperty, expression, ...args);
15
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectDefineProperty, node, ...args);
17
16
  case "entries":
18
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectEntries, expression, ...args);
17
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectEntries, node, ...args);
19
18
  case "fromEntries":
20
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectFromEntries, expression, ...args);
19
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectFromEntries, node, ...args);
21
20
  case "getOwnPropertyDescriptor":
22
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectGetOwnPropertyDescriptor, expression, ...args);
21
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectGetOwnPropertyDescriptor, node, ...args);
23
22
  case "getOwnPropertyDescriptors":
24
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectGetOwnPropertyDescriptors, expression, ...args);
23
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectGetOwnPropertyDescriptors, node, ...args);
25
24
  case "keys":
26
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectKeys, expression, ...args);
25
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectKeys, node, ...args);
27
26
  case "values":
28
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectValues, expression, ...args);
27
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ObjectValues, node, ...args);
29
28
  default:
30
- context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(method.name, "Object", methodName));
29
+ context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "Object", methodName));
31
30
  }
32
31
  }
33
32
  exports.transformObjectConstructorCall = transformObjectConstructorCall;
34
- function transformObjectPrototypeCall(context, node, expression) {
33
+ function transformObjectPrototypeCall(context, node, calledMethod) {
35
34
  const signature = context.checker.getResolvedSignature(node);
36
- const name = expression.name.text;
35
+ const name = calledMethod.name.text;
37
36
  switch (name) {
38
37
  case "toString":
39
38
  const toStringIdentifier = lua.createIdentifier("tostring");
40
- return lua.createCallExpression(toStringIdentifier, [context.transformExpression(expression.expression)], node);
39
+ return lua.createCallExpression(toStringIdentifier, [context.transformExpression(calledMethod.expression)], node);
41
40
  case "hasOwnProperty":
42
- const expr = context.transformExpression(expression.expression);
41
+ const expr = context.transformExpression(calledMethod.expression);
43
42
  const parameters = (0, call_1.transformArguments)(context, node.arguments, signature);
44
43
  const rawGetIdentifier = lua.createIdentifier("rawget");
45
44
  const rawGetCall = lua.createCallExpression(rawGetIdentifier, [expr, ...parameters]);
@@ -1,8 +1,7 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
3
  import { TransformationContext } from "../context";
4
- import { PropertyCallExpression } from "../visitors/call";
5
4
  export declare function isPromiseClass(context: TransformationContext, node: ts.Identifier): boolean;
6
5
  export declare function createPromiseIdentifier(original: ts.Node): lua.Identifier;
7
- export declare function transformPromiseConstructorCall(context: TransformationContext, node: PropertyCallExpression): lua.Expression | undefined;
6
+ export declare function transformPromiseConstructorCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.Expression | undefined;
8
7
  export declare function createStaticPromiseFunctionAccessor(functionName: string, node: ts.Node): lua.TableIndexExpression;
@@ -15,11 +15,10 @@ function createPromiseIdentifier(original) {
15
15
  return lua.createIdentifier("__TS__Promise", original);
16
16
  }
17
17
  exports.createPromiseIdentifier = createPromiseIdentifier;
18
- function transformPromiseConstructorCall(context, node) {
19
- const expression = node.expression;
18
+ function transformPromiseConstructorCall(context, node, calledMethod) {
20
19
  const signature = context.checker.getResolvedSignature(node);
21
20
  const params = (0, call_1.transformArguments)(context, node.arguments, signature);
22
- const expressionName = expression.name.text;
21
+ const expressionName = calledMethod.name.text;
23
22
  switch (expressionName) {
24
23
  case "all":
25
24
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.PromiseAll, node, ...params);
@@ -31,12 +30,12 @@ function transformPromiseConstructorCall(context, node) {
31
30
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.PromiseRace, node, ...params);
32
31
  case "resolve":
33
32
  (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Promise);
34
- return lua.createCallExpression(createStaticPromiseFunctionAccessor("resolve", expression), params, node);
33
+ return lua.createCallExpression(createStaticPromiseFunctionAccessor("resolve", calledMethod), params, node);
35
34
  case "reject":
36
35
  (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Promise);
37
- return lua.createCallExpression(createStaticPromiseFunctionAccessor("reject", expression), params, node);
36
+ return lua.createCallExpression(createStaticPromiseFunctionAccessor("reject", calledMethod), params, node);
38
37
  default:
39
- context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(expression.name, "Promise", expressionName));
38
+ context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "Promise", expressionName));
40
39
  }
41
40
  }
42
41
  exports.transformPromiseConstructorCall = transformPromiseConstructorCall;
@@ -1,7 +1,6 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
3
  import { TransformationContext } from "../context";
4
- import { PropertyCallExpression } from "../visitors/call";
5
- export declare function transformStringPrototypeCall(context: TransformationContext, node: PropertyCallExpression): lua.Expression | undefined;
6
- export declare function transformStringConstructorCall(context: TransformationContext, node: PropertyCallExpression): lua.Expression | undefined;
4
+ export declare function transformStringPrototypeCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.Expression | undefined;
5
+ export declare function transformStringConstructorCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.Expression | undefined;
7
6
  export declare function transformStringProperty(context: TransformationContext, node: ts.PropertyAccessExpression): lua.UnaryExpression | undefined;
@@ -10,11 +10,10 @@ function createStringCall(methodName, tsOriginal, ...params) {
10
10
  const stringIdentifier = lua.createIdentifier("string");
11
11
  return lua.createCallExpression(lua.createTableIndexExpression(stringIdentifier, lua.createStringLiteral(methodName)), params, tsOriginal);
12
12
  }
13
- function transformStringPrototypeCall(context, node) {
14
- const expression = node.expression;
13
+ function transformStringPrototypeCall(context, node, calledMethod) {
15
14
  const signature = context.checker.getResolvedSignature(node);
16
- const [caller, params] = (0, call_1.transformCallAndArguments)(context, expression.expression, node.arguments, signature);
17
- const expressionName = expression.name.text;
15
+ const [caller, params] = (0, call_1.transformCallAndArguments)(context, calledMethod.expression, node.arguments, signature);
16
+ const expressionName = calledMethod.name.text;
18
17
  switch (expressionName) {
19
18
  case "replace":
20
19
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.StringReplace, node, caller, ...params);
@@ -102,20 +101,19 @@ function transformStringPrototypeCall(context, node) {
102
101
  case "padEnd":
103
102
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.StringPadEnd, node, caller, ...params);
104
103
  default:
105
- context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(expression.name, "string", expressionName));
104
+ context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "string", expressionName));
106
105
  }
107
106
  }
108
107
  exports.transformStringPrototypeCall = transformStringPrototypeCall;
109
- function transformStringConstructorCall(context, node) {
110
- const expression = node.expression;
108
+ function transformStringConstructorCall(context, node, calledMethod) {
111
109
  const signature = context.checker.getResolvedSignature(node);
112
110
  const params = (0, call_1.transformArguments)(context, node.arguments, signature);
113
- const expressionName = expression.name.text;
111
+ const expressionName = calledMethod.name.text;
114
112
  switch (expressionName) {
115
113
  case "fromCharCode":
116
114
  return lua.createCallExpression(lua.createTableIndexExpression(lua.createIdentifier("string"), lua.createStringLiteral("char")), params, node);
117
115
  default:
118
- context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(expression.name, "String", expressionName));
116
+ context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "String", expressionName));
119
117
  }
120
118
  }
121
119
  exports.transformStringConstructorCall = transformStringConstructorCall;
@@ -1,4 +1,4 @@
1
+ import ts = require("typescript");
1
2
  import * as lua from "../../LuaAST";
2
3
  import { TransformationContext } from "../context";
3
- import { PropertyCallExpression } from "../visitors/call";
4
- export declare function transformSymbolConstructorCall(context: TransformationContext, expression: PropertyCallExpression): lua.CallExpression | undefined;
4
+ export declare function transformSymbolConstructorCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.CallExpression | undefined;
@@ -5,20 +5,19 @@ const lua = require("../../LuaAST");
5
5
  const diagnostics_1 = require("../utils/diagnostics");
6
6
  const lualib_1 = require("../utils/lualib");
7
7
  const call_1 = require("../visitors/call");
8
- function transformSymbolConstructorCall(context, expression) {
9
- const method = expression.expression;
10
- const signature = context.checker.getResolvedSignature(expression);
11
- const parameters = (0, call_1.transformArguments)(context, expression.arguments, signature);
12
- const methodName = method.name.text;
8
+ function transformSymbolConstructorCall(context, node, calledMethod) {
9
+ const signature = context.checker.getResolvedSignature(node);
10
+ const parameters = (0, call_1.transformArguments)(context, node.arguments, signature);
11
+ const methodName = calledMethod.name.text;
13
12
  switch (methodName) {
14
13
  case "for":
15
14
  case "keyFor":
16
15
  (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.SymbolRegistry);
17
16
  const upperMethodName = methodName[0].toUpperCase() + methodName.slice(1);
18
17
  const functionIdentifier = lua.createIdentifier(`__TS__SymbolRegistry${upperMethodName}`);
19
- return lua.createCallExpression(functionIdentifier, parameters, expression);
18
+ return lua.createCallExpression(functionIdentifier, parameters, node);
20
19
  default:
21
- context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(method.name, "Symbol", methodName));
20
+ context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "Symbol", methodName));
22
21
  }
23
22
  }
24
23
  exports.transformSymbolConstructorCall = transformSymbolConstructorCall;
@@ -16,7 +16,7 @@ export interface EmitResolver {
16
16
  moduleExportsSomeValue(moduleReferenceExpression: ts.Expression): boolean;
17
17
  getAllAccessorDeclarations(declaration: ts.AccessorDeclaration): AllAccessorDeclarations;
18
18
  }
19
- export interface DiagnosticsProducingTypeChecker extends ts.TypeChecker {
19
+ export interface TypeCheckerWithEmitResolver extends ts.TypeChecker {
20
20
  getEmitResolver(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): EmitResolver;
21
21
  }
22
22
  export declare class TransformationContext {
@@ -24,7 +24,7 @@ export declare class TransformationContext {
24
24
  sourceFile: ts.SourceFile;
25
25
  private visitorMap;
26
26
  readonly diagnostics: ts.Diagnostic[];
27
- readonly checker: DiagnosticsProducingTypeChecker;
27
+ readonly checker: TypeCheckerWithEmitResolver;
28
28
  readonly resolver: EmitResolver;
29
29
  readonly precedingStatementsStack: lua.Statement[][];
30
30
  readonly options: CompilerOptions;
@@ -16,7 +16,7 @@ class TransformationContext {
16
16
  this.sourceFile = sourceFile;
17
17
  this.visitorMap = visitorMap;
18
18
  this.diagnostics = [];
19
- this.checker = this.program.getDiagnosticsProducingTypeChecker();
19
+ this.checker = this.program.getTypeChecker();
20
20
  this.precedingStatementsStack = [];
21
21
  this.options = this.program.getCompilerOptions();
22
22
  this.luaTarget = (_a = this.options.luaTarget) !== null && _a !== void 0 ? _a : CompilerOptions_1.LuaTarget.Universal;
@@ -3,7 +3,7 @@ import * as lua from "../../LuaAST";
3
3
  import { TransformationContext } from "../context";
4
4
  export declare function hasDefaultExportModifier(node: ts.Node): boolean;
5
5
  export declare function hasExportModifier(node: ts.Node): boolean;
6
- export declare const createDefaultExportStringLiteral: (original?: ts.Node | undefined) => lua.StringLiteral;
6
+ export declare const createDefaultExportStringLiteral: (original?: ts.Node) => lua.StringLiteral;
7
7
  export declare function getExportedSymbolDeclaration(symbol: ts.Symbol): ts.Declaration | undefined;
8
8
  export declare function getSymbolFromIdentifier(context: TransformationContext, identifier: lua.Identifier): ts.Symbol | undefined;
9
9
  export declare function getIdentifierExportScope(context: TransformationContext, identifier: lua.Identifier): ts.SourceFile | ts.ModuleDeclaration | undefined;
@@ -59,8 +59,13 @@ function getDeclarationContextType({ program }, signatureDeclaration) {
59
59
  }
60
60
  // When using --noImplicitSelf and the signature is defined in a file targeted by the program apply the @noSelf rule.
61
61
  const options = program.getCompilerOptions();
62
- if (options.noImplicitSelf && program.getRootFileNames().includes(signatureDeclaration.getSourceFile().fileName)) {
63
- return ContextType.Void;
62
+ if (options.noImplicitSelf) {
63
+ const sourceFile = program.getSourceFile(signatureDeclaration.getSourceFile().fileName);
64
+ if (sourceFile !== undefined &&
65
+ !program.isSourceFileDefaultLibrary(sourceFile) &&
66
+ !program.isSourceFileFromExternalLibrary(sourceFile)) {
67
+ return ContextType.Void;
68
+ }
64
69
  }
65
70
  // Walk up to find @noSelf or @noSelfInFile
66
71
  if (hasNoSelfAncestor(signatureDeclaration)) {
@@ -13,4 +13,4 @@ export declare function wrapInTable(...expressions: lua.Expression[]): lua.Table
13
13
  export declare function wrapInToStringForConcat(expression: lua.Expression): lua.Expression;
14
14
  export declare function createHoistableVariableDeclarationStatement(context: TransformationContext, identifier: lua.Identifier, initializer?: lua.Expression, tsOriginal?: ts.Node): lua.AssignmentStatement | lua.VariableDeclarationStatement;
15
15
  export declare function createLocalOrExportedOrGlobalDeclaration(context: TransformationContext, lhs: lua.Identifier | lua.Identifier[], rhs?: lua.Expression | lua.Expression[], tsOriginal?: ts.Node, overrideExportScope?: ts.SourceFile | ts.ModuleDeclaration): lua.Statement[];
16
- export declare const createNaN: (tsOriginal?: ts.Node | undefined) => lua.BinaryExpression;
16
+ export declare const createNaN: (tsOriginal?: ts.Node) => lua.BinaryExpression;
@@ -104,6 +104,7 @@ function hasMultipleReferences(scope, identifiers) {
104
104
  function createLocalOrExportedOrGlobalDeclaration(context, lhs, rhs, tsOriginal, overrideExportScope) {
105
105
  let declaration;
106
106
  let assignment;
107
+ const noImplicitGlobalVariables = context.options.noImplicitGlobalVariables === true;
107
108
  const isFunctionDeclaration = tsOriginal !== undefined && ts.isFunctionDeclaration(tsOriginal);
108
109
  const identifiers = (0, utils_1.castArray)(lhs);
109
110
  if (identifiers.length === 0) {
@@ -122,7 +123,7 @@ function createLocalOrExportedOrGlobalDeclaration(context, lhs, rhs, tsOriginal,
122
123
  else {
123
124
  const scope = (0, scope_1.peekScope)(context);
124
125
  const isTopLevelVariable = scope.type === scope_1.ScopeType.File;
125
- if (context.isModule || !isTopLevelVariable) {
126
+ if (context.isModule || !isTopLevelVariable || noImplicitGlobalVariables) {
126
127
  const isLuaFunctionExpression = rhs && !Array.isArray(rhs) && lua.isFunctionExpression(rhs);
127
128
  const isSafeRecursiveFunctionDeclaration = isFunctionDeclaration && isLuaFunctionExpression;
128
129
  if (!isSafeRecursiveFunctionDeclaration && hasMultipleReferences(scope, lhs)) {
@@ -163,6 +164,7 @@ function createLocalOrExportedOrGlobalDeclaration(context, lhs, rhs, tsOriginal,
163
164
  }
164
165
  }
165
166
  }
167
+ setJSDocComments(context, tsOriginal, declaration, assignment);
166
168
  if (declaration && assignment) {
167
169
  return [declaration, assignment];
168
170
  }
@@ -177,6 +179,86 @@ function createLocalOrExportedOrGlobalDeclaration(context, lhs, rhs, tsOriginal,
177
179
  }
178
180
  }
179
181
  exports.createLocalOrExportedOrGlobalDeclaration = createLocalOrExportedOrGlobalDeclaration;
182
+ /**
183
+ * Apply JSDoc comments to the newly-created Lua statement, if present.
184
+ * https://stackoverflow.com/questions/47429792/is-it-possible-to-get-comments-as-nodes-in-the-ast-using-the-typescript-compiler
185
+ */
186
+ function setJSDocComments(context, tsOriginal, declaration, assignment) {
187
+ // Respect the vanilla TypeScript option of "removeComments":
188
+ // https://www.typescriptlang.org/tsconfig#removeComments
189
+ if (context.options.removeComments) {
190
+ return;
191
+ }
192
+ const docCommentArray = getJSDocCommentFromTSNode(context, tsOriginal);
193
+ if (docCommentArray === undefined) {
194
+ return;
195
+ }
196
+ if (declaration && assignment) {
197
+ declaration.leadingComments = docCommentArray;
198
+ }
199
+ else if (declaration) {
200
+ declaration.leadingComments = docCommentArray;
201
+ }
202
+ else if (assignment) {
203
+ assignment.leadingComments = docCommentArray;
204
+ }
205
+ }
206
+ function getJSDocCommentFromTSNode(context, tsOriginal) {
207
+ if (tsOriginal === undefined) {
208
+ return undefined;
209
+ }
210
+ // The "name" property is only on a subset of node types; we want to be permissive and get the
211
+ // comments from as many nodes as possible.
212
+ const node = tsOriginal;
213
+ if (node.name === undefined) {
214
+ return undefined;
215
+ }
216
+ const symbol = context.checker.getSymbolAtLocation(node.name);
217
+ if (symbol === undefined) {
218
+ return undefined;
219
+ }
220
+ // The TypeScript compiler separates JSDoc comments into the "documentation comment" and the
221
+ // "tags". The former is conventionally at the top of the comment, and the bottom is
222
+ // conventionally at the bottom. We need to get both from the TypeScript API and then combine
223
+ // them into one block of text.
224
+ const docCommentArray = symbol.getDocumentationComment(context.checker);
225
+ const docCommentText = ts.displayPartsToString(docCommentArray).trim();
226
+ const jsDocTagInfoArray = symbol.getJsDocTags(context.checker);
227
+ const jsDocTagsTextLines = jsDocTagInfoArray.map(jsDocTagInfo => {
228
+ let text = "@" + jsDocTagInfo.name;
229
+ if (jsDocTagInfo.text !== undefined) {
230
+ const tagDescriptionTextArray = jsDocTagInfo.text
231
+ .filter(symbolDisplayPart => symbolDisplayPart.text.trim() !== "")
232
+ .map(symbolDisplayPart => symbolDisplayPart.text.trim());
233
+ const tagDescriptionText = tagDescriptionTextArray.join(" ");
234
+ text += " " + tagDescriptionText;
235
+ }
236
+ return text;
237
+ });
238
+ const jsDocTagsText = jsDocTagsTextLines.join("\n");
239
+ const combined = (docCommentText + "\n\n" + jsDocTagsText).trim();
240
+ if (combined === "") {
241
+ return undefined;
242
+ }
243
+ // By default, TSTL will display comments immediately next to the "--" characters. We can make
244
+ // the comments look better if we separate them by a space (similar to what Prettier does in
245
+ // JavaScript/TypeScript).
246
+ const linesWithoutSpace = combined.split("\n");
247
+ const lines = linesWithoutSpace.map(line => ` ${line}`);
248
+ // We want to JSDoc comments to map on to LDoc comments:
249
+ // https://stevedonovan.github.io/ldoc/manual/doc.md.html
250
+ // LDoc comments require that the first line starts with three hyphens.
251
+ // Thus, need to add a hyphen to the first line.
252
+ const firstLine = lines[0];
253
+ if (firstLine.startsWith(" @")) {
254
+ lines.unshift("-");
255
+ }
256
+ else {
257
+ lines.shift();
258
+ lines.unshift("-" + firstLine);
259
+ }
260
+ return lines;
261
+ }
180
262
  const createNaN = (tsOriginal) => lua.createBinaryExpression(lua.createNumericLiteral(0), lua.createNumericLiteral(0), lua.SyntaxKind.DivisionOperator, tsOriginal);
181
263
  exports.createNaN = createNaN;
182
264
  //# sourceMappingURL=lua-ast.js.map
@@ -3,4 +3,4 @@ import * as lua from "../../LuaAST";
3
3
  import { FunctionVisitor, TransformationContext } from "../context";
4
4
  export declare const transformAwaitExpression: FunctionVisitor<ts.AwaitExpression>;
5
5
  export declare function isAsyncFunction(declaration: ts.FunctionLikeDeclaration): boolean;
6
- export declare function wrapInAsyncAwaiter(context: TransformationContext, statements: lua.Statement[]): lua.Statement[];
6
+ export declare function wrapInAsyncAwaiter(context: TransformationContext, statements: lua.Statement[], includeResolveParameter?: boolean): lua.CallExpression;
@@ -7,16 +7,12 @@ const diagnostics_1 = require("../utils/diagnostics");
7
7
  const lualib_1 = require("../utils/lualib");
8
8
  const typescript_1 = require("../utils/typescript");
9
9
  const transformAwaitExpression = (node, context) => {
10
- var _a;
11
10
  // Check if await is inside an async function, it is not allowed at top level or in non-async functions
12
- const containingFunction = (0, typescript_1.findFirstNodeAbove)(node, ts.isFunctionLike);
13
- if (containingFunction === undefined ||
14
- !((_a = containingFunction.modifiers) === null || _a === void 0 ? void 0 : _a.some(m => m.kind === ts.SyntaxKind.AsyncKeyword))) {
11
+ if (!(0, typescript_1.isInAsyncFunction)(node)) {
15
12
  context.diagnostics.push((0, diagnostics_1.awaitMustBeInAsyncFunction)(node));
16
13
  }
17
14
  const expression = context.transformExpression(node.expression);
18
- const catchIdentifier = lua.createIdentifier("____catch");
19
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Await, node, catchIdentifier, expression);
15
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Await, node, expression);
20
16
  };
21
17
  exports.transformAwaitExpression = transformAwaitExpression;
22
18
  function isAsyncFunction(declaration) {
@@ -24,15 +20,12 @@ function isAsyncFunction(declaration) {
24
20
  return (_b = (_a = declaration.modifiers) === null || _a === void 0 ? void 0 : _a.some(m => m.kind === ts.SyntaxKind.AsyncKeyword)) !== null && _b !== void 0 ? _b : false;
25
21
  }
26
22
  exports.isAsyncFunction = isAsyncFunction;
27
- function wrapInAsyncAwaiter(context, statements) {
23
+ function wrapInAsyncAwaiter(context, statements, includeResolveParameter = true) {
28
24
  (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Await);
29
- return [
30
- lua.createReturnStatement([
31
- lua.createCallExpression(lua.createIdentifier("__TS__AsyncAwaiter"), [
32
- lua.createFunctionExpression(lua.createBlock(statements)),
33
- ]),
34
- ]),
35
- ];
25
+ const parameters = includeResolveParameter ? [lua.createIdentifier("____awaiter_resolve")] : [];
26
+ return lua.createCallExpression(lua.createIdentifier("__TS__AsyncAwaiter"), [
27
+ lua.createFunctionExpression(lua.createBlock(statements), parameters),
28
+ ]);
36
29
  }
37
30
  exports.wrapInAsyncAwaiter = wrapInAsyncAwaiter;
38
31
  //# sourceMappingURL=async-await.js.map
@@ -72,17 +72,14 @@ function transformAssignmentWithRightPrecedingStatements(context, lhs, right, ri
72
72
  }
73
73
  exports.transformAssignmentWithRightPrecedingStatements = transformAssignmentWithRightPrecedingStatements;
74
74
  function transformDestructuredAssignmentExpression(context, expression) {
75
- const rootIdentifier = context.createTempNameForNode(expression.right);
76
75
  let [rightPrecedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
77
76
  context.addPrecedingStatements(rightPrecedingStatements);
78
77
  if ((0, multi_1.isMultiReturnCall)(context, expression.right)) {
79
78
  right = (0, lua_ast_1.wrapInTable)(right);
80
79
  }
81
- const statements = [
82
- lua.createVariableDeclarationStatement(rootIdentifier, right),
83
- ...(0, destructuring_assignments_1.transformDestructuringAssignment)(context, expression, rootIdentifier, rightPrecedingStatements.length > 0),
84
- ];
85
- return { statements, result: rootIdentifier };
80
+ const rightExpr = (0, expression_list_1.moveToPrecedingTemp)(context, right, expression.right);
81
+ const statements = (0, destructuring_assignments_1.transformDestructuringAssignment)(context, expression, rightExpr, rightPrecedingStatements.length > 0);
82
+ return { statements, result: rightExpr };
86
83
  }
87
84
  function transformAssignmentExpression(context, expression) {
88
85
  // Validate assignment
@@ -99,15 +96,12 @@ function transformAssignmentExpression(context, expression) {
99
96
  return result;
100
97
  }
101
98
  if (ts.isPropertyAccessExpression(expression.left) || ts.isElementAccessExpression(expression.left)) {
102
- const tempVar = context.createTempNameForNode(expression.right);
103
99
  const [precedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
104
100
  const left = transformAssignmentLeftHandSideExpression(context, expression.left, precedingStatements.length > 0);
105
- context.addPrecedingStatements([
106
- ...precedingStatements,
107
- lua.createVariableDeclarationStatement(tempVar, right, expression.right),
108
- lua.createAssignmentStatement(left, lua.cloneIdentifier(tempVar), expression.left),
109
- ]);
110
- return lua.cloneIdentifier(tempVar);
101
+ context.addPrecedingStatements(precedingStatements);
102
+ const rightExpr = (0, expression_list_1.moveToPrecedingTemp)(context, right, expression.right);
103
+ context.addPrecedingStatements(lua.createAssignmentStatement(left, rightExpr, expression.left));
104
+ return rightExpr;
111
105
  }
112
106
  else {
113
107
  // Simple assignment
@@ -158,16 +152,8 @@ function transformAssignmentStatement(context, expression) {
158
152
  const left = expression.left.elements.map(e => transformAssignmentLeftHandSideExpression(context, e));
159
153
  return [lua.createAssignmentStatement(left, right, expression)];
160
154
  }
161
- let [rightPrecedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
162
- context.addPrecedingStatements(rightPrecedingStatements);
163
- if ((0, multi_1.isMultiReturnCall)(context, expression.right)) {
164
- right = (0, lua_ast_1.wrapInTable)(right);
165
- }
166
- const rootIdentifier = context.createTempNameForNode(expression.left);
167
- return [
168
- lua.createVariableDeclarationStatement(rootIdentifier, right),
169
- ...(0, destructuring_assignments_1.transformDestructuringAssignment)(context, expression, rootIdentifier, rightPrecedingStatements.length > 0),
170
- ];
155
+ const { statements } = transformDestructuredAssignmentExpression(context, expression);
156
+ return statements;
171
157
  }
172
158
  else {
173
159
  const [precedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
@@ -6,7 +6,10 @@ export declare const isCompoundAssignmentToken: (token: ts.BinaryOperator) => to
6
6
  export declare const unwrapCompoundAssignmentToken: (token: ts.CompoundAssignmentOperator) => CompoundAssignmentToken;
7
7
  export declare function transformCompoundAssignment(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): {
8
8
  statements: lua.Statement[];
9
- result: lua.AssignmentLeftHandSideExpression;
9
+ result: lua.Identifier;
10
+ } | {
11
+ statements: lua.Statement[];
12
+ result: lua.TableIndexExpression;
10
13
  };
11
14
  export declare function transformCompoundAssignmentExpression(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): lua.Expression;
12
15
  export declare function transformCompoundAssignmentStatement(context: TransformationContext, node: ts.Node, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken): lua.Statement[];
@@ -39,7 +39,7 @@ exports.unwrapCompoundAssignmentToken = unwrapCompoundAssignmentToken;
39
39
  function transformCompoundAssignment(context, expression, lhs, rhs, operator, isPostfix) {
40
40
  const left = (0, utils_1.cast)(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression);
41
41
  const [rightPrecedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(rhs));
42
- if (lua.isTableIndexExpression(left) && shouldCacheTableIndexExpressions(left, rightPrecedingStatements)) {
42
+ if (lua.isTableIndexExpression(left)) {
43
43
  // Complex property/element accesses need to cache object/index expressions to avoid repeating side-effects
44
44
  // local __obj, __index = ${objExpression}, ${indexExpression};
45
45
  const obj = context.createTempNameForLuaExpression(left.table);
@@ -60,6 +60,15 @@ function transformCompoundAssignment(context, expression, lhs, rhs, operator, is
60
60
  };
61
61
  }
62
62
  else {
63
+ if (isSetterSkippingCompoundAssignmentOperator(operator)) {
64
+ return {
65
+ statements: [
66
+ objAndIndexDeclaration,
67
+ ...transformSetterSkippingCompoundAssignment(accessExpression, operator, right, rightPrecedingStatements),
68
+ ],
69
+ result: left,
70
+ };
71
+ }
63
72
  // local ____tmp = ____obj[____index] ${replacementOperator} ${right};
64
73
  // ____obj[____index] = ____tmp;
65
74
  // return ____tmp
@@ -83,24 +92,6 @@ function transformCompoundAssignment(context, expression, lhs, rhs, operator, is
83
92
  const assignStatements = (0, assignments_1.transformAssignmentWithRightPrecedingStatements)(context, lhs, operatorExpression, rightPrecedingStatements);
84
93
  return { statements: [tmpDeclaration, ...precedingStatements, ...assignStatements], result: tmpIdentifier };
85
94
  }
86
- else if (ts.isPropertyAccessExpression(lhs) || ts.isElementAccessExpression(lhs)) {
87
- // Simple property/element access expressions need to cache in temp to avoid double-evaluation
88
- // local ____tmp = ${left} ${replacementOperator} ${right};
89
- // ${left} = ____tmp;
90
- // return ____tmp
91
- const tmpIdentifier = context.createTempNameForLuaExpression(left);
92
- const [precedingStatements, operatorExpression] = (0, binary_expression_1.transformBinaryOperation)(context, left, right, rightPrecedingStatements, operator, expression);
93
- const tmpDeclaration = lua.createVariableDeclarationStatement(tmpIdentifier, operatorExpression);
94
- if (isSetterSkippingCompoundAssignmentOperator(operator)) {
95
- const statements = [
96
- tmpDeclaration,
97
- ...transformSetterSkippingCompoundAssignment(tmpIdentifier, operator, right, precedingStatements),
98
- ];
99
- return { statements, result: tmpIdentifier };
100
- }
101
- const assignStatements = (0, assignments_1.transformAssignmentWithRightPrecedingStatements)(context, lhs, tmpIdentifier, precedingStatements);
102
- return { statements: [tmpDeclaration, ...assignStatements], result: tmpIdentifier };
103
- }
104
95
  else {
105
96
  if (rightPrecedingStatements.length > 0 && isSetterSkippingCompoundAssignmentOperator(operator)) {
106
97
  return {
@@ -1,11 +1,9 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
3
  import { FunctionVisitor, TransformationContext } from "../context";
4
- export declare type PropertyCallExpression = ts.CallExpression & {
5
- expression: ts.PropertyAccessExpression;
6
- };
7
4
  export declare function validateArguments(context: TransformationContext, params: readonly ts.Expression[], signature?: ts.Signature): void;
8
5
  export declare function transformArguments(context: TransformationContext, params: readonly ts.Expression[], signature?: ts.Signature, callContext?: ts.Expression): lua.Expression[];
9
6
  export declare function transformCallAndArguments(context: TransformationContext, callExpression: ts.Expression, params: readonly ts.Expression[], signature?: ts.Signature, callContext?: ts.Expression): [lua.Expression, lua.Expression[]];
10
7
  export declare function transformContextualCallExpression(context: TransformationContext, node: ts.CallExpression | ts.TaggedTemplateExpression, args: ts.Expression[] | ts.NodeArray<ts.Expression>, signature?: ts.Signature): lua.Expression;
11
8
  export declare const transformCallExpression: FunctionVisitor<ts.CallExpression>;
9
+ export declare function getCalledExpression(node: ts.CallExpression): ts.Expression;