typescript-to-lua 1.4.3 → 1.6.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 (45) 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/SourceMapTraceBack.lua +14 -1
  5. package/dist/lualib/lualib_bundle.lua +35 -35
  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 +1 -1
  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/utils/typescript/index.js +2 -2
  33. package/dist/transformation/visitors/async-await.d.ts +1 -1
  34. package/dist/transformation/visitors/async-await.js +7 -14
  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 +25 -14
  39. package/dist/transformation/visitors/errors.js +52 -11
  40. package/dist/transformation/visitors/function.js +1 -1
  41. package/dist/transformation/visitors/return.js +5 -4
  42. package/dist/transpilation/index.js +9 -4
  43. package/dist/transpilation/resolve.js +2 -2
  44. package/dist/transpilation/transpiler.js +3 -2
  45. package/package.json +9 -9
@@ -1,6 +1,5 @@
1
1
  import * as lua from "../../LuaAST";
2
2
  import * as ts from "typescript";
3
3
  import { TransformationContext } from "../context";
4
- import { PropertyCallExpression } from "../visitors/call";
5
- export declare function transformObjectConstructorCall(context: TransformationContext, expression: PropertyCallExpression): lua.Expression | undefined;
6
- export declare function transformObjectPrototypeCall(context: TransformationContext, node: ts.CallExpression, expression: ts.PropertyAccessExpression): lua.Expression | undefined;
4
+ export declare function transformObjectConstructorCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.Expression | undefined;
5
+ export declare function transformObjectPrototypeCall(context: TransformationContext, node: ts.CallExpression, calledMethod: ts.PropertyAccessExpression): lua.Expression | undefined;
@@ -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,7 +59,7 @@ 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)) {
62
+ if (options.noImplicitSelf && program.getSourceFile(signatureDeclaration.getSourceFile().fileName) !== undefined) {
63
63
  return ContextType.Void;
64
64
  }
65
65
  // Walk up to find @noSelf or @noSelfInFile
@@ -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
@@ -39,9 +39,9 @@ function findFirstNodeAbove(node, callback) {
39
39
  }
40
40
  exports.findFirstNodeAbove = findFirstNodeAbove;
41
41
  function findFirstNonOuterParent(node) {
42
- let current = node.parent;
42
+ let current = ts.getOriginalNode(node).parent;
43
43
  while (ts.isOuterExpression(current)) {
44
- current = current.parent;
44
+ current = ts.getOriginalNode(current).parent;
45
45
  }
46
46
  return current;
47
47
  }
@@ -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
@@ -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;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformCallExpression = exports.transformContextualCallExpression = exports.transformCallAndArguments = exports.transformArguments = exports.validateArguments = void 0;
3
+ exports.getCalledExpression = 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");
@@ -82,7 +82,7 @@ function transformContextualCallExpression(context, node, args, signature) {
82
82
  if (ts.isOptionalChain(node)) {
83
83
  return (0, optional_chaining_1.transformOptionalChain)(context, node);
84
84
  }
85
- const left = ts.isCallExpression(node) ? node.expression : node.tag;
85
+ const left = ts.isCallExpression(node) ? getCalledExpression(node) : node.tag;
86
86
  let [argPrecedingStatements, transformedArguments] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => transformArguments(context, args, signature));
87
87
  if (ts.isPropertyAccessExpression(left) &&
88
88
  ts.isIdentifier(left.name) &&
@@ -113,9 +113,9 @@ function transformContextualCallExpression(context, node, args, signature) {
113
113
  }
114
114
  }
115
115
  exports.transformContextualCallExpression = transformContextualCallExpression;
116
- function transformPropertyCall(context, node) {
116
+ function transformPropertyCall(context, node, calledMethod) {
117
117
  const signature = context.checker.getResolvedSignature(node);
118
- if (node.expression.expression.kind === ts.SyntaxKind.SuperKeyword) {
118
+ if (calledMethod.expression.kind === ts.SyntaxKind.SuperKeyword) {
119
119
  // Super calls take the format of super.call(self,...)
120
120
  const parameters = transformArguments(context, node.arguments, signature, ts.factory.createThis());
121
121
  return lua.createCallExpression(context.transformExpression(node.expression), parameters);
@@ -146,14 +146,15 @@ function transformElementCall(context, node) {
146
146
  }
147
147
  const transformCallExpression = (node, context) => {
148
148
  var _a;
149
- if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
149
+ const calledExpression = getCalledExpression(node);
150
+ if (calledExpression.kind === ts.SyntaxKind.ImportKeyword) {
150
151
  return (0, import_1.transformImportExpression)(node, context);
151
152
  }
152
153
  if (ts.isOptionalChain(node)) {
153
154
  return (0, optional_chaining_1.transformOptionalChain)(context, node);
154
155
  }
155
- const optionalContinuation = ts.isIdentifier(node.expression)
156
- ? (0, optional_chaining_1.getOptionalContinuationData)(node.expression)
156
+ const optionalContinuation = ts.isIdentifier(calledExpression)
157
+ ? (0, optional_chaining_1.getOptionalContinuationData)(calledExpression)
157
158
  : undefined;
158
159
  const wrapResultInTable = (0, multi_1.isMultiReturnCall)(context, node) && (0, multi_1.shouldMultiReturnCallBeWrapped)(context, node);
159
160
  if ((0, annotations_1.isTupleReturnCall)(context, node)) {
@@ -164,22 +165,22 @@ const transformCallExpression = (node, context) => {
164
165
  // unsupportedOptionalCall diagnostic already present
165
166
  return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(builtinOrExtensionResult) : builtinOrExtensionResult;
166
167
  }
167
- if (ts.isPropertyAccessExpression(node.expression)) {
168
- const ownerType = context.checker.getTypeAtLocation(node.expression.expression);
168
+ if (ts.isPropertyAccessExpression(calledExpression)) {
169
+ const ownerType = context.checker.getTypeAtLocation(calledExpression.expression);
169
170
  const annotations = (0, annotations_1.getTypeAnnotations)(ownerType);
170
171
  if (annotations.has(annotations_1.AnnotationKind.LuaTable)) {
171
172
  context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.LuaTable));
172
173
  }
173
- const result = transformPropertyCall(context, node);
174
+ const result = transformPropertyCall(context, node, calledExpression);
174
175
  return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(result) : result;
175
176
  }
176
- if (ts.isElementAccessExpression(node.expression)) {
177
+ if (ts.isElementAccessExpression(calledExpression)) {
177
178
  const result = transformElementCall(context, node);
178
179
  return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(result) : result;
179
180
  }
180
181
  const signature = context.checker.getResolvedSignature(node);
181
182
  // Handle super calls properly
182
- if (node.expression.kind === ts.SyntaxKind.SuperKeyword) {
183
+ if (calledExpression.kind === ts.SyntaxKind.SuperKeyword) {
183
184
  const parameters = transformArguments(context, node.arguments, signature, ts.factory.createThis());
184
185
  return lua.createCallExpression(lua.createTableIndexExpression(context.transformExpression(ts.factory.createSuper()), lua.createStringLiteral("____constructor")), parameters);
185
186
  }
@@ -188,13 +189,15 @@ const transformCallExpression = (node, context) => {
188
189
  let parameters;
189
190
  const isContextualCall = !signatureDeclaration || (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void;
190
191
  if (!isContextualCall) {
191
- [callPath, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature);
192
+ [callPath, parameters] = transformCallAndArguments(context, calledExpression, node.arguments, signature);
192
193
  }
193
194
  else {
194
195
  // if is optionalContinuation, context will be handled by transformOptionalChain.
195
196
  const useGlobalContext = !context.isStrict && optionalContinuation === undefined;
196
197
  const callContext = useGlobalContext ? ts.factory.createIdentifier("_G") : ts.factory.createNull();
197
- [callPath, parameters] = transformCallAndArguments(context, node.expression, node.arguments, signature, callContext);
198
+ [callPath, parameters] = transformCallAndArguments(context, calledExpression, node.arguments, signature,
199
+ // Only pass context if noImplicitSelf is not configured
200
+ context.options.noImplicitSelf ? undefined : callContext);
198
201
  }
199
202
  const callExpression = lua.createCallExpression(callPath, parameters, node);
200
203
  if (optionalContinuation && isContextualCall) {
@@ -203,4 +206,12 @@ const transformCallExpression = (node, context) => {
203
206
  return wrapResultInTable ? (0, lua_ast_1.wrapInTable)(callExpression) : callExpression;
204
207
  };
205
208
  exports.transformCallExpression = transformCallExpression;
209
+ function getCalledExpression(node) {
210
+ function unwrapExpression(expression) {
211
+ expression = ts.skipOuterExpressions(expression);
212
+ return ts.isNonNullExpression(expression) ? unwrapExpression(expression.expression) : expression;
213
+ }
214
+ return unwrapExpression(node.expression);
215
+ }
216
+ exports.getCalledExpression = getCalledExpression;
206
217
  //# sourceMappingURL=call.js.map