@suss/adapter-python 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/dist/index.cjs +654 -224
- package/dist/index.d.cts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +652 -221
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -97,6 +97,12 @@ var LATER_BODY_TYPES = /* @__PURE__ */ new Set([
|
|
|
97
97
|
"lambda",
|
|
98
98
|
"class_definition"
|
|
99
99
|
]);
|
|
100
|
+
function isModule(node) {
|
|
101
|
+
return node.type === "module";
|
|
102
|
+
}
|
|
103
|
+
function runsAtModuleLoad(node) {
|
|
104
|
+
return !LATER_BODY_TYPES.has(node.type) && node.type !== "decorator";
|
|
105
|
+
}
|
|
100
106
|
function enclosingFunction(node) {
|
|
101
107
|
let current = node.parent;
|
|
102
108
|
while (current !== null) {
|
|
@@ -784,8 +790,14 @@ var import_resolution = require("@suss/resolution");
|
|
|
784
790
|
function resolveCalls(db, callKeys) {
|
|
785
791
|
(0, import_resolution.askResolution)(db, callKeys);
|
|
786
792
|
}
|
|
787
|
-
function
|
|
788
|
-
(0, import_resolution.askResolution)(db,
|
|
793
|
+
function resolveEnvObjects(db, objectKeys) {
|
|
794
|
+
(0, import_resolution.askResolution)(db, objectKeys, "wantedEnvObject");
|
|
795
|
+
}
|
|
796
|
+
function resolvedFunctions(db, key) {
|
|
797
|
+
return [
|
|
798
|
+
...db.lookup("wantedResolves", 0, key),
|
|
799
|
+
...db.lookup("wantedGivesBack", 0, key)
|
|
800
|
+
].map((row) => String(row[1]));
|
|
789
801
|
}
|
|
790
802
|
function writtenValueUnder(db, key, site) {
|
|
791
803
|
if ((0, import_resolution.askResolutionUnder)(db, [[key, site]]) === "abandoned") {
|
|
@@ -805,6 +817,13 @@ function writtenValuesOf(db, key) {
|
|
|
805
817
|
resolveCalls(db, [key]);
|
|
806
818
|
return (0, import_resolution.writtenValuesOf)(db, key, (keys) => resolveCalls(db, keys));
|
|
807
819
|
}
|
|
820
|
+
function settleWrittenValues(db, keys) {
|
|
821
|
+
if (keys.length === 0) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
resolveCalls(db, keys);
|
|
825
|
+
(0, import_resolution.writtenValuesByKey)(db, keys, (behind) => resolveCalls(db, behind));
|
|
826
|
+
}
|
|
808
827
|
function originsOf(db, nameKey2) {
|
|
809
828
|
(0, import_resolution.askResolution)(db, [nameKey2], "wantedOrigin");
|
|
810
829
|
return db.facts("wantedComesFrom").filter((row) => String(row[0]) === nameKey2).map((row) => ({ module: String(row[1]), name: String(row[2]) }));
|
|
@@ -1101,9 +1120,51 @@ function walkExpressions(emitter, node, visit) {
|
|
|
1101
1120
|
walkExpressions(emitter, child, visit);
|
|
1102
1121
|
}
|
|
1103
1122
|
}
|
|
1123
|
+
var WRITTEN_KEY_TYPES = /* @__PURE__ */ new Set(["string", "integer", "concatenated_string"]);
|
|
1124
|
+
function emitKeyedRead(emitter, site, container, key) {
|
|
1125
|
+
if (WRITTEN_KEY_TYPES.has(key.type)) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
add(
|
|
1129
|
+
emitter,
|
|
1130
|
+
"readsKeyed",
|
|
1131
|
+
nodeId(emitter.filePath, site),
|
|
1132
|
+
valueKey(emitter, container),
|
|
1133
|
+
valueKey(emitter, key)
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
function singleSubscript(node) {
|
|
1137
|
+
const written = fields(node, "subscript");
|
|
1138
|
+
return written.length === 1 ? written[0] ?? null : null;
|
|
1139
|
+
}
|
|
1140
|
+
function mappingGetRead(call) {
|
|
1141
|
+
const callee = field(call, "function");
|
|
1142
|
+
if (callee === null || callee.type !== "attribute") {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
const container = field(callee, "object");
|
|
1146
|
+
if (container === null || field(callee, "attribute")?.text !== "get") {
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
const first = callArguments(call).find(
|
|
1150
|
+
(argument) => argument.kind === "positional" && argument.position === 0
|
|
1151
|
+
);
|
|
1152
|
+
return first === void 0 ? null : { container, key: first.node };
|
|
1153
|
+
}
|
|
1104
1154
|
function emitExpressionFact(emitter, child) {
|
|
1105
1155
|
if (child.type === "call") {
|
|
1106
1156
|
emitCall(emitter, child);
|
|
1157
|
+
const mapping = mappingGetRead(child);
|
|
1158
|
+
if (mapping !== null) {
|
|
1159
|
+
emitKeyedRead(emitter, child, mapping.container, mapping.key);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (child.type === "subscript") {
|
|
1163
|
+
const index = singleSubscript(child);
|
|
1164
|
+
const container = field(child, "value");
|
|
1165
|
+
if (index !== null && container !== null) {
|
|
1166
|
+
emitKeyedRead(emitter, child, container, index);
|
|
1167
|
+
}
|
|
1107
1168
|
}
|
|
1108
1169
|
if (child.type === "dictionary") {
|
|
1109
1170
|
emitDictionary(emitter, child);
|
|
@@ -1171,6 +1232,9 @@ function emitFunctionFacts(emitter, fn, classKey) {
|
|
|
1171
1232
|
return funcKey;
|
|
1172
1233
|
}
|
|
1173
1234
|
emitNestedDefinitions(inside, body);
|
|
1235
|
+
if (fn.type === "lambda") {
|
|
1236
|
+
emitExpressionFact(inside, body);
|
|
1237
|
+
}
|
|
1174
1238
|
let statesReturn = false;
|
|
1175
1239
|
const stores = /* @__PURE__ */ new Map();
|
|
1176
1240
|
walkExpressions(inside, body, (child) => {
|
|
@@ -2567,8 +2631,17 @@ function askWrittenValues(nodes, db) {
|
|
|
2567
2631
|
if (bound === void 0) {
|
|
2568
2632
|
return;
|
|
2569
2633
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2634
|
+
settleWrittenValues(db, resolutionKeysOf(nodes, bound));
|
|
2635
|
+
}
|
|
2636
|
+
function resolutionKeysOf(nodes, bound) {
|
|
2637
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2638
|
+
for (const node of nodes) {
|
|
2639
|
+
const key = bound.keyOf(node);
|
|
2640
|
+
if (key !== null) {
|
|
2641
|
+
keys.add(key);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
return [...keys];
|
|
2572
2645
|
}
|
|
2573
2646
|
function evaluatedValue(node, db, site) {
|
|
2574
2647
|
const evaluator = evaluatorFor(node, db);
|
|
@@ -2636,7 +2709,7 @@ function projectOver(db, nodes) {
|
|
|
2636
2709
|
filesByRoot.set(entry.root.id, entry);
|
|
2637
2710
|
rootsByFile.set(entry.file, entry.root);
|
|
2638
2711
|
}
|
|
2639
|
-
const
|
|
2712
|
+
const keyOf3 = (node) => {
|
|
2640
2713
|
const entry = filesByRoot.get(node.tree.rootNode.id);
|
|
2641
2714
|
if (entry === void 0) {
|
|
2642
2715
|
return null;
|
|
@@ -2645,7 +2718,7 @@ function projectOver(db, nodes) {
|
|
|
2645
2718
|
};
|
|
2646
2719
|
const context = {
|
|
2647
2720
|
writtenTo: (node, site) => {
|
|
2648
|
-
const key =
|
|
2721
|
+
const key = keyOf3(node);
|
|
2649
2722
|
if (key === null) {
|
|
2650
2723
|
return null;
|
|
2651
2724
|
}
|
|
@@ -2654,17 +2727,17 @@ function projectOver(db, nodes) {
|
|
|
2654
2727
|
},
|
|
2655
2728
|
callable: (call) => {
|
|
2656
2729
|
const callee = field(call, "function");
|
|
2657
|
-
const key = callee === null ? null :
|
|
2730
|
+
const key = callee === null ? null : keyOf3(callee);
|
|
2658
2731
|
if (key === null) {
|
|
2659
2732
|
return null;
|
|
2660
2733
|
}
|
|
2661
2734
|
resolveCalls(db, [key]);
|
|
2662
|
-
const resolved = db.
|
|
2663
|
-
const settled = resolved.length === 1 ? resolved[0] : void 0;
|
|
2735
|
+
const resolved = db.lookup("wantedResolves", 0, key);
|
|
2736
|
+
const settled = resolved.length === 1 ? String(resolved[0]?.[1]) : void 0;
|
|
2664
2737
|
return settled === void 0 ? null : nodes.definitions.get(settled) ?? null;
|
|
2665
2738
|
}
|
|
2666
2739
|
};
|
|
2667
|
-
return { keyOf:
|
|
2740
|
+
return { keyOf: keyOf3, roots: rootsByFile, context };
|
|
2668
2741
|
}
|
|
2669
2742
|
|
|
2670
2743
|
// src/decorators.ts
|
|
@@ -2879,7 +2952,7 @@ function passesParametersThrough(def, inner) {
|
|
|
2879
2952
|
// src/discovery.ts
|
|
2880
2953
|
var import_behavioral_ir4 = require("@suss/behavioral-ir");
|
|
2881
2954
|
var import_extractor5 = require("@suss/extractor");
|
|
2882
|
-
var
|
|
2955
|
+
var import_values13 = require("@suss/values");
|
|
2883
2956
|
|
|
2884
2957
|
// src/clientCalls.ts
|
|
2885
2958
|
var import_behavioral_ir2 = require("@suss/behavioral-ir");
|
|
@@ -3292,6 +3365,18 @@ function bodyCalls(node, found = []) {
|
|
|
3292
3365
|
}
|
|
3293
3366
|
return found;
|
|
3294
3367
|
}
|
|
3368
|
+
function moduleLoadCalls(node, found = []) {
|
|
3369
|
+
for (const child of node.namedChildren) {
|
|
3370
|
+
if (child === null || !runsAtModuleLoad(child)) {
|
|
3371
|
+
continue;
|
|
3372
|
+
}
|
|
3373
|
+
if (child.type === "call") {
|
|
3374
|
+
found.push(child);
|
|
3375
|
+
}
|
|
3376
|
+
moduleLoadCalls(child, found);
|
|
3377
|
+
}
|
|
3378
|
+
return found;
|
|
3379
|
+
}
|
|
3295
3380
|
function enclosingStatement(call, body) {
|
|
3296
3381
|
let current = call;
|
|
3297
3382
|
while (current !== null && current.parent !== null) {
|
|
@@ -3316,15 +3401,18 @@ function argOf(node, facts) {
|
|
|
3316
3401
|
}
|
|
3317
3402
|
return { kind: "identifier", name: node.text };
|
|
3318
3403
|
}
|
|
3319
|
-
function
|
|
3404
|
+
function argumentNodes(call) {
|
|
3320
3405
|
const args = field(call, "arguments");
|
|
3321
3406
|
if (args === null) {
|
|
3322
3407
|
return [];
|
|
3323
3408
|
}
|
|
3324
3409
|
return args.namedChildren.filter((child) => child !== null).map(
|
|
3325
|
-
(child) => child.type === "keyword_argument" ?
|
|
3410
|
+
(child) => child.type === "keyword_argument" ? field(child, "value") ?? child : child
|
|
3326
3411
|
);
|
|
3327
3412
|
}
|
|
3413
|
+
function argsOf(call, facts) {
|
|
3414
|
+
return argumentNodes(call).map((node) => argOf(node, facts));
|
|
3415
|
+
}
|
|
3328
3416
|
function calleeText(call) {
|
|
3329
3417
|
return field(call, "function")?.text ?? call.text;
|
|
3330
3418
|
}
|
|
@@ -3333,7 +3421,40 @@ function invocationEffects(definitionNode, facts) {
|
|
|
3333
3421
|
if (body === null) {
|
|
3334
3422
|
return [];
|
|
3335
3423
|
}
|
|
3336
|
-
|
|
3424
|
+
return invocationEffectsIn(body, bodyCalls(body), facts);
|
|
3425
|
+
}
|
|
3426
|
+
function moduleLoadInvocationEffects(moduleNode, facts) {
|
|
3427
|
+
return invocationEffectsIn(moduleNode, moduleLoadCalls(moduleNode), facts);
|
|
3428
|
+
}
|
|
3429
|
+
var ASKED_ABOUT_TYPES = /* @__PURE__ */ new Set(["identifier", "attribute", "call"]);
|
|
3430
|
+
function askedNodesUnder(node, found = []) {
|
|
3431
|
+
if (ASKED_ABOUT_TYPES.has(node.type)) {
|
|
3432
|
+
found.push(node);
|
|
3433
|
+
}
|
|
3434
|
+
for (const child of node.namedChildren) {
|
|
3435
|
+
if (child !== null && !NESTED_DEFINITION_TYPES.has(child.type)) {
|
|
3436
|
+
askedNodesUnder(child, found);
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
return found;
|
|
3440
|
+
}
|
|
3441
|
+
function bodyValueNodes(definitionNode) {
|
|
3442
|
+
const body = field(definitionNode, "body");
|
|
3443
|
+
return body === null ? [] : askedNodesUnder(body);
|
|
3444
|
+
}
|
|
3445
|
+
function effectValueNodes(call, gating) {
|
|
3446
|
+
const found = argumentNodes(call).flatMap((node) => askedNodesUnder(node));
|
|
3447
|
+
for (const path6 of gating ?? []) {
|
|
3448
|
+
for (const condition of path6) {
|
|
3449
|
+
if (condition.expression !== null) {
|
|
3450
|
+
askedNodesUnder(condition.expression, found);
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
return found;
|
|
3455
|
+
}
|
|
3456
|
+
function invocationEffectsIn(body, written, facts) {
|
|
3457
|
+
const calls = [...written].sort((a, b) => a.endIndex - b.endIndex);
|
|
3337
3458
|
if (calls.length === 0) {
|
|
3338
3459
|
return [];
|
|
3339
3460
|
}
|
|
@@ -3355,10 +3476,17 @@ function invocationEffects(definitionNode, facts) {
|
|
|
3355
3476
|
},
|
|
3356
3477
|
statements
|
|
3357
3478
|
);
|
|
3358
|
-
|
|
3479
|
+
const gatingOf = calls.map((call) => {
|
|
3359
3480
|
const statement = statementOf3.get(call.id);
|
|
3481
|
+
return statement === void 0 ? void 0 : enumerated.byTerminal.get(statement);
|
|
3482
|
+
});
|
|
3483
|
+
askWrittenValues(
|
|
3484
|
+
calls.flatMap((call, index) => effectValueNodes(call, gatingOf[index])),
|
|
3485
|
+
facts
|
|
3486
|
+
);
|
|
3487
|
+
return calls.map((call, index) => {
|
|
3360
3488
|
const conditions = (0, import_extractor3.sharedGatingConditions)(
|
|
3361
|
-
|
|
3489
|
+
gatingOf[index],
|
|
3362
3490
|
(condition) => predicateOf(condition, facts)
|
|
3363
3491
|
);
|
|
3364
3492
|
return {
|
|
@@ -3389,6 +3517,22 @@ function clientCallUnits(root, module2, pack, pattern, options) {
|
|
|
3389
3517
|
}
|
|
3390
3518
|
return units;
|
|
3391
3519
|
}
|
|
3520
|
+
function clientCallReceivers(root, module2) {
|
|
3521
|
+
const found = [];
|
|
3522
|
+
for (const definition of functionDefinitions(root)) {
|
|
3523
|
+
for (const call of bodyCalls(definition)) {
|
|
3524
|
+
const callee = field(call, "function");
|
|
3525
|
+
if (callee === null || originOf(callee, module2) !== null) {
|
|
3526
|
+
continue;
|
|
3527
|
+
}
|
|
3528
|
+
const object = field(callee, "object");
|
|
3529
|
+
if (object !== null && field(callee, "attribute") !== null) {
|
|
3530
|
+
found.push(object);
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
return found;
|
|
3535
|
+
}
|
|
3392
3536
|
function functionDefinitions(node, found = []) {
|
|
3393
3537
|
for (const child of children(node)) {
|
|
3394
3538
|
if (isFunction(child)) {
|
|
@@ -3751,44 +3895,91 @@ function isDefaultedAt(node) {
|
|
|
3751
3895
|
}
|
|
3752
3896
|
return false;
|
|
3753
3897
|
}
|
|
3754
|
-
function
|
|
3755
|
-
const
|
|
3898
|
+
function envFactsIn(filePath, root, module2) {
|
|
3899
|
+
const found = { sites: [], objects: [] };
|
|
3756
3900
|
(0, import_extractor4.walkDescendants)(root, module2.moduleScope, {
|
|
3757
3901
|
at: (node, scope) => {
|
|
3902
|
+
if (isEnviron(node, scope) && handsOnward(node)) {
|
|
3903
|
+
found.objects.push(keyOf(filePath, node));
|
|
3904
|
+
}
|
|
3758
3905
|
const syntax = envReadSyntaxAt(node, scope);
|
|
3759
3906
|
if (syntax === null || stringLiteralValue(syntax.name) !== null) {
|
|
3760
3907
|
return;
|
|
3761
3908
|
}
|
|
3762
|
-
sites.push({
|
|
3909
|
+
found.sites.push({
|
|
3763
3910
|
site: nodeId(filePath, node),
|
|
3764
|
-
nameKey:
|
|
3765
|
-
defaulted: syntax.defaulted
|
|
3911
|
+
nameKey: keyOf(filePath, syntax.name),
|
|
3912
|
+
defaulted: syntax.defaulted,
|
|
3913
|
+
functionKey: functionReadKey(filePath, node, scope)
|
|
3766
3914
|
});
|
|
3767
3915
|
},
|
|
3768
3916
|
into: (node, scope) => module2.scopeFor.get(node.id) ?? scope
|
|
3769
3917
|
});
|
|
3770
|
-
return
|
|
3918
|
+
return found;
|
|
3919
|
+
}
|
|
3920
|
+
var keyOf = (filePath, node) => readKey(filePath, node, enclosingFunction(node));
|
|
3921
|
+
function functionReadKey(filePath, node, scope) {
|
|
3922
|
+
if (node.type !== "call") {
|
|
3923
|
+
return null;
|
|
3924
|
+
}
|
|
3925
|
+
const callee = field(node, "function");
|
|
3926
|
+
if (callee === null || isEnviron(field(callee, "object") ?? callee, scope)) {
|
|
3927
|
+
return null;
|
|
3928
|
+
}
|
|
3929
|
+
return keyOf(filePath, callee);
|
|
3930
|
+
}
|
|
3931
|
+
function handsOnward(node) {
|
|
3932
|
+
const parent = node.parent;
|
|
3933
|
+
if (parent === null) {
|
|
3934
|
+
return true;
|
|
3935
|
+
}
|
|
3936
|
+
if (parent.type === "subscript" && field(parent, "value")?.id === node.id) {
|
|
3937
|
+
return !writesTheKey(field(parent, "subscript"));
|
|
3938
|
+
}
|
|
3939
|
+
if (parent.type === "attribute" && field(parent, "object")?.id === node.id) {
|
|
3940
|
+
const call = parent.parent;
|
|
3941
|
+
return field(parent, "attribute")?.text === "get" && call !== null && call.type === "call" && !writesTheKey(firstArgumentOf(call));
|
|
3942
|
+
}
|
|
3943
|
+
return true;
|
|
3944
|
+
}
|
|
3945
|
+
var writesTheKey = (key) => key !== null && stringLiteralValue(key) !== null;
|
|
3946
|
+
function firstArgumentOf(call) {
|
|
3947
|
+
const first = callArguments(call).find(
|
|
3948
|
+
(argument) => argument.kind === "positional" && argument.position === 0
|
|
3949
|
+
);
|
|
3950
|
+
return first?.node ?? null;
|
|
3771
3951
|
}
|
|
3772
3952
|
var sitesByDb = /* @__PURE__ */ new WeakMap();
|
|
3773
|
-
function
|
|
3774
|
-
|
|
3953
|
+
function bindEnvFacts(db, found) {
|
|
3954
|
+
const sites = found.flatMap((one) => one.sites);
|
|
3955
|
+
const objects = found.flatMap((one) => one.objects);
|
|
3956
|
+
if (sites.length === 0 && objects.length === 0) {
|
|
3775
3957
|
return;
|
|
3776
3958
|
}
|
|
3777
3959
|
let index = sitesByDb.get(db);
|
|
3778
3960
|
if (index === void 0) {
|
|
3779
|
-
index = { byId: /* @__PURE__ */ new Map(), sitesByParameter: null };
|
|
3961
|
+
index = { byId: /* @__PURE__ */ new Map(), objects: /* @__PURE__ */ new Set(), sitesByParameter: null };
|
|
3780
3962
|
sitesByDb.set(db, index);
|
|
3781
3963
|
}
|
|
3964
|
+
for (const object of objects) {
|
|
3965
|
+
db.add("environmentObject", [object]);
|
|
3966
|
+
index.objects.add(object);
|
|
3967
|
+
}
|
|
3782
3968
|
for (const site of sites) {
|
|
3783
|
-
db.add("readsEnvNamed", [site.site, site.nameKey]);
|
|
3784
3969
|
index.byId.set(site.site, site);
|
|
3970
|
+
if (site.functionKey === null) {
|
|
3971
|
+
continue;
|
|
3972
|
+
}
|
|
3973
|
+
db.add("environmentObject", [site.functionKey]);
|
|
3974
|
+
db.add("readsKeyed", [site.site, site.functionKey, site.nameKey]);
|
|
3975
|
+
index.objects.add(site.functionKey);
|
|
3785
3976
|
}
|
|
3786
3977
|
}
|
|
3787
3978
|
function sitesEachParameterNames(db, index) {
|
|
3788
3979
|
if (index.sitesByParameter !== null) {
|
|
3789
3980
|
return index.sitesByParameter;
|
|
3790
3981
|
}
|
|
3791
|
-
|
|
3982
|
+
resolveEnvObjects(db, [...index.objects]);
|
|
3792
3983
|
const found = /* @__PURE__ */ new Map();
|
|
3793
3984
|
for (const row of db.facts("wantedParamNamesEnv")) {
|
|
3794
3985
|
const parameter = String(row[0]);
|
|
@@ -3852,8 +4043,7 @@ function argumentsByParameter(db, call, calleeKey) {
|
|
|
3852
4043
|
positional.set(String(argument.position), argument.node);
|
|
3853
4044
|
}
|
|
3854
4045
|
const argumentAt2 = /* @__PURE__ */ new Map();
|
|
3855
|
-
for (const
|
|
3856
|
-
const callee = String(resolved[1]);
|
|
4046
|
+
for (const callee of resolvedFunctions(db, calleeKey)) {
|
|
3857
4047
|
for (const row of db.lookup("paramOf", 0, callee)) {
|
|
3858
4048
|
const at = positional.get(String(row[1]));
|
|
3859
4049
|
if (at !== void 0) {
|
|
@@ -3881,10 +4071,8 @@ function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
|
3881
4071
|
continue;
|
|
3882
4072
|
}
|
|
3883
4073
|
for (const id of sites) {
|
|
3884
|
-
const
|
|
3885
|
-
|
|
3886
|
-
reads.set(name, (reads.get(name) ?? true) && site.defaulted);
|
|
3887
|
-
}
|
|
4074
|
+
const defaulted = siteById.get(id)?.defaulted ?? false;
|
|
4075
|
+
reads.set(name, (reads.get(name) ?? true) && defaulted);
|
|
3888
4076
|
}
|
|
3889
4077
|
}
|
|
3890
4078
|
if (reads.size === 0) {
|
|
@@ -4104,71 +4292,301 @@ function returnedBodyShape(statement) {
|
|
|
4104
4292
|
// src/rawSql.ts
|
|
4105
4293
|
var import_ir_core = require("@suss/ir-core");
|
|
4106
4294
|
var import_sql = require("@suss/sql");
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4295
|
+
var import_values11 = require("@suss/values");
|
|
4296
|
+
|
|
4297
|
+
// src/receiverTypes.ts
|
|
4298
|
+
var UNDECLARED_MODULE = "builtins";
|
|
4299
|
+
function annotationTarget(annotation) {
|
|
4300
|
+
if (annotation.type === "type" && annotation.namedChildren[0]) {
|
|
4301
|
+
return annotationTarget(annotation.namedChildren[0]);
|
|
4110
4302
|
}
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4303
|
+
if (annotation.type === "binary_operator") {
|
|
4304
|
+
const named = [field(annotation, "left"), field(annotation, "right")].find(
|
|
4305
|
+
(side) => side !== null && side.type !== "none"
|
|
4306
|
+
);
|
|
4307
|
+
return named === void 0 || named === null ? null : annotationTarget(named);
|
|
4308
|
+
}
|
|
4309
|
+
if (annotation.type === "generic_type") {
|
|
4310
|
+
const outer = annotation.namedChildren[0];
|
|
4311
|
+
const first = genericTypeArgs(annotation)[0];
|
|
4312
|
+
if ((outer?.text === "Annotated" || outer?.text === "Optional") && first !== void 0) {
|
|
4313
|
+
return annotationTarget(first);
|
|
4116
4314
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
4315
|
+
return outer ?? null;
|
|
4316
|
+
}
|
|
4317
|
+
return annotation;
|
|
4318
|
+
}
|
|
4319
|
+
function typeNameOf(annotation) {
|
|
4320
|
+
const target = annotationTarget(annotation);
|
|
4321
|
+
if (target === null) {
|
|
4322
|
+
return null;
|
|
4323
|
+
}
|
|
4324
|
+
return target.type === "identifier" ? target.text : stringLiteralValue(target);
|
|
4325
|
+
}
|
|
4326
|
+
function firstInBody(node, read) {
|
|
4327
|
+
const here = read(node);
|
|
4328
|
+
if (here !== null) {
|
|
4329
|
+
return here;
|
|
4330
|
+
}
|
|
4331
|
+
for (const child of children(node)) {
|
|
4332
|
+
if (child.type === "function_definition" || child.type === "lambda") {
|
|
4119
4333
|
continue;
|
|
4120
4334
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
effects.push({
|
|
4125
|
-
type: "interaction",
|
|
4126
|
-
binding: (0, import_ir_core.storageBinding)({
|
|
4127
|
-
recognition: `python-${pattern.module}`,
|
|
4128
|
-
storageSystem: pattern.storageSystem,
|
|
4129
|
-
scope: "default",
|
|
4130
|
-
container: access.table
|
|
4131
|
-
}),
|
|
4132
|
-
callee: field(call, "function")?.text ?? "",
|
|
4133
|
-
interaction: {
|
|
4134
|
-
class: "storage-access",
|
|
4135
|
-
kind: access.kind,
|
|
4136
|
-
fields: access.fields,
|
|
4137
|
-
...access.selector.length > 0 ? { selector: access.selector } : {},
|
|
4138
|
-
operation: field(call, "function")?.text ?? ""
|
|
4139
|
-
}
|
|
4140
|
-
});
|
|
4335
|
+
const found = firstInBody(child, read);
|
|
4336
|
+
if (found !== null) {
|
|
4337
|
+
return found;
|
|
4141
4338
|
}
|
|
4142
4339
|
}
|
|
4143
|
-
return
|
|
4340
|
+
return null;
|
|
4341
|
+
}
|
|
4342
|
+
function statedBy(statement, name) {
|
|
4343
|
+
if (statement.type === "assignment") {
|
|
4344
|
+
const annotation = field(statement, "type");
|
|
4345
|
+
return field(statement, "left")?.text === name ? annotation : null;
|
|
4346
|
+
}
|
|
4347
|
+
if (statement.type === "as_pattern") {
|
|
4348
|
+
const alias = field(statement, "alias");
|
|
4349
|
+
const value = statement.namedChildren[0] ?? null;
|
|
4350
|
+
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
4351
|
+
return alias?.text === name ? callee : null;
|
|
4352
|
+
}
|
|
4353
|
+
return null;
|
|
4354
|
+
}
|
|
4355
|
+
function statedTypeNode(name, from) {
|
|
4356
|
+
const fn = enclosingFunction(from);
|
|
4357
|
+
if (fn === null) {
|
|
4358
|
+
return null;
|
|
4359
|
+
}
|
|
4360
|
+
const params = field(fn, "parameters");
|
|
4361
|
+
for (const param of params === null ? [] : children(params)) {
|
|
4362
|
+
const info = parameterNameAndType(param);
|
|
4363
|
+
if (info?.name === name && info.typeNode !== null) {
|
|
4364
|
+
return info.typeNode;
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
const body = field(fn, "body");
|
|
4368
|
+
return body === null ? null : firstInBody(body, (statement) => statedBy(statement, name));
|
|
4369
|
+
}
|
|
4370
|
+
function statedTypeName(name, from) {
|
|
4371
|
+
const stated = statedTypeNode(name, from);
|
|
4372
|
+
return stated === null ? null : typeNameOf(stated);
|
|
4373
|
+
}
|
|
4374
|
+
function statedOrigins(stated, options) {
|
|
4375
|
+
const name = typeNameOf(stated);
|
|
4376
|
+
const byRule = name === null ? [] : originsOf(options.facts, `${options.filePath}#${name}`);
|
|
4377
|
+
const target = annotationTarget(stated);
|
|
4378
|
+
const imported = target === null ? null : originOf(target, moduleOf(target));
|
|
4379
|
+
if (imported === null || imported.module === UNDECLARED_MODULE) {
|
|
4380
|
+
return byRule;
|
|
4381
|
+
}
|
|
4382
|
+
return [...byRule, imported];
|
|
4383
|
+
}
|
|
4384
|
+
function receiverTypeOrigins(receiver, options) {
|
|
4385
|
+
const stated = statedTypeNode(receiver.text, receiver);
|
|
4386
|
+
if (stated !== null) {
|
|
4387
|
+
return statedOrigins(stated, options);
|
|
4388
|
+
}
|
|
4389
|
+
const built = constructionBehind(receiver, options.facts);
|
|
4390
|
+
if (built.type === "oneCall") {
|
|
4391
|
+
return [built.construction.origin];
|
|
4392
|
+
}
|
|
4393
|
+
const key = nameKeyIn(
|
|
4394
|
+
options.filePath,
|
|
4395
|
+
enclosingFunction(receiver),
|
|
4396
|
+
receiver.text
|
|
4397
|
+
);
|
|
4398
|
+
return subjectConstructions(options.facts, [key]).get(key)?.origins ?? [];
|
|
4399
|
+
}
|
|
4400
|
+
|
|
4401
|
+
// src/rawSql.ts
|
|
4402
|
+
function rawSqlEffects(calls, options) {
|
|
4403
|
+
return matchesIn(calls, options).flatMap(
|
|
4404
|
+
(match) => match.accesses.flatMap((access) => effectFor(match, access))
|
|
4405
|
+
);
|
|
4406
|
+
}
|
|
4407
|
+
function rawSqlCallIds(calls, options) {
|
|
4408
|
+
return new Set(matchesIn(calls, options).map((match) => match.call.id));
|
|
4409
|
+
}
|
|
4410
|
+
function matchesIn(calls, options) {
|
|
4411
|
+
if (options.patterns.length === 0 && (options.clients ?? []).length === 0) {
|
|
4412
|
+
return [];
|
|
4413
|
+
}
|
|
4414
|
+
const matched = [];
|
|
4415
|
+
for (const call of calls) {
|
|
4416
|
+
const one = importedFunctionMatch(call, options) ?? clientMatch(call, options);
|
|
4417
|
+
if (one !== null) {
|
|
4418
|
+
matched.push(one);
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
return matched;
|
|
4422
|
+
}
|
|
4423
|
+
function effectFor(match, access) {
|
|
4424
|
+
const operation = field(match.call, "function")?.text ?? "";
|
|
4425
|
+
return [
|
|
4426
|
+
{
|
|
4427
|
+
type: "interaction",
|
|
4428
|
+
binding: (0, import_ir_core.storageBinding)({
|
|
4429
|
+
recognition: match.recognition,
|
|
4430
|
+
storageSystem: match.storageSystem,
|
|
4431
|
+
scope: access.qualifier[access.qualifier.length - 1] ?? NO_GROUP,
|
|
4432
|
+
container: access.table
|
|
4433
|
+
}),
|
|
4434
|
+
callee: operation,
|
|
4435
|
+
interaction: {
|
|
4436
|
+
class: "storage-access",
|
|
4437
|
+
kind: access.kind,
|
|
4438
|
+
fields: access.fields,
|
|
4439
|
+
...access.selector.length > 0 ? { selector: access.selector } : {},
|
|
4440
|
+
operation
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
];
|
|
4144
4444
|
}
|
|
4145
|
-
|
|
4445
|
+
var NO_GROUP = "default";
|
|
4446
|
+
function importedFunctionMatch(call, options) {
|
|
4146
4447
|
const callee = field(call, "function");
|
|
4147
4448
|
if (callee === null || callee.type !== "identifier") {
|
|
4148
|
-
return
|
|
4449
|
+
return null;
|
|
4149
4450
|
}
|
|
4150
4451
|
const from = options.facts.facts("pyImportedName").find((row) => String(row[0]) === `${options.filePath}#${callee.text}`);
|
|
4151
4452
|
if (from === void 0) {
|
|
4152
|
-
return
|
|
4453
|
+
return null;
|
|
4153
4454
|
}
|
|
4154
4455
|
const module2 = String(from[1]);
|
|
4155
|
-
|
|
4156
|
-
(
|
|
4456
|
+
const pattern = options.patterns.find(
|
|
4457
|
+
(candidate) => candidate.module === module2 && candidate.functions.includes(callee.text)
|
|
4157
4458
|
);
|
|
4158
|
-
|
|
4159
|
-
|
|
4459
|
+
if (pattern === void 0) {
|
|
4460
|
+
return null;
|
|
4461
|
+
}
|
|
4160
4462
|
const args = field(call, "arguments");
|
|
4161
4463
|
const first = args?.namedChildren.find((child) => child !== null) ?? null;
|
|
4162
|
-
|
|
4464
|
+
const statement = first === null ? null : statementAt(first, void 0, options.facts);
|
|
4465
|
+
if (statement === null) {
|
|
4466
|
+
return null;
|
|
4467
|
+
}
|
|
4468
|
+
return {
|
|
4469
|
+
call,
|
|
4470
|
+
recognition: `python-${pattern.module}`,
|
|
4471
|
+
storageSystem: pattern.storageSystem,
|
|
4472
|
+
accesses: (0, import_sql.readSqlAccess)(statement, { dialect: pattern.storageSystem })
|
|
4473
|
+
};
|
|
4474
|
+
}
|
|
4475
|
+
function clientMatch(call, options) {
|
|
4476
|
+
const callee = field(call, "function");
|
|
4477
|
+
if (callee === null || callee.type !== "attribute") {
|
|
4478
|
+
return null;
|
|
4479
|
+
}
|
|
4480
|
+
const method = field(callee, "attribute")?.text ?? "";
|
|
4481
|
+
const receiver = field(callee, "object");
|
|
4482
|
+
if (receiver === null) {
|
|
4163
4483
|
return null;
|
|
4164
4484
|
}
|
|
4165
|
-
const
|
|
4485
|
+
for (const pattern of options.clients ?? []) {
|
|
4486
|
+
const accesses = accessesOf(call, method, pattern, options);
|
|
4487
|
+
if (accesses === null || !isClientOf(receiver, pattern, options)) {
|
|
4488
|
+
continue;
|
|
4489
|
+
}
|
|
4490
|
+
return {
|
|
4491
|
+
call,
|
|
4492
|
+
recognition: `python-${pattern.module}`,
|
|
4493
|
+
storageSystem: pattern.storageSystem,
|
|
4494
|
+
accesses
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
4497
|
+
return null;
|
|
4498
|
+
}
|
|
4499
|
+
function accessesOf(call, method, pattern, options) {
|
|
4500
|
+
const dialect = pattern.dialect ?? pattern.storageSystem;
|
|
4501
|
+
for (const takes of pattern.statements ?? []) {
|
|
4502
|
+
if (takes.method !== method) {
|
|
4503
|
+
continue;
|
|
4504
|
+
}
|
|
4505
|
+
const written = argumentNode(call, takes);
|
|
4506
|
+
const statement = written === null ? null : statementAt(written, takes.path, options.facts);
|
|
4507
|
+
return statement === null ? [] : (0, import_sql.readSqlAccess)(statement, { dialect });
|
|
4508
|
+
}
|
|
4509
|
+
for (const takes of pattern.tables ?? []) {
|
|
4510
|
+
if (takes.method !== method) {
|
|
4511
|
+
continue;
|
|
4512
|
+
}
|
|
4513
|
+
const written = argumentNode(call, takes);
|
|
4514
|
+
const name = written === null ? null : stringValueOf(written, options.facts);
|
|
4515
|
+
const split = name === null ? null : (0, import_sql.splitQualifiedTable)(name);
|
|
4516
|
+
return split === null ? [] : [{ ...split, kind: takes.kind, fields: [], selector: [] }];
|
|
4517
|
+
}
|
|
4518
|
+
return null;
|
|
4519
|
+
}
|
|
4520
|
+
function isClientOf(receiver, pattern, options) {
|
|
4521
|
+
return receiverOrigins(receiver, options).some(
|
|
4522
|
+
(origin) => origin.module === pattern.module && pattern.clientTypes.includes(origin.name)
|
|
4523
|
+
);
|
|
4524
|
+
}
|
|
4525
|
+
function receiverOrigins(receiver, options) {
|
|
4526
|
+
if (receiver.type === "identifier") {
|
|
4527
|
+
return receiverTypeOrigins(receiver, options);
|
|
4528
|
+
}
|
|
4529
|
+
return receiver.type === "call" ? handedBack(receiver, options) : [];
|
|
4530
|
+
}
|
|
4531
|
+
function handedBack(call, options) {
|
|
4532
|
+
const callee = field(call, "function");
|
|
4533
|
+
if (callee === null || callee.type !== "attribute") {
|
|
4534
|
+
return [];
|
|
4535
|
+
}
|
|
4536
|
+
const method = field(callee, "attribute")?.text ?? "";
|
|
4537
|
+
const inner = field(callee, "object");
|
|
4538
|
+
if (inner === null) {
|
|
4539
|
+
return [];
|
|
4540
|
+
}
|
|
4541
|
+
const found = [];
|
|
4542
|
+
for (const pattern of options.clients ?? []) {
|
|
4543
|
+
const handoff = (pattern.handsBack ?? []).find(
|
|
4544
|
+
(one) => one.method === method
|
|
4545
|
+
);
|
|
4546
|
+
if (handoff !== void 0 && isClientOf(inner, pattern, options)) {
|
|
4547
|
+
found.push({ module: handoff.module, name: handoff.name });
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
return found;
|
|
4551
|
+
}
|
|
4552
|
+
function argumentNode(call, at) {
|
|
4553
|
+
const args = field(call, "arguments");
|
|
4554
|
+
const written = args === null ? [] : children(args);
|
|
4555
|
+
const named = written.find(
|
|
4556
|
+
(one) => one.type === "keyword_argument" && at.keyword !== void 0 && field(one, "name")?.text === at.keyword
|
|
4557
|
+
);
|
|
4558
|
+
const value = named === void 0 ? null : field(named, "value");
|
|
4559
|
+
if (value !== null) {
|
|
4560
|
+
return value;
|
|
4561
|
+
}
|
|
4562
|
+
if (at.argument === void 0) {
|
|
4563
|
+
return null;
|
|
4564
|
+
}
|
|
4565
|
+
return written.filter((one) => one.type !== "keyword_argument")[at.argument] ?? null;
|
|
4566
|
+
}
|
|
4567
|
+
function statementAt(node, path6, facts) {
|
|
4568
|
+
const reached = valueAt(evaluatedValue(node, facts), path6 ?? []);
|
|
4569
|
+
const parts = reached === null ? null : literalParts(reached);
|
|
4166
4570
|
if (parts === null) {
|
|
4167
4571
|
return null;
|
|
4168
4572
|
}
|
|
4169
4573
|
const statement = (0, import_sql.sqlFromParts)(parts);
|
|
4170
4574
|
return statement.trim() === "" ? null : statement;
|
|
4171
4575
|
}
|
|
4576
|
+
function valueAt(value, path6) {
|
|
4577
|
+
let reached = value;
|
|
4578
|
+
for (const key of path6) {
|
|
4579
|
+
if (reached.kind !== "record") {
|
|
4580
|
+
return null;
|
|
4581
|
+
}
|
|
4582
|
+
const item = reached.fields.get(key);
|
|
4583
|
+
if (item === void 0) {
|
|
4584
|
+
return null;
|
|
4585
|
+
}
|
|
4586
|
+
reached = (0, import_values11.force)(item.value);
|
|
4587
|
+
}
|
|
4588
|
+
return reached;
|
|
4589
|
+
}
|
|
4172
4590
|
function literalParts(value) {
|
|
4173
4591
|
if (value.kind !== "string") {
|
|
4174
4592
|
return null;
|
|
@@ -4266,78 +4684,7 @@ function receiverName(chain) {
|
|
|
4266
4684
|
return null;
|
|
4267
4685
|
}
|
|
4268
4686
|
const object = field(callee, "object");
|
|
4269
|
-
return object !== null && object.type === "identifier" ? object
|
|
4270
|
-
}
|
|
4271
|
-
function typeNameOf(annotation) {
|
|
4272
|
-
if (annotation.type === "type" && annotation.namedChildren[0]) {
|
|
4273
|
-
return typeNameOf(annotation.namedChildren[0]);
|
|
4274
|
-
}
|
|
4275
|
-
if (annotation.type === "identifier") {
|
|
4276
|
-
return annotation.text;
|
|
4277
|
-
}
|
|
4278
|
-
const quoted = stringLiteralValue(annotation);
|
|
4279
|
-
if (quoted !== null) {
|
|
4280
|
-
return quoted;
|
|
4281
|
-
}
|
|
4282
|
-
if (annotation.type === "binary_operator") {
|
|
4283
|
-
const named = [field(annotation, "left"), field(annotation, "right")].find(
|
|
4284
|
-
(side) => side !== null && side.type !== "none"
|
|
4285
|
-
);
|
|
4286
|
-
return named === void 0 || named === null ? null : typeNameOf(named);
|
|
4287
|
-
}
|
|
4288
|
-
if (annotation.type === "generic_type") {
|
|
4289
|
-
const outer = annotation.namedChildren[0];
|
|
4290
|
-
const first = genericTypeArgs(annotation)[0];
|
|
4291
|
-
if ((outer?.text === "Annotated" || outer?.text === "Optional") && first !== void 0) {
|
|
4292
|
-
return typeNameOf(first);
|
|
4293
|
-
}
|
|
4294
|
-
return outer?.type === "identifier" ? outer.text : null;
|
|
4295
|
-
}
|
|
4296
|
-
return null;
|
|
4297
|
-
}
|
|
4298
|
-
function statedTypeName(name, from) {
|
|
4299
|
-
const fn = enclosingFunction(from);
|
|
4300
|
-
if (fn === null) {
|
|
4301
|
-
return null;
|
|
4302
|
-
}
|
|
4303
|
-
const params = field(fn, "parameters");
|
|
4304
|
-
for (const param of params === null ? [] : children(params)) {
|
|
4305
|
-
const info = parameterNameAndType(param);
|
|
4306
|
-
if (info?.name === name && info.typeNode !== null) {
|
|
4307
|
-
return typeNameOf(info.typeNode);
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
const body = field(fn, "body");
|
|
4311
|
-
return body === null ? null : firstInBody(body, (statement) => statedBy(statement, name));
|
|
4312
|
-
}
|
|
4313
|
-
function firstInBody(node, read) {
|
|
4314
|
-
const here = read(node);
|
|
4315
|
-
if (here !== null) {
|
|
4316
|
-
return here;
|
|
4317
|
-
}
|
|
4318
|
-
for (const child of children(node)) {
|
|
4319
|
-
if (child.type === "function_definition" || child.type === "lambda") {
|
|
4320
|
-
continue;
|
|
4321
|
-
}
|
|
4322
|
-
const found = firstInBody(child, read);
|
|
4323
|
-
if (found !== null) {
|
|
4324
|
-
return found;
|
|
4325
|
-
}
|
|
4326
|
-
}
|
|
4327
|
-
return null;
|
|
4328
|
-
}
|
|
4329
|
-
function statedBy(statement, name) {
|
|
4330
|
-
if (statement.type === "assignment") {
|
|
4331
|
-
const annotation = field(statement, "type");
|
|
4332
|
-
return field(statement, "left")?.text === name && annotation !== null ? typeNameOf(annotation) : null;
|
|
4333
|
-
}
|
|
4334
|
-
if (statement.type === "as_pattern") {
|
|
4335
|
-
const alias = field(statement, "alias");
|
|
4336
|
-
const value = statement.namedChildren[0] ?? null;
|
|
4337
|
-
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
4338
|
-
return alias?.text === name && callee?.type === "identifier" ? callee.text : null;
|
|
4339
|
-
}
|
|
4340
|
-
return null;
|
|
4687
|
+
return object !== null && object.type === "identifier" ? object : null;
|
|
4341
4688
|
}
|
|
4342
4689
|
function builtType(call, options) {
|
|
4343
4690
|
const root = rootOf(call);
|
|
@@ -4385,7 +4732,7 @@ function typedReceiverPattern(options, chain) {
|
|
|
4385
4732
|
if (receiver === null) {
|
|
4386
4733
|
return void 0;
|
|
4387
4734
|
}
|
|
4388
|
-
for (const origin of receiverTypeOrigins(
|
|
4735
|
+
for (const origin of receiverTypeOrigins(receiver, options)) {
|
|
4389
4736
|
const pattern = queryTypePattern(options, origin.module, origin.name);
|
|
4390
4737
|
if (pattern !== void 0) {
|
|
4391
4738
|
return pattern;
|
|
@@ -4393,14 +4740,6 @@ function typedReceiverPattern(options, chain) {
|
|
|
4393
4740
|
}
|
|
4394
4741
|
return void 0;
|
|
4395
4742
|
}
|
|
4396
|
-
function receiverTypeOrigins(options, name, from) {
|
|
4397
|
-
const stated = statedTypeName(name, from);
|
|
4398
|
-
if (stated !== null) {
|
|
4399
|
-
return originsOf(options.facts, `${options.filePath}#${stated}`);
|
|
4400
|
-
}
|
|
4401
|
-
const key = nameKeyIn(options.filePath, enclosingFunction(from), name);
|
|
4402
|
-
return subjectConstructions(options.facts, [key]).get(key)?.origins ?? [];
|
|
4403
|
-
}
|
|
4404
4743
|
function queryTypePattern(options, module2, name) {
|
|
4405
4744
|
return options.patterns.find(
|
|
4406
4745
|
(pattern) => module2 === pattern.module && pattern.queryTypes.includes(name)
|
|
@@ -4522,7 +4861,7 @@ function classBehind(typeName, options) {
|
|
|
4522
4861
|
function isClassName(name) {
|
|
4523
4862
|
return /^[A-Z][A-Za-z0-9_]*$/.test(name) && name !== name.toUpperCase();
|
|
4524
4863
|
}
|
|
4525
|
-
function
|
|
4864
|
+
function effectFor2(pattern, chain, operation, options) {
|
|
4526
4865
|
const valueMethods = pattern.valueMethods ?? [];
|
|
4527
4866
|
const picked = selectorOf(chain, valueMethods);
|
|
4528
4867
|
return {
|
|
@@ -4632,7 +4971,7 @@ function storageCallIds(calls, options) {
|
|
|
4632
4971
|
}
|
|
4633
4972
|
function storageEffects(calls, options) {
|
|
4634
4973
|
return matchedChains(calls, options).flatMap(
|
|
4635
|
-
({ chain, pattern, operation }) => operation === null ? [] : [
|
|
4974
|
+
({ chain, pattern, operation }) => operation === null ? [] : [effectFor2(pattern, chain, operation, options)]
|
|
4636
4975
|
);
|
|
4637
4976
|
}
|
|
4638
4977
|
|
|
@@ -4667,8 +5006,10 @@ function decoratedStatements(root, module2, facts) {
|
|
|
4667
5006
|
}));
|
|
4668
5007
|
}
|
|
4669
5008
|
function discoverUnits(root, module2, options) {
|
|
5009
|
+
const decorated = decoratedStatements(root, module2, options.facts);
|
|
5010
|
+
askWrittenValues(clientCallReceivers(root, module2), options.facts);
|
|
4670
5011
|
return [
|
|
4671
|
-
...
|
|
5012
|
+
...decorated.flatMap(
|
|
4672
5013
|
(decoratedStatement) => decoratedUnits(decoratedStatement, module2, options)
|
|
4673
5014
|
),
|
|
4674
5015
|
...clientUnits(root, module2, options)
|
|
@@ -4764,7 +5105,7 @@ function readPathArgument(classification, options) {
|
|
|
4764
5105
|
const first = classification.args[0];
|
|
4765
5106
|
if (first !== void 0) {
|
|
4766
5107
|
const value = evaluatedValue(first.node, options.facts);
|
|
4767
|
-
const path6 = (0,
|
|
5108
|
+
const path6 = (0, import_values13.literalOf)(value) ?? (0, import_values13.pathOf)(value);
|
|
4768
5109
|
if (path6 !== void 0) {
|
|
4769
5110
|
return (0, import_extractor5.writtenReading)(path6, classification.range);
|
|
4770
5111
|
}
|
|
@@ -5011,11 +5352,11 @@ function statusFromReturnedValue(node, facts) {
|
|
|
5011
5352
|
return null;
|
|
5012
5353
|
}
|
|
5013
5354
|
const value = evaluatedValue(node, facts);
|
|
5014
|
-
const number = (0,
|
|
5355
|
+
const number = (0, import_values13.constantOf)(value);
|
|
5015
5356
|
if (typeof number === "number") {
|
|
5016
5357
|
return Number.isInteger(number) ? number : null;
|
|
5017
5358
|
}
|
|
5018
|
-
const text2 = (0,
|
|
5359
|
+
const text2 = (0, import_values13.literalOf)(value);
|
|
5019
5360
|
if (text2 === null) {
|
|
5020
5361
|
return null;
|
|
5021
5362
|
}
|
|
@@ -5454,22 +5795,29 @@ function recognizedBodyEffects(definitionNode, module2, storageLookup, facts) {
|
|
|
5454
5795
|
...storageLookup,
|
|
5455
5796
|
filePath: storageLookup.factsPath
|
|
5456
5797
|
}),
|
|
5457
|
-
...rawSqlEffects(bodyCalls(definitionNode),
|
|
5458
|
-
facts: storageLookup.facts,
|
|
5459
|
-
filePath: storageLookup.factsPath,
|
|
5460
|
-
patterns: storageLookup.rawSql ?? []
|
|
5461
|
-
})
|
|
5798
|
+
...rawSqlEffects(bodyCalls(definitionNode), rawSqlOf(storageLookup))
|
|
5462
5799
|
];
|
|
5463
5800
|
return [...envReadEffects(definitionNode, module2, facts), ...storage];
|
|
5464
5801
|
}
|
|
5465
|
-
function
|
|
5802
|
+
function rawSqlOf(storageLookup) {
|
|
5803
|
+
return {
|
|
5804
|
+
facts: storageLookup.facts,
|
|
5805
|
+
filePath: storageLookup.factsPath,
|
|
5806
|
+
patterns: storageLookup.rawSql ?? [],
|
|
5807
|
+
clients: storageLookup.sqlClients ?? []
|
|
5808
|
+
};
|
|
5809
|
+
}
|
|
5810
|
+
function recognizedCallIds(calls, storageLookup) {
|
|
5466
5811
|
if (storageLookup === void 0) {
|
|
5467
5812
|
return /* @__PURE__ */ new Set();
|
|
5468
5813
|
}
|
|
5469
|
-
return
|
|
5470
|
-
...
|
|
5471
|
-
|
|
5472
|
-
|
|
5814
|
+
return /* @__PURE__ */ new Set([
|
|
5815
|
+
...storageCallIds(calls, {
|
|
5816
|
+
...storageLookup,
|
|
5817
|
+
filePath: storageLookup.factsPath
|
|
5818
|
+
}),
|
|
5819
|
+
...rawSqlCallIds(calls, rawSqlOf(storageLookup))
|
|
5820
|
+
]);
|
|
5473
5821
|
}
|
|
5474
5822
|
function bodyContentOf(bodyNode) {
|
|
5475
5823
|
for (const stmt of bodyStatements(bodyNode)) {
|
|
@@ -5902,11 +6250,14 @@ function resolveCallee2(call, site, ctx, read) {
|
|
|
5902
6250
|
const outcome = read?.outcomes.get(spelling.key) ?? (0, import_resolution5.calleeOutcomeOf)(ctx.facts, spelling.key);
|
|
5903
6251
|
return asCallee(outcome, site.owner, ctx);
|
|
5904
6252
|
}
|
|
5905
|
-
function
|
|
6253
|
+
function namedOutcomes(keys, ctx) {
|
|
6254
|
+
return (0, import_resolution5.calleeOutcomes)(ctx.facts, [...new Set(keys)]);
|
|
6255
|
+
}
|
|
6256
|
+
function functionNamed(nameKey2, ctx, read) {
|
|
5906
6257
|
if (assignedElsewhere(ctx.facts, nameKey2)) {
|
|
5907
6258
|
return null;
|
|
5908
6259
|
}
|
|
5909
|
-
const outcome = (0, import_resolution5.calleeOutcomeOf)(ctx.facts, nameKey2);
|
|
6260
|
+
const outcome = read?.get(nameKey2) ?? (0, import_resolution5.calleeOutcomeOf)(ctx.facts, nameKey2);
|
|
5910
6261
|
return outcome.kind === "function" ? functionAt(outcome.key, ctx) : null;
|
|
5911
6262
|
}
|
|
5912
6263
|
function assignedElsewhere(facts, nameKey2) {
|
|
@@ -6114,6 +6465,7 @@ function reachedFunctions(seeds, options) {
|
|
|
6114
6465
|
const stopsByKey = /* @__PURE__ */ new Map();
|
|
6115
6466
|
const argTargetsByKey = /* @__PURE__ */ new Map();
|
|
6116
6467
|
const parameterCallsByKey = /* @__PURE__ */ new Map();
|
|
6468
|
+
const callsByKey = /* @__PURE__ */ new Map();
|
|
6117
6469
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
6118
6470
|
for (const seed of seeds) {
|
|
6119
6471
|
seedKeys.add(seed.key);
|
|
@@ -6140,12 +6492,21 @@ function reachedFunctions(seeds, options) {
|
|
|
6140
6492
|
bodies.flatMap((body) => body.written),
|
|
6141
6493
|
ctx
|
|
6142
6494
|
);
|
|
6495
|
+
const passed = namedOutcomes(
|
|
6496
|
+
bodies.flatMap(
|
|
6497
|
+
({ source, written }) => written.flatMap(({ call }) => passedNameKeys(source.file, call))
|
|
6498
|
+
),
|
|
6499
|
+
ctx
|
|
6500
|
+
);
|
|
6143
6501
|
for (const { key, source, body, written } of bodies) {
|
|
6144
6502
|
const scan = scanBody(
|
|
6145
6503
|
source,
|
|
6146
6504
|
ctx,
|
|
6147
|
-
recognizedCallIds(
|
|
6148
|
-
|
|
6505
|
+
recognizedCallIds(
|
|
6506
|
+
written.map(({ call }) => call),
|
|
6507
|
+
options.storageFor(source.file)
|
|
6508
|
+
),
|
|
6509
|
+
{ body, written, spellings, passed }
|
|
6149
6510
|
);
|
|
6150
6511
|
if (scan.stops.length > 0) {
|
|
6151
6512
|
stopsByKey.set(key, scan.stops);
|
|
@@ -6158,21 +6519,27 @@ function reachedFunctions(seeds, options) {
|
|
|
6158
6519
|
for (const position of scan.passedPositions) {
|
|
6159
6520
|
passedPositions.add(position);
|
|
6160
6521
|
}
|
|
6522
|
+
const called = [];
|
|
6161
6523
|
for (const target of scan.followed) {
|
|
6162
|
-
const calleeKey =
|
|
6524
|
+
const calleeKey = keyOf2(target);
|
|
6163
6525
|
if (!functionByKey.has(calleeKey)) {
|
|
6164
6526
|
functionByKey.set(calleeKey, target);
|
|
6165
6527
|
}
|
|
6166
6528
|
db.add("calls", [key, calleeKey]);
|
|
6529
|
+
called.push(calleeKey);
|
|
6530
|
+
}
|
|
6531
|
+
if (called.length > 0) {
|
|
6532
|
+
callsByKey.set(key, called);
|
|
6167
6533
|
}
|
|
6168
6534
|
}
|
|
6169
6535
|
}
|
|
6536
|
+
const reached = db.facts("reachable").map(([keyAtom]) => String(keyAtom)).filter((key) => !seedKeys.has(key));
|
|
6537
|
+
settleBodyValues(reached, functionByKey, options.facts);
|
|
6170
6538
|
const summaries = [];
|
|
6171
6539
|
const summariesByKey = /* @__PURE__ */ new Map();
|
|
6172
|
-
for (const
|
|
6173
|
-
const key = String(keyAtom);
|
|
6540
|
+
for (const key of reached) {
|
|
6174
6541
|
const target = functionByKey.get(key);
|
|
6175
|
-
if (
|
|
6542
|
+
if (target === void 0) {
|
|
6176
6543
|
continue;
|
|
6177
6544
|
}
|
|
6178
6545
|
const summary = (0, import_extractor7.assembleSummary)(libraryUnit(target, options), {
|
|
@@ -6197,10 +6564,11 @@ function reachedFunctions(seeds, options) {
|
|
|
6197
6564
|
stopsByKey,
|
|
6198
6565
|
argTargetsByKey,
|
|
6199
6566
|
parameterCallsByKey,
|
|
6567
|
+
callsByKey,
|
|
6200
6568
|
passedPositions
|
|
6201
6569
|
};
|
|
6202
6570
|
}
|
|
6203
|
-
function
|
|
6571
|
+
function keyOf2(target) {
|
|
6204
6572
|
return nodeId(target.file.file, target.node);
|
|
6205
6573
|
}
|
|
6206
6574
|
var EMPTY_SCAN = {
|
|
@@ -6213,15 +6581,53 @@ var EMPTY_SCAN = {
|
|
|
6213
6581
|
};
|
|
6214
6582
|
function bodyOf(source) {
|
|
6215
6583
|
const { file, node } = source;
|
|
6216
|
-
const body = field(node, "body");
|
|
6584
|
+
const body = isModule(node) ? node : field(node, "body");
|
|
6217
6585
|
if (body === null) {
|
|
6218
6586
|
return { body, written: [] };
|
|
6219
6587
|
}
|
|
6220
6588
|
return {
|
|
6221
6589
|
body,
|
|
6222
|
-
written: callsWritten(file, body, scopeAt2(file, node),
|
|
6590
|
+
written: callsWritten(file, body, scopeAt2(file, node), keyOf2(source), {
|
|
6591
|
+
descendsInto: isModule(node) ? runsAtModuleLoad : outsideNestedDef
|
|
6592
|
+
})
|
|
6223
6593
|
};
|
|
6224
6594
|
}
|
|
6595
|
+
function outsideNestedDef(node) {
|
|
6596
|
+
return node.type !== "function_definition";
|
|
6597
|
+
}
|
|
6598
|
+
function settleBodyValues(reached, functionByKey, facts) {
|
|
6599
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
6600
|
+
for (const key of reached) {
|
|
6601
|
+
const target = functionByKey.get(key);
|
|
6602
|
+
if (target === void 0) {
|
|
6603
|
+
continue;
|
|
6604
|
+
}
|
|
6605
|
+
const listed = byFile.get(target.file.file) ?? [];
|
|
6606
|
+
for (const node of bodyValueNodes(target.node)) {
|
|
6607
|
+
listed.push(node);
|
|
6608
|
+
}
|
|
6609
|
+
byFile.set(target.file.file, listed);
|
|
6610
|
+
}
|
|
6611
|
+
for (const nodes of byFile.values()) {
|
|
6612
|
+
askWrittenValues(nodes, facts);
|
|
6613
|
+
}
|
|
6614
|
+
}
|
|
6615
|
+
function passedNameKeyOf(file, arg) {
|
|
6616
|
+
if (arg === null || arg.type !== "identifier") {
|
|
6617
|
+
return null;
|
|
6618
|
+
}
|
|
6619
|
+
return readKey(file.file, arg, enclosingFunction(arg));
|
|
6620
|
+
}
|
|
6621
|
+
function passedNameKeys(file, call) {
|
|
6622
|
+
const args = field(call, "arguments");
|
|
6623
|
+
if (args === null) {
|
|
6624
|
+
return [];
|
|
6625
|
+
}
|
|
6626
|
+
return args.namedChildren.flatMap((arg) => {
|
|
6627
|
+
const key = passedNameKeyOf(file, arg);
|
|
6628
|
+
return key === null ? [] : [key];
|
|
6629
|
+
});
|
|
6630
|
+
}
|
|
6225
6631
|
function scanBody(source, ctx, recognized, read) {
|
|
6226
6632
|
const followed = [];
|
|
6227
6633
|
const stops = [];
|
|
@@ -6242,17 +6648,15 @@ function scanBody(source, ctx, recognized, read) {
|
|
|
6242
6648
|
return;
|
|
6243
6649
|
}
|
|
6244
6650
|
args.namedChildren.forEach((arg, position) => {
|
|
6245
|
-
|
|
6651
|
+
const nameKey2 = passedNameKeyOf(file, arg);
|
|
6652
|
+
if (nameKey2 === null) {
|
|
6246
6653
|
return;
|
|
6247
6654
|
}
|
|
6248
|
-
const resolved = functionNamed(
|
|
6249
|
-
readKey(file.file, arg, enclosingFunction(arg)),
|
|
6250
|
-
ctx
|
|
6251
|
-
);
|
|
6655
|
+
const resolved = functionNamed(nameKey2, ctx, read.passed);
|
|
6252
6656
|
if (resolved === null) {
|
|
6253
6657
|
return;
|
|
6254
6658
|
}
|
|
6255
|
-
const key =
|
|
6659
|
+
const key = keyOf2(resolved);
|
|
6256
6660
|
if (!seen.has(key)) {
|
|
6257
6661
|
seen.add(key);
|
|
6258
6662
|
followed.push(resolved);
|
|
@@ -6277,7 +6681,7 @@ function scanBody(source, ctx, recognized, read) {
|
|
|
6277
6681
|
recordPassedArgs(
|
|
6278
6682
|
call,
|
|
6279
6683
|
callee,
|
|
6280
|
-
outcome.kind === "followed" ?
|
|
6684
|
+
outcome.kind === "followed" ? keyOf2(outcome.target) : null
|
|
6281
6685
|
);
|
|
6282
6686
|
if (outcome.kind === "stopped") {
|
|
6283
6687
|
const stopKey = `${outcome.reason}:${callee}`;
|
|
@@ -6294,7 +6698,7 @@ function scanBody(source, ctx, recognized, read) {
|
|
|
6294
6698
|
}
|
|
6295
6699
|
return;
|
|
6296
6700
|
}
|
|
6297
|
-
const key =
|
|
6701
|
+
const key = keyOf2(outcome.target);
|
|
6298
6702
|
if (!seen.has(key)) {
|
|
6299
6703
|
seen.add(key);
|
|
6300
6704
|
followed.push(outcome.target);
|
|
@@ -6312,7 +6716,7 @@ function scanBody(source, ctx, recognized, read) {
|
|
|
6312
6716
|
passedPositions
|
|
6313
6717
|
};
|
|
6314
6718
|
}
|
|
6315
|
-
function callsWritten(file, body, outer, owner) {
|
|
6719
|
+
function callsWritten(file, body, outer, owner, limit) {
|
|
6316
6720
|
const found = [];
|
|
6317
6721
|
(0, import_extractor7.walkDescendants)(body, outer, {
|
|
6318
6722
|
at: (child, scope) => {
|
|
@@ -6320,7 +6724,7 @@ function callsWritten(file, body, outer, owner) {
|
|
|
6320
6724
|
found.push({ call: child, site: { file, scope, owner } });
|
|
6321
6725
|
}
|
|
6322
6726
|
},
|
|
6323
|
-
into: (child, scope) => child
|
|
6727
|
+
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope : import_extractor7.SKIP_CHILDREN
|
|
6324
6728
|
});
|
|
6325
6729
|
return found;
|
|
6326
6730
|
}
|
|
@@ -8094,10 +8498,7 @@ function factsForFile(options) {
|
|
|
8094
8498
|
files: [{ file: options.file, root: options.root, module: options.module }],
|
|
8095
8499
|
definitions
|
|
8096
8500
|
});
|
|
8097
|
-
|
|
8098
|
-
db,
|
|
8099
|
-
envNameSites(options.file, options.root, options.module)
|
|
8100
|
-
);
|
|
8501
|
+
bindEnvFacts(db, [envFactsIn(options.file, options.root, options.module)]);
|
|
8101
8502
|
(0, import_resolution7.addPackWords)(db, packWordsOf(options.packs));
|
|
8102
8503
|
return db;
|
|
8103
8504
|
}
|
|
@@ -8148,6 +8549,7 @@ async function extractPythonProject(options) {
|
|
|
8148
8549
|
);
|
|
8149
8550
|
const storagePatterns = options.packs.flatMap((pack) => pack.storage ?? []);
|
|
8150
8551
|
const rawSqlPatterns = options.packs.flatMap((pack) => pack.rawSql ?? []);
|
|
8552
|
+
const sqlClients = options.packs.flatMap((pack) => pack.sqlClients ?? []);
|
|
8151
8553
|
const modelQueries = options.packs.flatMap((pack) => pack.models ?? []);
|
|
8152
8554
|
const discovers = options.packs.some((pack) => pack.discovery.length > 0);
|
|
8153
8555
|
const buildsReceivers = options.packs.some(
|
|
@@ -8155,10 +8557,15 @@ async function extractPythonProject(options) {
|
|
|
8155
8557
|
(client) => (client.receiverConstructors ?? []).length > 0
|
|
8156
8558
|
)
|
|
8157
8559
|
);
|
|
8158
|
-
const
|
|
8159
|
-
(boundFile) =>
|
|
8560
|
+
const envFacts = bound.map(
|
|
8561
|
+
(boundFile) => envFactsIn(boundFile.file, boundFile.root, boundFile.module)
|
|
8562
|
+
);
|
|
8563
|
+
const readsEnvThroughNames = envFacts.some(
|
|
8564
|
+
(one) => one.sites.length > 0 || one.objects.length > 0
|
|
8160
8565
|
);
|
|
8161
|
-
const needsValues = discovers || mountsRouters || buildsReceivers ||
|
|
8566
|
+
const needsValues = discovers || mountsRouters || buildsReceivers || readsEnvThroughNames || storagePatterns.length > 0 || modelQueries.length > 0 || // A statement written as SQL is a value, and so is the client the
|
|
8567
|
+
// call that hands it over is read off.
|
|
8568
|
+
rawSqlPatterns.length > 0 || sqlClients.length > 0;
|
|
8162
8569
|
const definitions = /* @__PURE__ */ new Map();
|
|
8163
8570
|
timer.time("discover", () => {
|
|
8164
8571
|
for (const { file, root, module: moduleBinding } of bound) {
|
|
@@ -8170,7 +8577,7 @@ async function extractPythonProject(options) {
|
|
|
8170
8577
|
}
|
|
8171
8578
|
if (needsValues) {
|
|
8172
8579
|
bindEvaluator(db, { files: bound, definitions });
|
|
8173
|
-
|
|
8580
|
+
bindEnvFacts(db, envFacts);
|
|
8174
8581
|
}
|
|
8175
8582
|
(0, import_resolution7.addPackWords)(db, packWordsOf(options.packs));
|
|
8176
8583
|
});
|
|
@@ -8186,13 +8593,14 @@ async function extractPythonProject(options) {
|
|
|
8186
8593
|
...mountsRouters ? { facts: db } : {}
|
|
8187
8594
|
})
|
|
8188
8595
|
);
|
|
8189
|
-
const storageFor = (file) => storagePatterns.length > 0 || rawSqlPatterns.length > 0 ? {
|
|
8596
|
+
const storageFor = (file) => storagePatterns.length > 0 || rawSqlPatterns.length > 0 || sqlClients.length > 0 ? {
|
|
8190
8597
|
facts: db,
|
|
8191
8598
|
factsPath: file.file,
|
|
8192
8599
|
patterns: storagePatterns,
|
|
8193
8600
|
definitionAt: (key) => definitions.get(key),
|
|
8194
8601
|
couldMatch,
|
|
8195
|
-
rawSql: rawSqlPatterns
|
|
8602
|
+
rawSql: rawSqlPatterns,
|
|
8603
|
+
sqlClients
|
|
8196
8604
|
} : void 0;
|
|
8197
8605
|
const wrapperIndex = timer.time(
|
|
8198
8606
|
"discover",
|
|
@@ -8227,6 +8635,7 @@ async function extractPythonProject(options) {
|
|
|
8227
8635
|
}
|
|
8228
8636
|
const seeds = [];
|
|
8229
8637
|
const summariesBySeed = /* @__PURE__ */ new Map();
|
|
8638
|
+
const moduleRoots = [];
|
|
8230
8639
|
for (const boundFile of bound) {
|
|
8231
8640
|
const { file, root, module: moduleBinding } = boundFile;
|
|
8232
8641
|
const displayPath = displayPathOf(file);
|
|
@@ -8261,21 +8670,15 @@ async function extractPythonProject(options) {
|
|
|
8261
8670
|
"discover",
|
|
8262
8671
|
() => envReadEffects(root, moduleBinding, db)
|
|
8263
8672
|
);
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
}),
|
|
8274
|
-
{ gapHandling }
|
|
8275
|
-
)
|
|
8276
|
-
);
|
|
8277
|
-
summary.confidence = { source: "inferred_static", level: "low" };
|
|
8278
|
-
summaries.push(summary);
|
|
8673
|
+
const moduleKey = nodeId(file, root);
|
|
8674
|
+
if (!summariesBySeed.has(moduleKey)) {
|
|
8675
|
+
seeds.push({ key: moduleKey, file: boundFile, node: root });
|
|
8676
|
+
moduleRoots.push({
|
|
8677
|
+
boundFile,
|
|
8678
|
+
displayPath,
|
|
8679
|
+
key: moduleKey,
|
|
8680
|
+
loadTimeReads
|
|
8681
|
+
});
|
|
8279
8682
|
}
|
|
8280
8683
|
}
|
|
8281
8684
|
const reached = timer.time(
|
|
@@ -8289,16 +8692,19 @@ async function extractPythonProject(options) {
|
|
|
8289
8692
|
definitions
|
|
8290
8693
|
})
|
|
8291
8694
|
);
|
|
8695
|
+
const placeWhatItReached = (summary, key) => {
|
|
8696
|
+
if (gapHandling !== "silent") {
|
|
8697
|
+
summary.gaps.push(
|
|
8698
|
+
...(reached.stopsByKey.get(key) ?? []).map(import_behavioral_ir6.unfollowedCallGap)
|
|
8699
|
+
);
|
|
8700
|
+
}
|
|
8701
|
+
(0, import_behavioral_ir6.placeCalls)(summary, reached.targetsByKey.get(key));
|
|
8702
|
+
(0, import_behavioral_ir6.placeArgTargets)(summary, reached.argTargetsByKey.get(key));
|
|
8703
|
+
(0, import_behavioral_ir6.placeCalleeParameters)(summary, reached.parameterCallsByKey.get(key));
|
|
8704
|
+
};
|
|
8292
8705
|
for (const [key, owners] of summariesBySeed) {
|
|
8293
8706
|
for (const summary of owners) {
|
|
8294
|
-
|
|
8295
|
-
summary.gaps.push(
|
|
8296
|
-
...(reached.stopsByKey.get(key) ?? []).map(import_behavioral_ir6.unfollowedCallGap)
|
|
8297
|
-
);
|
|
8298
|
-
}
|
|
8299
|
-
(0, import_behavioral_ir6.placeCalls)(summary, reached.targetsByKey.get(key));
|
|
8300
|
-
(0, import_behavioral_ir6.placeArgTargets)(summary, reached.argTargetsByKey.get(key));
|
|
8301
|
-
(0, import_behavioral_ir6.placeCalleeParameters)(summary, reached.parameterCallsByKey.get(key));
|
|
8707
|
+
placeWhatItReached(summary, key);
|
|
8302
8708
|
}
|
|
8303
8709
|
}
|
|
8304
8710
|
if (gapHandling !== "silent") {
|
|
@@ -8308,6 +8714,30 @@ async function extractPythonProject(options) {
|
|
|
8308
8714
|
reached.passedPositions
|
|
8309
8715
|
);
|
|
8310
8716
|
}
|
|
8717
|
+
for (const { boundFile, displayPath, key, loadTimeReads } of moduleRoots) {
|
|
8718
|
+
const calledAtLoad = reached.callsByKey.get(key) ?? [];
|
|
8719
|
+
if (loadTimeReads.length === 0 && calledAtLoad.length === 0) {
|
|
8720
|
+
continue;
|
|
8721
|
+
}
|
|
8722
|
+
const summary = timer.time(
|
|
8723
|
+
"summarize",
|
|
8724
|
+
() => (0, import_extractor10.assembleSummary)(
|
|
8725
|
+
(0, import_extractor10.moduleInitStructure)({
|
|
8726
|
+
name: import_node_path3.default.basename(displayPath),
|
|
8727
|
+
file: displayPath,
|
|
8728
|
+
range: rangeOf(boundFile.root),
|
|
8729
|
+
effects: [
|
|
8730
|
+
...loadTimeReads,
|
|
8731
|
+
...moduleLoadInvocationEffects(boundFile.root, db).map(import_extractor10.effectToIR)
|
|
8732
|
+
]
|
|
8733
|
+
}),
|
|
8734
|
+
{ gapHandling }
|
|
8735
|
+
)
|
|
8736
|
+
);
|
|
8737
|
+
summary.confidence = { source: "inferred_static", level: "low" };
|
|
8738
|
+
placeWhatItReached(summary, key);
|
|
8739
|
+
summaries.push(summary);
|
|
8740
|
+
}
|
|
8311
8741
|
summaries.push(...reached.summaries);
|
|
8312
8742
|
const resolvedImports = resolvedImportsOf(db, displayPathOf);
|
|
8313
8743
|
(0, import_extractor10.stampModuleImports)(summaries, (file) => resolvedImports.get(file) ?? []);
|