typescript-to-lua 1.11.0 → 1.12.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.
package/dist/LuaLib.d.ts CHANGED
@@ -50,7 +50,6 @@ export declare enum LuaLibFeature {
50
50
  MathAtan2 = "MathAtan2",
51
51
  MathModf = "MathModf",
52
52
  MathSign = "MathSign",
53
- Modulo50 = "Modulo50",
54
53
  New = "New",
55
54
  Number = "Number",
56
55
  NumberIsFinite = "NumberIsFinite",
package/dist/LuaLib.js CHANGED
@@ -54,7 +54,6 @@ var LuaLibFeature;
54
54
  LuaLibFeature["MathAtan2"] = "MathAtan2";
55
55
  LuaLibFeature["MathModf"] = "MathModf";
56
56
  LuaLibFeature["MathSign"] = "MathSign";
57
- LuaLibFeature["Modulo50"] = "Modulo50";
58
57
  LuaLibFeature["New"] = "New";
59
58
  LuaLibFeature["Number"] = "Number";
60
59
  LuaLibFeature["NumberIsFinite"] = "NumberIsFinite";
@@ -20,7 +20,7 @@ do
20
20
  do
21
21
  result = __TS__StringAccess(
22
22
  radixChars,
23
- __TS__Modulo50(integer, radix)
23
+ math.mod(integer, radix)
24
24
  ) .. result
25
25
  integer = math.floor(integer / radix)
26
26
  end
@@ -1445,10 +1445,6 @@ local function __TS__MathSign(val)
1445
1445
  return 0
1446
1446
  end
1447
1447
 
1448
- local function __TS__Modulo50(a, b)
1449
- return a - math.floor(a / b) * b
1450
- end
1451
-
1452
1448
  local function __TS__Number(value)
1453
1449
  local valueType = type(value)
1454
1450
  if valueType == "number" then
@@ -1506,7 +1502,7 @@ do
1506
1502
  do
1507
1503
  result = __TS__StringAccess(
1508
1504
  radixChars,
1509
- __TS__Modulo50(integer, radix)
1505
+ math.mod(integer, radix)
1510
1506
  ) .. result
1511
1507
  integer = math.floor(integer / radix)
1512
1508
  end
@@ -2533,7 +2529,6 @@ return {
2533
2529
  __TS__MathAtan2 = __TS__MathAtan2,
2534
2530
  __TS__MathModf = __TS__MathModf,
2535
2531
  __TS__MathSign = __TS__MathSign,
2536
- __TS__Modulo50 = __TS__Modulo50,
2537
2532
  __TS__New = __TS__New,
2538
2533
  __TS__Number = __TS__Number,
2539
2534
  __TS__NumberIsFinite = __TS__NumberIsFinite,
@@ -319,11 +319,6 @@
319
319
  "__TS__MathSign"
320
320
  ]
321
321
  },
322
- "Modulo50": {
323
- "exports": [
324
- "__TS__Modulo50"
325
- ]
326
- },
327
322
  "New": {
328
323
  "exports": [
329
324
  "__TS__New"
@@ -349,7 +344,6 @@
349
344
  "__TS__NumberToString"
350
345
  ],
351
346
  "dependencies": [
352
- "Modulo50",
353
347
  "StringAccess",
354
348
  "MathModf"
355
349
  ]
@@ -1384,10 +1384,6 @@ local function __TS__MathSign(val)
1384
1384
  return 0
1385
1385
  end
1386
1386
 
1387
- local function __TS__Modulo50(a, b)
1388
- return a - math.floor(a / b) * b
1389
- end
1390
-
1391
1387
  local function __TS__Number(value)
1392
1388
  local valueType = type(value)
1393
1389
  if valueType == "number" then
@@ -2476,7 +2472,6 @@ return {
2476
2472
  __TS__MathAtan2 = __TS__MathAtan2,
2477
2473
  __TS__MathModf = __TS__MathModf,
2478
2474
  __TS__MathSign = __TS__MathSign,
2479
- __TS__Modulo50 = __TS__Modulo50,
2480
2475
  __TS__New = __TS__New,
2481
2476
  __TS__Number = __TS__Number,
2482
2477
  __TS__NumberIsFinite = __TS__NumberIsFinite,
@@ -319,11 +319,6 @@
319
319
  "__TS__MathSign"
320
320
  ]
321
321
  },
322
- "Modulo50": {
323
- "exports": [
324
- "__TS__Modulo50"
325
- ]
326
- },
327
322
  "New": {
328
323
  "exports": [
329
324
  "__TS__New"
@@ -44,7 +44,8 @@ function transformBinaryOperationWithNoPrecedingStatements(context, left, right,
44
44
  return transformNullishCoalescingOperationNoPrecedingStatements(context, node, left, right);
45
45
  }
46
46
  if (operator === ts.SyntaxKind.PercentToken && context.luaTarget === CompilerOptions_1.LuaTarget.Lua50) {
47
- return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Modulo50, node, left, right);
47
+ const mathMod = lua.createTableIndexExpression(lua.createIdentifier("math"), lua.createStringLiteral("mod"));
48
+ return lua.createCallExpression(mathMod, [left, right], node);
48
49
  }
49
50
  let luaOperator = simpleOperatorsToLua[operator];
50
51
  // Check if we need to use string concat operator
@@ -0,0 +1,6 @@
1
+ export interface LuaRequire {
2
+ from: number;
3
+ to: number;
4
+ requirePath: string;
5
+ }
6
+ export declare function findLuaRequires(lua: string): LuaRequire[];
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findLuaRequires = void 0;
4
+ function findLuaRequires(lua) {
5
+ return findRequire(lua, 0);
6
+ }
7
+ exports.findLuaRequires = findLuaRequires;
8
+ function findRequire(lua, offset) {
9
+ const result = [];
10
+ while (offset < lua.length) {
11
+ const c = lua[offset];
12
+ if (c === "r" &&
13
+ (offset === 0 ||
14
+ isWhitespace(lua[offset - 1]) ||
15
+ lua[offset - 1] === "]" ||
16
+ lua[offset - 1] === "(" ||
17
+ lua[offset - 1] === "[")) {
18
+ const m = matchRequire(lua, offset);
19
+ if (m.matched) {
20
+ offset = m.match.to + 1;
21
+ result.push(m.match);
22
+ }
23
+ else {
24
+ offset = m.end;
25
+ }
26
+ }
27
+ else if (c === '"' || c === "'") {
28
+ offset = readString(lua, offset, c).offset; // Skip string and surrounding quotes
29
+ }
30
+ else if (c === "-" && offset + 1 < lua.length && lua[offset + 1] === "-") {
31
+ offset = skipComment(lua, offset);
32
+ }
33
+ else {
34
+ offset++;
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ function matchRequire(lua, offset) {
40
+ const start = offset;
41
+ for (const c of "require") {
42
+ if (offset > lua.length) {
43
+ return { matched: false, end: offset };
44
+ }
45
+ if (lua[offset] !== c) {
46
+ return { matched: false, end: offset };
47
+ }
48
+ offset++;
49
+ }
50
+ offset = skipWhitespace(lua, offset);
51
+ let hasParentheses = false;
52
+ if (offset > lua.length) {
53
+ return { matched: false, end: offset };
54
+ }
55
+ else {
56
+ if (lua[offset] === "(") {
57
+ hasParentheses = true;
58
+ offset++;
59
+ offset = skipWhitespace(lua, offset);
60
+ }
61
+ else if (lua[offset] === '"' || lua[offset] === "'") {
62
+ // require without parentheses
63
+ }
64
+ else {
65
+ // otherwise fail match
66
+ return { matched: false, end: offset };
67
+ }
68
+ }
69
+ if (offset > lua.length || (lua[offset] !== '"' && lua[offset] !== "'")) {
70
+ return { matched: false, end: offset };
71
+ }
72
+ const { value: requireString, offset: offsetAfterString } = readString(lua, offset, lua[offset]);
73
+ offset = offsetAfterString; // Skip string and surrounding quotes
74
+ if (hasParentheses) {
75
+ offset = skipWhitespace(lua, offset);
76
+ if (offset > lua.length || lua[offset] !== ")") {
77
+ return { matched: false, end: offset };
78
+ }
79
+ offset++;
80
+ }
81
+ return { matched: true, match: { from: start, to: offset - 1, requirePath: requireString } };
82
+ }
83
+ function readString(lua, offset, delimiter) {
84
+ expect(lua, offset, delimiter);
85
+ offset++;
86
+ let start = offset;
87
+ let result = "";
88
+ let escaped = false;
89
+ while (offset < lua.length && (lua[offset] !== delimiter || escaped)) {
90
+ if (lua[offset] === "\\" && !escaped) {
91
+ escaped = true;
92
+ }
93
+ else {
94
+ if (lua[offset] === delimiter) {
95
+ result += lua.slice(start, offset - 1);
96
+ start = offset;
97
+ }
98
+ escaped = false;
99
+ }
100
+ offset++;
101
+ }
102
+ if (offset < lua.length) {
103
+ expect(lua, offset, delimiter);
104
+ }
105
+ result += lua.slice(start, offset);
106
+ return { value: result, offset: offset + 1 };
107
+ }
108
+ function skipWhitespace(lua, offset) {
109
+ while (offset < lua.length && isWhitespace(lua[offset])) {
110
+ offset++;
111
+ }
112
+ return offset;
113
+ }
114
+ function isWhitespace(c) {
115
+ return c === " " || c === "\t" || c === "\r" || c === "\n";
116
+ }
117
+ function skipComment(lua, offset) {
118
+ expect(lua, offset, "-");
119
+ expect(lua, offset + 1, "-");
120
+ offset += 2;
121
+ if (offset + 1 < lua.length && lua[offset] === "[" && lua[offset + 1] === "[") {
122
+ return skipMultiLineComment(lua, offset);
123
+ }
124
+ else {
125
+ return skipSingleLineComment(lua, offset);
126
+ }
127
+ }
128
+ function skipMultiLineComment(lua, offset) {
129
+ while (offset < lua.length && !(lua[offset] === "]" && lua[offset - 1] === "]")) {
130
+ offset++;
131
+ }
132
+ return offset + 1;
133
+ }
134
+ function skipSingleLineComment(lua, offset) {
135
+ while (offset < lua.length && lua[offset] !== "\n") {
136
+ offset++;
137
+ }
138
+ return offset + 1;
139
+ }
140
+ function expect(lua, offset, char) {
141
+ if (lua[offset] !== char) {
142
+ throw new Error(`Expected ${char} at position ${offset} but found ${lua[offset]}`);
143
+ }
144
+ }
145
+ //# sourceMappingURL=find-lua-requires.js.map
@@ -9,6 +9,7 @@ const transpiler_1 = require("./transpiler");
9
9
  const utils_1 = require("../utils");
10
10
  const diagnostics_1 = require("./diagnostics");
11
11
  const CompilerOptions_1 = require("../CompilerOptions");
12
+ const find_lua_requires_1 = require("./find-lua-requires");
12
13
  const resolver = resolve.ResolverFactory.createResolver({
13
14
  extensions: [".lua"],
14
15
  enforceExtension: true,
@@ -32,12 +33,13 @@ class ResolutionContext {
32
33
  if (this.resolvedFiles.has(file.fileName))
33
34
  return;
34
35
  this.resolvedFiles.set(file.fileName, file);
35
- for (const required of findRequiredPaths(file.code)) {
36
+ // Do this backwards so the replacements do not mess with the positions of the previous requires
37
+ for (const required of (0, find_lua_requires_1.findLuaRequires)(file.code).reverse()) {
36
38
  // Do not resolve noResolution paths
37
- if (required.startsWith("@NoResolution:")) {
39
+ if (required.requirePath.startsWith("@NoResolution:")) {
38
40
  // Remove @NoResolution prefix if not building in library mode
39
41
  if (!isBuildModeLibrary(this.program)) {
40
- const path = required.replace("@NoResolution:", "");
42
+ const path = required.requirePath.replace("@NoResolution:", "");
41
43
  replaceRequireInCode(file, required, path);
42
44
  replaceRequireInSourceMap(file, required, path);
43
45
  }
@@ -50,21 +52,21 @@ class ResolutionContext {
50
52
  }
51
53
  resolveImport(file, required) {
52
54
  // Do no resolve lualib - always use the lualib of the application entry point, not the lualib from external packages
53
- if (required === "lualib_bundle") {
55
+ if (required.requirePath === "lualib_bundle") {
54
56
  this.resolvedFiles.set("lualib_bundle", { fileName: "lualib_bundle", code: "" });
55
57
  return;
56
58
  }
57
- if (this.noResolvePaths.has(required)) {
59
+ if (this.noResolvePaths.has(required.requirePath)) {
58
60
  if (this.options.tstlVerbose) {
59
- console.log(`Skipping module resolution of ${required} as it is in the tsconfig noResolvePaths.`);
61
+ console.log(`Skipping module resolution of ${required.requirePath} as it is in the tsconfig noResolvePaths.`);
60
62
  }
61
63
  return;
62
64
  }
63
- const dependencyPath = this.resolveDependencyPath(file, required);
65
+ const dependencyPath = this.resolveDependencyPath(file, required.requirePath);
64
66
  if (!dependencyPath)
65
67
  return this.couldNotResolveImport(required, file);
66
68
  if (this.options.tstlVerbose) {
67
- console.log(`Resolved ${required} to ${(0, utils_1.normalizeSlashes)(dependencyPath)}`);
69
+ console.log(`Resolved ${required.requirePath} to ${(0, utils_1.normalizeSlashes)(dependencyPath)}`);
68
70
  }
69
71
  this.processDependency(dependencyPath);
70
72
  // Figure out resolved require path and dependency output path
@@ -96,7 +98,7 @@ class ResolutionContext {
96
98
  const fallbackRequire = fallbackResolve(required, (0, transpiler_1.getSourceDir)(this.program), path.dirname(file.fileName));
97
99
  replaceRequireInCode(file, required, fallbackRequire);
98
100
  replaceRequireInSourceMap(file, required, fallbackRequire);
99
- this.diagnostics.push((0, diagnostics_1.couldNotResolveRequire)(required, path.relative((0, transpiler_1.getProjectRoot)(this.program), file.fileName)));
101
+ this.diagnostics.push((0, diagnostics_1.couldNotResolveRequire)(required.requirePath, path.relative((0, transpiler_1.getProjectRoot)(this.program), file.fileName)));
100
102
  }
101
103
  resolveDependencyPath(requiringFile, dependency) {
102
104
  var _a;
@@ -261,27 +263,17 @@ function shouldIncludeDependency(resolvedDependency, program) {
261
263
  function isBuildModeLibrary(program) {
262
264
  return program.getCompilerOptions().buildMode === CompilerOptions_1.BuildMode.Library;
263
265
  }
264
- function findRequiredPaths(code) {
265
- // Find all require("<path>") paths in a lua code string
266
- const paths = [];
267
- const pattern = /(^|\s|;|=|\()require\s*\(?(["|'])(.+?)\2\)?/g;
268
- // eslint-disable-next-line @typescript-eslint/ban-types
269
- let match;
270
- while ((match = pattern.exec(code))) {
271
- paths.push(match[3]);
272
- }
273
- return paths;
274
- }
275
266
  function replaceRequireInCode(file, originalRequire, newRequire) {
276
267
  const requirePath = (0, utils_1.formatPathToLuaPath)(newRequire.replace(".lua", ""));
277
- // Escape special characters to prevent the regex from breaking...
278
- const escapedRequire = originalRequire.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
279
- file.code = file.code.replace(new RegExp(`(^|\\s|;|=|\\()require\\s*\\(?["|']${escapedRequire}["|']\\)?`), `$1require("${requirePath}")`);
268
+ file.code = file.code =
269
+ file.code.substring(0, originalRequire.from) +
270
+ `require("${requirePath}")` +
271
+ file.code.substring(originalRequire.to + 1);
280
272
  }
281
273
  function replaceRequireInSourceMap(file, originalRequire, newRequire) {
282
274
  const requirePath = (0, utils_1.formatPathToLuaPath)(newRequire.replace(".lua", ""));
283
275
  if (file.sourceMapNode) {
284
- replaceInSourceMap(file.sourceMapNode, file.sourceMapNode, `"${originalRequire}"`, `"${requirePath}"`);
276
+ replaceInSourceMap(file.sourceMapNode, file.sourceMapNode, `"${originalRequire.requirePath}"`, `"${requirePath}"`);
285
277
  }
286
278
  }
287
279
  function replaceInSourceMap(node, parent, require, resolvedRequire) {
@@ -316,7 +308,7 @@ function hasSourceFileInProject(filePath, program) {
316
308
  // Transform an import path to a lua require that is probably not correct, but can be used as fallback when regular resolution fails
317
309
  function fallbackResolve(required, sourceRootDir, fileDir) {
318
310
  return (0, utils_1.formatPathToLuaPath)(path
319
- .normalize(path.join(path.relative(sourceRootDir, fileDir), required))
311
+ .normalize(path.join(path.relative(sourceRootDir, fileDir), required.requirePath))
320
312
  .split(path.sep)
321
313
  .filter(s => s !== "." && s !== "..")
322
314
  .join(path.sep));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typescript-to-lua",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!",
5
5
  "repository": "https://github.com/TypeScriptToLua/TypeScriptToLua",
6
6
  "homepage": "https://typescripttolua.github.io/",
@@ -1,3 +0,0 @@
1
- local function __TS__Modulo50(a, b)
2
- return a - math.floor(a / b) * b
3
- end
@@ -1,3 +0,0 @@
1
- local function __TS__Modulo50(a, b)
2
- return a - math.floor(a / b) * b
3
- end