@suss/adapter-python 0.35.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +491 -229
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +509 -221
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -989,6 +989,8 @@ import {
|
|
|
989
989
|
addTemplateRows,
|
|
990
990
|
NAMED_STORE_NAME,
|
|
991
991
|
RECEIVER_STORE_NAME,
|
|
992
|
+
SELF_AS_CLASS_NAME,
|
|
993
|
+
SELF_AS_INSTANCE_NAME,
|
|
992
994
|
SPREAD_ENTRY,
|
|
993
995
|
startsAtName,
|
|
994
996
|
UNPLACED_STORE_NAME,
|
|
@@ -1005,6 +1007,8 @@ var CONVERTING_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
1005
1007
|
]);
|
|
1006
1008
|
var ATTRIBUTE_GETTER = "getattr";
|
|
1007
1009
|
var POSITION_COUNTER = "enumerate";
|
|
1010
|
+
var CLASS_METHOD_DECORATOR = "classmethod";
|
|
1011
|
+
var STATIC_METHOD_DECORATOR = "staticmethod";
|
|
1008
1012
|
|
|
1009
1013
|
// src/facts/values.ts
|
|
1010
1014
|
function nodeId(filePath, node) {
|
|
@@ -1684,6 +1688,26 @@ function yieldedValue(node) {
|
|
|
1684
1688
|
}
|
|
1685
1689
|
return children(node).find((child) => child?.type !== "comment") ?? null;
|
|
1686
1690
|
}
|
|
1691
|
+
function emitReceiver(emitter, fn, paramKey, classKey) {
|
|
1692
|
+
const form = receiverFormOf(fn);
|
|
1693
|
+
if (form === SELF_AS_CLASS_NAME) {
|
|
1694
|
+
add(emitter, "binds", paramKey, classKey);
|
|
1695
|
+
} else {
|
|
1696
|
+
add(emitter, "instanceOf", paramKey, classKey);
|
|
1697
|
+
}
|
|
1698
|
+
if (form !== null) {
|
|
1699
|
+
add(emitter, "selfReceiver", nodeId(emitter.filePath, fn), paramKey, form);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
function receiverFormOf(fn) {
|
|
1703
|
+
const decorators = fn.parent?.type === "decorated_definition" ? stripDecorators(fn.parent).decorators.map(
|
|
1704
|
+
(decorator) => decorator.text.slice(1).trim()
|
|
1705
|
+
) : [];
|
|
1706
|
+
if (decorators.includes(STATIC_METHOD_DECORATOR)) {
|
|
1707
|
+
return null;
|
|
1708
|
+
}
|
|
1709
|
+
return decorators.includes(CLASS_METHOD_DECORATOR) ? SELF_AS_CLASS_NAME : SELF_AS_INSTANCE_NAME;
|
|
1710
|
+
}
|
|
1687
1711
|
function emitFunctionFacts(emitter, fn, classKey) {
|
|
1688
1712
|
const funcKey = nodeId(emitter.filePath, fn);
|
|
1689
1713
|
add(emitter, "func", funcKey);
|
|
@@ -1707,7 +1731,7 @@ function emitFunctionFacts(emitter, fn, classKey) {
|
|
|
1707
1731
|
}
|
|
1708
1732
|
if (classKey !== void 0 && position === -1) {
|
|
1709
1733
|
receiver = { classKey, name: paramName.text };
|
|
1710
|
-
|
|
1734
|
+
emitReceiver(emitter, fn, paramKey, classKey);
|
|
1711
1735
|
}
|
|
1712
1736
|
add(emitter, "paramNamed", funcKey, paramName.text, paramKey);
|
|
1713
1737
|
const fallback2 = field(param, "value");
|
|
@@ -3796,6 +3820,7 @@ import {
|
|
|
3796
3820
|
absentReading,
|
|
3797
3821
|
ambiguousReading,
|
|
3798
3822
|
andThenReading,
|
|
3823
|
+
effectsFiringOn as effectsFiringOn2,
|
|
3799
3824
|
firstWrittenReading,
|
|
3800
3825
|
mapReading,
|
|
3801
3826
|
unreadableReading,
|
|
@@ -3816,7 +3841,7 @@ import { redirectDeliveryWhenSet } from "@suss/extractor";
|
|
|
3816
3841
|
import { hostOf, pathOf, scalarOf } from "@suss/values";
|
|
3817
3842
|
|
|
3818
3843
|
// src/paths/bodyBranches.ts
|
|
3819
|
-
import {
|
|
3844
|
+
import { effectsFiringOn, enumerateOrDegrade } from "@suss/extractor";
|
|
3820
3845
|
|
|
3821
3846
|
// src/provenance.ts
|
|
3822
3847
|
import { sourceRefsOf } from "@suss/extractor";
|
|
@@ -3953,7 +3978,7 @@ import { storageBinding as storageBinding2 } from "@suss/ir-core";
|
|
|
3953
3978
|
import { answersFor } from "@suss/resolution";
|
|
3954
3979
|
|
|
3955
3980
|
// src/paths/effects.ts
|
|
3956
|
-
import {
|
|
3981
|
+
import { sharedGatingConditions, statementSites } from "@suss/extractor";
|
|
3957
3982
|
import { constantOf as constantOf2, literalOf as literalOf4 } from "@suss/values";
|
|
3958
3983
|
|
|
3959
3984
|
// src/paths/lowering.ts
|
|
@@ -4067,6 +4092,7 @@ var Lowerer = class {
|
|
|
4067
4092
|
) ?? null;
|
|
4068
4093
|
return {
|
|
4069
4094
|
kind: "try",
|
|
4095
|
+
lines: rangeOf(node),
|
|
4070
4096
|
tryBody: this.lowerBlock(field(node, "body")),
|
|
4071
4097
|
catchBody: excepts.length > 0 ? excepts.flatMap((clause) => this.lowerBlock(childBlock(clause))) : null,
|
|
4072
4098
|
finallyBody: finallyClause === null ? null : this.lowerBlock(childBlock(finallyClause)),
|
|
@@ -4107,12 +4133,19 @@ var Lowerer = class {
|
|
|
4107
4133
|
}
|
|
4108
4134
|
if (node.type === "while_statement" || node.type === "for_statement") {
|
|
4109
4135
|
const header = node.type === "while_statement" ? field(node, "condition") : field(node, "right");
|
|
4136
|
+
const body = field(node, "body");
|
|
4110
4137
|
return this.attach(
|
|
4111
4138
|
{
|
|
4112
4139
|
kind: "loop",
|
|
4113
4140
|
condition: handleOf(header),
|
|
4114
|
-
body: this.lowerBlock(
|
|
4115
|
-
exitKind: exitKindOf(node, this.thrown)
|
|
4141
|
+
body: this.lowerBlock(body),
|
|
4142
|
+
exitKind: exitKindOf(node, this.thrown),
|
|
4143
|
+
// An `else` clause runs once the loop is done, so it is no part
|
|
4144
|
+
// of what repeats.
|
|
4145
|
+
lines: {
|
|
4146
|
+
start: rangeOf(node).start,
|
|
4147
|
+
end: rangeOf(body ?? node).end
|
|
4148
|
+
}
|
|
4116
4149
|
},
|
|
4117
4150
|
[header]
|
|
4118
4151
|
);
|
|
@@ -4144,6 +4177,9 @@ function lowerPythonBody(body, terminals, thrown = new NodeSet()) {
|
|
|
4144
4177
|
// src/paths/effects.ts
|
|
4145
4178
|
var NESTED_DEFINITION_TYPES = /* @__PURE__ */ new Set(["function_definition"]);
|
|
4146
4179
|
function literalArgOf(node, facts) {
|
|
4180
|
+
if (node.type === "none") {
|
|
4181
|
+
return { kind: "null" };
|
|
4182
|
+
}
|
|
4147
4183
|
const value = evaluatedValue(node, facts);
|
|
4148
4184
|
const text2 = literalOf4(value);
|
|
4149
4185
|
if (text2 !== null) {
|
|
@@ -4221,9 +4257,6 @@ function argsOf(call, facts) {
|
|
|
4221
4257
|
function calleeText(call) {
|
|
4222
4258
|
return field(call, "function")?.text ?? call.text;
|
|
4223
4259
|
}
|
|
4224
|
-
function invocationEffects(definitionNode, facts) {
|
|
4225
|
-
return invocationSites(definitionNode, facts).map((site) => site.effect);
|
|
4226
|
-
}
|
|
4227
4260
|
function invocationSites(definitionNode, facts) {
|
|
4228
4261
|
const body = field(definitionNode, "body");
|
|
4229
4262
|
if (body === null) {
|
|
@@ -4279,33 +4312,26 @@ function gatingInputs(body, gatingOf, facts) {
|
|
|
4279
4312
|
);
|
|
4280
4313
|
return operands.length === 0 ? void 0 : guardInputs(operands, { facts, unit });
|
|
4281
4314
|
}
|
|
4315
|
+
function sitesIn(body, nodes) {
|
|
4316
|
+
return statementSites(nodes, {
|
|
4317
|
+
statementOf: (node) => enclosingStatement(node, body),
|
|
4318
|
+
lower: (statements) => lowerPythonBody(body, statements),
|
|
4319
|
+
firstLine: (node) => rangeOf(node).start
|
|
4320
|
+
});
|
|
4321
|
+
}
|
|
4322
|
+
function effectSitesIn(body, nodes) {
|
|
4323
|
+
if (body === null || nodes.length === 0) {
|
|
4324
|
+
return (node) => ({ line: rangeOf(node).start });
|
|
4325
|
+
}
|
|
4326
|
+
return sitesIn(body, nodes).plainSiteOf;
|
|
4327
|
+
}
|
|
4282
4328
|
function invocationEffectsIn(body, written, facts) {
|
|
4283
4329
|
const calls = [...written].sort((a, b) => a.endIndex - b.endIndex);
|
|
4284
4330
|
if (calls.length === 0) {
|
|
4285
4331
|
return [];
|
|
4286
4332
|
}
|
|
4287
|
-
const
|
|
4288
|
-
const
|
|
4289
|
-
for (const call of calls) {
|
|
4290
|
-
const statement = enclosingStatement(call, body);
|
|
4291
|
-
if (statement === null) {
|
|
4292
|
-
continue;
|
|
4293
|
-
}
|
|
4294
|
-
statementOf3.set(call.id, statement);
|
|
4295
|
-
statements.push(statement);
|
|
4296
|
-
}
|
|
4297
|
-
const lowered = lowerPythonBody(body, statements);
|
|
4298
|
-
const enumerated = enumerateOrDegrade(
|
|
4299
|
-
{
|
|
4300
|
-
statements: lowered.statements,
|
|
4301
|
-
terminalsByStmt: lowered.terminalsByStmt
|
|
4302
|
-
},
|
|
4303
|
-
statements
|
|
4304
|
-
);
|
|
4305
|
-
const gatingOf = calls.map((call) => {
|
|
4306
|
-
const statement = statementOf3.get(call.id);
|
|
4307
|
-
return statement === void 0 ? void 0 : enumerated.byTerminal.get(statement);
|
|
4308
|
-
});
|
|
4333
|
+
const sites = sitesIn(body, calls);
|
|
4334
|
+
const gatingOf = calls.map((call) => sites.pathsTo(call));
|
|
4309
4335
|
askWrittenValues(
|
|
4310
4336
|
calls.flatMap((call, index) => effectValueNodes(call, gatingOf[index])),
|
|
4311
4337
|
facts
|
|
@@ -4323,8 +4349,10 @@ function invocationEffectsIn(body, written, facts) {
|
|
|
4323
4349
|
callee: calleeText(call),
|
|
4324
4350
|
args: argsOf(call, facts),
|
|
4325
4351
|
async: false,
|
|
4326
|
-
...conditions.length > 0 ? { preconditions: conditions } : {}
|
|
4327
|
-
|
|
4352
|
+
...conditions.length > 0 ? { preconditions: conditions } : {},
|
|
4353
|
+
location: rangeOf(call)
|
|
4354
|
+
},
|
|
4355
|
+
site: sites.siteOf(call, conditions)
|
|
4328
4356
|
};
|
|
4329
4357
|
});
|
|
4330
4358
|
}
|
|
@@ -4429,7 +4457,7 @@ function rawSqlEffects(calls, options) {
|
|
|
4429
4457
|
for (const match of matchesIn(calls, options)) {
|
|
4430
4458
|
for (const access of match.accesses) {
|
|
4431
4459
|
const effect = effectFor(match, access);
|
|
4432
|
-
found.effects.push(effect);
|
|
4460
|
+
found.effects.push({ effect, at: match.call });
|
|
4433
4461
|
for (const slot of boundSlots(access, match.binds)) {
|
|
4434
4462
|
found.slots.push({ ...slot, effect });
|
|
4435
4463
|
}
|
|
@@ -4536,7 +4564,8 @@ function effectFor(match, access) {
|
|
|
4536
4564
|
fields: access.fields,
|
|
4537
4565
|
...access.selector.length > 0 ? { selector: access.selector } : {},
|
|
4538
4566
|
operation
|
|
4539
|
-
}
|
|
4567
|
+
},
|
|
4568
|
+
location: rangeOf(match.call)
|
|
4540
4569
|
};
|
|
4541
4570
|
}
|
|
4542
4571
|
var NO_GROUP = "default";
|
|
@@ -5050,7 +5079,8 @@ function effectFor2(pattern, chain, operation, options) {
|
|
|
5050
5079
|
fields: fieldsOf(chain, valueMethods),
|
|
5051
5080
|
operation,
|
|
5052
5081
|
...picked.length > 0 ? { selector: picked } : {}
|
|
5053
|
-
}
|
|
5082
|
+
},
|
|
5083
|
+
location: rangeOf(chain.last)
|
|
5054
5084
|
};
|
|
5055
5085
|
if (options.statesSlots !== void 0) {
|
|
5056
5086
|
const slots = slotsOf(chain, valueMethods);
|
|
@@ -5147,7 +5177,12 @@ function storageCallIds(calls, options) {
|
|
|
5147
5177
|
}
|
|
5148
5178
|
function storageEffects(calls, options) {
|
|
5149
5179
|
return matchedChains(calls, options).flatMap(
|
|
5150
|
-
({ chain, pattern, operation }) => operation === null ? [] : [
|
|
5180
|
+
({ chain, pattern, operation }) => operation === null ? [] : [
|
|
5181
|
+
{
|
|
5182
|
+
effect: effectFor2(pattern, chain, operation, options),
|
|
5183
|
+
at: chain.last
|
|
5184
|
+
}
|
|
5185
|
+
]
|
|
5151
5186
|
);
|
|
5152
5187
|
}
|
|
5153
5188
|
var storageByScope = /* @__PURE__ */ new WeakMap();
|
|
@@ -5345,11 +5380,6 @@ function bodyTerminals(body, raised, continuations = []) {
|
|
|
5345
5380
|
];
|
|
5346
5381
|
return found.sort((a, b) => a.statement.startIndex - b.statement.startIndex);
|
|
5347
5382
|
}
|
|
5348
|
-
function effectsReaching(effects, conditions) {
|
|
5349
|
-
return effects.filter(
|
|
5350
|
-
(effect) => guardsHoldOn(effect.preconditions, conditions)
|
|
5351
|
-
);
|
|
5352
|
-
}
|
|
5353
5383
|
function conditionInputs(pathSets, options) {
|
|
5354
5384
|
const unit = options.body?.parent ?? null;
|
|
5355
5385
|
if (options.facts === void 0 || unit === null) {
|
|
@@ -5371,7 +5401,7 @@ function enumerateBodyBranches(options) {
|
|
|
5371
5401
|
...options.terminals.filter((found) => found.type === "continuation").map((found) => found.statement)
|
|
5372
5402
|
]);
|
|
5373
5403
|
const lowered = lowerPythonBody(options.body, statements, leavesByCall);
|
|
5374
|
-
const enumerated =
|
|
5404
|
+
const enumerated = enumerateOrDegrade(
|
|
5375
5405
|
{
|
|
5376
5406
|
statements: lowered.statements,
|
|
5377
5407
|
terminalsByStmt: lowered.terminalsByStmt,
|
|
@@ -5384,7 +5414,8 @@ function enumerateBodyBranches(options) {
|
|
|
5384
5414
|
options
|
|
5385
5415
|
);
|
|
5386
5416
|
const branches = [];
|
|
5387
|
-
const push = (branch, paths) => {
|
|
5417
|
+
const push = (branch, paths, placement) => {
|
|
5418
|
+
const loopAround = placement?.loopAround;
|
|
5388
5419
|
for (const path8 of paths) {
|
|
5389
5420
|
const conditions = path8.map((condition) => ({
|
|
5390
5421
|
sourceText: condition.sourceText,
|
|
@@ -5392,10 +5423,14 @@ function enumerateBodyBranches(options) {
|
|
|
5392
5423
|
polarity: condition.polarity,
|
|
5393
5424
|
source: condition.source
|
|
5394
5425
|
}));
|
|
5395
|
-
|
|
5426
|
+
const ending = {
|
|
5396
5427
|
...branch,
|
|
5397
5428
|
conditions,
|
|
5398
|
-
|
|
5429
|
+
...loopAround === void 0 ? {} : { loopAround }
|
|
5430
|
+
};
|
|
5431
|
+
branches.push({
|
|
5432
|
+
...ending,
|
|
5433
|
+
effects: effectsFiringOn(options.effects, ending),
|
|
5399
5434
|
isDefault: path8.length === 0
|
|
5400
5435
|
});
|
|
5401
5436
|
}
|
|
@@ -5403,11 +5438,15 @@ function enumerateBodyBranches(options) {
|
|
|
5403
5438
|
for (const found of options.terminals) {
|
|
5404
5439
|
const paths = enumerated.byTerminal.get(found.statement);
|
|
5405
5440
|
if (paths !== void 0) {
|
|
5406
|
-
push(
|
|
5441
|
+
push(
|
|
5442
|
+
options.branchOf(found),
|
|
5443
|
+
paths,
|
|
5444
|
+
enumerated.placement.get(found.statement)
|
|
5445
|
+
);
|
|
5407
5446
|
}
|
|
5408
5447
|
}
|
|
5409
5448
|
if (options.fallthrough !== void 0) {
|
|
5410
|
-
push(options.fallthrough, enumerated.fallthrough);
|
|
5449
|
+
push(options.fallthrough, enumerated.fallthrough, void 0);
|
|
5411
5450
|
}
|
|
5412
5451
|
return branches;
|
|
5413
5452
|
}
|
|
@@ -5582,15 +5621,10 @@ function writtenMessageOf(call) {
|
|
|
5582
5621
|
import { helperPathsOnVariables, splitAtHandOffs } from "@suss/extractor";
|
|
5583
5622
|
function throughResponseHelpers(branches, sites, options) {
|
|
5584
5623
|
const handOffs = [];
|
|
5585
|
-
for (const { call,
|
|
5624
|
+
for (const { call, site } of sites) {
|
|
5586
5625
|
const helper = helperBranchesAt(call, options);
|
|
5587
5626
|
if (helper !== null) {
|
|
5588
|
-
handOffs.push({
|
|
5589
|
-
helper,
|
|
5590
|
-
preconditions: effect.preconditions,
|
|
5591
|
-
line: rangeOf(call).start,
|
|
5592
|
-
at: rangeOf(call)
|
|
5593
|
-
});
|
|
5627
|
+
handOffs.push({ ...site, helper, at: rangeOf(call) });
|
|
5594
5628
|
}
|
|
5595
5629
|
}
|
|
5596
5630
|
return handOffs.length === 0 ? [...branches] : branches.flatMap((branch) => splitAtHandOffs(branch, handOffs));
|
|
@@ -5837,7 +5871,7 @@ function callerBranches(definition, reading) {
|
|
|
5837
5871
|
body,
|
|
5838
5872
|
terminals: bodyTerminals(body, raised),
|
|
5839
5873
|
raised,
|
|
5840
|
-
effects,
|
|
5874
|
+
effects: sites,
|
|
5841
5875
|
branchOf: (found2) => found2.type === "raise" ? { terminal: found2.terminal, location: rangeOf(found2.statement) } : handsBackAt(rangeOf(found2.statement)),
|
|
5842
5876
|
fallthrough: handsBackAt(range),
|
|
5843
5877
|
facts: reading.facts,
|
|
@@ -6417,9 +6451,7 @@ function envReadEffects(root, module, facts) {
|
|
|
6417
6451
|
const syntax = envReadSyntaxAt(node, scope);
|
|
6418
6452
|
if (syntax !== null) {
|
|
6419
6453
|
const name = stringLiteralValue(syntax.name);
|
|
6420
|
-
|
|
6421
|
-
slots.push({ read: { name, defaulted: syntax.defaulted } });
|
|
6422
|
-
}
|
|
6454
|
+
slots.push({ read: { name, defaulted: syntax.defaulted }, at: node });
|
|
6423
6455
|
return;
|
|
6424
6456
|
}
|
|
6425
6457
|
if (readsHelpers && node.type === "call") {
|
|
@@ -6439,21 +6471,25 @@ function envReadEffects(root, module, facts) {
|
|
|
6439
6471
|
);
|
|
6440
6472
|
return slots.flatMap((slot) => {
|
|
6441
6473
|
if ("read" in slot) {
|
|
6442
|
-
return [configReadEffect(slot.read)];
|
|
6474
|
+
return [{ effect: configReadEffect(slot.read, slot.at), at: slot.at }];
|
|
6443
6475
|
}
|
|
6444
|
-
return throughHelpers.get(slot.call.id) ?? []
|
|
6476
|
+
return (throughHelpers.get(slot.call.id) ?? []).map((effect) => ({
|
|
6477
|
+
effect,
|
|
6478
|
+
at: slot.call
|
|
6479
|
+
}));
|
|
6445
6480
|
});
|
|
6446
6481
|
}
|
|
6447
|
-
function configReadEffect(read) {
|
|
6482
|
+
function configReadEffect(read, at) {
|
|
6448
6483
|
return {
|
|
6449
6484
|
type: "interaction",
|
|
6450
6485
|
binding: runtimeConfigBinding({ recognition: PYTHON_ENV_RECOGNITION }),
|
|
6451
|
-
callee: `os.environ["${read.name}"]`,
|
|
6486
|
+
callee: read.name === null ? at.text : `os.environ["${read.name}"]`,
|
|
6452
6487
|
interaction: {
|
|
6453
6488
|
class: "config-read",
|
|
6454
6489
|
name: read.name,
|
|
6455
6490
|
defaulted: read.defaulted
|
|
6456
|
-
}
|
|
6491
|
+
},
|
|
6492
|
+
location: rangeOf(at)
|
|
6457
6493
|
};
|
|
6458
6494
|
}
|
|
6459
6495
|
function envReadSyntaxAt(node, scope) {
|
|
@@ -6659,6 +6695,15 @@ function argumentsByParameter(db, call, calleeKey2) {
|
|
|
6659
6695
|
}
|
|
6660
6696
|
return argumentAt2;
|
|
6661
6697
|
}
|
|
6698
|
+
function handsOnParameter(argument) {
|
|
6699
|
+
const caller = enclosingFunction(argument);
|
|
6700
|
+
if (argument.type !== "identifier" || caller === null) {
|
|
6701
|
+
return false;
|
|
6702
|
+
}
|
|
6703
|
+
return children(field(caller, "parameters")).some(
|
|
6704
|
+
(param) => parameterIdentifier(param)?.text === argument.text
|
|
6705
|
+
);
|
|
6706
|
+
}
|
|
6662
6707
|
function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
6663
6708
|
const reads = /* @__PURE__ */ new Map();
|
|
6664
6709
|
for (const [parameter, argument] of argumentAt2) {
|
|
@@ -6668,7 +6713,7 @@ function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
|
6668
6713
|
`${NAMED_PARAMETER}${parameter}`,
|
|
6669
6714
|
describeSites(sites, siteById)
|
|
6670
6715
|
);
|
|
6671
|
-
if (sites === void 0) {
|
|
6716
|
+
if (sites === void 0 || handsOnParameter(argument)) {
|
|
6672
6717
|
continue;
|
|
6673
6718
|
}
|
|
6674
6719
|
const name = stringLiteralValue(argument) ?? stringValueOf(argument, db);
|
|
@@ -6685,7 +6730,7 @@ function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
|
6685
6730
|
}
|
|
6686
6731
|
const defaultedAtCall = isDefaultedAt(call);
|
|
6687
6732
|
return [...reads].map(
|
|
6688
|
-
([name, defaulted]) => configReadEffect({ name, defaulted: defaulted || defaultedAtCall })
|
|
6733
|
+
([name, defaulted]) => configReadEffect({ name, defaulted: defaulted || defaultedAtCall }, call)
|
|
6689
6734
|
);
|
|
6690
6735
|
}
|
|
6691
6736
|
|
|
@@ -6762,7 +6807,12 @@ function returnedBodyShape(statement) {
|
|
|
6762
6807
|
|
|
6763
6808
|
// src/streamWrites.ts
|
|
6764
6809
|
import { ioBinding } from "@suss/behavioral-ir";
|
|
6765
|
-
import {
|
|
6810
|
+
import {
|
|
6811
|
+
callSiteKey,
|
|
6812
|
+
numberRepeatedCallSites,
|
|
6813
|
+
SKIP_CHILDREN as SKIP_CHILDREN2,
|
|
6814
|
+
walkDescendants as walkDescendants2
|
|
6815
|
+
} from "@suss/extractor";
|
|
6766
6816
|
|
|
6767
6817
|
// src/stdlibNames.ts
|
|
6768
6818
|
function isStdlibModule(node, scope, module) {
|
|
@@ -6792,6 +6842,11 @@ var PYTHON_STREAM_RECOGNITION = "python-stdlib";
|
|
|
6792
6842
|
var STREAMS = /* @__PURE__ */ new Set(["stdout", "stderr"]);
|
|
6793
6843
|
var DEFERRED_BODY_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
6794
6844
|
function streamWriteEffects(root, module) {
|
|
6845
|
+
return numberRepeatedCallSites(
|
|
6846
|
+
writesUnder(root, module).map((write) => [write])
|
|
6847
|
+
).flat();
|
|
6848
|
+
}
|
|
6849
|
+
function writesUnder(root, module) {
|
|
6795
6850
|
const found = [];
|
|
6796
6851
|
const startScope = module.scopeFor.get(root.id) ?? module.moduleScope;
|
|
6797
6852
|
walkDescendants2(root, startScope, children, {
|
|
@@ -6801,7 +6856,7 @@ function streamWriteEffects(root, module) {
|
|
|
6801
6856
|
}
|
|
6802
6857
|
const write = streamWriteAt(node, scope);
|
|
6803
6858
|
if (write !== null) {
|
|
6804
|
-
found.push(write);
|
|
6859
|
+
found.push({ effect: write, at: node });
|
|
6805
6860
|
}
|
|
6806
6861
|
},
|
|
6807
6862
|
into: (node, scope) => {
|
|
@@ -6840,16 +6895,17 @@ function standardStream(node, scope) {
|
|
|
6840
6895
|
}
|
|
6841
6896
|
function writeEffect(site) {
|
|
6842
6897
|
const { call, callee, target } = site;
|
|
6843
|
-
|
|
6898
|
+
const effect = {
|
|
6844
6899
|
type: "interaction",
|
|
6845
6900
|
binding: ioBinding({ recognition: PYTHON_STREAM_RECOGNITION, target }),
|
|
6846
6901
|
callee,
|
|
6847
|
-
groupId: `${call.startPosition.row + 1}:${call.startPosition.column + 1}`,
|
|
6848
6902
|
interaction: {
|
|
6849
6903
|
class: "stream-write",
|
|
6850
6904
|
...payloadOf(site.positional, site.scope)
|
|
6851
|
-
}
|
|
6905
|
+
},
|
|
6906
|
+
location: rangeOf(call)
|
|
6852
6907
|
};
|
|
6908
|
+
return { ...effect, groupId: callSiteKey(effect) };
|
|
6853
6909
|
}
|
|
6854
6910
|
function payloadOf(args, scope) {
|
|
6855
6911
|
const only = args[0];
|
|
@@ -7710,7 +7766,8 @@ function buildRouteUnit(options) {
|
|
|
7710
7766
|
options.responseShape,
|
|
7711
7767
|
() => readReturnAnnotation(definitionNode, enclosingScope, ctx)
|
|
7712
7768
|
);
|
|
7713
|
-
const
|
|
7769
|
+
const calls = invocationSites(definitionNode, options.facts);
|
|
7770
|
+
const effects = calls.map((call) => call.effect);
|
|
7714
7771
|
const extra = recognizedBodyEffects(
|
|
7715
7772
|
definitionNode,
|
|
7716
7773
|
module,
|
|
@@ -7719,7 +7776,7 @@ function buildRouteUnit(options) {
|
|
|
7719
7776
|
);
|
|
7720
7777
|
const perTerminal = branchesPerTerminal({
|
|
7721
7778
|
definitionNode,
|
|
7722
|
-
effects,
|
|
7779
|
+
effects: calls,
|
|
7723
7780
|
responseStatusCalls: options.responseStatusCalls,
|
|
7724
7781
|
ctx: {
|
|
7725
7782
|
pattern,
|
|
@@ -7862,12 +7919,17 @@ function unreadRoleReadings(parameters, range) {
|
|
|
7862
7919
|
}
|
|
7863
7920
|
function recognizedBodyEffects(definitionNode, module, storageLookup, facts) {
|
|
7864
7921
|
const storage = storageLookup === void 0 ? { effects: [], slots: [] } : bodyStorage(definitionNode, storageLookup);
|
|
7922
|
+
const found = [
|
|
7923
|
+
...envReadEffects(definitionNode, module, facts),
|
|
7924
|
+
...storage.effects,
|
|
7925
|
+
...streamWriteEffects(definitionNode, module)
|
|
7926
|
+
];
|
|
7927
|
+
const siteOf2 = effectSitesIn(
|
|
7928
|
+
field(definitionNode, "body"),
|
|
7929
|
+
found.map((one) => one.at)
|
|
7930
|
+
);
|
|
7865
7931
|
return {
|
|
7866
|
-
effects:
|
|
7867
|
-
...envReadEffects(definitionNode, module, facts),
|
|
7868
|
-
...storage.effects,
|
|
7869
|
-
...streamWriteEffects(definitionNode, module)
|
|
7870
|
-
],
|
|
7932
|
+
effects: found.map(({ effect, at }) => ({ effect, site: siteOf2(at) })),
|
|
7871
7933
|
provenance: storage.slots.length === 0 || storageLookup === void 0 ? [] : slotProvenance(storage.slots, {
|
|
7872
7934
|
facts: storageLookup.facts,
|
|
7873
7935
|
unit: definitionNode
|
|
@@ -7875,12 +7937,13 @@ function recognizedBodyEffects(definitionNode, module, storageLookup, facts) {
|
|
|
7875
7937
|
};
|
|
7876
7938
|
}
|
|
7877
7939
|
function withBodyEffects(branch, extra) {
|
|
7878
|
-
|
|
7940
|
+
const effects = effectsFiringOn2(extra.effects, branch);
|
|
7941
|
+
if (effects.length === 0) {
|
|
7879
7942
|
return branch;
|
|
7880
7943
|
}
|
|
7881
7944
|
return {
|
|
7882
7945
|
...branch,
|
|
7883
|
-
extraEffects:
|
|
7946
|
+
extraEffects: effects,
|
|
7884
7947
|
...extra.provenance.length === 0 ? {} : { provenance: extra.provenance }
|
|
7885
7948
|
};
|
|
7886
7949
|
}
|
|
@@ -8315,6 +8378,33 @@ function buildPythonExtractionReport(args) {
|
|
|
8315
8378
|
});
|
|
8316
8379
|
}
|
|
8317
8380
|
|
|
8381
|
+
// src/reach/closure.ts
|
|
8382
|
+
import {
|
|
8383
|
+
functionCallBinding,
|
|
8384
|
+
placeArgTargets,
|
|
8385
|
+
placeCalleeParameters,
|
|
8386
|
+
placeCalls,
|
|
8387
|
+
placePossibleCalls,
|
|
8388
|
+
recordParameterGaps,
|
|
8389
|
+
StopList,
|
|
8390
|
+
sameDeclarations,
|
|
8391
|
+
TargetPlacements,
|
|
8392
|
+
unfollowedCallGap,
|
|
8393
|
+
worthRecording
|
|
8394
|
+
} from "@suss/behavioral-ir";
|
|
8395
|
+
import { Database, evaluate, lit, rule, variable as v } from "@suss/datalog";
|
|
8396
|
+
import {
|
|
8397
|
+
assembleSummary,
|
|
8398
|
+
SKIP_CHILDREN as SKIP_CHILDREN5,
|
|
8399
|
+
walkDescendants as walkDescendants6
|
|
8400
|
+
} from "@suss/extractor";
|
|
8401
|
+
import {
|
|
8402
|
+
keptVariants,
|
|
8403
|
+
noDependencies,
|
|
8404
|
+
plainKeyOf,
|
|
8405
|
+
variantKey
|
|
8406
|
+
} from "@suss/resolution";
|
|
8407
|
+
|
|
8318
8408
|
// src/exits.ts
|
|
8319
8409
|
import {
|
|
8320
8410
|
markReturnsAsExitCode,
|
|
@@ -8451,96 +8541,6 @@ function returnTerminal(shape, location) {
|
|
|
8451
8541
|
};
|
|
8452
8542
|
}
|
|
8453
8543
|
|
|
8454
|
-
// src/importedDefinitions.ts
|
|
8455
|
-
import { isObserved, noteKeyRead as noteKeyRead2 } from "@suss/resolution";
|
|
8456
|
-
function importedDefinitionLookup(db, files) {
|
|
8457
|
-
const fileOfModuleScope = /* @__PURE__ */ new Map();
|
|
8458
|
-
const byFile = /* @__PURE__ */ new Map();
|
|
8459
|
-
for (const file of files) {
|
|
8460
|
-
fileOfModuleScope.set(file.module.moduleScope.node.id, file.file);
|
|
8461
|
-
byFile.set(file.file, file);
|
|
8462
|
-
}
|
|
8463
|
-
const found = /* @__PURE__ */ new Map();
|
|
8464
|
-
return (scope, name) => {
|
|
8465
|
-
const fromFile = fileOfModuleScope.get(moduleScopeOf(scope).node.id);
|
|
8466
|
-
if (fromFile === void 0) {
|
|
8467
|
-
return null;
|
|
8468
|
-
}
|
|
8469
|
-
const key = `${fromFile}#${name}`;
|
|
8470
|
-
let definition = found.get(key);
|
|
8471
|
-
if (definition === void 0) {
|
|
8472
|
-
definition = definitionAmong(originsOf(db, key), byFile);
|
|
8473
|
-
found.set(key, definition);
|
|
8474
|
-
} else if (isObserved(db)) {
|
|
8475
|
-
originsOf(db, key);
|
|
8476
|
-
}
|
|
8477
|
-
if (definition !== null) {
|
|
8478
|
-
noteKeyRead2(db, definition.file);
|
|
8479
|
-
}
|
|
8480
|
-
return definition;
|
|
8481
|
-
};
|
|
8482
|
-
}
|
|
8483
|
-
function definitionAmong(origins, byFile) {
|
|
8484
|
-
for (const origin of origins) {
|
|
8485
|
-
const file = byFile.get(origin.module);
|
|
8486
|
-
const binding = file?.module.moduleScope.bindings.get(origin.name);
|
|
8487
|
-
if (file === void 0 || binding === void 0) {
|
|
8488
|
-
continue;
|
|
8489
|
-
}
|
|
8490
|
-
const node = definedNodeOf(binding);
|
|
8491
|
-
if (node !== null) {
|
|
8492
|
-
return {
|
|
8493
|
-
node,
|
|
8494
|
-
file: file.file,
|
|
8495
|
-
moduleScope: file.module.moduleScope,
|
|
8496
|
-
scopeFor: file.module.scopeFor
|
|
8497
|
-
};
|
|
8498
|
-
}
|
|
8499
|
-
}
|
|
8500
|
-
return null;
|
|
8501
|
-
}
|
|
8502
|
-
function definedNodeOf(binding) {
|
|
8503
|
-
if (binding.kind === "classDef") {
|
|
8504
|
-
return binding.node;
|
|
8505
|
-
}
|
|
8506
|
-
if (binding.kind === "assignment") {
|
|
8507
|
-
return binding.value;
|
|
8508
|
-
}
|
|
8509
|
-
return null;
|
|
8510
|
-
}
|
|
8511
|
-
|
|
8512
|
-
// src/moduleSurface.ts
|
|
8513
|
-
import { moduleExportBinding } from "@suss/behavioral-ir";
|
|
8514
|
-
import {
|
|
8515
|
-
MODULE_SURFACE_RECOGNITION,
|
|
8516
|
-
moduleOfFile,
|
|
8517
|
-
settleModules
|
|
8518
|
-
} from "@suss/extractor";
|
|
8519
|
-
import { noteKeyRead as noteKeyRead4 } from "@suss/resolution";
|
|
8520
|
-
|
|
8521
|
-
// src/reach/closure.ts
|
|
8522
|
-
import {
|
|
8523
|
-
functionCallBinding,
|
|
8524
|
-
placeArgTargets,
|
|
8525
|
-
placeCalleeParameters,
|
|
8526
|
-
placeCalls,
|
|
8527
|
-
placePossibleCalls,
|
|
8528
|
-
recordParameterGaps,
|
|
8529
|
-
StopList,
|
|
8530
|
-
TargetPlacements,
|
|
8531
|
-
unfollowedCallGap,
|
|
8532
|
-
worthRecording
|
|
8533
|
-
} from "@suss/behavioral-ir";
|
|
8534
|
-
import { Database, evaluate, lit, rule, variable as v } from "@suss/datalog";
|
|
8535
|
-
import {
|
|
8536
|
-
assembleSummary,
|
|
8537
|
-
SKIP_CHILDREN as SKIP_CHILDREN5,
|
|
8538
|
-
walkDescendants as walkDescendants6
|
|
8539
|
-
} from "@suss/extractor";
|
|
8540
|
-
import {
|
|
8541
|
-
noDependencies
|
|
8542
|
-
} from "@suss/resolution";
|
|
8543
|
-
|
|
8544
8544
|
// src/flags.ts
|
|
8545
8545
|
import { SKIP_CHILDREN as SKIP_CHILDREN4, walkDescendants as walkDescendants5 } from "@suss/extractor";
|
|
8546
8546
|
var PARSE_METHODS = /* @__PURE__ */ new Set(["parse_args", "parse_known_args"]);
|
|
@@ -8623,11 +8623,19 @@ function methodCalledOn(call) {
|
|
|
8623
8623
|
|
|
8624
8624
|
// src/reach/resolveCallee.ts
|
|
8625
8625
|
import {
|
|
8626
|
+
answersFor as answersFor2,
|
|
8626
8627
|
calleeOutcomeOf,
|
|
8627
8628
|
calleeOutcomes,
|
|
8628
8629
|
dispatchOutcomes,
|
|
8629
|
-
|
|
8630
|
+
fileOfKey,
|
|
8631
|
+
memberOf,
|
|
8632
|
+
nodeOfKey as nodeOfKey2,
|
|
8633
|
+
noteKeyRead as noteKeyRead2,
|
|
8630
8634
|
RECEIVER_STORE_NAME as RECEIVER_STORE_NAME2,
|
|
8635
|
+
resolutionProgram as resolutionProgram2,
|
|
8636
|
+
SELF_AS_CLASS_NAME as SELF_AS_CLASS_NAME2,
|
|
8637
|
+
selfFormOf,
|
|
8638
|
+
selfResultOf,
|
|
8631
8639
|
writtenSourcesOf
|
|
8632
8640
|
} from "@suss/resolution";
|
|
8633
8641
|
var STOP_FOR = {
|
|
@@ -8643,14 +8651,21 @@ var NO_DECLARATION = {
|
|
|
8643
8651
|
function calleeSpellings(calls, ctx) {
|
|
8644
8652
|
const spellingOf = /* @__PURE__ */ new Map();
|
|
8645
8653
|
const keys = /* @__PURE__ */ new Set();
|
|
8654
|
+
const receivers = /* @__PURE__ */ new Set();
|
|
8646
8655
|
for (const { call, site } of calls) {
|
|
8647
8656
|
const spelling = spellingFor2(call, site, ctx);
|
|
8648
8657
|
spellingOf.set(call.id, spelling);
|
|
8649
8658
|
if (spelling.kind === "key") {
|
|
8650
8659
|
keys.add(spelling.key);
|
|
8651
8660
|
}
|
|
8661
|
+
const receiver = receiverOf(call, site);
|
|
8662
|
+
if (receiver !== null) {
|
|
8663
|
+
receivers.add(receiver.key);
|
|
8664
|
+
}
|
|
8652
8665
|
}
|
|
8653
|
-
|
|
8666
|
+
const outcomes = calleeOutcomes(ctx.facts, [...keys]);
|
|
8667
|
+
resolveCalls(ctx.facts, [...receivers]);
|
|
8668
|
+
return { spellingOf, outcomes };
|
|
8654
8669
|
}
|
|
8655
8670
|
function resolveCallee2(call, site, ctx, read) {
|
|
8656
8671
|
const spelling = read?.spellingOf.get(call.id) ?? spellingFor2(call, site, ctx);
|
|
@@ -8658,10 +8673,100 @@ function resolveCallee2(call, site, ctx, read) {
|
|
|
8658
8673
|
return spelling;
|
|
8659
8674
|
}
|
|
8660
8675
|
const outcome = read?.outcomes.get(spelling.key) ?? calleeOutcomeOf(ctx.facts, spelling.key);
|
|
8661
|
-
|
|
8662
|
-
|
|
8676
|
+
const settled = selfCallInMixin(call, outcome, site, ctx) ? { kind: "stopped", reason: "selfCallInMixin" } : asCallee(outcome, site.owner, ctx);
|
|
8677
|
+
return onReceiverClass(call, site, ctx, settled) ?? settled;
|
|
8678
|
+
}
|
|
8679
|
+
function receiverOf(call, site) {
|
|
8680
|
+
const callee = readThrough(field(call, "function"));
|
|
8681
|
+
const object = callee?.type === "attribute" ? field(callee, "object") : null;
|
|
8682
|
+
const name = callee === null ? void 0 : field(callee, "attribute")?.text;
|
|
8683
|
+
if (object === null || name === void 0) {
|
|
8684
|
+
return null;
|
|
8685
|
+
}
|
|
8686
|
+
return {
|
|
8687
|
+
key: readKey(site.file.file, object, enclosingFunction(object)),
|
|
8688
|
+
name
|
|
8689
|
+
};
|
|
8690
|
+
}
|
|
8691
|
+
function onReceiverClass(call, site, ctx, settled) {
|
|
8692
|
+
const own = ownReceiverOf(site, ctx);
|
|
8693
|
+
const callee = readThrough(field(call, "function"));
|
|
8694
|
+
if (callee?.type === "identifier") {
|
|
8695
|
+
const calleeKey2 = readKey(
|
|
8696
|
+
site.file.file,
|
|
8697
|
+
callee,
|
|
8698
|
+
enclosingFunction(callee)
|
|
8699
|
+
);
|
|
8700
|
+
return own !== null && selfFormOf(ctx.facts, calleeKey2, own.key) === SELF_AS_CLASS_NAME2 ? methodOn(own.cls, CONSTRUCTOR_METHOD, ctx) : null;
|
|
8701
|
+
}
|
|
8702
|
+
const read = receiverOf(call, site);
|
|
8703
|
+
if (read === null) {
|
|
8704
|
+
return null;
|
|
8705
|
+
}
|
|
8706
|
+
if (own !== null && selfFormOf(ctx.facts, read.key, own.key) !== null) {
|
|
8707
|
+
return methodOn(own.cls, read.name, ctx);
|
|
8708
|
+
}
|
|
8709
|
+
const sentTo = classReturnedTo(read.key, own, ctx);
|
|
8710
|
+
if (sentTo !== null) {
|
|
8711
|
+
return methodOn(sentTo, read.name, ctx);
|
|
8712
|
+
}
|
|
8713
|
+
const receiverClass = settled.kind === "followed" ? onlyClassOf(read.key, ctx) : null;
|
|
8714
|
+
return receiverClass === null || settled.kind !== "followed" ? null : { kind: "followed", target: runningOn(settled.target, receiverClass) };
|
|
8715
|
+
}
|
|
8716
|
+
function ownReceiverOf(site, ctx) {
|
|
8717
|
+
const [row] = ctx.facts.lookup("selfReceiver", 0, site.owner);
|
|
8718
|
+
const cls = site.receiverClass ?? classOfFunction(site.owner, ctx);
|
|
8719
|
+
return row === void 0 || cls === null ? null : { key: String(row[1]), cls };
|
|
8720
|
+
}
|
|
8721
|
+
function classReturnedTo(key, own, ctx) {
|
|
8722
|
+
const returned = selfResultOf(ctx.facts, key);
|
|
8723
|
+
if (returned === null) {
|
|
8724
|
+
return null;
|
|
8725
|
+
}
|
|
8726
|
+
if (own !== null && returned.receiver === own.key) {
|
|
8727
|
+
return own.cls;
|
|
8663
8728
|
}
|
|
8664
|
-
|
|
8729
|
+
resolveCalls(ctx.facts, [returned.receiver]);
|
|
8730
|
+
return onlyClassOf(returned.receiver, ctx);
|
|
8731
|
+
}
|
|
8732
|
+
var CONSTRUCTOR_METHOD = "__init__";
|
|
8733
|
+
function methodOn(cls, name, ctx) {
|
|
8734
|
+
const key = memberOf(ctx.facts, cls.key, name, resolutionProgram2());
|
|
8735
|
+
const found = key === null ? null : functionCallee(key, ctx);
|
|
8736
|
+
if (found === null || found.kind !== "followed") {
|
|
8737
|
+
return null;
|
|
8738
|
+
}
|
|
8739
|
+
return { kind: "followed", target: runningOn(found.target, cls) };
|
|
8740
|
+
}
|
|
8741
|
+
function runningOn(target, cls) {
|
|
8742
|
+
const owner = ownerClassOf(target.node);
|
|
8743
|
+
if (owner === null || nodeId(target.file.file, owner) === cls.key) {
|
|
8744
|
+
return target;
|
|
8745
|
+
}
|
|
8746
|
+
return {
|
|
8747
|
+
...target,
|
|
8748
|
+
exportPath: [cls.name, target.name],
|
|
8749
|
+
receiverClass: cls
|
|
8750
|
+
};
|
|
8751
|
+
}
|
|
8752
|
+
function classOfFunction(functionKey2, ctx) {
|
|
8753
|
+
const node = ctx.definitions.get(functionKey2);
|
|
8754
|
+
const owner = node === void 0 ? null : ownerClassOf(node);
|
|
8755
|
+
return owner === null ? null : subclassAt(owner, fileOfKey(functionKey2));
|
|
8756
|
+
}
|
|
8757
|
+
function onlyClassOf(key, ctx) {
|
|
8758
|
+
const objects = answersFor2(ctx.facts, "wantedObjectOf", key);
|
|
8759
|
+
const [only] = objects;
|
|
8760
|
+
if (objects.length !== 1 || only === void 0) {
|
|
8761
|
+
return null;
|
|
8762
|
+
}
|
|
8763
|
+
const file = ctx.filesByPath.get(fileOfKey(only));
|
|
8764
|
+
const node = file === void 0 ? null : nodeOfKey2(/* @__PURE__ */ new Map([[file.file, file.root]]), only);
|
|
8765
|
+
return node?.type === "class_definition" ? subclassAt(node, file?.file ?? fileOfKey(only)) : null;
|
|
8766
|
+
}
|
|
8767
|
+
function subclassAt(cls, file) {
|
|
8768
|
+
const name = field(cls, "name")?.text;
|
|
8769
|
+
return name === void 0 ? null : { key: nodeId(file, cls), name, file };
|
|
8665
8770
|
}
|
|
8666
8771
|
function selfCallInMixin(call, outcome, site, ctx) {
|
|
8667
8772
|
if (outcome.kind !== "callerSupplied" || !outcome.key.startsWith(`${site.owner}#`)) {
|
|
@@ -8920,7 +9025,7 @@ function moduleNamed(from, module, relativeLevel, ctx) {
|
|
|
8920
9025
|
if (file === void 0) {
|
|
8921
9026
|
return null;
|
|
8922
9027
|
}
|
|
8923
|
-
|
|
9028
|
+
noteKeyRead2(ctx.facts, file.file);
|
|
8924
9029
|
return { kind: "module", file };
|
|
8925
9030
|
}
|
|
8926
9031
|
|
|
@@ -9018,7 +9123,10 @@ function reachedFunctions(seeds, options) {
|
|
|
9018
9123
|
passedPositions.add(position);
|
|
9019
9124
|
}
|
|
9020
9125
|
const called = [];
|
|
9021
|
-
|
|
9126
|
+
const calledHere = scan.followed.flatMap(
|
|
9127
|
+
(target) => target.receiverClass === void 0 ? [target] : [plainOf(target), target]
|
|
9128
|
+
);
|
|
9129
|
+
for (const target of calledHere) {
|
|
9022
9130
|
const calleeKey2 = keyOf2(target);
|
|
9023
9131
|
if (!functionByKey.has(calleeKey2)) {
|
|
9024
9132
|
functionByKey.set(calleeKey2, target);
|
|
@@ -9035,11 +9143,30 @@ function reachedFunctions(seeds, options) {
|
|
|
9035
9143
|
if (ledger === void 0) {
|
|
9036
9144
|
settleBodyValues(reached, functionByKey, options);
|
|
9037
9145
|
}
|
|
9146
|
+
const placementsOf = (key) => ({
|
|
9147
|
+
targets: targetsByKey.get(key),
|
|
9148
|
+
argTargets: argTargetsByKey.get(key),
|
|
9149
|
+
possibleTargets: possibleTargetsByKey.get(key)
|
|
9150
|
+
});
|
|
9151
|
+
const onSubclass = keptVariants(
|
|
9152
|
+
reached.flatMap(
|
|
9153
|
+
(key) => functionByKey.get(key)?.receiverClass === void 0 ? [] : [
|
|
9154
|
+
{
|
|
9155
|
+
key,
|
|
9156
|
+
differs: !sameDeclarations(
|
|
9157
|
+
placementsOf(key),
|
|
9158
|
+
placementsOf(plainKeyOf(key))
|
|
9159
|
+
),
|
|
9160
|
+
calls: callsByKey.get(key) ?? []
|
|
9161
|
+
}
|
|
9162
|
+
]
|
|
9163
|
+
)
|
|
9164
|
+
);
|
|
9038
9165
|
const summaries = [];
|
|
9039
9166
|
const summariesByKey = /* @__PURE__ */ new Map();
|
|
9040
9167
|
for (const key of reached) {
|
|
9041
9168
|
const target = functionByKey.get(key);
|
|
9042
|
-
if (target === void 0) {
|
|
9169
|
+
if (target === void 0 || target.receiverClass !== void 0 && !onSubclass.has(key)) {
|
|
9043
9170
|
continue;
|
|
9044
9171
|
}
|
|
9045
9172
|
const kept = replay?.summaryOf(key);
|
|
@@ -9054,6 +9181,9 @@ function reachedFunctions(seeds, options) {
|
|
|
9054
9181
|
const summary2 = assembleSummary(libraryUnit(target, options), {
|
|
9055
9182
|
gapHandling: options.gapHandling
|
|
9056
9183
|
});
|
|
9184
|
+
if (target.receiverClass !== void 0) {
|
|
9185
|
+
summary2.receiverClass = displayedClass(target.receiverClass, ctx);
|
|
9186
|
+
}
|
|
9057
9187
|
if (options.gapHandling !== "silent") {
|
|
9058
9188
|
summary2.gaps.push(
|
|
9059
9189
|
...(stopsByKey.get(key) ?? []).map(unfollowedCallGap)
|
|
@@ -9191,7 +9321,8 @@ function storedScan(scan) {
|
|
|
9191
9321
|
followed: scan.followed.map((target) => ({
|
|
9192
9322
|
key: keyOf2(target),
|
|
9193
9323
|
name: target.name,
|
|
9194
|
-
exportPath: target.exportPath
|
|
9324
|
+
exportPath: target.exportPath,
|
|
9325
|
+
...target.receiverClass === void 0 ? {} : { receiverClass: target.receiverClass }
|
|
9195
9326
|
})),
|
|
9196
9327
|
stops: scan.stops,
|
|
9197
9328
|
targets: [...scan.targets],
|
|
@@ -9224,14 +9355,25 @@ function scanFromStored(stored, functionFor) {
|
|
|
9224
9355
|
};
|
|
9225
9356
|
}
|
|
9226
9357
|
function keyOf2(target) {
|
|
9227
|
-
|
|
9358
|
+
const key = nodeId(target.file.file, target.node);
|
|
9359
|
+
return target.receiverClass === void 0 ? key : variantKey(key, target.receiverClass);
|
|
9360
|
+
}
|
|
9361
|
+
function plainOf(target) {
|
|
9362
|
+
return reachedFunctionOf(target.file, target.node);
|
|
9363
|
+
}
|
|
9364
|
+
function placeOf(target, ctx) {
|
|
9365
|
+
const place = { file: target.file.displayPath, span: spanOf(target.node) };
|
|
9366
|
+
return target.receiverClass === void 0 ? place : { ...place, receiverClass: displayedClass(target.receiverClass, ctx) };
|
|
9367
|
+
}
|
|
9368
|
+
function displayedClass(cls, ctx) {
|
|
9369
|
+
return {
|
|
9370
|
+
name: cls.name,
|
|
9371
|
+
file: ctx.filesByPath.get(cls.file)?.displayPath ?? cls.file
|
|
9372
|
+
};
|
|
9228
9373
|
}
|
|
9229
|
-
function placeCallee(placements, callee, outcome, call, file) {
|
|
9374
|
+
function placeCallee(placements, callee, outcome, call, file, ctx) {
|
|
9230
9375
|
if (outcome.kind === "followed") {
|
|
9231
|
-
placements.place(callee,
|
|
9232
|
-
file: outcome.target.file.displayPath,
|
|
9233
|
-
span: spanOf(outcome.target.node)
|
|
9234
|
-
});
|
|
9376
|
+
placements.place(callee, placeOf(outcome.target, ctx));
|
|
9235
9377
|
return;
|
|
9236
9378
|
}
|
|
9237
9379
|
if (outcome.reason === "noDeclaration" && !isMethodCall(call)) {
|
|
@@ -9259,9 +9401,13 @@ function bodyOf(source) {
|
|
|
9259
9401
|
}
|
|
9260
9402
|
return {
|
|
9261
9403
|
body,
|
|
9262
|
-
written: callsWritten(
|
|
9263
|
-
|
|
9264
|
-
|
|
9404
|
+
written: callsWritten(
|
|
9405
|
+
file,
|
|
9406
|
+
body,
|
|
9407
|
+
scopeAt2(file, node),
|
|
9408
|
+
{ owner: nodeId(file.file, node), receiverClass: source.receiverClass },
|
|
9409
|
+
{ descendsInto: isModule(node) ? runsAtModuleLoad : outsideNestedDef }
|
|
9410
|
+
)
|
|
9265
9411
|
};
|
|
9266
9412
|
}
|
|
9267
9413
|
function outsideNestedDef(node) {
|
|
@@ -9331,16 +9477,20 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9331
9477
|
followed.push(target);
|
|
9332
9478
|
}
|
|
9333
9479
|
};
|
|
9334
|
-
const recordPassedArgs = (call, callee,
|
|
9480
|
+
const recordPassedArgs = (call, callee, target) => {
|
|
9335
9481
|
const args = field(call, "arguments");
|
|
9336
9482
|
if (args === null) {
|
|
9337
9483
|
return;
|
|
9338
9484
|
}
|
|
9485
|
+
const calleeKeys = target === null ? [] : [keyOf2(target), keyOf2(plainOf(target))];
|
|
9486
|
+
const passes = (position) => {
|
|
9487
|
+
for (const calleeKey2 of calleeKeys) {
|
|
9488
|
+
passedPositions.add(`${calleeKey2}#${position}`);
|
|
9489
|
+
}
|
|
9490
|
+
};
|
|
9339
9491
|
children(args).forEach((arg, position) => {
|
|
9340
9492
|
if (arg.type === "lambda") {
|
|
9341
|
-
|
|
9342
|
-
passedPositions.add(`${calleeKey2}#${position}`);
|
|
9343
|
-
}
|
|
9493
|
+
passes(position);
|
|
9344
9494
|
return;
|
|
9345
9495
|
}
|
|
9346
9496
|
const nameKey2 = passedNameKeyOf(file, arg);
|
|
@@ -9352,23 +9502,15 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9352
9502
|
return;
|
|
9353
9503
|
}
|
|
9354
9504
|
follow(resolved);
|
|
9355
|
-
placements.placeArg(callee, position,
|
|
9356
|
-
|
|
9357
|
-
span: spanOf(resolved.node)
|
|
9358
|
-
});
|
|
9359
|
-
if (calleeKey2 !== null) {
|
|
9360
|
-
passedPositions.add(`${calleeKey2}#${position}`);
|
|
9361
|
-
}
|
|
9505
|
+
placements.placeArg(callee, position, placeOf(resolved, ctx));
|
|
9506
|
+
passes(position);
|
|
9362
9507
|
});
|
|
9363
9508
|
};
|
|
9364
9509
|
const recordPossible = (call, callee, dispatched) => {
|
|
9365
9510
|
dispatched.targets.forEach(follow);
|
|
9366
9511
|
placements.placePossible(
|
|
9367
9512
|
callee,
|
|
9368
|
-
dispatched.targets.map((target) => (
|
|
9369
|
-
file: target.file.displayPath,
|
|
9370
|
-
span: spanOf(target.node)
|
|
9371
|
-
}))
|
|
9513
|
+
dispatched.targets.map((target) => placeOf(target, ctx))
|
|
9372
9514
|
);
|
|
9373
9515
|
recordPassedArgs(call, callee, null);
|
|
9374
9516
|
if (dispatched.unresolved > 0 && !recognized.has(call.id)) {
|
|
@@ -9385,11 +9527,11 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9385
9527
|
return;
|
|
9386
9528
|
}
|
|
9387
9529
|
const outcome = only === void 0 ? settled : { kind: "followed", target: only };
|
|
9388
|
-
placeCallee(placements, callee, outcome, call, file);
|
|
9530
|
+
placeCallee(placements, callee, outcome, call, file, ctx);
|
|
9389
9531
|
recordPassedArgs(
|
|
9390
9532
|
call,
|
|
9391
9533
|
callee,
|
|
9392
|
-
outcome.kind === "followed" ?
|
|
9534
|
+
outcome.kind === "followed" ? outcome.target : null
|
|
9393
9535
|
);
|
|
9394
9536
|
if (outcome.kind === "stopped") {
|
|
9395
9537
|
if (!recognized.has(call.id) && worthRecording(outcome.reason)) {
|
|
@@ -9430,12 +9572,12 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9430
9572
|
passedPositions
|
|
9431
9573
|
};
|
|
9432
9574
|
}
|
|
9433
|
-
function callsWritten(file, body, outer,
|
|
9575
|
+
function callsWritten(file, body, outer, scanned, limit) {
|
|
9434
9576
|
const found = [];
|
|
9435
9577
|
walkDescendants6(body, outer, children, {
|
|
9436
9578
|
at: (child, scope) => {
|
|
9437
9579
|
if (child.type === "call") {
|
|
9438
|
-
found.push({ call: child, site: { file, scope,
|
|
9580
|
+
found.push({ call: child, site: { file, scope, ...scanned } });
|
|
9439
9581
|
}
|
|
9440
9582
|
},
|
|
9441
9583
|
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope : SKIP_CHILDREN5
|
|
@@ -9484,13 +9626,8 @@ function libraryUnit(target, options, binding = functionCallBinding({
|
|
|
9484
9626
|
file.module,
|
|
9485
9627
|
parameters.map((parameter) => parameter.name)
|
|
9486
9628
|
);
|
|
9487
|
-
const
|
|
9488
|
-
const branches = exitingBranches(
|
|
9489
|
-
node,
|
|
9490
|
-
file.module,
|
|
9491
|
-
effects,
|
|
9492
|
-
options.facts
|
|
9493
|
-
) ?? [
|
|
9629
|
+
const calls = invocationSites(node, options.facts);
|
|
9630
|
+
const branches = exitingBranches(node, file.module, calls, options.facts) ?? [
|
|
9494
9631
|
{
|
|
9495
9632
|
conditions: [],
|
|
9496
9633
|
terminal: {
|
|
@@ -9505,7 +9642,7 @@ function libraryUnit(target, options, binding = functionCallBinding({
|
|
|
9505
9642
|
emitEvent: null,
|
|
9506
9643
|
location: range
|
|
9507
9644
|
},
|
|
9508
|
-
effects,
|
|
9645
|
+
effects: calls.map((call) => call.effect),
|
|
9509
9646
|
location: range,
|
|
9510
9647
|
isDefault: true
|
|
9511
9648
|
}
|
|
@@ -9602,7 +9739,131 @@ function parameterName2(param) {
|
|
|
9602
9739
|
return identifiersUnder(param)[0] ?? null;
|
|
9603
9740
|
}
|
|
9604
9741
|
|
|
9742
|
+
// src/entryPoints.ts
|
|
9743
|
+
function declaredEntryUnits(file, packs, options) {
|
|
9744
|
+
const units = [];
|
|
9745
|
+
for (const pack of packs) {
|
|
9746
|
+
for (const entry of pack.entryPoints?.(file.file) ?? []) {
|
|
9747
|
+
const binding = file.module.moduleScope.bindings.get(entry.name);
|
|
9748
|
+
if (binding?.kind !== "functionDef") {
|
|
9749
|
+
continue;
|
|
9750
|
+
}
|
|
9751
|
+
for (const declared of entry.units) {
|
|
9752
|
+
const raw = libraryUnit(
|
|
9753
|
+
{
|
|
9754
|
+
file,
|
|
9755
|
+
node: binding.node,
|
|
9756
|
+
name: declared.name,
|
|
9757
|
+
exportPath: [entry.name]
|
|
9758
|
+
},
|
|
9759
|
+
options,
|
|
9760
|
+
declared.binding
|
|
9761
|
+
);
|
|
9762
|
+
units.push({
|
|
9763
|
+
...raw,
|
|
9764
|
+
identity: { ...raw.identity, kind: declared.kind },
|
|
9765
|
+
deployableUnit: declared.deployableUnit,
|
|
9766
|
+
...declared.metadata !== void 0 ? { packMetadata: declared.metadata } : {}
|
|
9767
|
+
});
|
|
9768
|
+
}
|
|
9769
|
+
}
|
|
9770
|
+
}
|
|
9771
|
+
return units;
|
|
9772
|
+
}
|
|
9773
|
+
|
|
9774
|
+
// src/importedDefinitions.ts
|
|
9775
|
+
import { isObserved, noteKeyRead as noteKeyRead3 } from "@suss/resolution";
|
|
9776
|
+
function importedDefinitionLookup(db, files) {
|
|
9777
|
+
const fileOfModuleScope = /* @__PURE__ */ new Map();
|
|
9778
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
9779
|
+
for (const file of files) {
|
|
9780
|
+
fileOfModuleScope.set(file.module.moduleScope.node.id, file.file);
|
|
9781
|
+
byFile.set(file.file, file);
|
|
9782
|
+
}
|
|
9783
|
+
const found = /* @__PURE__ */ new Map();
|
|
9784
|
+
return (scope, name) => {
|
|
9785
|
+
const fromFile = fileOfModuleScope.get(moduleScopeOf(scope).node.id);
|
|
9786
|
+
if (fromFile === void 0) {
|
|
9787
|
+
return null;
|
|
9788
|
+
}
|
|
9789
|
+
const key = `${fromFile}#${name}`;
|
|
9790
|
+
let definition = found.get(key);
|
|
9791
|
+
if (definition === void 0) {
|
|
9792
|
+
definition = definitionAmong(originsOf(db, key), byFile);
|
|
9793
|
+
found.set(key, definition);
|
|
9794
|
+
} else if (isObserved(db)) {
|
|
9795
|
+
originsOf(db, key);
|
|
9796
|
+
}
|
|
9797
|
+
if (definition !== null) {
|
|
9798
|
+
noteKeyRead3(db, definition.file);
|
|
9799
|
+
}
|
|
9800
|
+
return definition;
|
|
9801
|
+
};
|
|
9802
|
+
}
|
|
9803
|
+
function definitionAmong(origins, byFile) {
|
|
9804
|
+
for (const origin of origins) {
|
|
9805
|
+
const file = byFile.get(origin.module);
|
|
9806
|
+
const binding = file?.module.moduleScope.bindings.get(origin.name);
|
|
9807
|
+
if (file === void 0 || binding === void 0) {
|
|
9808
|
+
continue;
|
|
9809
|
+
}
|
|
9810
|
+
const node = definedNodeOf(binding);
|
|
9811
|
+
if (node !== null) {
|
|
9812
|
+
return {
|
|
9813
|
+
node,
|
|
9814
|
+
file: file.file,
|
|
9815
|
+
moduleScope: file.module.moduleScope,
|
|
9816
|
+
scopeFor: file.module.scopeFor
|
|
9817
|
+
};
|
|
9818
|
+
}
|
|
9819
|
+
}
|
|
9820
|
+
return null;
|
|
9821
|
+
}
|
|
9822
|
+
function definedNodeOf(binding) {
|
|
9823
|
+
if (binding.kind === "classDef") {
|
|
9824
|
+
return binding.node;
|
|
9825
|
+
}
|
|
9826
|
+
if (binding.kind === "assignment") {
|
|
9827
|
+
return binding.value;
|
|
9828
|
+
}
|
|
9829
|
+
return null;
|
|
9830
|
+
}
|
|
9831
|
+
|
|
9832
|
+
// src/libraryEnvReads.ts
|
|
9833
|
+
import { libraryEnvReadMarker } from "@suss/extractor";
|
|
9834
|
+
function libraryEnvReadMarkers(files, packs) {
|
|
9835
|
+
const markers = [];
|
|
9836
|
+
for (const pack of packs) {
|
|
9837
|
+
for (const declared of pack.libraryEnvVars ?? []) {
|
|
9838
|
+
const importer = files.find(
|
|
9839
|
+
(file) => importsModule(file, declared.module)
|
|
9840
|
+
);
|
|
9841
|
+
if (importer !== void 0) {
|
|
9842
|
+
markers.push(
|
|
9843
|
+
libraryEnvReadMarker(pack.name, declared, importer.displayPath)
|
|
9844
|
+
);
|
|
9845
|
+
}
|
|
9846
|
+
}
|
|
9847
|
+
}
|
|
9848
|
+
return markers;
|
|
9849
|
+
}
|
|
9850
|
+
function importsModule(file, prefix) {
|
|
9851
|
+
for (const binding of file.module.moduleScope.bindings.values()) {
|
|
9852
|
+
if ((binding.kind === "import" || binding.kind === "importFrom") && binding.relativeLevel === 0 && binding.module.startsWith(prefix)) {
|
|
9853
|
+
return true;
|
|
9854
|
+
}
|
|
9855
|
+
}
|
|
9856
|
+
return false;
|
|
9857
|
+
}
|
|
9858
|
+
|
|
9605
9859
|
// src/moduleSurface.ts
|
|
9860
|
+
import { moduleExportBinding } from "@suss/behavioral-ir";
|
|
9861
|
+
import {
|
|
9862
|
+
MODULE_SURFACE_RECOGNITION,
|
|
9863
|
+
moduleOfFile,
|
|
9864
|
+
settleModules
|
|
9865
|
+
} from "@suss/extractor";
|
|
9866
|
+
import { noteKeyRead as noteKeyRead4 } from "@suss/resolution";
|
|
9606
9867
|
function settlePythonModules(modules) {
|
|
9607
9868
|
return settleModules(modules, ["__init__.py"]);
|
|
9608
9869
|
}
|
|
@@ -9690,7 +9951,13 @@ function exportsOf(file, node, exportName) {
|
|
|
9690
9951
|
}
|
|
9691
9952
|
|
|
9692
9953
|
// src/reuse.ts
|
|
9693
|
-
import {
|
|
9954
|
+
import {
|
|
9955
|
+
EntryReuse,
|
|
9956
|
+
fileOfKey as fileOfKey2,
|
|
9957
|
+
noteLookup as noteLookup2,
|
|
9958
|
+
plainKeyOf as plainKeyOf2,
|
|
9959
|
+
variantKey as variantKey2
|
|
9960
|
+
} from "@suss/resolution";
|
|
9694
9961
|
function seedsOfRecord(record) {
|
|
9695
9962
|
return [
|
|
9696
9963
|
...record.module.seedKey === null ? [] : [record.module.seedKey],
|
|
@@ -9703,9 +9970,20 @@ function pythonEntryReuse(records, changedFiles, changes) {
|
|
|
9703
9970
|
return new EntryReuse(records, changedFiles, changes, seedsOfRecord);
|
|
9704
9971
|
}
|
|
9705
9972
|
function storedFunction(target, definitions, filesByPath) {
|
|
9706
|
-
const
|
|
9707
|
-
const
|
|
9708
|
-
|
|
9973
|
+
const plainKey = plainKeyOf2(target.key);
|
|
9974
|
+
const node = definitions.get(plainKey);
|
|
9975
|
+
const file = filesByPath.get(fileOfKey2(target.key));
|
|
9976
|
+
const key = target.receiverClass === void 0 ? plainKey : variantKey2(plainKey, target.receiverClass);
|
|
9977
|
+
if (node === void 0 || file === void 0 || key !== target.key) {
|
|
9978
|
+
return null;
|
|
9979
|
+
}
|
|
9980
|
+
const found = {
|
|
9981
|
+
file,
|
|
9982
|
+
node,
|
|
9983
|
+
name: target.name,
|
|
9984
|
+
exportPath: target.exportPath
|
|
9985
|
+
};
|
|
9986
|
+
return target.receiverClass === void 0 ? found : { ...found, receiverClass: target.receiverClass };
|
|
9709
9987
|
}
|
|
9710
9988
|
var WalkReplay = class {
|
|
9711
9989
|
constructor(reuse, definitions, filesByPath) {
|
|
@@ -12486,7 +12764,7 @@ function unitAround(target, pattern, reading, options) {
|
|
|
12486
12764
|
});
|
|
12487
12765
|
const continuations = reading.continuations;
|
|
12488
12766
|
const terminals = bodyTerminals(body, raised, continuations);
|
|
12489
|
-
const effects =
|
|
12767
|
+
const effects = invocationSites(node, options.facts);
|
|
12490
12768
|
const extra = recognizedBodyEffects(
|
|
12491
12769
|
node,
|
|
12492
12770
|
file.module,
|
|
@@ -12821,7 +13099,9 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12821
13099
|
const sqlClients = options.packs.flatMap((pack) => pack.sqlClients ?? []);
|
|
12822
13100
|
const modelQueries = options.packs.flatMap((pack) => pack.models ?? []);
|
|
12823
13101
|
const declaredModules = settlePythonModules(options.modules);
|
|
12824
|
-
const discovers = declaredModules.length > 0 || options.packs.some(
|
|
13102
|
+
const discovers = declaredModules.length > 0 || options.packs.some(
|
|
13103
|
+
(pack) => pack.discovery.length > 0 || pack.entryPoints !== void 0
|
|
13104
|
+
);
|
|
12825
13105
|
const buildsReceivers = options.packs.some(
|
|
12826
13106
|
(pack) => (pack.clients ?? []).some(
|
|
12827
13107
|
(client) => (client.receiverConstructors ?? []).length > 0
|
|
@@ -12984,6 +13264,10 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12984
13264
|
facts: db,
|
|
12985
13265
|
storageFor
|
|
12986
13266
|
}),
|
|
13267
|
+
...declaredEntryUnits(boundFile, options.packs, {
|
|
13268
|
+
facts: db,
|
|
13269
|
+
storageFor
|
|
13270
|
+
}),
|
|
12987
13271
|
...tests === null ? [] : tests.unitsIn(boundFile, { storageFor, facts: db })
|
|
12988
13272
|
];
|
|
12989
13273
|
const charge = noDependencies2();
|
|
@@ -13093,7 +13377,10 @@ async function runPython(options, roots, cache, previous) {
|
|
|
13093
13377
|
}
|
|
13094
13378
|
const loadTimeReads = record !== void 0 && discoveries.get(file) === record ? null : timer.time(
|
|
13095
13379
|
"discover",
|
|
13096
|
-
() => charged(
|
|
13380
|
+
() => charged(
|
|
13381
|
+
file,
|
|
13382
|
+
() => envReadEffects(root, moduleBinding, db).map((one) => one.effect)
|
|
13383
|
+
)
|
|
13097
13384
|
);
|
|
13098
13385
|
const moduleKey = nodeId(file, root);
|
|
13099
13386
|
if (!summariesBySeed.has(moduleKey)) {
|
|
@@ -13196,6 +13483,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
13196
13483
|
});
|
|
13197
13484
|
}
|
|
13198
13485
|
summaries.push(...reached.summaries);
|
|
13486
|
+
summaries.push(...libraryEnvReadMarkers(bound, options.packs));
|
|
13199
13487
|
const spend = underQuestionSpend(db);
|
|
13200
13488
|
const overBudget = spend.abandoned + spend.skipped > 0;
|
|
13201
13489
|
if (overBudget && reuse !== null) {
|