@suss/extractor 0.25.0 → 0.27.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/index.cjs +95 -48
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +94 -48
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
assembleSummary: () => assembleSummary,
|
|
44
44
|
assessConfidence: () => assessConfidence,
|
|
45
45
|
buildUngatedExtractionReport: () => buildUngatedExtractionReport,
|
|
46
|
+
commonDirectoryOf: () => commonDirectoryOf,
|
|
46
47
|
composeWrappers: () => composeWrappers,
|
|
47
48
|
computeContentHash: () => computeContentHash,
|
|
48
49
|
computeDistHashFrom: () => computeDistHashFrom,
|
|
@@ -295,8 +296,8 @@ var catchEntryCond = () => fixedCond(
|
|
|
295
296
|
"positive",
|
|
296
297
|
"catchBlock"
|
|
297
298
|
);
|
|
298
|
-
function classify(
|
|
299
|
-
return
|
|
299
|
+
function classify(path4, home, isAncestorOrSelf) {
|
|
300
|
+
return path4.map((cond) => {
|
|
300
301
|
if (cond.branchStmt === null) {
|
|
301
302
|
return cond.info;
|
|
302
303
|
}
|
|
@@ -361,9 +362,9 @@ function chargeBudget(state) {
|
|
|
361
362
|
);
|
|
362
363
|
}
|
|
363
364
|
}
|
|
364
|
-
function recordTerminal(ctx, terminal, home,
|
|
365
|
+
function recordTerminal(ctx, terminal, home, path4) {
|
|
365
366
|
chargeBudget(ctx.state);
|
|
366
|
-
const info = classify(
|
|
367
|
+
const info = classify(path4, home, ctx.isAncestorOrSelf);
|
|
367
368
|
const existing = ctx.state.byTerminal.get(terminal) ?? [];
|
|
368
369
|
existing.push(info);
|
|
369
370
|
ctx.state.byTerminal.set(terminal, existing);
|
|
@@ -374,15 +375,15 @@ function containsTerminal(ctx, stmt) {
|
|
|
374
375
|
}
|
|
375
376
|
return childrenOf(stmt).some((child) => containsTerminal(ctx, child));
|
|
376
377
|
}
|
|
377
|
-
function stepIf(stmt,
|
|
378
|
+
function stepIf(stmt, path4, ctx) {
|
|
378
379
|
const thenExit = exitKindOfList(stmt.thenBody);
|
|
379
380
|
const elseExit = stmt.elseBody === null ? null : exitKindOfList(stmt.elseBody);
|
|
380
381
|
const thenPath = [
|
|
381
|
-
...
|
|
382
|
+
...path4,
|
|
382
383
|
branchCond(stmt, stmt.condition, "positive", elseExit)
|
|
383
384
|
];
|
|
384
385
|
const elsePath = [
|
|
385
|
-
...
|
|
386
|
+
...path4,
|
|
386
387
|
branchCond(
|
|
387
388
|
stmt,
|
|
388
389
|
stmt.condition,
|
|
@@ -399,7 +400,7 @@ function stepIf(stmt, path3, ctx) {
|
|
|
399
400
|
}
|
|
400
401
|
return out;
|
|
401
402
|
}
|
|
402
|
-
function stepSwitch(stmt,
|
|
403
|
+
function stepSwitch(stmt, path4, ctx) {
|
|
403
404
|
const out = [];
|
|
404
405
|
const negations = [];
|
|
405
406
|
let defaultRanBody = false;
|
|
@@ -409,7 +410,7 @@ function stepSwitch(stmt, path3, ctx) {
|
|
|
409
410
|
if (hasStrayBreak(group.body)) {
|
|
410
411
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
411
412
|
}
|
|
412
|
-
const groupPath = group.condition === null ? [...
|
|
413
|
+
const groupPath = group.condition === null ? [...path4, ...negations] : [...path4, fixedCond(group.condition, "positive", "explicit")];
|
|
413
414
|
const conts = enumerate(ctx, group.body, groupPath);
|
|
414
415
|
if (conts.length > 0) {
|
|
415
416
|
if (!group.hasTrailingBreak && !fallthroughSafe) {
|
|
@@ -426,24 +427,24 @@ function stepSwitch(stmt, path3, ctx) {
|
|
|
426
427
|
}
|
|
427
428
|
}
|
|
428
429
|
if (!defaultRanBody) {
|
|
429
|
-
out.push([...
|
|
430
|
+
out.push([...path4, ...negations]);
|
|
430
431
|
}
|
|
431
432
|
return out;
|
|
432
433
|
}
|
|
433
|
-
function stepLoop(stmt,
|
|
434
|
+
function stepLoop(stmt, path4, ctx) {
|
|
434
435
|
const bodyExit = exitKindOfList(stmt.body);
|
|
435
436
|
if (containsTerminal(ctx, stmt)) {
|
|
436
437
|
enumerate(ctx, stmt.body, [
|
|
437
|
-
...
|
|
438
|
+
...path4,
|
|
438
439
|
loopIterationCond(stmt.condition.sourceText)
|
|
439
440
|
]);
|
|
440
441
|
}
|
|
441
442
|
if (bodyExit !== null) {
|
|
442
|
-
return [[...
|
|
443
|
+
return [[...path4, loopCompletedCond(stmt.condition.sourceText, bodyExit)]];
|
|
443
444
|
}
|
|
444
|
-
return [
|
|
445
|
+
return [path4];
|
|
445
446
|
}
|
|
446
|
-
function stepTry(stmt,
|
|
447
|
+
function stepTry(stmt, path4, ctx) {
|
|
447
448
|
if (stmt.finallyBody !== null) {
|
|
448
449
|
const finallyHasTerminal = stmt.finallyBody.some(
|
|
449
450
|
(s) => containsTerminal(ctx, s)
|
|
@@ -453,22 +454,22 @@ function stepTry(stmt, path3, ctx) {
|
|
|
453
454
|
}
|
|
454
455
|
}
|
|
455
456
|
const out = [];
|
|
456
|
-
out.push(...enumerate(ctx, stmt.tryBody,
|
|
457
|
+
out.push(...enumerate(ctx, stmt.tryBody, path4));
|
|
457
458
|
if (stmt.catchBody !== null) {
|
|
458
|
-
const catchPath = [...
|
|
459
|
+
const catchPath = [...path4, catchEntryCond()];
|
|
459
460
|
out.push(...enumerate(ctx, stmt.catchBody, catchPath));
|
|
460
461
|
}
|
|
461
462
|
return out;
|
|
462
463
|
}
|
|
463
|
-
function stepExit(stmt,
|
|
464
|
+
function stepExit(stmt, path4, ctx) {
|
|
464
465
|
const collector = ctx.state.callbackExits[ctx.state.callbackExits.length - 1];
|
|
465
466
|
if (collector !== void 0 && (stmt.exit === "return" || stmt.exit === "throw")) {
|
|
466
|
-
collector.push(
|
|
467
|
+
collector.push(path4);
|
|
467
468
|
}
|
|
468
469
|
return [];
|
|
469
470
|
}
|
|
470
|
-
function stepOpaque(_stmt,
|
|
471
|
-
return [
|
|
471
|
+
function stepOpaque(_stmt, path4, _ctx) {
|
|
472
|
+
return [path4];
|
|
472
473
|
}
|
|
473
474
|
var stepHandlers = {
|
|
474
475
|
if: stepIf,
|
|
@@ -478,20 +479,20 @@ var stepHandlers = {
|
|
|
478
479
|
exit: stepExit,
|
|
479
480
|
opaque: stepOpaque
|
|
480
481
|
};
|
|
481
|
-
function stepCallback(ctx, body,
|
|
482
|
+
function stepCallback(ctx, body, path4) {
|
|
482
483
|
const exits = [];
|
|
483
484
|
ctx.state.callbackExits.push(exits);
|
|
484
485
|
let fellThrough;
|
|
485
486
|
try {
|
|
486
|
-
fellThrough = enumerate(ctx, body,
|
|
487
|
+
fellThrough = enumerate(ctx, body, path4);
|
|
487
488
|
} finally {
|
|
488
489
|
ctx.state.callbackExits.pop();
|
|
489
490
|
}
|
|
490
491
|
const out = [...fellThrough, ...exits];
|
|
491
|
-
return out.length === 0 ? [
|
|
492
|
+
return out.length === 0 ? [path4] : out;
|
|
492
493
|
}
|
|
493
|
-
function stepStatement(ctx, stmt,
|
|
494
|
-
let paths = [
|
|
494
|
+
function stepStatement(ctx, stmt, path4) {
|
|
495
|
+
let paths = [path4];
|
|
495
496
|
for (const body of stmt.callbacks ?? []) {
|
|
496
497
|
paths = paths.flatMap((each) => stepCallback(ctx, body, each));
|
|
497
498
|
}
|
|
@@ -572,8 +573,8 @@ function enumerate(ctx, stmts, prefix) {
|
|
|
572
573
|
let frontiers = [[...prefix]];
|
|
573
574
|
for (const stmt of stmts) {
|
|
574
575
|
const nextFrontiers = [];
|
|
575
|
-
for (const
|
|
576
|
-
nextFrontiers.push(...stepStatement(ctx, stmt,
|
|
576
|
+
for (const path4 of mergeRejoined(frontiers)) {
|
|
577
|
+
nextFrontiers.push(...stepStatement(ctx, stmt, path4));
|
|
577
578
|
}
|
|
578
579
|
frontiers = nextFrontiers;
|
|
579
580
|
if (frontiers.length > MAX_PATHS) {
|
|
@@ -624,9 +625,9 @@ function enumerateStructuredPaths(input) {
|
|
|
624
625
|
isAncestorOrSelf
|
|
625
626
|
};
|
|
626
627
|
const continuations = withRejoined(enumerate(ctx, input.statements, []));
|
|
627
|
-
for (const
|
|
628
|
+
for (const path4 of continuations) {
|
|
628
629
|
chargeBudget(state);
|
|
629
|
-
state.fallthrough.push(classify(
|
|
630
|
+
state.fallthrough.push(classify(path4, null, isAncestorOrSelf));
|
|
630
631
|
}
|
|
631
632
|
return { byTerminal: state.byTerminal, fallthrough: state.fallthrough };
|
|
632
633
|
}
|
|
@@ -672,9 +673,12 @@ function composeWrappers(summaries, options = {}) {
|
|
|
672
673
|
const byKey = /* @__PURE__ */ new Map();
|
|
673
674
|
for (const summary of summaries) {
|
|
674
675
|
const key = summaryKey(summary.location.file, summary.identity.name);
|
|
675
|
-
|
|
676
|
-
|
|
676
|
+
const sharing = byKey.get(key);
|
|
677
|
+
if (sharing === void 0) {
|
|
678
|
+
byKey.set(key, [summary]);
|
|
679
|
+
continue;
|
|
677
680
|
}
|
|
681
|
+
sharing.push(summary);
|
|
678
682
|
}
|
|
679
683
|
const keepGaps = options.gapHandling !== "silent";
|
|
680
684
|
return summaries.map((summary) => composeOne(summary, byKey, keepGaps));
|
|
@@ -682,6 +686,13 @@ function composeWrappers(summaries, options = {}) {
|
|
|
682
686
|
function summaryKey(file, name) {
|
|
683
687
|
return `${file}::${name}`;
|
|
684
688
|
}
|
|
689
|
+
function summaryOf(reference, byKey) {
|
|
690
|
+
const sharing = byKey.get(summaryKey(reference.file, reference.name)) ?? [];
|
|
691
|
+
if (reference.line === void 0) {
|
|
692
|
+
return sharing[0];
|
|
693
|
+
}
|
|
694
|
+
return sharing.find((one) => one.location.range.start === reference.line) ?? sharing[0];
|
|
695
|
+
}
|
|
685
696
|
function composeOne(summary, byKey, keepGaps) {
|
|
686
697
|
const recorded = (0, import_behavioral_ir3.readWrapperMetadata)(summary);
|
|
687
698
|
const applied = recorded?.applied ?? [];
|
|
@@ -695,7 +706,7 @@ function composeOne(summary, byKey, keepGaps) {
|
|
|
695
706
|
})
|
|
696
707
|
};
|
|
697
708
|
const wrappers = covering.flatMap((reference) => {
|
|
698
|
-
const found =
|
|
709
|
+
const found = summaryOf(reference, byKey);
|
|
699
710
|
return found === void 0 ? [] : [{ reference, summary: found }];
|
|
700
711
|
});
|
|
701
712
|
if (wrappers.length === 0) {
|
|
@@ -775,8 +786,8 @@ function applyWrapper(wrapper, inner) {
|
|
|
775
786
|
wrapper.summary.transitions.filter((t) => t.output.type !== "delegate"),
|
|
776
787
|
wrapper.reference
|
|
777
788
|
);
|
|
778
|
-
const passThroughs =
|
|
779
|
-
(t) => t.output.type === "delegate"
|
|
789
|
+
const passThroughs = withoutCoveredPassThroughs(
|
|
790
|
+
wrapper.summary.transitions.filter((t) => t.output.type === "delegate")
|
|
780
791
|
);
|
|
781
792
|
if (passThroughs.length === 0 || shortCircuits.length + passThroughs.length * inner.transitions.length > MAX_PATHS) {
|
|
782
793
|
return {
|
|
@@ -789,6 +800,20 @@ function applyWrapper(wrapper, inner) {
|
|
|
789
800
|
);
|
|
790
801
|
return { transitions: [...shortCircuits, ...continued], degraded: false };
|
|
791
802
|
}
|
|
803
|
+
function withoutCoveredPassThroughs(passThroughs) {
|
|
804
|
+
return passThroughs.filter(
|
|
805
|
+
(candidate, i) => !passThroughs.some(
|
|
806
|
+
(other, j) => j !== i && covers(other, candidate) && (j < i || !covers(candidate, other))
|
|
807
|
+
)
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
function covers(wider, narrower) {
|
|
811
|
+
if (JSON.stringify(wider.effects) !== JSON.stringify(narrower.effects)) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
const required = new Set(narrower.conditions.map((c) => JSON.stringify(c)));
|
|
815
|
+
return wider.conditions.every((c) => required.has(JSON.stringify(c)));
|
|
816
|
+
}
|
|
792
817
|
function applyThrowWrapper(wrapper, inner) {
|
|
793
818
|
const thrown = inner.transitions.filter((t) => t.output.type === "throw");
|
|
794
819
|
if (thrown.length === 0) {
|
|
@@ -1114,8 +1139,8 @@ function sharedGatingConditions(paths, readPredicate) {
|
|
|
1114
1139
|
return [];
|
|
1115
1140
|
}
|
|
1116
1141
|
const shared = new Set(first.map(keyOf2));
|
|
1117
|
-
for (const
|
|
1118
|
-
const here = new Set(
|
|
1142
|
+
for (const path4 of rest) {
|
|
1143
|
+
const here = new Set(path4.map(keyOf2));
|
|
1119
1144
|
for (const value of shared) {
|
|
1120
1145
|
if (!here.has(value)) {
|
|
1121
1146
|
shared.delete(value);
|
|
@@ -1191,6 +1216,27 @@ function walkDescendants(root, carried, visitor) {
|
|
|
1191
1216
|
}
|
|
1192
1217
|
}
|
|
1193
1218
|
|
|
1219
|
+
// src/projectRoot.ts
|
|
1220
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
1221
|
+
function commonDirectoryOf(files) {
|
|
1222
|
+
const absolute = files.filter((f) => import_node_path.default.isAbsolute(f));
|
|
1223
|
+
const first = absolute[0];
|
|
1224
|
+
if (first === void 0) {
|
|
1225
|
+
return void 0;
|
|
1226
|
+
}
|
|
1227
|
+
let shared = import_node_path.default.dirname(first).split(import_node_path.default.sep);
|
|
1228
|
+
for (const file of absolute.slice(1)) {
|
|
1229
|
+
const parts = import_node_path.default.dirname(file).split(import_node_path.default.sep);
|
|
1230
|
+
let i = 0;
|
|
1231
|
+
while (i < shared.length && i < parts.length && shared[i] === parts[i]) {
|
|
1232
|
+
i += 1;
|
|
1233
|
+
}
|
|
1234
|
+
shared = shared.slice(0, i);
|
|
1235
|
+
}
|
|
1236
|
+
const joined = shared.join(import_node_path.default.sep);
|
|
1237
|
+
return joined.length > 1 ? joined : void 0;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1194
1240
|
// src/reading.ts
|
|
1195
1241
|
function writtenReading(value, range) {
|
|
1196
1242
|
return { kind: "written", value, range };
|
|
@@ -1248,7 +1294,7 @@ function valueToReadFurtherFrom(reading) {
|
|
|
1248
1294
|
var import_node_crypto = require("crypto");
|
|
1249
1295
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
1250
1296
|
var import_node_module = require("module");
|
|
1251
|
-
var
|
|
1297
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
1252
1298
|
var import_node_url = require("url");
|
|
1253
1299
|
var import_meta = {};
|
|
1254
1300
|
var ANALYSIS_PACKAGES = [
|
|
@@ -1291,14 +1337,14 @@ function createAdapterStamp(config) {
|
|
|
1291
1337
|
function readAdapterCodeStamp(moduleUrl) {
|
|
1292
1338
|
try {
|
|
1293
1339
|
const selfPath = (0, import_node_url.fileURLToPath)(moduleUrl);
|
|
1294
|
-
const hash = computeDistHashFrom(
|
|
1340
|
+
const hash = computeDistHashFrom(import_node_path2.default.dirname(selfPath));
|
|
1295
1341
|
return hash.length > 0 ? { kind: "bundle", hash } : SOURCE_STAMP;
|
|
1296
1342
|
} catch {
|
|
1297
1343
|
return SOURCE_STAMP;
|
|
1298
1344
|
}
|
|
1299
1345
|
}
|
|
1300
1346
|
function computeDistHashFrom(dir) {
|
|
1301
|
-
const candidates = [
|
|
1347
|
+
const candidates = [import_node_path2.default.join(dir, "index.js"), import_node_path2.default.join(dir, "index.cjs")];
|
|
1302
1348
|
for (const candidate of candidates) {
|
|
1303
1349
|
if (!import_node_fs.default.existsSync(candidate)) {
|
|
1304
1350
|
continue;
|
|
@@ -1356,7 +1402,7 @@ function analysisBundles() {
|
|
|
1356
1402
|
// src/cache.ts
|
|
1357
1403
|
var import_node_crypto2 = require("crypto");
|
|
1358
1404
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
1359
|
-
var
|
|
1405
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
1360
1406
|
var SCHEMA_VERSION = "7";
|
|
1361
1407
|
var MAX_ENTRIES = 2;
|
|
1362
1408
|
var ENTRY_PREFIX = "key-";
|
|
@@ -1382,7 +1428,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1382
1428
|
async lookup(input) {
|
|
1383
1429
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1384
1430
|
const manifest = await readManifest(
|
|
1385
|
-
|
|
1431
|
+
import_node_path3.default.join(entryDir, "manifest.json")
|
|
1386
1432
|
);
|
|
1387
1433
|
if (manifest === null) {
|
|
1388
1434
|
return missDiag(await describeAbsentEntry(cacheDir));
|
|
@@ -1405,7 +1451,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1405
1451
|
async plan(input) {
|
|
1406
1452
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1407
1453
|
const manifest = await readManifest(
|
|
1408
|
-
|
|
1454
|
+
import_node_path3.default.join(entryDir, "manifest.json")
|
|
1409
1455
|
);
|
|
1410
1456
|
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
1411
1457
|
return null;
|
|
@@ -1420,7 +1466,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1420
1466
|
async write(input, summaries, attribution) {
|
|
1421
1467
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1422
1468
|
const previous = await readManifest(
|
|
1423
|
-
|
|
1469
|
+
import_node_path3.default.join(entryDir, "manifest.json")
|
|
1424
1470
|
);
|
|
1425
1471
|
const configStamp = await stampConfigFile(input.configPath);
|
|
1426
1472
|
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
@@ -1434,7 +1480,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1434
1480
|
};
|
|
1435
1481
|
await import_promises.default.mkdir(entryDir, { recursive: true });
|
|
1436
1482
|
await import_promises.default.writeFile(
|
|
1437
|
-
|
|
1483
|
+
import_node_path3.default.join(entryDir, "manifest.json"),
|
|
1438
1484
|
JSON.stringify(manifest)
|
|
1439
1485
|
);
|
|
1440
1486
|
await evictOldEntries(cacheDir, entryDir);
|
|
@@ -1613,7 +1659,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
1613
1659
|
input.configPath ?? ""
|
|
1614
1660
|
].join(" ");
|
|
1615
1661
|
const name = (0, import_node_crypto2.createHash)("sha256").update(key).digest("hex").slice(0, 16);
|
|
1616
|
-
return
|
|
1662
|
+
return import_node_path3.default.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
1617
1663
|
}
|
|
1618
1664
|
function isEntryDir(name) {
|
|
1619
1665
|
return ENTRY_DIR_NAME.test(name);
|
|
@@ -1627,11 +1673,11 @@ async function markUsed(entryDir) {
|
|
|
1627
1673
|
}
|
|
1628
1674
|
async function evictOldEntries(cacheDir, keepDir) {
|
|
1629
1675
|
try {
|
|
1630
|
-
await import_promises.default.rm(
|
|
1676
|
+
await import_promises.default.rm(import_node_path3.default.join(cacheDir, "manifest.json"), { force: true });
|
|
1631
1677
|
const entries = await import_promises.default.readdir(cacheDir, { withFileTypes: true });
|
|
1632
1678
|
const dirs = await Promise.all(
|
|
1633
1679
|
entries.filter((e) => e.isDirectory() && isEntryDir(e.name)).map(async (e) => {
|
|
1634
|
-
const dir =
|
|
1680
|
+
const dir = import_node_path3.default.join(cacheDir, e.name);
|
|
1635
1681
|
const stat = await import_promises.default.stat(dir);
|
|
1636
1682
|
return { dir, mtimeMs: stat.mtimeMs };
|
|
1637
1683
|
})
|
|
@@ -2458,6 +2504,7 @@ function paramToInput(param) {
|
|
|
2458
2504
|
assembleSummary,
|
|
2459
2505
|
assessConfidence,
|
|
2460
2506
|
buildUngatedExtractionReport,
|
|
2507
|
+
commonDirectoryOf,
|
|
2461
2508
|
composeWrappers,
|
|
2462
2509
|
computeContentHash,
|
|
2463
2510
|
computeDistHashFrom,
|
package/dist/index.d.cts
CHANGED
|
@@ -173,6 +173,12 @@ type DiscoveryMatch = {
|
|
|
173
173
|
* `axios.get(...)`.
|
|
174
174
|
*/
|
|
175
175
|
factoryMethods?: string[];
|
|
176
|
+
/**
|
|
177
|
+
* The import and every instance built from it can be called as a
|
|
178
|
+
* function, so `axios(config)` and `api(config)` are requests the
|
|
179
|
+
* same as a call through a method in `methodFilter`.
|
|
180
|
+
*/
|
|
181
|
+
callable?: boolean;
|
|
176
182
|
} | {
|
|
177
183
|
/**
|
|
178
184
|
* A constructor or factory call that takes a configuration object
|
|
@@ -2272,6 +2278,16 @@ interface NodeVisitor<T, C> {
|
|
|
2272
2278
|
*/
|
|
2273
2279
|
declare function walkDescendants<T extends WalkableNode<T>, C>(root: T, carried: C, visitor: NodeVisitor<T, C>): void;
|
|
2274
2280
|
|
|
2281
|
+
/**
|
|
2282
|
+
* The project root when nothing declares one.
|
|
2283
|
+
*
|
|
2284
|
+
* Resolution from anywhere inside a tree finds the same `node_modules`,
|
|
2285
|
+
* and a recursive reader pointed at the directory every file shares
|
|
2286
|
+
* reaches all of them, so the deepest common directory serves both.
|
|
2287
|
+
*/
|
|
2288
|
+
/** The deepest directory containing every file, or undefined when they share no absolute root. */
|
|
2289
|
+
declare function commonDirectoryOf(files: ReadonlyArray<string>): string | undefined;
|
|
2290
|
+
|
|
2275
2291
|
/**
|
|
2276
2292
|
* The small surface every language adapter implements, whatever that
|
|
2277
2293
|
* language's own tooling looks like underneath.
|
|
@@ -3434,4 +3450,4 @@ declare function rawConditionToPredicate(c: RawCondition): Predicate;
|
|
|
3434
3450
|
declare function effectToIR(effect: RawEffect): Effect;
|
|
3435
3451
|
declare function paramToInput(param: RawParameter): Input;
|
|
3436
3452
|
|
|
3437
|
-
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, type ExitKind, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_PATHS, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, SKIP_CHILDREN, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type Timer, type TimingReport, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type WalkableNode, type WrapperMethodRegistration, type WrapperOptionRegistration, type WrapperRegistration, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, buildUngatedExtractionReport, composeWrappers, computeContentHash, computeDistHashFrom, configuredCallOption, createAdapterStamp, createCacheLayer, createPackTallies, createTimer, detectGaps, effectToIR, emptyTally, enumerateOrDegrade, enumerateStructuredPaths, evaluatePackHealth, firstWrittenReading, formatPackHealth, guardsHoldOn, httpRouteDiscovery, makeTransitionId, mapReading, moduleInitStructure, noopTimer, packGradients, paramToInput, projectFileStamp, rawConditionToPredicate, recordPackFailure, registrationHelperDiscovery, routeHelperIndex, runDigest, runsBefore, scopeOption, sharedGatingConditions, stampModuleImports, storageSystemOption, summaryCountsByPack, tallyUnit, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, walkDescendants, wrapperDiscovery, writtenReading };
|
|
3453
|
+
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, type ExitKind, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_PATHS, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, SKIP_CHILDREN, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type Timer, type TimingReport, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type WalkableNode, type WrapperMethodRegistration, type WrapperOptionRegistration, type WrapperRegistration, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, buildUngatedExtractionReport, commonDirectoryOf, composeWrappers, computeContentHash, computeDistHashFrom, configuredCallOption, createAdapterStamp, createCacheLayer, createPackTallies, createTimer, detectGaps, effectToIR, emptyTally, enumerateOrDegrade, enumerateStructuredPaths, evaluatePackHealth, firstWrittenReading, formatPackHealth, guardsHoldOn, httpRouteDiscovery, makeTransitionId, mapReading, moduleInitStructure, noopTimer, packGradients, paramToInput, projectFileStamp, rawConditionToPredicate, recordPackFailure, registrationHelperDiscovery, routeHelperIndex, runDigest, runsBefore, scopeOption, sharedGatingConditions, stampModuleImports, storageSystemOption, summaryCountsByPack, tallyUnit, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, walkDescendants, wrapperDiscovery, writtenReading };
|
package/dist/index.d.ts
CHANGED
|
@@ -173,6 +173,12 @@ type DiscoveryMatch = {
|
|
|
173
173
|
* `axios.get(...)`.
|
|
174
174
|
*/
|
|
175
175
|
factoryMethods?: string[];
|
|
176
|
+
/**
|
|
177
|
+
* The import and every instance built from it can be called as a
|
|
178
|
+
* function, so `axios(config)` and `api(config)` are requests the
|
|
179
|
+
* same as a call through a method in `methodFilter`.
|
|
180
|
+
*/
|
|
181
|
+
callable?: boolean;
|
|
176
182
|
} | {
|
|
177
183
|
/**
|
|
178
184
|
* A constructor or factory call that takes a configuration object
|
|
@@ -2272,6 +2278,16 @@ interface NodeVisitor<T, C> {
|
|
|
2272
2278
|
*/
|
|
2273
2279
|
declare function walkDescendants<T extends WalkableNode<T>, C>(root: T, carried: C, visitor: NodeVisitor<T, C>): void;
|
|
2274
2280
|
|
|
2281
|
+
/**
|
|
2282
|
+
* The project root when nothing declares one.
|
|
2283
|
+
*
|
|
2284
|
+
* Resolution from anywhere inside a tree finds the same `node_modules`,
|
|
2285
|
+
* and a recursive reader pointed at the directory every file shares
|
|
2286
|
+
* reaches all of them, so the deepest common directory serves both.
|
|
2287
|
+
*/
|
|
2288
|
+
/** The deepest directory containing every file, or undefined when they share no absolute root. */
|
|
2289
|
+
declare function commonDirectoryOf(files: ReadonlyArray<string>): string | undefined;
|
|
2290
|
+
|
|
2275
2291
|
/**
|
|
2276
2292
|
* The small surface every language adapter implements, whatever that
|
|
2277
2293
|
* language's own tooling looks like underneath.
|
|
@@ -3434,4 +3450,4 @@ declare function rawConditionToPredicate(c: RawCondition): Predicate;
|
|
|
3434
3450
|
declare function effectToIR(effect: RawEffect): Effect;
|
|
3435
3451
|
declare function paramToInput(param: RawParameter): Input;
|
|
3436
3452
|
|
|
3437
|
-
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, type ExitKind, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_PATHS, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, SKIP_CHILDREN, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type Timer, type TimingReport, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type WalkableNode, type WrapperMethodRegistration, type WrapperOptionRegistration, type WrapperRegistration, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, buildUngatedExtractionReport, composeWrappers, computeContentHash, computeDistHashFrom, configuredCallOption, createAdapterStamp, createCacheLayer, createPackTallies, createTimer, detectGaps, effectToIR, emptyTally, enumerateOrDegrade, enumerateStructuredPaths, evaluatePackHealth, firstWrittenReading, formatPackHealth, guardsHoldOn, httpRouteDiscovery, makeTransitionId, mapReading, moduleInitStructure, noopTimer, packGradients, paramToInput, projectFileStamp, rawConditionToPredicate, recordPackFailure, registrationHelperDiscovery, routeHelperIndex, runDigest, runsBefore, scopeOption, sharedGatingConditions, stampModuleImports, storageSystemOption, summaryCountsByPack, tallyUnit, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, walkDescendants, wrapperDiscovery, writtenReading };
|
|
3453
|
+
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, type ExitKind, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_PATHS, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, SKIP_CHILDREN, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type Timer, type TimingReport, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type WalkableNode, type WrapperMethodRegistration, type WrapperOptionRegistration, type WrapperRegistration, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, buildUngatedExtractionReport, commonDirectoryOf, composeWrappers, computeContentHash, computeDistHashFrom, configuredCallOption, createAdapterStamp, createCacheLayer, createPackTallies, createTimer, detectGaps, effectToIR, emptyTally, enumerateOrDegrade, enumerateStructuredPaths, evaluatePackHealth, firstWrittenReading, formatPackHealth, guardsHoldOn, httpRouteDiscovery, makeTransitionId, mapReading, moduleInitStructure, noopTimer, packGradients, paramToInput, projectFileStamp, rawConditionToPredicate, recordPackFailure, registrationHelperDiscovery, routeHelperIndex, runDigest, runsBefore, scopeOption, sharedGatingConditions, stampModuleImports, storageSystemOption, summaryCountsByPack, tallyUnit, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, walkDescendants, wrapperDiscovery, writtenReading };
|
package/dist/index.js
CHANGED
|
@@ -218,8 +218,8 @@ var catchEntryCond = () => fixedCond(
|
|
|
218
218
|
"positive",
|
|
219
219
|
"catchBlock"
|
|
220
220
|
);
|
|
221
|
-
function classify(
|
|
222
|
-
return
|
|
221
|
+
function classify(path4, home, isAncestorOrSelf) {
|
|
222
|
+
return path4.map((cond) => {
|
|
223
223
|
if (cond.branchStmt === null) {
|
|
224
224
|
return cond.info;
|
|
225
225
|
}
|
|
@@ -284,9 +284,9 @@ function chargeBudget(state) {
|
|
|
284
284
|
);
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
|
-
function recordTerminal(ctx, terminal, home,
|
|
287
|
+
function recordTerminal(ctx, terminal, home, path4) {
|
|
288
288
|
chargeBudget(ctx.state);
|
|
289
|
-
const info = classify(
|
|
289
|
+
const info = classify(path4, home, ctx.isAncestorOrSelf);
|
|
290
290
|
const existing = ctx.state.byTerminal.get(terminal) ?? [];
|
|
291
291
|
existing.push(info);
|
|
292
292
|
ctx.state.byTerminal.set(terminal, existing);
|
|
@@ -297,15 +297,15 @@ function containsTerminal(ctx, stmt) {
|
|
|
297
297
|
}
|
|
298
298
|
return childrenOf(stmt).some((child) => containsTerminal(ctx, child));
|
|
299
299
|
}
|
|
300
|
-
function stepIf(stmt,
|
|
300
|
+
function stepIf(stmt, path4, ctx) {
|
|
301
301
|
const thenExit = exitKindOfList(stmt.thenBody);
|
|
302
302
|
const elseExit = stmt.elseBody === null ? null : exitKindOfList(stmt.elseBody);
|
|
303
303
|
const thenPath = [
|
|
304
|
-
...
|
|
304
|
+
...path4,
|
|
305
305
|
branchCond(stmt, stmt.condition, "positive", elseExit)
|
|
306
306
|
];
|
|
307
307
|
const elsePath = [
|
|
308
|
-
...
|
|
308
|
+
...path4,
|
|
309
309
|
branchCond(
|
|
310
310
|
stmt,
|
|
311
311
|
stmt.condition,
|
|
@@ -322,7 +322,7 @@ function stepIf(stmt, path3, ctx) {
|
|
|
322
322
|
}
|
|
323
323
|
return out;
|
|
324
324
|
}
|
|
325
|
-
function stepSwitch(stmt,
|
|
325
|
+
function stepSwitch(stmt, path4, ctx) {
|
|
326
326
|
const out = [];
|
|
327
327
|
const negations = [];
|
|
328
328
|
let defaultRanBody = false;
|
|
@@ -332,7 +332,7 @@ function stepSwitch(stmt, path3, ctx) {
|
|
|
332
332
|
if (hasStrayBreak(group.body)) {
|
|
333
333
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
334
334
|
}
|
|
335
|
-
const groupPath = group.condition === null ? [...
|
|
335
|
+
const groupPath = group.condition === null ? [...path4, ...negations] : [...path4, fixedCond(group.condition, "positive", "explicit")];
|
|
336
336
|
const conts = enumerate(ctx, group.body, groupPath);
|
|
337
337
|
if (conts.length > 0) {
|
|
338
338
|
if (!group.hasTrailingBreak && !fallthroughSafe) {
|
|
@@ -349,24 +349,24 @@ function stepSwitch(stmt, path3, ctx) {
|
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
351
|
if (!defaultRanBody) {
|
|
352
|
-
out.push([...
|
|
352
|
+
out.push([...path4, ...negations]);
|
|
353
353
|
}
|
|
354
354
|
return out;
|
|
355
355
|
}
|
|
356
|
-
function stepLoop(stmt,
|
|
356
|
+
function stepLoop(stmt, path4, ctx) {
|
|
357
357
|
const bodyExit = exitKindOfList(stmt.body);
|
|
358
358
|
if (containsTerminal(ctx, stmt)) {
|
|
359
359
|
enumerate(ctx, stmt.body, [
|
|
360
|
-
...
|
|
360
|
+
...path4,
|
|
361
361
|
loopIterationCond(stmt.condition.sourceText)
|
|
362
362
|
]);
|
|
363
363
|
}
|
|
364
364
|
if (bodyExit !== null) {
|
|
365
|
-
return [[...
|
|
365
|
+
return [[...path4, loopCompletedCond(stmt.condition.sourceText, bodyExit)]];
|
|
366
366
|
}
|
|
367
|
-
return [
|
|
367
|
+
return [path4];
|
|
368
368
|
}
|
|
369
|
-
function stepTry(stmt,
|
|
369
|
+
function stepTry(stmt, path4, ctx) {
|
|
370
370
|
if (stmt.finallyBody !== null) {
|
|
371
371
|
const finallyHasTerminal = stmt.finallyBody.some(
|
|
372
372
|
(s) => containsTerminal(ctx, s)
|
|
@@ -376,22 +376,22 @@ function stepTry(stmt, path3, ctx) {
|
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
const out = [];
|
|
379
|
-
out.push(...enumerate(ctx, stmt.tryBody,
|
|
379
|
+
out.push(...enumerate(ctx, stmt.tryBody, path4));
|
|
380
380
|
if (stmt.catchBody !== null) {
|
|
381
|
-
const catchPath = [...
|
|
381
|
+
const catchPath = [...path4, catchEntryCond()];
|
|
382
382
|
out.push(...enumerate(ctx, stmt.catchBody, catchPath));
|
|
383
383
|
}
|
|
384
384
|
return out;
|
|
385
385
|
}
|
|
386
|
-
function stepExit(stmt,
|
|
386
|
+
function stepExit(stmt, path4, ctx) {
|
|
387
387
|
const collector = ctx.state.callbackExits[ctx.state.callbackExits.length - 1];
|
|
388
388
|
if (collector !== void 0 && (stmt.exit === "return" || stmt.exit === "throw")) {
|
|
389
|
-
collector.push(
|
|
389
|
+
collector.push(path4);
|
|
390
390
|
}
|
|
391
391
|
return [];
|
|
392
392
|
}
|
|
393
|
-
function stepOpaque(_stmt,
|
|
394
|
-
return [
|
|
393
|
+
function stepOpaque(_stmt, path4, _ctx) {
|
|
394
|
+
return [path4];
|
|
395
395
|
}
|
|
396
396
|
var stepHandlers = {
|
|
397
397
|
if: stepIf,
|
|
@@ -401,20 +401,20 @@ var stepHandlers = {
|
|
|
401
401
|
exit: stepExit,
|
|
402
402
|
opaque: stepOpaque
|
|
403
403
|
};
|
|
404
|
-
function stepCallback(ctx, body,
|
|
404
|
+
function stepCallback(ctx, body, path4) {
|
|
405
405
|
const exits = [];
|
|
406
406
|
ctx.state.callbackExits.push(exits);
|
|
407
407
|
let fellThrough;
|
|
408
408
|
try {
|
|
409
|
-
fellThrough = enumerate(ctx, body,
|
|
409
|
+
fellThrough = enumerate(ctx, body, path4);
|
|
410
410
|
} finally {
|
|
411
411
|
ctx.state.callbackExits.pop();
|
|
412
412
|
}
|
|
413
413
|
const out = [...fellThrough, ...exits];
|
|
414
|
-
return out.length === 0 ? [
|
|
414
|
+
return out.length === 0 ? [path4] : out;
|
|
415
415
|
}
|
|
416
|
-
function stepStatement(ctx, stmt,
|
|
417
|
-
let paths = [
|
|
416
|
+
function stepStatement(ctx, stmt, path4) {
|
|
417
|
+
let paths = [path4];
|
|
418
418
|
for (const body of stmt.callbacks ?? []) {
|
|
419
419
|
paths = paths.flatMap((each) => stepCallback(ctx, body, each));
|
|
420
420
|
}
|
|
@@ -495,8 +495,8 @@ function enumerate(ctx, stmts, prefix) {
|
|
|
495
495
|
let frontiers = [[...prefix]];
|
|
496
496
|
for (const stmt of stmts) {
|
|
497
497
|
const nextFrontiers = [];
|
|
498
|
-
for (const
|
|
499
|
-
nextFrontiers.push(...stepStatement(ctx, stmt,
|
|
498
|
+
for (const path4 of mergeRejoined(frontiers)) {
|
|
499
|
+
nextFrontiers.push(...stepStatement(ctx, stmt, path4));
|
|
500
500
|
}
|
|
501
501
|
frontiers = nextFrontiers;
|
|
502
502
|
if (frontiers.length > MAX_PATHS) {
|
|
@@ -547,9 +547,9 @@ function enumerateStructuredPaths(input) {
|
|
|
547
547
|
isAncestorOrSelf
|
|
548
548
|
};
|
|
549
549
|
const continuations = withRejoined(enumerate(ctx, input.statements, []));
|
|
550
|
-
for (const
|
|
550
|
+
for (const path4 of continuations) {
|
|
551
551
|
chargeBudget(state);
|
|
552
|
-
state.fallthrough.push(classify(
|
|
552
|
+
state.fallthrough.push(classify(path4, null, isAncestorOrSelf));
|
|
553
553
|
}
|
|
554
554
|
return { byTerminal: state.byTerminal, fallthrough: state.fallthrough };
|
|
555
555
|
}
|
|
@@ -595,9 +595,12 @@ function composeWrappers(summaries, options = {}) {
|
|
|
595
595
|
const byKey = /* @__PURE__ */ new Map();
|
|
596
596
|
for (const summary of summaries) {
|
|
597
597
|
const key = summaryKey(summary.location.file, summary.identity.name);
|
|
598
|
-
|
|
599
|
-
|
|
598
|
+
const sharing = byKey.get(key);
|
|
599
|
+
if (sharing === void 0) {
|
|
600
|
+
byKey.set(key, [summary]);
|
|
601
|
+
continue;
|
|
600
602
|
}
|
|
603
|
+
sharing.push(summary);
|
|
601
604
|
}
|
|
602
605
|
const keepGaps = options.gapHandling !== "silent";
|
|
603
606
|
return summaries.map((summary) => composeOne(summary, byKey, keepGaps));
|
|
@@ -605,6 +608,13 @@ function composeWrappers(summaries, options = {}) {
|
|
|
605
608
|
function summaryKey(file, name) {
|
|
606
609
|
return `${file}::${name}`;
|
|
607
610
|
}
|
|
611
|
+
function summaryOf(reference, byKey) {
|
|
612
|
+
const sharing = byKey.get(summaryKey(reference.file, reference.name)) ?? [];
|
|
613
|
+
if (reference.line === void 0) {
|
|
614
|
+
return sharing[0];
|
|
615
|
+
}
|
|
616
|
+
return sharing.find((one) => one.location.range.start === reference.line) ?? sharing[0];
|
|
617
|
+
}
|
|
608
618
|
function composeOne(summary, byKey, keepGaps) {
|
|
609
619
|
const recorded = readWrapperMetadata2(summary);
|
|
610
620
|
const applied = recorded?.applied ?? [];
|
|
@@ -618,7 +628,7 @@ function composeOne(summary, byKey, keepGaps) {
|
|
|
618
628
|
})
|
|
619
629
|
};
|
|
620
630
|
const wrappers = covering.flatMap((reference) => {
|
|
621
|
-
const found =
|
|
631
|
+
const found = summaryOf(reference, byKey);
|
|
622
632
|
return found === void 0 ? [] : [{ reference, summary: found }];
|
|
623
633
|
});
|
|
624
634
|
if (wrappers.length === 0) {
|
|
@@ -698,8 +708,8 @@ function applyWrapper(wrapper, inner) {
|
|
|
698
708
|
wrapper.summary.transitions.filter((t) => t.output.type !== "delegate"),
|
|
699
709
|
wrapper.reference
|
|
700
710
|
);
|
|
701
|
-
const passThroughs =
|
|
702
|
-
(t) => t.output.type === "delegate"
|
|
711
|
+
const passThroughs = withoutCoveredPassThroughs(
|
|
712
|
+
wrapper.summary.transitions.filter((t) => t.output.type === "delegate")
|
|
703
713
|
);
|
|
704
714
|
if (passThroughs.length === 0 || shortCircuits.length + passThroughs.length * inner.transitions.length > MAX_PATHS) {
|
|
705
715
|
return {
|
|
@@ -712,6 +722,20 @@ function applyWrapper(wrapper, inner) {
|
|
|
712
722
|
);
|
|
713
723
|
return { transitions: [...shortCircuits, ...continued], degraded: false };
|
|
714
724
|
}
|
|
725
|
+
function withoutCoveredPassThroughs(passThroughs) {
|
|
726
|
+
return passThroughs.filter(
|
|
727
|
+
(candidate, i) => !passThroughs.some(
|
|
728
|
+
(other, j) => j !== i && covers(other, candidate) && (j < i || !covers(candidate, other))
|
|
729
|
+
)
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
function covers(wider, narrower) {
|
|
733
|
+
if (JSON.stringify(wider.effects) !== JSON.stringify(narrower.effects)) {
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
const required = new Set(narrower.conditions.map((c) => JSON.stringify(c)));
|
|
737
|
+
return wider.conditions.every((c) => required.has(JSON.stringify(c)));
|
|
738
|
+
}
|
|
715
739
|
function applyThrowWrapper(wrapper, inner) {
|
|
716
740
|
const thrown = inner.transitions.filter((t) => t.output.type === "throw");
|
|
717
741
|
if (thrown.length === 0) {
|
|
@@ -1037,8 +1061,8 @@ function sharedGatingConditions(paths, readPredicate) {
|
|
|
1037
1061
|
return [];
|
|
1038
1062
|
}
|
|
1039
1063
|
const shared = new Set(first.map(keyOf2));
|
|
1040
|
-
for (const
|
|
1041
|
-
const here = new Set(
|
|
1064
|
+
for (const path4 of rest) {
|
|
1065
|
+
const here = new Set(path4.map(keyOf2));
|
|
1042
1066
|
for (const value of shared) {
|
|
1043
1067
|
if (!here.has(value)) {
|
|
1044
1068
|
shared.delete(value);
|
|
@@ -1114,6 +1138,27 @@ function walkDescendants(root, carried, visitor) {
|
|
|
1114
1138
|
}
|
|
1115
1139
|
}
|
|
1116
1140
|
|
|
1141
|
+
// src/projectRoot.ts
|
|
1142
|
+
import path from "path";
|
|
1143
|
+
function commonDirectoryOf(files) {
|
|
1144
|
+
const absolute = files.filter((f) => path.isAbsolute(f));
|
|
1145
|
+
const first = absolute[0];
|
|
1146
|
+
if (first === void 0) {
|
|
1147
|
+
return void 0;
|
|
1148
|
+
}
|
|
1149
|
+
let shared = path.dirname(first).split(path.sep);
|
|
1150
|
+
for (const file of absolute.slice(1)) {
|
|
1151
|
+
const parts = path.dirname(file).split(path.sep);
|
|
1152
|
+
let i = 0;
|
|
1153
|
+
while (i < shared.length && i < parts.length && shared[i] === parts[i]) {
|
|
1154
|
+
i += 1;
|
|
1155
|
+
}
|
|
1156
|
+
shared = shared.slice(0, i);
|
|
1157
|
+
}
|
|
1158
|
+
const joined = shared.join(path.sep);
|
|
1159
|
+
return joined.length > 1 ? joined : void 0;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1117
1162
|
// src/reading.ts
|
|
1118
1163
|
function writtenReading(value, range) {
|
|
1119
1164
|
return { kind: "written", value, range };
|
|
@@ -1171,7 +1216,7 @@ function valueToReadFurtherFrom(reading) {
|
|
|
1171
1216
|
import { createHash } from "crypto";
|
|
1172
1217
|
import fs from "fs";
|
|
1173
1218
|
import { createRequire } from "module";
|
|
1174
|
-
import
|
|
1219
|
+
import path2 from "path";
|
|
1175
1220
|
import { fileURLToPath } from "url";
|
|
1176
1221
|
var ANALYSIS_PACKAGES = [
|
|
1177
1222
|
"@suss/extractor",
|
|
@@ -1213,14 +1258,14 @@ function createAdapterStamp(config) {
|
|
|
1213
1258
|
function readAdapterCodeStamp(moduleUrl) {
|
|
1214
1259
|
try {
|
|
1215
1260
|
const selfPath = fileURLToPath(moduleUrl);
|
|
1216
|
-
const hash = computeDistHashFrom(
|
|
1261
|
+
const hash = computeDistHashFrom(path2.dirname(selfPath));
|
|
1217
1262
|
return hash.length > 0 ? { kind: "bundle", hash } : SOURCE_STAMP;
|
|
1218
1263
|
} catch {
|
|
1219
1264
|
return SOURCE_STAMP;
|
|
1220
1265
|
}
|
|
1221
1266
|
}
|
|
1222
1267
|
function computeDistHashFrom(dir) {
|
|
1223
|
-
const candidates = [
|
|
1268
|
+
const candidates = [path2.join(dir, "index.js"), path2.join(dir, "index.cjs")];
|
|
1224
1269
|
for (const candidate of candidates) {
|
|
1225
1270
|
if (!fs.existsSync(candidate)) {
|
|
1226
1271
|
continue;
|
|
@@ -1278,7 +1323,7 @@ function analysisBundles() {
|
|
|
1278
1323
|
// src/cache.ts
|
|
1279
1324
|
import { createHash as createHash2 } from "crypto";
|
|
1280
1325
|
import fs2 from "fs/promises";
|
|
1281
|
-
import
|
|
1326
|
+
import path3 from "path";
|
|
1282
1327
|
var SCHEMA_VERSION = "7";
|
|
1283
1328
|
var MAX_ENTRIES = 2;
|
|
1284
1329
|
var ENTRY_PREFIX = "key-";
|
|
@@ -1304,7 +1349,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1304
1349
|
async lookup(input) {
|
|
1305
1350
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1306
1351
|
const manifest = await readManifest(
|
|
1307
|
-
|
|
1352
|
+
path3.join(entryDir, "manifest.json")
|
|
1308
1353
|
);
|
|
1309
1354
|
if (manifest === null) {
|
|
1310
1355
|
return missDiag(await describeAbsentEntry(cacheDir));
|
|
@@ -1327,7 +1372,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1327
1372
|
async plan(input) {
|
|
1328
1373
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1329
1374
|
const manifest = await readManifest(
|
|
1330
|
-
|
|
1375
|
+
path3.join(entryDir, "manifest.json")
|
|
1331
1376
|
);
|
|
1332
1377
|
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
1333
1378
|
return null;
|
|
@@ -1342,7 +1387,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1342
1387
|
async write(input, summaries, attribution) {
|
|
1343
1388
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1344
1389
|
const previous = await readManifest(
|
|
1345
|
-
|
|
1390
|
+
path3.join(entryDir, "manifest.json")
|
|
1346
1391
|
);
|
|
1347
1392
|
const configStamp = await stampConfigFile(input.configPath);
|
|
1348
1393
|
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
@@ -1356,7 +1401,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1356
1401
|
};
|
|
1357
1402
|
await fs2.mkdir(entryDir, { recursive: true });
|
|
1358
1403
|
await fs2.writeFile(
|
|
1359
|
-
|
|
1404
|
+
path3.join(entryDir, "manifest.json"),
|
|
1360
1405
|
JSON.stringify(manifest)
|
|
1361
1406
|
);
|
|
1362
1407
|
await evictOldEntries(cacheDir, entryDir);
|
|
@@ -1535,7 +1580,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
1535
1580
|
input.configPath ?? ""
|
|
1536
1581
|
].join(" ");
|
|
1537
1582
|
const name = createHash2("sha256").update(key).digest("hex").slice(0, 16);
|
|
1538
|
-
return
|
|
1583
|
+
return path3.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
1539
1584
|
}
|
|
1540
1585
|
function isEntryDir(name) {
|
|
1541
1586
|
return ENTRY_DIR_NAME.test(name);
|
|
@@ -1549,11 +1594,11 @@ async function markUsed(entryDir) {
|
|
|
1549
1594
|
}
|
|
1550
1595
|
async function evictOldEntries(cacheDir, keepDir) {
|
|
1551
1596
|
try {
|
|
1552
|
-
await fs2.rm(
|
|
1597
|
+
await fs2.rm(path3.join(cacheDir, "manifest.json"), { force: true });
|
|
1553
1598
|
const entries = await fs2.readdir(cacheDir, { withFileTypes: true });
|
|
1554
1599
|
const dirs = await Promise.all(
|
|
1555
1600
|
entries.filter((e) => e.isDirectory() && isEntryDir(e.name)).map(async (e) => {
|
|
1556
|
-
const dir =
|
|
1601
|
+
const dir = path3.join(cacheDir, e.name);
|
|
1557
1602
|
const stat = await fs2.stat(dir);
|
|
1558
1603
|
return { dir, mtimeMs: stat.mtimeMs };
|
|
1559
1604
|
})
|
|
@@ -2379,6 +2424,7 @@ export {
|
|
|
2379
2424
|
assembleSummary,
|
|
2380
2425
|
assessConfidence,
|
|
2381
2426
|
buildUngatedExtractionReport,
|
|
2427
|
+
commonDirectoryOf,
|
|
2382
2428
|
composeWrappers,
|
|
2383
2429
|
computeContentHash,
|
|
2384
2430
|
computeDistHashFrom,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/extractor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The suss extraction pipeline, which turns what a language adapter read into the summaries the checker pairs across a boundary.",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@suss/behavioral-ir": "0.
|
|
49
|
+
"@suss/behavioral-ir": "0.27.0",
|
|
50
50
|
"zod": "^4.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|