@suss/adapter-typescript 0.21.1 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -35
- package/dist/index.cjs +934 -1508
- package/dist/index.d.cts +74 -414
- package/dist/index.d.ts +74 -414
- package/dist/index.js +868 -1424
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -32,26 +32,24 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ADAPTER_VERSION: () => ADAPTER_VERSION,
|
|
34
34
|
ResolutionStore: () => ResolutionStore,
|
|
35
|
-
|
|
35
|
+
TypeScriptWhySession: () => TypeScriptWhySession,
|
|
36
36
|
accessContextFor: () => accessContextFor,
|
|
37
37
|
buildProjectHelperIndex: () => buildProjectHelperIndex,
|
|
38
38
|
callOpsFor: () => callOpsFor,
|
|
39
39
|
collectAncestorBranches: () => collectAncestorBranches,
|
|
40
40
|
collectClientFieldAccesses: () => collectClientFieldAccesses,
|
|
41
41
|
computeAdapterPacksDigest: () => computeAdapterPacksDigest,
|
|
42
|
-
computeContentHash: () => computeContentHash,
|
|
42
|
+
computeContentHash: () => import_extractor10.computeContentHash,
|
|
43
43
|
createProjectWithoutTsconfig: () => createProjectWithoutTsconfig,
|
|
44
44
|
createTsDiscoveryContext: () => createTsDiscoveryContext,
|
|
45
45
|
createTsSubUnitContext: () => createTsSubUnitContext,
|
|
46
46
|
createTypeScriptAdapter: () => createTypeScriptAdapter,
|
|
47
47
|
discoverUnits: () => discoverUnits,
|
|
48
|
-
evaluatePackHealth: () => evaluatePackHealth,
|
|
49
48
|
exportedDeclarationsOf: () => exportedDeclarationsOf,
|
|
50
49
|
extractCodeStructure: () => extractCodeStructure,
|
|
51
50
|
extractRawBranches: () => extractRawBranches,
|
|
52
51
|
findNearestTsconfig: () => findNearestTsconfig,
|
|
53
52
|
findTerminals: () => findTerminals,
|
|
54
|
-
formatPackHealth: () => formatPackHealth,
|
|
55
53
|
functionTargetOf: () => functionTargetOf,
|
|
56
54
|
importDeclarationsOf: () => importDeclarationsOf,
|
|
57
55
|
importedNamesOf: () => importedNamesOf,
|
|
@@ -75,15 +73,15 @@ __export(index_exports, {
|
|
|
75
73
|
module.exports = __toCommonJS(index_exports);
|
|
76
74
|
|
|
77
75
|
// src/adapter.ts
|
|
78
|
-
var
|
|
76
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
79
77
|
var import_ts_morph66 = require("ts-morph");
|
|
80
|
-
var
|
|
78
|
+
var import_behavioral_ir9 = require("@suss/behavioral-ir");
|
|
81
79
|
var import_datalog6 = require("@suss/datalog");
|
|
82
|
-
var
|
|
80
|
+
var import_extractor11 = require("@suss/extractor");
|
|
83
81
|
|
|
84
82
|
// src/assembly.ts
|
|
85
83
|
var import_ts_morph54 = require("ts-morph");
|
|
86
|
-
var
|
|
84
|
+
var import_extractor5 = require("@suss/extractor");
|
|
87
85
|
|
|
88
86
|
// src/conditions.ts
|
|
89
87
|
var import_ts_morph6 = require("ts-morph");
|
|
@@ -95,6 +93,7 @@ var import_ts_morph5 = require("ts-morph");
|
|
|
95
93
|
var import_ts_morph2 = require("ts-morph");
|
|
96
94
|
|
|
97
95
|
// src/walk/nodeKeys.ts
|
|
96
|
+
var import_behavioral_ir = require("@suss/behavioral-ir");
|
|
98
97
|
function offsetKeyOf(node) {
|
|
99
98
|
return offsetKeyFor(node.getSourceFile().getFilePath(), {
|
|
100
99
|
start: node.getStart(),
|
|
@@ -102,7 +101,7 @@ function offsetKeyOf(node) {
|
|
|
102
101
|
});
|
|
103
102
|
}
|
|
104
103
|
function offsetKeyFor(file, span) {
|
|
105
|
-
return
|
|
104
|
+
return (0, import_behavioral_ir.declarationKey)(file, span);
|
|
106
105
|
}
|
|
107
106
|
function lineRangeKey(file, startLine, endLine) {
|
|
108
107
|
return `${file}:${startLine}-${endLine}`;
|
|
@@ -1542,7 +1541,7 @@ function degradedResult(func, terminalNodes, reason) {
|
|
|
1542
1541
|
|
|
1543
1542
|
// src/resolve/invocationEffects.ts
|
|
1544
1543
|
var import_ts_morph43 = require("ts-morph");
|
|
1545
|
-
var
|
|
1544
|
+
var import_extractor4 = require("@suss/extractor");
|
|
1546
1545
|
|
|
1547
1546
|
// src/lines.ts
|
|
1548
1547
|
function startLineOf(node) {
|
|
@@ -1910,8 +1909,8 @@ function loadImportGraphsDepthFirstFromPaths(project, rootPaths) {
|
|
|
1910
1909
|
stack.pop();
|
|
1911
1910
|
loadOrder.push(top.path);
|
|
1912
1911
|
let deepest = 0;
|
|
1913
|
-
for (const
|
|
1914
|
-
deepest = Math.max(deepest, chainDepth.get(
|
|
1912
|
+
for (const path14 of top.deps) {
|
|
1913
|
+
deepest = Math.max(deepest, chainDepth.get(path14) ?? 0);
|
|
1915
1914
|
}
|
|
1916
1915
|
chainDepth.set(top.path, deepest + 1);
|
|
1917
1916
|
}
|
|
@@ -2263,11 +2262,11 @@ function walkAndWarm(root, reach) {
|
|
|
2263
2262
|
if (warmedFiles.get(target) !== void 0) {
|
|
2264
2263
|
continue;
|
|
2265
2264
|
}
|
|
2266
|
-
const
|
|
2267
|
-
if (visited.has(
|
|
2265
|
+
const path14 = target.getFilePath();
|
|
2266
|
+
if (visited.has(path14)) {
|
|
2268
2267
|
continue;
|
|
2269
2268
|
}
|
|
2270
|
-
visited.add(
|
|
2269
|
+
visited.add(path14);
|
|
2271
2270
|
stack.push(frameOf(target, reach));
|
|
2272
2271
|
continue;
|
|
2273
2272
|
}
|
|
@@ -2284,7 +2283,7 @@ function sitsOnWarmChains(file) {
|
|
|
2284
2283
|
return false;
|
|
2285
2284
|
}
|
|
2286
2285
|
const imported = importedFilePathsOf(project, file.getFilePath());
|
|
2287
|
-
return imported.length > 0 && imported.every((
|
|
2286
|
+
return imported.length > 0 && imported.every((path14) => warmed.has(path14));
|
|
2288
2287
|
}
|
|
2289
2288
|
function markWarmed(file) {
|
|
2290
2289
|
warmedFiles.set(file, true);
|
|
@@ -2579,6 +2578,32 @@ function writesToBindingUncached(declaration) {
|
|
|
2579
2578
|
}
|
|
2580
2579
|
return { values, inOrder: writesRunInOrder(declaration, writes) };
|
|
2581
2580
|
}
|
|
2581
|
+
function sameConstructionAcrossWrites(values) {
|
|
2582
|
+
const candidates = values.filter((value) => !isNotYetPlaceholder(value));
|
|
2583
|
+
if (candidates.length === 0) {
|
|
2584
|
+
return null;
|
|
2585
|
+
}
|
|
2586
|
+
let construction = null;
|
|
2587
|
+
for (const value of candidates) {
|
|
2588
|
+
if (!isConstruction(value)) {
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
if (construction !== null && sourceOf(value) !== sourceOf(construction)) {
|
|
2592
|
+
return null;
|
|
2593
|
+
}
|
|
2594
|
+
construction = value;
|
|
2595
|
+
}
|
|
2596
|
+
return construction;
|
|
2597
|
+
}
|
|
2598
|
+
function isNotYetPlaceholder(value) {
|
|
2599
|
+
return value.getKind() === import_ts_morph14.SyntaxKind.NullKeyword || import_ts_morph14.Node.isIdentifier(value) && value.getText() === "undefined";
|
|
2600
|
+
}
|
|
2601
|
+
function isConstruction(value) {
|
|
2602
|
+
return import_ts_morph14.Node.isCallExpression(value) || import_ts_morph14.Node.isNewExpression(value);
|
|
2603
|
+
}
|
|
2604
|
+
function sourceOf(node) {
|
|
2605
|
+
return node.getText().replace(/\s+/g, " ").trim();
|
|
2606
|
+
}
|
|
2582
2607
|
function writesToField(declaration) {
|
|
2583
2608
|
const remembered = byField.get(declaration);
|
|
2584
2609
|
if (remembered !== void 0) {
|
|
@@ -2669,6 +2694,9 @@ function assignmentsInFile(sourceFile) {
|
|
|
2669
2694
|
function isAssignmentOperator(kind) {
|
|
2670
2695
|
return kind >= import_ts_morph14.SyntaxKind.FirstAssignment && kind <= import_ts_morph14.SyntaxKind.LastAssignment;
|
|
2671
2696
|
}
|
|
2697
|
+
function writesItsWholeValue(kind) {
|
|
2698
|
+
return kind === import_ts_morph14.SyntaxKind.EqualsToken || kind === import_ts_morph14.SyntaxKind.QuestionQuestionEqualsToken || kind === import_ts_morph14.SyntaxKind.BarBarEqualsToken;
|
|
2699
|
+
}
|
|
2672
2700
|
function writeAt(node) {
|
|
2673
2701
|
if (import_ts_morph14.Node.isBinaryExpression(node)) {
|
|
2674
2702
|
const operator = node.getOperatorToken().getKind();
|
|
@@ -2676,7 +2704,7 @@ function writeAt(node) {
|
|
|
2676
2704
|
if (!isAssignmentOperator(operator) || !(import_ts_morph14.Node.isIdentifier(target) || import_ts_morph14.Node.isPropertyAccessExpression(target))) {
|
|
2677
2705
|
return null;
|
|
2678
2706
|
}
|
|
2679
|
-
const value = operator
|
|
2707
|
+
const value = writesItsWholeValue(operator) ? node.getRight() : null;
|
|
2680
2708
|
return { target, write: { value, node } };
|
|
2681
2709
|
}
|
|
2682
2710
|
if (import_ts_morph14.Node.isPrefixUnaryExpression(node) || import_ts_morph14.Node.isPostfixUnaryExpression(node)) {
|
|
@@ -3067,11 +3095,16 @@ function emitBindingValues(db, table, declaration) {
|
|
|
3067
3095
|
}
|
|
3068
3096
|
const { values, inOrder } = writesToBinding(declaration);
|
|
3069
3097
|
const last = values[values.length - 1];
|
|
3070
|
-
if (
|
|
3071
|
-
|
|
3098
|
+
if (inOrder && last !== void 0) {
|
|
3099
|
+
fact(db, "endsHolding", declarationId, emitValue(db, table, last));
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
const construction = sameConstructionAcrossWrites(values);
|
|
3103
|
+
if (construction !== null) {
|
|
3104
|
+
fact(db, "endsHolding", declarationId, emitValue(db, table, construction));
|
|
3072
3105
|
return;
|
|
3073
3106
|
}
|
|
3074
|
-
|
|
3107
|
+
reassignedUnstated.add(declarationId);
|
|
3075
3108
|
}
|
|
3076
3109
|
var reassignedUnstated = /* @__PURE__ */ new Set();
|
|
3077
3110
|
function reassignedNamesUnstated() {
|
|
@@ -3083,23 +3116,31 @@ function forgetReassignedNamesUnstated() {
|
|
|
3083
3116
|
function emitFieldValues(db, table, declaration) {
|
|
3084
3117
|
const { values, inOrder } = writesToField(declaration);
|
|
3085
3118
|
const last = values[values.length - 1];
|
|
3086
|
-
if (
|
|
3119
|
+
if (inOrder && last !== void 0 && import_ts_morph15.Node.isExpression(last)) {
|
|
3120
|
+
fact(db, "binds", nodeId(declaration), emitValue(db, table, last));
|
|
3087
3121
|
return;
|
|
3088
3122
|
}
|
|
3089
|
-
|
|
3123
|
+
const construction = sameConstructionAcrossWrites(values);
|
|
3124
|
+
if (construction !== null) {
|
|
3125
|
+
fact(db, "binds", nodeId(declaration), emitValue(db, table, construction));
|
|
3126
|
+
}
|
|
3090
3127
|
}
|
|
3091
3128
|
function emitParameterPropertyRead(db, table, referenceId, declaration) {
|
|
3092
3129
|
const { values, inOrder } = writesToField(declaration);
|
|
3093
3130
|
const last = values[values.length - 1];
|
|
3094
|
-
if (
|
|
3131
|
+
if (inOrder && last !== void 0 && import_ts_morph15.Node.isExpression(last)) {
|
|
3132
|
+
fact(db, "binds", referenceId, emitValue(db, table, last));
|
|
3095
3133
|
return;
|
|
3096
3134
|
}
|
|
3097
|
-
if (
|
|
3135
|
+
if (inOrder && last !== void 0) {
|
|
3098
3136
|
table.byId.set(nodeId(last), last);
|
|
3099
3137
|
fact(db, "binds", referenceId, nodeId(last));
|
|
3100
3138
|
return;
|
|
3101
3139
|
}
|
|
3102
|
-
|
|
3140
|
+
const construction = sameConstructionAcrossWrites(values);
|
|
3141
|
+
if (construction !== null) {
|
|
3142
|
+
fact(db, "binds", referenceId, emitValue(db, table, construction));
|
|
3143
|
+
}
|
|
3103
3144
|
}
|
|
3104
3145
|
function emitBindingElementFacts(db, table, element) {
|
|
3105
3146
|
const id = nodeId(element);
|
|
@@ -3563,7 +3604,8 @@ var JS_RULES = [
|
|
|
3563
3604
|
];
|
|
3564
3605
|
var RESOLUTION_PROGRAM = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? {
|
|
3565
3606
|
rules: [...import_resolution2.RESOLUTION_RULES, ...JS_RULES, ...import_resolution2.RESOLUTION_QUESTIONS],
|
|
3566
|
-
demandDriven: []
|
|
3607
|
+
demandDriven: [],
|
|
3608
|
+
demands: []
|
|
3567
3609
|
} : (0, import_datalog2.deriveOnDemand)(
|
|
3568
3610
|
[...import_resolution2.RESOLUTION_RULES, ...JS_RULES, ...import_resolution2.RESOLUTION_QUESTIONS],
|
|
3569
3611
|
import_resolution2.ANSWER_RELATIONS
|
|
@@ -3590,7 +3632,9 @@ var QUERY_FACTS = RESOLUTION_PROGRAM.demandDriven.length === 0 ? [] : [
|
|
|
3590
3632
|
"wantedAnchor",
|
|
3591
3633
|
"wantedSubject"
|
|
3592
3634
|
];
|
|
3593
|
-
var
|
|
3635
|
+
var MODULE_DEMANDS = RESOLUTION_PROGRAM.demands.filter(
|
|
3636
|
+
(one) => (one.relation === "moduleExport" || one.relation === "moduleForwards") && one.bound[0] === true
|
|
3637
|
+
).map((one) => one.demand);
|
|
3594
3638
|
var ResolutionStore = class {
|
|
3595
3639
|
db = new import_datalog2.Database();
|
|
3596
3640
|
table = createNodeTable();
|
|
@@ -3606,7 +3650,7 @@ var ResolutionStore = class {
|
|
|
3606
3650
|
* extraction elsewhere cannot change an entry.
|
|
3607
3651
|
*/
|
|
3608
3652
|
exportTables = /* @__PURE__ */ new Map();
|
|
3609
|
-
/** Files the most recent
|
|
3653
|
+
/** Files the most recent query read, for the memo to keep. */
|
|
3610
3654
|
lastQueryWalked = [];
|
|
3611
3655
|
declarations = /* @__PURE__ */ new Map();
|
|
3612
3656
|
graph = new ModuleGraph();
|
|
@@ -3637,19 +3681,19 @@ var ResolutionStore = class {
|
|
|
3637
3681
|
*/
|
|
3638
3682
|
resolveCallableSources(value, alsoFrom) {
|
|
3639
3683
|
const target = factKeyOf(value);
|
|
3640
|
-
return this.
|
|
3684
|
+
return this.askAbout(
|
|
3641
3685
|
target,
|
|
3642
3686
|
"wanted",
|
|
3643
3687
|
() => this.lookupSources(target),
|
|
3644
3688
|
alsoFrom
|
|
3645
|
-
)
|
|
3689
|
+
);
|
|
3646
3690
|
}
|
|
3647
3691
|
/**
|
|
3648
3692
|
* The witness proof behind `resolveCallable`'s answer. Resolves the
|
|
3649
|
-
* value first, which
|
|
3650
|
-
*
|
|
3651
|
-
*
|
|
3652
|
-
*
|
|
3693
|
+
* value first, which extracts the files the question demands, then
|
|
3694
|
+
* re-evaluates the rules over those base facts under the witness
|
|
3695
|
+
* algebra and rebuilds the proof of the answer. Null when the value
|
|
3696
|
+
* does not resolve at all.
|
|
3653
3697
|
*/
|
|
3654
3698
|
explainCallable(value, options = {}) {
|
|
3655
3699
|
const resolved = this.resolveCallable(value, options.alsoFrom);
|
|
@@ -3686,11 +3730,7 @@ var ResolutionStore = class {
|
|
|
3686
3730
|
}
|
|
3687
3731
|
resolveObject(value) {
|
|
3688
3732
|
const target = factKeyOf(value);
|
|
3689
|
-
return this.
|
|
3690
|
-
target,
|
|
3691
|
-
"wanted",
|
|
3692
|
-
() => this.lookupObject(target)
|
|
3693
|
-
);
|
|
3733
|
+
return this.askAbout(target, "wanted", () => this.lookupObject(target));
|
|
3694
3734
|
}
|
|
3695
3735
|
/**
|
|
3696
3736
|
* For a value that is neither a function nor an object, such as a
|
|
@@ -3706,17 +3746,17 @@ var ResolutionStore = class {
|
|
|
3706
3746
|
}
|
|
3707
3747
|
return cached.written;
|
|
3708
3748
|
}
|
|
3709
|
-
const
|
|
3749
|
+
const written = this.askAbout(
|
|
3710
3750
|
target,
|
|
3711
3751
|
"wanted",
|
|
3712
3752
|
() => this.lookupWritten(target)
|
|
3713
3753
|
);
|
|
3714
3754
|
this.writtenValues.set(key, {
|
|
3715
|
-
written
|
|
3755
|
+
written,
|
|
3716
3756
|
walked: [...this.lastQueryWalked],
|
|
3717
3757
|
extractedAt: this.fullyExtracted.size
|
|
3718
3758
|
});
|
|
3719
|
-
return
|
|
3759
|
+
return written;
|
|
3720
3760
|
}
|
|
3721
3761
|
/**
|
|
3722
3762
|
* The construction behind a registration subject: the call or `new`
|
|
@@ -3736,18 +3776,29 @@ var ResolutionStore = class {
|
|
|
3736
3776
|
}
|
|
3737
3777
|
return cached.construction;
|
|
3738
3778
|
}
|
|
3739
|
-
const settled2 = this.
|
|
3779
|
+
const settled2 = this.askAbout(
|
|
3740
3780
|
target,
|
|
3741
3781
|
"wantedSubject",
|
|
3742
3782
|
() => this.lookupSubjectConstruction(target, importModule, importName)
|
|
3743
3783
|
);
|
|
3784
|
+
const walked = [...this.lastQueryWalked];
|
|
3785
|
+
let resolved = settled2;
|
|
3786
|
+
if (settled2.construction === null && settled2.candidate !== null && import_ts_morph16.Node.isCallExpression(settled2.candidate) && this.resolveCallable(settled2.candidate.getExpression()) !== null) {
|
|
3787
|
+
const call = settled2.candidate;
|
|
3788
|
+
resolved = this.askAbout(
|
|
3789
|
+
call,
|
|
3790
|
+
"wantedSubject",
|
|
3791
|
+
() => this.lookupSubjectConstruction(call, importModule, importName)
|
|
3792
|
+
);
|
|
3793
|
+
walked.push(...this.lastQueryWalked);
|
|
3794
|
+
}
|
|
3744
3795
|
this.subjectConstructions.set(key, {
|
|
3745
|
-
construction:
|
|
3746
|
-
candidates:
|
|
3747
|
-
walked
|
|
3796
|
+
construction: resolved.construction,
|
|
3797
|
+
candidates: resolved.candidates,
|
|
3798
|
+
walked,
|
|
3748
3799
|
extractedAt: this.fullyExtracted.size
|
|
3749
3800
|
});
|
|
3750
|
-
return
|
|
3801
|
+
return resolved.construction;
|
|
3751
3802
|
}
|
|
3752
3803
|
/**
|
|
3753
3804
|
* How many constructions this value was written as, which is what
|
|
@@ -3761,10 +3812,8 @@ var ResolutionStore = class {
|
|
|
3761
3812
|
)?.candidates ?? 0;
|
|
3762
3813
|
}
|
|
3763
3814
|
/**
|
|
3764
|
-
* The single-answer policy over the written-value
|
|
3765
|
-
* origin check on the one candidate.
|
|
3766
|
-
* is settled refusal rather than a reason to widen: its own file's
|
|
3767
|
-
* import facts are already in, and more files only add candidates.
|
|
3815
|
+
* The single-answer policy over the written-value chain, then the
|
|
3816
|
+
* origin check on the one candidate.
|
|
3768
3817
|
*/
|
|
3769
3818
|
lookupSubjectConstruction(value, importModule, importName) {
|
|
3770
3819
|
this.derive();
|
|
@@ -3780,6 +3829,7 @@ var ResolutionStore = class {
|
|
|
3780
3829
|
if (candidates.size > 1) {
|
|
3781
3830
|
return {
|
|
3782
3831
|
construction: null,
|
|
3832
|
+
candidate: null,
|
|
3783
3833
|
candidates: [...candidates].filter(
|
|
3784
3834
|
(one) => this.constructionComesFrom(valueId, one, importModule, importName)
|
|
3785
3835
|
).length
|
|
@@ -3787,7 +3837,7 @@ var ResolutionStore = class {
|
|
|
3787
3837
|
}
|
|
3788
3838
|
const single = [...candidates][0];
|
|
3789
3839
|
if (single === void 0) {
|
|
3790
|
-
return
|
|
3840
|
+
return { construction: null, candidate: null, candidates: 0 };
|
|
3791
3841
|
}
|
|
3792
3842
|
return {
|
|
3793
3843
|
construction: this.constructionComesFrom(
|
|
@@ -3796,6 +3846,7 @@ var ResolutionStore = class {
|
|
|
3796
3846
|
importModule,
|
|
3797
3847
|
importName
|
|
3798
3848
|
) ? single : null,
|
|
3849
|
+
candidate: single,
|
|
3799
3850
|
candidates: 1
|
|
3800
3851
|
};
|
|
3801
3852
|
}
|
|
@@ -3855,11 +3906,11 @@ var ResolutionStore = class {
|
|
|
3855
3906
|
return cached.names;
|
|
3856
3907
|
}
|
|
3857
3908
|
const target = factKeyOf(value);
|
|
3858
|
-
const found = this.
|
|
3909
|
+
const found = this.askAbout(
|
|
3859
3910
|
target,
|
|
3860
3911
|
"wantedOrigin",
|
|
3861
3912
|
() => this.lookupImportedNames(target, modules)
|
|
3862
|
-
)
|
|
3913
|
+
);
|
|
3863
3914
|
this.importedNames.set(declaration, {
|
|
3864
3915
|
names: found,
|
|
3865
3916
|
walked: [...this.lastQueryWalked]
|
|
@@ -3878,8 +3929,8 @@ var ResolutionStore = class {
|
|
|
3878
3929
|
return this.importOriginsOfMany([value], modules).get(value) ?? [];
|
|
3879
3930
|
}
|
|
3880
3931
|
/**
|
|
3881
|
-
* The batched form: one demand set, one derivation, one
|
|
3882
|
-
*
|
|
3932
|
+
* The batched form: one demand set, one derivation, one round of
|
|
3933
|
+
* extraction shared by every value. A discovery pass asks about every
|
|
3883
3934
|
* callee in a file, and per-value queries would re-pay demand
|
|
3884
3935
|
* clearing and re-derivation once per call site.
|
|
3885
3936
|
*/
|
|
@@ -3907,49 +3958,12 @@ var ResolutionStore = class {
|
|
|
3907
3958
|
this.wantValue("wantedCallOrigin", one.target);
|
|
3908
3959
|
this.seedValue(one.target);
|
|
3909
3960
|
}
|
|
3910
|
-
|
|
3911
|
-
this.lastQueryWalked = [];
|
|
3912
|
-
let frontier = [];
|
|
3961
|
+
this.extractDemanded(pending.map((one) => one.target.getSourceFile()));
|
|
3913
3962
|
for (const one of pending) {
|
|
3914
|
-
const
|
|
3915
|
-
|
|
3916
|
-
frontier.push(file);
|
|
3917
|
-
}
|
|
3918
|
-
}
|
|
3919
|
-
const open = new Set(pending);
|
|
3920
|
-
for (let hop = 0; hop <= MAX_MODULE_HOPS && open.size > 0; hop++) {
|
|
3921
|
-
const next = [];
|
|
3922
|
-
for (const sourceFile of frontier) {
|
|
3923
|
-
if (walked.has(sourceFile.getFilePath())) {
|
|
3924
|
-
continue;
|
|
3925
|
-
}
|
|
3926
|
-
walked.add(sourceFile.getFilePath());
|
|
3927
|
-
this.lastQueryWalked.push(sourceFile.getFilePath());
|
|
3928
|
-
recordFileDependency(sourceFile.getFilePath());
|
|
3929
|
-
this.extractFile(sourceFile);
|
|
3930
|
-
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
3931
|
-
}
|
|
3932
|
-
for (const one of [...open]) {
|
|
3933
|
-
const found = this.lookupImportOrigins(one.target, modules);
|
|
3934
|
-
if (found !== null) {
|
|
3935
|
-
results.set(one.value, found);
|
|
3936
|
-
this.importOrigins.set(one.key, {
|
|
3937
|
-
origins: found,
|
|
3938
|
-
walked: [...this.lastQueryWalked],
|
|
3939
|
-
extractedAt: this.fullyExtracted.size
|
|
3940
|
-
});
|
|
3941
|
-
open.delete(one);
|
|
3942
|
-
}
|
|
3943
|
-
}
|
|
3944
|
-
if (next.length === 0) {
|
|
3945
|
-
break;
|
|
3946
|
-
}
|
|
3947
|
-
frontier = next;
|
|
3948
|
-
}
|
|
3949
|
-
for (const one of open) {
|
|
3950
|
-
results.set(one.value, []);
|
|
3963
|
+
const origins = this.lookupImportOrigins(one.target, modules);
|
|
3964
|
+
results.set(one.value, origins);
|
|
3951
3965
|
this.importOrigins.set(one.key, {
|
|
3952
|
-
origins
|
|
3966
|
+
origins,
|
|
3953
3967
|
walked: [...this.lastQueryWalked],
|
|
3954
3968
|
extractedAt: this.fullyExtracted.size
|
|
3955
3969
|
});
|
|
@@ -4008,67 +4022,89 @@ var ResolutionStore = class {
|
|
|
4008
4022
|
const refined = new Set(
|
|
4009
4023
|
[...byPath.values()].filter((one) => one.path.length > 1).map((one) => (0, import_datalog2.tupleKey)(one.path.slice(0, -1)))
|
|
4010
4024
|
);
|
|
4011
|
-
|
|
4012
|
-
if (origins.length > 0) {
|
|
4013
|
-
return origins;
|
|
4014
|
-
}
|
|
4015
|
-
return all.some((one) => namesAPackage(one.module)) ? [] : null;
|
|
4025
|
+
return [...byPath.values()].filter((one) => !refined.has((0, import_datalog2.tupleKey)(one.path))).sort((a, b) => a.path.join(".").localeCompare(b.path.join(".")));
|
|
4016
4026
|
}
|
|
4017
|
-
/**
|
|
4018
|
-
* Null tells the walk to keep widening. A value that landed in a
|
|
4019
|
-
* package returns empty instead, because a library's own body is not
|
|
4020
|
-
* here to read and widening would never find anything.
|
|
4021
|
-
*/
|
|
4022
4027
|
lookupImportedNames(value, modules) {
|
|
4023
4028
|
this.derive();
|
|
4024
|
-
const
|
|
4025
|
-
|
|
4029
|
+
const reached = new Set(
|
|
4030
|
+
this.answerPairsFor("wantedComesFrom", nodeId(value))
|
|
4031
|
+
);
|
|
4026
4032
|
for (const target of this.answersFor("wantedComesTo", nodeId(value))) {
|
|
4027
4033
|
for (const entry of this.answerPairsFor("wantedCallsInto", target)) {
|
|
4028
4034
|
reached.add(entry);
|
|
4029
4035
|
}
|
|
4030
4036
|
}
|
|
4031
|
-
|
|
4032
|
-
if (names.length > 0) {
|
|
4033
|
-
return names;
|
|
4034
|
-
}
|
|
4035
|
-
return origins.some((pair) => namesAPackage(pairHalves(pair).module)) ? [] : null;
|
|
4037
|
+
return namesFrom([...reached], modules);
|
|
4036
4038
|
}
|
|
4037
|
-
|
|
4039
|
+
askAbout(value, question, read2, alsoFrom) {
|
|
4038
4040
|
try {
|
|
4039
|
-
|
|
4041
|
+
this.wantValue(question, value);
|
|
4042
|
+
this.seedValue(value);
|
|
4043
|
+
this.extractDemanded(
|
|
4044
|
+
alsoFrom === void 0 ? [value.getSourceFile()] : [value.getSourceFile(), alsoFrom]
|
|
4045
|
+
);
|
|
4046
|
+
return read2();
|
|
4040
4047
|
} finally {
|
|
4041
4048
|
this.forgetQuery();
|
|
4042
4049
|
}
|
|
4043
4050
|
}
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4051
|
+
/**
|
|
4052
|
+
* Extract the seed files, then every module the rules ask for, until
|
|
4053
|
+
* they ask for nothing new. The files a question reads are then fixed
|
|
4054
|
+
* by the question alone, so its answer does not depend on what an
|
|
4055
|
+
* earlier question left in the store.
|
|
4056
|
+
*/
|
|
4057
|
+
extractDemanded(seeds) {
|
|
4058
|
+
const project = seeds[0]?.getProject();
|
|
4059
|
+
if (project === void 0) {
|
|
4060
|
+
return;
|
|
4061
|
+
}
|
|
4062
|
+
const read2 = /* @__PURE__ */ new Set();
|
|
4063
|
+
const considered = /* @__PURE__ */ new Set();
|
|
4048
4064
|
this.lastQueryWalked = [];
|
|
4049
|
-
let
|
|
4050
|
-
|
|
4051
|
-
const
|
|
4052
|
-
for (const sourceFile of
|
|
4053
|
-
|
|
4065
|
+
let pending = [...seeds];
|
|
4066
|
+
while (pending.length > 0) {
|
|
4067
|
+
const readThisRound = [];
|
|
4068
|
+
for (const sourceFile of pending) {
|
|
4069
|
+
const filePath = sourceFile.getFilePath();
|
|
4070
|
+
if (read2.has(filePath)) {
|
|
4054
4071
|
continue;
|
|
4055
4072
|
}
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4073
|
+
read2.add(filePath);
|
|
4074
|
+
readThisRound.push(filePath);
|
|
4075
|
+
this.lastQueryWalked.push(filePath);
|
|
4076
|
+
recordFileDependency(filePath);
|
|
4059
4077
|
this.extractFile(sourceFile);
|
|
4060
|
-
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
4061
|
-
}
|
|
4062
|
-
const found = ask();
|
|
4063
|
-
if (found !== null) {
|
|
4064
|
-
return found;
|
|
4065
4078
|
}
|
|
4066
|
-
|
|
4067
|
-
|
|
4079
|
+
this.derive();
|
|
4080
|
+
pending = [];
|
|
4081
|
+
for (const moduleKey of this.demandedModules(readThisRound)) {
|
|
4082
|
+
if (considered.has(moduleKey)) {
|
|
4083
|
+
continue;
|
|
4084
|
+
}
|
|
4085
|
+
considered.add(moduleKey);
|
|
4086
|
+
const sourceFile = sourceFileFor(project, moduleKey);
|
|
4087
|
+
if (sourceFile !== void 0 && !read2.has(sourceFile.getFilePath())) {
|
|
4088
|
+
pending.push(sourceFile);
|
|
4089
|
+
}
|
|
4068
4090
|
}
|
|
4069
|
-
frontier = next;
|
|
4070
4091
|
}
|
|
4071
|
-
|
|
4092
|
+
}
|
|
4093
|
+
/**
|
|
4094
|
+
* Module keys the rules are waiting on. Demand facts are cleared
|
|
4095
|
+
* between queries, so the demand relations contain this query's
|
|
4096
|
+
* alone; the unrestricted program has none, and follows the imports
|
|
4097
|
+
* of the files read this round instead.
|
|
4098
|
+
*/
|
|
4099
|
+
demandedModules(readThisRound) {
|
|
4100
|
+
if (RESOLUTION_PROGRAM.demands.length === 0) {
|
|
4101
|
+
return readThisRound.flatMap(
|
|
4102
|
+
(filePath) => this.db.lookup("importsModule", 0, filePath).map((tuple) => String(tuple[1]))
|
|
4103
|
+
);
|
|
4104
|
+
}
|
|
4105
|
+
return MODULE_DEMANDS.flatMap(
|
|
4106
|
+
(relation) => this.db.facts(relation).map((tuple) => String(tuple[0]))
|
|
4107
|
+
);
|
|
4072
4108
|
}
|
|
4073
4109
|
/**
|
|
4074
4110
|
* The question and the chain that settled it are dropped. The files
|
|
@@ -4087,6 +4123,27 @@ var ResolutionStore = class {
|
|
|
4087
4123
|
this.stale = true;
|
|
4088
4124
|
}
|
|
4089
4125
|
}
|
|
4126
|
+
wantExportsOf(filePath) {
|
|
4127
|
+
if (this.db.add("wantedExportsOf", [filePath]) === "added") {
|
|
4128
|
+
this.stale = true;
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
/**
|
|
4132
|
+
* Discovery walks the table in order, and the rounds derive it in
|
|
4133
|
+
* the order files arrived. Deriving it again from the demand alone,
|
|
4134
|
+
* over the loaded closure, orders it by the file's own statements.
|
|
4135
|
+
*/
|
|
4136
|
+
rederiveExportsOf(filePath) {
|
|
4137
|
+
if (QUERY_FACTS.length === 0) {
|
|
4138
|
+
return;
|
|
4139
|
+
}
|
|
4140
|
+
this.db.retract("wantedModuleExport", [
|
|
4141
|
+
...this.db.lookup("wantedModuleExport", 0, filePath)
|
|
4142
|
+
]);
|
|
4143
|
+
this.forgetQuery();
|
|
4144
|
+
this.wantExportsOf(filePath);
|
|
4145
|
+
this.derive();
|
|
4146
|
+
}
|
|
4090
4147
|
/**
|
|
4091
4148
|
* File extraction only reaches values hanging off exports, and a query
|
|
4092
4149
|
* can be rooted anywhere, so the queried value gets its own facts.
|
|
@@ -4136,24 +4193,18 @@ var ResolutionStore = class {
|
|
|
4136
4193
|
}
|
|
4137
4194
|
candidates.add(node);
|
|
4138
4195
|
}
|
|
4139
|
-
if (candidates.size
|
|
4140
|
-
return
|
|
4141
|
-
}
|
|
4142
|
-
if (candidates.size > 1) {
|
|
4143
|
-
return { written: null };
|
|
4144
|
-
}
|
|
4145
|
-
if (neverWritable(value)) {
|
|
4146
|
-
return { written: null };
|
|
4196
|
+
if (candidates.size !== 1) {
|
|
4197
|
+
return null;
|
|
4147
4198
|
}
|
|
4148
|
-
return
|
|
4199
|
+
return [...candidates][0];
|
|
4149
4200
|
}
|
|
4150
4201
|
/**
|
|
4151
4202
|
* Read these files' facts now, before anything asks a question.
|
|
4152
4203
|
*
|
|
4153
|
-
* A query
|
|
4154
|
-
*
|
|
4204
|
+
* A query follows the imports of the file it starts in, which is
|
|
4205
|
+
* where a value's definition is. What a caller passed is the other
|
|
4155
4206
|
* direction, so a question about a parameter is answered only by
|
|
4156
|
-
* files the
|
|
4207
|
+
* files the query never reaches on its own.
|
|
4157
4208
|
*/
|
|
4158
4209
|
extractFiles(sourceFiles) {
|
|
4159
4210
|
for (const sourceFile of sourceFiles) {
|
|
@@ -4169,15 +4220,14 @@ var ResolutionStore = class {
|
|
|
4169
4220
|
return this.graph.filesReachingAnyPackage(fileSets);
|
|
4170
4221
|
}
|
|
4171
4222
|
/**
|
|
4172
|
-
* The calls behind a receiver that `matches` accepts
|
|
4173
|
-
*
|
|
4174
|
-
*
|
|
4175
|
-
*
|
|
4176
|
-
* cannot rank a nearer call above a farther one.
|
|
4223
|
+
* The calls behind a receiver that `matches` accepts. The caller
|
|
4224
|
+
* applies the single-answer policy to the set; the resolution
|
|
4225
|
+
* README's anchor section says why the rules cannot rank a nearer
|
|
4226
|
+
* call above a farther one.
|
|
4177
4227
|
*/
|
|
4178
4228
|
anchorCallsOf(value, matches) {
|
|
4179
4229
|
const target = factKeyOf(value);
|
|
4180
|
-
return this.
|
|
4230
|
+
return this.askAbout(target, "wantedAnchor", () => {
|
|
4181
4231
|
this.derive();
|
|
4182
4232
|
const found = [];
|
|
4183
4233
|
for (const id of this.answersFor("wantedAnchorCall", nodeId(target))) {
|
|
@@ -4186,12 +4236,12 @@ var ResolutionStore = class {
|
|
|
4186
4236
|
found.push(node);
|
|
4187
4237
|
}
|
|
4188
4238
|
}
|
|
4189
|
-
return found
|
|
4190
|
-
})
|
|
4239
|
+
return found;
|
|
4240
|
+
});
|
|
4191
4241
|
}
|
|
4192
4242
|
/**
|
|
4193
4243
|
* Every name a module exports and the values behind each, with
|
|
4194
|
-
* re-export chains flattened by the rules. The
|
|
4244
|
+
* re-export chains flattened by the rules. The demand follows
|
|
4195
4245
|
* re-export targets only, so a barrel of barrels extracts its own
|
|
4196
4246
|
* chain and nothing beside it, to any depth.
|
|
4197
4247
|
*/
|
|
@@ -4211,33 +4261,10 @@ var ResolutionStore = class {
|
|
|
4211
4261
|
}
|
|
4212
4262
|
}
|
|
4213
4263
|
collectExports(sourceFile) {
|
|
4214
|
-
const project = sourceFile.getProject();
|
|
4215
|
-
const walked = /* @__PURE__ */ new Set();
|
|
4216
|
-
let frontier = [sourceFile];
|
|
4217
|
-
while (frontier.length > 0) {
|
|
4218
|
-
const next = [];
|
|
4219
|
-
for (const file of frontier) {
|
|
4220
|
-
const filePath2 = file.getFilePath();
|
|
4221
|
-
if (walked.has(filePath2)) {
|
|
4222
|
-
continue;
|
|
4223
|
-
}
|
|
4224
|
-
walked.add(filePath2);
|
|
4225
|
-
recordFileDependency(filePath2);
|
|
4226
|
-
this.extractFile(file);
|
|
4227
|
-
for (const target of this.reExportTargetsOf(filePath2)) {
|
|
4228
|
-
const targetFile = sourceFileFor(project, target);
|
|
4229
|
-
if (targetFile !== void 0) {
|
|
4230
|
-
next.push(targetFile);
|
|
4231
|
-
}
|
|
4232
|
-
}
|
|
4233
|
-
}
|
|
4234
|
-
frontier = next;
|
|
4235
|
-
}
|
|
4236
4264
|
const filePath = sourceFile.getFilePath();
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
this.derive();
|
|
4265
|
+
this.wantExportsOf(filePath);
|
|
4266
|
+
this.extractDemanded([sourceFile]);
|
|
4267
|
+
this.rederiveExportsOf(filePath);
|
|
4241
4268
|
const exports2 = /* @__PURE__ */ new Map();
|
|
4242
4269
|
for (const tuple of this.db.lookup("wantedModuleExport", 0, filePath)) {
|
|
4243
4270
|
const node = this.table.byId.get(String(tuple[2]));
|
|
@@ -4254,22 +4281,9 @@ var ResolutionStore = class {
|
|
|
4254
4281
|
}
|
|
4255
4282
|
return exports2;
|
|
4256
4283
|
}
|
|
4257
|
-
/** Module keys this file re-exports from, read off its own facts. */
|
|
4258
|
-
reExportTargetsOf(filePath) {
|
|
4259
|
-
const targets = /* @__PURE__ */ new Set();
|
|
4260
|
-
for (const tuple of this.db.lookup("reExports", 0, filePath)) {
|
|
4261
|
-
targets.add(String(tuple[2]));
|
|
4262
|
-
}
|
|
4263
|
-
for (const tuple of this.db.lookup("reExportsAll", 0, filePath)) {
|
|
4264
|
-
targets.add(String(tuple[1]));
|
|
4265
|
-
}
|
|
4266
|
-
return [...targets];
|
|
4267
|
-
}
|
|
4268
4284
|
/**
|
|
4269
|
-
*
|
|
4270
|
-
*
|
|
4271
|
-
* single-answer policy stays with the callers: picking one of two
|
|
4272
|
-
* would make the result depend on the order the facts came in.
|
|
4285
|
+
* The single-answer policy stays with the callers: a value with two
|
|
4286
|
+
* sources is something to say at the site, not something to pick from.
|
|
4273
4287
|
*/
|
|
4274
4288
|
lookupSources(value) {
|
|
4275
4289
|
this.derive();
|
|
@@ -4283,7 +4297,7 @@ var ResolutionStore = class {
|
|
|
4283
4297
|
candidates.add(resolved);
|
|
4284
4298
|
}
|
|
4285
4299
|
}
|
|
4286
|
-
return
|
|
4300
|
+
return [...candidates];
|
|
4287
4301
|
}
|
|
4288
4302
|
derive() {
|
|
4289
4303
|
if (!this.stale) {
|
|
@@ -4342,18 +4356,6 @@ function pairHalves(pair) {
|
|
|
4342
4356
|
const [module2 = "", name = ""] = (0, import_datalog2.tupleKeyParts)(pair);
|
|
4343
4357
|
return { module: module2, name };
|
|
4344
4358
|
}
|
|
4345
|
-
function namesAPackage(moduleKey) {
|
|
4346
|
-
return !moduleKey.startsWith("/") || moduleKey.includes("/node_modules/");
|
|
4347
|
-
}
|
|
4348
|
-
function neverWritable(value) {
|
|
4349
|
-
if (!import_ts_morph16.Node.isIdentifier(value)) {
|
|
4350
|
-
return false;
|
|
4351
|
-
}
|
|
4352
|
-
const declarations = value.getSymbol()?.getDeclarations() ?? [];
|
|
4353
|
-
return declarations.some(
|
|
4354
|
-
(declaration) => declaration.getSourceFile().getFilePath().includes("/node_modules/")
|
|
4355
|
-
);
|
|
4356
|
-
}
|
|
4357
4359
|
function namesPackage2(moduleKey, packages) {
|
|
4358
4360
|
return namesAnyPackage(
|
|
4359
4361
|
[moduleKey, ...packagesDeclaring(moduleKey)],
|
|
@@ -4374,35 +4376,7 @@ var import_node_path3 = __toESM(require("path"), 1);
|
|
|
4374
4376
|
// src/diagnostics.ts
|
|
4375
4377
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
4376
4378
|
var import_ts_morph17 = require("ts-morph");
|
|
4377
|
-
var
|
|
4378
|
-
var emptyTally = () => ({
|
|
4379
|
-
candidateFiles: 0,
|
|
4380
|
-
unitsDiscovered: 0,
|
|
4381
|
-
unitsInGatedFiles: 0,
|
|
4382
|
-
effectsRecognized: 0,
|
|
4383
|
-
unitsClaimed: 0,
|
|
4384
|
-
selfCollisions: 0,
|
|
4385
|
-
summariesProduced: 0,
|
|
4386
|
-
failures: [],
|
|
4387
|
-
helpersMatched: /* @__PURE__ */ new Set()
|
|
4388
|
-
});
|
|
4389
|
-
function recordPackFailure(tally, failure) {
|
|
4390
|
-
const message = failure.error instanceof Error ? failure.error.message : String(failure.error);
|
|
4391
|
-
tally?.failures.push({
|
|
4392
|
-
hook: failure.hook,
|
|
4393
|
-
file: failure.file,
|
|
4394
|
-
message
|
|
4395
|
-
});
|
|
4396
|
-
return `[suss] pack "${failure.pack}" threw from ${failure.hook} while reading ${failure.file}: ${message}
|
|
4397
|
-
`;
|
|
4398
|
-
}
|
|
4399
|
-
function createPackTallies(packs) {
|
|
4400
|
-
const tallies = /* @__PURE__ */ new Map();
|
|
4401
|
-
for (const pack of packs) {
|
|
4402
|
-
tallies.set(pack.name, emptyTally());
|
|
4403
|
-
}
|
|
4404
|
-
return tallies;
|
|
4405
|
-
}
|
|
4379
|
+
var import_extractor3 = require("@suss/extractor");
|
|
4406
4380
|
function commonDirectoryOf(files) {
|
|
4407
4381
|
const absolute = files.filter((f) => import_node_path2.default.isAbsolute(f));
|
|
4408
4382
|
const first = absolute[0];
|
|
@@ -4479,30 +4453,6 @@ function unresolvedGatesFor(gates, args) {
|
|
|
4479
4453
|
}
|
|
4480
4454
|
return unresolved;
|
|
4481
4455
|
}
|
|
4482
|
-
var emptyCounts = () => ({
|
|
4483
|
-
bound: 0,
|
|
4484
|
-
providers: 0,
|
|
4485
|
-
withBehavior: 0
|
|
4486
|
-
});
|
|
4487
|
-
function summaryCountsByPack(summaries) {
|
|
4488
|
-
const counts = /* @__PURE__ */ new Map();
|
|
4489
|
-
for (const summary of summaries) {
|
|
4490
|
-
const recognition = summary.identity.boundaryBinding?.recognition;
|
|
4491
|
-
if (recognition === void 0 || recognition === null) {
|
|
4492
|
-
continue;
|
|
4493
|
-
}
|
|
4494
|
-
const entry = counts.get(recognition) ?? emptyCounts();
|
|
4495
|
-
entry.bound += 1;
|
|
4496
|
-
if (import_behavioral_ir.BOUNDARY_ROLE[summary.kind] === "provider") {
|
|
4497
|
-
entry.providers += 1;
|
|
4498
|
-
}
|
|
4499
|
-
if (summary.transitions.length > 0) {
|
|
4500
|
-
entry.withBehavior += 1;
|
|
4501
|
-
}
|
|
4502
|
-
counts.set(recognition, entry);
|
|
4503
|
-
}
|
|
4504
|
-
return counts;
|
|
4505
|
-
}
|
|
4506
4456
|
function helpersWithNoCall(patterns, matched, projectRoot) {
|
|
4507
4457
|
const missing = [];
|
|
4508
4458
|
for (const pattern of patterns) {
|
|
@@ -4523,11 +4473,15 @@ function shortModule(module2, projectRoot) {
|
|
|
4523
4473
|
return import_node_path2.default.relative(projectRoot, module2);
|
|
4524
4474
|
}
|
|
4525
4475
|
function buildExtractionReport(args) {
|
|
4526
|
-
const bySummary = summaryCountsByPack(args.summaries);
|
|
4476
|
+
const bySummary = (0, import_extractor3.summaryCountsByPack)(args.summaries);
|
|
4527
4477
|
const packFunnels = args.packs.map((pack) => {
|
|
4528
4478
|
const gates = packIsUngated(pack) ? [] : collectPackGates(pack);
|
|
4529
|
-
const tally = args.tallies.get(pack.name) ?? emptyTally();
|
|
4530
|
-
const counted = bySummary.get(pack.name) ??
|
|
4479
|
+
const tally = args.tallies.get(pack.name) ?? (0, import_extractor3.emptyTally)();
|
|
4480
|
+
const counted = bySummary.get(pack.name) ?? {
|
|
4481
|
+
bound: 0,
|
|
4482
|
+
providers: 0,
|
|
4483
|
+
withBehavior: 0
|
|
4484
|
+
};
|
|
4531
4485
|
return {
|
|
4532
4486
|
pack: pack.name,
|
|
4533
4487
|
version: pack.version ?? null,
|
|
@@ -4756,13 +4710,26 @@ function propertiesReached(object, resolution, seen) {
|
|
|
4756
4710
|
}
|
|
4757
4711
|
function writtenNodeOf(value, resolution) {
|
|
4758
4712
|
const written = factKeyOf(value);
|
|
4759
|
-
if (import_ts_morph18.Node.
|
|
4713
|
+
if (import_ts_morph18.Node.isNewExpression(written)) {
|
|
4760
4714
|
return written;
|
|
4761
4715
|
}
|
|
4716
|
+
if (import_ts_morph18.Node.isCallExpression(written)) {
|
|
4717
|
+
return writtenThroughCall(written, resolution);
|
|
4718
|
+
}
|
|
4762
4719
|
if (resolution === void 0 || !couldNameAValue(written)) {
|
|
4763
4720
|
return null;
|
|
4764
4721
|
}
|
|
4765
|
-
|
|
4722
|
+
const resolved = resolution.resolveWrittenValue(written);
|
|
4723
|
+
return resolved !== null && import_ts_morph18.Node.isCallExpression(resolved) ? writtenThroughCall(resolved, resolution) : resolved;
|
|
4724
|
+
}
|
|
4725
|
+
function writtenThroughCall(call, resolution) {
|
|
4726
|
+
if (resolution !== void 0 && resolution.resolveCallable(call.getExpression()) !== null) {
|
|
4727
|
+
const resolved = resolution.resolveWrittenValue(call);
|
|
4728
|
+
if (resolved !== null) {
|
|
4729
|
+
return resolved;
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
return call;
|
|
4766
4733
|
}
|
|
4767
4734
|
function stringValueOf(value, resolution) {
|
|
4768
4735
|
const written = factKeyOf(value);
|
|
@@ -4824,7 +4791,7 @@ function discoverClientCalls(sourceFile, match, kind, resolution) {
|
|
|
4824
4791
|
}
|
|
4825
4792
|
} else if (import_ts_morph19.Node.isPropertyAccessExpression(callee)) {
|
|
4826
4793
|
const subject = callee.getExpression();
|
|
4827
|
-
if (import_ts_morph19.Node.isIdentifier(subject) && (isClientImport(subject, match, resolution, true) || clientVarNames.has(subject.getText()) || resolvesToKnownInstance(subject, match, resolution))
|
|
4794
|
+
if (import_ts_morph19.Node.isIdentifier(subject) && (isClientImport(subject, match, resolution, true) || clientVarNames.has(subject.getText())) || resolvesToKnownInstance(subject, match, resolution)) {
|
|
4828
4795
|
methodName = callee.getName();
|
|
4829
4796
|
if (methodFilter === null || methodFilter.has(methodName)) {
|
|
4830
4797
|
matched = true;
|
|
@@ -6428,14 +6395,14 @@ function unitForJsxRoute(node, match, routeNames, kind, resolution) {
|
|
|
6428
6395
|
}
|
|
6429
6396
|
return routeUnit(node, kind, match.method, resolved.path, target, resolution);
|
|
6430
6397
|
}
|
|
6431
|
-
function routeUnit(at, kind, method,
|
|
6432
|
-
const routeInfo = { method, path:
|
|
6398
|
+
function routeUnit(at, kind, method, path14, target, resolution) {
|
|
6399
|
+
const routeInfo = { method, path: path14 };
|
|
6433
6400
|
if (target.kind === "unreadable") {
|
|
6434
6401
|
return {
|
|
6435
6402
|
func: null,
|
|
6436
6403
|
announcedAt: at,
|
|
6437
6404
|
kind,
|
|
6438
|
-
name:
|
|
6405
|
+
name: path14,
|
|
6439
6406
|
nameKind: "label",
|
|
6440
6407
|
routeInfo
|
|
6441
6408
|
};
|
|
@@ -6634,7 +6601,6 @@ function labelOfExpression(node) {
|
|
|
6634
6601
|
}
|
|
6635
6602
|
|
|
6636
6603
|
// src/discovery/packageExports.ts
|
|
6637
|
-
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
6638
6604
|
var import_ts_morph31 = require("ts-morph");
|
|
6639
6605
|
|
|
6640
6606
|
// src/packageExports.ts
|
|
@@ -6663,7 +6629,8 @@ function resolvePackageExports(packageJsonPath, opts = {}) {
|
|
|
6663
6629
|
packageName,
|
|
6664
6630
|
subPath,
|
|
6665
6631
|
exportPathPrefix: subPathToPrefix(subPath),
|
|
6666
|
-
sourceFile: src
|
|
6632
|
+
sourceFile: src,
|
|
6633
|
+
publishedFile: import_node_path5.default.resolve(pkgDir, distPath)
|
|
6667
6634
|
});
|
|
6668
6635
|
};
|
|
6669
6636
|
const exportsField = pkg.exports;
|
|
@@ -6683,6 +6650,53 @@ function resolvePackageExports(packageJsonPath, opts = {}) {
|
|
|
6683
6650
|
}
|
|
6684
6651
|
return { packageName, entries, warnings };
|
|
6685
6652
|
}
|
|
6653
|
+
var packageExportsCache = /* @__PURE__ */ new Map();
|
|
6654
|
+
var PATH_STAMP_SEPARATOR = "";
|
|
6655
|
+
function packageJsonStamp(packageJsonPath) {
|
|
6656
|
+
try {
|
|
6657
|
+
const stat = import_node_fs2.default.statSync(packageJsonPath);
|
|
6658
|
+
return `${stat.mtimeMs}:${stat.size}`;
|
|
6659
|
+
} catch {
|
|
6660
|
+
return "unreadable";
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
function resolvePackageExportsCached(packageJsonPath) {
|
|
6664
|
+
const stamp2 = packageJsonStamp(packageJsonPath);
|
|
6665
|
+
const key = `${packageJsonPath}${PATH_STAMP_SEPARATOR}${stamp2}`;
|
|
6666
|
+
const cached = packageExportsCache.get(key);
|
|
6667
|
+
if (cached !== void 0) {
|
|
6668
|
+
return cached;
|
|
6669
|
+
}
|
|
6670
|
+
const fresh = resolvePackageExports(packageJsonPath);
|
|
6671
|
+
packageExportsCache.set(key, fresh);
|
|
6672
|
+
return fresh;
|
|
6673
|
+
}
|
|
6674
|
+
function namedPackageDirAbove(start) {
|
|
6675
|
+
let at = import_node_path5.default.resolve(start);
|
|
6676
|
+
for (let up = 0; up < 12; up += 1) {
|
|
6677
|
+
if (packageNameAt(at) !== null) {
|
|
6678
|
+
return at;
|
|
6679
|
+
}
|
|
6680
|
+
const parent = import_node_path5.default.dirname(at);
|
|
6681
|
+
if (parent === at) {
|
|
6682
|
+
break;
|
|
6683
|
+
}
|
|
6684
|
+
at = parent;
|
|
6685
|
+
}
|
|
6686
|
+
return null;
|
|
6687
|
+
}
|
|
6688
|
+
function packageNameAt(dir) {
|
|
6689
|
+
try {
|
|
6690
|
+
const manifest = JSON.parse(
|
|
6691
|
+
import_node_fs2.default.readFileSync(import_node_path5.default.join(dir, "package.json"), "utf8")
|
|
6692
|
+
);
|
|
6693
|
+
if (typeof manifest.name === "string" && manifest.name.length > 0) {
|
|
6694
|
+
return manifest.name;
|
|
6695
|
+
}
|
|
6696
|
+
} catch {
|
|
6697
|
+
}
|
|
6698
|
+
return null;
|
|
6699
|
+
}
|
|
6686
6700
|
function pickConditional(value, warnings, key) {
|
|
6687
6701
|
if (value === void 0 || value === null) {
|
|
6688
6702
|
if (value === null) {
|
|
@@ -6732,8 +6746,55 @@ function resolveSourceFor(pkgDir, distPath, srcRoot) {
|
|
|
6732
6746
|
return null;
|
|
6733
6747
|
}
|
|
6734
6748
|
|
|
6749
|
+
// src/resolve/sourceDeclaration.ts
|
|
6750
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
6751
|
+
function sourceDeclarationsBehind(decl, resolution, visited = /* @__PURE__ */ new Set()) {
|
|
6752
|
+
const file = decl.getSourceFile();
|
|
6753
|
+
if (!file.isDeclarationFile() || file.isInNodeModules()) {
|
|
6754
|
+
return [decl];
|
|
6755
|
+
}
|
|
6756
|
+
const packageDir = namedPackageDirAbove(import_node_path6.default.dirname(file.getFilePath()));
|
|
6757
|
+
if (packageDir === null || visited.has(packageDir)) {
|
|
6758
|
+
return [decl];
|
|
6759
|
+
}
|
|
6760
|
+
visited.add(packageDir);
|
|
6761
|
+
const project = file.getProject();
|
|
6762
|
+
const { entries } = resolvePackageExportsCached(
|
|
6763
|
+
import_node_path6.default.join(packageDir, "package.json")
|
|
6764
|
+
);
|
|
6765
|
+
const found = [];
|
|
6766
|
+
for (const entry of entries) {
|
|
6767
|
+
const published = sourceFileFor(project, entry.publishedFile);
|
|
6768
|
+
const source = sourceFileFor(project, entry.sourceFile);
|
|
6769
|
+
if (published === void 0 || source === void 0) {
|
|
6770
|
+
continue;
|
|
6771
|
+
}
|
|
6772
|
+
for (const [name, nodes] of resolution.exportsOf(published)) {
|
|
6773
|
+
if (!nodes.some((node) => sameDeclaration(node, decl))) {
|
|
6774
|
+
continue;
|
|
6775
|
+
}
|
|
6776
|
+
for (const behind of resolution.exportsOf(source).get(name) ?? []) {
|
|
6777
|
+
for (const candidate of sourceDeclarationsBehind(
|
|
6778
|
+
behind,
|
|
6779
|
+
resolution,
|
|
6780
|
+
visited
|
|
6781
|
+
)) {
|
|
6782
|
+
if (!found.includes(candidate)) {
|
|
6783
|
+
found.push(candidate);
|
|
6784
|
+
}
|
|
6785
|
+
}
|
|
6786
|
+
}
|
|
6787
|
+
}
|
|
6788
|
+
}
|
|
6789
|
+
return found.length > 0 ? found : [decl];
|
|
6790
|
+
}
|
|
6791
|
+
function sameDeclaration(a, b) {
|
|
6792
|
+
return a === b || a.getSourceFile().getFilePath() === b.getSourceFile().getFilePath() && a.getStart() === b.getStart() && a.getEnd() === b.getEnd();
|
|
6793
|
+
}
|
|
6794
|
+
|
|
6735
6795
|
// src/discovery/factorySurface.ts
|
|
6736
6796
|
var import_ts_morph30 = require("ts-morph");
|
|
6797
|
+
var MAX_BUILDER_HOPS = 2;
|
|
6737
6798
|
function surfaceMethods(decl) {
|
|
6738
6799
|
if (import_ts_morph30.Node.isClassDeclaration(decl)) {
|
|
6739
6800
|
return surfaceClassMethods(decl);
|
|
@@ -6773,16 +6834,20 @@ function surfaceClassMethods(cls) {
|
|
|
6773
6834
|
function surfaceFactoryReturnMethods(fn) {
|
|
6774
6835
|
const out = [];
|
|
6775
6836
|
const seen = /* @__PURE__ */ new Set();
|
|
6837
|
+
collectFromFunctionReturns(fn, out, seen, 0);
|
|
6838
|
+
return out;
|
|
6839
|
+
}
|
|
6840
|
+
function collectFromFunctionReturns(fn, out, seen, depth) {
|
|
6776
6841
|
if (import_ts_morph30.Node.isArrowFunction(fn)) {
|
|
6777
6842
|
const body2 = fn.getBody();
|
|
6778
6843
|
if (import_ts_morph30.Node.isExpression(body2)) {
|
|
6779
|
-
|
|
6780
|
-
return
|
|
6844
|
+
collectFromReturnValue(body2, out, seen, depth);
|
|
6845
|
+
return;
|
|
6781
6846
|
}
|
|
6782
6847
|
}
|
|
6783
6848
|
const body = fn.getBody?.();
|
|
6784
6849
|
if (body === void 0) {
|
|
6785
|
-
return
|
|
6850
|
+
return;
|
|
6786
6851
|
}
|
|
6787
6852
|
const returns = [];
|
|
6788
6853
|
body.forEachDescendant((node, traversal) => {
|
|
@@ -6799,9 +6864,53 @@ function surfaceFactoryReturnMethods(fn) {
|
|
|
6799
6864
|
if (expr === void 0) {
|
|
6800
6865
|
continue;
|
|
6801
6866
|
}
|
|
6867
|
+
collectFromReturnValue(expr, out, seen, depth);
|
|
6868
|
+
}
|
|
6869
|
+
}
|
|
6870
|
+
function collectFromReturnValue(node, out, seen, depth) {
|
|
6871
|
+
const expr = peelParens(node);
|
|
6872
|
+
if (import_ts_morph30.Node.isObjectLiteralExpression(expr)) {
|
|
6802
6873
|
collectFromObjectLiteral(expr, out, seen);
|
|
6874
|
+
return;
|
|
6803
6875
|
}
|
|
6804
|
-
|
|
6876
|
+
if (depth >= MAX_BUILDER_HOPS || !import_ts_morph30.Node.isCallExpression(expr)) {
|
|
6877
|
+
return;
|
|
6878
|
+
}
|
|
6879
|
+
const callee = expr.getExpression();
|
|
6880
|
+
if (!import_ts_morph30.Node.isIdentifier(callee)) {
|
|
6881
|
+
return;
|
|
6882
|
+
}
|
|
6883
|
+
const helper = sameFileFunctionBehind(callee);
|
|
6884
|
+
if (helper !== null) {
|
|
6885
|
+
collectFromFunctionReturns(helper, out, seen, depth + 1);
|
|
6886
|
+
}
|
|
6887
|
+
}
|
|
6888
|
+
function sameFileFunctionBehind(id) {
|
|
6889
|
+
const symbol = id.getSymbol();
|
|
6890
|
+
if (symbol === void 0) {
|
|
6891
|
+
return null;
|
|
6892
|
+
}
|
|
6893
|
+
return functionAmong(
|
|
6894
|
+
symbol.getDeclarations(),
|
|
6895
|
+
id.getSourceFile().getFilePath()
|
|
6896
|
+
);
|
|
6897
|
+
}
|
|
6898
|
+
function functionAmong(declarations, filePath) {
|
|
6899
|
+
for (const decl of declarations) {
|
|
6900
|
+
if (decl.getSourceFile().getFilePath() !== filePath) {
|
|
6901
|
+
continue;
|
|
6902
|
+
}
|
|
6903
|
+
if (import_ts_morph30.Node.isFunctionDeclaration(decl)) {
|
|
6904
|
+
return decl;
|
|
6905
|
+
}
|
|
6906
|
+
if (import_ts_morph30.Node.isVariableDeclaration(decl)) {
|
|
6907
|
+
const init = decl.getInitializer();
|
|
6908
|
+
if (init !== void 0 && (import_ts_morph30.Node.isArrowFunction(init) || import_ts_morph30.Node.isFunctionExpression(init))) {
|
|
6909
|
+
return init;
|
|
6910
|
+
}
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6913
|
+
return null;
|
|
6805
6914
|
}
|
|
6806
6915
|
function collectFromObjectLiteral(node, out, seen) {
|
|
6807
6916
|
const e = peelParens(node);
|
|
@@ -6836,31 +6945,31 @@ function collectFromObjectLiteral(node, out, seen) {
|
|
|
6836
6945
|
out.push({ func: v3, name });
|
|
6837
6946
|
}
|
|
6838
6947
|
}
|
|
6948
|
+
if (import_ts_morph30.Node.isShorthandPropertyAssignment(prop)) {
|
|
6949
|
+
collectShorthandFunction(prop, out, seen);
|
|
6950
|
+
}
|
|
6839
6951
|
}
|
|
6840
6952
|
}
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
function packageJsonStamp(packageJsonPath) {
|
|
6846
|
-
try {
|
|
6847
|
-
const stat = import_node_fs3.default.statSync(packageJsonPath);
|
|
6848
|
-
return `${stat.mtimeMs}:${stat.size}`;
|
|
6849
|
-
} catch {
|
|
6850
|
-
return "unreadable";
|
|
6953
|
+
function collectShorthandFunction(prop, out, seen) {
|
|
6954
|
+
const name = prop.getName();
|
|
6955
|
+
if (seen.has(name)) {
|
|
6956
|
+
return;
|
|
6851
6957
|
}
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
const
|
|
6857
|
-
|
|
6858
|
-
|
|
6958
|
+
const symbol = prop.getValueSymbol();
|
|
6959
|
+
if (symbol === void 0) {
|
|
6960
|
+
return;
|
|
6961
|
+
}
|
|
6962
|
+
const fn = functionAmong(
|
|
6963
|
+
symbol.getDeclarations(),
|
|
6964
|
+
prop.getSourceFile().getFilePath()
|
|
6965
|
+
);
|
|
6966
|
+
if (fn !== null) {
|
|
6967
|
+
seen.add(name);
|
|
6968
|
+
out.push({ func: fn, name });
|
|
6859
6969
|
}
|
|
6860
|
-
const fresh = resolvePackageExports(packageJsonPath);
|
|
6861
|
-
packageExportsCache.set(key, fresh);
|
|
6862
|
-
return fresh;
|
|
6863
6970
|
}
|
|
6971
|
+
|
|
6972
|
+
// src/discovery/packageExports.ts
|
|
6864
6973
|
function discoverPackageExports(sourceFile, match, kind, resolution) {
|
|
6865
6974
|
if (match.packageJsonPath === void 0) {
|
|
6866
6975
|
return [];
|
|
@@ -6895,7 +7004,10 @@ function discoverPackageExports(sourceFile, match, kind, resolution) {
|
|
|
6895
7004
|
if (seenNames.has(key)) {
|
|
6896
7005
|
continue;
|
|
6897
7006
|
}
|
|
6898
|
-
|
|
7007
|
+
const candidates = decls.flatMap(
|
|
7008
|
+
(decl) => sourceDeclarationsBehind(decl, resolution)
|
|
7009
|
+
);
|
|
7010
|
+
for (const decl of candidates) {
|
|
6899
7011
|
if (import_ts_morph31.Node.isVariableDeclaration(decl)) {
|
|
6900
7012
|
const init = decl.getInitializer();
|
|
6901
7013
|
if (init !== void 0 && (import_ts_morph31.Node.isArrowFunction(init) || import_ts_morph31.Node.isFunctionExpression(init))) {
|
|
@@ -7048,7 +7160,7 @@ function attributedCalls(sourceFile, packages, resolution) {
|
|
|
7048
7160
|
return null;
|
|
7049
7161
|
}
|
|
7050
7162
|
if (!methodComesFromSource(callee)) {
|
|
7051
|
-
return
|
|
7163
|
+
return null;
|
|
7052
7164
|
}
|
|
7053
7165
|
return {
|
|
7054
7166
|
packageName: subject.packageName,
|
|
@@ -7162,12 +7274,12 @@ function originEndOf(flattened) {
|
|
|
7162
7274
|
const slash = flattened.indexOf("/", opener[0].length);
|
|
7163
7275
|
return slash === -1 ? flattened.length : slash;
|
|
7164
7276
|
}
|
|
7165
|
-
function appendPathText(
|
|
7277
|
+
function appendPathText(path14, text) {
|
|
7166
7278
|
const idx = text.search(/[?#]/);
|
|
7167
7279
|
if (idx === -1) {
|
|
7168
|
-
return { path:
|
|
7280
|
+
return { path: path14 + text, stop: false };
|
|
7169
7281
|
}
|
|
7170
|
-
return { path:
|
|
7282
|
+
return { path: path14 + text.slice(0, idx), stop: true };
|
|
7171
7283
|
}
|
|
7172
7284
|
function parseAbsoluteUrl(text) {
|
|
7173
7285
|
try {
|
|
@@ -7191,8 +7303,8 @@ function pathnameOfAbsoluteLiteral(text) {
|
|
|
7191
7303
|
return stripQueryAndFragment(stripOriginManually(text));
|
|
7192
7304
|
}
|
|
7193
7305
|
function pathFromLiteralUrl(text) {
|
|
7194
|
-
const
|
|
7195
|
-
return
|
|
7306
|
+
const path14 = isAbsoluteUrlLiteral(text) ? pathnameOfAbsoluteLiteral(text) : stripQueryAndFragment(text);
|
|
7307
|
+
return path14 === "" ? void 0 : path14;
|
|
7196
7308
|
}
|
|
7197
7309
|
function pathFromTemplateUrl(arg, resolution) {
|
|
7198
7310
|
const headText = arg.getHead().getLiteralText();
|
|
@@ -7200,7 +7312,7 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
7200
7312
|
const tails = spans.map((span) => span.getLiteral().getLiteralText());
|
|
7201
7313
|
const originEnd = originEndOf([headText, ...tails].join(SUBSTITUTION));
|
|
7202
7314
|
const head = appendPathText("", headText.slice(originEnd));
|
|
7203
|
-
let
|
|
7315
|
+
let path14 = head.path;
|
|
7204
7316
|
let stop = head.stop;
|
|
7205
7317
|
let at = headText.length;
|
|
7206
7318
|
for (let i = 0; i < spans.length && !stop; i++) {
|
|
@@ -7210,18 +7322,18 @@ function pathFromTemplateUrl(arg, resolution) {
|
|
|
7210
7322
|
continue;
|
|
7211
7323
|
}
|
|
7212
7324
|
if (at >= originEnd) {
|
|
7213
|
-
|
|
7325
|
+
path14 += holeText(span.getExpression(), resolution);
|
|
7214
7326
|
}
|
|
7215
7327
|
at += SUBSTITUTION.length;
|
|
7216
7328
|
const appended = appendPathText(
|
|
7217
|
-
|
|
7329
|
+
path14,
|
|
7218
7330
|
tailText.slice(Math.max(0, originEnd - at))
|
|
7219
7331
|
);
|
|
7220
|
-
|
|
7332
|
+
path14 = appended.path;
|
|
7221
7333
|
stop = appended.stop;
|
|
7222
7334
|
at += tailText.length;
|
|
7223
7335
|
}
|
|
7224
|
-
return
|
|
7336
|
+
return path14 === "" ? void 0 : path14;
|
|
7225
7337
|
}
|
|
7226
7338
|
function pathFromUrlNode(node, resolution) {
|
|
7227
7339
|
if (import_ts_morph33.Node.isStringLiteral(node)) {
|
|
@@ -7291,12 +7403,12 @@ function discoverRegistrationCalls(sourceFile, match, kind, bindingExtraction, r
|
|
|
7291
7403
|
match.importName,
|
|
7292
7404
|
resolution
|
|
7293
7405
|
);
|
|
7294
|
-
if (registrationSubjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution)) {
|
|
7295
|
-
return results;
|
|
7296
|
-
}
|
|
7297
7406
|
const registrationMethods = match.registrationChain.map(
|
|
7298
7407
|
(c) => c.startsWith(".") ? c.slice(1) : c
|
|
7299
7408
|
);
|
|
7409
|
+
if (registrationSubjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution, registrationMethods)) {
|
|
7410
|
+
return results;
|
|
7411
|
+
}
|
|
7300
7412
|
sourceFile.forEachDescendant((node) => {
|
|
7301
7413
|
if (!import_ts_morph34.Node.isCallExpression(node)) {
|
|
7302
7414
|
return;
|
|
@@ -7490,8 +7602,54 @@ function receiverOf(subject, subjects, match, resolution) {
|
|
|
7490
7602
|
);
|
|
7491
7603
|
return candidates > 1 ? { kind: "several", candidates } : NOT_A_ROUTABLE;
|
|
7492
7604
|
}
|
|
7493
|
-
function storeCanFindSubjects(sourceFile, match, resolution) {
|
|
7494
|
-
|
|
7605
|
+
function storeCanFindSubjects(sourceFile, match, resolution, methods = []) {
|
|
7606
|
+
if (resolution === void 0) {
|
|
7607
|
+
return false;
|
|
7608
|
+
}
|
|
7609
|
+
if (importDeclarationsOf(sourceFile, [match.importModule]).length > 0) {
|
|
7610
|
+
return true;
|
|
7611
|
+
}
|
|
7612
|
+
return methods.length > 0 && callsOnCallResult(sourceFile, methods);
|
|
7613
|
+
}
|
|
7614
|
+
function callsOnCallResult(sourceFile, methods) {
|
|
7615
|
+
let called = methodsCalledOnCallResults.get(sourceFile);
|
|
7616
|
+
if (called === void 0) {
|
|
7617
|
+
called = collectMethodsCalledOnCallResults(sourceFile);
|
|
7618
|
+
methodsCalledOnCallResults.set(sourceFile, called);
|
|
7619
|
+
}
|
|
7620
|
+
return methods.some((method) => called.has(method));
|
|
7621
|
+
}
|
|
7622
|
+
var methodsCalledOnCallResults = /* @__PURE__ */ new WeakMap();
|
|
7623
|
+
function collectMethodsCalledOnCallResults(sourceFile) {
|
|
7624
|
+
const setToCalls = /* @__PURE__ */ new Set();
|
|
7625
|
+
const calledOn = /* @__PURE__ */ new Map();
|
|
7626
|
+
sourceFile.forEachDescendant((node) => {
|
|
7627
|
+
if (import_ts_morph34.Node.isVariableDeclaration(node)) {
|
|
7628
|
+
const init = node.getInitializer();
|
|
7629
|
+
if (init !== void 0 && import_ts_morph34.Node.isCallExpression(init)) {
|
|
7630
|
+
setToCalls.add(node.getName());
|
|
7631
|
+
}
|
|
7632
|
+
return;
|
|
7633
|
+
}
|
|
7634
|
+
if (!import_ts_morph34.Node.isCallExpression(node)) {
|
|
7635
|
+
return;
|
|
7636
|
+
}
|
|
7637
|
+
const callee = node.getExpression();
|
|
7638
|
+
if (!import_ts_morph34.Node.isPropertyAccessExpression(callee) || !import_ts_morph34.Node.isIdentifier(callee.getExpression())) {
|
|
7639
|
+
return;
|
|
7640
|
+
}
|
|
7641
|
+
const receiver = callee.getExpression().getText();
|
|
7642
|
+
const methods = calledOn.get(receiver) ?? /* @__PURE__ */ new Set();
|
|
7643
|
+
methods.add(callee.getName());
|
|
7644
|
+
calledOn.set(receiver, methods);
|
|
7645
|
+
});
|
|
7646
|
+
const called = /* @__PURE__ */ new Set();
|
|
7647
|
+
for (const name of setToCalls) {
|
|
7648
|
+
for (const method of calledOn.get(name) ?? []) {
|
|
7649
|
+
called.add(method);
|
|
7650
|
+
}
|
|
7651
|
+
}
|
|
7652
|
+
return called;
|
|
7495
7653
|
}
|
|
7496
7654
|
function registrationSubjectsOf(sourceFile, importModule, importName, resolution) {
|
|
7497
7655
|
const importedLocalName = resolveImportedLocalName(
|
|
@@ -7556,9 +7714,33 @@ function registrationSubjectIdsOf(sourceFile, matches, resolution) {
|
|
|
7556
7714
|
).values()) {
|
|
7557
7715
|
ids.add(nodeId(node));
|
|
7558
7716
|
}
|
|
7717
|
+
for (const node of unboundConstructionsOf(
|
|
7718
|
+
sourceFile,
|
|
7719
|
+
match.importModule,
|
|
7720
|
+
match.importName
|
|
7721
|
+
)) {
|
|
7722
|
+
ids.add(nodeId(node));
|
|
7723
|
+
}
|
|
7559
7724
|
}
|
|
7560
7725
|
return ids;
|
|
7561
7726
|
}
|
|
7727
|
+
function unboundConstructionsOf(sourceFile, importModule, importName) {
|
|
7728
|
+
const importedLocalName = resolveImportedLocalName(
|
|
7729
|
+
sourceFile,
|
|
7730
|
+
importModule,
|
|
7731
|
+
importName
|
|
7732
|
+
);
|
|
7733
|
+
if (importedLocalName === null) {
|
|
7734
|
+
return [];
|
|
7735
|
+
}
|
|
7736
|
+
const constructions = [];
|
|
7737
|
+
sourceFile.forEachDescendant((node) => {
|
|
7738
|
+
if ((import_ts_morph34.Node.isCallExpression(node) || import_ts_morph34.Node.isNewExpression(node)) && node.getExpression().getText() === importedLocalName && !import_ts_morph34.Node.isVariableDeclaration(node.getParent())) {
|
|
7739
|
+
constructions.push(node);
|
|
7740
|
+
}
|
|
7741
|
+
});
|
|
7742
|
+
return constructions;
|
|
7743
|
+
}
|
|
7562
7744
|
function discoverMountEdges(sourceFile, match, mount, knownSubjectIds, resolution) {
|
|
7563
7745
|
const subjects = registrationSubjectsOf(
|
|
7564
7746
|
sourceFile,
|
|
@@ -7566,7 +7748,7 @@ function discoverMountEdges(sourceFile, match, mount, knownSubjectIds, resolutio
|
|
|
7566
7748
|
match.importName,
|
|
7567
7749
|
resolution
|
|
7568
7750
|
);
|
|
7569
|
-
if (subjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution)) {
|
|
7751
|
+
if (subjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution, [mount.method])) {
|
|
7570
7752
|
return [];
|
|
7571
7753
|
}
|
|
7572
7754
|
const edges = [];
|
|
@@ -7647,11 +7829,11 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
7647
7829
|
return null;
|
|
7648
7830
|
}
|
|
7649
7831
|
const method2 = stringProperty(routeObject, binding.method.property);
|
|
7650
|
-
const
|
|
7651
|
-
if (method2 === null ||
|
|
7832
|
+
const path15 = stringProperty(routeObject, binding.path.property);
|
|
7833
|
+
if (method2 === null || path15 === null) {
|
|
7652
7834
|
return null;
|
|
7653
7835
|
}
|
|
7654
|
-
return { method: method2.toUpperCase(), path:
|
|
7836
|
+
return { method: method2.toUpperCase(), path: path15 };
|
|
7655
7837
|
}
|
|
7656
7838
|
if (binding.method.type !== "fromRegistration" || binding.path.type !== "fromArgument") {
|
|
7657
7839
|
return null;
|
|
@@ -7668,8 +7850,8 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
7668
7850
|
method = arg.getLiteralValue().toUpperCase();
|
|
7669
7851
|
}
|
|
7670
7852
|
const pathArg = call.getArguments()[binding.path.position];
|
|
7671
|
-
const
|
|
7672
|
-
return
|
|
7853
|
+
const path14 = pathArg === void 0 ? void 0 : pathFromArgument(pathArg, resolution);
|
|
7854
|
+
return path14 === void 0 ? null : { method, path: path14 };
|
|
7673
7855
|
}
|
|
7674
7856
|
|
|
7675
7857
|
// src/discovery/registrationLoop.ts
|
|
@@ -7801,7 +7983,7 @@ function bodyCallsOnRoutable(loop, guard, resolution) {
|
|
|
7801
7983
|
}
|
|
7802
7984
|
function readRouteSpec(element, shape, resolution) {
|
|
7803
7985
|
let method = null;
|
|
7804
|
-
let
|
|
7986
|
+
let path14 = null;
|
|
7805
7987
|
let handler = null;
|
|
7806
7988
|
for (const prop of element.getProperties()) {
|
|
7807
7989
|
if (import_ts_morph35.Node.isMethodDeclaration(prop) && prop.getName() === shape.handlerKey) {
|
|
@@ -7819,16 +8001,16 @@ function readRouteSpec(element, shape, resolution) {
|
|
|
7819
8001
|
if (name === shape.methodKey) {
|
|
7820
8002
|
method = readStringLiteralValue(init);
|
|
7821
8003
|
} else if (name === shape.pathKey) {
|
|
7822
|
-
|
|
8004
|
+
path14 = readStringLiteralValue(init);
|
|
7823
8005
|
} else if (name === shape.handlerKey) {
|
|
7824
8006
|
const func = functionValueOf(init, resolution);
|
|
7825
8007
|
handler = func === null ? null : { func, name: handlerName(init) };
|
|
7826
8008
|
}
|
|
7827
8009
|
}
|
|
7828
|
-
if (method === null ||
|
|
8010
|
+
if (method === null || path14 === null || handler === null) {
|
|
7829
8011
|
return null;
|
|
7830
8012
|
}
|
|
7831
|
-
return { method, path:
|
|
8013
|
+
return { method, path: path14, handler: handler.func, handlerName: handler.name };
|
|
7832
8014
|
}
|
|
7833
8015
|
function readStringLiteralValue(node) {
|
|
7834
8016
|
if (import_ts_morph35.Node.isStringLiteral(node) || import_ts_morph35.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
@@ -7841,12 +8023,13 @@ function handlerName(value) {
|
|
|
7841
8023
|
}
|
|
7842
8024
|
|
|
7843
8025
|
// src/discovery/registrationTemplate.ts
|
|
7844
|
-
var
|
|
8026
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
7845
8027
|
var import_ts_morph37 = require("ts-morph");
|
|
7846
8028
|
var import_resolution4 = require("@suss/resolution");
|
|
7847
8029
|
|
|
7848
8030
|
// src/resolve/unfollowedCall.ts
|
|
7849
8031
|
var import_ts_morph36 = require("ts-morph");
|
|
8032
|
+
var import_behavioral_ir3 = require("@suss/behavioral-ir");
|
|
7850
8033
|
function isInExternalCode(sourceFile) {
|
|
7851
8034
|
if (sourceFile.isDeclarationFile()) {
|
|
7852
8035
|
return true;
|
|
@@ -7900,6 +8083,19 @@ function declarationsBehind(symbol) {
|
|
|
7900
8083
|
function isParameterOf(declaration, scanning) {
|
|
7901
8084
|
return import_ts_morph36.Node.isParameterDeclaration(declaration) && declaration.getParent() === scanning;
|
|
7902
8085
|
}
|
|
8086
|
+
function parameterIndexOf(declarations, scanning) {
|
|
8087
|
+
if (scanning === void 0) {
|
|
8088
|
+
return void 0;
|
|
8089
|
+
}
|
|
8090
|
+
const params = scanning.getParameters();
|
|
8091
|
+
for (const declaration of declarations) {
|
|
8092
|
+
const index = params.findIndex((param) => param === declaration);
|
|
8093
|
+
if (index !== -1) {
|
|
8094
|
+
return index;
|
|
8095
|
+
}
|
|
8096
|
+
}
|
|
8097
|
+
return void 0;
|
|
8098
|
+
}
|
|
7903
8099
|
function classifyStop(declarations, scanning) {
|
|
7904
8100
|
if (declarations.length === 0) {
|
|
7905
8101
|
return "noDeclaration";
|
|
@@ -7920,36 +8116,6 @@ function classifyStop(declarations, scanning) {
|
|
|
7920
8116
|
}
|
|
7921
8117
|
return "unsettledValue";
|
|
7922
8118
|
}
|
|
7923
|
-
var RECORDED = {
|
|
7924
|
-
noBody: true,
|
|
7925
|
-
unsettledValue: true,
|
|
7926
|
-
multipleSources: true,
|
|
7927
|
-
outsideRun: false,
|
|
7928
|
-
noDeclaration: false,
|
|
7929
|
-
callerSupplied: false,
|
|
7930
|
-
multipleReceivers: true
|
|
7931
|
-
};
|
|
7932
|
-
function worthRecording(reason) {
|
|
7933
|
-
return RECORDED[reason];
|
|
7934
|
-
}
|
|
7935
|
-
var STOP_SENTENCE = {
|
|
7936
|
-
noBody: ({ callee }) => `The call to ${callee} lands on a declaration with no body, so whatever runs there is missing from this summary`,
|
|
7937
|
-
unsettledValue: ({ callee }) => `The call to ${callee} goes through a value this run could not settle, so whatever runs there is missing from this summary`,
|
|
7938
|
-
multipleSources: ({ callee }) => `The call to ${callee} reaches a value with more than one possible source, so whatever runs there is missing from this summary`,
|
|
7939
|
-
outsideRun: ({ callee }) => `The call to ${callee} lands in a package whose source is not in this run, so whatever runs there is missing from this summary`,
|
|
7940
|
-
noDeclaration: ({ callee }) => `The call to ${callee} has no declaration this run could find, so whatever runs there is missing from this summary`,
|
|
7941
|
-
callerSupplied: ({ callee }) => `The call to ${callee} runs the function this unit's caller passed in, so what happens there is decided at the call site`,
|
|
7942
|
-
multipleReceivers: ({ callee, candidates }) => `The call to ${callee} is made on a receiver this run reads as ${candidates ?? "several"} different values, so nothing says which one it registers on and the registration is left out`
|
|
7943
|
-
};
|
|
7944
|
-
function unfollowedCallGap(stop) {
|
|
7945
|
-
return {
|
|
7946
|
-
type: "unfollowedCall",
|
|
7947
|
-
conditions: [],
|
|
7948
|
-
consequence: "unknown",
|
|
7949
|
-
description: STOP_SENTENCE[stop.reason](stop),
|
|
7950
|
-
callee: stop.callee
|
|
7951
|
-
};
|
|
7952
|
-
}
|
|
7953
8119
|
|
|
7954
8120
|
// src/discovery/registrationTemplate.ts
|
|
7955
8121
|
function discoverRegistrationTemplates(sourceFile, match, kind, resolution, mountPrefixes) {
|
|
@@ -7959,8 +8125,8 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution, moun
|
|
|
7959
8125
|
const subject = subjectOfCall(sourceFile, args, match, resolution);
|
|
7960
8126
|
const prefix = subject === void 0 ? "" : mountPrefixes?.effectivePrefixFor(subject) ?? "";
|
|
7961
8127
|
for (const reg of match.registrations) {
|
|
7962
|
-
const
|
|
7963
|
-
if (
|
|
8128
|
+
const path14 = substitutePath(reg.pathTemplate, args);
|
|
8129
|
+
if (path14 === null) {
|
|
7964
8130
|
continue;
|
|
7965
8131
|
}
|
|
7966
8132
|
const handler = resolveHandler(reg.handlerArg, args, resolution);
|
|
@@ -7974,7 +8140,7 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution, moun
|
|
|
7974
8140
|
...subject === void 0 ? {} : { registrationSubjectId: nodeId(subject) },
|
|
7975
8141
|
routeInfo: {
|
|
7976
8142
|
method: reg.method.toUpperCase(),
|
|
7977
|
-
path: prefix === "" ?
|
|
8143
|
+
path: prefix === "" ? path14 : (0, import_resolution4.joinMountedPath)(prefix, path14)
|
|
7978
8144
|
}
|
|
7979
8145
|
});
|
|
7980
8146
|
}
|
|
@@ -8007,7 +8173,7 @@ function subjectOfCall(sourceFile, args, match, resolution) {
|
|
|
8007
8173
|
}
|
|
8008
8174
|
function helperCallsOf(sourceFile, match, resolution) {
|
|
8009
8175
|
const module2 = match.importModule;
|
|
8010
|
-
if (module2 !== void 0 && !
|
|
8176
|
+
if (module2 !== void 0 && !import_node_path7.default.isAbsolute(module2)) {
|
|
8011
8177
|
const store = resolution ?? new ResolutionStore();
|
|
8012
8178
|
return callsResolvingTo(sourceFile, store, {
|
|
8013
8179
|
module: module2,
|
|
@@ -8453,24 +8619,24 @@ function declName(decl) {
|
|
|
8453
8619
|
|
|
8454
8620
|
// src/parameterReads.ts
|
|
8455
8621
|
function pathAbove(reference) {
|
|
8456
|
-
const
|
|
8622
|
+
const path14 = [];
|
|
8457
8623
|
let current2 = reference;
|
|
8458
8624
|
for (; ; ) {
|
|
8459
8625
|
const parent = current2.getParent();
|
|
8460
8626
|
if (parent !== void 0 && import_ts_morph40.Node.isPropertyAccessExpression(parent) && parent.getExpression() === current2) {
|
|
8461
|
-
|
|
8627
|
+
path14.push(parent.getName());
|
|
8462
8628
|
current2 = parent;
|
|
8463
8629
|
continue;
|
|
8464
8630
|
}
|
|
8465
8631
|
if (parent !== void 0 && import_ts_morph40.Node.isElementAccessExpression(parent) && parent.getExpression() === current2) {
|
|
8466
8632
|
const argument = parent.getArgumentExpression();
|
|
8467
8633
|
if (argument !== void 0 && import_ts_morph40.Node.isStringLiteral(argument)) {
|
|
8468
|
-
|
|
8634
|
+
path14.push(argument.getLiteralValue());
|
|
8469
8635
|
current2 = parent;
|
|
8470
8636
|
continue;
|
|
8471
8637
|
}
|
|
8472
8638
|
}
|
|
8473
|
-
return
|
|
8639
|
+
return path14;
|
|
8474
8640
|
}
|
|
8475
8641
|
}
|
|
8476
8642
|
function declaresParameterOf(node, func) {
|
|
@@ -8518,7 +8684,7 @@ function parameterReads(func, parameterNames2, barriers = NO_BARRIERS) {
|
|
|
8518
8684
|
|
|
8519
8685
|
// src/resolve/readName.ts
|
|
8520
8686
|
var import_ts_morph41 = require("ts-morph");
|
|
8521
|
-
var
|
|
8687
|
+
var import_behavioral_ir4 = require("@suss/behavioral-ir");
|
|
8522
8688
|
var MAX_HELPER_HOPS = 2;
|
|
8523
8689
|
var UNNAMED_HOLE = "param";
|
|
8524
8690
|
function readName(expr, options = {}) {
|
|
@@ -8533,7 +8699,7 @@ function readName(expr, options = {}) {
|
|
|
8533
8699
|
return name;
|
|
8534
8700
|
}
|
|
8535
8701
|
const reference = referenceIn(expr);
|
|
8536
|
-
return reference === null ? null : (0,
|
|
8702
|
+
return reference === null ? null : (0, import_behavioral_ir4.referenceName)(reference);
|
|
8537
8703
|
}
|
|
8538
8704
|
function referenceIn(expr) {
|
|
8539
8705
|
const fromParameter = parameterPath(expr);
|
|
@@ -8782,7 +8948,7 @@ function boundOnce(expr, ctx) {
|
|
|
8782
8948
|
}
|
|
8783
8949
|
function readOrHole(expr, ctx) {
|
|
8784
8950
|
const name = read(expr, ctx);
|
|
8785
|
-
return name ?? (0,
|
|
8951
|
+
return name ?? (0, import_behavioral_ir4.patternHole)(holeName(expr, ctx));
|
|
8786
8952
|
}
|
|
8787
8953
|
function holeName(expr, ctx) {
|
|
8788
8954
|
const bound = boundOnce(expr, ctx);
|
|
@@ -9169,142 +9335,40 @@ function importSpecifierMatches(decl, expectedModule) {
|
|
|
9169
9335
|
return import_ts_morph43.Node.isImportDeclaration(importDecl) && importDecl.getModuleSpecifierValue() === expectedModule;
|
|
9170
9336
|
}
|
|
9171
9337
|
function extractInvocationEffects(func, barriers = NO_BARRIERS) {
|
|
9172
|
-
const
|
|
9338
|
+
const calls = [];
|
|
9173
9339
|
func.forEachDescendant((node, traversal) => {
|
|
9174
|
-
if (isDescentStop(node, func, barriers)) {
|
|
9340
|
+
if (isDescentStop(node, func, barriers) || import_ts_morph43.Node.isDecorator(node)) {
|
|
9175
9341
|
traversal.skip();
|
|
9176
9342
|
return;
|
|
9177
9343
|
}
|
|
9178
|
-
if (import_ts_morph43.Node.isExpressionStatement(node)) {
|
|
9179
|
-
const { call, async } = unwrapCall(node.getExpression());
|
|
9180
|
-
if (call !== null) {
|
|
9181
|
-
const preconditions = collectPreconditions(node, func);
|
|
9182
|
-
results.push({
|
|
9183
|
-
effect: {
|
|
9184
|
-
type: "invocation",
|
|
9185
|
-
callee: call.getExpression().getText(),
|
|
9186
|
-
args: extractArgs(call),
|
|
9187
|
-
async,
|
|
9188
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9189
|
-
},
|
|
9190
|
-
line: startLineOf(node),
|
|
9191
|
-
neverTerminal: false,
|
|
9192
|
-
alwaysRuns: runsOnEveryPath(node, func)
|
|
9193
|
-
});
|
|
9194
|
-
}
|
|
9195
|
-
return;
|
|
9196
|
-
}
|
|
9197
|
-
if (import_ts_morph43.Node.isSpreadElement(node)) {
|
|
9198
|
-
const parent = node.getParent();
|
|
9199
|
-
if (parent !== void 0 && (import_ts_morph43.Node.isArrayLiteralExpression(parent) || import_ts_morph43.Node.isObjectLiteralExpression(parent))) {
|
|
9200
|
-
const { call, async } = unwrapCall(node.getExpression());
|
|
9201
|
-
if (call !== null) {
|
|
9202
|
-
const preconditions = collectPreconditions(node, func);
|
|
9203
|
-
results.push({
|
|
9204
|
-
effect: {
|
|
9205
|
-
type: "invocation",
|
|
9206
|
-
callee: call.getExpression().getText(),
|
|
9207
|
-
args: extractArgs(call),
|
|
9208
|
-
async,
|
|
9209
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9210
|
-
},
|
|
9211
|
-
line: enclosingStatementLine(node),
|
|
9212
|
-
neverTerminal: true,
|
|
9213
|
-
alwaysRuns: runsOnEveryPath(node, func)
|
|
9214
|
-
});
|
|
9215
|
-
}
|
|
9216
|
-
}
|
|
9217
|
-
return;
|
|
9218
|
-
}
|
|
9219
|
-
if (import_ts_morph43.Node.isVariableDeclaration(node)) {
|
|
9220
|
-
const initializer = node.getInitializer();
|
|
9221
|
-
if (initializer !== void 0) {
|
|
9222
|
-
const { call, async } = unwrapCall(initializer);
|
|
9223
|
-
if (call !== null) {
|
|
9224
|
-
const preconditions = collectPreconditions(node, func);
|
|
9225
|
-
results.push({
|
|
9226
|
-
effect: {
|
|
9227
|
-
type: "invocation",
|
|
9228
|
-
callee: call.getExpression().getText(),
|
|
9229
|
-
args: extractArgs(call),
|
|
9230
|
-
async,
|
|
9231
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9232
|
-
},
|
|
9233
|
-
line: enclosingStatementLine(node),
|
|
9234
|
-
neverTerminal: true,
|
|
9235
|
-
alwaysRuns: runsOnEveryPath(node, func)
|
|
9236
|
-
});
|
|
9237
|
-
}
|
|
9238
|
-
}
|
|
9239
|
-
return;
|
|
9240
|
-
}
|
|
9241
|
-
if (import_ts_morph43.Node.isReturnStatement(node)) {
|
|
9242
|
-
const returned = node.getExpression();
|
|
9243
|
-
const { call, async } = returned === void 0 ? { call: null, async: false } : unwrapCall(returned);
|
|
9244
|
-
if (call !== null) {
|
|
9245
|
-
const preconditions = collectPreconditions(node, func);
|
|
9246
|
-
results.push({
|
|
9247
|
-
effect: {
|
|
9248
|
-
type: "invocation",
|
|
9249
|
-
callee: call.getExpression().getText(),
|
|
9250
|
-
args: extractArgs(call),
|
|
9251
|
-
async,
|
|
9252
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9253
|
-
},
|
|
9254
|
-
line: startLineOf(node),
|
|
9255
|
-
neverTerminal: false,
|
|
9256
|
-
alwaysRuns: runsOnEveryPath(node, func),
|
|
9257
|
-
node: call
|
|
9258
|
-
});
|
|
9259
|
-
}
|
|
9260
|
-
return;
|
|
9261
|
-
}
|
|
9262
|
-
if (import_ts_morph43.Node.isArrowFunction(node)) {
|
|
9263
|
-
const body = node.getBody();
|
|
9264
|
-
const { call, async } = import_ts_morph43.Node.isExpression(body) ? unwrapCall(body) : { call: null, async: false };
|
|
9265
|
-
if (call !== null) {
|
|
9266
|
-
const preconditions = collectPreconditions(node, func);
|
|
9267
|
-
results.push({
|
|
9268
|
-
effect: {
|
|
9269
|
-
type: "invocation",
|
|
9270
|
-
callee: call.getExpression().getText(),
|
|
9271
|
-
args: extractArgs(call),
|
|
9272
|
-
async: async || node.isAsync(),
|
|
9273
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9274
|
-
},
|
|
9275
|
-
line: startLineOf(node),
|
|
9276
|
-
neverTerminal: false,
|
|
9277
|
-
alwaysRuns: runsOnEveryPath(node, func),
|
|
9278
|
-
node: call
|
|
9279
|
-
});
|
|
9280
|
-
}
|
|
9281
|
-
return;
|
|
9282
|
-
}
|
|
9283
9344
|
if (import_ts_morph43.Node.isCallExpression(node)) {
|
|
9284
|
-
|
|
9285
|
-
if (parent === void 0) {
|
|
9286
|
-
return;
|
|
9287
|
-
}
|
|
9288
|
-
const isArrayElement = import_ts_morph43.Node.isArrayLiteralExpression(parent);
|
|
9289
|
-
const isPropertyValue = import_ts_morph43.Node.isPropertyAssignment(parent) && parent.getInitializer() === node;
|
|
9290
|
-
if (isArrayElement || isPropertyValue) {
|
|
9291
|
-
const preconditions = collectPreconditions(node, func);
|
|
9292
|
-
results.push({
|
|
9293
|
-
effect: {
|
|
9294
|
-
type: "invocation",
|
|
9295
|
-
callee: node.getExpression().getText(),
|
|
9296
|
-
args: extractArgs(node),
|
|
9297
|
-
async: false,
|
|
9298
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
9299
|
-
},
|
|
9300
|
-
line: enclosingStatementLine(node),
|
|
9301
|
-
neverTerminal: true,
|
|
9302
|
-
alwaysRuns: runsOnEveryPath(node, func)
|
|
9303
|
-
});
|
|
9304
|
-
}
|
|
9345
|
+
calls.push(node);
|
|
9305
9346
|
}
|
|
9306
9347
|
});
|
|
9307
|
-
|
|
9348
|
+
calls.sort((a, b) => a.getEnd() - b.getEnd());
|
|
9349
|
+
return calls.map((call) => invocationAt(call, func));
|
|
9350
|
+
}
|
|
9351
|
+
function invocationAt(call, func) {
|
|
9352
|
+
const preconditions = collectPreconditions(call, func);
|
|
9353
|
+
return {
|
|
9354
|
+
effect: {
|
|
9355
|
+
type: "invocation",
|
|
9356
|
+
callee: call.getExpression().getText(),
|
|
9357
|
+
args: extractArgs(call),
|
|
9358
|
+
async: isAwaited(call),
|
|
9359
|
+
...preconditions.length > 0 ? { preconditions } : {}
|
|
9360
|
+
},
|
|
9361
|
+
node: call,
|
|
9362
|
+
line: enclosingStatementLine(call),
|
|
9363
|
+
alwaysRuns: runsOnEveryPath(call, func)
|
|
9364
|
+
};
|
|
9365
|
+
}
|
|
9366
|
+
function isAwaited(call) {
|
|
9367
|
+
let current2 = call.getParent();
|
|
9368
|
+
while (current2 !== void 0 && import_ts_morph43.Node.isParenthesizedExpression(current2)) {
|
|
9369
|
+
current2 = current2.getParent();
|
|
9370
|
+
}
|
|
9371
|
+
return current2 !== void 0 && import_ts_morph43.Node.isAwaitExpression(current2);
|
|
9308
9372
|
}
|
|
9309
9373
|
function runInvocationRecognizers(func, recognizers, barriers = NO_BARRIERS, resolveWrittenValue, originatesFrom, anchorCallsOf) {
|
|
9310
9374
|
if (recognizers.length === 0) {
|
|
@@ -9590,7 +9654,7 @@ function withPreconditions(effect, preconditions) {
|
|
|
9590
9654
|
}
|
|
9591
9655
|
return {
|
|
9592
9656
|
...effect,
|
|
9593
|
-
preconditions: preconditions.map(
|
|
9657
|
+
preconditions: preconditions.map(import_extractor4.rawConditionToPredicate)
|
|
9594
9658
|
};
|
|
9595
9659
|
}
|
|
9596
9660
|
function inlineModuleBinding(ident, depth) {
|
|
@@ -9647,22 +9711,6 @@ function enclosingStatementLine(node) {
|
|
|
9647
9711
|
}
|
|
9648
9712
|
return startLineOf(node);
|
|
9649
9713
|
}
|
|
9650
|
-
function unwrapCall(node) {
|
|
9651
|
-
if (import_ts_morph43.Node.isAwaitExpression(node)) {
|
|
9652
|
-
const inner = node.getExpression();
|
|
9653
|
-
if (import_ts_morph43.Node.isCallExpression(inner)) {
|
|
9654
|
-
return { call: inner, async: true };
|
|
9655
|
-
}
|
|
9656
|
-
return { call: null, async: false };
|
|
9657
|
-
}
|
|
9658
|
-
if (import_ts_morph43.Node.isParenthesizedExpression(node)) {
|
|
9659
|
-
return unwrapCall(node.getExpression());
|
|
9660
|
-
}
|
|
9661
|
-
if (import_ts_morph43.Node.isCallExpression(node)) {
|
|
9662
|
-
return { call: node, async: false };
|
|
9663
|
-
}
|
|
9664
|
-
return { call: null, async: false };
|
|
9665
|
-
}
|
|
9666
9714
|
|
|
9667
9715
|
// src/terminals/index.ts
|
|
9668
9716
|
var import_ts_morph53 = require("ts-morph");
|
|
@@ -11692,10 +11740,26 @@ function makeFallthroughTerminal(func) {
|
|
|
11692
11740
|
// src/assembly.ts
|
|
11693
11741
|
var preconditionsOf = (effect) => effect.type === "invocation" ? effect.preconditions : void 0;
|
|
11694
11742
|
function firesOn(site, branch) {
|
|
11695
|
-
if (!(0,
|
|
11743
|
+
if (!(0, import_extractor5.guardsHoldOn)(site.preconditions, branch.conditions)) {
|
|
11696
11744
|
return false;
|
|
11697
11745
|
}
|
|
11698
|
-
return site.alwaysRuns || (0,
|
|
11746
|
+
return site.alwaysRuns || (0, import_extractor5.runsBefore)(site.line, branch.terminal.location.end);
|
|
11747
|
+
}
|
|
11748
|
+
function writesTerminal(call, terminalNodes) {
|
|
11749
|
+
let current2 = call;
|
|
11750
|
+
for (; ; ) {
|
|
11751
|
+
if (terminalNodes.has(current2)) {
|
|
11752
|
+
return true;
|
|
11753
|
+
}
|
|
11754
|
+
const parent = current2.getParent();
|
|
11755
|
+
if (parent === void 0 || !isReceiverOf(current2, parent)) {
|
|
11756
|
+
return false;
|
|
11757
|
+
}
|
|
11758
|
+
current2 = parent;
|
|
11759
|
+
}
|
|
11760
|
+
}
|
|
11761
|
+
function isReceiverOf(node, parent) {
|
|
11762
|
+
return (import_ts_morph54.Node.isPropertyAccessExpression(parent) || import_ts_morph54.Node.isElementAccessExpression(parent) || import_ts_morph54.Node.isCallExpression(parent)) && parent.getExpression() === node;
|
|
11699
11763
|
}
|
|
11700
11764
|
var isDefaultConditionList = (conditions) => conditions.length === 0 || conditions.every(
|
|
11701
11765
|
(c) => c.source === "earlyReturn" || c.source === "earlyThrow"
|
|
@@ -11835,11 +11899,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
11835
11899
|
});
|
|
11836
11900
|
if (invocations.length > 0) {
|
|
11837
11901
|
const terminalNodes = new Set(terminals.map(({ node }) => node));
|
|
11838
|
-
const terminalLines = new Set(
|
|
11839
|
-
distinctBranches.map((b) => b.terminal.location.start)
|
|
11840
|
-
);
|
|
11841
11902
|
const sideEffects = invocations.filter(
|
|
11842
|
-
(i) =>
|
|
11903
|
+
(i) => !writesTerminal(i.node, terminalNodes)
|
|
11843
11904
|
);
|
|
11844
11905
|
for (const branch of distinctBranches) {
|
|
11845
11906
|
branch.effects = sideEffects.filter(
|
|
@@ -11885,9 +11946,9 @@ function createSourceFileLookup(project) {
|
|
|
11885
11946
|
if (sf === null) {
|
|
11886
11947
|
return null;
|
|
11887
11948
|
}
|
|
11888
|
-
const
|
|
11889
|
-
const index = functionsByFile.get(
|
|
11890
|
-
functionsByFile.set(
|
|
11949
|
+
const path14 = sf.getFilePath();
|
|
11950
|
+
const index = functionsByFile.get(path14) ?? indexFunctions(sf);
|
|
11951
|
+
functionsByFile.set(path14, index);
|
|
11891
11952
|
if (location.span !== void 0) {
|
|
11892
11953
|
const bySpan = index.get(spanKey(location.span));
|
|
11893
11954
|
if (bySpan !== void 0) {
|
|
@@ -11932,397 +11993,47 @@ function indexFunctions(sf) {
|
|
|
11932
11993
|
return index;
|
|
11933
11994
|
}
|
|
11934
11995
|
|
|
11935
|
-
// src/
|
|
11936
|
-
var
|
|
11937
|
-
var
|
|
11938
|
-
|
|
11939
|
-
|
|
11940
|
-
|
|
11941
|
-
var ENTRY_PREFIX = "key-";
|
|
11942
|
-
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
11943
|
-
function createCacheLayer(cacheDir) {
|
|
11944
|
-
if (cacheDir === null) {
|
|
11945
|
-
return {
|
|
11946
|
-
tryHit: async () => null,
|
|
11947
|
-
lookup: async () => ({
|
|
11948
|
-
kind: "miss",
|
|
11949
|
-
diagnostic: { kind: "miss", missReason: "no-manifest" }
|
|
11950
|
-
}),
|
|
11951
|
-
plan: async () => null,
|
|
11952
|
-
write: async () => {
|
|
11953
|
-
}
|
|
11954
|
-
};
|
|
11955
|
-
}
|
|
11956
|
-
return {
|
|
11957
|
-
async tryHit(input) {
|
|
11958
|
-
const result = await this.lookup(input);
|
|
11959
|
-
return result.kind === "hit" ? result.summaries : null;
|
|
11960
|
-
},
|
|
11961
|
-
async lookup(input) {
|
|
11962
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
11963
|
-
const manifest = await readManifest(import_node_path7.default.join(entryDir, "manifest.json"));
|
|
11964
|
-
if (manifest === null) {
|
|
11965
|
-
return missDiag(await describeAbsentEntry(cacheDir));
|
|
11966
|
-
}
|
|
11967
|
-
const currentTsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
11968
|
-
if (!fileStampEquals(manifest.tsconfigStamp, currentTsconfigStamp)) {
|
|
11969
|
-
return missDiag("tsconfig-changed");
|
|
11970
|
-
}
|
|
11971
|
-
const currentFiles = await resolveFileStamps(input);
|
|
11972
|
-
if (!fileStampsEqual(manifest.files, currentFiles)) {
|
|
11973
|
-
return missDiag("files-changed");
|
|
11974
|
-
}
|
|
11975
|
-
await markUsed(entryDir);
|
|
11976
|
-
return {
|
|
11977
|
-
kind: "hit",
|
|
11978
|
-
summaries: manifest.summaries,
|
|
11979
|
-
diagnostic: { kind: "hit" }
|
|
11980
|
-
};
|
|
11981
|
-
},
|
|
11982
|
-
async plan(input) {
|
|
11983
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
11984
|
-
const manifest = await readManifest(import_node_path7.default.join(entryDir, "manifest.json"));
|
|
11985
|
-
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
11986
|
-
return null;
|
|
11987
|
-
}
|
|
11988
|
-
const currentTsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
11989
|
-
if (!fileStampEquals(manifest.tsconfigStamp, currentTsconfigStamp)) {
|
|
11990
|
-
return null;
|
|
11991
|
-
}
|
|
11992
|
-
await markUsed(entryDir);
|
|
11993
|
-
return buildPlan(manifest, await resolveFileStamps(input));
|
|
11994
|
-
},
|
|
11995
|
-
async write(input, summaries, attribution) {
|
|
11996
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
11997
|
-
const previous = await readManifest(import_node_path7.default.join(entryDir, "manifest.json"));
|
|
11998
|
-
const tsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
11999
|
-
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
12000
|
-
const manifest = {
|
|
12001
|
-
schemaVersion: SCHEMA_VERSION,
|
|
12002
|
-
adapterPacksDigest: input.adapterPacksDigest,
|
|
12003
|
-
tsconfigStamp,
|
|
12004
|
-
files,
|
|
12005
|
-
summaries,
|
|
12006
|
-
...attribution === void 0 ? {} : encodeAttribution(attribution)
|
|
12007
|
-
};
|
|
12008
|
-
await import_promises2.default.mkdir(entryDir, { recursive: true });
|
|
12009
|
-
await import_promises2.default.writeFile(
|
|
12010
|
-
import_node_path7.default.join(entryDir, "manifest.json"),
|
|
12011
|
-
JSON.stringify(manifest)
|
|
12012
|
-
);
|
|
12013
|
-
await evictOldEntries(cacheDir, entryDir);
|
|
12014
|
-
}
|
|
12015
|
-
};
|
|
12016
|
-
}
|
|
12017
|
-
async function buildPlan(manifest, currentStamps) {
|
|
12018
|
-
const stored = new Map(manifest.files.map((f) => [f.path, f]));
|
|
12019
|
-
const current2 = new Map(currentStamps.map((f) => [f.path, f]));
|
|
12020
|
-
const changed = /* @__PURE__ */ new Set();
|
|
12021
|
-
const removed = /* @__PURE__ */ new Set();
|
|
12022
|
-
for (const p of stored.keys()) {
|
|
12023
|
-
if (!current2.has(p)) {
|
|
12024
|
-
removed.add(p);
|
|
12025
|
-
}
|
|
12026
|
-
}
|
|
12027
|
-
const toVerify = [];
|
|
12028
|
-
for (const [p, stamp] of current2) {
|
|
12029
|
-
const before = stored.get(p);
|
|
12030
|
-
if (before === void 0) {
|
|
12031
|
-
changed.add(p);
|
|
12032
|
-
} else if (!fileStampEquals(before, stamp)) {
|
|
12033
|
-
if (before.contentHash === void 0) {
|
|
12034
|
-
changed.add(p);
|
|
12035
|
-
} else {
|
|
12036
|
-
toVerify.push(p);
|
|
12037
|
-
}
|
|
12038
|
-
}
|
|
11996
|
+
// src/contract.ts
|
|
11997
|
+
var import_ts_morph56 = require("ts-morph");
|
|
11998
|
+
var import_behavioral_ir5 = require("@suss/behavioral-ir");
|
|
11999
|
+
function extractDeclaredBody(node) {
|
|
12000
|
+
if (node === void 0) {
|
|
12001
|
+
return null;
|
|
12039
12002
|
}
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
const hash = await hashFile(p);
|
|
12043
|
-
if (hash === null || hash !== stored.get(p)?.contentHash) {
|
|
12044
|
-
changed.add(p);
|
|
12045
|
-
}
|
|
12046
|
-
})
|
|
12047
|
-
);
|
|
12048
|
-
const roots = /* @__PURE__ */ new Map();
|
|
12049
|
-
const rootNames = manifest.roots ?? [];
|
|
12050
|
-
const depPaths = manifest.depPaths ?? [];
|
|
12051
|
-
let rootsDeclined = 0;
|
|
12052
|
-
rootNames.forEach((rootPath, i) => {
|
|
12053
|
-
const meta = manifest.rootMeta?.[i];
|
|
12054
|
-
if (meta === void 0) {
|
|
12055
|
-
return;
|
|
12056
|
-
}
|
|
12057
|
-
if (!meta.cacheable) {
|
|
12058
|
-
rootsDeclined += 1;
|
|
12059
|
-
}
|
|
12060
|
-
roots.set(rootPath, {
|
|
12061
|
-
path: rootPath,
|
|
12062
|
-
cacheable: meta.cacheable,
|
|
12063
|
-
deps: meta.deps.flatMap((d) => {
|
|
12064
|
-
const p = depPaths[d];
|
|
12065
|
-
return p === void 0 ? [] : [p];
|
|
12066
|
-
}),
|
|
12067
|
-
claims: meta.claims,
|
|
12068
|
-
mountPrefixes: meta.mountPrefixes,
|
|
12069
|
-
packs: meta.packs
|
|
12070
|
-
});
|
|
12071
|
-
});
|
|
12072
|
-
const validRoots = /* @__PURE__ */ new Set();
|
|
12073
|
-
for (const [rootPath, record2] of roots) {
|
|
12074
|
-
if (!record2.cacheable || !current2.has(rootPath)) {
|
|
12075
|
-
continue;
|
|
12076
|
-
}
|
|
12077
|
-
if (changed.has(rootPath)) {
|
|
12078
|
-
continue;
|
|
12079
|
-
}
|
|
12080
|
-
const depMoved = record2.deps.some((d) => changed.has(d) || removed.has(d));
|
|
12081
|
-
if (!depMoved) {
|
|
12082
|
-
validRoots.add(rootPath);
|
|
12083
|
-
}
|
|
12003
|
+
if (!import_ts_morph56.Node.isCallExpression(node)) {
|
|
12004
|
+
return null;
|
|
12084
12005
|
}
|
|
12085
|
-
const
|
|
12086
|
-
|
|
12087
|
-
changed,
|
|
12088
|
-
removed,
|
|
12089
|
-
roots,
|
|
12090
|
-
validRoots,
|
|
12091
|
-
rootsDeclined,
|
|
12092
|
-
reuse(valid) {
|
|
12093
|
-
const summaries = [];
|
|
12094
|
-
const reusedOwners = [];
|
|
12095
|
-
manifest.summaries.forEach((summary, i) => {
|
|
12096
|
-
const ownerPaths = (owners[i] ?? []).flatMap((o) => {
|
|
12097
|
-
const p = rootNames[o];
|
|
12098
|
-
return p === void 0 ? [] : [p];
|
|
12099
|
-
});
|
|
12100
|
-
if (ownerPaths.some((p) => valid.has(p))) {
|
|
12101
|
-
summaries.push(summary);
|
|
12102
|
-
reusedOwners.push(ownerPaths.filter((p) => valid.has(p)));
|
|
12103
|
-
}
|
|
12104
|
-
});
|
|
12105
|
-
return { summaries, owners: reusedOwners };
|
|
12106
|
-
},
|
|
12107
|
-
allSummaries() {
|
|
12108
|
-
return manifest.summaries;
|
|
12109
|
-
},
|
|
12110
|
-
attribution() {
|
|
12111
|
-
return {
|
|
12112
|
-
roots: [...roots.values()],
|
|
12113
|
-
owners: owners.map(
|
|
12114
|
-
(ownerIds) => ownerIds.flatMap((o) => {
|
|
12115
|
-
const p = rootNames[o];
|
|
12116
|
-
return p === void 0 ? [] : [p];
|
|
12117
|
-
})
|
|
12118
|
-
)
|
|
12119
|
-
};
|
|
12120
|
-
}
|
|
12121
|
-
};
|
|
12122
|
-
}
|
|
12123
|
-
function encodeAttribution(attribution) {
|
|
12124
|
-
const roots = attribution.roots.map((r) => r.path);
|
|
12125
|
-
const rootIndex = new Map(roots.map((p, i) => [p, i]));
|
|
12126
|
-
const depIndex = /* @__PURE__ */ new Map();
|
|
12127
|
-
const depPaths = [];
|
|
12128
|
-
const depIdOf = (p) => {
|
|
12129
|
-
const existing = depIndex.get(p);
|
|
12130
|
-
if (existing !== void 0) {
|
|
12131
|
-
return existing;
|
|
12132
|
-
}
|
|
12133
|
-
const id = depPaths.length;
|
|
12134
|
-
depPaths.push(p);
|
|
12135
|
-
depIndex.set(p, id);
|
|
12136
|
-
return id;
|
|
12137
|
-
};
|
|
12138
|
-
const rootMeta = attribution.roots.map((r) => ({
|
|
12139
|
-
cacheable: r.cacheable,
|
|
12140
|
-
deps: r.deps.map(depIdOf),
|
|
12141
|
-
claims: r.claims,
|
|
12142
|
-
mountPrefixes: r.mountPrefixes,
|
|
12143
|
-
packs: r.packs
|
|
12144
|
-
}));
|
|
12145
|
-
const owners = attribution.owners.map(
|
|
12146
|
-
(ownerPaths) => ownerPaths.flatMap((p) => {
|
|
12147
|
-
const i = rootIndex.get(p);
|
|
12148
|
-
return i === void 0 ? [] : [i];
|
|
12149
|
-
})
|
|
12150
|
-
);
|
|
12151
|
-
return { roots, rootMeta, depPaths, owners };
|
|
12152
|
-
}
|
|
12153
|
-
async function hashStamps(stamps, previous) {
|
|
12154
|
-
const before = new Map((previous?.files ?? []).map((f) => [f.path, f]));
|
|
12155
|
-
return Promise.all(
|
|
12156
|
-
stamps.map(async (stamp) => {
|
|
12157
|
-
const prior = before.get(stamp.path);
|
|
12158
|
-
if (prior !== void 0 && prior.contentHash !== void 0 && fileStampEquals(prior, stamp)) {
|
|
12159
|
-
return { ...stamp, contentHash: prior.contentHash };
|
|
12160
|
-
}
|
|
12161
|
-
const contentHash = await hashFile(stamp.path);
|
|
12162
|
-
return contentHash === null ? stamp : { ...stamp, contentHash };
|
|
12163
|
-
})
|
|
12164
|
-
);
|
|
12165
|
-
}
|
|
12166
|
-
async function hashFile(filePath) {
|
|
12167
|
-
try {
|
|
12168
|
-
const content = await import_promises2.default.readFile(filePath);
|
|
12169
|
-
return (0, import_node_crypto2.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
12170
|
-
} catch {
|
|
12006
|
+
const typeArgs = node.getTypeArguments();
|
|
12007
|
+
if (typeArgs.length === 0) {
|
|
12171
12008
|
return null;
|
|
12172
12009
|
}
|
|
12010
|
+
return shapeFromNodeType(typeArgs[0]);
|
|
12173
12011
|
}
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
return
|
|
12178
|
-
} catch {
|
|
12179
|
-
return "no-manifest";
|
|
12012
|
+
function resolveHandlerPropNode(func) {
|
|
12013
|
+
const parent = func.getParent();
|
|
12014
|
+
if (parent === void 0) {
|
|
12015
|
+
return null;
|
|
12180
12016
|
}
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
const key = [
|
|
12184
|
-
SCHEMA_VERSION,
|
|
12185
|
-
input.adapterPacksDigest,
|
|
12186
|
-
input.tsconfigPath ?? ""
|
|
12187
|
-
].join(" ");
|
|
12188
|
-
const name = (0, import_node_crypto2.createHash)("sha256").update(key).digest("hex").slice(0, 16);
|
|
12189
|
-
return import_node_path7.default.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
12190
|
-
}
|
|
12191
|
-
function isEntryDir(name) {
|
|
12192
|
-
return ENTRY_DIR_NAME.test(name);
|
|
12193
|
-
}
|
|
12194
|
-
async function markUsed(entryDir) {
|
|
12195
|
-
const now = /* @__PURE__ */ new Date();
|
|
12196
|
-
try {
|
|
12197
|
-
await import_promises2.default.utimes(entryDir, now, now);
|
|
12198
|
-
} catch {
|
|
12017
|
+
if (import_ts_morph56.Node.isPropertyAssignment(parent)) {
|
|
12018
|
+
return parent;
|
|
12199
12019
|
}
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
try {
|
|
12203
|
-
await import_promises2.default.rm(import_node_path7.default.join(cacheDir, "manifest.json"), { force: true });
|
|
12204
|
-
const entries = await import_promises2.default.readdir(cacheDir, { withFileTypes: true });
|
|
12205
|
-
const dirs = await Promise.all(
|
|
12206
|
-
entries.filter((e) => e.isDirectory() && isEntryDir(e.name)).map(async (e) => {
|
|
12207
|
-
const dir = import_node_path7.default.join(cacheDir, e.name);
|
|
12208
|
-
const stat = await import_promises2.default.stat(dir);
|
|
12209
|
-
return { dir, mtimeMs: stat.mtimeMs };
|
|
12210
|
-
})
|
|
12211
|
-
);
|
|
12212
|
-
const doomed = dirs.filter((d) => d.dir !== keepDir).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(MAX_ENTRIES - 1);
|
|
12213
|
-
await Promise.all(
|
|
12214
|
-
doomed.map((d) => import_promises2.default.rm(d.dir, { recursive: true, force: true }))
|
|
12215
|
-
);
|
|
12216
|
-
} catch {
|
|
12020
|
+
if (import_ts_morph56.Node.isMethodDeclaration(func)) {
|
|
12021
|
+
return func;
|
|
12217
12022
|
}
|
|
12023
|
+
return null;
|
|
12218
12024
|
}
|
|
12219
|
-
function
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
};
|
|
12224
|
-
}
|
|
12225
|
-
async function readManifest(manifestPath) {
|
|
12226
|
-
try {
|
|
12227
|
-
const raw = await import_promises2.default.readFile(manifestPath, "utf-8");
|
|
12228
|
-
return JSON.parse(raw);
|
|
12229
|
-
} catch {
|
|
12025
|
+
function findRouterCall(unit) {
|
|
12026
|
+
const func = unit.func;
|
|
12027
|
+
const propNode = func === null ? null : resolveHandlerPropNode(func);
|
|
12028
|
+
if (propNode === null) {
|
|
12230
12029
|
return null;
|
|
12231
12030
|
}
|
|
12232
|
-
|
|
12233
|
-
|
|
12234
|
-
if (tsconfigPath === void 0) {
|
|
12031
|
+
const handlersObj = propNode.getParent();
|
|
12032
|
+
if (handlersObj === void 0 || !import_ts_morph56.Node.isObjectLiteralExpression(handlersObj)) {
|
|
12235
12033
|
return null;
|
|
12236
12034
|
}
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
return { path: tsconfigPath, mtimeMs: stat.mtimeMs, size: stat.size };
|
|
12240
|
-
} catch {
|
|
12241
|
-
return null;
|
|
12242
|
-
}
|
|
12243
|
-
}
|
|
12244
|
-
async function resolveFileStamps(input) {
|
|
12245
|
-
if (input.files !== void 0) {
|
|
12246
|
-
return stampPaths(input.files);
|
|
12247
|
-
}
|
|
12248
|
-
if (input.project !== void 0) {
|
|
12249
|
-
return stampProjectFiles(input.project);
|
|
12250
|
-
}
|
|
12251
|
-
return [];
|
|
12252
|
-
}
|
|
12253
|
-
async function stampProjectFiles(project) {
|
|
12254
|
-
const files = project.getSourceFiles().filter((sf) => !sf.isDeclarationFile()).map((sf) => sf.getFilePath());
|
|
12255
|
-
return stampPaths(files);
|
|
12256
|
-
}
|
|
12257
|
-
async function stampPaths(paths) {
|
|
12258
|
-
const files = paths;
|
|
12259
|
-
const stamped = await Promise.all(
|
|
12260
|
-
files.map(async (p) => {
|
|
12261
|
-
try {
|
|
12262
|
-
const stat = await import_promises2.default.stat(p);
|
|
12263
|
-
return { path: p, mtimeMs: stat.mtimeMs, size: stat.size };
|
|
12264
|
-
} catch {
|
|
12265
|
-
return { path: p, mtimeMs: -1, size: -1 };
|
|
12266
|
-
}
|
|
12267
|
-
})
|
|
12268
|
-
);
|
|
12269
|
-
stamped.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
12270
|
-
return stamped;
|
|
12271
|
-
}
|
|
12272
|
-
function fileStampsEqual(a, b) {
|
|
12273
|
-
return a.length === b.length && a.every((s, i) => fileStampEquals(s, b[i]));
|
|
12274
|
-
}
|
|
12275
|
-
function fileStampEquals(a, b) {
|
|
12276
|
-
if (a === null && b === null) {
|
|
12277
|
-
return true;
|
|
12278
|
-
}
|
|
12279
|
-
if (a === null || b === null) {
|
|
12280
|
-
return false;
|
|
12281
|
-
}
|
|
12282
|
-
return a.path === b.path && a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
12283
|
-
}
|
|
12284
|
-
|
|
12285
|
-
// src/contract.ts
|
|
12286
|
-
var import_ts_morph56 = require("ts-morph");
|
|
12287
|
-
var import_behavioral_ir4 = require("@suss/behavioral-ir");
|
|
12288
|
-
function extractDeclaredBody(node) {
|
|
12289
|
-
if (node === void 0) {
|
|
12290
|
-
return null;
|
|
12291
|
-
}
|
|
12292
|
-
if (!import_ts_morph56.Node.isCallExpression(node)) {
|
|
12293
|
-
return null;
|
|
12294
|
-
}
|
|
12295
|
-
const typeArgs = node.getTypeArguments();
|
|
12296
|
-
if (typeArgs.length === 0) {
|
|
12297
|
-
return null;
|
|
12298
|
-
}
|
|
12299
|
-
return shapeFromNodeType(typeArgs[0]);
|
|
12300
|
-
}
|
|
12301
|
-
function resolveHandlerPropNode(func) {
|
|
12302
|
-
const parent = func.getParent();
|
|
12303
|
-
if (parent === void 0) {
|
|
12304
|
-
return null;
|
|
12305
|
-
}
|
|
12306
|
-
if (import_ts_morph56.Node.isPropertyAssignment(parent)) {
|
|
12307
|
-
return parent;
|
|
12308
|
-
}
|
|
12309
|
-
if (import_ts_morph56.Node.isMethodDeclaration(func)) {
|
|
12310
|
-
return func;
|
|
12311
|
-
}
|
|
12312
|
-
return null;
|
|
12313
|
-
}
|
|
12314
|
-
function findRouterCall(unit) {
|
|
12315
|
-
const func = unit.func;
|
|
12316
|
-
const propNode = func === null ? null : resolveHandlerPropNode(func);
|
|
12317
|
-
if (propNode === null) {
|
|
12318
|
-
return null;
|
|
12319
|
-
}
|
|
12320
|
-
const handlersObj = propNode.getParent();
|
|
12321
|
-
if (handlersObj === void 0 || !import_ts_morph56.Node.isObjectLiteralExpression(handlersObj)) {
|
|
12322
|
-
return null;
|
|
12323
|
-
}
|
|
12324
|
-
const routerCall = handlersObj.getParent();
|
|
12325
|
-
if (routerCall === void 0 || !import_ts_morph56.Node.isCallExpression(routerCall)) {
|
|
12035
|
+
const routerCall = handlersObj.getParent();
|
|
12036
|
+
if (routerCall === void 0 || !import_ts_morph56.Node.isCallExpression(routerCall)) {
|
|
12326
12037
|
return null;
|
|
12327
12038
|
}
|
|
12328
12039
|
const args = routerCall.getArguments();
|
|
@@ -12424,7 +12135,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
12424
12135
|
}
|
|
12425
12136
|
const responses = [];
|
|
12426
12137
|
let method;
|
|
12427
|
-
let
|
|
12138
|
+
let path14;
|
|
12428
12139
|
for (const prop of endpointNode.getProperties()) {
|
|
12429
12140
|
if (!import_ts_morph56.Node.isPropertyAssignment(prop)) {
|
|
12430
12141
|
continue;
|
|
@@ -12439,7 +12150,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
12439
12150
|
if (propName === pattern.pathProperty) {
|
|
12440
12151
|
const val = prop.getInitializer();
|
|
12441
12152
|
if (val !== void 0 && import_ts_morph56.Node.isStringLiteral(val)) {
|
|
12442
|
-
|
|
12153
|
+
path14 = val.getLiteralValue();
|
|
12443
12154
|
}
|
|
12444
12155
|
}
|
|
12445
12156
|
if (propName === pattern.responseExtraction.property) {
|
|
@@ -12463,10 +12174,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
12463
12174
|
if (responses.length === 0) {
|
|
12464
12175
|
return null;
|
|
12465
12176
|
}
|
|
12466
|
-
const boundaryBinding = method !== void 0 ||
|
|
12177
|
+
const boundaryBinding = method !== void 0 || path14 !== void 0 ? (0, import_behavioral_ir5.restBinding)({
|
|
12467
12178
|
transport: "http",
|
|
12468
12179
|
method: method ?? null,
|
|
12469
|
-
path:
|
|
12180
|
+
path: path14 ?? null,
|
|
12470
12181
|
recognition: framework
|
|
12471
12182
|
}) : null;
|
|
12472
12183
|
return {
|
|
@@ -12664,7 +12375,7 @@ function parameterName(segment, convention) {
|
|
|
12664
12375
|
// src/discovery/graphqlClientConstruction.ts
|
|
12665
12376
|
var import_picomatch2 = __toESM(require("picomatch"), 1);
|
|
12666
12377
|
var import_ts_morph57 = require("ts-morph");
|
|
12667
|
-
var
|
|
12378
|
+
var import_behavioral_ir6 = require("@suss/behavioral-ir");
|
|
12668
12379
|
function stampGraphqlClientRefs(summaries, sourceFiles, packs, resolution) {
|
|
12669
12380
|
const scopes = compileOperationScopes(packs);
|
|
12670
12381
|
const sole = soleGraphqlClientRef(
|
|
@@ -12674,10 +12385,10 @@ function stampGraphqlClientRefs(summaries, sourceFiles, packs, resolution) {
|
|
|
12674
12385
|
const soleClient = sole !== null ? workspace !== null ? { ...sole, workspace } : sole : null;
|
|
12675
12386
|
let registry = null;
|
|
12676
12387
|
for (const summary of summaries) {
|
|
12677
|
-
if (!(0,
|
|
12388
|
+
if (!(0, import_behavioral_ir6.isGraphqlOperationBinding)(summary.identity.boundaryBinding)) {
|
|
12678
12389
|
continue;
|
|
12679
12390
|
}
|
|
12680
|
-
const existing = (0,
|
|
12391
|
+
const existing = (0, import_behavioral_ir6.readGraphqlMetadata)(summary) ?? {};
|
|
12681
12392
|
const scoped = scopedWorkspaceFor(summary.location.file, scopes);
|
|
12682
12393
|
const client = scoped !== null ? { uri: null, uriRef: null, workspace: scoped } : soleClient;
|
|
12683
12394
|
const dangling = (existing.unresolvedFragments?.length ?? 0) > 0;
|
|
@@ -12687,7 +12398,7 @@ function stampGraphqlClientRefs(summaries, sourceFiles, packs, resolution) {
|
|
|
12687
12398
|
if (dangling && registry === null) {
|
|
12688
12399
|
registry = fragmentRegistryStatus(sourceFiles, packs);
|
|
12689
12400
|
}
|
|
12690
|
-
summary.metadata = (0,
|
|
12401
|
+
summary.metadata = (0, import_behavioral_ir6.withGraphqlMetadata)(summary.metadata, {
|
|
12691
12402
|
...existing,
|
|
12692
12403
|
...client !== null ? { client } : {},
|
|
12693
12404
|
...dangling && registry !== null ? { fragmentRegistry: registry } : {}
|
|
@@ -13099,8 +12810,8 @@ function noteExpanded(expanded, readings, discovery) {
|
|
|
13099
12810
|
const paths = new Set(match.registrations.map((one) => one.pathTemplate));
|
|
13100
12811
|
const methods = expanded.get(reading.declarationId) ?? /* @__PURE__ */ new Set();
|
|
13101
12812
|
for (const sink of reading.helper.sinks) {
|
|
13102
|
-
const
|
|
13103
|
-
if (sink.method !== null &&
|
|
12813
|
+
const path14 = sink.arguments[0];
|
|
12814
|
+
if (sink.method !== null && path14?.as === "text" && paths.has(path14.text)) {
|
|
13104
12815
|
methods.add(sink.method);
|
|
13105
12816
|
}
|
|
13106
12817
|
}
|
|
@@ -13689,7 +13400,7 @@ function scalarOrRef(node) {
|
|
|
13689
13400
|
}
|
|
13690
13401
|
|
|
13691
13402
|
// src/moduleInit.ts
|
|
13692
|
-
var
|
|
13403
|
+
var import_extractor6 = require("@suss/extractor");
|
|
13693
13404
|
function moduleInitName(sourceFile) {
|
|
13694
13405
|
return sourceFile.getBaseName();
|
|
13695
13406
|
}
|
|
@@ -13697,44 +13408,15 @@ function moduleInitSummary(sourceFile, effects, options) {
|
|
|
13697
13408
|
if (effects.length === 0) {
|
|
13698
13409
|
return null;
|
|
13699
13410
|
}
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
identity: {
|
|
13411
|
+
return (0, import_extractor6.assembleSummary)(
|
|
13412
|
+
(0, import_extractor6.moduleInitStructure)({
|
|
13703
13413
|
name: moduleInitName(sourceFile),
|
|
13704
|
-
kind: "module-init",
|
|
13705
13414
|
file: sourceFile.getFilePath(),
|
|
13706
|
-
range: { start: 0, end },
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
parameters: [],
|
|
13712
|
-
branches: [
|
|
13713
|
-
{
|
|
13714
|
-
conditions: [],
|
|
13715
|
-
terminal: {
|
|
13716
|
-
kind: "void",
|
|
13717
|
-
statusCode: null,
|
|
13718
|
-
body: null,
|
|
13719
|
-
exceptionType: null,
|
|
13720
|
-
message: null,
|
|
13721
|
-
component: null,
|
|
13722
|
-
renderTree: null,
|
|
13723
|
-
delegateTarget: null,
|
|
13724
|
-
emitEvent: null,
|
|
13725
|
-
location: { start: 0, end }
|
|
13726
|
-
},
|
|
13727
|
-
effects: [],
|
|
13728
|
-
extraEffects: effects,
|
|
13729
|
-
location: { start: 0, end },
|
|
13730
|
-
isDefault: true
|
|
13731
|
-
}
|
|
13732
|
-
],
|
|
13733
|
-
unmatchedReturns: 0,
|
|
13734
|
-
dependencyCalls: [],
|
|
13735
|
-
declaredContract: null
|
|
13736
|
-
};
|
|
13737
|
-
return (0, import_extractor5.assembleSummary)(raw, options);
|
|
13415
|
+
range: { start: 0, end: sourceFile.getEnd() },
|
|
13416
|
+
effects
|
|
13417
|
+
}),
|
|
13418
|
+
options
|
|
13419
|
+
);
|
|
13738
13420
|
}
|
|
13739
13421
|
|
|
13740
13422
|
// src/referencedFiles.ts
|
|
@@ -13882,9 +13564,9 @@ function deriveBoundaryEffects(summaries, facts) {
|
|
|
13882
13564
|
|
|
13883
13565
|
// src/resolve/reachableClosure.ts
|
|
13884
13566
|
var import_ts_morph62 = require("ts-morph");
|
|
13885
|
-
var
|
|
13567
|
+
var import_behavioral_ir7 = require("@suss/behavioral-ir");
|
|
13886
13568
|
var import_datalog4 = require("@suss/datalog");
|
|
13887
|
-
var
|
|
13569
|
+
var import_extractor7 = require("@suss/extractor");
|
|
13888
13570
|
var reachablePack = {
|
|
13889
13571
|
name: "reachable",
|
|
13890
13572
|
languages: ["typescript"],
|
|
@@ -13906,6 +13588,12 @@ var reachablePack = {
|
|
|
13906
13588
|
function nodeKey(func) {
|
|
13907
13589
|
return offsetKeyOf(func);
|
|
13908
13590
|
}
|
|
13591
|
+
function targetOf(node) {
|
|
13592
|
+
return {
|
|
13593
|
+
file: node.getSourceFile().getFilePath(),
|
|
13594
|
+
span: { start: node.getStart(), end: node.getEnd() }
|
|
13595
|
+
};
|
|
13596
|
+
}
|
|
13909
13597
|
function resolveCallee(call, calleeName, scan) {
|
|
13910
13598
|
if (!import_ts_morph62.Node.isCallExpression(call)) {
|
|
13911
13599
|
return null;
|
|
@@ -13930,19 +13618,42 @@ function resolveCallee(call, calleeName, scan) {
|
|
|
13930
13618
|
if (sources.length > 1) {
|
|
13931
13619
|
return {
|
|
13932
13620
|
kind: "stopped",
|
|
13933
|
-
stop: { callee: calleeName, reason: "multipleSources" }
|
|
13621
|
+
stop: { callee: calleeName, reason: "multipleSources" },
|
|
13622
|
+
declaration: declarationToReport(declarations, calleeName, scan)
|
|
13934
13623
|
};
|
|
13935
13624
|
}
|
|
13936
13625
|
}
|
|
13626
|
+
const reason = classifyStop(declarations, scan.scanning);
|
|
13627
|
+
const parameterIndex = reason === "callerSupplied" ? parameterIndexOf(declarations, scan.scanning) : void 0;
|
|
13937
13628
|
return {
|
|
13938
13629
|
kind: "stopped",
|
|
13939
|
-
stop: {
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
}
|
|
13630
|
+
stop: { callee: calleeName, reason },
|
|
13631
|
+
declaration: declarationToReport(declarations, calleeName, scan),
|
|
13632
|
+
...parameterIndex === void 0 ? {} : { parameterIndex }
|
|
13943
13633
|
};
|
|
13944
13634
|
}
|
|
13945
|
-
function
|
|
13635
|
+
function declarationToReport(declarations, calleeName, scan) {
|
|
13636
|
+
const first = declarations[0];
|
|
13637
|
+
if (first === void 0) {
|
|
13638
|
+
return null;
|
|
13639
|
+
}
|
|
13640
|
+
const sources = scan.sourceDeclarationsBehind?.(first) ?? [first];
|
|
13641
|
+
const only = sources.length === 1 ? sources[0] : void 0;
|
|
13642
|
+
if (only === void 0 || only === first) {
|
|
13643
|
+
return first;
|
|
13644
|
+
}
|
|
13645
|
+
return resolveDecl(only, calleeName)?.func ?? only;
|
|
13646
|
+
}
|
|
13647
|
+
function declaredAtOf(outcome) {
|
|
13648
|
+
if (outcome.kind === "followed") {
|
|
13649
|
+
return targetOf(outcome.candidate.func);
|
|
13650
|
+
}
|
|
13651
|
+
return outcome.declaration === null ? null : targetOf(outcome.declaration);
|
|
13652
|
+
}
|
|
13653
|
+
function passedPositionKey(target, position) {
|
|
13654
|
+
return `${offsetKeyFor(target.file, target.span)}#${position}`;
|
|
13655
|
+
}
|
|
13656
|
+
function resolveJsxReference(node, scan) {
|
|
13946
13657
|
if (!import_ts_morph62.Node.isJsxOpeningElement(node) && !import_ts_morph62.Node.isJsxSelfClosingElement(node)) {
|
|
13947
13658
|
return null;
|
|
13948
13659
|
}
|
|
@@ -13962,7 +13673,8 @@ function resolveJsxReference(node) {
|
|
|
13962
13673
|
tag: name,
|
|
13963
13674
|
outcome: {
|
|
13964
13675
|
kind: "stopped",
|
|
13965
|
-
stop: { callee: name, reason: classifyStop(declarations) }
|
|
13676
|
+
stop: { callee: name, reason: classifyStop(declarations) },
|
|
13677
|
+
declaration: declarationToReport(declarations, name, scan)
|
|
13966
13678
|
}
|
|
13967
13679
|
};
|
|
13968
13680
|
}
|
|
@@ -13970,11 +13682,15 @@ function collectReachable(func, scan) {
|
|
|
13970
13682
|
const inFunc = { ...scan, scanning: func };
|
|
13971
13683
|
const candidates = [];
|
|
13972
13684
|
const stops = [];
|
|
13685
|
+
const placements = new import_behavioral_ir7.TargetPlacements();
|
|
13686
|
+
const parameterCalls = [];
|
|
13687
|
+
const passedPositions = /* @__PURE__ */ new Set();
|
|
13973
13688
|
const seen = /* @__PURE__ */ new Set();
|
|
13689
|
+
const parameterCallsSeen = /* @__PURE__ */ new Set();
|
|
13974
13690
|
const record2 = (outcome) => {
|
|
13975
13691
|
if (outcome.kind === "stopped") {
|
|
13976
13692
|
const stopKey = `${outcome.stop.reason}:${outcome.stop.callee}`;
|
|
13977
|
-
if (!seen.has(stopKey) && worthRecording(outcome.stop.reason)) {
|
|
13693
|
+
if (!seen.has(stopKey) && (0, import_behavioral_ir3.worthRecording)(outcome.stop.reason)) {
|
|
13978
13694
|
seen.add(stopKey);
|
|
13979
13695
|
stops.push(outcome.stop);
|
|
13980
13696
|
}
|
|
@@ -13987,8 +13703,28 @@ function collectReachable(func, scan) {
|
|
|
13987
13703
|
seen.add(key);
|
|
13988
13704
|
candidates.push(outcome.candidate);
|
|
13989
13705
|
};
|
|
13706
|
+
const recordPassedArgs = (call, calleeText, calleeOutcome) => {
|
|
13707
|
+
if (!import_ts_morph62.Node.isCallExpression(call)) {
|
|
13708
|
+
return;
|
|
13709
|
+
}
|
|
13710
|
+
const calleeTarget = declaredAtOf(calleeOutcome);
|
|
13711
|
+
call.getArguments().forEach((arg, position) => {
|
|
13712
|
+
if (!import_ts_morph62.Node.isIdentifier(arg)) {
|
|
13713
|
+
return;
|
|
13714
|
+
}
|
|
13715
|
+
const resolved = functionTargetOf(arg);
|
|
13716
|
+
if (resolved === null) {
|
|
13717
|
+
return;
|
|
13718
|
+
}
|
|
13719
|
+
record2({ kind: "followed", candidate: resolved });
|
|
13720
|
+
placements.placeArg(calleeText, position, targetOf(resolved.func));
|
|
13721
|
+
if (calleeTarget !== null) {
|
|
13722
|
+
passedPositions.add(passedPositionKey(calleeTarget, position));
|
|
13723
|
+
}
|
|
13724
|
+
});
|
|
13725
|
+
};
|
|
13990
13726
|
func.forEachDescendant((node) => {
|
|
13991
|
-
const jsx = resolveJsxReference(node);
|
|
13727
|
+
const jsx = resolveJsxReference(node, inFunc);
|
|
13992
13728
|
if (jsx !== null) {
|
|
13993
13729
|
record2(jsx.outcome);
|
|
13994
13730
|
return;
|
|
@@ -14002,8 +13738,24 @@ function collectReachable(func, scan) {
|
|
|
14002
13738
|
return;
|
|
14003
13739
|
}
|
|
14004
13740
|
record2(outcome);
|
|
13741
|
+
placements.place(calleeText, declaredAtOf(outcome));
|
|
13742
|
+
recordPassedArgs(node, calleeText, outcome);
|
|
13743
|
+
if (outcome.kind === "stopped" && outcome.stop.reason === "callerSupplied" && outcome.parameterIndex !== void 0 && !parameterCallsSeen.has(calleeText)) {
|
|
13744
|
+
parameterCallsSeen.add(calleeText);
|
|
13745
|
+
parameterCalls.push({
|
|
13746
|
+
callee: calleeText,
|
|
13747
|
+
parameterIndex: outcome.parameterIndex
|
|
13748
|
+
});
|
|
13749
|
+
}
|
|
14005
13750
|
});
|
|
14006
|
-
return {
|
|
13751
|
+
return {
|
|
13752
|
+
candidates,
|
|
13753
|
+
stops,
|
|
13754
|
+
targets: placements.targets,
|
|
13755
|
+
argTargets: placements.argTargets,
|
|
13756
|
+
parameterCalls,
|
|
13757
|
+
passedPositions
|
|
13758
|
+
};
|
|
14007
13759
|
}
|
|
14008
13760
|
function normalizeCallee(text) {
|
|
14009
13761
|
return text.replace(/\s+/g, " ").trim();
|
|
@@ -14022,11 +13774,11 @@ function extractReachableSummary(candidate, options, recognizers) {
|
|
|
14022
13774
|
void 0,
|
|
14023
13775
|
recognizers.resolveWrittenValue
|
|
14024
13776
|
);
|
|
14025
|
-
raw.boundaryBinding = (0,
|
|
13777
|
+
raw.boundaryBinding = (0, import_behavioral_ir7.functionCallBinding)({
|
|
14026
13778
|
transport: "in-process",
|
|
14027
13779
|
recognition: "reachable"
|
|
14028
13780
|
});
|
|
14029
|
-
return (0,
|
|
13781
|
+
return (0, import_extractor7.assembleSummary)(raw, options);
|
|
14030
13782
|
}
|
|
14031
13783
|
var REACHABLE_RULES = [
|
|
14032
13784
|
(0, import_datalog4.rule)("reachable", [(0, import_datalog4.variable)("f")], [(0, import_datalog4.lit)("entry", (0, import_datalog4.variable)("f"))]),
|
|
@@ -14078,6 +13830,10 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
14078
13830
|
const seedKeys = /* @__PURE__ */ new Set();
|
|
14079
13831
|
const scanned = /* @__PURE__ */ new Set();
|
|
14080
13832
|
const stopsByKey = /* @__PURE__ */ new Map();
|
|
13833
|
+
const targetsByKey = /* @__PURE__ */ new Map();
|
|
13834
|
+
const argTargetsByKey = /* @__PURE__ */ new Map();
|
|
13835
|
+
const parameterCallsByKey = /* @__PURE__ */ new Map();
|
|
13836
|
+
const passedPositions = /* @__PURE__ */ new Set();
|
|
14081
13837
|
const summariesByKey = /* @__PURE__ */ new Map();
|
|
14082
13838
|
const reachedFrom = /* @__PURE__ */ new Map();
|
|
14083
13839
|
for (const seed of seeds) {
|
|
@@ -14122,9 +13878,17 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
14122
13878
|
const cameFrom = reachedFrom.get(key);
|
|
14123
13879
|
const scan = {
|
|
14124
13880
|
...recognizers.resolveCallableSources === void 0 ? {} : { resolveCallableSources: recognizers.resolveCallableSources },
|
|
13881
|
+
...recognizers.sourceDeclarationsBehind === void 0 ? {} : { sourceDeclarationsBehind: recognizers.sourceDeclarationsBehind },
|
|
14125
13882
|
...cameFrom === void 0 ? {} : { reachedFrom: cameFrom }
|
|
14126
13883
|
};
|
|
14127
|
-
const {
|
|
13884
|
+
const {
|
|
13885
|
+
candidates,
|
|
13886
|
+
stops,
|
|
13887
|
+
targets,
|
|
13888
|
+
argTargets,
|
|
13889
|
+
parameterCalls,
|
|
13890
|
+
passedPositions: scanPassedPositions
|
|
13891
|
+
} = scanWithRecording(
|
|
14128
13892
|
key,
|
|
14129
13893
|
facts,
|
|
14130
13894
|
() => collectReachable(source.func, scan)
|
|
@@ -14132,6 +13896,14 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
14132
13896
|
if (stops.length > 0) {
|
|
14133
13897
|
stopsByKey.set(key, stops);
|
|
14134
13898
|
}
|
|
13899
|
+
targetsByKey.set(key, targets);
|
|
13900
|
+
argTargetsByKey.set(key, argTargets);
|
|
13901
|
+
if (parameterCalls.length > 0) {
|
|
13902
|
+
parameterCallsByKey.set(key, parameterCalls);
|
|
13903
|
+
}
|
|
13904
|
+
for (const position of scanPassedPositions) {
|
|
13905
|
+
passedPositions.add(position);
|
|
13906
|
+
}
|
|
14135
13907
|
for (const candidate of candidates) {
|
|
14136
13908
|
const calleeKey = nodeKey(candidate.func);
|
|
14137
13909
|
if (!functionByKey.has(calleeKey)) {
|
|
@@ -14171,6 +13943,15 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
14171
13943
|
reached.push(summary);
|
|
14172
13944
|
}
|
|
14173
13945
|
recordStops(stopsByKey, summariesByKey, options);
|
|
13946
|
+
recordTargets(targetsByKey, summariesByKey);
|
|
13947
|
+
recordArgTargets(argTargetsByKey, summariesByKey);
|
|
13948
|
+
recordCalleeParameters(parameterCallsByKey, summariesByKey);
|
|
13949
|
+
recordParameterGaps(
|
|
13950
|
+
parameterCallsByKey,
|
|
13951
|
+
summariesByKey,
|
|
13952
|
+
passedPositions,
|
|
13953
|
+
options
|
|
13954
|
+
);
|
|
14174
13955
|
return [...seeds, ...reached];
|
|
14175
13956
|
}
|
|
14176
13957
|
function scanWithRecording(key, facts, fn) {
|
|
@@ -14198,7 +13979,91 @@ function recordStops(stopsByKey, summariesByKey, options) {
|
|
|
14198
13979
|
}
|
|
14199
13980
|
for (const [key, stops] of stopsByKey) {
|
|
14200
13981
|
for (const summary of summariesByKey.get(key) ?? []) {
|
|
14201
|
-
summary.gaps.push(...stops.map(unfollowedCallGap));
|
|
13982
|
+
summary.gaps.push(...stops.map(import_behavioral_ir3.unfollowedCallGap));
|
|
13983
|
+
}
|
|
13984
|
+
}
|
|
13985
|
+
}
|
|
13986
|
+
function recordTargets(targetsByKey, summariesByKey) {
|
|
13987
|
+
for (const [key, targets] of targetsByKey) {
|
|
13988
|
+
for (const summary of summariesByKey.get(key) ?? []) {
|
|
13989
|
+
for (const transition of summary.transitions) {
|
|
13990
|
+
for (const effect of transition.effects) {
|
|
13991
|
+
if (effect.type !== "invocation") {
|
|
13992
|
+
continue;
|
|
13993
|
+
}
|
|
13994
|
+
const target = targets.get(normalizeCallee(effect.callee));
|
|
13995
|
+
if (target !== void 0) {
|
|
13996
|
+
effect.declaredAt = target;
|
|
13997
|
+
}
|
|
13998
|
+
}
|
|
13999
|
+
}
|
|
14000
|
+
}
|
|
14001
|
+
}
|
|
14002
|
+
}
|
|
14003
|
+
function recordArgTargets(argTargetsByKey, summariesByKey) {
|
|
14004
|
+
for (const [key, argTargets] of argTargetsByKey) {
|
|
14005
|
+
for (const summary of summariesByKey.get(key) ?? []) {
|
|
14006
|
+
for (const transition of summary.transitions) {
|
|
14007
|
+
for (const effect of transition.effects) {
|
|
14008
|
+
if (effect.type !== "invocation") {
|
|
14009
|
+
continue;
|
|
14010
|
+
}
|
|
14011
|
+
const byPosition = argTargets.get(normalizeCallee(effect.callee));
|
|
14012
|
+
if (byPosition === void 0) {
|
|
14013
|
+
continue;
|
|
14014
|
+
}
|
|
14015
|
+
const argsDeclaredAt = {};
|
|
14016
|
+
for (const [position, target] of byPosition) {
|
|
14017
|
+
argsDeclaredAt[position] = target;
|
|
14018
|
+
}
|
|
14019
|
+
if (Object.keys(argsDeclaredAt).length > 0) {
|
|
14020
|
+
effect.argsDeclaredAt = argsDeclaredAt;
|
|
14021
|
+
}
|
|
14022
|
+
}
|
|
14023
|
+
}
|
|
14024
|
+
}
|
|
14025
|
+
}
|
|
14026
|
+
}
|
|
14027
|
+
function recordCalleeParameters(parameterCallsByKey, summariesByKey) {
|
|
14028
|
+
for (const [key, parameterCalls] of parameterCallsByKey) {
|
|
14029
|
+
const byCallee = new Map(
|
|
14030
|
+
parameterCalls.map(({ callee, parameterIndex }) => [
|
|
14031
|
+
callee,
|
|
14032
|
+
parameterIndex
|
|
14033
|
+
])
|
|
14034
|
+
);
|
|
14035
|
+
for (const summary of summariesByKey.get(key) ?? []) {
|
|
14036
|
+
for (const transition of summary.transitions) {
|
|
14037
|
+
for (const effect of transition.effects) {
|
|
14038
|
+
if (effect.type !== "invocation") {
|
|
14039
|
+
continue;
|
|
14040
|
+
}
|
|
14041
|
+
const parameterIndex = byCallee.get(normalizeCallee(effect.callee));
|
|
14042
|
+
if (parameterIndex !== void 0) {
|
|
14043
|
+
effect.calleeParameter = parameterIndex;
|
|
14044
|
+
}
|
|
14045
|
+
}
|
|
14046
|
+
}
|
|
14047
|
+
}
|
|
14048
|
+
}
|
|
14049
|
+
}
|
|
14050
|
+
function recordParameterGaps(parameterCallsByKey, summariesByKey, passedPositions, options) {
|
|
14051
|
+
if (options?.gapHandling === "silent") {
|
|
14052
|
+
return;
|
|
14053
|
+
}
|
|
14054
|
+
for (const [key, parameterCalls] of parameterCallsByKey) {
|
|
14055
|
+
const unbound = parameterCalls.filter(
|
|
14056
|
+
({ parameterIndex }) => !passedPositions.has(`${key}#${parameterIndex}`)
|
|
14057
|
+
);
|
|
14058
|
+
if (unbound.length === 0) {
|
|
14059
|
+
continue;
|
|
14060
|
+
}
|
|
14061
|
+
for (const summary of summariesByKey.get(key) ?? []) {
|
|
14062
|
+
summary.gaps.push(
|
|
14063
|
+
...unbound.map(
|
|
14064
|
+
({ callee }) => (0, import_behavioral_ir3.unfollowedCallGap)({ callee, reason: "unboundParameter" })
|
|
14065
|
+
)
|
|
14066
|
+
);
|
|
14202
14067
|
}
|
|
14203
14068
|
}
|
|
14204
14069
|
}
|
|
@@ -14933,9 +14798,8 @@ function readArrayLiteralText(node) {
|
|
|
14933
14798
|
}
|
|
14934
14799
|
|
|
14935
14800
|
// src/summaryIdentity.ts
|
|
14936
|
-
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
14937
14801
|
var import_node_path8 = __toESM(require("path"), 1);
|
|
14938
|
-
var
|
|
14802
|
+
var import_behavioral_ir8 = require("@suss/behavioral-ir");
|
|
14939
14803
|
function workspaceRootFor(anchor) {
|
|
14940
14804
|
return namedPackageDirAbove(anchor) ?? import_node_path8.default.resolve(anchor);
|
|
14941
14805
|
}
|
|
@@ -14950,32 +14814,6 @@ function workspaceNameFor(root) {
|
|
|
14950
14814
|
const folder = import_node_path8.default.basename(import_node_path8.default.resolve(root));
|
|
14951
14815
|
return folder.length > 0 ? folder : null;
|
|
14952
14816
|
}
|
|
14953
|
-
function namedPackageDirAbove(start) {
|
|
14954
|
-
let at = import_node_path8.default.resolve(start);
|
|
14955
|
-
for (let up = 0; up < 12; up += 1) {
|
|
14956
|
-
if (packageNameAt(at) !== null) {
|
|
14957
|
-
return at;
|
|
14958
|
-
}
|
|
14959
|
-
const parent = import_node_path8.default.dirname(at);
|
|
14960
|
-
if (parent === at) {
|
|
14961
|
-
break;
|
|
14962
|
-
}
|
|
14963
|
-
at = parent;
|
|
14964
|
-
}
|
|
14965
|
-
return null;
|
|
14966
|
-
}
|
|
14967
|
-
function packageNameAt(dir) {
|
|
14968
|
-
try {
|
|
14969
|
-
const manifest = JSON.parse(
|
|
14970
|
-
import_node_fs4.default.readFileSync(import_node_path8.default.join(dir, "package.json"), "utf8")
|
|
14971
|
-
);
|
|
14972
|
-
if (typeof manifest.name === "string" && manifest.name.length > 0) {
|
|
14973
|
-
return manifest.name;
|
|
14974
|
-
}
|
|
14975
|
-
} catch {
|
|
14976
|
-
}
|
|
14977
|
-
return null;
|
|
14978
|
-
}
|
|
14979
14817
|
function nameSummaries(summaries, args) {
|
|
14980
14818
|
for (const summary of summaries) {
|
|
14981
14819
|
const file = relativeFile(summary.location.file, args.projectRoot);
|
|
@@ -14984,8 +14822,8 @@ function nameSummaries(summaries, args) {
|
|
|
14984
14822
|
}
|
|
14985
14823
|
summary.identity.id = idFor(args.workspace, file, summary);
|
|
14986
14824
|
}
|
|
14987
|
-
(0,
|
|
14988
|
-
|
|
14825
|
+
(0, import_behavioral_ir8.disambiguateSummaryIds)(summaries);
|
|
14826
|
+
(0, import_behavioral_ir8.linkCallsToSummaries)(summaries);
|
|
14989
14827
|
}
|
|
14990
14828
|
function relativeFile(file, projectRoot) {
|
|
14991
14829
|
if (projectRoot === void 0 || !import_node_path8.default.isAbsolute(file)) {
|
|
@@ -14995,193 +14833,39 @@ function relativeFile(file, projectRoot) {
|
|
|
14995
14833
|
return relative.startsWith("..") ? file : relative;
|
|
14996
14834
|
}
|
|
14997
14835
|
function idFor(workspace, file, summary) {
|
|
14998
|
-
return (0,
|
|
14836
|
+
return (0, import_behavioral_ir8.summaryIdFromParts)({
|
|
14999
14837
|
workspace: workspace ?? void 0,
|
|
15000
14838
|
file,
|
|
15001
14839
|
name: summary.identity.name,
|
|
15002
14840
|
exportPath: summary.identity.exportPath
|
|
15003
14841
|
});
|
|
15004
14842
|
}
|
|
15005
|
-
function nameWhatEachCallReaches(summaries) {
|
|
15006
|
-
const byName = /* @__PURE__ */ new Map();
|
|
15007
|
-
const byFileAndName = /* @__PURE__ */ new Map();
|
|
15008
|
-
const remember = (index, key, summary) => {
|
|
15009
|
-
const found = index.get(key);
|
|
15010
|
-
if (found === void 0) {
|
|
15011
|
-
index.set(key, [summary]);
|
|
15012
|
-
return;
|
|
15013
|
-
}
|
|
15014
|
-
found.push(summary);
|
|
15015
|
-
};
|
|
15016
|
-
for (const summary of summaries) {
|
|
15017
|
-
if (summary.identity.nameKind === "label") {
|
|
15018
|
-
continue;
|
|
15019
|
-
}
|
|
15020
|
-
remember(byName, summary.identity.name, summary);
|
|
15021
|
-
remember(
|
|
15022
|
-
byFileAndName,
|
|
15023
|
-
`${summary.location.file}::${summary.identity.name}`,
|
|
15024
|
-
summary
|
|
15025
|
-
);
|
|
15026
|
-
}
|
|
15027
|
-
const onlyAnswer = (index, key) => {
|
|
15028
|
-
const found = index.get(key) ?? [];
|
|
15029
|
-
return found.length === 1 ? found[0] : null;
|
|
15030
|
-
};
|
|
15031
|
-
for (const summary of summaries) {
|
|
15032
|
-
for (const transition of summary.transitions) {
|
|
15033
|
-
for (const effect of transition.effects) {
|
|
15034
|
-
if (effect.type !== "invocation") {
|
|
15035
|
-
continue;
|
|
15036
|
-
}
|
|
15037
|
-
const called = effect.callee.split(".").pop() ?? effect.callee;
|
|
15038
|
-
const reached = onlyAnswer(byFileAndName, `${summary.location.file}::${called}`) ?? onlyAnswer(byName, called);
|
|
15039
|
-
if (reached?.identity.id !== void 0) {
|
|
15040
|
-
effect.summary = reached.identity.id;
|
|
15041
|
-
}
|
|
15042
|
-
}
|
|
15043
|
-
}
|
|
15044
|
-
}
|
|
15045
|
-
}
|
|
15046
14843
|
|
|
15047
14844
|
// src/timing.ts
|
|
15048
|
-
|
|
15049
|
-
const phases = /* @__PURE__ */ new Map();
|
|
15050
|
-
const start = performance.now();
|
|
15051
|
-
function record2(label, deltaMs) {
|
|
15052
|
-
const existing = phases.get(label);
|
|
15053
|
-
if (existing === void 0) {
|
|
15054
|
-
phases.set(label, { durationMs: deltaMs, calls: 1 });
|
|
15055
|
-
} else {
|
|
15056
|
-
existing.durationMs += deltaMs;
|
|
15057
|
-
existing.calls += 1;
|
|
15058
|
-
}
|
|
15059
|
-
}
|
|
15060
|
-
return {
|
|
15061
|
-
time(label, fn) {
|
|
15062
|
-
const t0 = performance.now();
|
|
15063
|
-
try {
|
|
15064
|
-
return fn();
|
|
15065
|
-
} finally {
|
|
15066
|
-
record2(label, performance.now() - t0);
|
|
15067
|
-
}
|
|
15068
|
-
},
|
|
15069
|
-
async timeAsync(label, fn) {
|
|
15070
|
-
const t0 = performance.now();
|
|
15071
|
-
try {
|
|
15072
|
-
return await fn();
|
|
15073
|
-
} finally {
|
|
15074
|
-
record2(label, performance.now() - t0);
|
|
15075
|
-
}
|
|
15076
|
-
},
|
|
15077
|
-
report() {
|
|
15078
|
-
const totalMs = performance.now() - start;
|
|
15079
|
-
const ordered = [...phases.entries()].map(([label, s]) => ({
|
|
15080
|
-
label,
|
|
15081
|
-
durationMs: s.durationMs,
|
|
15082
|
-
calls: s.calls
|
|
15083
|
-
})).sort((a, b) => b.durationMs - a.durationMs);
|
|
15084
|
-
return { totalMs, phases: ordered };
|
|
15085
|
-
}
|
|
15086
|
-
};
|
|
15087
|
-
}
|
|
14845
|
+
var import_extractor8 = require("@suss/extractor");
|
|
15088
14846
|
|
|
15089
14847
|
// src/version.ts
|
|
15090
|
-
var
|
|
15091
|
-
var
|
|
15092
|
-
var import_node_module = require("module");
|
|
15093
|
-
var import_node_path9 = __toESM(require("path"), 1);
|
|
15094
|
-
var import_node_url = require("url");
|
|
14848
|
+
var import_extractor9 = require("@suss/extractor");
|
|
14849
|
+
var import_extractor10 = require("@suss/extractor");
|
|
15095
14850
|
var import_meta = {};
|
|
15096
14851
|
var ADAPTER_VERSION = "0.2.1";
|
|
15097
|
-
var
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
"@suss/behavioral-ir"
|
|
15102
|
-
];
|
|
15103
|
-
var SOURCE_STAMP = { kind: "source" };
|
|
15104
|
-
var cachedCodeStamp = null;
|
|
15105
|
-
function adapterCodeStamp() {
|
|
15106
|
-
if (cachedCodeStamp !== null) {
|
|
15107
|
-
return cachedCodeStamp;
|
|
15108
|
-
}
|
|
15109
|
-
cachedCodeStamp = readAdapterCodeStamp();
|
|
15110
|
-
return cachedCodeStamp;
|
|
15111
|
-
}
|
|
15112
|
-
function readAdapterCodeStamp() {
|
|
15113
|
-
try {
|
|
15114
|
-
const selfPath = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
15115
|
-
const hash = computeDistHashFrom(import_node_path9.default.dirname(selfPath));
|
|
15116
|
-
return hash.length > 0 ? { kind: "bundle", hash } : SOURCE_STAMP;
|
|
15117
|
-
} catch {
|
|
15118
|
-
return SOURCE_STAMP;
|
|
15119
|
-
}
|
|
15120
|
-
}
|
|
15121
|
-
function computeDistHashFrom(dir) {
|
|
15122
|
-
const candidates = [import_node_path9.default.join(dir, "index.js"), import_node_path9.default.join(dir, "index.cjs")];
|
|
15123
|
-
for (const candidate of candidates) {
|
|
15124
|
-
if (!import_node_fs5.default.existsSync(candidate)) {
|
|
15125
|
-
continue;
|
|
15126
|
-
}
|
|
15127
|
-
return computeContentHash([candidate, ...analysisBundles()]);
|
|
15128
|
-
}
|
|
15129
|
-
return "";
|
|
15130
|
-
}
|
|
15131
|
-
function computeContentHash(paths) {
|
|
15132
|
-
if (paths.length === 0) {
|
|
15133
|
-
return "";
|
|
15134
|
-
}
|
|
15135
|
-
const hash = (0, import_node_crypto3.createHash)("sha256");
|
|
15136
|
-
for (const file of paths) {
|
|
15137
|
-
try {
|
|
15138
|
-
hash.update(import_node_fs5.default.readFileSync(file));
|
|
15139
|
-
} catch {
|
|
15140
|
-
return "";
|
|
15141
|
-
}
|
|
15142
|
-
}
|
|
15143
|
-
return hash.digest("hex").slice(0, 16);
|
|
15144
|
-
}
|
|
15145
|
-
function projectFileStamp(paths) {
|
|
15146
|
-
if (paths.length === 0) {
|
|
15147
|
-
return "none";
|
|
15148
|
-
}
|
|
15149
|
-
const hash = (0, import_node_crypto3.createHash)("sha256");
|
|
15150
|
-
for (const file of [...paths].sort()) {
|
|
15151
|
-
hash.update(file);
|
|
15152
|
-
hash.update("\0");
|
|
15153
|
-
try {
|
|
15154
|
-
hash.update(import_node_fs5.default.readFileSync(file));
|
|
15155
|
-
} catch {
|
|
15156
|
-
hash.update("absent");
|
|
15157
|
-
}
|
|
15158
|
-
}
|
|
15159
|
-
return hash.digest("hex").slice(0, 16);
|
|
15160
|
-
}
|
|
15161
|
-
function analysisBundles() {
|
|
15162
|
-
const require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
15163
|
-
const found = [];
|
|
15164
|
-
for (const name of ANALYSIS_PACKAGES) {
|
|
15165
|
-
try {
|
|
15166
|
-
found.push(require2.resolve(name));
|
|
15167
|
-
} catch {
|
|
15168
|
-
}
|
|
15169
|
-
}
|
|
15170
|
-
return found;
|
|
15171
|
-
}
|
|
14852
|
+
var stamp = (0, import_extractor9.createAdapterStamp)({
|
|
14853
|
+
moduleUrl: import_meta.url,
|
|
14854
|
+
version: ADAPTER_VERSION
|
|
14855
|
+
});
|
|
15172
14856
|
function computeAdapterPacksDigest(packVersions) {
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
return
|
|
14857
|
+
return stamp.packsDigest(packVersions);
|
|
14858
|
+
}
|
|
14859
|
+
function declineWhenRunFromSource(cacheDir) {
|
|
14860
|
+
return stamp.declineWhenRunFromSource(cacheDir);
|
|
15177
14861
|
}
|
|
15178
14862
|
|
|
15179
14863
|
// src/workspacePatterns.ts
|
|
15180
|
-
var
|
|
15181
|
-
var
|
|
14864
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
14865
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
15182
14866
|
function readJson(filePath) {
|
|
15183
14867
|
try {
|
|
15184
|
-
return JSON.parse(
|
|
14868
|
+
return JSON.parse(import_node_fs3.default.readFileSync(filePath, "utf8"));
|
|
15185
14869
|
} catch {
|
|
15186
14870
|
return void 0;
|
|
15187
14871
|
}
|
|
@@ -15208,7 +14892,7 @@ function pnpmWorkspaceGlobs(yamlText) {
|
|
|
15208
14892
|
return globs;
|
|
15209
14893
|
}
|
|
15210
14894
|
function workspaceGlobsAt(dir) {
|
|
15211
|
-
const pkg = readJson(
|
|
14895
|
+
const pkg = readJson(import_node_path9.default.join(dir, "package.json"));
|
|
15212
14896
|
if (typeof pkg === "object" && pkg !== null && "workspaces" in pkg) {
|
|
15213
14897
|
const ws = pkg.workspaces;
|
|
15214
14898
|
if (Array.isArray(ws)) {
|
|
@@ -15220,10 +14904,10 @@ function workspaceGlobsAt(dir) {
|
|
|
15220
14904
|
);
|
|
15221
14905
|
}
|
|
15222
14906
|
}
|
|
15223
|
-
const pnpmPath =
|
|
15224
|
-
if (
|
|
14907
|
+
const pnpmPath = import_node_path9.default.join(dir, "pnpm-workspace.yaml");
|
|
14908
|
+
if (import_node_fs3.default.existsSync(pnpmPath)) {
|
|
15225
14909
|
try {
|
|
15226
|
-
return pnpmWorkspaceGlobs(
|
|
14910
|
+
return pnpmWorkspaceGlobs(import_node_fs3.default.readFileSync(pnpmPath, "utf8"));
|
|
15227
14911
|
} catch {
|
|
15228
14912
|
return null;
|
|
15229
14913
|
}
|
|
@@ -15232,14 +14916,14 @@ function workspaceGlobsAt(dir) {
|
|
|
15232
14916
|
}
|
|
15233
14917
|
function isDirectory(candidate) {
|
|
15234
14918
|
try {
|
|
15235
|
-
return
|
|
14919
|
+
return import_node_fs3.default.statSync(candidate).isDirectory();
|
|
15236
14920
|
} catch {
|
|
15237
14921
|
return false;
|
|
15238
14922
|
}
|
|
15239
14923
|
}
|
|
15240
14924
|
function subdirectoriesOf(dir) {
|
|
15241
14925
|
try {
|
|
15242
|
-
return
|
|
14926
|
+
return import_node_fs3.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
15243
14927
|
} catch {
|
|
15244
14928
|
return [];
|
|
15245
14929
|
}
|
|
@@ -15257,13 +14941,13 @@ function directoriesMatchingGlob(root, glob) {
|
|
|
15257
14941
|
for (const dir of current2) {
|
|
15258
14942
|
for (const entry of subdirectoriesOf(dir)) {
|
|
15259
14943
|
if (pattern.test(entry)) {
|
|
15260
|
-
next.push(
|
|
14944
|
+
next.push(import_node_path9.default.join(dir, entry));
|
|
15261
14945
|
}
|
|
15262
14946
|
}
|
|
15263
14947
|
}
|
|
15264
14948
|
} else {
|
|
15265
14949
|
for (const dir of current2) {
|
|
15266
|
-
next.push(
|
|
14950
|
+
next.push(import_node_path9.default.join(dir, segment));
|
|
15267
14951
|
}
|
|
15268
14952
|
}
|
|
15269
14953
|
current2 = next.filter(isDirectory);
|
|
@@ -15271,7 +14955,7 @@ function directoriesMatchingGlob(root, glob) {
|
|
|
15271
14955
|
return current2;
|
|
15272
14956
|
}
|
|
15273
14957
|
function packageAt(dir) {
|
|
15274
|
-
const packageJsonPath =
|
|
14958
|
+
const packageJsonPath = import_node_path9.default.join(dir, "package.json");
|
|
15275
14959
|
const pkg = readJson(packageJsonPath);
|
|
15276
14960
|
if (typeof pkg === "object" && pkg !== null && typeof pkg.name === "string") {
|
|
15277
14961
|
return { name: pkg.name, packageJsonPath };
|
|
@@ -15279,7 +14963,7 @@ function packageAt(dir) {
|
|
|
15279
14963
|
return null;
|
|
15280
14964
|
}
|
|
15281
14965
|
function workspacePackagesFrom(anchor) {
|
|
15282
|
-
let dir =
|
|
14966
|
+
let dir = import_node_path9.default.resolve(anchor);
|
|
15283
14967
|
for (; ; ) {
|
|
15284
14968
|
const globs = workspaceGlobsAt(dir);
|
|
15285
14969
|
if (globs !== null) {
|
|
@@ -15299,7 +14983,7 @@ function workspacePackagesFrom(anchor) {
|
|
|
15299
14983
|
(a, b) => a.packageJsonPath.localeCompare(b.packageJsonPath)
|
|
15300
14984
|
);
|
|
15301
14985
|
}
|
|
15302
|
-
const parent =
|
|
14986
|
+
const parent = import_node_path9.default.dirname(dir);
|
|
15303
14987
|
if (parent === dir) {
|
|
15304
14988
|
return [];
|
|
15305
14989
|
}
|
|
@@ -15333,7 +15017,7 @@ function workspaceExpansionStamp(frameworks) {
|
|
|
15333
15017
|
const paths = frameworks.flatMap((pack) => pack.discovery).flatMap(
|
|
15334
15018
|
(pattern) => pattern.match.type === "packageExports" && pattern.match.packageJsonPath !== void 0 ? [pattern.match.packageJsonPath] : []
|
|
15335
15019
|
);
|
|
15336
|
-
return projectFileStamp(paths);
|
|
15020
|
+
return (0, import_extractor10.projectFileStamp)(paths);
|
|
15337
15021
|
}
|
|
15338
15022
|
function expandWorkspacePatterns(frameworks, anchor) {
|
|
15339
15023
|
const marked = frameworks.some(
|
|
@@ -15841,11 +15525,11 @@ function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
|
15841
15525
|
return null;
|
|
15842
15526
|
}
|
|
15843
15527
|
const method = extractBindingMethod(binding, callSite, pack, resolution);
|
|
15844
|
-
const
|
|
15845
|
-
return (0,
|
|
15528
|
+
const path14 = extractBindingPath(binding, callSite, pack, resolution);
|
|
15529
|
+
return (0, import_behavioral_ir9.restBinding)({
|
|
15846
15530
|
transport: pack.protocol,
|
|
15847
15531
|
method: method ?? null,
|
|
15848
|
-
path:
|
|
15532
|
+
path: path14 ?? null,
|
|
15849
15533
|
recognition: pack.name
|
|
15850
15534
|
});
|
|
15851
15535
|
}
|
|
@@ -15861,7 +15545,7 @@ function fileRouteBinding(filePath, unit, binding, pack) {
|
|
|
15861
15545
|
if (method === void 0) {
|
|
15862
15546
|
return null;
|
|
15863
15547
|
}
|
|
15864
|
-
return (0,
|
|
15548
|
+
return (0, import_behavioral_ir9.restBinding)({
|
|
15865
15549
|
transport: pack.protocol,
|
|
15866
15550
|
recognition: pack.name,
|
|
15867
15551
|
method,
|
|
@@ -15991,7 +15675,7 @@ function computeSubUnitBarriers(unit, packs, ctx, tallies, file) {
|
|
|
15991
15675
|
}
|
|
15992
15676
|
} catch (err) {
|
|
15993
15677
|
process.stderr.write(
|
|
15994
|
-
recordPackFailure(tallies?.get(pack.name), {
|
|
15678
|
+
(0, import_extractor3.recordPackFailure)(tallies?.get(pack.name), {
|
|
15995
15679
|
pack: pack.name,
|
|
15996
15680
|
hook: "subUnits",
|
|
15997
15681
|
file,
|
|
@@ -16053,7 +15737,7 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
16053
15737
|
}
|
|
16054
15738
|
} catch (err) {
|
|
16055
15739
|
process.stderr.write(
|
|
16056
|
-
recordPackFailure(tally, {
|
|
15740
|
+
(0, import_extractor3.recordPackFailure)(tally, {
|
|
16057
15741
|
pack: pack.name,
|
|
16058
15742
|
hook: "discoverUnits",
|
|
16059
15743
|
file: sourceFile.getFilePath(),
|
|
@@ -16114,7 +15798,7 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
16114
15798
|
stampWrappers(raw, unit, wrappers);
|
|
16115
15799
|
const matchedPattern = unit.pattern ?? pack.discovery.find((d) => d.kind === unit.kind);
|
|
16116
15800
|
if (unit.resolverInfo !== void 0) {
|
|
16117
|
-
raw.boundaryBinding = (0,
|
|
15801
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.graphqlResolverBinding)({
|
|
16118
15802
|
transport: pack.protocol,
|
|
16119
15803
|
recognition: pack.name,
|
|
16120
15804
|
typeName: unit.resolverInfo.typeName,
|
|
@@ -16141,26 +15825,26 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
16141
15825
|
}
|
|
16142
15826
|
}
|
|
16143
15827
|
} else if (unit.routeInfo !== void 0) {
|
|
16144
|
-
raw.boundaryBinding = (0,
|
|
15828
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.restBinding)({
|
|
16145
15829
|
transport: pack.protocol,
|
|
16146
15830
|
recognition: pack.name,
|
|
16147
15831
|
method: unit.routeInfo.method,
|
|
16148
15832
|
path: unit.routeInfo.path
|
|
16149
15833
|
});
|
|
16150
15834
|
} else if (unit.channelInfo !== void 0) {
|
|
16151
|
-
raw.boundaryBinding = (0,
|
|
15835
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.messageBusBinding)({
|
|
16152
15836
|
recognition: pack.name,
|
|
16153
15837
|
messageBus: unit.channelInfo.messageBus,
|
|
16154
15838
|
channel: unit.channelInfo.channel
|
|
16155
15839
|
});
|
|
16156
15840
|
} else if (unit.invocationInfo !== void 0) {
|
|
16157
|
-
raw.boundaryBinding = (0,
|
|
15841
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.unitInvocationBinding)({
|
|
16158
15842
|
recognition: pack.name,
|
|
16159
15843
|
deploymentTarget: unit.invocationInfo.deploymentTarget,
|
|
16160
15844
|
instanceName: unit.invocationInfo.instanceName
|
|
16161
15845
|
});
|
|
16162
15846
|
} else if (unit.operationInfo !== void 0) {
|
|
16163
|
-
raw.boundaryBinding = (0,
|
|
15847
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.graphqlOperationBinding)({
|
|
16164
15848
|
transport: pack.protocol,
|
|
16165
15849
|
recognition: pack.name,
|
|
16166
15850
|
operationType: unit.operationInfo.operationType,
|
|
@@ -16249,14 +15933,14 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
16249
15933
|
}
|
|
16250
15934
|
if (raw.boundaryBinding === null) {
|
|
16251
15935
|
if (unit.packageExportInfo !== void 0) {
|
|
16252
|
-
raw.boundaryBinding = (0,
|
|
15936
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.packageExportBinding)({
|
|
16253
15937
|
transport: pack.protocol,
|
|
16254
15938
|
recognition: pack.name,
|
|
16255
15939
|
packageName: unit.packageExportInfo.packageName,
|
|
16256
15940
|
exportPath: unit.packageExportInfo.exportPath
|
|
16257
15941
|
});
|
|
16258
15942
|
} else {
|
|
16259
|
-
raw.boundaryBinding = (0,
|
|
15943
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.functionCallBinding)({
|
|
16260
15944
|
transport: pack.protocol,
|
|
16261
15945
|
recognition: pack.name,
|
|
16262
15946
|
...unit.functionCallInfo !== void 0 ? {
|
|
@@ -16266,9 +15950,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
16266
15950
|
});
|
|
16267
15951
|
}
|
|
16268
15952
|
}
|
|
16269
|
-
const summary = (0,
|
|
15953
|
+
const summary = (0, import_extractor11.assembleSummary)(raw, options);
|
|
16270
15954
|
if (unit.unfollowed !== void 0 && options?.gapHandling !== "silent") {
|
|
16271
|
-
summary.gaps.push(unfollowedCallGap(unit.unfollowed));
|
|
15955
|
+
summary.gaps.push((0, import_behavioral_ir3.unfollowedCallGap)(unit.unfollowed));
|
|
16272
15956
|
}
|
|
16273
15957
|
if (unit.metadata !== void 0 && Object.keys(unit.metadata).length > 0) {
|
|
16274
15958
|
summary.metadata = {
|
|
@@ -16321,24 +16005,6 @@ function stampWrappers(raw, unit, wrappers) {
|
|
|
16321
16005
|
recordFileDependency(wrapper.file);
|
|
16322
16006
|
}
|
|
16323
16007
|
}
|
|
16324
|
-
function stampModuleImports(summaries, project) {
|
|
16325
|
-
const byFile2 = /* @__PURE__ */ new Map();
|
|
16326
|
-
for (const summary of summaries) {
|
|
16327
|
-
const file = summary.location.file;
|
|
16328
|
-
let imports = byFile2.get(file);
|
|
16329
|
-
if (imports === void 0) {
|
|
16330
|
-
imports = internalImportsOf(project, file);
|
|
16331
|
-
byFile2.set(file, imports);
|
|
16332
|
-
}
|
|
16333
|
-
if (imports.length === 0) {
|
|
16334
|
-
continue;
|
|
16335
|
-
}
|
|
16336
|
-
summary.metadata = {
|
|
16337
|
-
...summary.metadata ?? {},
|
|
16338
|
-
moduleImports: imports
|
|
16339
|
-
};
|
|
16340
|
-
}
|
|
16341
|
-
}
|
|
16342
16008
|
function emitLibraryEnvReadMarkers(summaries, project, frameworks) {
|
|
16343
16009
|
for (const pack of frameworks) {
|
|
16344
16010
|
for (const declared of pack.libraryEnvVars ?? []) {
|
|
@@ -16366,14 +16032,14 @@ function fileImporting(project, modulePrefix) {
|
|
|
16366
16032
|
function liftSchemasOntoDocuments(summaries) {
|
|
16367
16033
|
const sdlByDocument = /* @__PURE__ */ new Map();
|
|
16368
16034
|
for (const summary of summaries) {
|
|
16369
|
-
const label = (0,
|
|
16370
|
-
const graphql = (0,
|
|
16035
|
+
const label = (0, import_behavioral_ir9.readSourceDocumentMetadata)(summary)?.label;
|
|
16036
|
+
const graphql = (0, import_behavioral_ir9.readGraphqlMetadata)(summary);
|
|
16371
16037
|
if (label === void 0 || graphql?.schemaSdl === void 0) {
|
|
16372
16038
|
continue;
|
|
16373
16039
|
}
|
|
16374
16040
|
sdlByDocument.set(label, graphql.schemaSdl);
|
|
16375
16041
|
const { schemaSdl: _movedToTheDocument, ...rest } = graphql;
|
|
16376
|
-
summary.metadata = (0,
|
|
16042
|
+
summary.metadata = (0, import_behavioral_ir9.withGraphqlMetadata)(summary.metadata, rest);
|
|
16377
16043
|
}
|
|
16378
16044
|
for (const [label, schemaSdl] of sdlByDocument) {
|
|
16379
16045
|
summaries.push(schemaDocumentSummary(label, schemaSdl));
|
|
@@ -16388,8 +16054,8 @@ function schemaDocumentSummary(label, schemaSdl) {
|
|
|
16388
16054
|
transitions: [],
|
|
16389
16055
|
gaps: [],
|
|
16390
16056
|
confidence: { source: "declared", level: "high" },
|
|
16391
|
-
metadata: (0,
|
|
16392
|
-
(0,
|
|
16057
|
+
metadata: (0, import_behavioral_ir9.withGraphqlMetadata)(
|
|
16058
|
+
(0, import_behavioral_ir9.withSourceDocumentMetadata)(void 0, { label }),
|
|
16393
16059
|
{ schemaSdl }
|
|
16394
16060
|
)
|
|
16395
16061
|
};
|
|
@@ -16401,7 +16067,7 @@ function libraryEnvReadMarker(pack, declared, importer) {
|
|
|
16401
16067
|
identity: {
|
|
16402
16068
|
name: `${declared.module} env reads`,
|
|
16403
16069
|
exportPath: null,
|
|
16404
|
-
boundaryBinding: (0,
|
|
16070
|
+
boundaryBinding: (0, import_behavioral_ir9.functionCallBinding)({
|
|
16405
16071
|
transport: "in-process",
|
|
16406
16072
|
recognition: pack.name
|
|
16407
16073
|
})
|
|
@@ -16513,8 +16179,8 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
16513
16179
|
if (pathArg === void 0) {
|
|
16514
16180
|
continue;
|
|
16515
16181
|
}
|
|
16516
|
-
const
|
|
16517
|
-
if (
|
|
16182
|
+
const path14 = pathFromArgument(pathArg, resolution);
|
|
16183
|
+
if (path14 === void 0) {
|
|
16518
16184
|
continue;
|
|
16519
16185
|
}
|
|
16520
16186
|
const callerFunc = enclosingFunction(callExpr);
|
|
@@ -16526,7 +16192,7 @@ function synthesizeCallerSummaries(wrapper, _project, options, resolution) {
|
|
|
16526
16192
|
continue;
|
|
16527
16193
|
}
|
|
16528
16194
|
seen.add(dedupKey);
|
|
16529
|
-
out.push(buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
16195
|
+
out.push(buildCallerSummary(wrapper, callerFunc, callExpr, path14, options));
|
|
16530
16196
|
}
|
|
16531
16197
|
return out;
|
|
16532
16198
|
}
|
|
@@ -16583,7 +16249,7 @@ function callerName(func) {
|
|
|
16583
16249
|
}
|
|
16584
16250
|
return "anonymous";
|
|
16585
16251
|
}
|
|
16586
|
-
function buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
16252
|
+
function buildCallerSummary(wrapper, callerFunc, callExpr, path14, options) {
|
|
16587
16253
|
const wrapperBinding = wrapper.summary.identity.boundaryBinding;
|
|
16588
16254
|
const wrapperRest = wrapperBinding?.semantics.name === "rest" ? wrapperBinding.semantics : null;
|
|
16589
16255
|
const syntheticPack = {
|
|
@@ -16612,13 +16278,13 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path15, options) {
|
|
|
16612
16278
|
}
|
|
16613
16279
|
};
|
|
16614
16280
|
const raw = extractCodeStructure(unit, syntheticPack);
|
|
16615
|
-
raw.boundaryBinding = (0,
|
|
16281
|
+
raw.boundaryBinding = (0, import_behavioral_ir9.restBinding)({
|
|
16616
16282
|
transport: wrapperBinding?.transport ?? "http",
|
|
16617
16283
|
method: wrapperRest?.method ?? null,
|
|
16618
|
-
path:
|
|
16284
|
+
path: path14,
|
|
16619
16285
|
recognition: wrapperBinding?.recognition ?? "unknown"
|
|
16620
16286
|
});
|
|
16621
|
-
const summary = (0,
|
|
16287
|
+
const summary = (0, import_extractor11.assembleSummary)(raw, options);
|
|
16622
16288
|
summary.metadata = {
|
|
16623
16289
|
...summary.metadata ?? {},
|
|
16624
16290
|
derivedFromWrapper: {
|
|
@@ -16637,25 +16303,12 @@ function named(summaries, workspace, runRoot) {
|
|
|
16637
16303
|
});
|
|
16638
16304
|
return summaries;
|
|
16639
16305
|
}
|
|
16640
|
-
var saidWhyNoCache = false;
|
|
16641
16306
|
function extractionConfigStamp(config) {
|
|
16642
16307
|
return [
|
|
16643
16308
|
`includeReachable=${config.includeReachable !== false}`,
|
|
16644
16309
|
`gapHandling=${config.extractorOptions?.gapHandling ?? "default"}`
|
|
16645
16310
|
].join(",");
|
|
16646
16311
|
}
|
|
16647
|
-
function declineWhenRunFromSource(cacheDir) {
|
|
16648
|
-
if (cacheDir === null || adapterCodeStamp().kind === "bundle") {
|
|
16649
|
-
return cacheDir;
|
|
16650
|
-
}
|
|
16651
|
-
if (!saidWhyNoCache) {
|
|
16652
|
-
saidWhyNoCache = true;
|
|
16653
|
-
process.stderr.write(
|
|
16654
|
-
"[suss] extraction cache off: this process loaded the adapter from source, where nothing can tell one build of it from another. Run the built adapter to cache.\n"
|
|
16655
|
-
);
|
|
16656
|
-
}
|
|
16657
|
-
return null;
|
|
16658
|
-
}
|
|
16659
16312
|
function loadRunFiles(project, candidatePaths, timer) {
|
|
16660
16313
|
if (candidatePaths !== null) {
|
|
16661
16314
|
const deep2 = timer.time(
|
|
@@ -16686,7 +16339,7 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
16686
16339
|
...suppliedConfig,
|
|
16687
16340
|
frameworks: expandWorkspacePatterns(
|
|
16688
16341
|
suppliedConfig.frameworks,
|
|
16689
|
-
suppliedConfig.projectRoot ?? (suppliedConfig.tsConfigFilePath !== void 0 ?
|
|
16342
|
+
suppliedConfig.projectRoot ?? (suppliedConfig.tsConfigFilePath !== void 0 ? import_node_path10.default.dirname(suppliedConfig.tsConfigFilePath) : void 0)
|
|
16690
16343
|
)
|
|
16691
16344
|
};
|
|
16692
16345
|
const project = config.project ?? new import_ts_morph66.Project(
|
|
@@ -16695,24 +16348,18 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
16695
16348
|
skipAddingFilesFromTsConfig: true
|
|
16696
16349
|
} : { skipAddingFilesFromTsConfig: true }
|
|
16697
16350
|
);
|
|
16698
|
-
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(
|
|
16351
|
+
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(import_node_path10.default.dirname(config.tsConfigFilePath)) : void 0);
|
|
16699
16352
|
let lazyBootstrapped = false;
|
|
16700
16353
|
let projectFileSet;
|
|
16701
16354
|
const cacheDir = declineWhenRunFromSource(
|
|
16702
|
-
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ?
|
|
16355
|
+
config.cacheDir === null ? null : config.cacheDir ?? (config.tsConfigFilePath !== void 0 ? import_node_path10.default.join(import_node_path10.default.dirname(config.tsConfigFilePath), ".suss", "cache") : null)
|
|
16703
16356
|
);
|
|
16704
|
-
const cache = createCacheLayer(cacheDir);
|
|
16357
|
+
const cache = (0, import_extractor11.createCacheLayer)(cacheDir);
|
|
16705
16358
|
const packsDigest = `${computeAdapterPacksDigest(
|
|
16706
16359
|
config.frameworks.map(
|
|
16707
16360
|
(p) => p.version !== void 0 ? { name: p.name, version: p.version } : { name: p.name }
|
|
16708
16361
|
)
|
|
16709
16362
|
)}|${extractionConfigStamp(config)}|ws:${workspaceExpansionStamp(config.frameworks)}`;
|
|
16710
|
-
const digestFor = (files) => {
|
|
16711
|
-
const inputs = config.frameworks.flatMap(
|
|
16712
|
-
(pack) => pack.discoveryInputs?.(files) ?? []
|
|
16713
|
-
);
|
|
16714
|
-
return `${packsDigest}|reads:${projectFileStamp(inputs)}`;
|
|
16715
|
-
};
|
|
16716
16363
|
const packWrappers = config.frameworks.flatMap(
|
|
16717
16364
|
(pack) => pack.transparentWrappers ?? []
|
|
16718
16365
|
);
|
|
@@ -16745,8 +16392,8 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
16745
16392
|
return named(summaries, config.workspace, runRoot);
|
|
16746
16393
|
},
|
|
16747
16394
|
async extractAll() {
|
|
16748
|
-
const timer = createTimer();
|
|
16749
|
-
const tallies = createPackTallies(config.frameworks);
|
|
16395
|
+
const timer = (0, import_extractor8.createTimer)();
|
|
16396
|
+
const tallies = (0, import_extractor3.createPackTallies)(config.frameworks);
|
|
16750
16397
|
forgetUnreadableExportFiles();
|
|
16751
16398
|
forgetReassignedNamesUnstated();
|
|
16752
16399
|
const lazyEligible = !lazyBootstrapped && config.tsConfigFilePath !== void 0 && config.project === void 0;
|
|
@@ -16756,20 +16403,17 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
16756
16403
|
config.tsConfigFilePath ?? raise("lazy bootstrap requires tsConfigFilePath")
|
|
16757
16404
|
)
|
|
16758
16405
|
) : null;
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
() =>
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
tsconfigPath: config.tsConfigFilePath ?? raise("lazy bootstrap requires tsConfigFilePath")
|
|
16769
|
-
} : {
|
|
16770
|
-
project,
|
|
16406
|
+
let cacheFiles = null;
|
|
16407
|
+
const adapterPacksDigest = cacheDir === null ? packsDigest : timer.time("cache.digest", () => {
|
|
16408
|
+
cacheFiles = tsconfigFileList ?? project.getSourceFiles().map((sf) => sf.getFilePath());
|
|
16409
|
+
return (0, import_extractor11.runDigest)(packsDigest, config.frameworks, cacheFiles);
|
|
16410
|
+
});
|
|
16411
|
+
const cacheInput = {
|
|
16412
|
+
// Empty when cacheDir is null: a no-op cache layer never reads
|
|
16413
|
+
// the file list, so there is nothing worth resolving early.
|
|
16414
|
+
files: cacheFiles ?? [],
|
|
16771
16415
|
adapterPacksDigest,
|
|
16772
|
-
...config.tsConfigFilePath !== void 0 ? {
|
|
16416
|
+
...config.tsConfigFilePath !== void 0 ? { configPath: config.tsConfigFilePath } : {}
|
|
16773
16417
|
};
|
|
16774
16418
|
const lookup = await timer.timeAsync(
|
|
16775
16419
|
"cache.lookup",
|
|
@@ -16975,7 +16619,8 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
16975
16619
|
],
|
|
16976
16620
|
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
16977
16621
|
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value),
|
|
16978
|
-
resolveCallableSources: (value, alsoFrom) => resolution.resolveCallableSources(value, alsoFrom)
|
|
16622
|
+
resolveCallableSources: (value, alsoFrom) => resolution.resolveCallableSources(value, alsoFrom),
|
|
16623
|
+
sourceDeclarationsBehind: (declaration) => sourceDeclarationsBehind(declaration, resolution)
|
|
16979
16624
|
},
|
|
16980
16625
|
// Reached units the cache already serves emit nothing,
|
|
16981
16626
|
// the way a cold run's seeds do not.
|
|
@@ -17012,7 +16657,10 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
17012
16657
|
}
|
|
17013
16658
|
timer.time(
|
|
17014
16659
|
"stampModuleImports",
|
|
17015
|
-
() => stampModuleImports(enriched,
|
|
16660
|
+
() => (0, import_extractor11.stampModuleImports)(enriched, (file) => {
|
|
16661
|
+
const imports = internalImportsOf(project, file);
|
|
16662
|
+
return imports.length === 0 ? void 0 : imports;
|
|
16663
|
+
})
|
|
17016
16664
|
);
|
|
17017
16665
|
timer.time(
|
|
17018
16666
|
"emitLibraryEnvReadMarkers",
|
|
@@ -17071,7 +16719,7 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
17071
16719
|
});
|
|
17072
16720
|
const composed = timer.time(
|
|
17073
16721
|
"composeWrappers",
|
|
17074
|
-
() => (0,
|
|
16722
|
+
() => (0, import_extractor11.composeWrappers)(enriched)
|
|
17075
16723
|
);
|
|
17076
16724
|
if (config.onTiming !== void 0) {
|
|
17077
16725
|
config.onTiming(timer.report());
|
|
@@ -17103,7 +16751,7 @@ function createTypeScriptAdapter(suppliedConfig) {
|
|
|
17103
16751
|
};
|
|
17104
16752
|
}
|
|
17105
16753
|
function mountAssumptionsAgree(record2, index) {
|
|
17106
|
-
return Object.entries(record2.mountPrefixes).every(
|
|
16754
|
+
return Object.entries(record2.meta.mountPrefixes).every(
|
|
17107
16755
|
([childId, prefix]) => (index.prefixForId?.(childId) ?? "") === prefix
|
|
17108
16756
|
);
|
|
17109
16757
|
}
|
|
@@ -17203,10 +16851,10 @@ function mergeWithReused(reused, fresh, ownersBySummary) {
|
|
|
17203
16851
|
return { summaries: [...reusedKept, ...fresh], reusedKept, reusedOwners };
|
|
17204
16852
|
}
|
|
17205
16853
|
function readsRunLevelJoins(summary) {
|
|
17206
|
-
if ((0,
|
|
16854
|
+
if ((0, import_behavioral_ir9.readSourceDocumentMetadata)(summary) !== void 0) {
|
|
17207
16855
|
return true;
|
|
17208
16856
|
}
|
|
17209
|
-
if ((0,
|
|
16857
|
+
if ((0, import_behavioral_ir9.readGraphqlMetadata)(summary)?.client !== void 0) {
|
|
17210
16858
|
return true;
|
|
17211
16859
|
}
|
|
17212
16860
|
const semantics = summary.identity.boundaryBinding?.semantics;
|
|
@@ -17263,7 +16911,7 @@ function buildCacheAttribution(args) {
|
|
|
17263
16911
|
cacheable,
|
|
17264
16912
|
deps: [...deps].sort(),
|
|
17265
16913
|
claims: sink.claims,
|
|
17266
|
-
mountPrefixes: Object.fromEntries(sink.mountPrefixes),
|
|
16914
|
+
meta: { mountPrefixes: Object.fromEntries(sink.mountPrefixes) },
|
|
17267
16915
|
packs: packNamesByPath.get(rootPath) ?? []
|
|
17268
16916
|
});
|
|
17269
16917
|
}
|
|
@@ -17396,7 +17044,7 @@ function buildSubUnitSummary(subUnit, parent, invocationRecognizers, accessRecog
|
|
|
17396
17044
|
if (parent.identity.boundaryBinding !== null) {
|
|
17397
17045
|
raw.boundaryBinding = parent.identity.boundaryBinding;
|
|
17398
17046
|
}
|
|
17399
|
-
const summary = (0,
|
|
17047
|
+
const summary = (0, import_extractor11.assembleSummary)(raw, options);
|
|
17400
17048
|
if (subUnit.metadata !== void 0 && Object.keys(subUnit.metadata).length > 0) {
|
|
17401
17049
|
summary.metadata = {
|
|
17402
17050
|
...summary.metadata ?? {},
|
|
@@ -17408,8 +17056,8 @@ function buildSubUnitSummary(subUnit, parent, invocationRecognizers, accessRecog
|
|
|
17408
17056
|
}
|
|
17409
17057
|
|
|
17410
17058
|
// src/bootstrap/noTsconfigProject.ts
|
|
17411
|
-
var
|
|
17412
|
-
var
|
|
17059
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
17060
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
17413
17061
|
var import_ts_morph67 = require("ts-morph");
|
|
17414
17062
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
17415
17063
|
".ts",
|
|
@@ -17440,7 +17088,7 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
17440
17088
|
const found = [];
|
|
17441
17089
|
let entries;
|
|
17442
17090
|
try {
|
|
17443
|
-
entries =
|
|
17091
|
+
entries = import_node_fs4.default.readdirSync(rootDir, { withFileTypes: true });
|
|
17444
17092
|
} catch {
|
|
17445
17093
|
return [];
|
|
17446
17094
|
}
|
|
@@ -17448,10 +17096,10 @@ function findSourceFiles(rootDir, depth = 0) {
|
|
|
17448
17096
|
if (entry.name.startsWith(".") || SKIP_DIRECTORIES.has(entry.name)) {
|
|
17449
17097
|
continue;
|
|
17450
17098
|
}
|
|
17451
|
-
const full =
|
|
17099
|
+
const full = import_node_path11.default.join(rootDir, entry.name);
|
|
17452
17100
|
if (entry.isDirectory()) {
|
|
17453
17101
|
found.push(...findSourceFiles(full, depth + 1));
|
|
17454
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
17102
|
+
} else if (SOURCE_EXTENSIONS.has(import_node_path11.default.extname(entry.name)) && !entry.name.endsWith(".d.ts")) {
|
|
17455
17103
|
found.push(full);
|
|
17456
17104
|
}
|
|
17457
17105
|
}
|
|
@@ -17486,15 +17134,15 @@ function createProjectWithoutTsconfig(rootDir) {
|
|
|
17486
17134
|
return { project, files };
|
|
17487
17135
|
}
|
|
17488
17136
|
function findNearestTsconfig(startDir) {
|
|
17489
|
-
let dir =
|
|
17137
|
+
let dir = import_node_path11.default.resolve(startDir);
|
|
17490
17138
|
while (true) {
|
|
17491
17139
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
17492
|
-
const candidate =
|
|
17493
|
-
if (
|
|
17140
|
+
const candidate = import_node_path11.default.join(dir, name);
|
|
17141
|
+
if (import_node_fs4.default.existsSync(candidate)) {
|
|
17494
17142
|
return candidate;
|
|
17495
17143
|
}
|
|
17496
17144
|
}
|
|
17497
|
-
const parent =
|
|
17145
|
+
const parent = import_node_path11.default.dirname(dir);
|
|
17498
17146
|
if (parent === dir) {
|
|
17499
17147
|
return null;
|
|
17500
17148
|
}
|
|
@@ -17503,7 +17151,7 @@ function findNearestTsconfig(startDir) {
|
|
|
17503
17151
|
}
|
|
17504
17152
|
|
|
17505
17153
|
// src/facts/why.ts
|
|
17506
|
-
var
|
|
17154
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
17507
17155
|
var import_ts_morph68 = require("ts-morph");
|
|
17508
17156
|
var import_resolution7 = require("@suss/resolution");
|
|
17509
17157
|
var JS_PHRASES = {
|
|
@@ -17511,12 +17159,12 @@ var JS_PHRASES = {
|
|
|
17511
17159
|
reason: `${describe(tuple[0])} is a .bind of ${describe(tuple[1])}, which runs the same function`
|
|
17512
17160
|
})
|
|
17513
17161
|
};
|
|
17514
|
-
var
|
|
17162
|
+
var TypeScriptWhySession = class {
|
|
17515
17163
|
project;
|
|
17516
17164
|
store;
|
|
17517
17165
|
root;
|
|
17518
17166
|
constructor(options) {
|
|
17519
|
-
this.root =
|
|
17167
|
+
this.root = import_node_path12.default.resolve(options.dir);
|
|
17520
17168
|
const tsconfig = findNearestTsconfig(this.root);
|
|
17521
17169
|
this.project = tsconfig === null ? createProjectWithoutTsconfig(this.root).project : new import_ts_morph68.Project({ tsConfigFilePath: tsconfig });
|
|
17522
17170
|
this.store = new ResolutionStore();
|
|
@@ -17605,7 +17253,7 @@ var WhySession = class {
|
|
|
17605
17253
|
};
|
|
17606
17254
|
}
|
|
17607
17255
|
sourceFileAt(file) {
|
|
17608
|
-
const absolute =
|
|
17256
|
+
const absolute = import_node_path12.default.resolve(this.root, file);
|
|
17609
17257
|
const loaded = this.project.getSourceFile(absolute);
|
|
17610
17258
|
if (loaded !== void 0) {
|
|
17611
17259
|
return loaded;
|
|
@@ -17619,7 +17267,7 @@ var WhySession = class {
|
|
|
17619
17267
|
/** A module key: a file path said relative to the root, or a package name. */
|
|
17620
17268
|
displayPath(key) {
|
|
17621
17269
|
if (key.startsWith(this.root)) {
|
|
17622
|
-
return
|
|
17270
|
+
return import_node_path12.default.relative(this.root, key);
|
|
17623
17271
|
}
|
|
17624
17272
|
return key;
|
|
17625
17273
|
}
|
|
@@ -17647,228 +17295,8 @@ function displayNameOf(node) {
|
|
|
17647
17295
|
return text.length > 40 ? `${text.slice(0, 40)}...` : text;
|
|
17648
17296
|
}
|
|
17649
17297
|
|
|
17650
|
-
// src/packHealth.ts
|
|
17651
|
-
function stagesOf(funnel) {
|
|
17652
|
-
const stages = [];
|
|
17653
|
-
const gateSaysSomething = funnel.gates.length > 0 && funnel.unresolvedGates.length === 0;
|
|
17654
|
-
if (funnel.recognizes && !funnel.discovers && gateSaysSomething) {
|
|
17655
|
-
stages.push({
|
|
17656
|
-
from: { count: funnel.unitsInGatedFiles, name: "unit bodies" },
|
|
17657
|
-
to: { count: funnel.effectsRecognized, name: "effects" }
|
|
17658
|
-
});
|
|
17659
|
-
}
|
|
17660
|
-
if (funnel.discovers && gateSaysSomething) {
|
|
17661
|
-
stages.push({
|
|
17662
|
-
from: { count: funnel.candidateFiles, name: "source files" },
|
|
17663
|
-
to: { count: funnel.unitsDiscovered, name: "units" }
|
|
17664
|
-
});
|
|
17665
|
-
}
|
|
17666
|
-
stages.push(
|
|
17667
|
-
{
|
|
17668
|
-
from: { count: funnel.unitsClaimed, name: "units" },
|
|
17669
|
-
to: { count: funnel.summariesBound, name: "summaries" }
|
|
17670
|
-
},
|
|
17671
|
-
{
|
|
17672
|
-
from: { count: funnel.summariesBound, name: "summaries" },
|
|
17673
|
-
to: { count: funnel.summariesWithBehavior, name: "transitions" }
|
|
17674
|
-
}
|
|
17675
|
-
);
|
|
17676
|
-
return stages;
|
|
17677
|
-
}
|
|
17678
|
-
function funnelDrops(packs) {
|
|
17679
|
-
const violations = [];
|
|
17680
|
-
for (const funnel of packs) {
|
|
17681
|
-
for (const stage of stagesOf(funnel)) {
|
|
17682
|
-
if (stage.from.count === 0 || stage.to.count > 0) {
|
|
17683
|
-
continue;
|
|
17684
|
-
}
|
|
17685
|
-
violations.push({
|
|
17686
|
-
label: funnel.pack,
|
|
17687
|
-
detail: `${stage.from.count} ${stage.from.name} -> 0 ${stage.to.name}`
|
|
17688
|
-
});
|
|
17689
|
-
}
|
|
17690
|
-
}
|
|
17691
|
-
return violations;
|
|
17692
|
-
}
|
|
17693
|
-
function recognizersWithNoUnits(packs) {
|
|
17694
|
-
return packs.filter(
|
|
17695
|
-
(funnel) => funnel.recognizes && !funnel.discovers && funnel.gates.length > 0 && funnel.unresolvedGates.length === 0 && funnel.candidateFiles > 0 && funnel.unitsInGatedFiles === 0 && // The closure walks a recognizer-only pack's gated exports as
|
|
17696
|
-
// roots, so effects recognized there mean the run worked and
|
|
17697
|
-
// the missing framework pack costs attribution, not existence.
|
|
17698
|
-
funnel.effectsRecognized === 0
|
|
17699
|
-
).map((funnel) => ({
|
|
17700
|
-
label: funnel.pack,
|
|
17701
|
-
detail: `${funnel.candidateFiles} gated files, and no pack in this run discovered a unit in them. ${funnel.pack} reads calls inside units another pack finds, so add the pack that finds this project's handlers (-f express, -f fastify, ...), or run suss init to work out which.`
|
|
17702
|
-
}));
|
|
17703
|
-
}
|
|
17704
|
-
function helpersThatMatchedNothing(packs) {
|
|
17705
|
-
return packs.flatMap(
|
|
17706
|
-
(funnel) => funnel.helpersUnmatched.map((helper) => ({
|
|
17707
|
-
label: funnel.pack,
|
|
17708
|
-
detail: `${helper} matched no call in this run, so whatever it registers is missing. suss read that helper out of the project and then failed to match a call to it, which is a bug in suss rather than in your code.`
|
|
17709
|
-
}))
|
|
17710
|
-
);
|
|
17711
|
-
}
|
|
17712
|
-
function unversionedPacks(packs) {
|
|
17713
|
-
return packs.filter((funnel) => funnel.version === null).map((funnel) => ({
|
|
17714
|
-
label: funnel.pack,
|
|
17715
|
-
detail: "no version declared"
|
|
17716
|
-
}));
|
|
17717
|
-
}
|
|
17718
|
-
function selfCollisions(packs) {
|
|
17719
|
-
return packs.filter((funnel) => funnel.selfCollisions > 0).map((funnel) => ({
|
|
17720
|
-
label: funnel.pack,
|
|
17721
|
-
detail: `${funnel.selfCollisions} ${funnel.selfCollisions === 1 ? "unit" : "units"} matched twice, second dropped`
|
|
17722
|
-
}));
|
|
17723
|
-
}
|
|
17724
|
-
function threwWhileReading(packs) {
|
|
17725
|
-
return packs.filter((funnel) => funnel.failures.length > 0).map((funnel) => {
|
|
17726
|
-
const first = funnel.failures[0];
|
|
17727
|
-
const rest = funnel.failures.length - 1;
|
|
17728
|
-
const alsoIn = rest > 0 ? ` (+${rest} more)` : "";
|
|
17729
|
-
return {
|
|
17730
|
-
label: funnel.pack,
|
|
17731
|
-
detail: `${first.hook} on ${first.file}${alsoIn}: ${first.message}`
|
|
17732
|
-
};
|
|
17733
|
-
});
|
|
17734
|
-
}
|
|
17735
|
-
function packGradients(report) {
|
|
17736
|
-
const gradients = [];
|
|
17737
|
-
for (const funnel of report.packs) {
|
|
17738
|
-
if (funnel.declarations === null) {
|
|
17739
|
-
continue;
|
|
17740
|
-
}
|
|
17741
|
-
gradients.push(gradientOf(funnel.pack, funnel.declarations.declarations));
|
|
17742
|
-
}
|
|
17743
|
-
return gradients;
|
|
17744
|
-
}
|
|
17745
|
-
function gradientOf(pack, declarations) {
|
|
17746
|
-
const gradient = {
|
|
17747
|
-
pack,
|
|
17748
|
-
dataLinks: 0,
|
|
17749
|
-
functionLinks: [],
|
|
17750
|
-
astLinks: [],
|
|
17751
|
-
withoutExample: []
|
|
17752
|
-
};
|
|
17753
|
-
for (const declaration of declarations) {
|
|
17754
|
-
gradient.dataLinks += declaration.dataLinks;
|
|
17755
|
-
for (const question of declaration.functionLinks) {
|
|
17756
|
-
gradient.functionLinks.push(`${declaration.name}.${question}`);
|
|
17757
|
-
}
|
|
17758
|
-
for (const question of declaration.astLinks) {
|
|
17759
|
-
gradient.astLinks.push(`${declaration.name}.${question}`);
|
|
17760
|
-
}
|
|
17761
|
-
if (declaration.example === null) {
|
|
17762
|
-
gradient.withoutExample.push(declaration.name);
|
|
17763
|
-
}
|
|
17764
|
-
}
|
|
17765
|
-
return gradient;
|
|
17766
|
-
}
|
|
17767
|
-
function opaqueLinks(gradients) {
|
|
17768
|
-
return gradients.filter((gradient) => gradient.functionLinks.length > 0).map((gradient) => ({
|
|
17769
|
-
label: gradient.pack,
|
|
17770
|
-
detail: `${gradient.functionLinks.join(", ")} (${gradient.dataLinks} data)`
|
|
17771
|
-
}));
|
|
17772
|
-
}
|
|
17773
|
-
function reachesTheSyntaxTree(gradients) {
|
|
17774
|
-
return gradients.filter((gradient) => gradient.astLinks.length > 0).map((gradient) => ({
|
|
17775
|
-
label: gradient.pack,
|
|
17776
|
-
detail: gradient.astLinks.join(", ")
|
|
17777
|
-
}));
|
|
17778
|
-
}
|
|
17779
|
-
function undocumentedDeclarations(gradients) {
|
|
17780
|
-
return gradients.filter((gradient) => gradient.withoutExample.length > 0).map((gradient) => ({
|
|
17781
|
-
label: gradient.pack,
|
|
17782
|
-
detail: gradient.withoutExample.join(", ")
|
|
17783
|
-
}));
|
|
17784
|
-
}
|
|
17785
|
-
function evaluatePackHealth(report) {
|
|
17786
|
-
const gradients = packGradients(report);
|
|
17787
|
-
return [
|
|
17788
|
-
{
|
|
17789
|
-
name: "no pack throws while it reads",
|
|
17790
|
-
code: "threw",
|
|
17791
|
-
audience: "run",
|
|
17792
|
-
violations: threwWhileReading(report.packs)
|
|
17793
|
-
},
|
|
17794
|
-
{
|
|
17795
|
-
name: "no pack finds something and records nothing",
|
|
17796
|
-
code: "no-output",
|
|
17797
|
-
audience: "run",
|
|
17798
|
-
violations: funnelDrops(report.packs)
|
|
17799
|
-
},
|
|
17800
|
-
{
|
|
17801
|
-
name: "no pack collides with itself",
|
|
17802
|
-
code: "double-match",
|
|
17803
|
-
audience: "run",
|
|
17804
|
-
violations: selfCollisions(report.packs)
|
|
17805
|
-
},
|
|
17806
|
-
{
|
|
17807
|
-
name: "every recognizer had units to look inside",
|
|
17808
|
-
code: "no-units",
|
|
17809
|
-
audience: "run",
|
|
17810
|
-
violations: recognizersWithNoUnits(report.packs)
|
|
17811
|
-
},
|
|
17812
|
-
{
|
|
17813
|
-
name: "every registration helper the run read matched a call",
|
|
17814
|
-
code: "no-helper",
|
|
17815
|
-
audience: "run",
|
|
17816
|
-
violations: helpersThatMatchedNothing(report.packs)
|
|
17817
|
-
},
|
|
17818
|
-
{
|
|
17819
|
-
name: "every pack declares a version",
|
|
17820
|
-
code: "no-version",
|
|
17821
|
-
audience: "pack",
|
|
17822
|
-
violations: unversionedPacks(report.packs)
|
|
17823
|
-
},
|
|
17824
|
-
{
|
|
17825
|
-
name: "every link a declared pack states is data",
|
|
17826
|
-
code: "fn-link",
|
|
17827
|
-
audience: "pack",
|
|
17828
|
-
violations: opaqueLinks(gradients)
|
|
17829
|
-
},
|
|
17830
|
-
{
|
|
17831
|
-
name: "no declared pack reads the syntax tree",
|
|
17832
|
-
code: "ast-link",
|
|
17833
|
-
audience: "pack",
|
|
17834
|
-
violations: reachesTheSyntaxTree(gradients)
|
|
17835
|
-
},
|
|
17836
|
-
{
|
|
17837
|
-
name: "every declaration states an example",
|
|
17838
|
-
code: "no-example",
|
|
17839
|
-
audience: "pack",
|
|
17840
|
-
violations: undocumentedDeclarations(gradients)
|
|
17841
|
-
}
|
|
17842
|
-
];
|
|
17843
|
-
}
|
|
17844
|
-
function formatPackHealth(checks, audiences) {
|
|
17845
|
-
const fired = checks.filter(
|
|
17846
|
-
(check) => check.violations.length > 0 && audiences.includes(check.audience)
|
|
17847
|
-
);
|
|
17848
|
-
if (fired.length === 0) {
|
|
17849
|
-
return "";
|
|
17850
|
-
}
|
|
17851
|
-
const rows = fired.flatMap(
|
|
17852
|
-
(check) => check.violations.map((violation) => ({
|
|
17853
|
-
code: check.code,
|
|
17854
|
-
pack: violation.label,
|
|
17855
|
-
detail: violation.detail
|
|
17856
|
-
}))
|
|
17857
|
-
);
|
|
17858
|
-
const codeWidth = Math.max(...rows.map((row) => row.code.length));
|
|
17859
|
-
const packWidth = Math.max(...rows.map((row) => row.pack.length));
|
|
17860
|
-
const lines = ["", `Pack health (${rows.length}):`];
|
|
17861
|
-
for (const row of rows) {
|
|
17862
|
-
lines.push(
|
|
17863
|
-
` ${row.code.padEnd(codeWidth)} ${row.pack.padEnd(packWidth)} ${row.detail}`
|
|
17864
|
-
);
|
|
17865
|
-
}
|
|
17866
|
-
return `${lines.join("\n")}
|
|
17867
|
-
`;
|
|
17868
|
-
}
|
|
17869
|
-
|
|
17870
17298
|
// src/stubEvidence.ts
|
|
17871
|
-
var
|
|
17299
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
17872
17300
|
var import_ts_morph69 = require("ts-morph");
|
|
17873
17301
|
function stubEvidenceIn(project, packageName, root) {
|
|
17874
17302
|
const resolution = new ResolutionStore();
|
|
@@ -17884,7 +17312,7 @@ function stubEvidenceIn(project, packageName, root) {
|
|
|
17884
17312
|
calls: []
|
|
17885
17313
|
};
|
|
17886
17314
|
entry.calls.push({
|
|
17887
|
-
file:
|
|
17315
|
+
file: import_node_path13.default.relative(root, sourceFile.getFilePath()).split(import_node_path13.default.sep).join("/"),
|
|
17888
17316
|
line: one.call.getStartLineNumber(),
|
|
17889
17317
|
args: one.call.getArguments().map((arg) => effectArgOf(arg))
|
|
17890
17318
|
});
|
|
@@ -17899,7 +17327,7 @@ function stubEvidence(options) {
|
|
|
17899
17327
|
const project = new import_ts_morph69.Project(
|
|
17900
17328
|
options.tsConfigFilePath !== void 0 ? { tsConfigFilePath: options.tsConfigFilePath } : { compilerOptions: { allowJs: true } }
|
|
17901
17329
|
);
|
|
17902
|
-
const root = options.tsConfigFilePath !== void 0 ?
|
|
17330
|
+
const root = options.tsConfigFilePath !== void 0 ? import_node_path13.default.dirname(options.tsConfigFilePath) : import_node_path13.default.resolve(options.directory ?? process.cwd());
|
|
17903
17331
|
if (options.tsConfigFilePath === void 0) {
|
|
17904
17332
|
project.addSourceFilesAtPaths([
|
|
17905
17333
|
`${root}/**/*.{ts,tsx,js,jsx}`,
|
|
@@ -17912,7 +17340,7 @@ function stubEvidence(options) {
|
|
|
17912
17340
|
0 && (module.exports = {
|
|
17913
17341
|
ADAPTER_VERSION,
|
|
17914
17342
|
ResolutionStore,
|
|
17915
|
-
|
|
17343
|
+
TypeScriptWhySession,
|
|
17916
17344
|
accessContextFor,
|
|
17917
17345
|
buildProjectHelperIndex,
|
|
17918
17346
|
callOpsFor,
|
|
@@ -17925,13 +17353,11 @@ function stubEvidence(options) {
|
|
|
17925
17353
|
createTsSubUnitContext,
|
|
17926
17354
|
createTypeScriptAdapter,
|
|
17927
17355
|
discoverUnits,
|
|
17928
|
-
evaluatePackHealth,
|
|
17929
17356
|
exportedDeclarationsOf,
|
|
17930
17357
|
extractCodeStructure,
|
|
17931
17358
|
extractRawBranches,
|
|
17932
17359
|
findNearestTsconfig,
|
|
17933
17360
|
findTerminals,
|
|
17934
|
-
formatPackHealth,
|
|
17935
17361
|
functionTargetOf,
|
|
17936
17362
|
importDeclarationsOf,
|
|
17937
17363
|
importedNamesOf,
|