@tilua/compiler 1.1.0 → 2.1.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/README.md +17 -5
- package/dist/{chunk-2IPPO4V3.js → chunk-TBSJRVKA.js} +205 -60
- package/dist/cli.cjs +204 -59
- package/dist/cli.js +1 -1
- package/dist/index.cjs +204 -59
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -192,14 +192,18 @@ var Lowerer = class {
|
|
|
192
192
|
const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
|
|
193
193
|
const helpers = this.helperDefinitions();
|
|
194
194
|
const captured = [...this.builtins].map(([global, local2]) => local([local2], [identifier(global)]));
|
|
195
|
+
const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [table([{ type: "TableFieldPositional", value: vararg() }])])] : [];
|
|
195
196
|
return {
|
|
196
|
-
statements: [...captured, ...helpers, ...this.classRuntimeStatements(), ...body],
|
|
197
|
+
statements: [...scriptArgs, ...captured, ...helpers, ...this.classRuntimeStatements(), ...body],
|
|
197
198
|
exportsName: this.exportsName,
|
|
198
199
|
module: this.info,
|
|
199
200
|
diagnostics: this.diagnostics,
|
|
200
|
-
origins: this.origins
|
|
201
|
+
origins: this.origins,
|
|
202
|
+
usesScriptArgs: this.usesScriptArgs
|
|
201
203
|
};
|
|
202
204
|
}
|
|
205
|
+
/** Whether the file reads `scriptArgs`, the language's own global. */
|
|
206
|
+
usesScriptArgs = false;
|
|
203
207
|
report(node, message) {
|
|
204
208
|
this.diagnostics.push({ message, line: node.line.start, column: node.column.start });
|
|
205
209
|
}
|
|
@@ -324,6 +328,10 @@ var Lowerer = class {
|
|
|
324
328
|
/** The name a global is read by at `node`, or `undefined` when `node` is
|
|
325
329
|
* not a global — a local of the same name is the author's. */
|
|
326
330
|
globalName(node) {
|
|
331
|
+
if (node.type === "MemberExpression" && !node.optional) {
|
|
332
|
+
const base = this.globalName(node.object);
|
|
333
|
+
return base === void 0 ? void 0 : `${base}.${node.property.name}`;
|
|
334
|
+
}
|
|
327
335
|
if (node.type !== "Identifier") return void 0;
|
|
328
336
|
const id = this.scopes.bindingOf.get(node);
|
|
329
337
|
if (id === void 0) return node.name;
|
|
@@ -620,7 +628,7 @@ var Lowerer = class {
|
|
|
620
628
|
break;
|
|
621
629
|
}
|
|
622
630
|
case "ReturnStatement":
|
|
623
|
-
if (declaration.
|
|
631
|
+
if (declaration.argument) this.report(declaration, "A module cannot return a value; export it instead");
|
|
624
632
|
body.push(returns([]));
|
|
625
633
|
break;
|
|
626
634
|
case "ImportStatement":
|
|
@@ -799,7 +807,7 @@ var Lowerer = class {
|
|
|
799
807
|
case "CallStatement": {
|
|
800
808
|
const chain = optionalChain(node.expression);
|
|
801
809
|
if (chain) return [this.optionalCallStatement(chain)];
|
|
802
|
-
const expression = this.
|
|
810
|
+
const expression = this.callValues(node.expression);
|
|
803
811
|
if (expression.type !== "CallExpression" && expression.type !== "MethodCallExpression") {
|
|
804
812
|
this.report(node, "A statement must be a call");
|
|
805
813
|
return [];
|
|
@@ -852,23 +860,26 @@ var Lowerer = class {
|
|
|
852
860
|
}];
|
|
853
861
|
case "GenericForStatement": {
|
|
854
862
|
const prelude = [];
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
if (variables.length === 1 && this.options.types?.iteratesValues.has(node)) {
|
|
862
|
-
variables.unshift(this.names.fresh("_"));
|
|
863
|
+
let item;
|
|
864
|
+
if (node.variable.type === "IdentifierPattern") {
|
|
865
|
+
item = this.name(node.variable.name);
|
|
866
|
+
} else {
|
|
867
|
+
item = this.names.fresh("item");
|
|
868
|
+
prelude.push(...this.destructure(node.variable, identifier(item), "declare"));
|
|
863
869
|
}
|
|
870
|
+
const form = this.options.types?.loops.get(node) ?? { walks: "values", viaIter: false };
|
|
871
|
+
let source = this.expression(node.iterator);
|
|
872
|
+
if (form.viaIter) source = methodCall(source, "__iter", []);
|
|
873
|
+
const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
|
|
874
|
+
const iterators = form.walks === "iteration" ? [call(this.builtin("unpack"), [source, number(1), number(3)])] : [source];
|
|
864
875
|
return [genericFor(
|
|
865
876
|
variables,
|
|
866
|
-
|
|
877
|
+
iterators,
|
|
867
878
|
this.loopBody51(this.block(node.body, prelude)).statements
|
|
868
879
|
)];
|
|
869
880
|
}
|
|
870
881
|
case "ReturnStatement":
|
|
871
|
-
return [returns(this.
|
|
882
|
+
return [returns(node.argument ? [this.expression(node.argument)] : [])];
|
|
872
883
|
case "BreakStatement":
|
|
873
884
|
return [{ type: "BreakStatement", ...spanOf(node) }];
|
|
874
885
|
case "ContinueStatement":
|
|
@@ -912,7 +923,7 @@ var Lowerer = class {
|
|
|
912
923
|
// end
|
|
913
924
|
// function Dog.speak(this) ... end
|
|
914
925
|
//
|
|
915
|
-
// `new
|
|
926
|
+
// `Dog.new(x)` builds one, `dog:speak()` passes the instance
|
|
916
927
|
// as `this`, and `super.speak()` is `Animal.speak(this)` — the
|
|
917
928
|
// base's own function, run on this instance.
|
|
918
929
|
// ============================================================
|
|
@@ -938,6 +949,7 @@ var Lowerer = class {
|
|
|
938
949
|
classRuntimeStatements() {
|
|
939
950
|
if (!this.classHelpers) return [];
|
|
940
951
|
const { build, accessors } = this.classHelpers;
|
|
952
|
+
const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
|
|
941
953
|
return (0, import_luau_parser.parse)(`
|
|
942
954
|
local function ${build}(base)
|
|
943
955
|
local class = { __getters = {}, __setters = {} }
|
|
@@ -948,6 +960,9 @@ local function ${build}(base)
|
|
|
948
960
|
setmetatable(class, { __index = base })
|
|
949
961
|
setmetatable(class.__getters, { __index = base.__getters })
|
|
950
962
|
setmetatable(class.__setters, { __index = base.__setters })
|
|
963
|
+
for _, key in ipairs(${metamethods}) do
|
|
964
|
+
class[key] = base[key]
|
|
965
|
+
end
|
|
951
966
|
end
|
|
952
967
|
return class
|
|
953
968
|
end
|
|
@@ -1010,6 +1025,7 @@ end
|
|
|
1010
1025
|
}
|
|
1011
1026
|
break;
|
|
1012
1027
|
case "ClassMethod":
|
|
1028
|
+
if (member2.isAbstract) break;
|
|
1013
1029
|
out2.push(this.functionStatement(
|
|
1014
1030
|
member(self, member2.name.name),
|
|
1015
1031
|
member2,
|
|
@@ -1031,7 +1047,7 @@ end
|
|
|
1031
1047
|
}
|
|
1032
1048
|
}
|
|
1033
1049
|
out2.push(this.classInit(node, self));
|
|
1034
|
-
out2.push(this.classNew(node, self));
|
|
1050
|
+
if (!node.isAbstract) out2.push(this.classNew(node, self));
|
|
1035
1051
|
out2.push(callStatement(call(identifier(accessors), [self])));
|
|
1036
1052
|
} finally {
|
|
1037
1053
|
this.classContext = previous;
|
|
@@ -1309,6 +1325,10 @@ end
|
|
|
1309
1325
|
}
|
|
1310
1326
|
switch (node.type) {
|
|
1311
1327
|
case "Identifier":
|
|
1328
|
+
if (node.name === "scriptArgs" && this.isLanguageGlobal(node)) {
|
|
1329
|
+
this.usesScriptArgs = true;
|
|
1330
|
+
return identifier("scriptArgs");
|
|
1331
|
+
}
|
|
1312
1332
|
return this.loweredGlobalValue(node) ?? this.reference(node);
|
|
1313
1333
|
case "NilLiteral":
|
|
1314
1334
|
return nil();
|
|
@@ -1318,8 +1338,6 @@ end
|
|
|
1318
1338
|
return number(node.value, this.numberRaw(node));
|
|
1319
1339
|
case "StringLiteral":
|
|
1320
1340
|
return string(node.value);
|
|
1321
|
-
case "VarargExpression":
|
|
1322
|
-
return vararg();
|
|
1323
1341
|
// Only a recovering parse makes one, and a syntax error stops the build.
|
|
1324
1342
|
case "ErrorExpression":
|
|
1325
1343
|
this.report(node, "Syntax error");
|
|
@@ -1340,11 +1358,6 @@ end
|
|
|
1340
1358
|
}
|
|
1341
1359
|
case "UnaryExpression":
|
|
1342
1360
|
return unary(node.operator, this.expression(node.argument));
|
|
1343
|
-
case "NewExpression":
|
|
1344
|
-
return call(
|
|
1345
|
-
member(this.expression(node.callee), "new"),
|
|
1346
|
-
this.values(node.arguments)
|
|
1347
|
-
);
|
|
1348
1361
|
case "SuperExpression":
|
|
1349
1362
|
return this.superClassReference(node);
|
|
1350
1363
|
case "SpreadElement":
|
|
@@ -1352,17 +1365,16 @@ end
|
|
|
1352
1365
|
return nil();
|
|
1353
1366
|
case "ClassExpression":
|
|
1354
1367
|
return this.classExpression(node);
|
|
1355
|
-
case "MemberExpression":
|
|
1356
|
-
case "IndexExpression":
|
|
1357
1368
|
case "CallExpression":
|
|
1358
|
-
case "MethodCallExpression":
|
|
1369
|
+
case "MethodCallExpression":
|
|
1370
|
+
return this.callValues(node);
|
|
1371
|
+
case "MemberExpression":
|
|
1372
|
+
case "IndexExpression": {
|
|
1359
1373
|
const chain = optionalChain(node);
|
|
1360
1374
|
if (chain) return this.optionalChainExpression(chain);
|
|
1361
|
-
const
|
|
1362
|
-
if (
|
|
1363
|
-
|
|
1364
|
-
}
|
|
1365
|
-
return this.link(node, this.expression(object));
|
|
1375
|
+
const global = node.type === "MemberExpression" ? this.loweredGlobalValue(node) : void 0;
|
|
1376
|
+
if (global) return global;
|
|
1377
|
+
return this.link(node, this.expression(linkObject(node)));
|
|
1366
1378
|
}
|
|
1367
1379
|
case "ParenthesizedExpression":
|
|
1368
1380
|
return parenthesized(this.expression(node.expression));
|
|
@@ -1381,14 +1393,47 @@ end
|
|
|
1381
1393
|
};
|
|
1382
1394
|
}
|
|
1383
1395
|
}
|
|
1396
|
+
/** A call. */
|
|
1397
|
+
callValues(node) {
|
|
1398
|
+
const chain = optionalChain(node);
|
|
1399
|
+
if (chain) return this.optionalChainExpression(chain);
|
|
1400
|
+
const object = linkObject(node);
|
|
1401
|
+
if (node.type === "CallExpression" && object.type === "Identifier") {
|
|
1402
|
+
return this.link(node, this.reference(object));
|
|
1403
|
+
}
|
|
1404
|
+
return this.link(node, this.expression(object));
|
|
1405
|
+
}
|
|
1406
|
+
/** A call is one value in tilua, and Luau would hand on every value one
|
|
1407
|
+
* in the last place of an argument list or an array returns. Types say
|
|
1408
|
+
* how many a call returns; where a type says nothing — `any`, `unknown`
|
|
1409
|
+
* — the call is kept to one: `f((g()))`. */
|
|
1410
|
+
keptToOne(nodes, values) {
|
|
1411
|
+
const node = nodes[nodes.length - 1];
|
|
1412
|
+
const last = values[values.length - 1];
|
|
1413
|
+
if (!node || !last || !expandsToMany(last)) return values;
|
|
1414
|
+
const type = this.options.types?.typeOf.get(node);
|
|
1415
|
+
if (type && type.kind !== "any" && type.kind !== "unknown") return values;
|
|
1416
|
+
return [...values.slice(0, -1), parenthesized(last)];
|
|
1417
|
+
}
|
|
1418
|
+
/** Is this `scriptArgs` the language's own, not a name the file declared? */
|
|
1419
|
+
isLanguageGlobal(node) {
|
|
1420
|
+
const id = this.bindingIdOf(node);
|
|
1421
|
+
return id === void 0 || this.scopes.bindings.get(id)?.kind === "global";
|
|
1422
|
+
}
|
|
1384
1423
|
/** A list of values — a call's arguments, a `return`'s, a declaration's,
|
|
1385
1424
|
* an assignment's. `f(a, ...xs)` is Lua's own last-value expansion,
|
|
1386
1425
|
* `f(a, table.unpack(xs))`; a spread anywhere else cannot be, since only
|
|
1387
1426
|
* the last value of a list expands, so the whole list is built as an
|
|
1388
|
-
* array first and that is what expands.
|
|
1389
|
-
|
|
1427
|
+
* array first and that is what expands.
|
|
1428
|
+
*
|
|
1429
|
+
* `arguments` is set for a call's arguments, where Luau hands on every
|
|
1430
|
+
* value the last one returns — see `keptToOne`. */
|
|
1431
|
+
values(list, asArguments = false) {
|
|
1390
1432
|
const spreads = list.filter((a) => a.type === "SpreadElement");
|
|
1391
|
-
if (!spreads.length)
|
|
1433
|
+
if (!spreads.length) {
|
|
1434
|
+
const lowered = list.map((a) => this.expression(a));
|
|
1435
|
+
return asArguments ? this.keptToOne(list, lowered) : lowered;
|
|
1436
|
+
}
|
|
1392
1437
|
const unpack = (value) => call(member(this.builtin("table"), "unpack"), [value]);
|
|
1393
1438
|
const last = list[list.length - 1];
|
|
1394
1439
|
if (spreads.length === 1 && last.type === "SpreadElement") {
|
|
@@ -1409,13 +1454,13 @@ end
|
|
|
1409
1454
|
return index(object, this.expression(node.index));
|
|
1410
1455
|
case "CallExpression": {
|
|
1411
1456
|
const lowered = this.loweredGlobalCall(node);
|
|
1412
|
-
const args2 = this.values(node.arguments);
|
|
1413
|
-
if (lowered) return call(
|
|
1414
|
-
return call(
|
|
1457
|
+
const args2 = this.values(node.arguments, true);
|
|
1458
|
+
if (!lowered) return call(object, args2);
|
|
1459
|
+
return call(calleePath(lowered.callee), [...lowered.prepend, ...args2]);
|
|
1415
1460
|
}
|
|
1416
1461
|
case "MethodCallExpression": {
|
|
1417
1462
|
const lowered = this.loweredMethodCall(node);
|
|
1418
|
-
const args2 = this.values(node.arguments);
|
|
1463
|
+
const args2 = this.values(node.arguments, true);
|
|
1419
1464
|
if (lowered) {
|
|
1420
1465
|
return call(calleePath(lowered.callee), [
|
|
1421
1466
|
...lowered.prepend,
|
|
@@ -1649,7 +1694,8 @@ end
|
|
|
1649
1694
|
* runs of plain elements and the spread arrays are joined by `concat`. */
|
|
1650
1695
|
arrayExpression(node) {
|
|
1651
1696
|
if (!node.elements.some((e) => e.type === "SpreadElement")) {
|
|
1652
|
-
|
|
1697
|
+
const elements = node.elements;
|
|
1698
|
+
return table(this.keptToOne(elements, elements.map((e) => this.expression(e))).map((value) => ({ type: "TableFieldPositional", value })));
|
|
1653
1699
|
}
|
|
1654
1700
|
const parts = [];
|
|
1655
1701
|
let current = [];
|
|
@@ -1848,6 +1894,24 @@ function allNodes(root) {
|
|
|
1848
1894
|
visit(root);
|
|
1849
1895
|
return out2;
|
|
1850
1896
|
}
|
|
1897
|
+
var CLASS_METAMETHODS = [
|
|
1898
|
+
"__add",
|
|
1899
|
+
"__sub",
|
|
1900
|
+
"__mul",
|
|
1901
|
+
"__div",
|
|
1902
|
+
"__idiv",
|
|
1903
|
+
"__mod",
|
|
1904
|
+
"__pow",
|
|
1905
|
+
"__unm",
|
|
1906
|
+
"__concat",
|
|
1907
|
+
"__len",
|
|
1908
|
+
"__eq",
|
|
1909
|
+
"__lt",
|
|
1910
|
+
"__le",
|
|
1911
|
+
"__call",
|
|
1912
|
+
"__tostring",
|
|
1913
|
+
"__iter"
|
|
1914
|
+
];
|
|
1851
1915
|
|
|
1852
1916
|
// src/linemap.ts
|
|
1853
1917
|
function statementsOf(node) {
|
|
@@ -1987,7 +2051,8 @@ async function bundle(options) {
|
|
|
1987
2051
|
name: source.name,
|
|
1988
2052
|
statements: lowered.statements,
|
|
1989
2053
|
exportsName: lowered.exportsName,
|
|
1990
|
-
info: lowered.module
|
|
2054
|
+
info: lowered.module,
|
|
2055
|
+
usesScriptArgs: lowered.usesScriptArgs
|
|
1991
2056
|
});
|
|
1992
2057
|
}
|
|
1993
2058
|
for (const [file, fileDirectives] of directives) {
|
|
@@ -2012,6 +2077,9 @@ async function bundle(options) {
|
|
|
2012
2077
|
}
|
|
2013
2078
|
const program = (0, import_luau_parser2.parse)(runtime(G));
|
|
2014
2079
|
const assignment = program.body.statements[1];
|
|
2080
|
+
if ([...modules.values()].some((m) => m.usesScriptArgs)) {
|
|
2081
|
+
program.body.statements.unshift(local(["scriptArgs"], [table([{ type: "TableFieldPositional", value: { type: "VarargExpression" } }])]));
|
|
2082
|
+
}
|
|
2015
2083
|
const modulesTable = assignment.type === "AssignmentStatement" && assignment.values[0].type === "TableExpression" ? assignment.values[0].fields.find((f) => f.type === "TableFieldNamed" && f.name.name === "modules")?.value : void 0;
|
|
2016
2084
|
if (!modulesTable) throw new Error("@tilua/compiler: the bundle runtime has no modules table");
|
|
2017
2085
|
for (const module2 of modules.values()) {
|
|
@@ -2148,7 +2216,22 @@ ${G} = {
|
|
|
2148
2216
|
}
|
|
2149
2217
|
`;
|
|
2150
2218
|
}
|
|
2219
|
+
function stampOf(file) {
|
|
2220
|
+
try {
|
|
2221
|
+
const at = (0, import_node_fs.statSync)(file);
|
|
2222
|
+
return `${at.size}:${at.mtimeMs}`;
|
|
2223
|
+
} catch {
|
|
2224
|
+
return void 0;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
var parsedFiles = /* @__PURE__ */ new Map();
|
|
2151
2228
|
function parseFile(file, diagnostics, directives) {
|
|
2229
|
+
const stamp = stampOf(file);
|
|
2230
|
+
const cached = stamp !== void 0 ? parsedFiles.get(file) : void 0;
|
|
2231
|
+
if (cached && cached.stamp === stamp) {
|
|
2232
|
+
directives.set(file, cached.directives);
|
|
2233
|
+
return { program: cached.program, text: cached.text };
|
|
2234
|
+
}
|
|
2152
2235
|
let text;
|
|
2153
2236
|
try {
|
|
2154
2237
|
text = (0, import_node_fs.readFileSync)(file, "utf8");
|
|
@@ -2158,7 +2241,9 @@ function parseFile(file, diagnostics, directives) {
|
|
|
2158
2241
|
}
|
|
2159
2242
|
try {
|
|
2160
2243
|
const program = (0, import_parser3.parse)(text);
|
|
2161
|
-
|
|
2244
|
+
const found = (0, import_parser3.directivesOf)(text);
|
|
2245
|
+
directives.set(file, found);
|
|
2246
|
+
if (stamp !== void 0) parsedFiles.set(file, { stamp, program, text, directives: found });
|
|
2162
2247
|
return { program, text };
|
|
2163
2248
|
} catch (error) {
|
|
2164
2249
|
if (error instanceof import_parser3.ParseError || error instanceof import_parser3.LexError) {
|
|
@@ -2172,22 +2257,93 @@ function parseFile(file, diagnostics, directives) {
|
|
|
2172
2257
|
function importedSpecifiers(program) {
|
|
2173
2258
|
return program.body.statements.flatMap((s) => s.type === "ImportStatement" || s.type === "ExportAllStatement" || s.type === "ExportNamedStatement" && s.source ? [s.source.value] : []);
|
|
2174
2259
|
}
|
|
2260
|
+
var libraryCache = /* @__PURE__ */ new Map();
|
|
2261
|
+
function parsedLibrary(file) {
|
|
2262
|
+
let stamp;
|
|
2263
|
+
try {
|
|
2264
|
+
const at = (0, import_node_fs.statSync)(file);
|
|
2265
|
+
stamp = `${at.size}:${at.mtimeMs}`;
|
|
2266
|
+
} catch {
|
|
2267
|
+
stamp = "";
|
|
2268
|
+
}
|
|
2269
|
+
const cached = libraryCache.get(file);
|
|
2270
|
+
if (cached && cached.stamp === stamp) return cached.program;
|
|
2271
|
+
const program = (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8"));
|
|
2272
|
+
libraryCache.set(file, { stamp, program });
|
|
2273
|
+
return program;
|
|
2274
|
+
}
|
|
2275
|
+
var moduleAnalyses = /* @__PURE__ */ new Map();
|
|
2175
2276
|
function analyzeModules(modules, config2) {
|
|
2176
2277
|
const out2 = [];
|
|
2177
2278
|
const analyses = /* @__PURE__ */ new Map();
|
|
2178
2279
|
const libraries = config2 ? (0, import_parser3.resolveTypeLibraries)(config2) : { files: [], lowerings: [], problems: [] };
|
|
2179
2280
|
for (const p of libraries.problems) out2.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
|
|
2180
|
-
const libs = libraries.files.map(
|
|
2281
|
+
const libs = libraries.files.map(parsedLibrary);
|
|
2181
2282
|
const globals = libs.flatMap((lib) => lib.body.statements.flatMap((s) => s.type === "DeclareStatement" ? [s.name] : []));
|
|
2182
2283
|
const byFile = new Map(modules.map((m) => [m.file, m]));
|
|
2183
2284
|
const exportsCache = /* @__PURE__ */ new Map();
|
|
2184
2285
|
const inProgress = /* @__PURE__ */ new Set();
|
|
2286
|
+
const analyzed = /* @__PURE__ */ new Map();
|
|
2287
|
+
let partials = 0;
|
|
2288
|
+
const readWhile = /* @__PURE__ */ new Map();
|
|
2289
|
+
const settingFor = `${libraries.files.join("|")}#${config2?.directory ?? ""}#${JSON.stringify(config2?.paths ?? {})}`;
|
|
2290
|
+
const analyzeModule = (file, program) => {
|
|
2291
|
+
const done = analyzed.get(file);
|
|
2292
|
+
if (done) return done;
|
|
2293
|
+
const remembered = moduleAnalyses.get(file);
|
|
2294
|
+
if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program && [...remembered.read].every(([read, stamp]) => stampOf(read) === stamp)) {
|
|
2295
|
+
analyzed.set(file, remembered.result);
|
|
2296
|
+
readWhile.set(file, remembered.read);
|
|
2297
|
+
return remembered.result;
|
|
2298
|
+
}
|
|
2299
|
+
const scopes = (0, import_parser3.analyzeScopes)(program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
|
|
2300
|
+
const said = [];
|
|
2301
|
+
for (const d of scopes.diagnostics) {
|
|
2302
|
+
if (d.kind !== "undeclared") continue;
|
|
2303
|
+
said.push({ file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
|
|
2304
|
+
}
|
|
2305
|
+
const before = partials;
|
|
2306
|
+
const types = (0, import_parser3.analyzeTypes)(program, scopes, {
|
|
2307
|
+
libs,
|
|
2308
|
+
resolveModule: resolverFor(file),
|
|
2309
|
+
reportUnknownTypes: libs.length > 0
|
|
2310
|
+
});
|
|
2311
|
+
for (const d of types.diagnostics) {
|
|
2312
|
+
const at = d.node;
|
|
2313
|
+
said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
|
|
2314
|
+
}
|
|
2315
|
+
const result = { types, diagnostics: said };
|
|
2316
|
+
if (partials === before) {
|
|
2317
|
+
analyzed.set(file, result);
|
|
2318
|
+
const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
|
|
2319
|
+
const own = stampOf(file);
|
|
2320
|
+
if (own !== void 0) read.set(file, own);
|
|
2321
|
+
readWhile.set(file, read);
|
|
2322
|
+
if ([...read.values()].every((stamp) => stamp !== void 0)) {
|
|
2323
|
+
moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program, read, result });
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
return result;
|
|
2327
|
+
};
|
|
2185
2328
|
const resolverFor = (file) => (specifier) => {
|
|
2186
2329
|
const target = (0, import_parser3.resolveModulePath)(file, specifier, config2);
|
|
2187
2330
|
if (!target) return void 0;
|
|
2188
|
-
|
|
2331
|
+
const noteRead = () => {
|
|
2332
|
+
const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
|
|
2333
|
+
readWhile.set(file, read);
|
|
2334
|
+
const stamp = stampOf(target);
|
|
2335
|
+
if (stamp !== void 0) read.set(target, stamp);
|
|
2336
|
+
for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
|
|
2337
|
+
};
|
|
2338
|
+
if (inProgress.has(target)) {
|
|
2339
|
+
partials++;
|
|
2340
|
+
return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
|
|
2341
|
+
}
|
|
2189
2342
|
const cached = exportsCache.get(target);
|
|
2190
|
-
if (cached)
|
|
2343
|
+
if (cached) {
|
|
2344
|
+
noteRead();
|
|
2345
|
+
return cached;
|
|
2346
|
+
}
|
|
2191
2347
|
let program = byFile.get(target)?.program;
|
|
2192
2348
|
if (!program) {
|
|
2193
2349
|
try {
|
|
@@ -2199,30 +2355,19 @@ function analyzeModules(modules, config2) {
|
|
|
2199
2355
|
inProgress.add(target);
|
|
2200
2356
|
try {
|
|
2201
2357
|
const scopes = (0, import_parser3.analyzeScopes)(program, { builtinGlobals: globals });
|
|
2202
|
-
const types = (0, import_parser3.analyzeTypes)(program, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
|
|
2358
|
+
const types = byFile.has(target) ? analyzeModule(target, program).types : (0, import_parser3.analyzeTypes)(program, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
|
|
2203
2359
|
const exports2 = (0, import_parser3.moduleExports)(program, scopes, types, resolverFor(target));
|
|
2204
2360
|
exportsCache.set(target, exports2);
|
|
2361
|
+
noteRead();
|
|
2205
2362
|
return exports2;
|
|
2206
2363
|
} finally {
|
|
2207
2364
|
inProgress.delete(target);
|
|
2208
2365
|
}
|
|
2209
2366
|
};
|
|
2210
2367
|
for (const module2 of modules) {
|
|
2211
|
-
const
|
|
2212
|
-
for (const d of scopes.diagnostics) {
|
|
2213
|
-
if (d.kind !== "undeclared") continue;
|
|
2214
|
-
out2.push({ file: module2.file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
|
|
2215
|
-
}
|
|
2216
|
-
const types = (0, import_parser3.analyzeTypes)(module2.program, scopes, {
|
|
2217
|
-
libs,
|
|
2218
|
-
resolveModule: resolverFor(module2.file),
|
|
2219
|
-
reportUnknownTypes: libs.length > 0
|
|
2220
|
-
});
|
|
2368
|
+
const { types, diagnostics } = analyzeModule(module2.file, module2.program);
|
|
2221
2369
|
analyses.set(module2.file, types);
|
|
2222
|
-
|
|
2223
|
-
const at = d.node;
|
|
2224
|
-
out2.push({ file: module2.file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
|
|
2225
|
-
}
|
|
2370
|
+
out2.push(...diagnostics);
|
|
2226
2371
|
}
|
|
2227
2372
|
return { types: analyses, diagnostics: out2, lowerings: [...libraries.lowerings] };
|
|
2228
2373
|
}
|