@alveolus/arch 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.mjs +1 -1
- package/dist/{docs-B1Tzkjrn.mjs → docs-B6M9DxTM.mjs} +449 -56
- package/dist/docs-B6M9DxTM.mjs.map +1 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/docs/core/strategic/open-host-services.md +1 -1
- package/docs/rules/index.md +7 -3
- package/docs/rules/strategic/no-cross-context-import.md +34 -5
- package/docs/rules/strategic/no-leaky-host-service.md +59 -6
- package/docs/rules/strategic/no-shared-state.md +37 -11
- package/docs/rules/strategic/no-unmapped-context.md +17 -11
- package/package.json +1 -1
- package/dist/docs-B1Tzkjrn.mjs.map +0 -1
|
@@ -173,6 +173,9 @@ var Member = class {
|
|
|
173
173
|
parameterTypes;
|
|
174
174
|
returns;
|
|
175
175
|
holdsCollection;
|
|
176
|
+
receivesFunction;
|
|
177
|
+
erasedType;
|
|
178
|
+
opaqueValue;
|
|
176
179
|
constructor(props) {
|
|
177
180
|
this.name = props.name;
|
|
178
181
|
this.line = props.line;
|
|
@@ -186,6 +189,9 @@ var Member = class {
|
|
|
186
189
|
this.parameterTypes = props.parameterTypes;
|
|
187
190
|
this.returns = props.returns;
|
|
188
191
|
this.holdsCollection = props.holdsCollection;
|
|
192
|
+
this.receivesFunction = props.receivesFunction;
|
|
193
|
+
this.erasedType = props.erasedType;
|
|
194
|
+
this.opaqueValue = props.opaqueValue;
|
|
189
195
|
}
|
|
190
196
|
get isPublicInstance() {
|
|
191
197
|
return this.visibility === "public" && !this.isStatic;
|
|
@@ -217,6 +223,18 @@ var Dependency = class {
|
|
|
217
223
|
}
|
|
218
224
|
};
|
|
219
225
|
//#endregion
|
|
226
|
+
//#region src/model/dependencies/global-channel.ts
|
|
227
|
+
var GlobalChannel = class {
|
|
228
|
+
line;
|
|
229
|
+
name;
|
|
230
|
+
access;
|
|
231
|
+
constructor(line, name, access) {
|
|
232
|
+
this.line = line;
|
|
233
|
+
this.name = name;
|
|
234
|
+
this.access = access;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
//#endregion
|
|
220
238
|
//#region src/model/dependencies/global-use.ts
|
|
221
239
|
var GlobalUse = class {
|
|
222
240
|
line;
|
|
@@ -231,6 +249,20 @@ var GlobalUse = class {
|
|
|
231
249
|
}
|
|
232
250
|
};
|
|
233
251
|
//#endregion
|
|
252
|
+
//#region src/model/dependencies/module-reach.ts
|
|
253
|
+
var ModuleReach = class {
|
|
254
|
+
line;
|
|
255
|
+
expression;
|
|
256
|
+
means;
|
|
257
|
+
module;
|
|
258
|
+
constructor(line, expression, means, module) {
|
|
259
|
+
this.line = line;
|
|
260
|
+
this.expression = expression;
|
|
261
|
+
this.means = means;
|
|
262
|
+
this.module = module;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
//#endregion
|
|
234
266
|
//#region src/model/dependencies/wiring.ts
|
|
235
267
|
var Wiring = class {
|
|
236
268
|
line;
|
|
@@ -273,7 +305,9 @@ var SourceFile = class {
|
|
|
273
305
|
statements;
|
|
274
306
|
throws;
|
|
275
307
|
globals;
|
|
308
|
+
globalChannels;
|
|
276
309
|
wirings;
|
|
310
|
+
moduleReaches;
|
|
277
311
|
disables;
|
|
278
312
|
lines;
|
|
279
313
|
constructor(props) {
|
|
@@ -283,7 +317,9 @@ var SourceFile = class {
|
|
|
283
317
|
this.statements = props.statements;
|
|
284
318
|
this.throws = props.throws;
|
|
285
319
|
this.globals = props.globals;
|
|
320
|
+
this.globalChannels = props.globalChannels;
|
|
286
321
|
this.wirings = props.wirings;
|
|
322
|
+
this.moduleReaches = props.moduleReaches;
|
|
287
323
|
this.disables = props.disables;
|
|
288
324
|
this.lines = props.text.split(/\r?\n/);
|
|
289
325
|
}
|
|
@@ -1339,9 +1375,11 @@ var NoCrossContextImportRule = class extends ImportRule {
|
|
|
1339
1375
|
id: "strategic/no-cross-context-import",
|
|
1340
1376
|
messages: {
|
|
1341
1377
|
dynamicLoad: "Loads code at runtime with {loader}: the analysis cannot tell which bounded context it reaches; use a static import.",
|
|
1378
|
+
globalChannel: "{access} {name}, which no file declares: two contexts can meet there without the context map showing it. Integrate through an open host service, or publish an integration event.",
|
|
1342
1379
|
notOpenHostService: "Imports {target}: only an OpenHostService of another bounded context may be imported.",
|
|
1343
1380
|
outsideAntiCorruptionLayer: "Uses the open host service of {context} outside an AntiCorruptionLayer: a core context translates what it consumes in an anti-corruption layer.",
|
|
1344
1381
|
publishedLanguage: "Imports the published language of {context}: redeclare the fields you read in your own published-language/.",
|
|
1382
|
+
reachedModule: "Reaches into {expression} with {means}: in the wiring, a module of another context is read by its properties, so that what crosses can be seen.",
|
|
1345
1383
|
reexport: "The composition root re-exports {names}: it exports its own module only, so that no other context reaches through it.",
|
|
1346
1384
|
sharedKernel: "The shared kernel imports no bounded context, but imports {target}.",
|
|
1347
1385
|
unseen: "Imports {target}: the analysis cannot tell which bounded context it reaches; move the file into a bounded context or the shared kernel.",
|
|
@@ -1350,11 +1388,38 @@ var NoCrossContextImportRule = class extends ImportRule {
|
|
|
1350
1388
|
};
|
|
1351
1389
|
check(architecture) {
|
|
1352
1390
|
const findings = super.check(architecture);
|
|
1353
|
-
for (const file of this.filesOf(architecture))
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1391
|
+
for (const file of this.filesOf(architecture)) {
|
|
1392
|
+
findings.push(...this.reachedModules(file, architecture));
|
|
1393
|
+
findings.push(...this.globalChannels(file, architecture));
|
|
1394
|
+
for (const crossing of architecture.crossingsIn(file)) if (!crossing.isOpenHostService) findings.push(this.finding(file, crossing.line, crossing.expression, "wiredModel", {
|
|
1395
|
+
expression: crossing.expression,
|
|
1396
|
+
from: crossing.from,
|
|
1397
|
+
to: crossing.to
|
|
1398
|
+
}));
|
|
1399
|
+
}
|
|
1400
|
+
return findings;
|
|
1401
|
+
}
|
|
1402
|
+
globalChannels(file, architecture) {
|
|
1403
|
+
const location = architecture.locationOf(file);
|
|
1404
|
+
if (!location.isInBoundedContext && !location.isInSharedKernel && !location.isAtRoot) return [];
|
|
1405
|
+
return file.globalChannels.map((channel) => {
|
|
1406
|
+
const access = channel.access === "writes" ? "Writes" : "Reads";
|
|
1407
|
+
return this.finding(file, channel.line, channel.name, "globalChannel", {
|
|
1408
|
+
access,
|
|
1409
|
+
name: channel.name
|
|
1410
|
+
});
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
reachedModules(file, architecture) {
|
|
1414
|
+
const from = architecture.locationOf(file);
|
|
1415
|
+
const findings = [];
|
|
1416
|
+
for (const reach of file.moduleReaches) {
|
|
1417
|
+
const module = architecture.locationOfPath(reach.module.declaredIn ?? "");
|
|
1418
|
+
if (module.isCompositionRoot && module.isInBoundedContext && !module.isSameContextAs(from)) findings.push(this.finding(file, reach.line, reach.expression, "reachedModule", {
|
|
1419
|
+
expression: reach.expression,
|
|
1420
|
+
means: reach.means
|
|
1421
|
+
}));
|
|
1422
|
+
}
|
|
1358
1423
|
return findings;
|
|
1359
1424
|
}
|
|
1360
1425
|
appliesTo(file, architecture) {
|
|
@@ -1424,15 +1489,24 @@ var NoFatSharedKernelRule = class extends ClassRule {
|
|
|
1424
1489
|
var NoLeakyHostServiceRule = class extends ClassRule {
|
|
1425
1490
|
meta = {
|
|
1426
1491
|
contexts: "every",
|
|
1427
|
-
description: "An open host service that exposes a class of its context instead of the published language.",
|
|
1492
|
+
description: "An open host service that exposes a class of its context, receives a function or returns an erased type, instead of speaking the published language.",
|
|
1428
1493
|
id: "strategic/no-leaky-host-service",
|
|
1429
|
-
messages: {
|
|
1494
|
+
messages: {
|
|
1495
|
+
behaviour: "{member} receives a function: an open host service receives data, never behaviour, or the upstream context ends up running code of another one. To let another context react, publish an integration event.",
|
|
1496
|
+
erased: "{member} returns {type}: an open host service returns a type of its published language, so that what leaves the context can be seen.",
|
|
1497
|
+
exposes: "{member} exposes {type}, {kind}{owner}: an open host service speaks the published language."
|
|
1498
|
+
}
|
|
1430
1499
|
};
|
|
1431
1500
|
findingsFor(codeClass, file, architecture) {
|
|
1432
1501
|
if (!architecture.implementsMarker(codeClass, "OpenHostService")) return [];
|
|
1433
1502
|
const findings = /* @__PURE__ */ new Map();
|
|
1434
1503
|
for (const member of codeClass.publicSurface) {
|
|
1435
1504
|
const symbol = `${codeClass.name}.${member.name}`;
|
|
1505
|
+
if (member.receivesFunction) findings.set(`${symbol}:behaviour`, this.finding(file, member.line, symbol, "behaviour", { member: symbol }));
|
|
1506
|
+
if (member.erasedType !== void 0) findings.set(`${symbol}:erased`, this.finding(file, member.line, symbol, "erased", {
|
|
1507
|
+
member: symbol,
|
|
1508
|
+
type: member.erasedType
|
|
1509
|
+
}));
|
|
1436
1510
|
for (const type of [...member.parameterTypes, ...member.valueTypes]) {
|
|
1437
1511
|
const key = `${symbol}:${type.name}`;
|
|
1438
1512
|
if (this.leaks(type, architecture) && !findings.has(key)) findings.set(key, this.finding(file, member.line, symbol, "exposes", this.describe(symbol, type, architecture)));
|
|
@@ -1463,29 +1537,52 @@ var NoLeakyHostServiceRule = class extends ClassRule {
|
|
|
1463
1537
|
var NoSharedStateRule = class extends ClassRule {
|
|
1464
1538
|
meta = {
|
|
1465
1539
|
contexts: "every",
|
|
1466
|
-
description: "A static field of the shared kernel that holds state: one without readonly, or
|
|
1540
|
+
description: "A static field of the shared kernel that holds state: one without readonly, a collection, or anything but a value.",
|
|
1467
1541
|
id: "strategic/no-shared-state",
|
|
1468
1542
|
messages: {
|
|
1469
1543
|
collection: "{class}.{field} holds a collection in a static field: every context reaches the same one, a channel the context map does not show. The shared kernel shares a model, not state: integrate through an open host service.",
|
|
1470
|
-
mutable: "{class}.{field} is a static field without readonly: every context reaches the same one, a channel the context map does not show. The shared kernel shares a model, not state: integrate through an open host service."
|
|
1544
|
+
mutable: "{class}.{field} is a static field without readonly: every context reaches the same one, a channel the context map does not show. The shared kernel shares a model, not state: integrate through an open host service.",
|
|
1545
|
+
notValue: "{class}.{field} holds {holds} in a static field, which can keep state every context reaches, a channel the context map does not show. A static field of the shared kernel holds a value: a primitive, a value object, an identifier, a class of domainDependencies, or a readonly collection of them."
|
|
1471
1546
|
}
|
|
1472
1547
|
};
|
|
1473
1548
|
findingsFor(codeClass, file, architecture) {
|
|
1474
1549
|
if (!architecture.locationOf(file).isInSharedKernel) return [];
|
|
1475
1550
|
const findings = [];
|
|
1476
1551
|
for (const member of codeClass.members) {
|
|
1477
|
-
const
|
|
1478
|
-
if (
|
|
1552
|
+
const state = this.stateOf(member, architecture);
|
|
1553
|
+
if (state !== void 0) findings.push(this.finding(file, member.line, member.name, state.messageId, {
|
|
1554
|
+
...state.data,
|
|
1479
1555
|
class: codeClass.name,
|
|
1480
1556
|
field: member.name
|
|
1481
1557
|
}));
|
|
1482
1558
|
}
|
|
1483
1559
|
return findings;
|
|
1484
1560
|
}
|
|
1485
|
-
stateOf(member) {
|
|
1561
|
+
stateOf(member, architecture) {
|
|
1486
1562
|
if (!member.isStatic || member.kind !== "field") return;
|
|
1487
|
-
if (!member.isReadonly) return
|
|
1488
|
-
|
|
1563
|
+
if (!member.isReadonly) return {
|
|
1564
|
+
data: {},
|
|
1565
|
+
messageId: "mutable"
|
|
1566
|
+
};
|
|
1567
|
+
if (member.holdsCollection) return {
|
|
1568
|
+
data: {},
|
|
1569
|
+
messageId: "collection"
|
|
1570
|
+
};
|
|
1571
|
+
if (member.opaqueValue !== void 0) return {
|
|
1572
|
+
data: { holds: member.opaqueValue },
|
|
1573
|
+
messageId: "notValue"
|
|
1574
|
+
};
|
|
1575
|
+
const service = member.valueTypes.find((type) => !this.isValue(type, architecture));
|
|
1576
|
+
if (service === void 0) return;
|
|
1577
|
+
return {
|
|
1578
|
+
data: { holds: `${/^[AEIOU]/.test(service.name) ? "an" : "a"} ${service.name}` },
|
|
1579
|
+
messageId: "notValue"
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
isValue(type, architecture) {
|
|
1583
|
+
if (architecture.is(type, "ValueObject") || architecture.is(type, "Identifier")) return true;
|
|
1584
|
+
const packageName = type.lineage[0]?.packageName;
|
|
1585
|
+
return packageName !== void 0 && architecture.domainDependencies.has(packageName);
|
|
1489
1586
|
}
|
|
1490
1587
|
};
|
|
1491
1588
|
//#endregion
|
|
@@ -1496,8 +1593,8 @@ var NoUnmappedContextRule = class extends Rule {
|
|
|
1496
1593
|
description: "A bounded context consuming one the context map does not allow, through an import or through the wiring.",
|
|
1497
1594
|
id: "strategic/no-unmapped-context",
|
|
1498
1595
|
messages: {
|
|
1499
|
-
unmapped: "{from} consumes {to}, which the context map does not allow: reverse the dependency, or if {from} really is downstream of {to}, add {to} to contextMap.{from}.consumes.",
|
|
1500
|
-
unmappedWiring: "{from} receives {expression} from {to} here, which the context map does not allow: reverse the dependency, or if {from} really is downstream of {to}, add {to} to contextMap.{from}.consumes."
|
|
1596
|
+
unmapped: "{from} consumes {to}, which the context map does not allow: reverse the dependency with an integration event that {from} publishes and {to} subscribes to, not with a callback; or if {from} really is downstream of {to}, add {to} to contextMap.{from}.consumes.",
|
|
1597
|
+
unmappedWiring: "{from} receives {expression} from {to} here, which the context map does not allow: reverse the dependency with an integration event that {from} publishes and {to} subscribes to, not with a callback; or if {from} really is downstream of {to}, add {to} to contextMap.{from}.consumes."
|
|
1501
1598
|
}
|
|
1502
1599
|
};
|
|
1503
1600
|
check(architecture) {
|
|
@@ -2404,8 +2501,11 @@ var ClassReader = class {
|
|
|
2404
2501
|
const type = member.getType();
|
|
2405
2502
|
const [signature] = type.getCallSignatures();
|
|
2406
2503
|
return [this.member(member, "field", {
|
|
2504
|
+
erasedType: this.types.erasedNameOf(signature === void 0 ? type : signature.getReturnType()),
|
|
2407
2505
|
holdsCollection: this.types.holdsCollection(type),
|
|
2408
2506
|
isCallable: signature !== void 0,
|
|
2507
|
+
opaqueValue: this.types.opaqueValueIn(type),
|
|
2508
|
+
receivesFunction: signature !== void 0 && signature.getParameters().some((parameter) => this.types.holdsFunction(parameter.getTypeAtLocation(member))),
|
|
2409
2509
|
returns: signature === void 0 ? void 0 : this.types.returnShapeOf(signature.getReturnType()),
|
|
2410
2510
|
valueTypes: this.types.classTypesIn(type)
|
|
2411
2511
|
})];
|
|
@@ -2413,8 +2513,11 @@ var ClassReader = class {
|
|
|
2413
2513
|
if (Node.isMethodDeclaration(member)) {
|
|
2414
2514
|
const returnType = member.getReturnType();
|
|
2415
2515
|
const parameterTypes = member.getParameters().flatMap((parameter) => this.types.classTypesIn(parameter.getType()));
|
|
2516
|
+
const receivesFunction = member.getParameters().some((parameter) => this.types.holdsFunction(parameter.getType()));
|
|
2416
2517
|
return [this.member(member, "method", {
|
|
2518
|
+
erasedType: this.types.erasedNameOf(returnType),
|
|
2417
2519
|
parameterTypes,
|
|
2520
|
+
receivesFunction,
|
|
2418
2521
|
returns: this.types.returnShapeOf(returnType),
|
|
2419
2522
|
valueTypes: this.types.classTypesIn(returnType)
|
|
2420
2523
|
})];
|
|
@@ -2422,6 +2525,7 @@ var ClassReader = class {
|
|
|
2422
2525
|
if (Node.isGetAccessorDeclaration(member)) {
|
|
2423
2526
|
const returnType = member.getReturnType();
|
|
2424
2527
|
return [this.member(member, "getter", {
|
|
2528
|
+
erasedType: this.types.erasedNameOf(returnType),
|
|
2425
2529
|
returns: this.types.returnShapeOf(returnType),
|
|
2426
2530
|
valueTypes: this.types.classTypesIn(returnType)
|
|
2427
2531
|
})];
|
|
@@ -2434,6 +2538,7 @@ var ClassReader = class {
|
|
|
2434
2538
|
const isStatic = Node.isStaticable(member) && member.isStatic();
|
|
2435
2539
|
const scope = Node.isScoped(member) ? member.getScope() : Scope.Public;
|
|
2436
2540
|
return new Member({
|
|
2541
|
+
erasedType: types.erasedType,
|
|
2437
2542
|
holdsCollection: types.holdsCollection ?? false,
|
|
2438
2543
|
isCallable: types.isCallable ?? false,
|
|
2439
2544
|
isParameterProperty: false,
|
|
@@ -2442,7 +2547,9 @@ var ClassReader = class {
|
|
|
2442
2547
|
kind,
|
|
2443
2548
|
line: member.getStartLineNumber(),
|
|
2444
2549
|
name,
|
|
2550
|
+
opaqueValue: types.opaqueValue,
|
|
2445
2551
|
parameterTypes: types.parameterTypes ?? [],
|
|
2552
|
+
receivesFunction: types.receivesFunction ?? false,
|
|
2446
2553
|
returns: types.returns,
|
|
2447
2554
|
valueTypes: types.valueTypes ?? [],
|
|
2448
2555
|
visibility: name.startsWith("#") ? "private" : this.visibilityOf(scope)
|
|
@@ -2453,6 +2560,7 @@ var ClassReader = class {
|
|
|
2453
2560
|
}
|
|
2454
2561
|
constructorParameter(parameter) {
|
|
2455
2562
|
return new Member({
|
|
2563
|
+
erasedType: void 0,
|
|
2456
2564
|
holdsCollection: this.types.holdsCollection(parameter.getType()),
|
|
2457
2565
|
isCallable: false,
|
|
2458
2566
|
isParameterProperty: parameter.isParameterProperty(),
|
|
@@ -2461,7 +2569,9 @@ var ClassReader = class {
|
|
|
2461
2569
|
kind: "constructor parameter",
|
|
2462
2570
|
line: parameter.getStartLineNumber(),
|
|
2463
2571
|
name: parameter.getName(),
|
|
2572
|
+
opaqueValue: void 0,
|
|
2464
2573
|
parameterTypes: [],
|
|
2574
|
+
receivesFunction: false,
|
|
2465
2575
|
returns: void 0,
|
|
2466
2576
|
valueTypes: this.types.classTypesIn(parameter.getType()),
|
|
2467
2577
|
visibility: this.visibilityOf(parameter.getScope() ?? Scope.Public)
|
|
@@ -2494,13 +2604,12 @@ var ClassReader = class {
|
|
|
2494
2604
|
}
|
|
2495
2605
|
};
|
|
2496
2606
|
//#endregion
|
|
2497
|
-
//#region src/importer/ts-morph/readers/
|
|
2498
|
-
const
|
|
2499
|
-
|
|
2500
|
-
"
|
|
2501
|
-
"
|
|
2502
|
-
"
|
|
2503
|
-
"node:vm"
|
|
2607
|
+
//#region src/importer/ts-morph/readers/loader-reader.ts
|
|
2608
|
+
const globalObjects$1 = [
|
|
2609
|
+
"globalThis",
|
|
2610
|
+
"global",
|
|
2611
|
+
"window",
|
|
2612
|
+
"self"
|
|
2504
2613
|
];
|
|
2505
2614
|
const globalLoaders = ["eval", "Function"];
|
|
2506
2615
|
const loaderMembers = [
|
|
@@ -2509,9 +2618,87 @@ const loaderMembers = [
|
|
|
2509
2618
|
"require",
|
|
2510
2619
|
"getBuiltinModule"
|
|
2511
2620
|
];
|
|
2621
|
+
const reflections = [
|
|
2622
|
+
"get",
|
|
2623
|
+
"apply",
|
|
2624
|
+
"construct"
|
|
2625
|
+
];
|
|
2626
|
+
var LoaderReader = class {
|
|
2627
|
+
read(file) {
|
|
2628
|
+
const loads = [];
|
|
2629
|
+
file.forEachDescendant((node) => {
|
|
2630
|
+
const loader = this.loaderAt(node);
|
|
2631
|
+
if (loader !== void 0) loads.push({
|
|
2632
|
+
line: node.getStartLineNumber(),
|
|
2633
|
+
loader
|
|
2634
|
+
});
|
|
2635
|
+
});
|
|
2636
|
+
return loads;
|
|
2637
|
+
}
|
|
2638
|
+
loaderAt(node) {
|
|
2639
|
+
if (Node.isCallExpression(node) || Node.isNewExpression(node)) return this.calledLoader(node);
|
|
2640
|
+
if (Node.isElementAccessExpression(node)) return this.globalLookup(node.getExpression(), node.getArgumentExpression());
|
|
2641
|
+
}
|
|
2642
|
+
calledLoader(call) {
|
|
2643
|
+
const callee = call.getExpression();
|
|
2644
|
+
const bare = this.unwrapped(callee);
|
|
2645
|
+
if (Node.isElementAccessExpression(bare)) return;
|
|
2646
|
+
const reflected = this.reflectedLoader(bare, call.getArguments());
|
|
2647
|
+
if (reflected !== void 0) return reflected;
|
|
2648
|
+
return this.namedLoader(bare) ?? this.typedLoader(callee) ?? this.typedLoader(bare);
|
|
2649
|
+
}
|
|
2650
|
+
reflectedLoader(callee, args) {
|
|
2651
|
+
if (!Node.isPropertyAccessExpression(callee) || callee.getExpression().getText() !== "Reflect" || !reflections.includes(callee.getName())) return;
|
|
2652
|
+
const [target, key] = args;
|
|
2653
|
+
if (target === void 0) return;
|
|
2654
|
+
if (callee.getName() === "get") return this.globalLookup(target, key);
|
|
2655
|
+
const bare = this.unwrapped(target);
|
|
2656
|
+
return this.namedLoader(bare) ?? this.typedLoader(target) ?? this.typedLoader(bare);
|
|
2657
|
+
}
|
|
2658
|
+
globalLookup(object, key) {
|
|
2659
|
+
const bare = this.unwrapped(object);
|
|
2660
|
+
if (!Node.isIdentifier(bare) || !globalObjects$1.includes(bare.getText()) || !this.isFromLibrary(bare)) return;
|
|
2661
|
+
if (key === void 0 || !Node.isStringLiteral(key)) return `${bare.getText()}[…]`;
|
|
2662
|
+
return globalLoaders.includes(key.getLiteralValue()) ? `${bare.getText()}.${key.getLiteralValue()}` : void 0;
|
|
2663
|
+
}
|
|
2664
|
+
namedLoader(callee) {
|
|
2665
|
+
if (Node.isIdentifier(callee)) return globalLoaders.includes(callee.getText()) && this.isFromLibrary(callee) ? callee.getText() : void 0;
|
|
2666
|
+
if (!Node.isPropertyAccessExpression(callee)) return;
|
|
2667
|
+
if (loaderMembers.includes(callee.getName())) return callee.getText();
|
|
2668
|
+
if (callee.getName() === "constructor") {
|
|
2669
|
+
const owner = callee.getExpression().getType();
|
|
2670
|
+
return owner.isAny() || owner.getCallSignatures().length > 0 ? callee.getText() : void 0;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
typedLoader(callee) {
|
|
2674
|
+
const symbol = callee.getType().getSymbol();
|
|
2675
|
+
if (symbol?.getName() === "FunctionConstructor") return "Function";
|
|
2676
|
+
const declaration = symbol?.getDeclarations()[0];
|
|
2677
|
+
if (symbol?.getName() === "eval" && declaration?.getSourceFile().isDeclarationFile() === true) return "eval";
|
|
2678
|
+
}
|
|
2679
|
+
isFromLibrary(identifier) {
|
|
2680
|
+
const declaration = identifier.getSymbol()?.getDeclarations()[0];
|
|
2681
|
+
return declaration === void 0 || declaration.getSourceFile().isDeclarationFile();
|
|
2682
|
+
}
|
|
2683
|
+
unwrapped(expression) {
|
|
2684
|
+
if (Node.isParenthesizedExpression(expression) || Node.isAsExpression(expression) || Node.isNonNullExpression(expression) || Node.isSatisfiesExpression(expression)) return this.unwrapped(expression.getExpression());
|
|
2685
|
+
if (Node.isBinaryExpression(expression) && expression.getOperatorToken().getText() === ",") return this.unwrapped(expression.getRight());
|
|
2686
|
+
return expression;
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
//#endregion
|
|
2690
|
+
//#region src/importer/ts-morph/readers/dependency-reader.ts
|
|
2691
|
+
const everything = ["*"];
|
|
2692
|
+
const loaderPackages = [
|
|
2693
|
+
"module",
|
|
2694
|
+
"node:module",
|
|
2695
|
+
"vm",
|
|
2696
|
+
"node:vm"
|
|
2697
|
+
];
|
|
2512
2698
|
var DependencyReader = class {
|
|
2513
2699
|
project;
|
|
2514
2700
|
scope;
|
|
2701
|
+
loaders = new LoaderReader();
|
|
2515
2702
|
constructor(project, scope) {
|
|
2516
2703
|
this.project = project;
|
|
2517
2704
|
this.scope = scope;
|
|
@@ -2528,11 +2715,14 @@ var DependencyReader = class {
|
|
|
2528
2715
|
for (const declaration of file.getExportDeclarations()) if (declaration.hasModuleSpecifier()) references.push(this.fromDeclaration(declaration, "re-export"));
|
|
2529
2716
|
for (const declaration of file.getDescendantsOfKind(SyntaxKind.ImportEqualsDeclaration)) references.push(...this.fromImportEquals(declaration));
|
|
2530
2717
|
for (const node of file.getDescendantsOfKind(SyntaxKind.ImportType)) references.push(this.fromImportType(node));
|
|
2531
|
-
for (const call of file.getDescendantsOfKind(SyntaxKind.CallExpression))
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2718
|
+
for (const call of file.getDescendantsOfKind(SyntaxKind.CallExpression)) references.push(...this.fromCall(call));
|
|
2719
|
+
for (const load of this.loaders.read(file)) references.push({
|
|
2720
|
+
form: "dynamic load",
|
|
2721
|
+
line: load.line,
|
|
2722
|
+
names: [],
|
|
2723
|
+
specifier: load.loader,
|
|
2724
|
+
text: load.loader
|
|
2725
|
+
});
|
|
2536
2726
|
for (const reference of file.getPathReferenceDirectives()) references.push({
|
|
2537
2727
|
...this.fromDirective(reference, file),
|
|
2538
2728
|
isPath: true
|
|
@@ -2594,31 +2784,6 @@ var DependencyReader = class {
|
|
|
2594
2784
|
if (!name.isKind(SyntaxKind.StringLiteral) || name.getLiteralValue().includes("*")) return [];
|
|
2595
2785
|
return [this.reference(declaration, "augmentation", name, everything)];
|
|
2596
2786
|
}
|
|
2597
|
-
fromLoader(call) {
|
|
2598
|
-
const loader = this.loaderOf(call.getExpression());
|
|
2599
|
-
if (loader === void 0) return [];
|
|
2600
|
-
return [{
|
|
2601
|
-
form: "dynamic load",
|
|
2602
|
-
line: call.getStartLineNumber(),
|
|
2603
|
-
names: [],
|
|
2604
|
-
specifier: loader,
|
|
2605
|
-
text: loader
|
|
2606
|
-
}];
|
|
2607
|
-
}
|
|
2608
|
-
loaderOf(callee) {
|
|
2609
|
-
const expression = this.unwrapped(callee);
|
|
2610
|
-
if (expression.isKind(SyntaxKind.Identifier)) return globalLoaders.includes(expression.getText()) && !this.isDeclaredInProject(expression) ? expression.getText() : void 0;
|
|
2611
|
-
if (expression.isKind(SyntaxKind.PropertyAccessExpression) && loaderMembers.includes(expression.getName())) return expression.getText();
|
|
2612
|
-
}
|
|
2613
|
-
unwrapped(expression) {
|
|
2614
|
-
if (expression.isKind(SyntaxKind.ParenthesizedExpression)) return this.unwrapped(expression.getExpression());
|
|
2615
|
-
if (expression.isKind(SyntaxKind.BinaryExpression) && expression.getOperatorToken().isKind(SyntaxKind.CommaToken)) return this.unwrapped(expression.getRight());
|
|
2616
|
-
return expression;
|
|
2617
|
-
}
|
|
2618
|
-
isDeclaredInProject(expression) {
|
|
2619
|
-
const declaration = expression.getSymbol()?.getDeclarations()[0];
|
|
2620
|
-
return declaration !== void 0 && this.isInsideProject(normalize(declaration.getSourceFile().getFilePath()));
|
|
2621
|
-
}
|
|
2622
2787
|
reference(node, form, specifierNode, names) {
|
|
2623
2788
|
const isLiteral = specifierNode.isKind(SyntaxKind.StringLiteral) || specifierNode.isKind(SyntaxKind.NoSubstitutionTemplateLiteral);
|
|
2624
2789
|
return {
|
|
@@ -2693,6 +2858,97 @@ var DisableReader = class {
|
|
|
2693
2858
|
}
|
|
2694
2859
|
};
|
|
2695
2860
|
//#endregion
|
|
2861
|
+
//#region src/importer/ts-morph/readers/global-channel-reader.ts
|
|
2862
|
+
const globalObjects = [
|
|
2863
|
+
"globalThis",
|
|
2864
|
+
"global",
|
|
2865
|
+
"window",
|
|
2866
|
+
"self"
|
|
2867
|
+
];
|
|
2868
|
+
const assignments = [
|
|
2869
|
+
SyntaxKind.EqualsToken,
|
|
2870
|
+
SyntaxKind.QuestionQuestionEqualsToken,
|
|
2871
|
+
SyntaxKind.BarBarEqualsToken,
|
|
2872
|
+
SyntaxKind.AmpersandAmpersandEqualsToken,
|
|
2873
|
+
SyntaxKind.PlusEqualsToken
|
|
2874
|
+
];
|
|
2875
|
+
const reflectionWrites = [
|
|
2876
|
+
"set",
|
|
2877
|
+
"defineProperty",
|
|
2878
|
+
"deleteProperty"
|
|
2879
|
+
];
|
|
2880
|
+
const objectWrites = [
|
|
2881
|
+
"defineProperty",
|
|
2882
|
+
"defineProperties",
|
|
2883
|
+
"assign"
|
|
2884
|
+
];
|
|
2885
|
+
var GlobalChannelReader = class {
|
|
2886
|
+
read(file) {
|
|
2887
|
+
const channels = [];
|
|
2888
|
+
file.forEachDescendant((node) => {
|
|
2889
|
+
channels.push(...this.channelsAt(node));
|
|
2890
|
+
});
|
|
2891
|
+
return channels;
|
|
2892
|
+
}
|
|
2893
|
+
channelsAt(node) {
|
|
2894
|
+
if (Node.isPropertyAccessExpression(node)) return this.lookup(node, node.getExpression(), node.getName());
|
|
2895
|
+
if (Node.isElementAccessExpression(node)) {
|
|
2896
|
+
const key = node.getArgumentExpression();
|
|
2897
|
+
return key !== void 0 && Node.isStringLiteral(key) ? this.lookup(node, node.getExpression(), key.getLiteralValue()) : [];
|
|
2898
|
+
}
|
|
2899
|
+
if (Node.isCallExpression(node)) return this.reflected(node);
|
|
2900
|
+
return [];
|
|
2901
|
+
}
|
|
2902
|
+
lookup(access, object, name) {
|
|
2903
|
+
const global = this.globalObject(object);
|
|
2904
|
+
if (global === void 0 || global.getType().getProperty(name) !== void 0) return [];
|
|
2905
|
+
return [new GlobalChannel(access.getStartLineNumber(), `${global.getText()}.${name}`, this.accessOf(access))];
|
|
2906
|
+
}
|
|
2907
|
+
reflected(call) {
|
|
2908
|
+
const callee = call.getExpression();
|
|
2909
|
+
if (!Node.isPropertyAccessExpression(callee)) return [];
|
|
2910
|
+
const owner = callee.getExpression().getText();
|
|
2911
|
+
const method = callee.getName();
|
|
2912
|
+
const [target, key] = call.getArguments();
|
|
2913
|
+
const global = target === void 0 ? void 0 : this.globalObject(target);
|
|
2914
|
+
if (global === void 0) return [];
|
|
2915
|
+
if (owner === "Reflect" && key !== void 0 && Node.isStringLiteral(key)) {
|
|
2916
|
+
const access = reflectionWrites.includes(method) ? "writes" : "reads";
|
|
2917
|
+
return this.undeclared(global, [key.getLiteralValue()], call.getStartLineNumber(), access);
|
|
2918
|
+
}
|
|
2919
|
+
if (owner === "Object" && objectWrites.includes(method) && key !== void 0) {
|
|
2920
|
+
const names = Node.isStringLiteral(key) ? [key.getLiteralValue()] : this.propertyNames(key);
|
|
2921
|
+
return this.undeclared(global, names, call.getStartLineNumber(), "writes");
|
|
2922
|
+
}
|
|
2923
|
+
return [];
|
|
2924
|
+
}
|
|
2925
|
+
undeclared(global, names, line, access) {
|
|
2926
|
+
const type = global.getType();
|
|
2927
|
+
return names.filter((name) => type.getProperty(name) === void 0).map((name) => new GlobalChannel(line, `${global.getText()}.${name}`, access));
|
|
2928
|
+
}
|
|
2929
|
+
propertyNames(node) {
|
|
2930
|
+
if (!Node.isObjectLiteralExpression(node)) return [];
|
|
2931
|
+
const names = [];
|
|
2932
|
+
for (const property of node.getProperties()) if (Node.isPropertyAssignment(property) || Node.isShorthandPropertyAssignment(property) || Node.isMethodDeclaration(property)) names.push(property.getName());
|
|
2933
|
+
return names;
|
|
2934
|
+
}
|
|
2935
|
+
globalObject(node) {
|
|
2936
|
+
const bare = this.unwrapped(node);
|
|
2937
|
+
if (!Node.isIdentifier(bare) || !globalObjects.includes(bare.getText())) return;
|
|
2938
|
+
const declaration = bare.getSymbol()?.getDeclarations()[0];
|
|
2939
|
+
return declaration === void 0 || declaration.getSourceFile().isDeclarationFile() ? bare : void 0;
|
|
2940
|
+
}
|
|
2941
|
+
accessOf(access) {
|
|
2942
|
+
const parent = access.getParent();
|
|
2943
|
+
if (Node.isBinaryExpression(parent) && parent.getLeft() === access && assignments.includes(parent.getOperatorToken().getKind())) return "writes";
|
|
2944
|
+
return Node.isDeleteExpression(parent) ? "writes" : "reads";
|
|
2945
|
+
}
|
|
2946
|
+
unwrapped(node) {
|
|
2947
|
+
if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isNonNullExpression(node) || Node.isSatisfiesExpression(node)) return this.unwrapped(node.getExpression());
|
|
2948
|
+
return node;
|
|
2949
|
+
}
|
|
2950
|
+
};
|
|
2951
|
+
//#endregion
|
|
2696
2952
|
//#region src/importer/ts-morph/readers/global-reader.ts
|
|
2697
2953
|
const ecmaScriptLibrary = /^lib\.(es|decorators).*\.d\.ts$/;
|
|
2698
2954
|
var GlobalReader = class {
|
|
@@ -2764,6 +3020,70 @@ var GlobalReader = class {
|
|
|
2764
3020
|
}
|
|
2765
3021
|
};
|
|
2766
3022
|
//#endregion
|
|
3023
|
+
//#region src/importer/ts-morph/readers/module-reach-reader.ts
|
|
3024
|
+
const candidates = [
|
|
3025
|
+
SyntaxKind.Identifier,
|
|
3026
|
+
SyntaxKind.PropertyAccessExpression,
|
|
3027
|
+
SyntaxKind.ElementAccessExpression,
|
|
3028
|
+
SyntaxKind.CallExpression,
|
|
3029
|
+
SyntaxKind.NewExpression
|
|
3030
|
+
];
|
|
3031
|
+
var ModuleReachReader = class {
|
|
3032
|
+
types;
|
|
3033
|
+
scope;
|
|
3034
|
+
constructor(types, scope) {
|
|
3035
|
+
this.types = types;
|
|
3036
|
+
this.scope = scope;
|
|
3037
|
+
}
|
|
3038
|
+
read(file) {
|
|
3039
|
+
if (!this.scope.readsWiring(file.getFilePath())) return [];
|
|
3040
|
+
const reaches = [];
|
|
3041
|
+
file.forEachDescendant((node) => {
|
|
3042
|
+
const reach = this.reachAt(node, file);
|
|
3043
|
+
if (reach !== void 0) reaches.push(reach);
|
|
3044
|
+
});
|
|
3045
|
+
return reaches;
|
|
3046
|
+
}
|
|
3047
|
+
reachAt(node, file) {
|
|
3048
|
+
if (!candidates.includes(node.getKind()) || this.isName(node)) return;
|
|
3049
|
+
const type = node.getType();
|
|
3050
|
+
if (!type.isClass()) return;
|
|
3051
|
+
const module = this.types.classTypeOf(type);
|
|
3052
|
+
if (module.declaredIn === void 0 || module.declaredIn === file.getFilePath() || !this.scope.readsWiring(module.declaredIn)) return;
|
|
3053
|
+
const means = this.meansOf(node);
|
|
3054
|
+
return means === void 0 ? void 0 : new ModuleReach(node.getStartLineNumber(), node.getText(), means, module);
|
|
3055
|
+
}
|
|
3056
|
+
meansOf(node) {
|
|
3057
|
+
const { child, parent } = this.usageOf(node);
|
|
3058
|
+
if (parent === void 0) return;
|
|
3059
|
+
if (Node.isElementAccessExpression(parent) && parent.getExpression() === child) return "brackets";
|
|
3060
|
+
if (Node.isSpreadAssignment(parent) || Node.isSpreadElement(parent)) return "a spread";
|
|
3061
|
+
if (Node.isVariableDeclaration(parent) && !Node.isIdentifier(parent.getNameNode())) return "destructuring";
|
|
3062
|
+
if ((Node.isCallExpression(parent) || Node.isNewExpression(parent)) && parent.getArguments().includes(child)) return this.isModuleConstruction(parent) ? void 0 : parent.getExpression().getText();
|
|
3063
|
+
}
|
|
3064
|
+
usageOf(node) {
|
|
3065
|
+
let child = node;
|
|
3066
|
+
let parent = node.getParent();
|
|
3067
|
+
while (parent !== void 0 && (Node.isParenthesizedExpression(parent) || Node.isAsExpression(parent) || Node.isNonNullExpression(parent) || Node.isSatisfiesExpression(parent))) {
|
|
3068
|
+
child = parent;
|
|
3069
|
+
parent = parent.getParent();
|
|
3070
|
+
}
|
|
3071
|
+
return {
|
|
3072
|
+
child,
|
|
3073
|
+
parent
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
isModuleConstruction(call) {
|
|
3077
|
+
if (!Node.isNewExpression(call)) return false;
|
|
3078
|
+
const declaredIn = call.getType().getSymbol()?.getDeclarations()[0]?.getSourceFile().getFilePath();
|
|
3079
|
+
return declaredIn !== void 0 && this.scope.readsWiring(declaredIn);
|
|
3080
|
+
}
|
|
3081
|
+
isName(node) {
|
|
3082
|
+
const parent = node.getParent();
|
|
3083
|
+
return parent !== void 0 && Node.hasName(parent) && parent.getNameNode() === node;
|
|
3084
|
+
}
|
|
3085
|
+
};
|
|
3086
|
+
//#endregion
|
|
2767
3087
|
//#region src/importer/ts-morph/readers/statement-reader.ts
|
|
2768
3088
|
const declarative = /* @__PURE__ */ new Set([
|
|
2769
3089
|
SyntaxKind.ImportDeclaration,
|
|
@@ -2859,6 +3179,11 @@ const collections = [
|
|
|
2859
3179
|
"WeakMap",
|
|
2860
3180
|
"WeakSet"
|
|
2861
3181
|
];
|
|
3182
|
+
const readonlyCollections = [
|
|
3183
|
+
"ReadonlyMap",
|
|
3184
|
+
"ReadonlySet",
|
|
3185
|
+
"ReadonlyArray"
|
|
3186
|
+
];
|
|
2862
3187
|
var TypeReader = class {
|
|
2863
3188
|
packageNames;
|
|
2864
3189
|
constructor(packageNames) {
|
|
@@ -2887,6 +3212,18 @@ var TypeReader = class {
|
|
|
2887
3212
|
if (type.getStringIndexType() !== void 0 || type.getNumberIndexType() !== void 0) return true;
|
|
2888
3213
|
return type.isAnonymous() && type.getCallSignatures().length === 0 && type.getConstructSignatures().length === 0;
|
|
2889
3214
|
}
|
|
3215
|
+
opaqueValueIn(type) {
|
|
3216
|
+
return this.findsOpaqueValue(type, /* @__PURE__ */ new Set());
|
|
3217
|
+
}
|
|
3218
|
+
holdsFunction(type) {
|
|
3219
|
+
return this.findsFunction(type, /* @__PURE__ */ new Set());
|
|
3220
|
+
}
|
|
3221
|
+
erasedNameOf(type) {
|
|
3222
|
+
const settled = this.settled(type);
|
|
3223
|
+
if (settled.isAny()) return "any";
|
|
3224
|
+
if (settled.isUnknown()) return "unknown";
|
|
3225
|
+
return (settled.getFlags() & ts.TypeFlags.NonPrimitive) === 0 ? void 0 : "object";
|
|
3226
|
+
}
|
|
2890
3227
|
returnShapeOf(type) {
|
|
2891
3228
|
if (type.getSymbol()?.getName() === "Promise") {
|
|
2892
3229
|
const [inner] = type.getTypeArguments();
|
|
@@ -2899,6 +3236,52 @@ var TypeReader = class {
|
|
|
2899
3236
|
union: members.map((member) => this.namedTypeOf(member))
|
|
2900
3237
|
};
|
|
2901
3238
|
}
|
|
3239
|
+
findsOpaqueValue(type, seen) {
|
|
3240
|
+
if (seen.has(type.compilerType)) return;
|
|
3241
|
+
seen.add(type.compilerType);
|
|
3242
|
+
if (type.isAny() || type.isUnknown()) return type.getText();
|
|
3243
|
+
if (type.isUnion()) return this.firstOpaque(type.getUnionTypes(), seen);
|
|
3244
|
+
if (type.isIntersection()) return this.firstOpaque(type.getIntersectionTypes(), seen);
|
|
3245
|
+
if (!type.isObject() || type.isClass()) return;
|
|
3246
|
+
if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) return "a function";
|
|
3247
|
+
if (type.isArray() || type.isTuple()) {
|
|
3248
|
+
if (!type.isReadonlyArray()) return "a mutable array";
|
|
3249
|
+
return this.firstOpaque(type.isTuple() ? type.getTupleElements() : type.getTypeArguments(), seen);
|
|
3250
|
+
}
|
|
3251
|
+
if (readonlyCollections.includes(type.getSymbol()?.getName() ?? "")) return this.firstOpaque(type.getTypeArguments(), seen);
|
|
3252
|
+
return "an object";
|
|
3253
|
+
}
|
|
3254
|
+
firstOpaque(types, seen) {
|
|
3255
|
+
for (const inner of types) {
|
|
3256
|
+
const opaque = this.findsOpaqueValue(inner, seen);
|
|
3257
|
+
if (opaque !== void 0) return opaque;
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
findsFunction(type, seen) {
|
|
3261
|
+
if (seen.has(type.compilerType)) return false;
|
|
3262
|
+
seen.add(type.compilerType);
|
|
3263
|
+
if (type.isUnion()) return type.getUnionTypes().some((member) => this.findsFunction(member, seen));
|
|
3264
|
+
if (type.isIntersection()) return type.getIntersectionTypes().some((member) => this.findsFunction(member, seen));
|
|
3265
|
+
if (type.isClass()) return false;
|
|
3266
|
+
if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) return true;
|
|
3267
|
+
return this.dataTypesOf(type).some((inner) => this.findsFunction(inner, seen));
|
|
3268
|
+
}
|
|
3269
|
+
dataTypesOf(type) {
|
|
3270
|
+
const inner = [
|
|
3271
|
+
...type.getTypeArguments(),
|
|
3272
|
+
...type.getAliasTypeArguments(),
|
|
3273
|
+
...type.getTupleElements()
|
|
3274
|
+
];
|
|
3275
|
+
if (this.isDeclaredByProject(type)) for (const property of type.getProperties()) {
|
|
3276
|
+
const declaration = property.getDeclarations()[0];
|
|
3277
|
+
if (declaration !== void 0) inner.push(declaration.getType());
|
|
3278
|
+
}
|
|
3279
|
+
return inner;
|
|
3280
|
+
}
|
|
3281
|
+
settled(type) {
|
|
3282
|
+
const [inner] = type.getTypeArguments();
|
|
3283
|
+
return type.getSymbol()?.getName() === "Promise" && inner !== void 0 ? this.settled(inner) : type;
|
|
3284
|
+
}
|
|
2902
3285
|
lineageOf(type) {
|
|
2903
3286
|
const classType = type.getTargetType() ?? type;
|
|
2904
3287
|
const symbol = classType.getSymbol();
|
|
@@ -3038,6 +3421,7 @@ var TsMorphImporter = class TsMorphImporter extends Importer {
|
|
|
3038
3421
|
statements = new StatementReader();
|
|
3039
3422
|
disables = new DisableReader();
|
|
3040
3423
|
throws = new ThrowReader();
|
|
3424
|
+
globalChannels = new GlobalChannelReader();
|
|
3041
3425
|
constructor(sources) {
|
|
3042
3426
|
super();
|
|
3043
3427
|
this.sources = sources;
|
|
@@ -3055,18 +3439,27 @@ var TsMorphImporter = class TsMorphImporter extends Importer {
|
|
|
3055
3439
|
read(scope) {
|
|
3056
3440
|
const dependencies = new DependencyReader(this.sources, scope);
|
|
3057
3441
|
const wirings = new WiringReader(this.types, scope);
|
|
3442
|
+
const reaches = new ModuleReachReader(this.types, scope);
|
|
3058
3443
|
const globals = new GlobalReader(scope.projectDir);
|
|
3059
3444
|
const files = [];
|
|
3060
|
-
for (const file of this.sources.getSourceFiles()) if (this.isInside(scope.rootDir, file.getFilePath()) && !scope.isIgnored(file.getFilePath())) files.push(this.readFile(file,
|
|
3445
|
+
for (const file of this.sources.getSourceFiles()) if (this.isInside(scope.rootDir, file.getFilePath()) && !scope.isIgnored(file.getFilePath())) files.push(this.readFile(file, {
|
|
3446
|
+
dependencies,
|
|
3447
|
+
globals,
|
|
3448
|
+
reaches,
|
|
3449
|
+
wirings
|
|
3450
|
+
}));
|
|
3061
3451
|
return new Project$1(scope.projectDir, files);
|
|
3062
3452
|
}
|
|
3063
|
-
readFile(file,
|
|
3453
|
+
readFile(file, readers) {
|
|
3454
|
+
const { dependencies, globals, reaches, wirings } = readers;
|
|
3064
3455
|
const globalReferences = globals.read(file);
|
|
3065
3456
|
return new SourceFile({
|
|
3066
3457
|
classes: file.getClasses().map((declaration) => this.classes.read(declaration)),
|
|
3067
3458
|
dependencies: dependencies.read(file, globalReferences),
|
|
3068
3459
|
disables: this.disables.read(file),
|
|
3460
|
+
globalChannels: this.globalChannels.read(file),
|
|
3069
3461
|
globals: this.globalUsesOf(globalReferences),
|
|
3462
|
+
moduleReaches: reaches.read(file),
|
|
3070
3463
|
path: normalize(file.getFilePath()),
|
|
3071
3464
|
statements: this.statements.read(file),
|
|
3072
3465
|
text: file.getFullText(),
|
|
@@ -3366,4 +3759,4 @@ var Docs = class Docs {
|
|
|
3366
3759
|
//#endregion
|
|
3367
3760
|
export { TsMorphImporter as a, Config as c, RuleRegistry as d, Rule as f, Baseline as h, Init as i, Report as l, AllowedPackages as m, Page as n, Importer as o, Architecture as p, Cli as r, ConfigLoader as s, Docs as t, Checker as u };
|
|
3368
3761
|
|
|
3369
|
-
//# sourceMappingURL=docs-
|
|
3762
|
+
//# sourceMappingURL=docs-B6M9DxTM.mjs.map
|