typescript-to-lua 1.6.3 → 1.7.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 (97) hide show
  1. package/dist/CompilerOptions.d.ts +1 -0
  2. package/dist/cli/parse.js +5 -0
  3. package/dist/lualib/ArraySlice.lua +10 -2
  4. package/dist/lualib/ArraySplice.lua +5 -1
  5. package/dist/lualib/Generator.lua +8 -1
  6. package/dist/lualib/ParseFloat.lua +5 -1
  7. package/dist/lualib/SparseArraySpread.lua +5 -1
  8. package/dist/lualib/StringCharCodeAt.lua +5 -1
  9. package/dist/lualib/lualib_bundle.lua +38 -7
  10. package/dist/lualib-build/plugin.js +1 -2
  11. package/dist/measure-performance.d.ts +15 -0
  12. package/dist/measure-performance.js +83 -0
  13. package/dist/transformation/builtins/array.js +2 -1
  14. package/dist/transformation/builtins/function.js +1 -1
  15. package/dist/transformation/builtins/global.d.ts +1 -1
  16. package/dist/transformation/builtins/global.js +13 -12
  17. package/dist/transformation/builtins/index.d.ts +2 -2
  18. package/dist/transformation/builtins/index.js +87 -89
  19. package/dist/transformation/builtins/object.d.ts +1 -1
  20. package/dist/transformation/builtins/object.js +4 -4
  21. package/dist/transformation/builtins/promise.js +4 -2
  22. package/dist/transformation/builtins/string.js +2 -0
  23. package/dist/transformation/context/context.d.ts +15 -0
  24. package/dist/transformation/context/context.js +66 -24
  25. package/dist/transformation/context/visitors.d.ts +1 -1
  26. package/dist/transformation/index.js +6 -5
  27. package/dist/transformation/utils/annotations.d.ts +1 -17
  28. package/dist/transformation/utils/annotations.js +48 -88
  29. package/dist/transformation/utils/assignment-validation.js +27 -23
  30. package/dist/transformation/utils/diagnostics.d.ts +1 -4
  31. package/dist/transformation/utils/diagnostics.js +2 -3
  32. package/dist/transformation/utils/function-context.d.ts +1 -1
  33. package/dist/transformation/utils/function-context.js +57 -51
  34. package/dist/transformation/utils/language-extensions.d.ts +57 -51
  35. package/dist/transformation/utils/language-extensions.js +99 -119
  36. package/dist/transformation/utils/lualib.d.ts +0 -1
  37. package/dist/transformation/utils/lualib.js +2 -8
  38. package/dist/transformation/utils/safe-names.d.ts +1 -1
  39. package/dist/transformation/utils/safe-names.js +3 -6
  40. package/dist/transformation/utils/scope.d.ts +0 -2
  41. package/dist/transformation/utils/scope.js +10 -27
  42. package/dist/transformation/utils/symbols.d.ts +1 -1
  43. package/dist/transformation/utils/symbols.js +7 -20
  44. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  45. package/dist/transformation/utils/typescript/index.js +2 -1
  46. package/dist/transformation/utils/typescript/types.d.ts +2 -5
  47. package/dist/transformation/utils/typescript/types.js +27 -37
  48. package/dist/transformation/visitors/access.js +1 -4
  49. package/dist/transformation/visitors/block.js +4 -4
  50. package/dist/transformation/visitors/call.js +7 -18
  51. package/dist/transformation/visitors/class/index.js +8 -20
  52. package/dist/transformation/visitors/class/members/constructor.js +2 -2
  53. package/dist/transformation/visitors/class/new.js +2 -5
  54. package/dist/transformation/visitors/class/setup.d.ts +1 -1
  55. package/dist/transformation/visitors/class/setup.js +4 -4
  56. package/dist/transformation/visitors/class/utils.d.ts +1 -1
  57. package/dist/transformation/visitors/class/utils.js +2 -9
  58. package/dist/transformation/visitors/conditional.js +4 -4
  59. package/dist/transformation/visitors/function.d.ts +1 -1
  60. package/dist/transformation/visitors/function.js +8 -16
  61. package/dist/transformation/visitors/identifier.d.ts +1 -0
  62. package/dist/transformation/visitors/identifier.js +40 -44
  63. package/dist/transformation/visitors/language-extensions/call-extension.d.ts +10 -0
  64. package/dist/transformation/visitors/language-extensions/call-extension.js +23 -0
  65. package/dist/transformation/visitors/language-extensions/identifier.d.ts +5 -0
  66. package/dist/transformation/visitors/language-extensions/identifier.js +27 -0
  67. package/dist/transformation/visitors/language-extensions/iterable.d.ts +2 -3
  68. package/dist/transformation/visitors/language-extensions/iterable.js +21 -22
  69. package/dist/transformation/visitors/language-extensions/multi.d.ts +0 -1
  70. package/dist/transformation/visitors/language-extensions/multi.js +10 -24
  71. package/dist/transformation/visitors/language-extensions/operators.d.ts +2 -5
  72. package/dist/transformation/visitors/language-extensions/operators.js +89 -96
  73. package/dist/transformation/visitors/language-extensions/range.js +4 -2
  74. package/dist/transformation/visitors/language-extensions/table.d.ts +6 -3
  75. package/dist/transformation/visitors/language-extensions/table.js +46 -75
  76. package/dist/transformation/visitors/language-extensions/vararg.js +7 -3
  77. package/dist/transformation/visitors/literal.js +2 -23
  78. package/dist/transformation/visitors/loops/for-of.js +18 -18
  79. package/dist/transformation/visitors/loops/utils.js +5 -5
  80. package/dist/transformation/visitors/namespace.js +5 -14
  81. package/dist/transformation/visitors/return.js +2 -3
  82. package/dist/transformation/visitors/sourceFile.js +3 -4
  83. package/dist/transformation/visitors/spread.js +0 -5
  84. package/dist/transformation/visitors/switch.js +2 -2
  85. package/dist/transformation/visitors/variable-declaration.js +1 -1
  86. package/dist/transpilation/plugins.js +3 -0
  87. package/dist/transpilation/resolve.js +144 -161
  88. package/dist/transpilation/transpile.js +10 -0
  89. package/dist/transpilation/transpiler.d.ts +1 -0
  90. package/dist/transpilation/transpiler.js +18 -5
  91. package/dist/tstl.js +21 -0
  92. package/language-extensions/index.d.ts +156 -67
  93. package/package.json +2 -2
  94. package/dist/transformation/visitors/language-extensions/index.d.ts +0 -4
  95. package/dist/transformation/visitors/language-extensions/index.js +0 -17
  96. package/dist/transformation/visitors/language-extensions/pairsIterable.d.ts +0 -5
  97. package/dist/transformation/visitors/language-extensions/pairsIterable.js +0 -53
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformObjectPrototypeCall = exports.transformObjectConstructorCall = void 0;
3
+ exports.tryTransformObjectPrototypeCall = exports.transformObjectConstructorCall = void 0;
4
4
  const lua = require("../../LuaAST");
5
5
  const diagnostics_1 = require("../utils/diagnostics");
6
6
  const lualib_1 = require("../utils/lualib");
@@ -30,8 +30,7 @@ function transformObjectConstructorCall(context, node, calledMethod) {
30
30
  }
31
31
  }
32
32
  exports.transformObjectConstructorCall = transformObjectConstructorCall;
33
- function transformObjectPrototypeCall(context, node, calledMethod) {
34
- const signature = context.checker.getResolvedSignature(node);
33
+ function tryTransformObjectPrototypeCall(context, node, calledMethod) {
35
34
  const name = calledMethod.name.text;
36
35
  switch (name) {
37
36
  case "toString":
@@ -39,11 +38,12 @@ function transformObjectPrototypeCall(context, node, calledMethod) {
39
38
  return lua.createCallExpression(toStringIdentifier, [context.transformExpression(calledMethod.expression)], node);
40
39
  case "hasOwnProperty":
41
40
  const expr = context.transformExpression(calledMethod.expression);
41
+ const signature = context.checker.getResolvedSignature(node);
42
42
  const parameters = (0, call_1.transformArguments)(context, node.arguments, signature);
43
43
  const rawGetIdentifier = lua.createIdentifier("rawget");
44
44
  const rawGetCall = lua.createCallExpression(rawGetIdentifier, [expr, ...parameters]);
45
45
  return lua.createBinaryExpression(rawGetCall, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator, node);
46
46
  }
47
47
  }
48
- exports.transformObjectPrototypeCall = transformObjectPrototypeCall;
48
+ exports.tryTransformObjectPrototypeCall = tryTransformObjectPrototypeCall;
49
49
  //# sourceMappingURL=object.js.map
@@ -4,11 +4,13 @@ exports.createStaticPromiseFunctionAccessor = exports.transformPromiseConstructo
4
4
  const lua = require("../../LuaAST");
5
5
  const diagnostics_1 = require("../utils/diagnostics");
6
6
  const lualib_1 = require("../utils/lualib");
7
- const typescript_1 = require("../utils/typescript");
8
7
  const call_1 = require("../visitors/call");
8
+ const typescript_1 = require("../utils/typescript");
9
9
  function isPromiseClass(context, node) {
10
+ if (node.text !== "Promise")
11
+ return false;
10
12
  const type = context.checker.getTypeAtLocation(node);
11
- return (0, typescript_1.isStandardLibraryType)(context, type, undefined) && node.text === "Promise";
13
+ return (0, typescript_1.isStandardLibraryType)(context, type, undefined);
12
14
  }
13
15
  exports.isPromiseClass = isPromiseClass;
14
16
  function createPromiseIdentifier(original) {
@@ -100,6 +100,8 @@ function transformStringPrototypeCall(context, node, calledMethod) {
100
100
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.StringPadStart, node, caller, ...params);
101
101
  case "padEnd":
102
102
  return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.StringPadEnd, node, caller, ...params);
103
+ case "toString":
104
+ return; // will be handled by transformObjectPrototypeCall
103
105
  default:
104
106
  context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(calledMethod.name, "string", expressionName));
105
107
  }
@@ -2,6 +2,9 @@ import * as ts from "typescript";
2
2
  import { CompilerOptions, LuaTarget } from "../../CompilerOptions";
3
3
  import * as lua from "../../LuaAST";
4
4
  import { ExpressionLikeNode, StatementLikeNode, VisitorMap } from "./visitors";
5
+ import { SymbolInfo } from "../utils/symbols";
6
+ import { LuaLibFeature } from "../../LuaLib";
7
+ import { Scope, ScopeType } from "../utils/scope";
5
8
  export declare const tempSymbolId: lua.SymbolId;
6
9
  export interface AllAccessorDeclarations {
7
10
  firstAccessor: ts.AccessorDeclaration;
@@ -33,10 +36,13 @@ export declare class TransformationContext {
33
36
  readonly isStrict: boolean;
34
37
  constructor(program: ts.Program, sourceFile: ts.SourceFile, visitorMap: VisitorMap);
35
38
  private currentNodeVisitors;
39
+ private currentNodeVisitorsIndex;
36
40
  private nextTempId;
37
41
  transformNode(node: ts.Node): lua.Node[];
38
42
  superTransformNode(node: ts.Node): lua.Node[];
43
+ private doSuperTransformNode;
39
44
  transformExpression(node: ExpressionLikeNode): lua.Expression;
45
+ private assertIsExpression;
40
46
  superTransformExpression(node: ExpressionLikeNode): lua.Expression;
41
47
  transformStatements(node: StatementLikeNode | readonly StatementLikeNode[]): lua.Statement[];
42
48
  superTransformStatements(node: StatementLikeNode | readonly StatementLikeNode[]): lua.Statement[];
@@ -49,4 +55,13 @@ export declare class TransformationContext {
49
55
  createTempNameForLuaExpression(expression: lua.Expression): lua.Identifier;
50
56
  private getTempNameForNode;
51
57
  createTempNameForNode(node: ts.Node): lua.Identifier;
58
+ private lastSymbolId;
59
+ readonly symbolInfoMap: Map<lua.SymbolId, SymbolInfo>;
60
+ readonly symbolIdMaps: Map<ts.Symbol, lua.SymbolId>;
61
+ nextSymbolId(): lua.SymbolId;
62
+ readonly usedLuaLibFeatures: Set<LuaLibFeature>;
63
+ readonly scopeStack: Scope[];
64
+ private lastScopeId;
65
+ pushScope(type: ScopeType): Scope;
66
+ popScope(): Scope;
52
67
  }
@@ -24,66 +24,91 @@ class TransformationContext {
24
24
  this.isStrict = ((_b = this.options.alwaysStrict) !== null && _b !== void 0 ? _b : this.options.strict) ||
25
25
  (this.isModule && this.options.target !== undefined && this.options.target >= ts.ScriptTarget.ES2015);
26
26
  this.currentNodeVisitors = [];
27
+ this.currentNodeVisitorsIndex = 0;
27
28
  this.nextTempId = 0;
29
+ // other utils
30
+ this.lastSymbolId = 0;
31
+ this.symbolInfoMap = new Map();
32
+ this.symbolIdMaps = new Map();
33
+ this.usedLuaLibFeatures = new Set();
34
+ this.scopeStack = [];
35
+ this.lastScopeId = 0;
36
+ /** @internal */
37
+ this.classSuperInfos = [];
28
38
  // Use `getParseTreeNode` to get original SourceFile node, before it was substituted by custom transformers.
29
39
  // It's required because otherwise `getEmitResolver` won't use cached diagnostics, produced in `emitWorker`
30
40
  // and would try to re-analyze the file, which would fail because of replaced nodes.
31
41
  const originalSourceFile = (_c = ts.getParseTreeNode(sourceFile, ts.isSourceFile)) !== null && _c !== void 0 ? _c : sourceFile;
32
42
  this.resolver = this.checker.getEmitResolver(originalSourceFile);
33
43
  }
34
- transformNode(node, isExpression) {
44
+ transformNode(node) {
45
+ return (0, lua_ast_1.unwrapVisitorResult)(this.transformNodeRaw(node));
46
+ }
47
+ /** @internal */
48
+ transformNodeRaw(node, isExpression) {
35
49
  var _a;
36
50
  // TODO: Move to visitors?
37
51
  if ((_a = node.modifiers) === null || _a === void 0 ? void 0 : _a.some(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword)) {
38
52
  return [];
39
53
  }
40
54
  const nodeVisitors = this.visitorMap.get(node.kind);
41
- if (!nodeVisitors || nodeVisitors.length === 0) {
55
+ if (!nodeVisitors) {
42
56
  this.diagnostics.push((0, diagnostics_1.unsupportedNodeKind)(node, node.kind));
43
57
  return isExpression ? [lua.createNilLiteral()] : [];
44
58
  }
45
59
  const previousNodeVisitors = this.currentNodeVisitors;
46
- this.currentNodeVisitors = [...nodeVisitors];
47
- const visitor = this.currentNodeVisitors.pop();
48
- const result = (0, lua_ast_1.unwrapVisitorResult)(visitor.transform(node, this));
60
+ const previousNodeVisitorsIndex = this.currentNodeVisitorsIndex;
61
+ this.currentNodeVisitors = nodeVisitors;
62
+ this.currentNodeVisitorsIndex = nodeVisitors.length - 1;
63
+ const visitor = this.currentNodeVisitors[this.currentNodeVisitorsIndex];
64
+ const result = visitor(node, this);
49
65
  this.currentNodeVisitors = previousNodeVisitors;
66
+ this.currentNodeVisitorsIndex = previousNodeVisitorsIndex;
50
67
  return result;
51
68
  }
52
69
  superTransformNode(node) {
53
- if (this.currentNodeVisitors.length === 0) {
70
+ return (0, lua_ast_1.unwrapVisitorResult)(this.doSuperTransformNode(node));
71
+ }
72
+ doSuperTransformNode(node) {
73
+ if (--this.currentNodeVisitorsIndex < 0) {
54
74
  throw new Error(`There is no super transform for ${ts.SyntaxKind[node.kind]} visitor`);
55
75
  }
56
- const visitor = this.currentNodeVisitors.pop();
57
- return (0, lua_ast_1.unwrapVisitorResult)(visitor.transform(node, this));
76
+ const visitor = this.currentNodeVisitors[this.currentNodeVisitorsIndex];
77
+ return (0, lua_ast_1.unwrapVisitorResult)(visitor(node, this));
58
78
  }
59
79
  transformExpression(node) {
60
- const [result] = this.transformNode(node, true);
80
+ const result = this.transformNodeRaw(node, true);
81
+ return this.assertIsExpression(node, result);
82
+ }
83
+ assertIsExpression(node, result) {
61
84
  if (result === undefined) {
62
85
  throw new Error(`Expression visitor for node type ${ts.SyntaxKind[node.kind]} did not return any result.`);
63
86
  }
87
+ if (Array.isArray(result)) {
88
+ return result[0];
89
+ }
64
90
  return result;
65
91
  }
66
92
  superTransformExpression(node) {
67
- const [result] = this.superTransformNode(node);
68
- if (result === undefined) {
69
- throw new Error(`Expression visitor for node type ${ts.SyntaxKind[node.kind]} did not return any result.`);
70
- }
71
- return result;
93
+ const result = this.doSuperTransformNode(node);
94
+ return this.assertIsExpression(node, result);
72
95
  }
73
96
  transformStatements(node) {
74
97
  return (0, utils_1.castArray)(node).flatMap(n => {
75
98
  this.pushPrecedingStatements();
76
99
  const statements = this.transformNode(n);
77
- statements.unshift(...this.popPrecedingStatements());
78
- return statements;
100
+ const result = this.popPrecedingStatements();
101
+ result.push(...statements);
102
+ return result;
79
103
  });
80
104
  }
81
105
  superTransformStatements(node) {
82
106
  return (0, utils_1.castArray)(node).flatMap(n => {
83
107
  this.pushPrecedingStatements();
84
108
  const statements = this.superTransformNode(n);
85
- statements.unshift(...this.popPrecedingStatements());
86
- return statements;
109
+ const result = this.popPrecedingStatements();
110
+ result.push(...statements);
111
+ return result;
87
112
  });
88
113
  }
89
114
  pushPrecedingStatements() {
@@ -97,18 +122,22 @@ class TransformationContext {
97
122
  addPrecedingStatements(statements) {
98
123
  const precedingStatements = this.precedingStatementsStack[this.precedingStatementsStack.length - 1];
99
124
  (0, utils_1.assert)(precedingStatements);
100
- if (!Array.isArray(statements)) {
101
- statements = [statements];
125
+ if (Array.isArray(statements)) {
126
+ precedingStatements.push(...statements);
127
+ }
128
+ else {
129
+ precedingStatements.push(statements);
102
130
  }
103
- precedingStatements.push(...statements);
104
131
  }
105
132
  prependPrecedingStatements(statements) {
106
133
  const precedingStatements = this.precedingStatementsStack[this.precedingStatementsStack.length - 1];
107
134
  (0, utils_1.assert)(precedingStatements);
108
- if (!Array.isArray(statements)) {
109
- statements = [statements];
135
+ if (Array.isArray(statements)) {
136
+ precedingStatements.unshift(...statements);
137
+ }
138
+ else {
139
+ precedingStatements.unshift(statements);
110
140
  }
111
- precedingStatements.unshift(...statements);
112
141
  }
113
142
  createTempName(prefix = "temp") {
114
143
  prefix = prefix.replace(/^_*/, ""); // Strip leading underscores because createSafeName will add them again
@@ -171,6 +200,19 @@ class TransformationContext {
171
200
  const name = this.getTempNameForNode(node);
172
201
  return lua.createIdentifier(this.createTempName(name), node, exports.tempSymbolId);
173
202
  }
203
+ nextSymbolId() {
204
+ return ++this.lastSymbolId;
205
+ }
206
+ pushScope(type) {
207
+ const scope = { type, id: ++this.lastScopeId };
208
+ this.scopeStack.push(scope);
209
+ return scope;
210
+ }
211
+ popScope() {
212
+ const scope = this.scopeStack.pop();
213
+ (0, utils_1.assert)(scope);
214
+ return scope;
215
+ }
174
216
  }
175
217
  exports.TransformationContext = TransformationContext;
176
218
  //# sourceMappingURL=context.js.map
@@ -149,5 +149,5 @@ export interface ObjectVisitor<T extends ts.Node> {
149
149
  export declare type Visitors = {
150
150
  [P in keyof NodesBySyntaxKind]?: Visitor<NodesBySyntaxKind[P]>;
151
151
  };
152
- export declare type VisitorMap = Map<ts.SyntaxKind, Array<ObjectVisitor<ts.Node>>>;
152
+ export declare type VisitorMap = Map<ts.SyntaxKind, Array<FunctionVisitor<ts.Node>>>;
153
153
  export {};
@@ -5,22 +5,23 @@ const utils_1 = require("../utils");
5
5
  const context_1 = require("./context");
6
6
  const visitors_1 = require("./visitors");
7
7
  function createVisitorMap(customVisitors) {
8
- const visitorMap = new Map();
8
+ const objectVisitorMap = new Map();
9
9
  for (const visitors of [visitors_1.standardVisitors, ...customVisitors]) {
10
10
  const priority = visitors === visitors_1.standardVisitors ? -Infinity : 0;
11
11
  for (const [syntaxKindKey, visitor] of Object.entries(visitors)) {
12
12
  if (!visitor)
13
13
  continue;
14
14
  const syntaxKind = Number(syntaxKindKey);
15
- const nodeVisitors = (0, utils_1.getOrUpdate)(visitorMap, syntaxKind, () => []);
15
+ const nodeVisitors = (0, utils_1.getOrUpdate)(objectVisitorMap, syntaxKind, () => []);
16
16
  const objectVisitor = typeof visitor === "function" ? { transform: visitor, priority } : visitor;
17
17
  nodeVisitors.push(objectVisitor);
18
18
  }
19
19
  }
20
- for (const nodeVisitors of visitorMap.values()) {
21
- nodeVisitors.sort((a, b) => { var _a, _b; return ((_a = a.priority) !== null && _a !== void 0 ? _a : 0) - ((_b = b.priority) !== null && _b !== void 0 ? _b : 0); });
20
+ const result = new Map();
21
+ for (const [kind, nodeVisitors] of objectVisitorMap) {
22
+ result.set(kind, nodeVisitors.sort((a, b) => { var _a, _b; return ((_a = a.priority) !== null && _a !== void 0 ? _a : 0) - ((_b = b.priority) !== null && _b !== void 0 ? _b : 0); }).map(visitor => visitor.transform));
22
23
  }
23
- return visitorMap;
24
+ return result;
24
25
  }
25
26
  exports.createVisitorMap = createVisitorMap;
26
27
  function transformSourceFile(program, sourceFile, visitorMap) {
@@ -1,20 +1,10 @@
1
1
  import * as ts from "typescript";
2
- import { TransformationContext } from "../context";
3
2
  export declare enum AnnotationKind {
4
- Extension = "extension",
5
- MetaExtension = "metaExtension",
6
3
  CustomConstructor = "customConstructor",
7
4
  CompileMembersOnly = "compileMembersOnly",
8
5
  NoResolution = "noResolution",
9
- PureAbstract = "pureAbstract",
10
- Phantom = "phantom",
11
- TupleReturn = "tupleReturn",
12
- LuaIterator = "luaIterator",
13
- LuaTable = "luaTable",
14
6
  NoSelf = "noSelf",
15
- NoSelfInFile = "noSelfInFile",
16
- Vararg = "vararg",
17
- ForRange = "forRange"
7
+ NoSelfInFile = "noSelfInFile"
18
8
  }
19
9
  export interface Annotation {
20
10
  kind: AnnotationKind;
@@ -25,9 +15,3 @@ export declare function getSymbolAnnotations(symbol: ts.Symbol): AnnotationsMap;
25
15
  export declare function getTypeAnnotations(type: ts.Type): AnnotationsMap;
26
16
  export declare function getNodeAnnotations(node: ts.Node): AnnotationsMap;
27
17
  export declare function getFileAnnotations(sourceFile: ts.SourceFile): AnnotationsMap;
28
- export declare function getSignatureAnnotations(context: TransformationContext, signature: ts.Signature): AnnotationsMap;
29
- export declare function isTupleReturnCall(context: TransformationContext, node: ts.Node): boolean;
30
- export declare function isLuaIteratorType(context: TransformationContext, node: ts.Node): boolean;
31
- export declare function isVarargType(context: TransformationContext, node: ts.Node): boolean;
32
- export declare function isForRangeType(context: TransformationContext, node: ts.Node): boolean;
33
- export declare function getTagArgsFromComment(tag: ts.JSDocTag): string[];
@@ -1,135 +1,96 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTagArgsFromComment = exports.isForRangeType = exports.isVarargType = exports.isLuaIteratorType = exports.isTupleReturnCall = exports.getSignatureAnnotations = exports.getFileAnnotations = exports.getNodeAnnotations = exports.getTypeAnnotations = exports.getSymbolAnnotations = exports.AnnotationKind = void 0;
3
+ exports.getFileAnnotations = exports.getNodeAnnotations = exports.getTypeAnnotations = exports.getSymbolAnnotations = exports.AnnotationKind = void 0;
4
4
  const ts = require("typescript");
5
5
  var AnnotationKind;
6
6
  (function (AnnotationKind) {
7
- AnnotationKind["Extension"] = "extension";
8
- AnnotationKind["MetaExtension"] = "metaExtension";
9
7
  AnnotationKind["CustomConstructor"] = "customConstructor";
10
8
  AnnotationKind["CompileMembersOnly"] = "compileMembersOnly";
11
9
  AnnotationKind["NoResolution"] = "noResolution";
12
- AnnotationKind["PureAbstract"] = "pureAbstract";
13
- AnnotationKind["Phantom"] = "phantom";
14
- AnnotationKind["TupleReturn"] = "tupleReturn";
15
- AnnotationKind["LuaIterator"] = "luaIterator";
16
- AnnotationKind["LuaTable"] = "luaTable";
17
10
  AnnotationKind["NoSelf"] = "noSelf";
18
11
  AnnotationKind["NoSelfInFile"] = "noSelfInFile";
19
- AnnotationKind["Vararg"] = "vararg";
20
- AnnotationKind["ForRange"] = "forRange";
21
12
  })(AnnotationKind = exports.AnnotationKind || (exports.AnnotationKind = {}));
22
- function createAnnotation(name, args) {
23
- const kind = Object.values(AnnotationKind).find(k => k.toLowerCase() === name.toLowerCase());
24
- if (kind !== undefined) {
25
- return { kind, args };
26
- }
27
- }
13
+ const annotationValues = new Map(Object.values(AnnotationKind).map(k => [k.toLowerCase(), k]));
28
14
  function collectAnnotations(source, annotationsMap) {
29
15
  var _a, _b;
30
16
  for (const tag of source.getJsDocTags()) {
31
- const annotation = createAnnotation(tag.name, (_b = (_a = tag.text) === null || _a === void 0 ? void 0 : _a.map(p => p.text)) !== null && _b !== void 0 ? _b : []);
32
- if (annotation) {
33
- annotationsMap.set(annotation.kind, annotation);
34
- }
17
+ const tagName = annotationValues.get(tag.name.toLowerCase());
18
+ if (!tagName)
19
+ continue;
20
+ const annotation = {
21
+ kind: tag.name,
22
+ args: (_b = (_a = tag.text) === null || _a === void 0 ? void 0 : _a.map(p => p.text)) !== null && _b !== void 0 ? _b : [],
23
+ };
24
+ annotationsMap.set(tagName, annotation);
35
25
  }
36
26
  }
27
+ const symbolAnnotations = new WeakMap();
37
28
  function getSymbolAnnotations(symbol) {
29
+ const known = symbolAnnotations.get(symbol);
30
+ if (known)
31
+ return known;
38
32
  const annotationsMap = new Map();
39
33
  collectAnnotations(symbol, annotationsMap);
34
+ symbolAnnotations.set(symbol, annotationsMap);
40
35
  return annotationsMap;
41
36
  }
42
37
  exports.getSymbolAnnotations = getSymbolAnnotations;
43
38
  function getTypeAnnotations(type) {
39
+ // types are not frequently repeatedly polled for annotations, so it's not worth caching them
44
40
  const annotationsMap = new Map();
45
- if (type.symbol)
46
- collectAnnotations(type.symbol, annotationsMap);
47
- if (type.aliasSymbol)
48
- collectAnnotations(type.aliasSymbol, annotationsMap);
41
+ if (type.symbol) {
42
+ getSymbolAnnotations(type.symbol).forEach((value, key) => {
43
+ annotationsMap.set(key, value);
44
+ });
45
+ }
46
+ if (type.aliasSymbol) {
47
+ getSymbolAnnotations(type.aliasSymbol).forEach((value, key) => {
48
+ annotationsMap.set(key, value);
49
+ });
50
+ }
49
51
  return annotationsMap;
50
52
  }
51
53
  exports.getTypeAnnotations = getTypeAnnotations;
54
+ const nodeAnnotations = new WeakMap();
52
55
  function getNodeAnnotations(node) {
56
+ const known = nodeAnnotations.get(node);
57
+ if (known)
58
+ return known;
53
59
  const annotationsMap = new Map();
54
- for (const tag of ts.getJSDocTags(node)) {
55
- const tagName = tag.tagName.text;
56
- const annotation = createAnnotation(tagName, getTagArgsFromComment(tag));
57
- if (annotation) {
58
- annotationsMap.set(annotation.kind, annotation);
59
- }
60
- }
60
+ collectAnnotationsFromTags(annotationsMap, ts.getAllJSDocTags(node, ts.isJSDocUnknownTag));
61
+ nodeAnnotations.set(node, annotationsMap);
61
62
  return annotationsMap;
62
63
  }
63
64
  exports.getNodeAnnotations = getNodeAnnotations;
65
+ function collectAnnotationsFromTags(annotationsMap, tags) {
66
+ for (const tag of tags) {
67
+ const tagName = annotationValues.get(tag.tagName.text.toLowerCase());
68
+ if (!tagName)
69
+ continue;
70
+ annotationsMap.set(tagName, { kind: tagName, args: getTagArgsFromComment(tag) });
71
+ }
72
+ }
73
+ const fileAnnotations = new WeakMap();
64
74
  function getFileAnnotations(sourceFile) {
75
+ const known = fileAnnotations.get(sourceFile);
76
+ if (known)
77
+ return known;
65
78
  const annotationsMap = new Map();
66
79
  if (sourceFile.statements.length > 0) {
67
80
  // Manually collect jsDoc because `getJSDocTags` includes tags only from closest comment
68
81
  const jsDoc = sourceFile.statements[0].jsDoc;
69
82
  if (jsDoc) {
70
- for (const tag of jsDoc.flatMap(x => { var _a; return (_a = x.tags) !== null && _a !== void 0 ? _a : []; })) {
71
- const tagName = tag.tagName.text;
72
- const annotation = createAnnotation(tagName, getTagArgsFromComment(tag));
73
- if (annotation) {
74
- annotationsMap.set(annotation.kind, annotation);
83
+ for (const jsDocElement of jsDoc) {
84
+ if (jsDocElement.tags) {
85
+ collectAnnotationsFromTags(annotationsMap, jsDocElement.tags);
75
86
  }
76
87
  }
77
88
  }
78
89
  }
90
+ fileAnnotations.set(sourceFile, annotationsMap);
79
91
  return annotationsMap;
80
92
  }
81
93
  exports.getFileAnnotations = getFileAnnotations;
82
- function getSignatureAnnotations(context, signature) {
83
- const annotationsMap = new Map();
84
- collectAnnotations(signature, annotationsMap);
85
- // Function properties on interfaces have the JSDoc tags on the parent PropertySignature
86
- const declaration = signature.getDeclaration();
87
- if ((declaration === null || declaration === void 0 ? void 0 : declaration.parent) && ts.isPropertySignature(declaration.parent)) {
88
- const symbol = context.checker.getSymbolAtLocation(declaration.parent.name);
89
- if (symbol) {
90
- collectAnnotations(symbol, annotationsMap);
91
- }
92
- }
93
- return annotationsMap;
94
- }
95
- exports.getSignatureAnnotations = getSignatureAnnotations;
96
- function isTupleReturnCall(context, node) {
97
- if (!ts.isCallExpression(node)) {
98
- return false;
99
- }
100
- const signature = context.checker.getResolvedSignature(node);
101
- if (signature) {
102
- if (getSignatureAnnotations(context, signature).has(AnnotationKind.TupleReturn)) {
103
- return true;
104
- }
105
- // Only check function type for directive if it is declared as an interface or type alias
106
- const declaration = signature.getDeclaration();
107
- const isInterfaceOrAlias = (declaration === null || declaration === void 0 ? void 0 : declaration.parent) &&
108
- ((ts.isInterfaceDeclaration(declaration.parent) && ts.isCallSignatureDeclaration(declaration)) ||
109
- ts.isTypeAliasDeclaration(declaration.parent));
110
- if (!isInterfaceOrAlias) {
111
- return false;
112
- }
113
- }
114
- const type = context.checker.getTypeAtLocation(node.expression);
115
- return getTypeAnnotations(type).has(AnnotationKind.TupleReturn);
116
- }
117
- exports.isTupleReturnCall = isTupleReturnCall;
118
- function isLuaIteratorType(context, node) {
119
- const type = context.checker.getTypeAtLocation(node);
120
- return getTypeAnnotations(type).has(AnnotationKind.LuaIterator);
121
- }
122
- exports.isLuaIteratorType = isLuaIteratorType;
123
- function isVarargType(context, node) {
124
- const type = context.checker.getTypeAtLocation(node);
125
- return getTypeAnnotations(type).has(AnnotationKind.Vararg);
126
- }
127
- exports.isVarargType = isVarargType;
128
- function isForRangeType(context, node) {
129
- const type = context.checker.getTypeAtLocation(node);
130
- return getTypeAnnotations(type).has(AnnotationKind.ForRange);
131
- }
132
- exports.isForRangeType = isForRangeType;
133
94
  function getTagArgsFromComment(tag) {
134
95
  if (tag.comment) {
135
96
  if (typeof tag.comment === "string") {
@@ -141,5 +102,4 @@ function getTagArgsFromComment(tag) {
141
102
  }
142
103
  return [];
143
104
  }
144
- exports.getTagArgsFromComment = getTagArgsFromComment;
145
105
  //# sourceMappingURL=annotations.js.map
@@ -8,6 +8,7 @@ const function_context_1 = require("./function-context");
8
8
  // TODO: Clear if types are reused between compilations
9
9
  const typeValidationCache = new WeakMap();
10
10
  function validateAssignment(context, node, fromType, toType, toName) {
11
+ var _a, _b;
11
12
  if (toType === fromType) {
12
13
  return;
13
14
  }
@@ -21,13 +22,9 @@ function validateAssignment(context, node, fromType, toType, toName) {
21
22
  return;
22
23
  fromTypeCache.add(toType);
23
24
  validateFunctionAssignment(context, node, fromType, toType, toName);
24
- const fromTypeNode = context.checker.typeToTypeNode(fromType, undefined, undefined);
25
- const toTypeNode = context.checker.typeToTypeNode(toType, undefined, undefined);
26
- if (!fromTypeNode || !toTypeNode) {
27
- return;
28
- }
29
- if ((ts.isArrayTypeNode(toTypeNode) || ts.isTupleTypeNode(toTypeNode)) &&
30
- (ts.isArrayTypeNode(fromTypeNode) || ts.isTupleTypeNode(fromTypeNode))) {
25
+ const checker = context.checker;
26
+ if ((checker.isTupleType(toType) || checker.isArrayType(toType)) &&
27
+ (checker.isTupleType(fromType) || checker.isArrayType(fromType))) {
31
28
  // Recurse into arrays/tuples
32
29
  const fromTypeArguments = fromType.typeArguments;
33
30
  const toTypeArguments = toType.typeArguments;
@@ -39,25 +36,32 @@ function validateAssignment(context, node, fromType, toType, toName) {
39
36
  validateAssignment(context, node, fromTypeArguments[i], toTypeArguments[i], toName);
40
37
  }
41
38
  }
42
- if ((toType.flags & ts.TypeFlags.Object) !== 0 &&
43
- (ts.isTypeLiteralNode(toTypeNode) ||
44
- (toType.objectFlags & ts.ObjectFlags.ClassOrInterface) !== 0) &&
45
- toType.symbol &&
46
- toType.symbol.members &&
47
- fromType.symbol &&
48
- fromType.symbol.members) {
39
+ const fromMembers = (_a = fromType.symbol) === null || _a === void 0 ? void 0 : _a.members;
40
+ const toMembers = (_b = toType.symbol) === null || _b === void 0 ? void 0 : _b.members;
41
+ if (fromMembers && toMembers) {
49
42
  // Recurse into interfaces
50
- toType.symbol.members.forEach((toMember, escapedMemberName) => {
51
- if (fromType.symbol.members) {
52
- const fromMember = fromType.symbol.members.get(escapedMemberName);
43
+ if (toMembers.size < fromMembers.size) {
44
+ toMembers.forEach((toMember, escapedMemberName) => {
45
+ const fromMember = fromMembers.get(escapedMemberName);
53
46
  if (fromMember) {
54
- const toMemberType = context.checker.getTypeOfSymbolAtLocation(toMember, node);
55
- const fromMemberType = context.checker.getTypeOfSymbolAtLocation(fromMember, node);
56
- const memberName = ts.unescapeLeadingUnderscores(escapedMemberName);
57
- validateAssignment(context, node, fromMemberType, toMemberType, toName ? `${toName}.${memberName}` : memberName);
47
+ validateMember(toMember, fromMember, escapedMemberName);
48
+ }
49
+ });
50
+ }
51
+ else {
52
+ fromMembers.forEach((fromMember, escapedMemberName) => {
53
+ const toMember = toMembers.get(escapedMemberName);
54
+ if (toMember) {
55
+ validateMember(toMember, fromMember, escapedMemberName);
58
56
  }
59
- }
60
- });
57
+ });
58
+ }
59
+ }
60
+ function validateMember(toMember, fromMember, escapedMemberName) {
61
+ const toMemberType = context.checker.getTypeOfSymbolAtLocation(toMember, node);
62
+ const fromMemberType = context.checker.getTypeOfSymbolAtLocation(fromMember, node);
63
+ const memberName = ts.unescapeLeadingUnderscores(escapedMemberName);
64
+ validateAssignment(context, node, fromMemberType, toMemberType, toName ? `${toName}.${memberName}` : memberName);
61
65
  }
62
66
  }
63
67
  exports.validateAssignment = validateAssignment;
@@ -74,10 +74,7 @@ export declare const invalidMultiTypeToEmptyPatternOrArrayLiteral: ((node: ts.No
74
74
  export declare const invalidMultiReturnAccess: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
75
75
  code: number;
76
76
  };
77
- export declare const invalidOperatorMappingUse: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
78
- code: number;
79
- };
80
- export declare const invalidTableExtensionUse: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
77
+ export declare const invalidCallExtensionUse: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
81
78
  code: number;
82
79
  };
83
80
  export declare const annotationRemoved: ((node: ts.Node, kind: AnnotationKind) => ts.Diagnostic) & {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.undefinedInArrayLiteral = exports.unsupportedOptionalCompileMembersOnly = exports.unsupportedBuiltinOptionalCall = exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTargetButOverrideAvailable = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidPairsIterableWithoutDestructuring = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
3
+ exports.undefinedInArrayLiteral = exports.unsupportedOptionalCompileMembersOnly = exports.unsupportedBuiltinOptionalCall = exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidCallExtensionUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTargetButOverrideAvailable = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidPairsIterableWithoutDestructuring = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
4
4
  const ts = require("typescript");
5
5
  const CompilerOptions_1 = require("../../CompilerOptions");
6
6
  const utils_1 = require("../../utils");
@@ -52,8 +52,7 @@ exports.invalidMultiFunctionReturnType = createErrorDiagnosticFactory("The $mult
52
52
  exports.invalidMultiTypeToNonArrayLiteral = createErrorDiagnosticFactory("Expected an array literal.");
53
53
  exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = createErrorDiagnosticFactory("There must be one or more elements specified here.");
54
54
  exports.invalidMultiReturnAccess = createErrorDiagnosticFactory("The LuaMultiReturn type can only be accessed via an element access expression of a numeric type.");
55
- exports.invalidOperatorMappingUse = createErrorDiagnosticFactory("This function must always be directly called and cannot be referred to.");
56
- exports.invalidTableExtensionUse = createErrorDiagnosticFactory("This function must be called directly and cannot be referred to.");
55
+ exports.invalidCallExtensionUse = createErrorDiagnosticFactory("This function must be called directly and cannot be referred to.");
57
56
  exports.annotationRemoved = createErrorDiagnosticFactory((kind) => `'@${kind}' has been removed and will no longer have any effect.` +
58
57
  `See https://typescripttolua.github.io/docs/advanced/compiler-annotations#${kind.toLowerCase()} for more information.`);
59
58
  exports.annotationDeprecated = createWarningDiagnosticFactory((kind) => `'@${kind}' is deprecated and will be removed in a future update. Please update your code before upgrading to the next release, otherwise your project will no longer compile. ` +
@@ -6,5 +6,5 @@ export declare enum ContextType {
6
6
  NonVoid = 2,
7
7
  Mixed = 3
8
8
  }
9
- export declare function getDeclarationContextType({ program }: TransformationContext, signatureDeclaration: ts.SignatureDeclaration): ContextType;
9
+ export declare function getDeclarationContextType(context: TransformationContext, signatureDeclaration: ts.SignatureDeclaration): ContextType;
10
10
  export declare function getFunctionContextType(context: TransformationContext, type: ts.Type): ContextType;