@suss/adapter-python 0.34.1 → 0.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +551 -81
- package/dist/index.d.cts +43 -3
- package/dist/index.d.ts +43 -3
- package/dist/index.js +560 -81
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -985,10 +985,14 @@ function objectReturnedBy(db, callKey) {
|
|
|
985
985
|
|
|
986
986
|
// src/facts/values.ts
|
|
987
987
|
import {
|
|
988
|
+
addEntryRows,
|
|
989
|
+
addTemplateRows,
|
|
988
990
|
NAMED_STORE_NAME,
|
|
989
991
|
RECEIVER_STORE_NAME,
|
|
992
|
+
SPREAD_ENTRY,
|
|
990
993
|
startsAtName,
|
|
991
994
|
UNPLACED_STORE_NAME,
|
|
995
|
+
VALUE_ENTRY,
|
|
992
996
|
valueLeftByWrites,
|
|
993
997
|
writesRunInOrder
|
|
994
998
|
} from "@suss/resolution";
|
|
@@ -999,6 +1003,8 @@ var CONVERTING_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
999
1003
|
"str",
|
|
1000
1004
|
"float"
|
|
1001
1005
|
]);
|
|
1006
|
+
var ATTRIBUTE_GETTER = "getattr";
|
|
1007
|
+
var POSITION_COUNTER = "enumerate";
|
|
1002
1008
|
|
|
1003
1009
|
// src/facts/values.ts
|
|
1004
1010
|
function nodeId(filePath, node) {
|
|
@@ -1170,8 +1176,7 @@ function emitConversion(emitter, call, callKey) {
|
|
|
1170
1176
|
return;
|
|
1171
1177
|
}
|
|
1172
1178
|
const name = callee.text;
|
|
1173
|
-
|
|
1174
|
-
if (builtin) {
|
|
1179
|
+
if (isBuiltin(emitter, name)) {
|
|
1175
1180
|
add(emitter, "converts", callKey, valueKey(emitter, first.node), name);
|
|
1176
1181
|
}
|
|
1177
1182
|
}
|
|
@@ -1220,6 +1225,7 @@ function emitSequence(emitter, sequence) {
|
|
|
1220
1225
|
const objectKey = nodeId(emitter.filePath, sequence);
|
|
1221
1226
|
add(emitter, "objectValue", objectKey);
|
|
1222
1227
|
let position = 0;
|
|
1228
|
+
const entries = [];
|
|
1223
1229
|
for (const element of children(sequence)) {
|
|
1224
1230
|
add(
|
|
1225
1231
|
emitter,
|
|
@@ -1229,12 +1235,21 @@ function emitSequence(emitter, sequence) {
|
|
|
1229
1235
|
valueKey(emitter, element)
|
|
1230
1236
|
);
|
|
1231
1237
|
position += 1;
|
|
1238
|
+
if (element.type !== "comment") {
|
|
1239
|
+
entries.push(writtenEntry(emitter, element));
|
|
1240
|
+
}
|
|
1232
1241
|
}
|
|
1242
|
+
addEntryRows(rowsOf(emitter), objectKey, entries);
|
|
1233
1243
|
}
|
|
1234
1244
|
function emitDictionary(emitter, dictionary) {
|
|
1235
1245
|
const objectKey = nodeId(emitter.filePath, dictionary);
|
|
1236
1246
|
add(emitter, "objectValue", objectKey);
|
|
1247
|
+
const entries = [];
|
|
1237
1248
|
for (const pair of children(dictionary)) {
|
|
1249
|
+
if (SPREAD_TYPES.has(pair.type)) {
|
|
1250
|
+
entries.push(writtenEntry(emitter, pair));
|
|
1251
|
+
continue;
|
|
1252
|
+
}
|
|
1238
1253
|
if (pair.type !== "pair") {
|
|
1239
1254
|
continue;
|
|
1240
1255
|
}
|
|
@@ -1243,6 +1258,7 @@ function emitDictionary(emitter, dictionary) {
|
|
|
1243
1258
|
if (key === null || value === null) {
|
|
1244
1259
|
continue;
|
|
1245
1260
|
}
|
|
1261
|
+
entries.push(writtenEntry(emitter, value));
|
|
1246
1262
|
if (key.type !== "string") {
|
|
1247
1263
|
add(emitter, "holdsUnderKey", objectKey, valueKey(emitter, value));
|
|
1248
1264
|
continue;
|
|
@@ -1255,6 +1271,15 @@ function emitDictionary(emitter, dictionary) {
|
|
|
1255
1271
|
valueKey(emitter, value)
|
|
1256
1272
|
);
|
|
1257
1273
|
}
|
|
1274
|
+
addEntryRows(rowsOf(emitter), objectKey, entries);
|
|
1275
|
+
}
|
|
1276
|
+
var SPREAD_TYPES = /* @__PURE__ */ new Set(["list_splat", "dictionary_splat"]);
|
|
1277
|
+
function writtenEntry(emitter, entry) {
|
|
1278
|
+
const unpacked = SPREAD_TYPES.has(entry.type) ? children(entry)[0] : void 0;
|
|
1279
|
+
return unpacked === void 0 ? { key: valueKey(emitter, entry), form: VALUE_ENTRY } : { key: valueKey(emitter, unpacked), form: SPREAD_ENTRY };
|
|
1280
|
+
}
|
|
1281
|
+
function rowsOf(emitter) {
|
|
1282
|
+
return (relation, row) => add(emitter, relation, ...row);
|
|
1258
1283
|
}
|
|
1259
1284
|
function emitAttribute(emitter, attribute) {
|
|
1260
1285
|
const object = field(attribute, "object");
|
|
@@ -1319,13 +1344,50 @@ function emitKeyedRead(emitter, site, container, key) {
|
|
|
1319
1344
|
if (WRITTEN_KEY_TYPES.has(key.type)) {
|
|
1320
1345
|
return;
|
|
1321
1346
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1347
|
+
const siteKey = nodeId(emitter.filePath, site);
|
|
1348
|
+
const containerKey = valueKey(emitter, container);
|
|
1349
|
+
add(emitter, "readsKeyed", siteKey, containerKey, valueKey(emitter, key));
|
|
1350
|
+
add(emitter, "choosesEntry", siteKey, containerKey);
|
|
1351
|
+
}
|
|
1352
|
+
function emitAttributeChoice(emitter, call) {
|
|
1353
|
+
const callee = field(call, "function");
|
|
1354
|
+
const [target, name] = callArguments(call);
|
|
1355
|
+
if (callee?.type !== "identifier" || callee.text !== ATTRIBUTE_GETTER || !isBuiltin(emitter, callee.text) || target?.kind !== "positional" || name?.kind !== "positional") {
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
const siteKey = nodeId(emitter.filePath, call);
|
|
1359
|
+
const targetKey = valueKey(emitter, target.node);
|
|
1360
|
+
const written = plainStringOf(name.node);
|
|
1361
|
+
if (written !== null) {
|
|
1362
|
+
add(emitter, "choosesNamedEntry", siteKey, targetKey, written);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
const ends = writtenEnds(name.node);
|
|
1366
|
+
if (ends === null) {
|
|
1367
|
+
add(emitter, "choosesEntry", siteKey, targetKey);
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
add(emitter, "choosesEntryLike", siteKey, targetKey, ends.start, ends.end);
|
|
1371
|
+
}
|
|
1372
|
+
function writtenEnds(node) {
|
|
1373
|
+
if (node.type !== "string") {
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
const parts = children(node).filter(
|
|
1377
|
+
(part) => part.type !== "string_start" && part.type !== "string_end"
|
|
1328
1378
|
);
|
|
1379
|
+
const written = (part) => part.type === "string_content";
|
|
1380
|
+
const firstComputed = parts.findIndex((part) => !written(part));
|
|
1381
|
+
if (firstComputed === -1) {
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1384
|
+
const lastComputed = parts.length - 1 - [...parts].reverse().findIndex((part) => !written(part));
|
|
1385
|
+
const start = parts.slice(0, firstComputed).map((part) => part.text).join("");
|
|
1386
|
+
const end = parts.slice(lastComputed + 1).map((part) => part.text).join("");
|
|
1387
|
+
return start === "" && end === "" ? null : { start, end };
|
|
1388
|
+
}
|
|
1389
|
+
function isBuiltin(emitter, name) {
|
|
1390
|
+
return nameKey(emitter.filePath, emitter.enclosing, name) === nameId(emitter.filePath, name) && !emitter.moduleNames().has(name);
|
|
1329
1391
|
}
|
|
1330
1392
|
function emitWrittenKeyRead(emitter, site, container, key) {
|
|
1331
1393
|
const name = plainStringOf(key);
|
|
@@ -1461,6 +1523,86 @@ function emitComprehensionElement(emitter, comprehension) {
|
|
|
1461
1523
|
);
|
|
1462
1524
|
}
|
|
1463
1525
|
}
|
|
1526
|
+
var PAIR_TARGET_TYPES = /* @__PURE__ */ new Set(["pattern_list", "tuple_pattern"]);
|
|
1527
|
+
function emitElementVariables(emitter, clause) {
|
|
1528
|
+
const target = field(clause, "left");
|
|
1529
|
+
const over = field(clause, "right");
|
|
1530
|
+
if (target === null || over === null) {
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
const names = PAIR_TARGET_TYPES.has(target.type) ? children(target) : [];
|
|
1534
|
+
const [position, element] = names;
|
|
1535
|
+
const counted = countedCollection(emitter, over);
|
|
1536
|
+
if (counted !== null && names.length === 2 && position?.type === "identifier" && element !== void 0) {
|
|
1537
|
+
emitElementTaken(emitter, element, valueKey(emitter, counted), position);
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
emitElementTaken(emitter, target, valueKey(emitter, over), null);
|
|
1541
|
+
}
|
|
1542
|
+
function emitElementTaken(emitter, target, overKey, position) {
|
|
1543
|
+
const variables = target.type === "identifier" ? [{ node: target, part: null }] : partsTakenApart(target);
|
|
1544
|
+
for (const variable of variables) {
|
|
1545
|
+
const key = valueKey(emitter, variable.node);
|
|
1546
|
+
if (variable.part === null) {
|
|
1547
|
+
add(emitter, "elementOf", key, overKey);
|
|
1548
|
+
continue;
|
|
1549
|
+
}
|
|
1550
|
+
add(emitter, "elementPartOf", key, overKey, variable.part);
|
|
1551
|
+
}
|
|
1552
|
+
const [first] = variables;
|
|
1553
|
+
if (position !== null && first !== void 0) {
|
|
1554
|
+
add(
|
|
1555
|
+
emitter,
|
|
1556
|
+
"positionOf",
|
|
1557
|
+
valueKey(emitter, position),
|
|
1558
|
+
valueKey(emitter, first.node)
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
function partsTakenApart(target) {
|
|
1563
|
+
const parts = [];
|
|
1564
|
+
if (!PAIR_TARGET_TYPES.has(target.type)) {
|
|
1565
|
+
return parts;
|
|
1566
|
+
}
|
|
1567
|
+
for (const [position, part] of children(target).entries()) {
|
|
1568
|
+
if (part.type === "list_splat_pattern") {
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
if (part.type === "identifier") {
|
|
1572
|
+
parts.push({ node: part, part: String(position) });
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return parts;
|
|
1576
|
+
}
|
|
1577
|
+
function countedCollection(emitter, over) {
|
|
1578
|
+
const callee = over.type === "call" ? field(over, "function") : null;
|
|
1579
|
+
const args = field(over, "arguments");
|
|
1580
|
+
const [first] = callArguments(over);
|
|
1581
|
+
if (callee?.type !== "identifier" || callee.text !== POSITION_COUNTER || !isBuiltin(emitter, POSITION_COUNTER) || args === null || writtenArgumentCount(args) !== 1 || first?.kind !== "positional") {
|
|
1582
|
+
return null;
|
|
1583
|
+
}
|
|
1584
|
+
return first.node;
|
|
1585
|
+
}
|
|
1586
|
+
function interpolatedPieces(emitter, string2) {
|
|
1587
|
+
const parts = children(string2);
|
|
1588
|
+
if (!parts.some((part) => part.type === "interpolation")) {
|
|
1589
|
+
return [];
|
|
1590
|
+
}
|
|
1591
|
+
return parts.flatMap((part) => {
|
|
1592
|
+
if (part.type === "string_content") {
|
|
1593
|
+
return [{ text: stringContentValue(part) }];
|
|
1594
|
+
}
|
|
1595
|
+
const expression = part.type === "interpolation" ? field(part, "expression") ?? children(part)[0] : void 0;
|
|
1596
|
+
return expression === void 0 ? [] : [{ hole: valueKey(emitter, expression) }];
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
function adjacentPieces(emitter, joined2) {
|
|
1600
|
+
return children(joined2).filter((part) => part.type !== "comment").map((part) => ({ hole: valueKey(emitter, part) }));
|
|
1601
|
+
}
|
|
1602
|
+
var TEMPLATE_PIECES = {
|
|
1603
|
+
string: interpolatedPieces,
|
|
1604
|
+
concatenated_string: adjacentPieces
|
|
1605
|
+
};
|
|
1464
1606
|
function emitExpressionFact(emitter, child, type) {
|
|
1465
1607
|
if (type === "call") {
|
|
1466
1608
|
emitCall(emitter, child);
|
|
@@ -1468,6 +1610,7 @@ function emitExpressionFact(emitter, child, type) {
|
|
|
1468
1610
|
if (mapping !== null) {
|
|
1469
1611
|
emitKeyedRead(emitter, child, mapping.container, mapping.key);
|
|
1470
1612
|
}
|
|
1613
|
+
emitAttributeChoice(emitter, child);
|
|
1471
1614
|
}
|
|
1472
1615
|
if (type === "subscript") {
|
|
1473
1616
|
const index = singleSubscript(child);
|
|
@@ -1497,6 +1640,13 @@ function emitExpressionFact(emitter, child, type) {
|
|
|
1497
1640
|
if (COMPREHENSION_TYPES.has(type)) {
|
|
1498
1641
|
emitComprehensionElement(emitter, child);
|
|
1499
1642
|
}
|
|
1643
|
+
if (type === "for_in_clause") {
|
|
1644
|
+
emitElementVariables(emitter, child);
|
|
1645
|
+
}
|
|
1646
|
+
const pieces = TEMPLATE_PIECES[type]?.(emitter, child) ?? [];
|
|
1647
|
+
if (pieces.length > 0) {
|
|
1648
|
+
addTemplateRows(rowsOf(emitter), nodeId(emitter.filePath, child), pieces);
|
|
1649
|
+
}
|
|
1500
1650
|
const branches = fallbackBranchesOf(child, type);
|
|
1501
1651
|
if (branches !== null) {
|
|
1502
1652
|
for (const branch of branches) {
|
|
@@ -2015,6 +2165,9 @@ function readUnderName(emitter, statement, funcKey, accessed) {
|
|
|
2015
2165
|
function emitNestedDefinitions(emitter, node) {
|
|
2016
2166
|
for (const child of children(node)) {
|
|
2017
2167
|
const type = child.type;
|
|
2168
|
+
if (type === "decorated_definition") {
|
|
2169
|
+
emitDecoratorCalls(emitter, child);
|
|
2170
|
+
}
|
|
2018
2171
|
if (FUNCTION_TYPES.has(type)) {
|
|
2019
2172
|
emitFunctionFacts(emitter, child);
|
|
2020
2173
|
if (emitter.enclosing !== null) {
|
|
@@ -2034,6 +2187,20 @@ function emitNestedDefinitions(emitter, node) {
|
|
|
2034
2187
|
emitNestedDefinitions(emitter, child);
|
|
2035
2188
|
}
|
|
2036
2189
|
}
|
|
2190
|
+
function emitDecoratorCalls(emitter, decorated) {
|
|
2191
|
+
const { definition, decorators } = stripDecorators(decorated);
|
|
2192
|
+
let applied = nodeId(emitter.filePath, definition);
|
|
2193
|
+
for (const decorator of [...decorators].reverse()) {
|
|
2194
|
+
const [expression] = children(decorator);
|
|
2195
|
+
if (expression === void 0) {
|
|
2196
|
+
continue;
|
|
2197
|
+
}
|
|
2198
|
+
const callKey = nodeId(emitter.filePath, decorator);
|
|
2199
|
+
add(emitter, "call", callKey, valueKey(emitter, expression));
|
|
2200
|
+
add(emitter, "callArg", callKey, "0", applied);
|
|
2201
|
+
applied = callKey;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2037
2204
|
var readingsByTree = /* @__PURE__ */ new WeakMap();
|
|
2038
2205
|
function scopeReadingOf(fn, given) {
|
|
2039
2206
|
const tree = fn.tree;
|
|
@@ -4771,13 +4938,37 @@ function modelColumn(node) {
|
|
|
4771
4938
|
}
|
|
4772
4939
|
return field(node, "attribute")?.text ?? null;
|
|
4773
4940
|
}
|
|
4774
|
-
function selectorOf(chain, valueMethods) {
|
|
4941
|
+
function selectorOf(chain, valueMethods, model) {
|
|
4942
|
+
const picking = laterCalls(chain).filter(
|
|
4943
|
+
(call) => !valueMethods.includes(methodNameOf(call))
|
|
4944
|
+
);
|
|
4775
4945
|
return [
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4946
|
+
.../* @__PURE__ */ new Set([
|
|
4947
|
+
...picking.flatMap((call) => pickedBy(call).map((one) => one.name)),
|
|
4948
|
+
...model === null ? [] : picking.flatMap((call) => columnsComparedBy(call, model))
|
|
4949
|
+
])
|
|
4779
4950
|
];
|
|
4780
4951
|
}
|
|
4952
|
+
var COMBINED_TESTS = ["and_", "or_", "not_"];
|
|
4953
|
+
function columnsComparedBy(call, model) {
|
|
4954
|
+
const args = field(call, "arguments");
|
|
4955
|
+
return (args === null ? [] : children(args)).flatMap(
|
|
4956
|
+
(argument) => columnsCompared(argument, model)
|
|
4957
|
+
);
|
|
4958
|
+
}
|
|
4959
|
+
function columnsCompared(node, model) {
|
|
4960
|
+
if (node.type === "call" && COMBINED_TESTS.includes(methodNameOf(node))) {
|
|
4961
|
+
return columnsComparedBy(node, model);
|
|
4962
|
+
}
|
|
4963
|
+
if (node.type !== "comparison_operator") {
|
|
4964
|
+
return [];
|
|
4965
|
+
}
|
|
4966
|
+
return children(node).flatMap((side) => {
|
|
4967
|
+
const object = side.type === "attribute" ? field(side, "object") : null;
|
|
4968
|
+
const column = object?.text === model ? field(side, "attribute") : null;
|
|
4969
|
+
return column === null ? [] : [column.text];
|
|
4970
|
+
});
|
|
4971
|
+
}
|
|
4781
4972
|
var TABLE_METHODS = ["select_from", "join"];
|
|
4782
4973
|
function modelOf(chain, options) {
|
|
4783
4974
|
const fromRoot = modelArgument(chain.root, chain.root, options);
|
|
@@ -4842,14 +5033,15 @@ function isClassName(name) {
|
|
|
4842
5033
|
}
|
|
4843
5034
|
function effectFor2(pattern, chain, operation, options) {
|
|
4844
5035
|
const valueMethods = pattern.valueMethods ?? [];
|
|
4845
|
-
const
|
|
5036
|
+
const model = modelOf(chain, options);
|
|
5037
|
+
const picked = selectorOf(chain, valueMethods, model);
|
|
4846
5038
|
const effect = {
|
|
4847
5039
|
type: "interaction",
|
|
4848
5040
|
binding: storageBinding2({
|
|
4849
5041
|
recognition: "python-storage",
|
|
4850
5042
|
storageSystem: pattern.storageSystem,
|
|
4851
5043
|
scope: "default",
|
|
4852
|
-
container:
|
|
5044
|
+
container: model
|
|
4853
5045
|
}),
|
|
4854
5046
|
callee: chain.last.text,
|
|
4855
5047
|
interaction: {
|
|
@@ -6580,7 +6772,7 @@ function isStdlibModule(node, scope, module) {
|
|
|
6580
6772
|
const binding = resolveName(scope, node.text);
|
|
6581
6773
|
return binding?.kind === "import" && binding.module === module && binding.relativeLevel === 0;
|
|
6582
6774
|
}
|
|
6583
|
-
function
|
|
6775
|
+
function isBuiltin2(node, scope, name) {
|
|
6584
6776
|
return node.type === "identifier" && node.text === name && resolveName(scope, name) === null;
|
|
6585
6777
|
}
|
|
6586
6778
|
function isStdlibMember(node, scope, module, name) {
|
|
@@ -6628,7 +6820,7 @@ function streamWriteAt(call, scope) {
|
|
|
6628
6820
|
}
|
|
6629
6821
|
const written = callArguments(call);
|
|
6630
6822
|
const positional = written.filter((argument) => argument.kind === "positional").map((argument) => argument.node);
|
|
6631
|
-
if (callee.type === "identifier" &&
|
|
6823
|
+
if (callee.type === "identifier" && isBuiltin2(callee, scope, "print")) {
|
|
6632
6824
|
const file = written.find(
|
|
6633
6825
|
(argument) => argument.kind === "keyword" && argument.name === "file"
|
|
6634
6826
|
);
|
|
@@ -8068,6 +8260,7 @@ import {
|
|
|
8068
8260
|
placeArgTargets as placeArgTargets2,
|
|
8069
8261
|
placeCalleeParameters as placeCalleeParameters2,
|
|
8070
8262
|
placeCalls as placeCalls2,
|
|
8263
|
+
placePossibleCalls as placePossibleCalls2,
|
|
8071
8264
|
recordParameterGaps as recordParameterGaps2,
|
|
8072
8265
|
summaryIdFromParts,
|
|
8073
8266
|
unfollowedCallGap as unfollowedCallGap2
|
|
@@ -8079,10 +8272,12 @@ import {
|
|
|
8079
8272
|
createCacheLayer,
|
|
8080
8273
|
createTimer,
|
|
8081
8274
|
effectToIR,
|
|
8275
|
+
extractionCacheDirFor,
|
|
8082
8276
|
extractionConfigStamp,
|
|
8083
8277
|
KeptParses,
|
|
8084
8278
|
moduleInitStructure,
|
|
8085
8279
|
noopTimer,
|
|
8280
|
+
ownersWhereWritten,
|
|
8086
8281
|
runDigest,
|
|
8087
8282
|
stampModuleImports,
|
|
8088
8283
|
stampModules
|
|
@@ -8163,12 +8358,12 @@ function exitSiteAt(statement, scope) {
|
|
|
8163
8358
|
return endsTheProcess(callee, scope) ? { statement, code, raised: false } : null;
|
|
8164
8359
|
}
|
|
8165
8360
|
if (statement.type === "raise_statement") {
|
|
8166
|
-
return
|
|
8361
|
+
return isBuiltin2(callee, scope, "SystemExit") ? { statement, code, raised: true } : null;
|
|
8167
8362
|
}
|
|
8168
8363
|
return null;
|
|
8169
8364
|
}
|
|
8170
8365
|
function endsTheProcess(callee, scope) {
|
|
8171
|
-
return isStdlibMember(callee, scope, "sys", "exit") ||
|
|
8366
|
+
return isStdlibMember(callee, scope, "sys", "exit") || isBuiltin2(callee, scope, "exit") || isBuiltin2(callee, scope, "quit");
|
|
8172
8367
|
}
|
|
8173
8368
|
function firstArgument(call) {
|
|
8174
8369
|
return callArguments(call).find(
|
|
@@ -8329,6 +8524,7 @@ import {
|
|
|
8329
8524
|
placeArgTargets,
|
|
8330
8525
|
placeCalleeParameters,
|
|
8331
8526
|
placeCalls,
|
|
8527
|
+
placePossibleCalls,
|
|
8332
8528
|
recordParameterGaps,
|
|
8333
8529
|
StopList,
|
|
8334
8530
|
TargetPlacements,
|
|
@@ -8429,6 +8625,7 @@ function methodCalledOn(call) {
|
|
|
8429
8625
|
import {
|
|
8430
8626
|
calleeOutcomeOf,
|
|
8431
8627
|
calleeOutcomes,
|
|
8628
|
+
dispatchOutcomes,
|
|
8432
8629
|
noteKeyRead as noteKeyRead3,
|
|
8433
8630
|
RECEIVER_STORE_NAME as RECEIVER_STORE_NAME2,
|
|
8434
8631
|
writtenSourcesOf
|
|
@@ -8498,6 +8695,40 @@ function instancesHaveAttribute(facts, classKey, name) {
|
|
|
8498
8695
|
function namedOutcomes(keys, ctx) {
|
|
8499
8696
|
return calleeOutcomes(ctx.facts, [...new Set(keys)]);
|
|
8500
8697
|
}
|
|
8698
|
+
function dispatchedCalls(calls, ctx) {
|
|
8699
|
+
const byKey = new Map(
|
|
8700
|
+
calls.map(({ call, site }) => [nodeId(site.file.file, call), call])
|
|
8701
|
+
);
|
|
8702
|
+
const found = /* @__PURE__ */ new Map();
|
|
8703
|
+
for (const [key, outcome] of dispatchOutcomes(ctx.facts, [...byKey.keys()])) {
|
|
8704
|
+
const call = byKey.get(key);
|
|
8705
|
+
if (call === void 0) {
|
|
8706
|
+
continue;
|
|
8707
|
+
}
|
|
8708
|
+
const targets = /* @__PURE__ */ new Map();
|
|
8709
|
+
for (const fn of outcome.functions) {
|
|
8710
|
+
for (const target of reachedThrough(fn, outcome.through, ctx)) {
|
|
8711
|
+
targets.set(nodeId(target.file.file, target.node), target);
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
8714
|
+
found.set(call.id, {
|
|
8715
|
+
targets: [...targets.values()],
|
|
8716
|
+
certain: outcome.certain && outcome.functions.every((fn) => !isLambda(fn, ctx)),
|
|
8717
|
+
unresolved: outcome.unresolved
|
|
8718
|
+
});
|
|
8719
|
+
}
|
|
8720
|
+
return found;
|
|
8721
|
+
}
|
|
8722
|
+
function reachedThrough(key, through, ctx) {
|
|
8723
|
+
const keys = isLambda(key, ctx) ? through.get(key) ?? [] : [key];
|
|
8724
|
+
return keys.flatMap((one) => {
|
|
8725
|
+
const target = isLambda(one, ctx) ? null : functionAt(one, ctx);
|
|
8726
|
+
return target === null ? [] : [target];
|
|
8727
|
+
});
|
|
8728
|
+
}
|
|
8729
|
+
function isLambda(key, ctx) {
|
|
8730
|
+
return ctx.definitions.get(key)?.type === "lambda";
|
|
8731
|
+
}
|
|
8501
8732
|
function functionNamed(nameKey2, ctx, read) {
|
|
8502
8733
|
if (assignedElsewhere(ctx.facts, nameKey2)) {
|
|
8503
8734
|
return null;
|
|
@@ -8716,6 +8947,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8716
8947
|
const targetsByKey = /* @__PURE__ */ new Map();
|
|
8717
8948
|
const stopsByKey = /* @__PURE__ */ new Map();
|
|
8718
8949
|
const argTargetsByKey = /* @__PURE__ */ new Map();
|
|
8950
|
+
const possibleTargetsByKey = /* @__PURE__ */ new Map();
|
|
8719
8951
|
const parameterCallsByKey = /* @__PURE__ */ new Map();
|
|
8720
8952
|
const callsByKey = /* @__PURE__ */ new Map();
|
|
8721
8953
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
@@ -8778,6 +9010,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8778
9010
|
}
|
|
8779
9011
|
targetsByKey.set(key, scan.targets);
|
|
8780
9012
|
argTargetsByKey.set(key, scan.argTargets);
|
|
9013
|
+
possibleTargetsByKey.set(key, scan.possibleTargets);
|
|
8781
9014
|
if (scan.parameterCalls.length > 0) {
|
|
8782
9015
|
parameterCallsByKey.set(key, scan.parameterCalls);
|
|
8783
9016
|
}
|
|
@@ -8828,6 +9061,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8828
9061
|
}
|
|
8829
9062
|
placeCalls(summary2, targetsByKey.get(key));
|
|
8830
9063
|
placeArgTargets(summary2, argTargetsByKey.get(key));
|
|
9064
|
+
placePossibleCalls(summary2, possibleTargetsByKey.get(key));
|
|
8831
9065
|
placeCalleeParameters(summary2, parameterCallsByKey.get(key));
|
|
8832
9066
|
return summary2;
|
|
8833
9067
|
};
|
|
@@ -8851,6 +9085,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8851
9085
|
targetsByKey,
|
|
8852
9086
|
stopsByKey,
|
|
8853
9087
|
argTargetsByKey,
|
|
9088
|
+
possibleTargetsByKey,
|
|
8854
9089
|
parameterCallsByKey,
|
|
8855
9090
|
callsByKey,
|
|
8856
9091
|
passedPositions,
|
|
@@ -8874,24 +9109,42 @@ function chargeOf(charges, key) {
|
|
|
8874
9109
|
}
|
|
8875
9110
|
return charge;
|
|
8876
9111
|
}
|
|
9112
|
+
function dispatchedAmong(written, spellings, ctx) {
|
|
9113
|
+
return dispatchedCalls(
|
|
9114
|
+
written.filter(({ call, site }) => {
|
|
9115
|
+
if (!ENTRY_CALLEE_TYPES.has(field(call, "function")?.type ?? "")) {
|
|
9116
|
+
return false;
|
|
9117
|
+
}
|
|
9118
|
+
const outcome = resolveCallee2(call, site, ctx, spellings);
|
|
9119
|
+
return outcome.kind === "stopped" && outcome.reason !== "callerSupplied";
|
|
9120
|
+
}),
|
|
9121
|
+
ctx
|
|
9122
|
+
);
|
|
9123
|
+
}
|
|
9124
|
+
var ENTRY_CALLEE_TYPES = /* @__PURE__ */ new Set(["subscript", "call", "identifier"]);
|
|
8877
9125
|
function batchedReads(round, ctx) {
|
|
8878
9126
|
const bodies = round.flatMap(
|
|
8879
9127
|
(entry) => "source" in entry ? [{ key: entry.key, source: entry.source, ...bodyOf(entry.source) }] : []
|
|
8880
9128
|
);
|
|
8881
|
-
const
|
|
8882
|
-
|
|
8883
|
-
ctx
|
|
8884
|
-
);
|
|
9129
|
+
const written = bodies.flatMap((body) => body.written);
|
|
9130
|
+
const spellings = calleeSpellings(written, ctx);
|
|
8885
9131
|
const passed = namedOutcomes(
|
|
8886
9132
|
bodies.flatMap(
|
|
8887
|
-
({ source, written }) =>
|
|
9133
|
+
({ source, written: written2 }) => written2.flatMap(({ call }) => passedNameKeys(source.file, call))
|
|
8888
9134
|
),
|
|
8889
9135
|
ctx
|
|
8890
9136
|
);
|
|
9137
|
+
const dispatched = dispatchedAmong(written, spellings, ctx);
|
|
8891
9138
|
return new Map(
|
|
8892
9139
|
bodies.map((body) => [
|
|
8893
9140
|
body.key,
|
|
8894
|
-
{
|
|
9141
|
+
{
|
|
9142
|
+
body: body.body,
|
|
9143
|
+
written: body.written,
|
|
9144
|
+
spellings,
|
|
9145
|
+
passed,
|
|
9146
|
+
dispatched
|
|
9147
|
+
}
|
|
8895
9148
|
])
|
|
8896
9149
|
);
|
|
8897
9150
|
}
|
|
@@ -8922,13 +9175,15 @@ function scanOnce(source, key, ctx, options, read, charges) {
|
|
|
8922
9175
|
}
|
|
8923
9176
|
function ownReads(source, ctx) {
|
|
8924
9177
|
const body = bodyOf(source);
|
|
9178
|
+
const spellings = calleeSpellings(body.written, ctx);
|
|
8925
9179
|
return {
|
|
8926
9180
|
...body,
|
|
8927
|
-
spellings
|
|
9181
|
+
spellings,
|
|
8928
9182
|
passed: namedOutcomes(
|
|
8929
9183
|
body.written.flatMap(({ call }) => passedNameKeys(source.file, call)),
|
|
8930
9184
|
ctx
|
|
8931
|
-
)
|
|
9185
|
+
),
|
|
9186
|
+
dispatched: dispatchedAmong(body.written, spellings, ctx)
|
|
8932
9187
|
};
|
|
8933
9188
|
}
|
|
8934
9189
|
function storedScan(scan) {
|
|
@@ -8944,6 +9199,10 @@ function storedScan(scan) {
|
|
|
8944
9199
|
callee,
|
|
8945
9200
|
[...byPosition]
|
|
8946
9201
|
]),
|
|
9202
|
+
possibleTargets: [...scan.possibleTargets].map(([callee, places]) => [
|
|
9203
|
+
callee,
|
|
9204
|
+
[...places]
|
|
9205
|
+
]),
|
|
8947
9206
|
parameterCalls: [...scan.parameterCalls],
|
|
8948
9207
|
passedPositions: [...scan.passedPositions]
|
|
8949
9208
|
};
|
|
@@ -8959,6 +9218,7 @@ function scanFromStored(stored, functionFor) {
|
|
|
8959
9218
|
new Map(byPosition)
|
|
8960
9219
|
])
|
|
8961
9220
|
),
|
|
9221
|
+
possibleTargets: new Map(stored.possibleTargets),
|
|
8962
9222
|
parameterCalls: stored.parameterCalls,
|
|
8963
9223
|
passedPositions: new Set(stored.passedPositions)
|
|
8964
9224
|
};
|
|
@@ -8987,6 +9247,7 @@ var EMPTY_SCAN = {
|
|
|
8987
9247
|
stops: [],
|
|
8988
9248
|
targets: /* @__PURE__ */ new Map(),
|
|
8989
9249
|
argTargets: /* @__PURE__ */ new Map(),
|
|
9250
|
+
possibleTargets: /* @__PURE__ */ new Map(),
|
|
8990
9251
|
parameterCalls: [],
|
|
8991
9252
|
passedPositions: /* @__PURE__ */ new Set()
|
|
8992
9253
|
};
|
|
@@ -9063,12 +9324,25 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9063
9324
|
return EMPTY_SCAN;
|
|
9064
9325
|
}
|
|
9065
9326
|
const ownParameters = callParameterNames(node, source.exportPath.length > 1);
|
|
9327
|
+
const follow = (target) => {
|
|
9328
|
+
const key = keyOf2(target);
|
|
9329
|
+
if (!seen.has(key)) {
|
|
9330
|
+
seen.add(key);
|
|
9331
|
+
followed.push(target);
|
|
9332
|
+
}
|
|
9333
|
+
};
|
|
9066
9334
|
const recordPassedArgs = (call, callee, calleeKey2) => {
|
|
9067
9335
|
const args = field(call, "arguments");
|
|
9068
9336
|
if (args === null) {
|
|
9069
9337
|
return;
|
|
9070
9338
|
}
|
|
9071
9339
|
children(args).forEach((arg, position) => {
|
|
9340
|
+
if (arg.type === "lambda") {
|
|
9341
|
+
if (calleeKey2 !== null) {
|
|
9342
|
+
passedPositions.add(`${calleeKey2}#${position}`);
|
|
9343
|
+
}
|
|
9344
|
+
return;
|
|
9345
|
+
}
|
|
9072
9346
|
const nameKey2 = passedNameKeyOf(file, arg);
|
|
9073
9347
|
if (nameKey2 === null) {
|
|
9074
9348
|
return;
|
|
@@ -9077,11 +9351,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9077
9351
|
if (resolved === null) {
|
|
9078
9352
|
return;
|
|
9079
9353
|
}
|
|
9080
|
-
|
|
9081
|
-
if (!seen.has(key)) {
|
|
9082
|
-
seen.add(key);
|
|
9083
|
-
followed.push(resolved);
|
|
9084
|
-
}
|
|
9354
|
+
follow(resolved);
|
|
9085
9355
|
placements.placeArg(callee, position, {
|
|
9086
9356
|
file: resolved.file.displayPath,
|
|
9087
9357
|
span: spanOf(resolved.node)
|
|
@@ -9091,9 +9361,30 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9091
9361
|
}
|
|
9092
9362
|
});
|
|
9093
9363
|
};
|
|
9364
|
+
const recordPossible = (call, callee, dispatched) => {
|
|
9365
|
+
dispatched.targets.forEach(follow);
|
|
9366
|
+
placements.placePossible(
|
|
9367
|
+
callee,
|
|
9368
|
+
dispatched.targets.map((target) => ({
|
|
9369
|
+
file: target.file.displayPath,
|
|
9370
|
+
span: spanOf(target.node)
|
|
9371
|
+
}))
|
|
9372
|
+
);
|
|
9373
|
+
recordPassedArgs(call, callee, null);
|
|
9374
|
+
if (dispatched.unresolved > 0 && !recognized.has(call.id)) {
|
|
9375
|
+
stops.add({ callee, reason: "unsettledValue" });
|
|
9376
|
+
}
|
|
9377
|
+
};
|
|
9094
9378
|
const record = (call, site) => {
|
|
9095
9379
|
const callee = calleeText(call);
|
|
9096
|
-
const
|
|
9380
|
+
const settled = resolveCallee2(call, site, ctx, spellings);
|
|
9381
|
+
const dispatched = settled.kind === "stopped" ? read.dispatched.get(call.id) : void 0;
|
|
9382
|
+
const [only] = dispatched?.targets ?? [];
|
|
9383
|
+
if (dispatched !== void 0 && only !== void 0 && !dispatched.certain) {
|
|
9384
|
+
recordPossible(call, callee, dispatched);
|
|
9385
|
+
return;
|
|
9386
|
+
}
|
|
9387
|
+
const outcome = only === void 0 ? settled : { kind: "followed", target: only };
|
|
9097
9388
|
placeCallee(placements, callee, outcome, call, file);
|
|
9098
9389
|
recordPassedArgs(
|
|
9099
9390
|
call,
|
|
@@ -9117,11 +9408,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9117
9408
|
}
|
|
9118
9409
|
return;
|
|
9119
9410
|
}
|
|
9120
|
-
|
|
9121
|
-
if (!seen.has(key)) {
|
|
9122
|
-
seen.add(key);
|
|
9123
|
-
followed.push(outcome.target);
|
|
9124
|
-
}
|
|
9411
|
+
follow(outcome.target);
|
|
9125
9412
|
};
|
|
9126
9413
|
for (const { call, site } of written) {
|
|
9127
9414
|
record(call, site);
|
|
@@ -9131,17 +9418,14 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
9131
9418
|
file: target.file.displayPath,
|
|
9132
9419
|
span: spanOf(target.node)
|
|
9133
9420
|
});
|
|
9134
|
-
|
|
9135
|
-
if (!seen.has(key)) {
|
|
9136
|
-
seen.add(key);
|
|
9137
|
-
followed.push(target);
|
|
9138
|
-
}
|
|
9421
|
+
follow(target);
|
|
9139
9422
|
}
|
|
9140
9423
|
return {
|
|
9141
9424
|
followed,
|
|
9142
9425
|
stops: stops.stops,
|
|
9143
9426
|
targets: placements.targets,
|
|
9144
9427
|
argTargets: placements.argTargets,
|
|
9428
|
+
possibleTargets: placements.possibleTargets,
|
|
9145
9429
|
parameterCalls,
|
|
9146
9430
|
passedPositions
|
|
9147
9431
|
};
|
|
@@ -9465,6 +9749,10 @@ var PackPositions = class {
|
|
|
9465
9749
|
const [packAt, patternAt] = id.split("/").map(Number);
|
|
9466
9750
|
return this.packs[packAt ?? -1]?.discovery[patternAt ?? -1];
|
|
9467
9751
|
}
|
|
9752
|
+
packOf(id) {
|
|
9753
|
+
const [packAt] = id.split("/").map(Number);
|
|
9754
|
+
return this.packs[packAt ?? -1];
|
|
9755
|
+
}
|
|
9468
9756
|
formAt(at) {
|
|
9469
9757
|
const pack = this.packs[at[0]];
|
|
9470
9758
|
const pattern = pack?.discovery[at[1]];
|
|
@@ -11559,7 +11847,10 @@ var PythonWrapperIndex = class {
|
|
|
11559
11847
|
/** By wrapper reference: the parameters a dependency function declares, and its file. */
|
|
11560
11848
|
dependencyParameterTable = /* @__PURE__ */ new Map();
|
|
11561
11849
|
unitsByFile = /* @__PURE__ */ new Map();
|
|
11562
|
-
/**
|
|
11850
|
+
/**
|
|
11851
|
+
* Told about every registration, a pack's form or a project decorator's
|
|
11852
|
+
* closure, so a cache can repeat the ones a file's discovery made.
|
|
11853
|
+
*/
|
|
11563
11854
|
onRegistered = null;
|
|
11564
11855
|
/**
|
|
11565
11856
|
* The same lookup `wrappersFor` noted under `id`, made again over this
|
|
@@ -11640,6 +11931,25 @@ var PythonWrapperIndex = class {
|
|
|
11640
11931
|
}
|
|
11641
11932
|
return { reference, form: declared.form };
|
|
11642
11933
|
}
|
|
11934
|
+
/**
|
|
11935
|
+
* The unit for the closure a project's decorator hands back, built once
|
|
11936
|
+
* however many routes the decorator is written on. Its name is what
|
|
11937
|
+
* calling the decorator writes, since the decorator may have a summary
|
|
11938
|
+
* of its own under its name.
|
|
11939
|
+
*/
|
|
11940
|
+
registeredClosure(target, closure) {
|
|
11941
|
+
this.onRegistered?.(target, closure);
|
|
11942
|
+
const span = spanOf(target.node);
|
|
11943
|
+
const key = `${target.file.file}:${span.start}-${span.end}`;
|
|
11944
|
+
if (!this.unitsByKey.has(key)) {
|
|
11945
|
+
const unit = closureUnit(target, closure, this.options);
|
|
11946
|
+
this.unitsByKey.set(key, unit);
|
|
11947
|
+
const inFile = this.unitsByFile.get(target.file.file) ?? [];
|
|
11948
|
+
inFile.push(unit);
|
|
11949
|
+
this.unitsByFile.set(target.file.file, inFile);
|
|
11950
|
+
}
|
|
11951
|
+
return { file: target.file.displayPath, name: target.name };
|
|
11952
|
+
}
|
|
11643
11953
|
/**
|
|
11644
11954
|
* The parameters the dependencies among these wrappers declare, and
|
|
11645
11955
|
* whether one is declared through a parameter source such as `Query()`.
|
|
@@ -11671,9 +11981,13 @@ var PythonWrapperIndex = class {
|
|
|
11671
11981
|
pattern: query.pattern,
|
|
11672
11982
|
form
|
|
11673
11983
|
}));
|
|
11674
|
-
if (file === void 0
|
|
11984
|
+
if (file === void 0) {
|
|
11675
11985
|
return [];
|
|
11676
11986
|
}
|
|
11987
|
+
const decorators = this.decoratorLayers(query, file);
|
|
11988
|
+
if (forms.length === 0) {
|
|
11989
|
+
return decorators;
|
|
11990
|
+
}
|
|
11677
11991
|
const own = this.ownRoutesOf(query);
|
|
11678
11992
|
const found = [
|
|
11679
11993
|
...this.noted(
|
|
@@ -11711,7 +12025,68 @@ var PythonWrapperIndex = class {
|
|
|
11711
12025
|
seen.add(key);
|
|
11712
12026
|
ordered.push(wrapper.reference);
|
|
11713
12027
|
}
|
|
11714
|
-
return
|
|
12028
|
+
return [
|
|
12029
|
+
...ordered.filter((one) => one.onThrow !== true),
|
|
12030
|
+
...decorators,
|
|
12031
|
+
...ordered.filter((one) => one.onThrow === true)
|
|
12032
|
+
];
|
|
12033
|
+
}
|
|
12034
|
+
/**
|
|
12035
|
+
* The decorators written on the route's function below the one that
|
|
12036
|
+
* registers it, outermost first. Each wraps the function the library
|
|
12037
|
+
* calls. None has a summary: a library's has no body in the run, and a
|
|
12038
|
+
* project's own is not composed into the route yet, so a project
|
|
12039
|
+
* decorator goes by what calling it writes, `require_admin(fn)`, which
|
|
12040
|
+
* no summary is named. The decorators the packs read, such as the
|
|
12041
|
+
* route's own and the namespace's `@ns.doc`, are left out.
|
|
12042
|
+
*/
|
|
12043
|
+
decoratorLayers(query, file) {
|
|
12044
|
+
const decorated = query.definitionNode.parent;
|
|
12045
|
+
if (decorated === null || decorated.type !== "decorated_definition") {
|
|
12046
|
+
return [];
|
|
12047
|
+
}
|
|
12048
|
+
const written = stripDecorators(decorated).decorators;
|
|
12049
|
+
const routeAt = written.findIndex(
|
|
12050
|
+
(decorator) => sameRange(rangeOf(decorator), query.classification.range)
|
|
12051
|
+
);
|
|
12052
|
+
return written.slice(routeAt + 1).flatMap((decorator) => this.decoratorLayer(decorator, query, file));
|
|
12053
|
+
}
|
|
12054
|
+
decoratorLayer(decorator, query, file) {
|
|
12055
|
+
const facts = this.options.facts;
|
|
12056
|
+
const direct = classifyDecorator(decorator, query.module, facts);
|
|
12057
|
+
const written = decoratorCallee(decorator);
|
|
12058
|
+
if (written === null || direct.module !== null && readByAPack(direct.module, this.options) || direct.objectName !== null && direct.objectName === query.classification.objectName || unwrapDecorator(decorator, facts) !== null) {
|
|
12059
|
+
return [];
|
|
12060
|
+
}
|
|
12061
|
+
const project = written.type === "identifier" ? this.functionCalled(file.file, written.text) : null;
|
|
12062
|
+
if (project !== null) {
|
|
12063
|
+
if (facts !== void 0) {
|
|
12064
|
+
noteKeyRead6(facts, project.file.file);
|
|
12065
|
+
}
|
|
12066
|
+
return [this.projectDecoratorLayer(project, query)];
|
|
12067
|
+
}
|
|
12068
|
+
return [{ file: direct.module ?? file.displayPath, name: written.text }];
|
|
12069
|
+
}
|
|
12070
|
+
/**
|
|
12071
|
+
* The layer a project's own decorator puts around the route. When it
|
|
12072
|
+
* hands back a closure written inside it that returns what calling the
|
|
12073
|
+
* function it was given returns, the closure is summarized and
|
|
12074
|
+
* composed into the route. Any other decorator, including one whose
|
|
12075
|
+
* closure keeps going after that call, goes by the same name with no
|
|
12076
|
+
* summary behind it.
|
|
12077
|
+
*/
|
|
12078
|
+
projectDecoratorLayer(decorator, query) {
|
|
12079
|
+
const continuation = parameterNamesOf(decorator.node)[0] ?? "";
|
|
12080
|
+
const name = `${decorator.name}(${continuation})`;
|
|
12081
|
+
const closure = closureReturnedBy(decorator.node);
|
|
12082
|
+
const handsOn = closure === null || continuation === "" ? [] : callsThrough(closure, continuation);
|
|
12083
|
+
if (closure === null || handsOn.length === 0 || !handsOn.every((statement) => returnsCallTo(statement, continuation))) {
|
|
12084
|
+
return { file: decorator.file.displayPath, name };
|
|
12085
|
+
}
|
|
12086
|
+
return this.registeredClosure(
|
|
12087
|
+
{ file: decorator.file, node: closure, name, exportPath: [] },
|
|
12088
|
+
{ pack: query.pack, pattern: query.pattern, continuation }
|
|
12089
|
+
);
|
|
11715
12090
|
}
|
|
11716
12091
|
/**
|
|
11717
12092
|
* What the mounts above the route's router register on the way down:
|
|
@@ -11872,6 +12247,21 @@ var PythonWrapperIndex = class {
|
|
|
11872
12247
|
function referenceKey(reference) {
|
|
11873
12248
|
return `${reference.file}::${reference.name}`;
|
|
11874
12249
|
}
|
|
12250
|
+
function readByAPack(module, options) {
|
|
12251
|
+
return options.packs.some(
|
|
12252
|
+
(pack) => pack.discovery.some((pattern) => pattern.importModule.includes(module))
|
|
12253
|
+
);
|
|
12254
|
+
}
|
|
12255
|
+
function decoratorCallee(decorator) {
|
|
12256
|
+
const written = decorator.namedChild(0);
|
|
12257
|
+
if (written === null) {
|
|
12258
|
+
return null;
|
|
12259
|
+
}
|
|
12260
|
+
return written.type === "call" ? field(written, "function") : written;
|
|
12261
|
+
}
|
|
12262
|
+
function sameRange(a, b) {
|
|
12263
|
+
return a.start === b.start && a.end === b.end;
|
|
12264
|
+
}
|
|
11875
12265
|
function parameterNamesOf(definition) {
|
|
11876
12266
|
return children(field(definition, "parameters")).flatMap((parameter) => {
|
|
11877
12267
|
const named = parameterNameAndType(parameter);
|
|
@@ -12059,16 +12449,42 @@ function parameterDependencies(definitionNode, form) {
|
|
|
12059
12449
|
return names;
|
|
12060
12450
|
}
|
|
12061
12451
|
function wrapperUnit(target, declared, options) {
|
|
12452
|
+
return unitAround(
|
|
12453
|
+
target,
|
|
12454
|
+
declared.pattern,
|
|
12455
|
+
{
|
|
12456
|
+
continuations: continuationStatements(target.node, declared.form),
|
|
12457
|
+
continuationName: null,
|
|
12458
|
+
form: declared.form,
|
|
12459
|
+
nameKind: "binding"
|
|
12460
|
+
},
|
|
12461
|
+
options
|
|
12462
|
+
);
|
|
12463
|
+
}
|
|
12464
|
+
function closureUnit(target, closure, options) {
|
|
12465
|
+
return unitAround(
|
|
12466
|
+
target,
|
|
12467
|
+
closure.pattern,
|
|
12468
|
+
{
|
|
12469
|
+
continuations: callsThrough(target.node, closure.continuation),
|
|
12470
|
+
continuationName: closure.continuation,
|
|
12471
|
+
form: null,
|
|
12472
|
+
nameKind: "label"
|
|
12473
|
+
},
|
|
12474
|
+
options
|
|
12475
|
+
);
|
|
12476
|
+
}
|
|
12477
|
+
function unitAround(target, pattern, reading, options) {
|
|
12062
12478
|
const { file, node, name, exportPath } = target;
|
|
12063
12479
|
const body = field(node, "body");
|
|
12064
12480
|
const range = rangeOf(node);
|
|
12065
12481
|
const raised = raisedResponses(body, {
|
|
12066
|
-
calls:
|
|
12482
|
+
calls: pattern.responseStatusCalls ?? [],
|
|
12067
12483
|
module: file.module,
|
|
12068
12484
|
facts: options.facts,
|
|
12069
|
-
constants:
|
|
12485
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
12070
12486
|
});
|
|
12071
|
-
const continuations =
|
|
12487
|
+
const continuations = reading.continuations;
|
|
12072
12488
|
const terminals = bodyTerminals(body, raised, continuations);
|
|
12073
12489
|
const effects = invocationEffects(node, options.facts);
|
|
12074
12490
|
const extra = recognizedBodyEffects(
|
|
@@ -12077,7 +12493,7 @@ function wrapperUnit(target, declared, options) {
|
|
|
12077
12493
|
options.storageFor(file),
|
|
12078
12494
|
options.facts
|
|
12079
12495
|
);
|
|
12080
|
-
const delegate = (at) => ({
|
|
12496
|
+
const delegate = (at, to = null) => ({
|
|
12081
12497
|
terminal: {
|
|
12082
12498
|
kind: "delegate",
|
|
12083
12499
|
statusCode: null,
|
|
@@ -12086,18 +12502,18 @@ function wrapperUnit(target, declared, options) {
|
|
|
12086
12502
|
message: null,
|
|
12087
12503
|
component: null,
|
|
12088
12504
|
renderTree: null,
|
|
12089
|
-
delegateTarget:
|
|
12505
|
+
delegateTarget: to,
|
|
12090
12506
|
emitEvent: null,
|
|
12091
12507
|
location: rangeOf(at)
|
|
12092
12508
|
},
|
|
12093
12509
|
location: rangeOf(at)
|
|
12094
12510
|
});
|
|
12095
12511
|
const respond = (statement) => returnBranch(statement, {
|
|
12096
|
-
pattern
|
|
12512
|
+
pattern,
|
|
12097
12513
|
responseShape: { reading: absentReading2 },
|
|
12098
12514
|
declaredStatus: {
|
|
12099
12515
|
reading: absentReading2,
|
|
12100
|
-
...
|
|
12516
|
+
...pattern.defaultStatusCode !== void 0 ? { libraryDefault: pattern.defaultStatusCode } : {}
|
|
12101
12517
|
},
|
|
12102
12518
|
module: file.module,
|
|
12103
12519
|
facts: options.facts
|
|
@@ -12109,7 +12525,10 @@ function wrapperUnit(target, declared, options) {
|
|
|
12109
12525
|
location: rangeOf(terminal.statement)
|
|
12110
12526
|
};
|
|
12111
12527
|
}
|
|
12112
|
-
if (terminal.type === "continuation"
|
|
12528
|
+
if (terminal.type === "continuation") {
|
|
12529
|
+
return delegate(terminal.statement, reading.continuationName);
|
|
12530
|
+
}
|
|
12531
|
+
if (reading.form !== null && returnHandsOn(terminal.statement, reading.form)) {
|
|
12113
12532
|
return delegate(terminal.statement);
|
|
12114
12533
|
}
|
|
12115
12534
|
return respond(terminal.statement);
|
|
@@ -12126,7 +12545,7 @@ function wrapperUnit(target, declared, options) {
|
|
|
12126
12545
|
return {
|
|
12127
12546
|
identity: {
|
|
12128
12547
|
name,
|
|
12129
|
-
nameKind:
|
|
12548
|
+
nameKind: reading.nameKind,
|
|
12130
12549
|
kind: "middleware",
|
|
12131
12550
|
file: file.displayPath,
|
|
12132
12551
|
range,
|
|
@@ -12162,23 +12581,45 @@ function continuationStatements(node, form) {
|
|
|
12162
12581
|
const params = children(field(node, "parameters"));
|
|
12163
12582
|
const param = params[form.continuationParam];
|
|
12164
12583
|
const continuation = param === void 0 ? null : field(param, "name")?.text ?? (param.type === "identifier" ? param.text : null);
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12584
|
+
return continuation === null ? [] : callsThrough(node, continuation);
|
|
12585
|
+
}
|
|
12586
|
+
function callsThrough(node, callee) {
|
|
12168
12587
|
const body = field(node, "body");
|
|
12169
12588
|
if (body === null) {
|
|
12170
12589
|
return [];
|
|
12171
12590
|
}
|
|
12172
12591
|
const found = [];
|
|
12173
12592
|
for (const call of bodyCalls(body)) {
|
|
12174
|
-
const
|
|
12175
|
-
const statement =
|
|
12593
|
+
const called = field(call, "function");
|
|
12594
|
+
const statement = called?.type === "identifier" && called.text === callee ? enclosingStatement(call, body) : null;
|
|
12176
12595
|
if (statement !== null) {
|
|
12177
12596
|
found.push(statement);
|
|
12178
12597
|
}
|
|
12179
12598
|
}
|
|
12180
12599
|
return found;
|
|
12181
12600
|
}
|
|
12601
|
+
function returnsCallTo(statement, callee) {
|
|
12602
|
+
if (statement.type !== "return_statement") {
|
|
12603
|
+
return false;
|
|
12604
|
+
}
|
|
12605
|
+
const value = statement.namedChild(0);
|
|
12606
|
+
const call = value?.type === "await" ? value.namedChild(0) : value;
|
|
12607
|
+
return call?.type === "call" && field(call, "function")?.text === callee;
|
|
12608
|
+
}
|
|
12609
|
+
function closureReturnedBy(decorator) {
|
|
12610
|
+
const statements = children(field(decorator, "body"));
|
|
12611
|
+
const returned = statements.find((statement) => statement.type === "return_statement")?.namedChild(0);
|
|
12612
|
+
if (returned?.type !== "identifier") {
|
|
12613
|
+
return null;
|
|
12614
|
+
}
|
|
12615
|
+
for (const statement of statements) {
|
|
12616
|
+
const { definition } = stripDecorators(statement);
|
|
12617
|
+
if (definition.type === "function_definition" && field(definition, "name")?.text === returned.text) {
|
|
12618
|
+
return definition;
|
|
12619
|
+
}
|
|
12620
|
+
}
|
|
12621
|
+
return null;
|
|
12622
|
+
}
|
|
12182
12623
|
|
|
12183
12624
|
// src/project.ts
|
|
12184
12625
|
function keptPythonParses() {
|
|
@@ -12273,7 +12714,7 @@ async function extractPythonProject(options) {
|
|
|
12273
12714
|
const { roots, unreadManifests } = rootsOfRun(options);
|
|
12274
12715
|
const timer = options.onTiming !== void 0 ? createTimer() : noopTimer();
|
|
12275
12716
|
const cacheDir = adapterStamp.declineWhenRunFromSource(
|
|
12276
|
-
options.cacheDir === null ? null : options.cacheDir ?? (options.projectRoot !== void 0 ?
|
|
12717
|
+
options.cacheDir === null ? null : options.cacheDir ?? (options.projectRoot !== void 0 ? extractionCacheDirFor(options.projectRoot) : null)
|
|
12277
12718
|
);
|
|
12278
12719
|
const layer = createCacheLayer(cacheDir);
|
|
12279
12720
|
const packsDigest = `${adapterStamp.packsDigest(
|
|
@@ -12296,11 +12737,14 @@ async function extractPythonProject(options) {
|
|
|
12296
12737
|
"cache.lookup",
|
|
12297
12738
|
() => layer.lookup(input)
|
|
12298
12739
|
);
|
|
12740
|
+
const composed = (stored) => composeWrappers(stored, {
|
|
12741
|
+
gapHandling: options.gapHandling ?? "permissive"
|
|
12742
|
+
});
|
|
12299
12743
|
if (lookup.kind === "hit") {
|
|
12300
12744
|
options.onCacheDiagnostic?.(lookup.diagnostic);
|
|
12301
12745
|
options.onTiming?.(timer.report());
|
|
12302
12746
|
return {
|
|
12303
|
-
summaries: lookup.summaries,
|
|
12747
|
+
summaries: composed(lookup.summaries),
|
|
12304
12748
|
facts: new Database2(),
|
|
12305
12749
|
roots,
|
|
12306
12750
|
unreadManifests
|
|
@@ -12315,7 +12759,7 @@ async function extractPythonProject(options) {
|
|
|
12315
12759
|
options.onCacheDiagnostic?.({ kind: "hit" });
|
|
12316
12760
|
options.onTiming?.(timer.report());
|
|
12317
12761
|
return {
|
|
12318
|
-
summaries: plan.allSummaries(),
|
|
12762
|
+
summaries: composed(plan.allSummaries()),
|
|
12319
12763
|
facts: new Database2(),
|
|
12320
12764
|
roots,
|
|
12321
12765
|
unreadManifests
|
|
@@ -12497,15 +12941,10 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12497
12941
|
});
|
|
12498
12942
|
let registering = null;
|
|
12499
12943
|
if (ledger !== null) {
|
|
12500
|
-
wrapperIndex.onRegistered = (target,
|
|
12501
|
-
const
|
|
12502
|
-
if (registering !== null &&
|
|
12503
|
-
registering.push(
|
|
12504
|
-
key: nodeId(target.file.file, target.node),
|
|
12505
|
-
name: target.name,
|
|
12506
|
-
exportPath: target.exportPath,
|
|
12507
|
-
form
|
|
12508
|
-
});
|
|
12944
|
+
wrapperIndex.onRegistered = (target, how) => {
|
|
12945
|
+
const stored = storedRegistration(target, how, positions);
|
|
12946
|
+
if (registering !== null && stored !== null) {
|
|
12947
|
+
registering.push(stored);
|
|
12509
12948
|
}
|
|
12510
12949
|
};
|
|
12511
12950
|
}
|
|
@@ -12518,12 +12957,11 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12518
12957
|
if (record !== void 0) {
|
|
12519
12958
|
discoveries.set(file, record);
|
|
12520
12959
|
for (const registration of record.registrations) {
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
}
|
|
12526
|
-
wrapperIndex.registered(target, declared);
|
|
12960
|
+
registerAgain(registration, {
|
|
12961
|
+
positions,
|
|
12962
|
+
wrapperIndex,
|
|
12963
|
+
target: storedFunction(registration, definitions, filesByPath)
|
|
12964
|
+
});
|
|
12527
12965
|
}
|
|
12528
12966
|
continue;
|
|
12529
12967
|
}
|
|
@@ -12692,6 +13130,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12692
13130
|
}
|
|
12693
13131
|
placeCalls2(summary, reached.targetsByKey.get(key));
|
|
12694
13132
|
placeArgTargets2(summary, reached.argTargetsByKey.get(key));
|
|
13133
|
+
placePossibleCalls2(summary, reached.possibleTargetsByKey.get(key));
|
|
12695
13134
|
placeCalleeParameters2(summary, reached.parameterCallsByKey.get(key));
|
|
12696
13135
|
};
|
|
12697
13136
|
for (const [key, owners] of summariesBySeed) {
|
|
@@ -12781,16 +13220,20 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12781
13220
|
markExitCodeFunctions(summaries, exits, db, options.workspaceRoot);
|
|
12782
13221
|
return composeWrappers(summaries, { gapHandling });
|
|
12783
13222
|
});
|
|
13223
|
+
const walkedFiles = new Map(
|
|
13224
|
+
bound.map(({ file, displayPath }) => [displayPath, file])
|
|
13225
|
+
);
|
|
12784
13226
|
await timer.timeAsync("cache.write", async () => {
|
|
12785
|
-
if (cacheDir === null ||
|
|
13227
|
+
if (cacheDir === null || summaries.length === 0) {
|
|
12786
13228
|
return;
|
|
12787
13229
|
}
|
|
12788
13230
|
try {
|
|
12789
13231
|
await cache.layer.write(
|
|
12790
13232
|
cache.input,
|
|
12791
|
-
|
|
13233
|
+
summaries,
|
|
12792
13234
|
log === null || ledger === null || overBudget ? void 0 : pythonAttribution({
|
|
12793
|
-
|
|
13235
|
+
summaries,
|
|
13236
|
+
walkedFileOf: (locationFile) => walkedFiles.get(locationFile),
|
|
12794
13237
|
discoveries,
|
|
12795
13238
|
charges,
|
|
12796
13239
|
unitDrafts,
|
|
@@ -12845,6 +13288,39 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12845
13288
|
options.onTiming?.(timer.report());
|
|
12846
13289
|
return { summaries: composed, facts: db };
|
|
12847
13290
|
}
|
|
13291
|
+
function storedRegistration(target, how, positions) {
|
|
13292
|
+
const at = {
|
|
13293
|
+
key: nodeId(target.file.file, target.node),
|
|
13294
|
+
name: target.name,
|
|
13295
|
+
exportPath: target.exportPath
|
|
13296
|
+
};
|
|
13297
|
+
if ("continuation" in how) {
|
|
13298
|
+
const pattern = positions.idOf(how.pattern);
|
|
13299
|
+
return pattern === void 0 ? null : { ...at, pattern, continuation: how.continuation };
|
|
13300
|
+
}
|
|
13301
|
+
const form = positions.positionOf(how);
|
|
13302
|
+
return form === void 0 ? null : { ...at, form };
|
|
13303
|
+
}
|
|
13304
|
+
function registerAgain(registration, context) {
|
|
13305
|
+
const { positions, wrapperIndex, target } = context;
|
|
13306
|
+
const how = howRegistered(registration, positions);
|
|
13307
|
+
if (target === null || how === null) {
|
|
13308
|
+
throw new ReplayFailed(registration.key);
|
|
13309
|
+
}
|
|
13310
|
+
if ("continuation" in how) {
|
|
13311
|
+
wrapperIndex.registeredClosure(target, how);
|
|
13312
|
+
return;
|
|
13313
|
+
}
|
|
13314
|
+
wrapperIndex.registered(target, how);
|
|
13315
|
+
}
|
|
13316
|
+
function howRegistered(registration, positions) {
|
|
13317
|
+
if (!("continuation" in registration)) {
|
|
13318
|
+
return positions.formAt(registration.form) ?? null;
|
|
13319
|
+
}
|
|
13320
|
+
const pack = positions.packOf(registration.pattern);
|
|
13321
|
+
const pattern = positions.patternOf(registration.pattern);
|
|
13322
|
+
return pack === void 0 || pattern === void 0 ? null : { pack, pattern, continuation: registration.continuation };
|
|
13323
|
+
}
|
|
12848
13324
|
function pythonAttribution(args) {
|
|
12849
13325
|
const walkedByFile = walkRecordsByFile({
|
|
12850
13326
|
scans: args.reached.scans,
|
|
@@ -12873,7 +13349,10 @@ function pythonAttribution(args) {
|
|
|
12873
13349
|
}
|
|
12874
13350
|
};
|
|
12875
13351
|
});
|
|
12876
|
-
return {
|
|
13352
|
+
return {
|
|
13353
|
+
roots,
|
|
13354
|
+
owners: ownersWhereWritten(args.summaries, args.walkedFileOf)
|
|
13355
|
+
};
|
|
12877
13356
|
}
|
|
12878
13357
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
12879
13358
|
"__pycache__",
|