typescript-to-lua 1.6.3 → 1.7.2
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.
- package/dist/CompilerOptions.d.ts +1 -0
- package/dist/cli/parse.js +5 -0
- package/dist/lualib/ArraySlice.lua +10 -2
- package/dist/lualib/ArraySplice.lua +5 -1
- package/dist/lualib/Generator.lua +8 -1
- package/dist/lualib/ParseFloat.lua +5 -1
- package/dist/lualib/SparseArraySpread.lua +5 -1
- package/dist/lualib/StringCharCodeAt.lua +5 -1
- package/dist/lualib/lualib_bundle.lua +38 -7
- package/dist/lualib-build/plugin.js +1 -2
- package/dist/measure-performance.d.ts +15 -0
- package/dist/measure-performance.js +83 -0
- package/dist/transformation/builtins/array.js +2 -1
- package/dist/transformation/builtins/function.js +1 -1
- package/dist/transformation/builtins/global.d.ts +1 -1
- package/dist/transformation/builtins/global.js +13 -12
- package/dist/transformation/builtins/index.d.ts +2 -2
- package/dist/transformation/builtins/index.js +87 -89
- package/dist/transformation/builtins/object.d.ts +1 -1
- package/dist/transformation/builtins/object.js +4 -4
- package/dist/transformation/builtins/promise.js +4 -2
- package/dist/transformation/builtins/string.js +2 -0
- package/dist/transformation/context/context.d.ts +15 -0
- package/dist/transformation/context/context.js +66 -24
- package/dist/transformation/context/visitors.d.ts +1 -1
- package/dist/transformation/index.js +6 -5
- package/dist/transformation/utils/annotations.d.ts +1 -17
- package/dist/transformation/utils/annotations.js +48 -88
- package/dist/transformation/utils/assignment-validation.js +27 -23
- package/dist/transformation/utils/diagnostics.d.ts +1 -4
- package/dist/transformation/utils/diagnostics.js +2 -3
- package/dist/transformation/utils/function-context.d.ts +1 -1
- package/dist/transformation/utils/function-context.js +57 -51
- package/dist/transformation/utils/language-extensions.d.ts +57 -51
- package/dist/transformation/utils/language-extensions.js +99 -119
- package/dist/transformation/utils/lualib.d.ts +0 -1
- package/dist/transformation/utils/lualib.js +2 -8
- package/dist/transformation/utils/safe-names.d.ts +1 -1
- package/dist/transformation/utils/safe-names.js +3 -6
- package/dist/transformation/utils/scope.d.ts +0 -2
- package/dist/transformation/utils/scope.js +10 -27
- package/dist/transformation/utils/symbols.d.ts +1 -1
- package/dist/transformation/utils/symbols.js +7 -20
- package/dist/transformation/utils/typescript/index.d.ts +1 -0
- package/dist/transformation/utils/typescript/index.js +2 -1
- package/dist/transformation/utils/typescript/types.d.ts +2 -5
- package/dist/transformation/utils/typescript/types.js +27 -37
- package/dist/transformation/visitors/access.js +1 -4
- package/dist/transformation/visitors/block.js +4 -4
- package/dist/transformation/visitors/call.js +10 -21
- package/dist/transformation/visitors/class/index.js +8 -20
- package/dist/transformation/visitors/class/members/constructor.js +2 -2
- package/dist/transformation/visitors/class/new.js +2 -5
- package/dist/transformation/visitors/class/setup.d.ts +1 -1
- package/dist/transformation/visitors/class/setup.js +4 -4
- package/dist/transformation/visitors/class/utils.d.ts +1 -1
- package/dist/transformation/visitors/class/utils.js +2 -9
- package/dist/transformation/visitors/conditional.js +4 -4
- package/dist/transformation/visitors/function.d.ts +1 -1
- package/dist/transformation/visitors/function.js +8 -16
- package/dist/transformation/visitors/identifier.d.ts +1 -0
- package/dist/transformation/visitors/identifier.js +40 -44
- package/dist/transformation/visitors/language-extensions/call-extension.d.ts +10 -0
- package/dist/transformation/visitors/language-extensions/call-extension.js +23 -0
- package/dist/transformation/visitors/language-extensions/identifier.d.ts +5 -0
- package/dist/transformation/visitors/language-extensions/identifier.js +27 -0
- package/dist/transformation/visitors/language-extensions/iterable.d.ts +2 -3
- package/dist/transformation/visitors/language-extensions/iterable.js +23 -22
- package/dist/transformation/visitors/language-extensions/multi.d.ts +0 -1
- package/dist/transformation/visitors/language-extensions/multi.js +10 -24
- package/dist/transformation/visitors/language-extensions/operators.d.ts +2 -5
- package/dist/transformation/visitors/language-extensions/operators.js +89 -96
- package/dist/transformation/visitors/language-extensions/range.js +4 -2
- package/dist/transformation/visitors/language-extensions/table.d.ts +6 -3
- package/dist/transformation/visitors/language-extensions/table.js +46 -75
- package/dist/transformation/visitors/language-extensions/vararg.js +7 -3
- package/dist/transformation/visitors/literal.js +2 -23
- package/dist/transformation/visitors/loops/for-of.js +18 -18
- package/dist/transformation/visitors/loops/utils.js +5 -5
- package/dist/transformation/visitors/modules/import.js +2 -2
- package/dist/transformation/visitors/namespace.js +5 -14
- package/dist/transformation/visitors/return.js +2 -3
- package/dist/transformation/visitors/sourceFile.js +3 -4
- package/dist/transformation/visitors/spread.js +0 -5
- package/dist/transformation/visitors/switch.js +2 -2
- package/dist/transformation/visitors/variable-declaration.js +1 -1
- package/dist/transpilation/plugins.js +3 -0
- package/dist/transpilation/resolve.js +210 -186
- package/dist/transpilation/transpile.js +10 -0
- package/dist/transpilation/transpiler.d.ts +1 -0
- package/dist/transpilation/transpiler.js +18 -5
- package/dist/tstl.js +21 -0
- package/language-extensions/index.d.ts +167 -67
- package/package.json +2 -2
- package/dist/transformation/visitors/language-extensions/index.d.ts +0 -4
- package/dist/transformation/visitors/language-extensions/index.js +0 -17
- package/dist/transformation/visitors/language-extensions/pairsIterable.d.ts +0 -5
- package/dist/transformation/visitors/language-extensions/pairsIterable.js +0 -53
|
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.transformModuleDeclaration = exports.createModuleLocalNameIdentifier = void 0;
|
|
4
4
|
const ts = require("typescript");
|
|
5
5
|
const lua = require("../../LuaAST");
|
|
6
|
-
const annotations_1 = require("../utils/annotations");
|
|
7
|
-
const diagnostics_1 = require("../utils/diagnostics");
|
|
8
6
|
const export_1 = require("../utils/export");
|
|
9
7
|
const lua_ast_1 = require("../utils/lua-ast");
|
|
10
8
|
const safe_names_1 = require("../utils/safe-names");
|
|
@@ -33,16 +31,9 @@ function moduleHasEmittedBody(node) {
|
|
|
33
31
|
}
|
|
34
32
|
return false;
|
|
35
33
|
}
|
|
36
|
-
// Static context -> namespace dictionary keeping the current namespace for each transformation context
|
|
37
|
-
const currentNamespaces = new WeakMap();
|
|
38
34
|
const transformModuleDeclaration = (node, context) => {
|
|
39
35
|
var _a, _b;
|
|
40
|
-
const
|
|
41
|
-
// If phantom namespace elide the declaration and return the body
|
|
42
|
-
if (annotations.has(annotations_1.AnnotationKind.Phantom)) {
|
|
43
|
-
context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Phantom));
|
|
44
|
-
}
|
|
45
|
-
const currentNamespace = currentNamespaces.get(context);
|
|
36
|
+
const currentNamespace = context.currentNamespaces;
|
|
46
37
|
const result = [];
|
|
47
38
|
const symbol = context.checker.getSymbolAtLocation(node.name);
|
|
48
39
|
const hasExports = symbol !== undefined && context.checker.getExportsOfModule(symbol).length > 0;
|
|
@@ -75,15 +66,15 @@ const transformModuleDeclaration = (node, context) => {
|
|
|
75
66
|
}
|
|
76
67
|
// Set current namespace for nested NS
|
|
77
68
|
// Keep previous namespace to reset after block transpilation
|
|
78
|
-
currentNamespaces
|
|
69
|
+
context.currentNamespaces = node;
|
|
79
70
|
// Transform moduleblock to block and visit it
|
|
80
71
|
if (moduleHasEmittedBody(node)) {
|
|
81
|
-
|
|
72
|
+
context.pushScope(scope_1.ScopeType.Block);
|
|
82
73
|
const statements = (0, scope_1.performHoisting)(context, context.transformStatements(ts.isModuleBlock(node.body) ? node.body.statements : node.body));
|
|
83
|
-
|
|
74
|
+
context.popScope();
|
|
84
75
|
result.push(lua.createDoStatement(statements));
|
|
85
76
|
}
|
|
86
|
-
currentNamespaces
|
|
77
|
+
context.currentNamespaces = currentNamespace;
|
|
87
78
|
return result;
|
|
88
79
|
};
|
|
89
80
|
exports.transformModuleDeclaration = transformModuleDeclaration;
|
|
@@ -60,7 +60,6 @@ const transformReturnStatement = (statement, context) => {
|
|
|
60
60
|
};
|
|
61
61
|
exports.transformReturnStatement = transformReturnStatement;
|
|
62
62
|
function createReturnStatement(context, values, node) {
|
|
63
|
-
const results = [...values];
|
|
64
63
|
if ((0, typescript_1.isInAsyncFunction)(node)) {
|
|
65
64
|
return lua.createReturnStatement([
|
|
66
65
|
lua.createCallExpression(lua.createIdentifier("____awaiter_resolve"), [lua.createNilLiteral(), ...values]),
|
|
@@ -68,9 +67,9 @@ function createReturnStatement(context, values, node) {
|
|
|
68
67
|
}
|
|
69
68
|
if (isInTryCatch(context)) {
|
|
70
69
|
// Bubble up explicit return flag and check if we're inside a try/catch block
|
|
71
|
-
|
|
70
|
+
values = [lua.createBooleanLiteral(true), ...values];
|
|
72
71
|
}
|
|
73
|
-
return lua.createReturnStatement(
|
|
72
|
+
return lua.createReturnStatement(values, node);
|
|
74
73
|
}
|
|
75
74
|
exports.createReturnStatement = createReturnStatement;
|
|
76
75
|
function isInTryCatch(context) {
|
|
@@ -5,7 +5,6 @@ const ts = require("typescript");
|
|
|
5
5
|
const lua = require("../../LuaAST");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const lua_ast_1 = require("../utils/lua-ast");
|
|
8
|
-
const lualib_1 = require("../utils/lualib");
|
|
9
8
|
const preceding_statements_1 = require("../utils/preceding-statements");
|
|
10
9
|
const scope_1 = require("../utils/scope");
|
|
11
10
|
const typescript_1 = require("../utils/typescript");
|
|
@@ -28,9 +27,9 @@ const transformSourceFileNode = (node, context) => {
|
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
else {
|
|
31
|
-
|
|
30
|
+
context.pushScope(scope_1.ScopeType.File);
|
|
32
31
|
statements = (0, scope_1.performHoisting)(context, context.transformStatements(node.statements));
|
|
33
|
-
|
|
32
|
+
context.popScope();
|
|
34
33
|
if (context.isModule) {
|
|
35
34
|
// If export equals was not used. Create the exports table.
|
|
36
35
|
// local ____exports = {}
|
|
@@ -42,7 +41,7 @@ const transformSourceFileNode = (node, context) => {
|
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
const trivia = (_b = (_a = node.getFullText().match(/^#!.*\r?\n/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : "";
|
|
45
|
-
return lua.createFile(statements,
|
|
44
|
+
return lua.createFile(statements, context.usedLuaLibFeatures, trivia, node);
|
|
46
45
|
};
|
|
47
46
|
exports.transformSourceFileNode = transformSourceFileNode;
|
|
48
47
|
//# sourceMappingURL=sourceFile.js.map
|
|
@@ -3,13 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.transformSpreadElement = exports.isOptimizedVarArgSpread = void 0;
|
|
4
4
|
const ts = require("typescript");
|
|
5
5
|
const lua = require("../../LuaAST");
|
|
6
|
-
const annotations_1 = require("../utils/annotations");
|
|
7
6
|
const lua_ast_1 = require("../utils/lua-ast");
|
|
8
7
|
const lualib_1 = require("../utils/lualib");
|
|
9
8
|
const scope_1 = require("../utils/scope");
|
|
10
9
|
const typescript_1 = require("../utils/typescript");
|
|
11
10
|
const multi_1 = require("./language-extensions/multi");
|
|
12
|
-
const diagnostics_1 = require("../utils/diagnostics");
|
|
13
11
|
const vararg_1 = require("./language-extensions/vararg");
|
|
14
12
|
function isOptimizedVarArgSpread(context, symbol, identifier) {
|
|
15
13
|
var _a;
|
|
@@ -53,9 +51,6 @@ exports.isOptimizedVarArgSpread = isOptimizedVarArgSpread;
|
|
|
53
51
|
const transformSpreadElement = (node, context) => {
|
|
54
52
|
const tsInnerExpression = ts.skipOuterExpressions(node.expression);
|
|
55
53
|
if (ts.isIdentifier(tsInnerExpression)) {
|
|
56
|
-
if ((0, annotations_1.isVarargType)(context, tsInnerExpression)) {
|
|
57
|
-
context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Vararg));
|
|
58
|
-
}
|
|
59
54
|
const symbol = context.checker.getSymbolAtLocation(tsInnerExpression);
|
|
60
55
|
if (symbol && isOptimizedVarArgSpread(context, symbol, tsInnerExpression)) {
|
|
61
56
|
return lua.createDotsLiteral(node);
|
|
@@ -39,7 +39,7 @@ const coalesceCondition = (condition, conditionPrecedingStatements, switchVariab
|
|
|
39
39
|
return [[...conditionPrecedingStatements, ...precedingStatements], comparison];
|
|
40
40
|
};
|
|
41
41
|
const transformSwitchStatement = (statement, context) => {
|
|
42
|
-
const scope =
|
|
42
|
+
const scope = context.pushScope(scope_1.ScopeType.Switch);
|
|
43
43
|
// Give the switch and condition accumulator a unique name to prevent nested switches from acting up.
|
|
44
44
|
const switchName = `____switch${scope.id}`;
|
|
45
45
|
const conditionName = `____cond${scope.id}`;
|
|
@@ -158,7 +158,7 @@ const transformSwitchStatement = (statement, context) => {
|
|
|
158
158
|
if (hoistedIdentifiers.length > 0) {
|
|
159
159
|
statements.unshift(lua.createVariableDeclarationStatement(hoistedIdentifiers));
|
|
160
160
|
}
|
|
161
|
-
|
|
161
|
+
context.popScope();
|
|
162
162
|
// Add the switch expression after hoisting
|
|
163
163
|
const expression = context.transformExpression(statement.expression);
|
|
164
164
|
statements.unshift(lua.createVariableDeclarationStatement(switchVariable, expression));
|
|
@@ -201,7 +201,7 @@ function transformVariableDeclaration(context, statement) {
|
|
|
201
201
|
// Skip named function expressions because they will have been wrapped already
|
|
202
202
|
if (ts.isFunctionExpression(initializer) && initializer.name)
|
|
203
203
|
return false;
|
|
204
|
-
return (0, function_1.isFunctionTypeWithProperties)(context.checker.getTypeAtLocation(statement.name));
|
|
204
|
+
return (0, function_1.isFunctionTypeWithProperties)(context, context.checker.getTypeAtLocation(statement.name));
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
exports.transformVariableDeclaration = transformVariableDeclaration;
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getPlugins = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
|
+
const performance = require("../measure-performance");
|
|
5
6
|
function getPlugins(program) {
|
|
6
7
|
var _a;
|
|
8
|
+
performance.startSection("getPlugins");
|
|
7
9
|
const diagnostics = [];
|
|
8
10
|
const pluginsFromOptions = [];
|
|
9
11
|
const options = program.getCompilerOptions();
|
|
@@ -20,6 +22,7 @@ function getPlugins(program) {
|
|
|
20
22
|
if (options.tstlVerbose) {
|
|
21
23
|
console.log(`Loaded ${pluginsFromOptions.length} plugins`);
|
|
22
24
|
}
|
|
25
|
+
performance.endSection("getPlugins");
|
|
23
26
|
return { diagnostics, plugins: pluginsFromOptions };
|
|
24
27
|
}
|
|
25
28
|
exports.getPlugins = getPlugins;
|
|
@@ -21,223 +21,238 @@ class ResolutionContext {
|
|
|
21
21
|
this.program = program;
|
|
22
22
|
this.options = options;
|
|
23
23
|
this.emitHost = emitHost;
|
|
24
|
-
this.
|
|
24
|
+
this.diagnostics = [];
|
|
25
|
+
this.resolvedFiles = new Map();
|
|
26
|
+
this.processedDependencies = new Set();
|
|
27
|
+
// value is false if already searched but not found
|
|
28
|
+
this.pathToFile = new Map();
|
|
25
29
|
this.noResolvePaths = new Set(options.noResolvePaths);
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
addAndResolveDependencies(file) {
|
|
32
|
+
if (this.resolvedFiles.has(file.fileName))
|
|
33
|
+
return;
|
|
34
|
+
this.resolvedFiles.set(file.fileName, file);
|
|
35
|
+
for (const required of findRequiredPaths(file.code)) {
|
|
36
|
+
// Do not resolve noResolution paths
|
|
37
|
+
if (required.startsWith("@NoResolution:")) {
|
|
38
|
+
// Remove @NoResolution prefix if not building in library mode
|
|
39
|
+
if (!isBuildModeLibrary(this.program)) {
|
|
40
|
+
const path = required.replace("@NoResolution:", "");
|
|
41
|
+
replaceRequireInCode(file, required, path);
|
|
42
|
+
replaceRequireInSourceMap(file, required, path);
|
|
43
|
+
}
|
|
44
|
+
// Skip
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Try to resolve the import starting from the directory `file` is in
|
|
48
|
+
this.resolveImport(file, required);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
resolveImport(file, required) {
|
|
52
|
+
// Do no resolve lualib - always use the lualib of the application entry point, not the lualib from external packages
|
|
53
|
+
if (required === "lualib_bundle") {
|
|
54
|
+
this.resolvedFiles.set("lualib_bundle", { fileName: "lualib_bundle", code: "" });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
28
57
|
if (this.noResolvePaths.has(required)) {
|
|
29
58
|
if (this.options.tstlVerbose) {
|
|
30
59
|
console.log(`Skipping module resolution of ${required} as it is in the tsconfig noResolvePaths.`);
|
|
31
60
|
}
|
|
32
|
-
return
|
|
61
|
+
return;
|
|
33
62
|
}
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
// Figure out resolved require path and dependency output path
|
|
40
|
-
const resolvedRequire = (0, transpiler_1.getEmitPathRelativeToOutDir)(resolvedDependency, this.program);
|
|
41
|
-
if (shouldRewriteRequires(resolvedDependency, this.program)) {
|
|
42
|
-
replaceRequireInCode(file, required, resolvedRequire);
|
|
43
|
-
replaceRequireInSourceMap(file, required, resolvedRequire);
|
|
44
|
-
}
|
|
45
|
-
// Check cache to prevent resolving nested dependencies double to break dependency loops
|
|
46
|
-
if (this.resultsCache.has(resolvedDependency)) {
|
|
47
|
-
if (this.options.tstlVerbose) {
|
|
48
|
-
console.log(`Resolution cache hit for ${(0, utils_1.normalizeSlashes)(resolvedDependency)}`);
|
|
49
|
-
}
|
|
50
|
-
return this.resultsCache.get(resolvedDependency);
|
|
51
|
-
}
|
|
52
|
-
// If dependency is not part of project, add dependency to output and resolve its dependencies recursively
|
|
53
|
-
if (shouldIncludeDependency(resolvedDependency, this.program)) {
|
|
54
|
-
// If dependency resolved successfully, read its content
|
|
55
|
-
const dependencyContent = this.emitHost.readFile(resolvedDependency);
|
|
56
|
-
if (dependencyContent === undefined) {
|
|
57
|
-
return { resolvedFiles: [], diagnostics: [(0, diagnostics_1.couldNotReadDependency)(resolvedDependency)] };
|
|
58
|
-
}
|
|
59
|
-
const dependency = {
|
|
60
|
-
fileName: resolvedDependency,
|
|
61
|
-
code: dependencyContent,
|
|
62
|
-
};
|
|
63
|
-
const nestedDependencies = resolveFileDependencies(dependency, this);
|
|
64
|
-
// Cache result and return
|
|
65
|
-
const result = {
|
|
66
|
-
resolvedFiles: [dependency, ...nestedDependencies.resolvedFiles],
|
|
67
|
-
diagnostics: [...nestedDependencies.diagnostics],
|
|
68
|
-
};
|
|
69
|
-
this.resultsCache.set(resolvedDependency, result);
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
const result = {
|
|
74
|
-
resolvedFiles: [],
|
|
75
|
-
diagnostics: [],
|
|
76
|
-
};
|
|
77
|
-
this.resultsCache.set(resolvedDependency, result);
|
|
78
|
-
return result;
|
|
79
|
-
}
|
|
63
|
+
const dependencyPath = this.resolveDependencyPath(file, required);
|
|
64
|
+
if (!dependencyPath)
|
|
65
|
+
return this.couldNotResolveImport(required, file);
|
|
66
|
+
if (this.options.tstlVerbose) {
|
|
67
|
+
console.log(`Resolved ${required} to ${(0, utils_1.normalizeSlashes)(dependencyPath)}`);
|
|
80
68
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
diagnostics: [
|
|
88
|
-
(0, diagnostics_1.couldNotResolveRequire)(required, path.relative((0, transpiler_1.getProjectRoot)(this.program), file.fileName)),
|
|
89
|
-
],
|
|
90
|
-
};
|
|
69
|
+
this.processDependency(dependencyPath);
|
|
70
|
+
// Figure out resolved require path and dependency output path
|
|
71
|
+
if (shouldRewriteRequires(dependencyPath, this.program)) {
|
|
72
|
+
const resolvedRequire = (0, transpiler_1.getEmitPathRelativeToOutDir)(dependencyPath, this.program);
|
|
73
|
+
replaceRequireInCode(file, required, resolvedRequire);
|
|
74
|
+
replaceRequireInSourceMap(file, required, resolvedRequire);
|
|
91
75
|
}
|
|
92
76
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
77
|
+
processDependency(dependencyPath) {
|
|
78
|
+
if (this.processedDependencies.has(dependencyPath))
|
|
79
|
+
return;
|
|
80
|
+
this.processedDependencies.add(dependencyPath);
|
|
81
|
+
if (!shouldIncludeDependency(dependencyPath, this.program))
|
|
82
|
+
return;
|
|
83
|
+
// If dependency is not part of project, add dependency to output and resolve its dependencies recursively
|
|
84
|
+
const dependencyContent = this.emitHost.readFile(dependencyPath);
|
|
85
|
+
if (dependencyContent === undefined) {
|
|
86
|
+
this.diagnostics.push((0, diagnostics_1.couldNotReadDependency)(dependencyPath));
|
|
87
|
+
return;
|
|
103
88
|
}
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
89
|
+
const dependency = {
|
|
90
|
+
fileName: dependencyPath,
|
|
91
|
+
code: dependencyContent,
|
|
92
|
+
};
|
|
93
|
+
this.addAndResolveDependencies(dependency);
|
|
107
94
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (required === "lualib_bundle") {
|
|
120
|
-
dependencies.push({ fileName: "lualib_bundle", code: "" });
|
|
121
|
-
continue;
|
|
95
|
+
couldNotResolveImport(required, file) {
|
|
96
|
+
const fallbackRequire = fallbackResolve(required, (0, transpiler_1.getSourceDir)(this.program), path.dirname(file.fileName));
|
|
97
|
+
replaceRequireInCode(file, required, fallbackRequire);
|
|
98
|
+
replaceRequireInSourceMap(file, required, fallbackRequire);
|
|
99
|
+
this.diagnostics.push((0, diagnostics_1.couldNotResolveRequire)(required, path.relative((0, transpiler_1.getProjectRoot)(this.program), file.fileName)));
|
|
100
|
+
}
|
|
101
|
+
resolveDependencyPath(requiringFile, dependency) {
|
|
102
|
+
var _a;
|
|
103
|
+
const fileDirectory = path.dirname(requiringFile.fileName);
|
|
104
|
+
if (this.options.tstlVerbose) {
|
|
105
|
+
console.log(`Resolving "${dependency}" from ${(0, utils_1.normalizeSlashes)(requiringFile.fileName)}`);
|
|
122
106
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
// Skip
|
|
132
|
-
continue;
|
|
107
|
+
const requiredFromLuaFile = requiringFile.fileName.endsWith(".lua");
|
|
108
|
+
const dependencyPath = requiredFromLuaFile ? luaRequireToPath(dependency) : dependency;
|
|
109
|
+
if (requiredFromLuaFile && isNodeModulesFile(requiringFile.fileName)) {
|
|
110
|
+
// If requiring file is in lua module, try to resolve sibling in that file first
|
|
111
|
+
const resolvedNodeModulesFile = this.resolveLuaDependencyPathFromNodeModules(requiringFile, dependencyPath);
|
|
112
|
+
if (resolvedNodeModulesFile)
|
|
113
|
+
return resolvedNodeModulesFile;
|
|
133
114
|
}
|
|
134
|
-
//
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const isRelative = ["/", "./", "../"].some(p => dependency.startsWith(p));
|
|
150
|
-
// If the import is relative, always resolve it relative to the requiring file
|
|
151
|
-
// If the import is not relative, resolve it relative to options.baseUrl if it is set
|
|
152
|
-
const relativeTo = isRelative ? fileDirectory : (_a = options.baseUrl) !== null && _a !== void 0 ? _a : fileDirectory;
|
|
153
|
-
// Check if file is a file in the project
|
|
154
|
-
const resolvedPath = path.join(relativeTo, dependency);
|
|
155
|
-
const possibleProjectFiles = [
|
|
156
|
-
resolvedPath,
|
|
157
|
-
resolvedPath + ".ts",
|
|
158
|
-
path.join(resolvedPath, "index.ts"),
|
|
159
|
-
resolvedPath + ".tsx",
|
|
160
|
-
path.join(resolvedPath, "index.tsx"), // tsx index
|
|
161
|
-
];
|
|
162
|
-
for (const possibleFile of possibleProjectFiles) {
|
|
163
|
-
if (isProjectFile(possibleFile, program)) {
|
|
164
|
-
return possibleFile;
|
|
115
|
+
// Check if the import is relative
|
|
116
|
+
const isRelative = ["/", "./", "../"].some(p => dependency.startsWith(p));
|
|
117
|
+
// If the import is relative, always resolve it relative to the requiring file
|
|
118
|
+
// If the import is not relative, resolve it relative to options.baseUrl if it is set
|
|
119
|
+
const relativeTo = isRelative ? fileDirectory : (_a = this.options.baseUrl) !== null && _a !== void 0 ? _a : fileDirectory;
|
|
120
|
+
// Check if file is a file in the project
|
|
121
|
+
const resolvedPath = path.join(relativeTo, dependencyPath);
|
|
122
|
+
const fileFromPath = this.getFileFromPath(resolvedPath);
|
|
123
|
+
if (fileFromPath)
|
|
124
|
+
return fileFromPath;
|
|
125
|
+
if (this.options.paths && this.options.baseUrl) {
|
|
126
|
+
// If no file found yet and paths are present, try to find project file via paths mappings
|
|
127
|
+
const fileFromPaths = this.tryGetModuleNameFromPaths(dependencyPath, this.options.paths, this.options.baseUrl);
|
|
128
|
+
if (fileFromPaths)
|
|
129
|
+
return fileFromPaths;
|
|
165
130
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
path.join(resolvedPath, "init.lua"), // lua looks for <require>/init.lua if it cannot find <require>.lua
|
|
172
|
-
];
|
|
173
|
-
for (const possibleFile of possibleLuaProjectFiles) {
|
|
174
|
-
if (emitHost.fileExists(possibleFile)) {
|
|
175
|
-
return possibleFile;
|
|
131
|
+
// Not a TS file in our project sources, use resolver to check if we can find dependency
|
|
132
|
+
try {
|
|
133
|
+
const resolveResult = resolver.resolveSync({}, fileDirectory, dependencyPath);
|
|
134
|
+
if (resolveResult)
|
|
135
|
+
return resolveResult;
|
|
176
136
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (requiringFile.fileName.endsWith(".lua")) {
|
|
180
|
-
const luaFilePath = resolveLuaPath(fileDirectory, dependency, emitHost);
|
|
181
|
-
if (luaFilePath) {
|
|
182
|
-
return luaFilePath;
|
|
137
|
+
catch (e) {
|
|
138
|
+
// resolveSync errors if it fails to resolve
|
|
183
139
|
}
|
|
140
|
+
return undefined;
|
|
184
141
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
142
|
+
resolveLuaDependencyPathFromNodeModules(requiringFile, dependency) {
|
|
143
|
+
// We don't know for sure where the lua root is, so guess it is at package root
|
|
144
|
+
const splitPath = path.normalize(requiringFile.fileName).split(path.sep);
|
|
145
|
+
let packageRootIndex = splitPath.lastIndexOf("node_modules") + 2;
|
|
146
|
+
let packageRoot = splitPath.slice(0, packageRootIndex).join(path.sep);
|
|
147
|
+
while (packageRootIndex < splitPath.length) {
|
|
148
|
+
// Try to find lua file relative to currently guessed Lua root
|
|
149
|
+
const resolvedPath = path.join(packageRoot, dependency);
|
|
150
|
+
const fileFromPath = this.getFileFromPath(resolvedPath);
|
|
151
|
+
if (fileFromPath) {
|
|
152
|
+
return fileFromPath;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// Did not find file at current root, try again one directory deeper
|
|
156
|
+
packageRoot = path.join(packageRoot, splitPath[packageRootIndex++]);
|
|
157
|
+
}
|
|
190
158
|
}
|
|
159
|
+
return undefined;
|
|
191
160
|
}
|
|
192
|
-
|
|
193
|
-
|
|
161
|
+
getFileFromPath(resolvedPath) {
|
|
162
|
+
const existingFile = this.pathToFile.get(resolvedPath);
|
|
163
|
+
if (existingFile)
|
|
164
|
+
return existingFile;
|
|
165
|
+
if (existingFile === false)
|
|
166
|
+
return undefined;
|
|
167
|
+
const file = this.searchForFileFromPath(resolvedPath);
|
|
168
|
+
this.pathToFile.set(resolvedPath, file !== null && file !== void 0 ? file : false);
|
|
169
|
+
return file;
|
|
194
170
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
171
|
+
searchForFileFromPath(resolvedPath) {
|
|
172
|
+
const possibleProjectFiles = [
|
|
173
|
+
resolvedPath,
|
|
174
|
+
resolvedPath + ".ts",
|
|
175
|
+
path.join(resolvedPath, "index.ts"),
|
|
176
|
+
resolvedPath + ".tsx",
|
|
177
|
+
path.join(resolvedPath, "index.tsx"), // tsx index
|
|
178
|
+
];
|
|
179
|
+
for (const possibleFile of possibleProjectFiles) {
|
|
180
|
+
if (isProjectFile(possibleFile, this.program)) {
|
|
181
|
+
return possibleFile;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Check if this is a lua file in the project sources
|
|
185
|
+
const possibleLuaProjectFiles = [
|
|
186
|
+
resolvedPath + ".lua",
|
|
187
|
+
path.join(resolvedPath, "index.lua"),
|
|
188
|
+
path.join(resolvedPath, "init.lua"), // lua looks for <require>/init.lua if it cannot find <require>.lua
|
|
189
|
+
];
|
|
190
|
+
for (const possibleFile of possibleLuaProjectFiles) {
|
|
191
|
+
if (this.emitHost.fileExists(possibleFile)) {
|
|
192
|
+
return possibleFile;
|
|
193
|
+
}
|
|
204
194
|
}
|
|
205
195
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
196
|
+
// Taken from TS and modified: https://github.com/microsoft/TypeScript/blob/88a1e3a1dd8d2d86e844ff1c16d5f041cebcfdb9/src/compiler/moduleSpecifiers.ts#L562
|
|
197
|
+
tryGetModuleNameFromPaths(relativeToBaseUrl, paths, baseUrl) {
|
|
198
|
+
const relativeImport = removeTrailingDirectorySeparator((0, utils_1.normalizeSlashes)(relativeToBaseUrl));
|
|
199
|
+
for (const [importPattern, targetPatterns] of Object.entries(paths)) {
|
|
200
|
+
const pattern = removeFileExtension((0, utils_1.normalizeSlashes)(importPattern));
|
|
201
|
+
const indexOfStar = pattern.indexOf("*");
|
|
202
|
+
if (indexOfStar !== -1) {
|
|
203
|
+
// Try to match <prefix>*<suffix> to relativeImport
|
|
204
|
+
const prefix = pattern.substring(0, indexOfStar);
|
|
205
|
+
const suffix = pattern.substring(indexOfStar + 1);
|
|
206
|
+
if ((relativeImport.length >= prefix.length + suffix.length &&
|
|
207
|
+
relativeImport.startsWith(prefix) &&
|
|
208
|
+
relativeImport.endsWith(suffix)) ||
|
|
209
|
+
(!suffix && relativeImport === removeTrailingDirectorySeparator(prefix))) {
|
|
210
|
+
// If import matches <prefix>*<suffix>, extract the matched * path
|
|
211
|
+
const matchedStar = relativeImport.substring(prefix.length, relativeImport.length - suffix.length);
|
|
212
|
+
// Try to resolve to the target patterns with filled in * pattern
|
|
213
|
+
for (const target of targetPatterns) {
|
|
214
|
+
const file = this.getFileFromPath(path.join(baseUrl, target.replace("*", matchedStar)));
|
|
215
|
+
if (file)
|
|
216
|
+
return file;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else if (pattern === relativeImport) {
|
|
221
|
+
// If there is no * pattern, check for exact matches and try those targets
|
|
222
|
+
for (const target of targetPatterns) {
|
|
223
|
+
const file = this.getFileFromPath(path.join(baseUrl, target));
|
|
224
|
+
if (file)
|
|
225
|
+
return file;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
211
228
|
}
|
|
212
229
|
}
|
|
213
230
|
}
|
|
214
|
-
function
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
231
|
+
function resolveDependencies(program, files, emitHost) {
|
|
232
|
+
const options = program.getCompilerOptions();
|
|
233
|
+
const resolutionContext = new ResolutionContext(program, options, emitHost);
|
|
234
|
+
// Resolve dependencies for all processed files
|
|
235
|
+
for (const file of files) {
|
|
236
|
+
if (options.tstlVerbose) {
|
|
237
|
+
console.log(`Resolving dependencies for ${(0, utils_1.normalizeSlashes)(file.fileName)}`);
|
|
220
238
|
}
|
|
221
|
-
|
|
239
|
+
resolutionContext.addAndResolveDependencies(file);
|
|
222
240
|
}
|
|
223
|
-
return
|
|
241
|
+
return { resolvedFiles: [...resolutionContext.resolvedFiles.values()], diagnostics: resolutionContext.diagnostics };
|
|
224
242
|
}
|
|
243
|
+
exports.resolveDependencies = resolveDependencies;
|
|
225
244
|
function shouldRewriteRequires(resolvedDependency, program) {
|
|
226
|
-
return !
|
|
245
|
+
return !isBuildModeLibrary(program) || !isNodeModulesFile(resolvedDependency);
|
|
227
246
|
}
|
|
228
247
|
function shouldIncludeDependency(resolvedDependency, program) {
|
|
229
248
|
// Never include lua files (again) that are transpiled from project sources
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return !isBuildModeLibrary(program);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return false;
|
|
249
|
+
if (hasSourceFileInProject(resolvedDependency, program))
|
|
250
|
+
return false;
|
|
251
|
+
// Always include lua files not in node_modules (internal lua sources)
|
|
252
|
+
if (!isNodeModulesFile(resolvedDependency))
|
|
253
|
+
return true;
|
|
254
|
+
// Only include node_modules files if not in library mode
|
|
255
|
+
return !isBuildModeLibrary(program);
|
|
241
256
|
}
|
|
242
257
|
function isBuildModeLibrary(program) {
|
|
243
258
|
return program.getCompilerOptions().buildMode === CompilerOptions_1.BuildMode.Library;
|
|
@@ -245,7 +260,7 @@ function isBuildModeLibrary(program) {
|
|
|
245
260
|
function findRequiredPaths(code) {
|
|
246
261
|
// Find all require("<path>") paths in a lua code string
|
|
247
262
|
const paths = [];
|
|
248
|
-
const pattern = /(^|\s
|
|
263
|
+
const pattern = /(^|\s|;|=|\()require\("(.+?)"\)/g;
|
|
249
264
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
250
265
|
let match;
|
|
251
266
|
while ((match = pattern.exec(code))) {
|
|
@@ -257,7 +272,7 @@ function replaceRequireInCode(file, originalRequire, newRequire) {
|
|
|
257
272
|
const requirePath = (0, utils_1.formatPathToLuaPath)(newRequire.replace(".lua", ""));
|
|
258
273
|
// Escape special characters to prevent the regex from breaking...
|
|
259
274
|
const escapedRequire = originalRequire.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
260
|
-
file.code = file.code.replace(new RegExp(`(^|\\s
|
|
275
|
+
file.code = file.code.replace(new RegExp(`(^|\\s|;|=|\\()require\\("${escapedRequire}"\\)`), `$1require("${requirePath}")`);
|
|
261
276
|
}
|
|
262
277
|
function replaceRequireInSourceMap(file, originalRequire, newRequire) {
|
|
263
278
|
const requirePath = (0, utils_1.formatPathToLuaPath)(newRequire.replace(".lua", ""));
|
|
@@ -302,4 +317,13 @@ function fallbackResolve(required, sourceRootDir, fileDir) {
|
|
|
302
317
|
.filter(s => s !== "." && s !== "..")
|
|
303
318
|
.join(path.sep));
|
|
304
319
|
}
|
|
320
|
+
function luaRequireToPath(requirePath) {
|
|
321
|
+
return requirePath.replace(/\./g, path.sep);
|
|
322
|
+
}
|
|
323
|
+
function removeFileExtension(path) {
|
|
324
|
+
return path.includes(".") ? (0, utils_1.trimExtension)(path) : path;
|
|
325
|
+
}
|
|
326
|
+
function removeTrailingDirectorySeparator(path) {
|
|
327
|
+
return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, -1) : path;
|
|
328
|
+
}
|
|
305
329
|
//# sourceMappingURL=resolve.js.map
|