@suss/adapter-python 0.34.0 → 0.35.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 +1681 -600
- package/dist/index.d.cts +126 -6
- package/dist/index.d.ts +126 -6
- package/dist/index.js +1576 -478
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -153,10 +153,7 @@ function stringLiteralValue(node) {
|
|
|
153
153
|
return null;
|
|
154
154
|
}
|
|
155
155
|
let content = "";
|
|
156
|
-
for (const child of node
|
|
157
|
-
if (child === null) {
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
156
|
+
for (const child of children(node)) {
|
|
160
157
|
if (child.type === "string_content") {
|
|
161
158
|
content += stringContentValue(child);
|
|
162
159
|
continue;
|
|
@@ -168,7 +165,29 @@ function stringLiteralValue(node) {
|
|
|
168
165
|
return content;
|
|
169
166
|
}
|
|
170
167
|
function children(node) {
|
|
171
|
-
|
|
168
|
+
if (node === null || node === void 0) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
const found = [];
|
|
172
|
+
const count = node.namedChildCount;
|
|
173
|
+
for (let index = 0; index < count; index++) {
|
|
174
|
+
const child = node.namedChild(index);
|
|
175
|
+
if (child !== null) {
|
|
176
|
+
found.push(child);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return found;
|
|
180
|
+
}
|
|
181
|
+
function allChildren(node) {
|
|
182
|
+
const found = [];
|
|
183
|
+
const count = node.childCount;
|
|
184
|
+
for (let index = 0; index < count; index++) {
|
|
185
|
+
const child = node.child(index);
|
|
186
|
+
if (child !== null) {
|
|
187
|
+
found.push(child);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return found;
|
|
172
191
|
}
|
|
173
192
|
function bodyStatements(body) {
|
|
174
193
|
return children(body);
|
|
@@ -200,11 +219,59 @@ function stripDecorators(node) {
|
|
|
200
219
|
if (definition === null) {
|
|
201
220
|
throw new Error("decorated_definition with no definition field");
|
|
202
221
|
}
|
|
203
|
-
const decorators = node.
|
|
204
|
-
(child) => child
|
|
222
|
+
const decorators = children(node).filter(
|
|
223
|
+
(child) => child.type === "decorator"
|
|
205
224
|
);
|
|
206
225
|
return { definition, decorators };
|
|
207
226
|
}
|
|
227
|
+
var isChild = (fieldName) => (parent, child) => field(parent, fieldName)?.id === child.id;
|
|
228
|
+
var always = () => true;
|
|
229
|
+
var asCondition = isChild("condition");
|
|
230
|
+
var isConditionalTest = (parent, child) => parent.namedChild(1)?.id === child.id;
|
|
231
|
+
var VALUE_USED_UNDER = {
|
|
232
|
+
assignment: isChild("right"),
|
|
233
|
+
augmented_assignment: isChild("right"),
|
|
234
|
+
named_expression: isChild("value"),
|
|
235
|
+
attribute: isChild("object"),
|
|
236
|
+
subscript: always,
|
|
237
|
+
argument_list: always,
|
|
238
|
+
keyword_argument: isChild("value"),
|
|
239
|
+
pair: always,
|
|
240
|
+
list: always,
|
|
241
|
+
tuple: always,
|
|
242
|
+
set: always,
|
|
243
|
+
dictionary: always,
|
|
244
|
+
interpolation: always,
|
|
245
|
+
comparison_operator: always,
|
|
246
|
+
binary_operator: always,
|
|
247
|
+
unary_operator: always,
|
|
248
|
+
not_operator: always,
|
|
249
|
+
if_statement: asCondition,
|
|
250
|
+
elif_clause: asCondition,
|
|
251
|
+
while_statement: asCondition,
|
|
252
|
+
conditional_expression: isConditionalTest,
|
|
253
|
+
assert_statement: always,
|
|
254
|
+
for_statement: isChild("right"),
|
|
255
|
+
for_in_clause: isChild("right"),
|
|
256
|
+
with_item: always,
|
|
257
|
+
as_pattern: always
|
|
258
|
+
};
|
|
259
|
+
var PASSES_VALUE_ON = {
|
|
260
|
+
parenthesized_expression: always,
|
|
261
|
+
await: always,
|
|
262
|
+
boolean_operator: always,
|
|
263
|
+
conditional_expression: (parent, child) => !isConditionalTest(parent, child)
|
|
264
|
+
};
|
|
265
|
+
function resultUsedAsValue(node) {
|
|
266
|
+
let child = node;
|
|
267
|
+
let parent = node.parent;
|
|
268
|
+
while (parent !== null && PASSES_VALUE_ON[parent.type]?.(parent, child) === true) {
|
|
269
|
+
child = parent;
|
|
270
|
+
parent = parent.parent;
|
|
271
|
+
}
|
|
272
|
+
const used = parent === null ? void 0 : VALUE_USED_UNDER[parent.type];
|
|
273
|
+
return parent !== null && used !== void 0 && used(parent, child);
|
|
274
|
+
}
|
|
208
275
|
var NodeSet = class extends import_extractor.IdSet {
|
|
209
276
|
};
|
|
210
277
|
var NodeMap = class extends import_extractor.IdMap {
|
|
@@ -266,7 +333,7 @@ function bindWithStatement(stmt, scope, ctx) {
|
|
|
266
333
|
}
|
|
267
334
|
}
|
|
268
335
|
function asPatternsIn(stmt, found = []) {
|
|
269
|
-
for (const child of stmt
|
|
336
|
+
for (const child of children(stmt)) {
|
|
270
337
|
if (child === null || child.type === "block") {
|
|
271
338
|
continue;
|
|
272
339
|
}
|
|
@@ -295,12 +362,12 @@ function bindDeleteStatement(stmt, scope) {
|
|
|
295
362
|
return;
|
|
296
363
|
}
|
|
297
364
|
if (node.type === "expression_list") {
|
|
298
|
-
for (const child of node
|
|
365
|
+
for (const child of children(node)) {
|
|
299
366
|
unbind(child);
|
|
300
367
|
}
|
|
301
368
|
}
|
|
302
369
|
};
|
|
303
|
-
for (const child of stmt
|
|
370
|
+
for (const child of children(stmt)) {
|
|
304
371
|
unbind(child);
|
|
305
372
|
}
|
|
306
373
|
}
|
|
@@ -341,10 +408,7 @@ function bindImportStatement(stmt, scope) {
|
|
|
341
408
|
function relativeImportParts(node) {
|
|
342
409
|
let relativeLevel = 0;
|
|
343
410
|
let module2 = "";
|
|
344
|
-
for (const child of node
|
|
345
|
-
if (child === null) {
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
411
|
+
for (const child of children(node)) {
|
|
348
412
|
if (child.type === "import_prefix") {
|
|
349
413
|
relativeLevel += child.text.length;
|
|
350
414
|
continue;
|
|
@@ -361,8 +425,8 @@ function bindImportFromStatement(stmt, scope, ctx) {
|
|
|
361
425
|
return;
|
|
362
426
|
}
|
|
363
427
|
const { module: module2, relativeLevel } = moduleNode.type === "relative_import" ? relativeImportParts(moduleNode) : { module: moduleNode.text, relativeLevel: 0 };
|
|
364
|
-
const hasWildcard = stmt.
|
|
365
|
-
(child) => child
|
|
428
|
+
const hasWildcard = children(stmt).some(
|
|
429
|
+
(child) => child.type === "wildcard_import"
|
|
366
430
|
);
|
|
367
431
|
if (hasWildcard) {
|
|
368
432
|
ctx.openImports.push(
|
|
@@ -420,10 +484,7 @@ function bindFunctionDefinition(stmt, scope, ctx) {
|
|
|
420
484
|
}
|
|
421
485
|
}
|
|
422
486
|
function bindParameters(parametersNode, functionScope) {
|
|
423
|
-
for (const param of parametersNode
|
|
424
|
-
if (param === null) {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
487
|
+
for (const param of children(parametersNode)) {
|
|
427
488
|
const name = parameterName(param);
|
|
428
489
|
if (name !== null) {
|
|
429
490
|
bindName(functionScope, name, { kind: "parameter" });
|
|
@@ -440,9 +501,7 @@ function parameterName(param) {
|
|
|
440
501
|
"list_splat_pattern",
|
|
441
502
|
"dictionary_splat_pattern"
|
|
442
503
|
)) {
|
|
443
|
-
const inner = param.
|
|
444
|
-
(child) => child !== null && child.type === "identifier"
|
|
445
|
-
);
|
|
504
|
+
const inner = children(param).find((child) => child.type === "identifier");
|
|
446
505
|
return inner?.text ?? null;
|
|
447
506
|
}
|
|
448
507
|
if (isType(param, "default_parameter", "typed_default_parameter")) {
|
|
@@ -469,8 +528,8 @@ function bindClassDefinition(stmt, scope, ctx) {
|
|
|
469
528
|
}
|
|
470
529
|
}
|
|
471
530
|
function bindExpressionStatement(stmt, scope) {
|
|
472
|
-
const assignment2 = stmt.
|
|
473
|
-
(child) => child
|
|
531
|
+
const assignment2 = children(stmt).find(
|
|
532
|
+
(child) => child.type === "assignment"
|
|
474
533
|
);
|
|
475
534
|
if (assignment2 === void 0 || assignment2 === null) {
|
|
476
535
|
return;
|
|
@@ -487,15 +546,15 @@ function bindExpressionStatement(stmt, scope) {
|
|
|
487
546
|
}
|
|
488
547
|
}
|
|
489
548
|
function bindGlobalStatement(stmt, scope) {
|
|
490
|
-
for (const child of stmt
|
|
491
|
-
if (child
|
|
549
|
+
for (const child of children(stmt)) {
|
|
550
|
+
if (child.type === "identifier") {
|
|
492
551
|
scope.bindings.set(child.text, { kind: "global" });
|
|
493
552
|
}
|
|
494
553
|
}
|
|
495
554
|
}
|
|
496
555
|
function bindNonlocalStatement(stmt, scope) {
|
|
497
|
-
for (const child of stmt
|
|
498
|
-
if (child
|
|
556
|
+
for (const child of children(stmt)) {
|
|
557
|
+
if (child.type === "identifier") {
|
|
499
558
|
scope.bindings.set(child.text, { kind: "nonlocal" });
|
|
500
559
|
}
|
|
501
560
|
}
|
|
@@ -644,18 +703,9 @@ function shapeFromName(name, scope, ctx) {
|
|
|
644
703
|
if (DICT_NAMES.has(name)) {
|
|
645
704
|
return { type: "dictionary", values: { type: "unknown" } };
|
|
646
705
|
}
|
|
647
|
-
const
|
|
648
|
-
if (
|
|
649
|
-
return recordShapeRef(name,
|
|
650
|
-
}
|
|
651
|
-
if (binding?.kind === "import" || binding?.kind === "importFrom") {
|
|
652
|
-
const imported = ctx.importedDefinition?.(scope, name) ?? null;
|
|
653
|
-
if (imported?.node.type === "class_definition") {
|
|
654
|
-
if (!ctx.scopeMaps.includes(imported.scopeFor)) {
|
|
655
|
-
ctx.scopeMaps.push(imported.scopeFor);
|
|
656
|
-
}
|
|
657
|
-
return recordShapeRef(name, imported.node, ctx);
|
|
658
|
-
}
|
|
706
|
+
const classNode = projectClassNamed(name, scope, ctx);
|
|
707
|
+
if (classNode !== null) {
|
|
708
|
+
return recordShapeRef(name, classNode, ctx);
|
|
659
709
|
}
|
|
660
710
|
const alias = aliasValueOf(name, scope, ctx);
|
|
661
711
|
if (alias !== null) {
|
|
@@ -663,6 +713,23 @@ function shapeFromName(name, scope, ctx) {
|
|
|
663
713
|
}
|
|
664
714
|
return { type: "ref", name };
|
|
665
715
|
}
|
|
716
|
+
function projectClassNamed(name, scope, ctx) {
|
|
717
|
+
const binding = resolveName(scope, name);
|
|
718
|
+
if (binding?.kind === "classDef") {
|
|
719
|
+
return binding.node;
|
|
720
|
+
}
|
|
721
|
+
if (binding?.kind !== "import" && binding?.kind !== "importFrom") {
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
const imported = ctx.importedDefinition?.(scope, name) ?? null;
|
|
725
|
+
if (imported?.node.type !== "class_definition") {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
if (!ctx.scopeMaps.includes(imported.scopeFor)) {
|
|
729
|
+
ctx.scopeMaps.push(imported.scopeFor);
|
|
730
|
+
}
|
|
731
|
+
return imported.node;
|
|
732
|
+
}
|
|
666
733
|
function shapeFromAliasValue(name, alias, ctx) {
|
|
667
734
|
if (ctx.expanding.has(alias.node.id)) {
|
|
668
735
|
return { type: "ref", name };
|
|
@@ -689,8 +756,9 @@ function shapeFromSubscript(node, scope, ctx) {
|
|
|
689
756
|
);
|
|
690
757
|
}
|
|
691
758
|
function annotationTarget(annotation) {
|
|
692
|
-
|
|
693
|
-
|
|
759
|
+
const inner = annotation.type === "type" ? annotation.namedChild(0) : null;
|
|
760
|
+
if (inner !== null) {
|
|
761
|
+
return annotationTarget(inner);
|
|
694
762
|
}
|
|
695
763
|
if (annotation.type === "binary_operator") {
|
|
696
764
|
const named = [field(annotation, "left"), field(annotation, "right")].find(
|
|
@@ -699,7 +767,7 @@ function annotationTarget(annotation) {
|
|
|
699
767
|
return named === void 0 || named === null ? null : annotationTarget(named);
|
|
700
768
|
}
|
|
701
769
|
if (annotation.type === "generic_type") {
|
|
702
|
-
const outer = annotation.
|
|
770
|
+
const outer = annotation.namedChild(0);
|
|
703
771
|
const first = genericTypeArgs(annotation)[0];
|
|
704
772
|
if ((outer?.text === "Annotated" || outer?.text === "Optional") && first !== void 0) {
|
|
705
773
|
return annotationTarget(first);
|
|
@@ -716,12 +784,10 @@ function typeNameOf(annotation) {
|
|
|
716
784
|
return target.type === "identifier" ? target.text : stringLiteralValue(target);
|
|
717
785
|
}
|
|
718
786
|
function genericTypeArgs(node) {
|
|
719
|
-
const typeParameter = node.
|
|
720
|
-
(child) => child
|
|
787
|
+
const typeParameter = children(node).find(
|
|
788
|
+
(child) => child.type === "type_parameter"
|
|
721
789
|
);
|
|
722
|
-
return typeParameter
|
|
723
|
-
(child) => child !== null && child.type === "type"
|
|
724
|
-
) ?? [];
|
|
790
|
+
return children(typeParameter).filter((child) => child.type === "type");
|
|
725
791
|
}
|
|
726
792
|
function shapeFromGenericType(node, scope, ctx) {
|
|
727
793
|
const base = node.namedChild(0);
|
|
@@ -773,22 +839,44 @@ function recordShapeRef(name, classNode, ctx) {
|
|
|
773
839
|
return ref;
|
|
774
840
|
}
|
|
775
841
|
ctx.definitions.set(key, null);
|
|
842
|
+
ctx.definitions.set(key, {
|
|
843
|
+
type: "record",
|
|
844
|
+
properties: classFields(classNode, ctx, /* @__PURE__ */ new Set())
|
|
845
|
+
});
|
|
846
|
+
return ref;
|
|
847
|
+
}
|
|
848
|
+
function classFields(classNode, ctx, visiting) {
|
|
776
849
|
const bodyNode = field(classNode, "body");
|
|
777
850
|
const classScope = scopeOfNode(ctx, classNode);
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
851
|
+
if (bodyNode === null || classScope === void 0 || visiting.has(classNode.id)) {
|
|
852
|
+
return {};
|
|
853
|
+
}
|
|
854
|
+
visiting.add(classNode.id);
|
|
855
|
+
const inherited = baseClassNames(classNode).flatMap((name) => {
|
|
856
|
+
const base = projectClassNamed(name, classScope, ctx);
|
|
857
|
+
return base === null ? [] : [classFields(base, ctx, visiting)];
|
|
858
|
+
});
|
|
859
|
+
const own = recordShapeOf(bodyNode, classScope, ctx);
|
|
860
|
+
return Object.assign(
|
|
861
|
+
{},
|
|
862
|
+
...inherited.reverse(),
|
|
863
|
+
own.type === "record" ? own.properties : {}
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
function baseClassNames(classNode) {
|
|
867
|
+
const superclasses = field(classNode, "superclasses");
|
|
868
|
+
return children(superclasses).flatMap(
|
|
869
|
+
(child) => child.type === "identifier" ? [child.text] : []
|
|
781
870
|
);
|
|
782
|
-
return ref;
|
|
783
871
|
}
|
|
784
872
|
function recordShapeOf(bodyNode, classScope, ctx) {
|
|
785
873
|
const properties = {};
|
|
786
|
-
for (const stmt of bodyNode
|
|
874
|
+
for (const stmt of children(bodyNode)) {
|
|
787
875
|
if (stmt === null || stmt.type !== "expression_statement") {
|
|
788
876
|
continue;
|
|
789
877
|
}
|
|
790
|
-
const assignment2 = stmt.
|
|
791
|
-
(child) => child
|
|
878
|
+
const assignment2 = children(stmt).find(
|
|
879
|
+
(child) => child.type === "assignment"
|
|
792
880
|
);
|
|
793
881
|
if (assignment2 === void 0 || assignment2 === null) {
|
|
794
882
|
continue;
|
|
@@ -798,6 +886,9 @@ function recordShapeOf(bodyNode, classScope, ctx) {
|
|
|
798
886
|
if (left === null || left.type !== "identifier" || typeNode === null) {
|
|
799
887
|
continue;
|
|
800
888
|
}
|
|
889
|
+
if (typeNameOf(typeNode) === "ClassVar") {
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
801
892
|
properties[left.text] = annotationToShape(typeNode, classScope, ctx);
|
|
802
893
|
}
|
|
803
894
|
return { type: "record", properties };
|
|
@@ -807,13 +898,14 @@ function shortHash(text2) {
|
|
|
807
898
|
}
|
|
808
899
|
|
|
809
900
|
// src/decorators.ts
|
|
810
|
-
var
|
|
901
|
+
var import_behavioral_ir2 = require("@suss/behavioral-ir");
|
|
811
902
|
|
|
812
903
|
// src/values/evaluator.ts
|
|
813
904
|
var import_resolution4 = require("@suss/resolution");
|
|
814
905
|
var import_values4 = require("@suss/values");
|
|
815
906
|
|
|
816
907
|
// src/facts/resolve.ts
|
|
908
|
+
var import_behavioral_ir = require("@suss/behavioral-ir");
|
|
817
909
|
var import_resolution = require("@suss/resolution");
|
|
818
910
|
var import_resolution2 = require("@suss/resolution");
|
|
819
911
|
var evaluationsUnderSite = /* @__PURE__ */ new WeakMap();
|
|
@@ -859,7 +951,13 @@ function constructionSites(db, classKey) {
|
|
|
859
951
|
}
|
|
860
952
|
function writtenValueOf(db, key) {
|
|
861
953
|
resolveWritten(db, [key]);
|
|
862
|
-
return (0, import_resolution.writtenValueOf)(
|
|
954
|
+
return (0, import_resolution.writtenValueOf)(
|
|
955
|
+
db,
|
|
956
|
+
key,
|
|
957
|
+
(keys) => resolveWritten(db, keys),
|
|
958
|
+
void 0,
|
|
959
|
+
(0, import_resolution.answersFromTestsLeftOut)(key, import_behavioral_ir.isTestFile)
|
|
960
|
+
);
|
|
863
961
|
}
|
|
864
962
|
function writtenValuesOf(db, key) {
|
|
865
963
|
resolveWritten(db, [key]);
|
|
@@ -950,6 +1048,8 @@ var CONVERTING_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
950
1048
|
"str",
|
|
951
1049
|
"float"
|
|
952
1050
|
]);
|
|
1051
|
+
var ATTRIBUTE_GETTER = "getattr";
|
|
1052
|
+
var POSITION_COUNTER = "enumerate";
|
|
953
1053
|
|
|
954
1054
|
// src/facts/values.ts
|
|
955
1055
|
function nodeId(filePath, node) {
|
|
@@ -1121,8 +1221,7 @@ function emitConversion(emitter, call, callKey) {
|
|
|
1121
1221
|
return;
|
|
1122
1222
|
}
|
|
1123
1223
|
const name = callee.text;
|
|
1124
|
-
|
|
1125
|
-
if (builtin) {
|
|
1224
|
+
if (isBuiltin(emitter, name)) {
|
|
1126
1225
|
add(emitter, "converts", callKey, valueKey(emitter, first.node), name);
|
|
1127
1226
|
}
|
|
1128
1227
|
}
|
|
@@ -1171,6 +1270,7 @@ function emitSequence(emitter, sequence) {
|
|
|
1171
1270
|
const objectKey = nodeId(emitter.filePath, sequence);
|
|
1172
1271
|
add(emitter, "objectValue", objectKey);
|
|
1173
1272
|
let position = 0;
|
|
1273
|
+
const entries = [];
|
|
1174
1274
|
for (const element of children(sequence)) {
|
|
1175
1275
|
add(
|
|
1176
1276
|
emitter,
|
|
@@ -1180,12 +1280,21 @@ function emitSequence(emitter, sequence) {
|
|
|
1180
1280
|
valueKey(emitter, element)
|
|
1181
1281
|
);
|
|
1182
1282
|
position += 1;
|
|
1283
|
+
if (element.type !== "comment") {
|
|
1284
|
+
entries.push(writtenEntry(emitter, element));
|
|
1285
|
+
}
|
|
1183
1286
|
}
|
|
1287
|
+
(0, import_resolution3.addEntryRows)(rowsOf(emitter), objectKey, entries);
|
|
1184
1288
|
}
|
|
1185
1289
|
function emitDictionary(emitter, dictionary) {
|
|
1186
1290
|
const objectKey = nodeId(emitter.filePath, dictionary);
|
|
1187
1291
|
add(emitter, "objectValue", objectKey);
|
|
1292
|
+
const entries = [];
|
|
1188
1293
|
for (const pair of children(dictionary)) {
|
|
1294
|
+
if (SPREAD_TYPES.has(pair.type)) {
|
|
1295
|
+
entries.push(writtenEntry(emitter, pair));
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1189
1298
|
if (pair.type !== "pair") {
|
|
1190
1299
|
continue;
|
|
1191
1300
|
}
|
|
@@ -1194,6 +1303,7 @@ function emitDictionary(emitter, dictionary) {
|
|
|
1194
1303
|
if (key === null || value === null) {
|
|
1195
1304
|
continue;
|
|
1196
1305
|
}
|
|
1306
|
+
entries.push(writtenEntry(emitter, value));
|
|
1197
1307
|
if (key.type !== "string") {
|
|
1198
1308
|
add(emitter, "holdsUnderKey", objectKey, valueKey(emitter, value));
|
|
1199
1309
|
continue;
|
|
@@ -1206,6 +1316,15 @@ function emitDictionary(emitter, dictionary) {
|
|
|
1206
1316
|
valueKey(emitter, value)
|
|
1207
1317
|
);
|
|
1208
1318
|
}
|
|
1319
|
+
(0, import_resolution3.addEntryRows)(rowsOf(emitter), objectKey, entries);
|
|
1320
|
+
}
|
|
1321
|
+
var SPREAD_TYPES = /* @__PURE__ */ new Set(["list_splat", "dictionary_splat"]);
|
|
1322
|
+
function writtenEntry(emitter, entry) {
|
|
1323
|
+
const unpacked = SPREAD_TYPES.has(entry.type) ? children(entry)[0] : void 0;
|
|
1324
|
+
return unpacked === void 0 ? { key: valueKey(emitter, entry), form: import_resolution3.VALUE_ENTRY } : { key: valueKey(emitter, unpacked), form: import_resolution3.SPREAD_ENTRY };
|
|
1325
|
+
}
|
|
1326
|
+
function rowsOf(emitter) {
|
|
1327
|
+
return (relation, row) => add(emitter, relation, ...row);
|
|
1209
1328
|
}
|
|
1210
1329
|
function emitAttribute(emitter, attribute) {
|
|
1211
1330
|
const object = field(attribute, "object");
|
|
@@ -1270,13 +1389,50 @@ function emitKeyedRead(emitter, site, container, key) {
|
|
|
1270
1389
|
if (WRITTEN_KEY_TYPES.has(key.type)) {
|
|
1271
1390
|
return;
|
|
1272
1391
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1392
|
+
const siteKey = nodeId(emitter.filePath, site);
|
|
1393
|
+
const containerKey = valueKey(emitter, container);
|
|
1394
|
+
add(emitter, "readsKeyed", siteKey, containerKey, valueKey(emitter, key));
|
|
1395
|
+
add(emitter, "choosesEntry", siteKey, containerKey);
|
|
1396
|
+
}
|
|
1397
|
+
function emitAttributeChoice(emitter, call) {
|
|
1398
|
+
const callee = field(call, "function");
|
|
1399
|
+
const [target, name] = callArguments(call);
|
|
1400
|
+
if (callee?.type !== "identifier" || callee.text !== ATTRIBUTE_GETTER || !isBuiltin(emitter, callee.text) || target?.kind !== "positional" || name?.kind !== "positional") {
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
const siteKey = nodeId(emitter.filePath, call);
|
|
1404
|
+
const targetKey = valueKey(emitter, target.node);
|
|
1405
|
+
const written = plainStringOf(name.node);
|
|
1406
|
+
if (written !== null) {
|
|
1407
|
+
add(emitter, "choosesNamedEntry", siteKey, targetKey, written);
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const ends = writtenEnds(name.node);
|
|
1411
|
+
if (ends === null) {
|
|
1412
|
+
add(emitter, "choosesEntry", siteKey, targetKey);
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
add(emitter, "choosesEntryLike", siteKey, targetKey, ends.start, ends.end);
|
|
1416
|
+
}
|
|
1417
|
+
function writtenEnds(node) {
|
|
1418
|
+
if (node.type !== "string") {
|
|
1419
|
+
return null;
|
|
1420
|
+
}
|
|
1421
|
+
const parts = children(node).filter(
|
|
1422
|
+
(part) => part.type !== "string_start" && part.type !== "string_end"
|
|
1279
1423
|
);
|
|
1424
|
+
const written = (part) => part.type === "string_content";
|
|
1425
|
+
const firstComputed = parts.findIndex((part) => !written(part));
|
|
1426
|
+
if (firstComputed === -1) {
|
|
1427
|
+
return null;
|
|
1428
|
+
}
|
|
1429
|
+
const lastComputed = parts.length - 1 - [...parts].reverse().findIndex((part) => !written(part));
|
|
1430
|
+
const start = parts.slice(0, firstComputed).map((part) => part.text).join("");
|
|
1431
|
+
const end = parts.slice(lastComputed + 1).map((part) => part.text).join("");
|
|
1432
|
+
return start === "" && end === "" ? null : { start, end };
|
|
1433
|
+
}
|
|
1434
|
+
function isBuiltin(emitter, name) {
|
|
1435
|
+
return nameKey(emitter.filePath, emitter.enclosing, name) === nameId(emitter.filePath, name) && !emitter.moduleNames().has(name);
|
|
1280
1436
|
}
|
|
1281
1437
|
function emitWrittenKeyRead(emitter, site, container, key) {
|
|
1282
1438
|
const name = plainStringOf(key);
|
|
@@ -1412,6 +1568,86 @@ function emitComprehensionElement(emitter, comprehension) {
|
|
|
1412
1568
|
);
|
|
1413
1569
|
}
|
|
1414
1570
|
}
|
|
1571
|
+
var PAIR_TARGET_TYPES = /* @__PURE__ */ new Set(["pattern_list", "tuple_pattern"]);
|
|
1572
|
+
function emitElementVariables(emitter, clause) {
|
|
1573
|
+
const target = field(clause, "left");
|
|
1574
|
+
const over = field(clause, "right");
|
|
1575
|
+
if (target === null || over === null) {
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
const names = PAIR_TARGET_TYPES.has(target.type) ? children(target) : [];
|
|
1579
|
+
const [position, element] = names;
|
|
1580
|
+
const counted = countedCollection(emitter, over);
|
|
1581
|
+
if (counted !== null && names.length === 2 && position?.type === "identifier" && element !== void 0) {
|
|
1582
|
+
emitElementTaken(emitter, element, valueKey(emitter, counted), position);
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
emitElementTaken(emitter, target, valueKey(emitter, over), null);
|
|
1586
|
+
}
|
|
1587
|
+
function emitElementTaken(emitter, target, overKey, position) {
|
|
1588
|
+
const variables = target.type === "identifier" ? [{ node: target, part: null }] : partsTakenApart(target);
|
|
1589
|
+
for (const variable of variables) {
|
|
1590
|
+
const key = valueKey(emitter, variable.node);
|
|
1591
|
+
if (variable.part === null) {
|
|
1592
|
+
add(emitter, "elementOf", key, overKey);
|
|
1593
|
+
continue;
|
|
1594
|
+
}
|
|
1595
|
+
add(emitter, "elementPartOf", key, overKey, variable.part);
|
|
1596
|
+
}
|
|
1597
|
+
const [first] = variables;
|
|
1598
|
+
if (position !== null && first !== void 0) {
|
|
1599
|
+
add(
|
|
1600
|
+
emitter,
|
|
1601
|
+
"positionOf",
|
|
1602
|
+
valueKey(emitter, position),
|
|
1603
|
+
valueKey(emitter, first.node)
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
function partsTakenApart(target) {
|
|
1608
|
+
const parts = [];
|
|
1609
|
+
if (!PAIR_TARGET_TYPES.has(target.type)) {
|
|
1610
|
+
return parts;
|
|
1611
|
+
}
|
|
1612
|
+
for (const [position, part] of children(target).entries()) {
|
|
1613
|
+
if (part.type === "list_splat_pattern") {
|
|
1614
|
+
break;
|
|
1615
|
+
}
|
|
1616
|
+
if (part.type === "identifier") {
|
|
1617
|
+
parts.push({ node: part, part: String(position) });
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
return parts;
|
|
1621
|
+
}
|
|
1622
|
+
function countedCollection(emitter, over) {
|
|
1623
|
+
const callee = over.type === "call" ? field(over, "function") : null;
|
|
1624
|
+
const args = field(over, "arguments");
|
|
1625
|
+
const [first] = callArguments(over);
|
|
1626
|
+
if (callee?.type !== "identifier" || callee.text !== POSITION_COUNTER || !isBuiltin(emitter, POSITION_COUNTER) || args === null || writtenArgumentCount(args) !== 1 || first?.kind !== "positional") {
|
|
1627
|
+
return null;
|
|
1628
|
+
}
|
|
1629
|
+
return first.node;
|
|
1630
|
+
}
|
|
1631
|
+
function interpolatedPieces(emitter, string2) {
|
|
1632
|
+
const parts = children(string2);
|
|
1633
|
+
if (!parts.some((part) => part.type === "interpolation")) {
|
|
1634
|
+
return [];
|
|
1635
|
+
}
|
|
1636
|
+
return parts.flatMap((part) => {
|
|
1637
|
+
if (part.type === "string_content") {
|
|
1638
|
+
return [{ text: stringContentValue(part) }];
|
|
1639
|
+
}
|
|
1640
|
+
const expression = part.type === "interpolation" ? field(part, "expression") ?? children(part)[0] : void 0;
|
|
1641
|
+
return expression === void 0 ? [] : [{ hole: valueKey(emitter, expression) }];
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
function adjacentPieces(emitter, joined2) {
|
|
1645
|
+
return children(joined2).filter((part) => part.type !== "comment").map((part) => ({ hole: valueKey(emitter, part) }));
|
|
1646
|
+
}
|
|
1647
|
+
var TEMPLATE_PIECES = {
|
|
1648
|
+
string: interpolatedPieces,
|
|
1649
|
+
concatenated_string: adjacentPieces
|
|
1650
|
+
};
|
|
1415
1651
|
function emitExpressionFact(emitter, child, type) {
|
|
1416
1652
|
if (type === "call") {
|
|
1417
1653
|
emitCall(emitter, child);
|
|
@@ -1419,6 +1655,7 @@ function emitExpressionFact(emitter, child, type) {
|
|
|
1419
1655
|
if (mapping !== null) {
|
|
1420
1656
|
emitKeyedRead(emitter, child, mapping.container, mapping.key);
|
|
1421
1657
|
}
|
|
1658
|
+
emitAttributeChoice(emitter, child);
|
|
1422
1659
|
}
|
|
1423
1660
|
if (type === "subscript") {
|
|
1424
1661
|
const index = singleSubscript(child);
|
|
@@ -1448,6 +1685,13 @@ function emitExpressionFact(emitter, child, type) {
|
|
|
1448
1685
|
if (COMPREHENSION_TYPES.has(type)) {
|
|
1449
1686
|
emitComprehensionElement(emitter, child);
|
|
1450
1687
|
}
|
|
1688
|
+
if (type === "for_in_clause") {
|
|
1689
|
+
emitElementVariables(emitter, child);
|
|
1690
|
+
}
|
|
1691
|
+
const pieces = TEMPLATE_PIECES[type]?.(emitter, child) ?? [];
|
|
1692
|
+
if (pieces.length > 0) {
|
|
1693
|
+
(0, import_resolution3.addTemplateRows)(rowsOf(emitter), nodeId(emitter.filePath, child), pieces);
|
|
1694
|
+
}
|
|
1451
1695
|
const branches = fallbackBranchesOf(child, type);
|
|
1452
1696
|
if (branches !== null) {
|
|
1453
1697
|
for (const branch of branches) {
|
|
@@ -1480,10 +1724,10 @@ function emitExpressionFacts(emitter, node) {
|
|
|
1480
1724
|
});
|
|
1481
1725
|
}
|
|
1482
1726
|
function yieldedValue(node) {
|
|
1483
|
-
if (node.
|
|
1727
|
+
if (allChildren(node).some((child) => child.type === "from")) {
|
|
1484
1728
|
return null;
|
|
1485
1729
|
}
|
|
1486
|
-
return node.
|
|
1730
|
+
return children(node).find((child) => child?.type !== "comment") ?? null;
|
|
1487
1731
|
}
|
|
1488
1732
|
function emitFunctionFacts(emitter, fn, classKey) {
|
|
1489
1733
|
const funcKey = nodeId(emitter.filePath, fn);
|
|
@@ -1555,7 +1799,7 @@ function emitFunctionFacts(emitter, fn, classKey) {
|
|
|
1555
1799
|
const stores = /* @__PURE__ */ new Map();
|
|
1556
1800
|
const visit = (child, type) => {
|
|
1557
1801
|
if (type === "return_statement") {
|
|
1558
|
-
const returned = child.
|
|
1802
|
+
const returned = child.namedChild(0);
|
|
1559
1803
|
if (returned != null) {
|
|
1560
1804
|
add(inside, "returnsValue", funcKey, valueKey(inside, returned));
|
|
1561
1805
|
statesReturn = true;
|
|
@@ -1966,6 +2210,9 @@ function readUnderName(emitter, statement, funcKey, accessed) {
|
|
|
1966
2210
|
function emitNestedDefinitions(emitter, node) {
|
|
1967
2211
|
for (const child of children(node)) {
|
|
1968
2212
|
const type = child.type;
|
|
2213
|
+
if (type === "decorated_definition") {
|
|
2214
|
+
emitDecoratorCalls(emitter, child);
|
|
2215
|
+
}
|
|
1969
2216
|
if (FUNCTION_TYPES.has(type)) {
|
|
1970
2217
|
emitFunctionFacts(emitter, child);
|
|
1971
2218
|
if (emitter.enclosing !== null) {
|
|
@@ -1985,6 +2232,20 @@ function emitNestedDefinitions(emitter, node) {
|
|
|
1985
2232
|
emitNestedDefinitions(emitter, child);
|
|
1986
2233
|
}
|
|
1987
2234
|
}
|
|
2235
|
+
function emitDecoratorCalls(emitter, decorated) {
|
|
2236
|
+
const { definition, decorators } = stripDecorators(decorated);
|
|
2237
|
+
let applied = nodeId(emitter.filePath, definition);
|
|
2238
|
+
for (const decorator of [...decorators].reverse()) {
|
|
2239
|
+
const [expression] = children(decorator);
|
|
2240
|
+
if (expression === void 0) {
|
|
2241
|
+
continue;
|
|
2242
|
+
}
|
|
2243
|
+
const callKey = nodeId(emitter.filePath, decorator);
|
|
2244
|
+
add(emitter, "call", callKey, valueKey(emitter, expression));
|
|
2245
|
+
add(emitter, "callArg", callKey, "0", applied);
|
|
2246
|
+
applied = callKey;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
1988
2249
|
var readingsByTree = /* @__PURE__ */ new WeakMap();
|
|
1989
2250
|
function scopeReadingOf(fn, given) {
|
|
1990
2251
|
const tree = fn.tree;
|
|
@@ -2593,9 +2854,7 @@ function stringExpression(node) {
|
|
|
2593
2854
|
}
|
|
2594
2855
|
function comparisonExpression(node) {
|
|
2595
2856
|
const operands = children(node);
|
|
2596
|
-
const operators = node.
|
|
2597
|
-
(child) => child !== null && !child.isNamed
|
|
2598
|
-
);
|
|
2857
|
+
const operators = allChildren(node).filter((child) => !child.isNamed);
|
|
2599
2858
|
const operator = operators[0];
|
|
2600
2859
|
if (operands.length !== 2 || operators.length !== 1 || operator === void 0) {
|
|
2601
2860
|
return { kind: "opaque" };
|
|
@@ -2689,6 +2948,7 @@ var STATEMENT_TYPES = {
|
|
|
2689
2948
|
kind: "return",
|
|
2690
2949
|
value: children(node)[0] ?? null
|
|
2691
2950
|
}),
|
|
2951
|
+
raise_statement: (node) => caughtInSameFunction(node) ? OPAQUE : { kind: "throw" },
|
|
2692
2952
|
try_statement: (node) => ({
|
|
2693
2953
|
kind: "block",
|
|
2694
2954
|
body: [
|
|
@@ -2777,6 +3037,19 @@ function blockStatements(block) {
|
|
|
2777
3037
|
function isRoot(node) {
|
|
2778
3038
|
return ROOT_TYPES.has(node.type);
|
|
2779
3039
|
}
|
|
3040
|
+
var EXCEPT_CLAUSE_TYPES = /* @__PURE__ */ new Set(["except_clause", "except_group_clause"]);
|
|
3041
|
+
function caughtInSameFunction(node) {
|
|
3042
|
+
let child = node;
|
|
3043
|
+
let parent = node.parent;
|
|
3044
|
+
while (parent !== null && !isRoot(parent)) {
|
|
3045
|
+
if (parent.type === "try_statement" && field(parent, "body")?.id === child.id && children(parent).some((clause) => EXCEPT_CLAUSE_TYPES.has(clause.type))) {
|
|
3046
|
+
return true;
|
|
3047
|
+
}
|
|
3048
|
+
child = parent;
|
|
3049
|
+
parent = parent.parent;
|
|
3050
|
+
}
|
|
3051
|
+
return false;
|
|
3052
|
+
}
|
|
2780
3053
|
function isPathStatement(node, parent) {
|
|
2781
3054
|
return parent.type === "module" || parent.type === "block" || node.type === "elif_clause";
|
|
2782
3055
|
}
|
|
@@ -3167,6 +3440,10 @@ function writtenNodeOf(node, db) {
|
|
|
3167
3440
|
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3168
3441
|
return bound?.context.writtenTo(node) ?? null;
|
|
3169
3442
|
}
|
|
3443
|
+
function calledDefinition(call, db) {
|
|
3444
|
+
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3445
|
+
return bound?.context.callable(call) ?? null;
|
|
3446
|
+
}
|
|
3170
3447
|
function resolutionKeyOf(node, db) {
|
|
3171
3448
|
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3172
3449
|
return bound?.keyOf(node) ?? null;
|
|
@@ -3389,7 +3666,7 @@ function argShapeOf(node) {
|
|
|
3389
3666
|
if (node.type === "list") {
|
|
3390
3667
|
return {
|
|
3391
3668
|
kind: "list",
|
|
3392
|
-
items: node
|
|
3669
|
+
items: children(node).map(readArg)
|
|
3393
3670
|
};
|
|
3394
3671
|
}
|
|
3395
3672
|
return { kind: "other" };
|
|
@@ -3400,10 +3677,7 @@ function readCallArguments(argumentList) {
|
|
|
3400
3677
|
if (argumentList === null) {
|
|
3401
3678
|
return { args, keywordArgs };
|
|
3402
3679
|
}
|
|
3403
|
-
for (const child of argumentList
|
|
3404
|
-
if (child === null) {
|
|
3405
|
-
continue;
|
|
3406
|
-
}
|
|
3680
|
+
for (const child of children(argumentList)) {
|
|
3407
3681
|
if (child.type === "keyword_argument") {
|
|
3408
3682
|
const nameNode = field(child, "name");
|
|
3409
3683
|
const valueNode = field(child, "value");
|
|
@@ -3447,7 +3721,7 @@ function builtObjectCallee(built, attributeName, objectName) {
|
|
|
3447
3721
|
return { importedName: attributeName, module: agreed, objectName };
|
|
3448
3722
|
}
|
|
3449
3723
|
};
|
|
3450
|
-
return (0,
|
|
3724
|
+
return (0, import_behavioral_ir2.dispatchByType)(table, built);
|
|
3451
3725
|
}
|
|
3452
3726
|
function resolveCallee(expr, module2, facts) {
|
|
3453
3727
|
if (expr.type === "identifier") {
|
|
@@ -3529,10 +3803,10 @@ function unwrapDecorator(decoratorNode, facts) {
|
|
|
3529
3803
|
}
|
|
3530
3804
|
function passesParametersThrough(def, inner) {
|
|
3531
3805
|
const params = field(def, "parameters");
|
|
3532
|
-
const names = (params
|
|
3806
|
+
const names = children(params).filter((child) => child.type === "identifier").map((child) => child.text);
|
|
3533
3807
|
const argumentList = field(inner, "arguments");
|
|
3534
|
-
const positional = (argumentList
|
|
3535
|
-
(child) => child
|
|
3808
|
+
const positional = children(argumentList).filter(
|
|
3809
|
+
(child) => child.type !== "keyword_argument"
|
|
3536
3810
|
);
|
|
3537
3811
|
return positional.length === names.length && positional.every(
|
|
3538
3812
|
(argument, at) => argument.type === "identifier" && argument.text === names[at]
|
|
@@ -3540,13 +3814,14 @@ function passesParametersThrough(def, inner) {
|
|
|
3540
3814
|
}
|
|
3541
3815
|
|
|
3542
3816
|
// src/discovery.ts
|
|
3543
|
-
var
|
|
3544
|
-
var
|
|
3545
|
-
var
|
|
3817
|
+
var import_behavioral_ir6 = require("@suss/behavioral-ir");
|
|
3818
|
+
var import_extractor9 = require("@suss/extractor");
|
|
3819
|
+
var import_values20 = require("@suss/values");
|
|
3546
3820
|
|
|
3547
3821
|
// src/clientCalls.ts
|
|
3548
|
-
var
|
|
3549
|
-
var
|
|
3822
|
+
var import_behavioral_ir3 = require("@suss/behavioral-ir");
|
|
3823
|
+
var import_extractor6 = require("@suss/extractor");
|
|
3824
|
+
var import_values14 = require("@suss/values");
|
|
3550
3825
|
|
|
3551
3826
|
// src/paths/bodyBranches.ts
|
|
3552
3827
|
var import_extractor4 = require("@suss/extractor");
|
|
@@ -3567,7 +3842,7 @@ var COMPARISONS = {
|
|
|
3567
3842
|
"<=": "lte"
|
|
3568
3843
|
};
|
|
3569
3844
|
function operatorText(node) {
|
|
3570
|
-
return node.
|
|
3845
|
+
return allChildren(node).filter((child) => !child.isNamed).map((child) => child.text).join(" ");
|
|
3571
3846
|
}
|
|
3572
3847
|
function valueRefOf(node, facts, inputs) {
|
|
3573
3848
|
const value = evaluatedValue(node, facts);
|
|
@@ -3619,7 +3894,7 @@ function nullCheckOf(subject, negated2, facts, inputs) {
|
|
|
3619
3894
|
};
|
|
3620
3895
|
}
|
|
3621
3896
|
function comparisonOf(node, facts, inputs) {
|
|
3622
|
-
const [left, right] = node.
|
|
3897
|
+
const [left, right] = children(node).filter(
|
|
3623
3898
|
(child) => child !== null
|
|
3624
3899
|
);
|
|
3625
3900
|
if (left === void 0 || right === void 0) {
|
|
@@ -3648,14 +3923,14 @@ function comparisonOf(node, facts, inputs) {
|
|
|
3648
3923
|
}
|
|
3649
3924
|
function predicateOf(node, facts, inputs) {
|
|
3650
3925
|
if (node.type === "parenthesized_expression") {
|
|
3651
|
-
const inner = node.
|
|
3926
|
+
const inner = node.namedChild(0);
|
|
3652
3927
|
return inner == null ? opaqueOf(node) : predicateOf(inner, facts, inputs);
|
|
3653
3928
|
}
|
|
3654
3929
|
if (node.type === "comparison_operator") {
|
|
3655
3930
|
return comparisonOf(node, facts, inputs);
|
|
3656
3931
|
}
|
|
3657
3932
|
if (node.type === "not_operator") {
|
|
3658
|
-
const operand2 = field(node, "argument") ?? node.
|
|
3933
|
+
const operand2 = field(node, "argument") ?? node.namedChild(0);
|
|
3659
3934
|
return operand2 == null ? opaqueOf(node) : { type: "negation", operand: predicateOf(operand2, facts, inputs) };
|
|
3660
3935
|
}
|
|
3661
3936
|
if (node.type === "identifier" || node.type === "attribute" || inputs?.has(node.id) === true) {
|
|
@@ -3670,11 +3945,11 @@ function predicateOf(node, facts, inputs) {
|
|
|
3670
3945
|
var SUBJECT_TYPES = /* @__PURE__ */ new Set(["identifier", "attribute", "subscript"]);
|
|
3671
3946
|
function operandsOf(node) {
|
|
3672
3947
|
if (node.type === "parenthesized_expression" || node.type === "not_operator") {
|
|
3673
|
-
const inner = field(node, "argument") ?? node.
|
|
3948
|
+
const inner = field(node, "argument") ?? node.namedChild(0);
|
|
3674
3949
|
return inner == null ? [] : operandsOf(inner);
|
|
3675
3950
|
}
|
|
3676
3951
|
if (node.type === "comparison_operator") {
|
|
3677
|
-
return node.
|
|
3952
|
+
return children(node).filter(
|
|
3678
3953
|
(child) => child !== null && SUBJECT_TYPES.has(child.type)
|
|
3679
3954
|
);
|
|
3680
3955
|
}
|
|
@@ -3700,7 +3975,7 @@ var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set(["function_definition", "lam
|
|
|
3700
3975
|
function exitKindOf(node, thrown) {
|
|
3701
3976
|
let sawReturn = false;
|
|
3702
3977
|
const raises = (current) => {
|
|
3703
|
-
for (const child of current
|
|
3978
|
+
for (const child of children(current)) {
|
|
3704
3979
|
if (child === null || NESTED_FUNCTION_TYPES.has(child.type)) {
|
|
3705
3980
|
continue;
|
|
3706
3981
|
}
|
|
@@ -3728,12 +4003,10 @@ function blockStatements2(block) {
|
|
|
3728
4003
|
if (block === null) {
|
|
3729
4004
|
return [];
|
|
3730
4005
|
}
|
|
3731
|
-
return block
|
|
4006
|
+
return children(block);
|
|
3732
4007
|
}
|
|
3733
4008
|
function childBlock(node) {
|
|
3734
|
-
return node.
|
|
3735
|
-
(child) => child !== null && child.type === "block"
|
|
3736
|
-
) ?? null;
|
|
4009
|
+
return children(node).find((child) => child.type === "block") ?? null;
|
|
3737
4010
|
}
|
|
3738
4011
|
var Lowerer = class {
|
|
3739
4012
|
// tree-sitter hands back a fresh wrapper object each time a child is
|
|
@@ -3782,7 +4055,7 @@ var Lowerer = class {
|
|
|
3782
4055
|
return [nested];
|
|
3783
4056
|
}
|
|
3784
4057
|
lowerIf(node) {
|
|
3785
|
-
const clauses = node.
|
|
4058
|
+
const clauses = children(node).filter(
|
|
3786
4059
|
(child) => child !== null && (child.type === "elif_clause" || child.type === "else_clause")
|
|
3787
4060
|
);
|
|
3788
4061
|
return {
|
|
@@ -3794,10 +4067,10 @@ var Lowerer = class {
|
|
|
3794
4067
|
};
|
|
3795
4068
|
}
|
|
3796
4069
|
lowerTry(node) {
|
|
3797
|
-
const excepts = node.
|
|
4070
|
+
const excepts = children(node).filter(
|
|
3798
4071
|
(child) => child !== null && (child.type === "except_clause" || child.type === "except_group_clause")
|
|
3799
4072
|
);
|
|
3800
|
-
const finallyClause = node.
|
|
4073
|
+
const finallyClause = children(node).find(
|
|
3801
4074
|
(child) => child !== null && child.type === "finally_clause"
|
|
3802
4075
|
) ?? null;
|
|
3803
4076
|
return {
|
|
@@ -3813,7 +4086,7 @@ var Lowerer = class {
|
|
|
3813
4086
|
(child) => child.type === "case_clause"
|
|
3814
4087
|
);
|
|
3815
4088
|
const groups = cases.map((clause) => {
|
|
3816
|
-
const pattern = clause.
|
|
4089
|
+
const pattern = children(clause).find(
|
|
3817
4090
|
(child) => child !== null && child.type === "case_pattern"
|
|
3818
4091
|
) ?? null;
|
|
3819
4092
|
return {
|
|
@@ -3894,7 +4167,7 @@ function literalArgOf(node, facts) {
|
|
|
3894
4167
|
return null;
|
|
3895
4168
|
}
|
|
3896
4169
|
function bodyCalls(node, found = []) {
|
|
3897
|
-
for (const child of node
|
|
4170
|
+
for (const child of children(node)) {
|
|
3898
4171
|
if (child === null || NESTED_DEFINITION_TYPES.has(child.type)) {
|
|
3899
4172
|
continue;
|
|
3900
4173
|
}
|
|
@@ -3906,7 +4179,7 @@ function bodyCalls(node, found = []) {
|
|
|
3906
4179
|
return found;
|
|
3907
4180
|
}
|
|
3908
4181
|
function moduleLoadCalls(node, found = []) {
|
|
3909
|
-
for (const child of node
|
|
4182
|
+
for (const child of children(node)) {
|
|
3910
4183
|
if (child === null || !runsAtModuleLoad(child)) {
|
|
3911
4184
|
continue;
|
|
3912
4185
|
}
|
|
@@ -3946,7 +4219,7 @@ function argumentNodes(call) {
|
|
|
3946
4219
|
if (args === null) {
|
|
3947
4220
|
return [];
|
|
3948
4221
|
}
|
|
3949
|
-
return args
|
|
4222
|
+
return children(args).map(
|
|
3950
4223
|
(child) => child.type === "keyword_argument" ? field(child, "value") ?? child : child
|
|
3951
4224
|
);
|
|
3952
4225
|
}
|
|
@@ -3957,6 +4230,9 @@ function calleeText(call) {
|
|
|
3957
4230
|
return field(call, "function")?.text ?? call.text;
|
|
3958
4231
|
}
|
|
3959
4232
|
function invocationEffects(definitionNode, facts) {
|
|
4233
|
+
return invocationSites(definitionNode, facts).map((site) => site.effect);
|
|
4234
|
+
}
|
|
4235
|
+
function invocationSites(definitionNode, facts) {
|
|
3960
4236
|
const body = field(definitionNode, "body");
|
|
3961
4237
|
if (body === null) {
|
|
3962
4238
|
return [];
|
|
@@ -3964,14 +4240,18 @@ function invocationEffects(definitionNode, facts) {
|
|
|
3964
4240
|
return invocationEffectsIn(body, bodyCalls(body), facts);
|
|
3965
4241
|
}
|
|
3966
4242
|
function moduleLoadInvocationEffects(moduleNode, facts) {
|
|
3967
|
-
return invocationEffectsIn(
|
|
4243
|
+
return invocationEffectsIn(
|
|
4244
|
+
moduleNode,
|
|
4245
|
+
moduleLoadCalls(moduleNode),
|
|
4246
|
+
facts
|
|
4247
|
+
).map((site) => site.effect);
|
|
3968
4248
|
}
|
|
3969
4249
|
var ASKED_ABOUT_TYPES = /* @__PURE__ */ new Set(["identifier", "attribute", "call"]);
|
|
3970
4250
|
function askedNodesUnder(node, found = []) {
|
|
3971
4251
|
if (ASKED_ABOUT_TYPES.has(node.type)) {
|
|
3972
4252
|
found.push(node);
|
|
3973
4253
|
}
|
|
3974
|
-
for (const child of node
|
|
4254
|
+
for (const child of children(node)) {
|
|
3975
4255
|
if (child !== null && !NESTED_DEFINITION_TYPES.has(child.type)) {
|
|
3976
4256
|
askedNodesUnder(child, found);
|
|
3977
4257
|
}
|
|
@@ -4045,11 +4325,14 @@ function invocationEffectsIn(body, written, facts) {
|
|
|
4045
4325
|
(condition) => predicateOf(condition, facts, inputs)
|
|
4046
4326
|
);
|
|
4047
4327
|
return {
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4328
|
+
call,
|
|
4329
|
+
effect: {
|
|
4330
|
+
type: "invocation",
|
|
4331
|
+
callee: calleeText(call),
|
|
4332
|
+
args: argsOf(call, facts),
|
|
4333
|
+
async: false,
|
|
4334
|
+
...conditions.length > 0 ? { preconditions: conditions } : {}
|
|
4335
|
+
}
|
|
4053
4336
|
};
|
|
4054
4337
|
});
|
|
4055
4338
|
}
|
|
@@ -4084,7 +4367,7 @@ function statedBy(statement, name) {
|
|
|
4084
4367
|
}
|
|
4085
4368
|
if (statement.type === "as_pattern") {
|
|
4086
4369
|
const alias = field(statement, "alias");
|
|
4087
|
-
const value = statement.
|
|
4370
|
+
const value = statement.namedChild(0) ?? null;
|
|
4088
4371
|
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
4089
4372
|
return alias?.text === name ? callee : null;
|
|
4090
4373
|
}
|
|
@@ -4280,7 +4563,7 @@ function importedFunctionMatch(call, options) {
|
|
|
4280
4563
|
return null;
|
|
4281
4564
|
}
|
|
4282
4565
|
const args = field(call, "arguments");
|
|
4283
|
-
const first = args
|
|
4566
|
+
const first = children(args)[0] ?? null;
|
|
4284
4567
|
const statement = first === null ? null : writtenStatement(first, void 0, options.facts);
|
|
4285
4568
|
if (statement === null) {
|
|
4286
4569
|
return null;
|
|
@@ -4644,7 +4927,7 @@ function columnComparisons(node) {
|
|
|
4644
4927
|
const args = field(node, "arguments");
|
|
4645
4928
|
return (args === null ? [] : children(args)).flatMap(columnComparisons);
|
|
4646
4929
|
}
|
|
4647
|
-
const operator = node.
|
|
4930
|
+
const operator = allChildren(node).find((child) => !child.isNamed);
|
|
4648
4931
|
const [left, right, ...rest] = children(node);
|
|
4649
4932
|
if (node.type !== "comparison_operator" || operator?.type !== "==" || left === void 0 || right === void 0 || rest.length > 0) {
|
|
4650
4933
|
return [];
|
|
@@ -4663,13 +4946,37 @@ function modelColumn(node) {
|
|
|
4663
4946
|
}
|
|
4664
4947
|
return field(node, "attribute")?.text ?? null;
|
|
4665
4948
|
}
|
|
4666
|
-
function selectorOf(chain, valueMethods) {
|
|
4949
|
+
function selectorOf(chain, valueMethods, model) {
|
|
4950
|
+
const picking = laterCalls(chain).filter(
|
|
4951
|
+
(call) => !valueMethods.includes(methodNameOf(call))
|
|
4952
|
+
);
|
|
4667
4953
|
return [
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4954
|
+
.../* @__PURE__ */ new Set([
|
|
4955
|
+
...picking.flatMap((call) => pickedBy(call).map((one) => one.name)),
|
|
4956
|
+
...model === null ? [] : picking.flatMap((call) => columnsComparedBy(call, model))
|
|
4957
|
+
])
|
|
4671
4958
|
];
|
|
4672
4959
|
}
|
|
4960
|
+
var COMBINED_TESTS = ["and_", "or_", "not_"];
|
|
4961
|
+
function columnsComparedBy(call, model) {
|
|
4962
|
+
const args = field(call, "arguments");
|
|
4963
|
+
return (args === null ? [] : children(args)).flatMap(
|
|
4964
|
+
(argument) => columnsCompared(argument, model)
|
|
4965
|
+
);
|
|
4966
|
+
}
|
|
4967
|
+
function columnsCompared(node, model) {
|
|
4968
|
+
if (node.type === "call" && COMBINED_TESTS.includes(methodNameOf(node))) {
|
|
4969
|
+
return columnsComparedBy(node, model);
|
|
4970
|
+
}
|
|
4971
|
+
if (node.type !== "comparison_operator") {
|
|
4972
|
+
return [];
|
|
4973
|
+
}
|
|
4974
|
+
return children(node).flatMap((side) => {
|
|
4975
|
+
const object = side.type === "attribute" ? field(side, "object") : null;
|
|
4976
|
+
const column = object?.text === model ? field(side, "attribute") : null;
|
|
4977
|
+
return column === null ? [] : [column.text];
|
|
4978
|
+
});
|
|
4979
|
+
}
|
|
4673
4980
|
var TABLE_METHODS = ["select_from", "join"];
|
|
4674
4981
|
function modelOf(chain, options) {
|
|
4675
4982
|
const fromRoot = modelArgument(chain.root, chain.root, options);
|
|
@@ -4734,14 +5041,15 @@ function isClassName(name) {
|
|
|
4734
5041
|
}
|
|
4735
5042
|
function effectFor2(pattern, chain, operation, options) {
|
|
4736
5043
|
const valueMethods = pattern.valueMethods ?? [];
|
|
4737
|
-
const
|
|
5044
|
+
const model = modelOf(chain, options);
|
|
5045
|
+
const picked = selectorOf(chain, valueMethods, model);
|
|
4738
5046
|
const effect = {
|
|
4739
5047
|
type: "interaction",
|
|
4740
5048
|
binding: (0, import_ir_core2.storageBinding)({
|
|
4741
5049
|
recognition: "python-storage",
|
|
4742
5050
|
storageSystem: pattern.storageSystem,
|
|
4743
5051
|
scope: "default",
|
|
4744
|
-
container:
|
|
5052
|
+
container: model
|
|
4745
5053
|
}),
|
|
4746
5054
|
callee: chain.last.text,
|
|
4747
5055
|
interaction: {
|
|
@@ -5017,10 +5325,7 @@ function literalAt(key, facts) {
|
|
|
5017
5325
|
|
|
5018
5326
|
// src/paths/bodyBranches.ts
|
|
5019
5327
|
function returnStatements(node, found = []) {
|
|
5020
|
-
for (const child of node
|
|
5021
|
-
if (child === null) {
|
|
5022
|
-
continue;
|
|
5023
|
-
}
|
|
5328
|
+
for (const child of children(node)) {
|
|
5024
5329
|
if (child.type === "function_definition" || child.type === "lambda") {
|
|
5025
5330
|
continue;
|
|
5026
5331
|
}
|
|
@@ -5077,7 +5382,8 @@ function enumerateBodyBranches(options) {
|
|
|
5077
5382
|
const enumerated = (0, import_extractor4.enumerateOrDegrade)(
|
|
5078
5383
|
{
|
|
5079
5384
|
statements: lowered.statements,
|
|
5080
|
-
terminalsByStmt: lowered.terminalsByStmt
|
|
5385
|
+
terminalsByStmt: lowered.terminalsByStmt,
|
|
5386
|
+
...options.keepsArms === void 0 ? {} : { keepsArms: options.keepsArms }
|
|
5081
5387
|
},
|
|
5082
5388
|
statements
|
|
5083
5389
|
);
|
|
@@ -5114,57 +5420,287 @@ function enumerateBodyBranches(options) {
|
|
|
5114
5420
|
return branches;
|
|
5115
5421
|
}
|
|
5116
5422
|
|
|
5117
|
-
// src/
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
continue;
|
|
5124
|
-
}
|
|
5125
|
-
for (const call of bodyCalls(definition)) {
|
|
5126
|
-
for (const request of requestCalls(call, pattern, module2, options)) {
|
|
5127
|
-
units.push(
|
|
5128
|
-
clientUnit(definition, name, request, pattern, pack, options)
|
|
5129
|
-
);
|
|
5130
|
-
}
|
|
5131
|
-
}
|
|
5423
|
+
// src/paths/raisedResponses.ts
|
|
5424
|
+
var import_values12 = require("@suss/values");
|
|
5425
|
+
function statusNumberOf(node, options) {
|
|
5426
|
+
const value = (0, import_values12.constantOf)(evaluatedValue(node, options.facts));
|
|
5427
|
+
if (typeof value === "number") {
|
|
5428
|
+
return value;
|
|
5132
5429
|
}
|
|
5133
|
-
|
|
5430
|
+
const origin = originOf(node, options.module);
|
|
5431
|
+
return origin === null ? null : options.constants?.[`${origin.module}.${origin.name}`] ?? null;
|
|
5134
5432
|
}
|
|
5135
|
-
|
|
5433
|
+
var NESTED_DEFINITION_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
5434
|
+
function raisedResponses(body, options) {
|
|
5435
|
+
if (options.calls.length === 0) {
|
|
5436
|
+
return [];
|
|
5437
|
+
}
|
|
5438
|
+
return raisesIn(body, options);
|
|
5439
|
+
}
|
|
5440
|
+
function raisesIn(body, options) {
|
|
5441
|
+
if (body === null) {
|
|
5442
|
+
return [];
|
|
5443
|
+
}
|
|
5136
5444
|
const found = [];
|
|
5137
|
-
|
|
5138
|
-
for (const
|
|
5139
|
-
|
|
5140
|
-
if (callee === null || originOf(callee, module2) !== null) {
|
|
5445
|
+
const walk = (node) => {
|
|
5446
|
+
for (const child of children(node)) {
|
|
5447
|
+
if (child === null || NESTED_DEFINITION_TYPES2.has(child.type)) {
|
|
5141
5448
|
continue;
|
|
5142
5449
|
}
|
|
5143
|
-
const
|
|
5144
|
-
if (
|
|
5145
|
-
found.push(
|
|
5450
|
+
const response = raisedResponseOf(child, options);
|
|
5451
|
+
if (response !== null) {
|
|
5452
|
+
found.push(response);
|
|
5146
5453
|
}
|
|
5454
|
+
walk(child);
|
|
5147
5455
|
}
|
|
5148
|
-
}
|
|
5456
|
+
};
|
|
5457
|
+
walk(body);
|
|
5149
5458
|
return found;
|
|
5150
5459
|
}
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
functionDefinitions(child, found);
|
|
5460
|
+
var ENDING_EXPRESSION = {
|
|
5461
|
+
raise_statement: (statement) => statement.namedChild(0) ?? null,
|
|
5462
|
+
expression_statement: (statement) => {
|
|
5463
|
+
const only = statement.namedChild(0);
|
|
5464
|
+
return only?.type === "call" ? only : null;
|
|
5157
5465
|
}
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
if (attribute === null) {
|
|
5164
|
-
return [];
|
|
5466
|
+
};
|
|
5467
|
+
function raisedResponseOf(statement, options) {
|
|
5468
|
+
const expression = ENDING_EXPRESSION[statement.type]?.(statement) ?? null;
|
|
5469
|
+
if (expression === null) {
|
|
5470
|
+
return null;
|
|
5165
5471
|
}
|
|
5166
|
-
const
|
|
5167
|
-
|
|
5472
|
+
const thrownByCall = statement.type !== "raise_statement";
|
|
5473
|
+
const prebuilt = thrownByCall ? null : prebuiltCallOf(expression, options);
|
|
5474
|
+
if (prebuilt !== null) {
|
|
5475
|
+
return {
|
|
5476
|
+
statement,
|
|
5477
|
+
thrownByCall,
|
|
5478
|
+
terminal: terminalOf(
|
|
5479
|
+
statement,
|
|
5480
|
+
calleeOf(prebuilt.call, prebuilt.call),
|
|
5481
|
+
prebuilt.call,
|
|
5482
|
+
prebuilt.declared,
|
|
5483
|
+
prebuilt.options
|
|
5484
|
+
)
|
|
5485
|
+
};
|
|
5486
|
+
}
|
|
5487
|
+
const call = expression.type === "call" ? expression : null;
|
|
5488
|
+
const callee = calleeOf(expression, call);
|
|
5489
|
+
const declared = declaredCallFor(callee, options);
|
|
5490
|
+
if (declared === void 0 && thrownByCall) {
|
|
5491
|
+
return null;
|
|
5492
|
+
}
|
|
5493
|
+
return {
|
|
5494
|
+
statement,
|
|
5495
|
+
thrownByCall,
|
|
5496
|
+
terminal: terminalOf(statement, callee, call, declared, options)
|
|
5497
|
+
};
|
|
5498
|
+
}
|
|
5499
|
+
function prebuiltCallOf(expression, options) {
|
|
5500
|
+
if (expression.type !== "identifier" && expression.type !== "attribute") {
|
|
5501
|
+
return null;
|
|
5502
|
+
}
|
|
5503
|
+
const written = writtenNodeOf(expression, options.facts);
|
|
5504
|
+
if (written === null || written.type !== "call") {
|
|
5505
|
+
return null;
|
|
5506
|
+
}
|
|
5507
|
+
const inItsFile = { ...options, module: moduleOf(written) };
|
|
5508
|
+
const declared = declaredCallFor(calleeOf(written, written), inItsFile);
|
|
5509
|
+
return declared === void 0 ? null : { call: written, declared, options: inItsFile };
|
|
5510
|
+
}
|
|
5511
|
+
function returnedResponseStatus(statement, options) {
|
|
5512
|
+
const returned = statement.namedChild(0);
|
|
5513
|
+
if (options.calls.length === 0 || returned === void 0 || returned === null || returned.type !== "call") {
|
|
5514
|
+
return null;
|
|
5515
|
+
}
|
|
5516
|
+
const callee = field(returned, "function");
|
|
5517
|
+
if (callee === null) {
|
|
5518
|
+
return null;
|
|
5519
|
+
}
|
|
5520
|
+
const declared = declaredCallFor(callee, options);
|
|
5521
|
+
return declared === void 0 ? null : statusOf(declared, returned, options);
|
|
5522
|
+
}
|
|
5523
|
+
function calleeOf(expression, call) {
|
|
5524
|
+
return call === null ? expression : field(call, "function") ?? expression;
|
|
5525
|
+
}
|
|
5526
|
+
function declaredCallFor(callee, options) {
|
|
5527
|
+
const origin = originOf(callee, options.module);
|
|
5528
|
+
if (origin === null) {
|
|
5529
|
+
return void 0;
|
|
5530
|
+
}
|
|
5531
|
+
const qualified = `${origin.module}.${origin.name}`;
|
|
5532
|
+
return options.calls.find((call) => call.callee === qualified);
|
|
5533
|
+
}
|
|
5534
|
+
function terminalOf(statement, callee, call, declared, options) {
|
|
5535
|
+
return {
|
|
5536
|
+
kind: "throw",
|
|
5537
|
+
statusCode: declared === void 0 ? null : statusOf(declared, call, options),
|
|
5538
|
+
body: null,
|
|
5539
|
+
exceptionType: lastSegmentOf(declared?.callee ?? callee.text),
|
|
5540
|
+
message: call === null ? null : writtenMessageOf(call),
|
|
5541
|
+
...declared === void 0 ? {} : { producesResponse: true },
|
|
5542
|
+
component: null,
|
|
5543
|
+
renderTree: null,
|
|
5544
|
+
delegateTarget: null,
|
|
5545
|
+
emitEvent: null,
|
|
5546
|
+
location: rangeOf(statement)
|
|
5547
|
+
};
|
|
5548
|
+
}
|
|
5549
|
+
function lastSegmentOf(dotted) {
|
|
5550
|
+
const segment = dotted.split(".").pop();
|
|
5551
|
+
return segment === void 0 || segment === "" ? null : segment;
|
|
5552
|
+
}
|
|
5553
|
+
function statusOf(declared, call, options) {
|
|
5554
|
+
const written = call === null ? null : statusArgumentOf(declared, call);
|
|
5555
|
+
if (written === null) {
|
|
5556
|
+
return declared.defaultStatusCode === void 0 ? null : { type: "literal", value: declared.defaultStatusCode };
|
|
5557
|
+
}
|
|
5558
|
+
const value = statusNumberOf(written, options);
|
|
5559
|
+
return value === null ? { type: "dynamic", sourceText: written.text } : { type: "literal", value };
|
|
5560
|
+
}
|
|
5561
|
+
function argumentsOf2(call) {
|
|
5562
|
+
return children(field(call, "arguments"));
|
|
5563
|
+
}
|
|
5564
|
+
function statusArgumentOf(declared, call) {
|
|
5565
|
+
const args = argumentsOf2(call);
|
|
5566
|
+
const keyed = args.find(
|
|
5567
|
+
(arg) => arg.type === "keyword_argument" && field(arg, "name")?.text === declared.statusKeyword
|
|
5568
|
+
);
|
|
5569
|
+
if (keyed !== void 0) {
|
|
5570
|
+
return field(keyed, "value");
|
|
5571
|
+
}
|
|
5572
|
+
if (declared.statusArgument === void 0) {
|
|
5573
|
+
return null;
|
|
5574
|
+
}
|
|
5575
|
+
const positional = args.filter((arg) => arg.type !== "keyword_argument");
|
|
5576
|
+
return positional[declared.statusArgument] ?? null;
|
|
5577
|
+
}
|
|
5578
|
+
function writtenMessageOf(call) {
|
|
5579
|
+
for (const arg of argumentsOf2(call)) {
|
|
5580
|
+
const value = arg.type === "keyword_argument" ? field(arg, "value") : arg;
|
|
5581
|
+
const literal = value === null ? null : stringLiteralValue(value);
|
|
5582
|
+
if (literal !== null) {
|
|
5583
|
+
return literal;
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
return null;
|
|
5587
|
+
}
|
|
5588
|
+
|
|
5589
|
+
// src/responseHandOff.ts
|
|
5590
|
+
var import_extractor5 = require("@suss/extractor");
|
|
5591
|
+
function throughResponseHelpers(branches, sites, options) {
|
|
5592
|
+
const handOffs = [];
|
|
5593
|
+
for (const { call, effect } of sites) {
|
|
5594
|
+
const helper = helperBranchesAt(call, options);
|
|
5595
|
+
if (helper !== null) {
|
|
5596
|
+
handOffs.push({
|
|
5597
|
+
helper,
|
|
5598
|
+
preconditions: effect.preconditions,
|
|
5599
|
+
line: rangeOf(call).start,
|
|
5600
|
+
at: rangeOf(call)
|
|
5601
|
+
});
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
return handOffs.length === 0 ? [...branches] : branches.flatMap((branch) => (0, import_extractor5.splitAtHandOffs)(branch, handOffs));
|
|
5605
|
+
}
|
|
5606
|
+
function helperBranchesAt(call, options) {
|
|
5607
|
+
const handed = callArguments(call).filter(
|
|
5608
|
+
(argument) => argument.node.type === "identifier" && refersToResponse(argument.node, options)
|
|
5609
|
+
);
|
|
5610
|
+
if (handed.length === 0) {
|
|
5611
|
+
return null;
|
|
5612
|
+
}
|
|
5613
|
+
const helper = calledDefinition(call, options.facts);
|
|
5614
|
+
if (helper === null || helper.type !== "function_definition") {
|
|
5615
|
+
return null;
|
|
5616
|
+
}
|
|
5617
|
+
const passed = /* @__PURE__ */ new Map();
|
|
5618
|
+
const parameters = parameterShapes(helper, isMethod(helper) ? 1 : 0);
|
|
5619
|
+
for (const argument of handed) {
|
|
5620
|
+
const parameter = parameters.find(
|
|
5621
|
+
(one) => argument.kind === "positional" ? one.position === argument.position : one.name === argument.name
|
|
5622
|
+
);
|
|
5623
|
+
if (parameter !== void 0) {
|
|
5624
|
+
passed.set(parameter.name, argument.node.text);
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
return passed.size === 0 ? null : (0, import_extractor5.helperPathsOnVariables)(options.readHelper(helper), passed);
|
|
5628
|
+
}
|
|
5629
|
+
function refersToResponse(name, options) {
|
|
5630
|
+
const written = awaited(writtenNodeOf(name, options.facts));
|
|
5631
|
+
if (written === null) {
|
|
5632
|
+
return false;
|
|
5633
|
+
}
|
|
5634
|
+
if (sameNode(written, options.request)) {
|
|
5635
|
+
return true;
|
|
5636
|
+
}
|
|
5637
|
+
const callee = written.type === "call" ? field(written, "function") : null;
|
|
5638
|
+
const method = callee === null ? null : field(callee, "attribute");
|
|
5639
|
+
const receiver = callee === null ? null : field(callee, "object");
|
|
5640
|
+
if (method === null || receiver?.type !== "identifier" || !options.bodyMethods.includes(method.text)) {
|
|
5641
|
+
return false;
|
|
5642
|
+
}
|
|
5643
|
+
const parsedFrom = awaited(writtenNodeOf(receiver, options.facts));
|
|
5644
|
+
return parsedFrom !== null && sameNode(parsedFrom, options.request);
|
|
5645
|
+
}
|
|
5646
|
+
function awaited(node) {
|
|
5647
|
+
return node?.type === "await" ? node.namedChild(0) ?? null : node;
|
|
5648
|
+
}
|
|
5649
|
+
function sameNode(a, b) {
|
|
5650
|
+
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.tree === b.tree;
|
|
5651
|
+
}
|
|
5652
|
+
|
|
5653
|
+
// src/clientCalls.ts
|
|
5654
|
+
function clientCallUnits(root, module2, pack, pattern, options) {
|
|
5655
|
+
const units = [];
|
|
5656
|
+
for (const definition of functionDefinitions(root)) {
|
|
5657
|
+
const name = field(definition, "name")?.text;
|
|
5658
|
+
if (name === void 0) {
|
|
5659
|
+
continue;
|
|
5660
|
+
}
|
|
5661
|
+
for (const call of bodyCalls(definition)) {
|
|
5662
|
+
for (const request of requestCalls(call, pattern, module2, options)) {
|
|
5663
|
+
units.push(
|
|
5664
|
+
clientUnit(definition, name, request, pattern, pack, options)
|
|
5665
|
+
);
|
|
5666
|
+
}
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
return units;
|
|
5670
|
+
}
|
|
5671
|
+
function clientCallReceivers(root, module2) {
|
|
5672
|
+
const found = [];
|
|
5673
|
+
for (const definition of functionDefinitions(root)) {
|
|
5674
|
+
for (const call of bodyCalls(definition)) {
|
|
5675
|
+
const callee = field(call, "function");
|
|
5676
|
+
if (callee === null || originOf(callee, module2) !== null) {
|
|
5677
|
+
continue;
|
|
5678
|
+
}
|
|
5679
|
+
const object = field(callee, "object");
|
|
5680
|
+
if (object !== null && field(callee, "attribute") !== null) {
|
|
5681
|
+
found.push(object);
|
|
5682
|
+
}
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
return found;
|
|
5686
|
+
}
|
|
5687
|
+
function functionDefinitions(node, found = []) {
|
|
5688
|
+
for (const child of children(node)) {
|
|
5689
|
+
if (isFunction(child)) {
|
|
5690
|
+
found.push(child);
|
|
5691
|
+
}
|
|
5692
|
+
functionDefinitions(child, found);
|
|
5693
|
+
}
|
|
5694
|
+
return found;
|
|
5695
|
+
}
|
|
5696
|
+
function requestCalls(call, pattern, module2, options) {
|
|
5697
|
+
const callee = field(call, "function");
|
|
5698
|
+
const attribute = callee === null ? null : calledAttribute(callee, pattern, module2, options.facts);
|
|
5699
|
+
if (attribute === null) {
|
|
5700
|
+
return [];
|
|
5701
|
+
}
|
|
5702
|
+
const plain = requestCall(call, attribute, pattern, options);
|
|
5703
|
+
if (plain !== null && !(0, import_behavioral_ir3.hasNameHole)(plain.path)) {
|
|
5168
5704
|
return [plain];
|
|
5169
5705
|
}
|
|
5170
5706
|
const byBoundary = /* @__PURE__ */ new Map();
|
|
@@ -5173,7 +5709,7 @@ function requestCalls(call, pattern, module2, options) {
|
|
|
5173
5709
|
if (stated === null) {
|
|
5174
5710
|
continue;
|
|
5175
5711
|
}
|
|
5176
|
-
const key = `${stated.method} ${stated.path}`;
|
|
5712
|
+
const key = `${stated.method} ${stated.host ?? ""} ${stated.path}`;
|
|
5177
5713
|
if (!byBoundary.has(key)) {
|
|
5178
5714
|
byBoundary.set(key, stated);
|
|
5179
5715
|
}
|
|
@@ -5184,16 +5720,33 @@ function requestCalls(call, pattern, module2, options) {
|
|
|
5184
5720
|
return plain === null ? [] : [plain];
|
|
5185
5721
|
}
|
|
5186
5722
|
function requestCall(call, attribute, pattern, options, site) {
|
|
5723
|
+
const stated = methodAndPath(call, attribute, pattern, options, site);
|
|
5724
|
+
if (stated === null) {
|
|
5725
|
+
return null;
|
|
5726
|
+
}
|
|
5727
|
+
const redirectDelivery = redirectDeliveryAt(call, pattern, options, site);
|
|
5728
|
+
return redirectDelivery === void 0 ? stated : { ...stated, redirectDelivery };
|
|
5729
|
+
}
|
|
5730
|
+
function redirectDeliveryAt(call, pattern, options, site) {
|
|
5731
|
+
const option = pattern.response?.redirectOption;
|
|
5732
|
+
const argument = option === void 0 ? null : argumentAt(call, null, option.name);
|
|
5733
|
+
if (option === void 0 || argument === null) {
|
|
5734
|
+
return void 0;
|
|
5735
|
+
}
|
|
5736
|
+
const value = (0, import_values14.scalarOf)(evaluatedValue(argument, options.facts, site));
|
|
5737
|
+
return value === null ? void 0 : (0, import_extractor6.redirectDeliveryWhenSet)(option, value);
|
|
5738
|
+
}
|
|
5739
|
+
function methodAndPath(call, attribute, pattern, options, site) {
|
|
5187
5740
|
const verb = pattern.verbAttributeNames[attribute];
|
|
5188
5741
|
if (verb !== void 0) {
|
|
5189
|
-
const
|
|
5742
|
+
const target2 = urlAt(
|
|
5190
5743
|
call,
|
|
5191
5744
|
pattern.url.position,
|
|
5192
5745
|
pattern.url.keyword,
|
|
5193
5746
|
options,
|
|
5194
5747
|
site
|
|
5195
5748
|
);
|
|
5196
|
-
return
|
|
5749
|
+
return target2 === null ? null : { method: verb, ...target2, range: rangeOf(call), node: call };
|
|
5197
5750
|
}
|
|
5198
5751
|
const methodCall = pattern.methodCall;
|
|
5199
5752
|
if (methodCall === void 0 || methodCall.attribute !== attribute) {
|
|
@@ -5208,14 +5761,19 @@ function requestCall(call, attribute, pattern, options, site) {
|
|
|
5208
5761
|
if (method === null) {
|
|
5209
5762
|
return null;
|
|
5210
5763
|
}
|
|
5211
|
-
const
|
|
5764
|
+
const target = urlAt(
|
|
5212
5765
|
call,
|
|
5213
5766
|
methodCall.urlPosition,
|
|
5214
5767
|
pattern.url.keyword,
|
|
5215
5768
|
options,
|
|
5216
5769
|
site
|
|
5217
5770
|
);
|
|
5218
|
-
return
|
|
5771
|
+
return target === null ? null : {
|
|
5772
|
+
method: method.toUpperCase(),
|
|
5773
|
+
...target,
|
|
5774
|
+
range: rangeOf(call),
|
|
5775
|
+
node: call
|
|
5776
|
+
};
|
|
5219
5777
|
}
|
|
5220
5778
|
function calledAttribute(callee, pattern, module2, facts) {
|
|
5221
5779
|
const origin = originOf(callee, module2);
|
|
@@ -5248,7 +5806,9 @@ function urlAt(call, position, keyword, options, site) {
|
|
|
5248
5806
|
if (argument === null) {
|
|
5249
5807
|
return null;
|
|
5250
5808
|
}
|
|
5251
|
-
|
|
5809
|
+
const value = evaluatedValue(argument, options.facts, site);
|
|
5810
|
+
const path8 = (0, import_values14.pathOf)(value);
|
|
5811
|
+
return path8 === void 0 ? null : { path: path8, host: (0, import_values14.hostOf)(value) };
|
|
5252
5812
|
}
|
|
5253
5813
|
function argumentAt(call, position, keyword) {
|
|
5254
5814
|
const args = field(call, "arguments");
|
|
@@ -5266,25 +5826,33 @@ function argumentAt(call, position, keyword) {
|
|
|
5266
5826
|
}
|
|
5267
5827
|
positional.push(child);
|
|
5268
5828
|
}
|
|
5269
|
-
return positional[position] ?? null;
|
|
5829
|
+
return position === null ? null : positional[position] ?? null;
|
|
5270
5830
|
}
|
|
5271
|
-
function callerBranches(definition,
|
|
5831
|
+
function callerBranches(definition, reading) {
|
|
5832
|
+
const range = rangeOf(definition);
|
|
5272
5833
|
const body = field(definition, "body");
|
|
5273
|
-
const
|
|
5274
|
-
const
|
|
5275
|
-
if (body === null
|
|
5834
|
+
const sites = invocationSites(definition, reading.facts);
|
|
5835
|
+
const effects = sites.map((site) => site.effect);
|
|
5836
|
+
if (body === null) {
|
|
5276
5837
|
return [handsBack(range, effects)];
|
|
5277
5838
|
}
|
|
5839
|
+
const raised = raisesIn(body, {
|
|
5840
|
+
calls: [],
|
|
5841
|
+
module: moduleOf(definition),
|
|
5842
|
+
facts: reading.facts
|
|
5843
|
+
});
|
|
5278
5844
|
const branches = enumerateBodyBranches({
|
|
5279
5845
|
body,
|
|
5280
|
-
terminals,
|
|
5281
|
-
raised
|
|
5846
|
+
terminals: bodyTerminals(body, raised),
|
|
5847
|
+
raised,
|
|
5282
5848
|
effects,
|
|
5283
|
-
branchOf: (
|
|
5849
|
+
branchOf: (found2) => found2.type === "raise" ? { terminal: found2.terminal, location: rangeOf(found2.statement) } : handsBackAt(rangeOf(found2.statement)),
|
|
5284
5850
|
fallthrough: handsBackAt(range),
|
|
5285
|
-
facts
|
|
5851
|
+
facts: reading.facts,
|
|
5852
|
+
keepsArms: (condition) => (0, import_behavioral_ir3.testsStatus)(predicateOf(condition, reading.facts), reading.statusMembers)
|
|
5286
5853
|
});
|
|
5287
|
-
|
|
5854
|
+
const found = branches.length === 0 ? [handsBack(range, effects)] : branches;
|
|
5855
|
+
return reading.handOff === void 0 ? found : throughResponseHelpers(found, sites, reading.handOff);
|
|
5288
5856
|
}
|
|
5289
5857
|
function handsBackAt(range) {
|
|
5290
5858
|
return {
|
|
@@ -5320,11 +5888,24 @@ function responseAccessors(pattern) {
|
|
|
5320
5888
|
...response.body === void 0 ? {} : { bodyAccessors: response.body },
|
|
5321
5889
|
...response.statusCode === void 0 ? {} : { statusAccessors: response.statusCode },
|
|
5322
5890
|
...response.success === void 0 ? {} : { successAccessors: response.success },
|
|
5323
|
-
...response.failureDelivery === void 0 ? {} : { failureDelivery: response.failureDelivery }
|
|
5891
|
+
...response.failureDelivery === void 0 ? {} : { failureDelivery: response.failureDelivery },
|
|
5892
|
+
...response.redirectDelivery === void 0 ? {} : { redirectDelivery: response.redirectDelivery }
|
|
5324
5893
|
};
|
|
5325
5894
|
}
|
|
5326
5895
|
function clientUnit(definition, name, request, pattern, pack, options) {
|
|
5327
5896
|
const range = rangeOf(definition);
|
|
5897
|
+
const accessors = responseAccessors(pattern);
|
|
5898
|
+
const statusMembers = (0, import_behavioral_ir3.statusMembersOf)(accessors);
|
|
5899
|
+
const reading = {
|
|
5900
|
+
facts: options.facts,
|
|
5901
|
+
statusMembers,
|
|
5902
|
+
handOff: {
|
|
5903
|
+
request: request.node,
|
|
5904
|
+
bodyMethods: accessors.bodyAccessors ?? [],
|
|
5905
|
+
facts: options.facts,
|
|
5906
|
+
readHelper: (helper) => callerBranches(helper, { facts: options.facts, statusMembers })
|
|
5907
|
+
}
|
|
5908
|
+
};
|
|
5328
5909
|
return {
|
|
5329
5910
|
identity: {
|
|
5330
5911
|
name,
|
|
@@ -5336,15 +5917,17 @@ function clientUnit(definition, name, request, pattern, pack, options) {
|
|
|
5336
5917
|
exportName: name,
|
|
5337
5918
|
exportPath: [name]
|
|
5338
5919
|
},
|
|
5339
|
-
boundaryBinding: (0,
|
|
5920
|
+
boundaryBinding: (0, import_behavioral_ir3.restBinding)({
|
|
5340
5921
|
transport: pack.protocol,
|
|
5341
5922
|
method: request.method,
|
|
5342
5923
|
path: request.path,
|
|
5924
|
+
host: request.host,
|
|
5343
5925
|
recognition: pack.name
|
|
5344
5926
|
}),
|
|
5345
5927
|
parameters: [],
|
|
5346
|
-
branches: callerBranches(definition,
|
|
5347
|
-
...
|
|
5928
|
+
branches: callerBranches(definition, reading),
|
|
5929
|
+
...accessors,
|
|
5930
|
+
...request.redirectDelivery === void 0 ? {} : { redirectDelivery: request.redirectDelivery },
|
|
5348
5931
|
bodyContent: "statements",
|
|
5349
5932
|
dependencyCalls: [],
|
|
5350
5933
|
declaredContract: null
|
|
@@ -5388,8 +5971,8 @@ function routeOnDroppedApp(facts, object, constructionKey, pattern) {
|
|
|
5388
5971
|
}
|
|
5389
5972
|
|
|
5390
5973
|
// src/envReads.ts
|
|
5391
|
-
var
|
|
5392
|
-
var
|
|
5974
|
+
var import_behavioral_ir4 = require("@suss/behavioral-ir");
|
|
5975
|
+
var import_extractor7 = require("@suss/extractor");
|
|
5393
5976
|
var import_resolution7 = require("@suss/resolution");
|
|
5394
5977
|
|
|
5395
5978
|
// src/envSpellings.ts
|
|
@@ -5567,7 +6150,7 @@ function isTestedAt(parent, child, subject, seen) {
|
|
|
5567
6150
|
}
|
|
5568
6151
|
function conditionOf(node) {
|
|
5569
6152
|
if (node.type === "conditional_expression") {
|
|
5570
|
-
return node.
|
|
6153
|
+
return node.namedChild(1) ?? null;
|
|
5571
6154
|
}
|
|
5572
6155
|
return CONDITIONED_TYPES.has(node.type) ? field(node, "condition") : null;
|
|
5573
6156
|
}
|
|
@@ -5590,7 +6173,7 @@ function isPresentAt(node, subject) {
|
|
|
5590
6173
|
}
|
|
5591
6174
|
function isBranchWherePresent(parent, child, subject) {
|
|
5592
6175
|
if (parent.type === "conditional_expression") {
|
|
5593
|
-
const [whenTrue, test2, whenFalse] = parent
|
|
6176
|
+
const [whenTrue, test2, whenFalse] = children(parent);
|
|
5594
6177
|
return test2 !== void 0 && test2 !== null && (whenTrue?.id === child.id && isPresentWhen(test2, true, subject) || whenFalse?.id === child.id && isPresentWhen(test2, false, subject));
|
|
5595
6178
|
}
|
|
5596
6179
|
if (parent.type === "boolean_operator") {
|
|
@@ -5628,7 +6211,7 @@ function followsExitWhenAbsent(parent, child, subject) {
|
|
|
5628
6211
|
if (parent.type !== "block" && parent.type !== "module") {
|
|
5629
6212
|
return false;
|
|
5630
6213
|
}
|
|
5631
|
-
const statements = parent
|
|
6214
|
+
const statements = children(parent);
|
|
5632
6215
|
const at = statements.findIndex((statement) => statement?.id === child.id);
|
|
5633
6216
|
return statements.slice(0, at).some(
|
|
5634
6217
|
(statement) => statement !== null && leavesWhenAbsent(statement, subject)
|
|
@@ -5672,7 +6255,7 @@ function continuationRaises(from) {
|
|
|
5672
6255
|
let parent = current.parent;
|
|
5673
6256
|
while (parent !== null) {
|
|
5674
6257
|
if (parent.type === "block" || parent.type === "module") {
|
|
5675
|
-
const statements = parent
|
|
6258
|
+
const statements = children(parent);
|
|
5676
6259
|
const at = statements.findIndex((one) => one?.id === current.id);
|
|
5677
6260
|
const exit = firstExit(statements.slice(at + 1));
|
|
5678
6261
|
if (exit !== null) {
|
|
@@ -5716,7 +6299,7 @@ function exitOf(statement) {
|
|
|
5716
6299
|
if (LEAVING_TYPES.has(statement.type)) {
|
|
5717
6300
|
return "leave";
|
|
5718
6301
|
}
|
|
5719
|
-
return statement.type === "block" ? firstExit(statement
|
|
6302
|
+
return statement.type === "block" ? firstExit(children(statement)) : null;
|
|
5720
6303
|
}
|
|
5721
6304
|
function isPresentWhen(test, outcome, subject) {
|
|
5722
6305
|
const expression = peelParens(test);
|
|
@@ -5756,7 +6339,7 @@ function isPresentAfterComparison(comparison, outcome, subject) {
|
|
|
5756
6339
|
}
|
|
5757
6340
|
function comparisonParts(comparison) {
|
|
5758
6341
|
const operators = fields(comparison, "operators");
|
|
5759
|
-
const operands = comparison.
|
|
6342
|
+
const operands = children(comparison).filter(
|
|
5760
6343
|
(child) => child !== null && !operators.some((one) => one.id === child.id)
|
|
5761
6344
|
);
|
|
5762
6345
|
const [left, right] = operands;
|
|
@@ -5779,7 +6362,7 @@ function comparedWithNone(comparison) {
|
|
|
5779
6362
|
}
|
|
5780
6363
|
var NONE_OPERATORS = /* @__PURE__ */ new Set(["is", "is not", "==", "!="]);
|
|
5781
6364
|
function peelParens(node) {
|
|
5782
|
-
const inner = node.type === "parenthesized_expression" ? node.
|
|
6365
|
+
const inner = node.type === "parenthesized_expression" ? node.namedChild(0) : null;
|
|
5783
6366
|
return inner === null || inner === void 0 ? node : peelParens(inner);
|
|
5784
6367
|
}
|
|
5785
6368
|
function climbParens(node) {
|
|
@@ -5837,7 +6420,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5837
6420
|
const slots = [];
|
|
5838
6421
|
const readsHelpers = facts !== void 0 && sitesByDb.has(facts);
|
|
5839
6422
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
5840
|
-
(0,
|
|
6423
|
+
(0, import_extractor7.walkDescendants)(root, startScope, children, {
|
|
5841
6424
|
at: (node, scope) => {
|
|
5842
6425
|
const syntax = envReadSyntaxAt(node, scope);
|
|
5843
6426
|
if (syntax !== null) {
|
|
@@ -5853,7 +6436,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5853
6436
|
},
|
|
5854
6437
|
into: (node, scope) => {
|
|
5855
6438
|
if (DEFERRED_BODY_TYPES.has(node.type)) {
|
|
5856
|
-
return
|
|
6439
|
+
return import_extractor7.SKIP_CHILDREN;
|
|
5857
6440
|
}
|
|
5858
6441
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
5859
6442
|
}
|
|
@@ -5872,7 +6455,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5872
6455
|
function configReadEffect(read) {
|
|
5873
6456
|
return {
|
|
5874
6457
|
type: "interaction",
|
|
5875
|
-
binding: (0,
|
|
6458
|
+
binding: (0, import_behavioral_ir4.runtimeConfigBinding)({ recognition: PYTHON_ENV_RECOGNITION }),
|
|
5876
6459
|
callee: `os.environ["${read.name}"]`,
|
|
5877
6460
|
interaction: {
|
|
5878
6461
|
class: "config-read",
|
|
@@ -5896,7 +6479,7 @@ function hasFallback(node, spelling, scope) {
|
|
|
5896
6479
|
}
|
|
5897
6480
|
function envFactsIn(filePath, root, module2) {
|
|
5898
6481
|
const found = { sites: [], objects: [] };
|
|
5899
|
-
(0,
|
|
6482
|
+
(0, import_extractor7.walkDescendants)(root, module2.moduleScope, children, {
|
|
5900
6483
|
at: (node, scope) => {
|
|
5901
6484
|
if (isEnviron(node, scope) && handsOnward(node)) {
|
|
5902
6485
|
found.objects.push(keyOf(filePath, node));
|
|
@@ -6114,137 +6697,6 @@ function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
|
6114
6697
|
);
|
|
6115
6698
|
}
|
|
6116
6699
|
|
|
6117
|
-
// src/paths/raisedResponses.ts
|
|
6118
|
-
var import_values17 = require("@suss/values");
|
|
6119
|
-
var NESTED_DEFINITION_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
6120
|
-
function raisedResponses(body, options) {
|
|
6121
|
-
if (body === null || options.calls.length === 0) {
|
|
6122
|
-
return [];
|
|
6123
|
-
}
|
|
6124
|
-
const found = [];
|
|
6125
|
-
const walk = (node) => {
|
|
6126
|
-
for (const child of node.namedChildren) {
|
|
6127
|
-
if (child === null || NESTED_DEFINITION_TYPES2.has(child.type)) {
|
|
6128
|
-
continue;
|
|
6129
|
-
}
|
|
6130
|
-
const response = raisedResponseOf(child, options);
|
|
6131
|
-
if (response !== null) {
|
|
6132
|
-
found.push(response);
|
|
6133
|
-
}
|
|
6134
|
-
walk(child);
|
|
6135
|
-
}
|
|
6136
|
-
};
|
|
6137
|
-
walk(body);
|
|
6138
|
-
return found;
|
|
6139
|
-
}
|
|
6140
|
-
var ENDING_EXPRESSION = {
|
|
6141
|
-
raise_statement: (statement) => statement.namedChildren[0] ?? null,
|
|
6142
|
-
expression_statement: (statement) => {
|
|
6143
|
-
const only = statement.namedChildren[0];
|
|
6144
|
-
return only?.type === "call" ? only : null;
|
|
6145
|
-
}
|
|
6146
|
-
};
|
|
6147
|
-
function raisedResponseOf(statement, options) {
|
|
6148
|
-
const expression = ENDING_EXPRESSION[statement.type]?.(statement) ?? null;
|
|
6149
|
-
if (expression === null) {
|
|
6150
|
-
return null;
|
|
6151
|
-
}
|
|
6152
|
-
const thrownByCall = statement.type !== "raise_statement";
|
|
6153
|
-
const call = expression.type === "call" ? expression : null;
|
|
6154
|
-
const callee = calleeOf(expression, call);
|
|
6155
|
-
const declared = declaredCallFor(callee, options);
|
|
6156
|
-
if (declared === void 0 && thrownByCall) {
|
|
6157
|
-
return null;
|
|
6158
|
-
}
|
|
6159
|
-
return {
|
|
6160
|
-
statement,
|
|
6161
|
-
thrownByCall,
|
|
6162
|
-
terminal: terminalOf(statement, callee, call, declared, options.facts)
|
|
6163
|
-
};
|
|
6164
|
-
}
|
|
6165
|
-
function returnedResponseStatus(statement, options) {
|
|
6166
|
-
const returned = statement.namedChildren[0];
|
|
6167
|
-
if (options.calls.length === 0 || returned === void 0 || returned === null || returned.type !== "call") {
|
|
6168
|
-
return null;
|
|
6169
|
-
}
|
|
6170
|
-
const callee = field(returned, "function");
|
|
6171
|
-
if (callee === null) {
|
|
6172
|
-
return null;
|
|
6173
|
-
}
|
|
6174
|
-
const declared = declaredCallFor(callee, options);
|
|
6175
|
-
return declared === void 0 ? null : statusOf(declared, returned, options.facts);
|
|
6176
|
-
}
|
|
6177
|
-
function calleeOf(expression, call) {
|
|
6178
|
-
return call === null ? expression : field(call, "function") ?? expression;
|
|
6179
|
-
}
|
|
6180
|
-
function declaredCallFor(callee, options) {
|
|
6181
|
-
const origin = originOf(callee, options.module);
|
|
6182
|
-
if (origin === null) {
|
|
6183
|
-
return void 0;
|
|
6184
|
-
}
|
|
6185
|
-
const qualified = `${origin.module}.${origin.name}`;
|
|
6186
|
-
return options.calls.find((call) => call.callee === qualified);
|
|
6187
|
-
}
|
|
6188
|
-
function terminalOf(statement, callee, call, declared, facts) {
|
|
6189
|
-
return {
|
|
6190
|
-
kind: "throw",
|
|
6191
|
-
statusCode: declared === void 0 ? null : statusOf(declared, call, facts),
|
|
6192
|
-
body: null,
|
|
6193
|
-
exceptionType: lastSegmentOf(declared?.callee ?? callee.text),
|
|
6194
|
-
message: call === null ? null : writtenMessageOf(call),
|
|
6195
|
-
...declared === void 0 ? {} : { producesResponse: true },
|
|
6196
|
-
component: null,
|
|
6197
|
-
renderTree: null,
|
|
6198
|
-
delegateTarget: null,
|
|
6199
|
-
emitEvent: null,
|
|
6200
|
-
location: rangeOf(statement)
|
|
6201
|
-
};
|
|
6202
|
-
}
|
|
6203
|
-
function lastSegmentOf(dotted) {
|
|
6204
|
-
const segment = dotted.split(".").pop();
|
|
6205
|
-
return segment === void 0 || segment === "" ? null : segment;
|
|
6206
|
-
}
|
|
6207
|
-
function statusOf(declared, call, facts) {
|
|
6208
|
-
const written = call === null ? null : statusArgumentOf(declared, call);
|
|
6209
|
-
if (written === null) {
|
|
6210
|
-
return declared.defaultStatusCode === void 0 ? null : { type: "literal", value: declared.defaultStatusCode };
|
|
6211
|
-
}
|
|
6212
|
-
const value = (0, import_values17.constantOf)(evaluatedValue(written, facts));
|
|
6213
|
-
if (typeof value === "number") {
|
|
6214
|
-
return { type: "literal", value };
|
|
6215
|
-
}
|
|
6216
|
-
return { type: "dynamic", sourceText: written.text };
|
|
6217
|
-
}
|
|
6218
|
-
function argumentsOf2(call) {
|
|
6219
|
-
return (field(call, "arguments")?.namedChildren ?? []).filter(
|
|
6220
|
-
(child) => child !== null
|
|
6221
|
-
);
|
|
6222
|
-
}
|
|
6223
|
-
function statusArgumentOf(declared, call) {
|
|
6224
|
-
const args = argumentsOf2(call);
|
|
6225
|
-
const keyed = args.find(
|
|
6226
|
-
(arg) => arg.type === "keyword_argument" && field(arg, "name")?.text === declared.statusKeyword
|
|
6227
|
-
);
|
|
6228
|
-
if (keyed !== void 0) {
|
|
6229
|
-
return field(keyed, "value");
|
|
6230
|
-
}
|
|
6231
|
-
if (declared.statusArgument === void 0) {
|
|
6232
|
-
return null;
|
|
6233
|
-
}
|
|
6234
|
-
const positional = args.filter((arg) => arg.type !== "keyword_argument");
|
|
6235
|
-
return positional[declared.statusArgument] ?? null;
|
|
6236
|
-
}
|
|
6237
|
-
function writtenMessageOf(call) {
|
|
6238
|
-
for (const arg of argumentsOf2(call)) {
|
|
6239
|
-
const value = arg.type === "keyword_argument" ? field(arg, "value") : arg;
|
|
6240
|
-
const literal = value === null ? null : stringLiteralValue(value);
|
|
6241
|
-
if (literal !== null) {
|
|
6242
|
-
return literal;
|
|
6243
|
-
}
|
|
6244
|
-
}
|
|
6245
|
-
return null;
|
|
6246
|
-
}
|
|
6247
|
-
|
|
6248
6700
|
// src/paths/returnedShape.ts
|
|
6249
6701
|
var MAX_DEPTH = 6;
|
|
6250
6702
|
var SCALARS = {
|
|
@@ -6304,7 +6756,7 @@ function shapeOfReturned(node, depth = 0) {
|
|
|
6304
6756
|
return { type: "unknown" };
|
|
6305
6757
|
}
|
|
6306
6758
|
function returnedBodyShape(statement) {
|
|
6307
|
-
const returned = statement.
|
|
6759
|
+
const returned = statement.namedChild(0);
|
|
6308
6760
|
if (returned == null) {
|
|
6309
6761
|
return null;
|
|
6310
6762
|
}
|
|
@@ -6317,8 +6769,8 @@ function returnedBodyShape(statement) {
|
|
|
6317
6769
|
}
|
|
6318
6770
|
|
|
6319
6771
|
// src/streamWrites.ts
|
|
6320
|
-
var
|
|
6321
|
-
var
|
|
6772
|
+
var import_behavioral_ir5 = require("@suss/behavioral-ir");
|
|
6773
|
+
var import_extractor8 = require("@suss/extractor");
|
|
6322
6774
|
|
|
6323
6775
|
// src/stdlibNames.ts
|
|
6324
6776
|
function isStdlibModule(node, scope, module2) {
|
|
@@ -6328,7 +6780,7 @@ function isStdlibModule(node, scope, module2) {
|
|
|
6328
6780
|
const binding = resolveName(scope, node.text);
|
|
6329
6781
|
return binding?.kind === "import" && binding.module === module2 && binding.relativeLevel === 0;
|
|
6330
6782
|
}
|
|
6331
|
-
function
|
|
6783
|
+
function isBuiltin2(node, scope, name) {
|
|
6332
6784
|
return node.type === "identifier" && node.text === name && resolveName(scope, name) === null;
|
|
6333
6785
|
}
|
|
6334
6786
|
function isStdlibMember(node, scope, module2, name) {
|
|
@@ -6350,7 +6802,7 @@ var DEFERRED_BODY_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lamb
|
|
|
6350
6802
|
function streamWriteEffects(root, module2) {
|
|
6351
6803
|
const found = [];
|
|
6352
6804
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
6353
|
-
(0,
|
|
6805
|
+
(0, import_extractor8.walkDescendants)(root, startScope, children, {
|
|
6354
6806
|
at: (node, scope) => {
|
|
6355
6807
|
if (node.type !== "call") {
|
|
6356
6808
|
return;
|
|
@@ -6362,7 +6814,7 @@ function streamWriteEffects(root, module2) {
|
|
|
6362
6814
|
},
|
|
6363
6815
|
into: (node, scope) => {
|
|
6364
6816
|
if (DEFERRED_BODY_TYPES2.has(node.type)) {
|
|
6365
|
-
return
|
|
6817
|
+
return import_extractor8.SKIP_CHILDREN;
|
|
6366
6818
|
}
|
|
6367
6819
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
6368
6820
|
}
|
|
@@ -6376,7 +6828,7 @@ function streamWriteAt(call, scope) {
|
|
|
6376
6828
|
}
|
|
6377
6829
|
const written = callArguments(call);
|
|
6378
6830
|
const positional = written.filter((argument) => argument.kind === "positional").map((argument) => argument.node);
|
|
6379
|
-
if (callee.type === "identifier" &&
|
|
6831
|
+
if (callee.type === "identifier" && isBuiltin2(callee, scope, "print")) {
|
|
6380
6832
|
const file = written.find(
|
|
6381
6833
|
(argument) => argument.kind === "keyword" && argument.name === "file"
|
|
6382
6834
|
);
|
|
@@ -6398,7 +6850,7 @@ function writeEffect(site) {
|
|
|
6398
6850
|
const { call, callee, target } = site;
|
|
6399
6851
|
return {
|
|
6400
6852
|
type: "interaction",
|
|
6401
|
-
binding: (0,
|
|
6853
|
+
binding: (0, import_behavioral_ir5.ioBinding)({ recognition: PYTHON_STREAM_RECOGNITION, target }),
|
|
6402
6854
|
callee,
|
|
6403
6855
|
groupId: `${call.startPosition.row + 1}:${call.startPosition.column + 1}`,
|
|
6404
6856
|
interaction: {
|
|
@@ -6437,7 +6889,7 @@ function jsonDumped(node, scope) {
|
|
|
6437
6889
|
// src/discovery.ts
|
|
6438
6890
|
function decoratedNodes(root) {
|
|
6439
6891
|
const found = [];
|
|
6440
|
-
(0,
|
|
6892
|
+
(0, import_extractor9.walkDescendants)(root, null, children, {
|
|
6441
6893
|
at: (node) => {
|
|
6442
6894
|
if (node.type !== "decorated_definition") {
|
|
6443
6895
|
return;
|
|
@@ -6588,18 +7040,18 @@ function unitsFor(pattern, pack, decoratorModule, classification, definition, mo
|
|
|
6588
7040
|
);
|
|
6589
7041
|
}
|
|
6590
7042
|
};
|
|
6591
|
-
return (0,
|
|
7043
|
+
return (0, import_behavioral_ir6.dispatchByType)(table, pattern);
|
|
6592
7044
|
}
|
|
6593
7045
|
function readPathArgument(classification, options) {
|
|
6594
7046
|
const first = classification.args[0];
|
|
6595
7047
|
if (first !== void 0) {
|
|
6596
7048
|
const value = evaluatedValue(first.node, options.facts);
|
|
6597
|
-
const path8 = (0,
|
|
7049
|
+
const path8 = (0, import_values20.literalOf)(value) ?? (0, import_values20.pathOf)(value);
|
|
6598
7050
|
if (path8 !== void 0) {
|
|
6599
|
-
return (0,
|
|
7051
|
+
return (0, import_extractor9.writtenReading)(path8, classification.range);
|
|
6600
7052
|
}
|
|
6601
7053
|
}
|
|
6602
|
-
return (0,
|
|
7054
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6603
7055
|
"The path in this route's decorator is not a string literal, so the binding names no path and nothing pairs with it",
|
|
6604
7056
|
classification.range
|
|
6605
7057
|
);
|
|
@@ -6624,16 +7076,16 @@ var PATH_TEMPLATE_READERS = {
|
|
|
6624
7076
|
function readPathTemplate(pattern, path8, range) {
|
|
6625
7077
|
const syntax = pattern.pathParamSyntax;
|
|
6626
7078
|
if (syntax === void 0) {
|
|
6627
|
-
return (0,
|
|
7079
|
+
return (0, import_extractor9.writtenReading)({ path: path8, paramNames: NO_PATH_PARAMS }, range);
|
|
6628
7080
|
}
|
|
6629
7081
|
const reader = PATH_TEMPLATE_READERS[syntax];
|
|
6630
7082
|
if (reader === void 0) {
|
|
6631
|
-
return (0,
|
|
7083
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6632
7084
|
`The route's pack declares path-parameter syntax "${syntax}", which this adapter has no reader for, so the binding names no path and nothing pairs with it`,
|
|
6633
7085
|
range
|
|
6634
7086
|
);
|
|
6635
7087
|
}
|
|
6636
|
-
return (0,
|
|
7088
|
+
return (0, import_extractor9.writtenReading)(reader(path8), range);
|
|
6637
7089
|
}
|
|
6638
7090
|
function classRouteUnits(pattern, pack, classification, classNode, module2, options) {
|
|
6639
7091
|
const pathArgument = readPathArgument(classification, options);
|
|
@@ -6684,7 +7136,7 @@ function classRouteUnits(pattern, pack, classification, classNode, module2, opti
|
|
|
6684
7136
|
module: module2,
|
|
6685
7137
|
filePath: options.filePath,
|
|
6686
7138
|
skipReceiverParam: true,
|
|
6687
|
-
responseShape:
|
|
7139
|
+
responseShape: import_extractor9.absentReading,
|
|
6688
7140
|
statusCode: defaultedStatus(
|
|
6689
7141
|
readReturnedStatus(pattern, maybeMethod, {
|
|
6690
7142
|
module: module2,
|
|
@@ -6711,11 +7163,11 @@ function classRouteUnits(pattern, pack, classification, classNode, module2, opti
|
|
|
6711
7163
|
return units;
|
|
6712
7164
|
}
|
|
6713
7165
|
function readRoutePath(pattern, pathArgument, classification, module2, options) {
|
|
6714
|
-
const composed = (0,
|
|
7166
|
+
const composed = (0, import_extractor9.andThenReading)(
|
|
6715
7167
|
pathArgument,
|
|
6716
7168
|
(literal, range) => composeRoutePath(pattern, classification, module2, options, literal, range)
|
|
6717
7169
|
);
|
|
6718
|
-
return (0,
|
|
7170
|
+
return (0, import_extractor9.andThenReading)(
|
|
6719
7171
|
composed,
|
|
6720
7172
|
(path8, range) => readPathTemplate(pattern, path8, range)
|
|
6721
7173
|
);
|
|
@@ -6741,10 +7193,10 @@ function readRoutePaths(pattern, pathArgument, classification, module2, options)
|
|
|
6741
7193
|
];
|
|
6742
7194
|
}
|
|
6743
7195
|
return resolution.values.map((prefix) => ({
|
|
6744
|
-
routePath: (0,
|
|
6745
|
-
(0,
|
|
7196
|
+
routePath: (0, import_extractor9.andThenReading)(
|
|
7197
|
+
(0, import_extractor9.andThenReading)(
|
|
6746
7198
|
pathArgument,
|
|
6747
|
-
(literal, range) => (0,
|
|
7199
|
+
(literal, range) => (0, import_extractor9.writtenReading)(servedSpelling(pattern, prefix + literal), range)
|
|
6748
7200
|
),
|
|
6749
7201
|
(path8, range) => readPathTemplate(pattern, path8, range)
|
|
6750
7202
|
),
|
|
@@ -6785,9 +7237,9 @@ function composeRoutePath(pattern, classification, module2, options, literal, ra
|
|
|
6785
7237
|
range
|
|
6786
7238
|
);
|
|
6787
7239
|
if (prefix.kind === "absent") {
|
|
6788
|
-
return (0,
|
|
7240
|
+
return (0, import_extractor9.writtenReading)(servedSpelling(pattern, literal), range);
|
|
6789
7241
|
}
|
|
6790
|
-
return (0,
|
|
7242
|
+
return (0, import_extractor9.mapReading)(
|
|
6791
7243
|
prefix,
|
|
6792
7244
|
(value) => servedSpelling(pattern, value + literal)
|
|
6793
7245
|
);
|
|
@@ -6807,32 +7259,36 @@ function readRouterPrefix(pattern, classification, module2, options, range) {
|
|
|
6807
7259
|
options
|
|
6808
7260
|
);
|
|
6809
7261
|
if (resolution === null) {
|
|
6810
|
-
return
|
|
7262
|
+
return import_extractor9.absentReading;
|
|
6811
7263
|
}
|
|
6812
7264
|
if (resolution.kind === "abstain") {
|
|
6813
|
-
return (0,
|
|
7265
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6814
7266
|
`The router this route is declared on ${resolution.reason}, so the binding names no path and nothing pairs with it`,
|
|
6815
7267
|
range
|
|
6816
7268
|
);
|
|
6817
7269
|
}
|
|
6818
7270
|
if (resolution.kind === "composed") {
|
|
6819
|
-
return (0,
|
|
7271
|
+
return (0, import_extractor9.writtenReading)(resolution.value, range);
|
|
6820
7272
|
}
|
|
6821
|
-
return
|
|
7273
|
+
return import_extractor9.absentReading;
|
|
6822
7274
|
}
|
|
6823
|
-
function readStatusCode(pattern, classification) {
|
|
7275
|
+
function readStatusCode(pattern, classification, options) {
|
|
6824
7276
|
if (pattern.statusCodeKeyword === void 0) {
|
|
6825
|
-
return
|
|
7277
|
+
return import_extractor9.absentReading;
|
|
6826
7278
|
}
|
|
6827
7279
|
const arg = classification.keywordArgs[pattern.statusCodeKeyword];
|
|
6828
7280
|
if (arg === void 0) {
|
|
6829
|
-
return
|
|
7281
|
+
return import_extractor9.absentReading;
|
|
6830
7282
|
}
|
|
6831
|
-
|
|
6832
|
-
|
|
7283
|
+
const status = statusNumberOf(arg.node, {
|
|
7284
|
+
...options,
|
|
7285
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
7286
|
+
});
|
|
7287
|
+
if (status !== null) {
|
|
7288
|
+
return (0, import_extractor9.writtenReading)(status, classification.range);
|
|
6833
7289
|
}
|
|
6834
|
-
return (0,
|
|
6835
|
-
"The status this route's decorator states
|
|
7290
|
+
return (0, import_extractor9.unreadableReading)(
|
|
7291
|
+
"The status this route's decorator states does not come to a number here, so the response claims no status",
|
|
6836
7292
|
classification.range
|
|
6837
7293
|
);
|
|
6838
7294
|
}
|
|
@@ -6841,11 +7297,11 @@ function statusFromReturnedValue(node, facts) {
|
|
|
6841
7297
|
return null;
|
|
6842
7298
|
}
|
|
6843
7299
|
const value = evaluatedValue(node, facts);
|
|
6844
|
-
const number = (0,
|
|
7300
|
+
const number = (0, import_values20.constantOf)(value);
|
|
6845
7301
|
if (typeof number === "number") {
|
|
6846
7302
|
return Number.isInteger(number) ? number : null;
|
|
6847
7303
|
}
|
|
6848
|
-
const text2 = (0,
|
|
7304
|
+
const text2 = (0, import_values20.literalOf)(value);
|
|
6849
7305
|
if (text2 === null) {
|
|
6850
7306
|
return null;
|
|
6851
7307
|
}
|
|
@@ -6853,30 +7309,49 @@ function statusFromReturnedValue(node, facts) {
|
|
|
6853
7309
|
return digits === null ? null : Number.parseInt(digits[1], 10);
|
|
6854
7310
|
}
|
|
6855
7311
|
function statusOfReturn(statement, facts) {
|
|
6856
|
-
const returned = statement.
|
|
7312
|
+
const returned = statement.namedChild(0);
|
|
6857
7313
|
if (returned?.type !== "expression_list") {
|
|
6858
7314
|
return { kind: "none" };
|
|
6859
7315
|
}
|
|
6860
|
-
const status = statusFromReturnedValue(
|
|
7316
|
+
const status = statusFromReturnedValue(
|
|
7317
|
+
returned.namedChild(1) ?? void 0,
|
|
7318
|
+
facts
|
|
7319
|
+
);
|
|
6861
7320
|
return status === null ? { kind: "unreadable" } : { kind: "status", value: status };
|
|
6862
7321
|
}
|
|
6863
7322
|
function returnStatusReading(statement, ctx) {
|
|
6864
7323
|
const read = statusOfReturnIn(statement, ctx.pattern, ctx);
|
|
6865
7324
|
const range = rangeOf(statement);
|
|
6866
7325
|
if (read.kind === "status") {
|
|
6867
|
-
return (0,
|
|
7326
|
+
return (0, import_extractor9.writtenReading)(read.value, range);
|
|
6868
7327
|
}
|
|
6869
7328
|
if (read.kind === "unreadable") {
|
|
6870
|
-
return (0,
|
|
7329
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6871
7330
|
"This return gives a status this reading cannot resolve to a number, so this outcome claims none",
|
|
6872
7331
|
range
|
|
6873
7332
|
);
|
|
6874
7333
|
}
|
|
6875
|
-
return ctx.pattern.statusFromReturnedTuple === true ?
|
|
7334
|
+
return ctx.pattern.statusFromReturnedTuple === true ? import_extractor9.absentReading : ctx.declaredStatus.reading;
|
|
6876
7335
|
}
|
|
6877
7336
|
function returnBranch(statement, ctx) {
|
|
6878
7337
|
const range = rangeOf(statement);
|
|
6879
7338
|
const writtenBody = returnedBodyShape(statement);
|
|
7339
|
+
return responseBranchAt(
|
|
7340
|
+
range,
|
|
7341
|
+
returnStatusReading(statement, ctx),
|
|
7342
|
+
writtenBody === null ? ctx.responseShape.reading : (0, import_extractor9.writtenReading)(writtenBody, range),
|
|
7343
|
+
ctx
|
|
7344
|
+
);
|
|
7345
|
+
}
|
|
7346
|
+
function fallthroughBranch(definitionNode, ctx) {
|
|
7347
|
+
return responseBranchAt(
|
|
7348
|
+
rangeOf(definitionNode),
|
|
7349
|
+
ctx.pattern.statusFromReturnedTuple === true ? import_extractor9.absentReading : ctx.declaredStatus.reading,
|
|
7350
|
+
ctx.responseShape.reading,
|
|
7351
|
+
ctx
|
|
7352
|
+
);
|
|
7353
|
+
}
|
|
7354
|
+
function responseBranchAt(range, status, body, ctx) {
|
|
6880
7355
|
return {
|
|
6881
7356
|
terminal: {
|
|
6882
7357
|
kind: "response",
|
|
@@ -6893,12 +7368,10 @@ function returnBranch(statement, ctx) {
|
|
|
6893
7368
|
location: range
|
|
6894
7369
|
},
|
|
6895
7370
|
statusCodeReading: {
|
|
6896
|
-
reading:
|
|
7371
|
+
reading: status,
|
|
6897
7372
|
...ctx.declaredStatus.libraryDefault !== void 0 ? { libraryDefault: ctx.declaredStatus.libraryDefault } : {}
|
|
6898
7373
|
},
|
|
6899
|
-
bodyShapeReading: {
|
|
6900
|
-
reading: writtenBody === null ? ctx.responseShape.reading : (0, import_extractor7.writtenReading)(writtenBody, range)
|
|
6901
|
-
},
|
|
7374
|
+
bodyShapeReading: { reading: body },
|
|
6902
7375
|
location: range
|
|
6903
7376
|
};
|
|
6904
7377
|
}
|
|
@@ -6912,18 +7385,19 @@ function terminalBranchOf(found, ctx) {
|
|
|
6912
7385
|
// A route has no continuation, so none is ever collected for it.
|
|
6913
7386
|
continuation: (variant) => returnBranch(variant.statement, ctx)
|
|
6914
7387
|
};
|
|
6915
|
-
return (0,
|
|
7388
|
+
return (0, import_behavioral_ir6.dispatchByType)(table, found);
|
|
6916
7389
|
}
|
|
6917
7390
|
function branchesPerTerminal(options) {
|
|
6918
7391
|
const body = field(options.definitionNode, "body");
|
|
6919
7392
|
const raised = raisedResponses(body, {
|
|
6920
7393
|
calls: options.responseStatusCalls,
|
|
6921
7394
|
module: options.ctx.module,
|
|
6922
|
-
facts: options.ctx.facts
|
|
7395
|
+
facts: options.ctx.facts,
|
|
7396
|
+
constants: options.ctx.pattern.statusCodeConstants ?? {}
|
|
6923
7397
|
});
|
|
6924
7398
|
const terminals = bodyTerminals(body, raised);
|
|
6925
7399
|
const soleReturnWritesBody = terminals.length === 1 && terminals[0]?.type === "return" && returnedBodyShape(terminals[0].statement) !== null;
|
|
6926
|
-
if (terminals.length
|
|
7400
|
+
if (terminals.length === 0) {
|
|
6927
7401
|
return null;
|
|
6928
7402
|
}
|
|
6929
7403
|
const branches = enumerateBodyBranches({
|
|
@@ -6932,6 +7406,7 @@ function branchesPerTerminal(options) {
|
|
|
6932
7406
|
raised,
|
|
6933
7407
|
effects: options.effects,
|
|
6934
7408
|
branchOf: (found) => terminalBranchOf(found, options.ctx),
|
|
7409
|
+
fallthrough: fallthroughBranch(options.definitionNode, options.ctx),
|
|
6935
7410
|
facts: options.ctx.facts
|
|
6936
7411
|
});
|
|
6937
7412
|
return branches.length > 1 || soleReturnWritesBody ? branches : null;
|
|
@@ -6940,7 +7415,8 @@ function statusOfReturnIn(statement, pattern, options) {
|
|
|
6940
7415
|
const constructed = returnedResponseStatus(statement, {
|
|
6941
7416
|
calls: pattern.responseConstructors ?? [],
|
|
6942
7417
|
module: options.module,
|
|
6943
|
-
facts: options.facts
|
|
7418
|
+
facts: options.facts,
|
|
7419
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
6944
7420
|
});
|
|
6945
7421
|
if (constructed !== null) {
|
|
6946
7422
|
return constructed.type === "literal" ? { kind: "status", value: constructed.value } : { kind: "unreadable" };
|
|
@@ -6952,7 +7428,7 @@ function statusOfReturnIn(statement, pattern, options) {
|
|
|
6952
7428
|
}
|
|
6953
7429
|
function readReturnedStatus(pattern, definitionNode, options) {
|
|
6954
7430
|
if (pattern.statusFromReturnedTuple !== true && (pattern.responseConstructors ?? []).length === 0) {
|
|
6955
|
-
return
|
|
7431
|
+
return import_extractor9.absentReading;
|
|
6956
7432
|
}
|
|
6957
7433
|
const range = rangeOf(definitionNode);
|
|
6958
7434
|
const statuses = /* @__PURE__ */ new Set();
|
|
@@ -6969,23 +7445,23 @@ function readReturnedStatus(pattern, definitionNode, options) {
|
|
|
6969
7445
|
}
|
|
6970
7446
|
}
|
|
6971
7447
|
if (unreadable > 0) {
|
|
6972
|
-
return (0,
|
|
7448
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6973
7449
|
"This route returns a status this reading cannot resolve to a number, so no status is claimed for it",
|
|
6974
7450
|
range
|
|
6975
7451
|
);
|
|
6976
7452
|
}
|
|
6977
7453
|
if (statuses.size === 0) {
|
|
6978
|
-
return
|
|
7454
|
+
return import_extractor9.absentReading;
|
|
6979
7455
|
}
|
|
6980
7456
|
const candidates = [...statuses];
|
|
6981
7457
|
if (statuses.size > 1 || plainReturns > 0) {
|
|
6982
|
-
return (0,
|
|
7458
|
+
return (0, import_extractor9.ambiguousReading)(
|
|
6983
7459
|
candidates,
|
|
6984
7460
|
"This route returns more than one status depending on which branch runs, and nothing here reads which, so no status is claimed for it",
|
|
6985
7461
|
range
|
|
6986
7462
|
);
|
|
6987
7463
|
}
|
|
6988
|
-
return (0,
|
|
7464
|
+
return (0, import_extractor9.writtenReading)(candidates[0], range);
|
|
6989
7465
|
}
|
|
6990
7466
|
function declaredOrReturnedStatus(declared, returned) {
|
|
6991
7467
|
return declared.kind === "absent" ? returned : declared;
|
|
@@ -6998,19 +7474,19 @@ function defaultedStatus(reading, pattern) {
|
|
|
6998
7474
|
}
|
|
6999
7475
|
function readResponseModel(pattern, classification, module2, ctx) {
|
|
7000
7476
|
if (pattern.responseModelKeyword === void 0) {
|
|
7001
|
-
return
|
|
7477
|
+
return import_extractor9.absentReading;
|
|
7002
7478
|
}
|
|
7003
7479
|
const arg = classification.keywordArgs[pattern.responseModelKeyword];
|
|
7004
7480
|
if (arg === void 0) {
|
|
7005
|
-
return
|
|
7481
|
+
return import_extractor9.absentReading;
|
|
7006
7482
|
}
|
|
7007
7483
|
if (arg.kind === "identifier") {
|
|
7008
|
-
return (0,
|
|
7484
|
+
return (0, import_extractor9.writtenReading)(
|
|
7009
7485
|
shapeFromName(arg.name, module2.moduleScope, ctx),
|
|
7010
7486
|
classification.range
|
|
7011
7487
|
);
|
|
7012
7488
|
}
|
|
7013
|
-
return (0,
|
|
7489
|
+
return (0, import_extractor9.unreadableReading)(
|
|
7014
7490
|
"The response model this route's decorator states is not a name, so the response claims no body shape",
|
|
7015
7491
|
classification.range
|
|
7016
7492
|
);
|
|
@@ -7018,9 +7494,9 @@ function readResponseModel(pattern, classification, module2, ctx) {
|
|
|
7018
7494
|
function readReturnAnnotation(definitionNode, scope, ctx) {
|
|
7019
7495
|
const returnTypeNode = field(definitionNode, "return_type");
|
|
7020
7496
|
if (returnTypeNode === null) {
|
|
7021
|
-
return
|
|
7497
|
+
return import_extractor9.absentReading;
|
|
7022
7498
|
}
|
|
7023
|
-
return (0,
|
|
7499
|
+
return (0, import_extractor9.writtenReading)(
|
|
7024
7500
|
annotationToShape(returnTypeNode, scope, ctx),
|
|
7025
7501
|
rangeOf(returnTypeNode)
|
|
7026
7502
|
);
|
|
@@ -7034,6 +7510,25 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7034
7510
|
module2.scopeFor,
|
|
7035
7511
|
options.importedDefinition ?? null
|
|
7036
7512
|
);
|
|
7513
|
+
const wrappers = wrappersAround(
|
|
7514
|
+
pattern,
|
|
7515
|
+
pack,
|
|
7516
|
+
classification,
|
|
7517
|
+
functionNode,
|
|
7518
|
+
module2,
|
|
7519
|
+
options
|
|
7520
|
+
);
|
|
7521
|
+
const dependencyParameters = options.wrappers?.dependencyParameters(
|
|
7522
|
+
wrappers
|
|
7523
|
+
) ?? { names: /* @__PURE__ */ new Set(), declaresSource: false };
|
|
7524
|
+
const declaredStatuses = declaredStatusesOf(
|
|
7525
|
+
pattern,
|
|
7526
|
+
pack,
|
|
7527
|
+
classification,
|
|
7528
|
+
functionNode,
|
|
7529
|
+
module2,
|
|
7530
|
+
options
|
|
7531
|
+
);
|
|
7037
7532
|
return readRoutePaths(
|
|
7038
7533
|
pattern,
|
|
7039
7534
|
readPathArgument(classification, options),
|
|
@@ -7046,6 +7541,8 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7046
7541
|
pack,
|
|
7047
7542
|
name: functionName,
|
|
7048
7543
|
exportPath: [functionName],
|
|
7544
|
+
dependencyParameters,
|
|
7545
|
+
declaredStatuses,
|
|
7049
7546
|
method: verb,
|
|
7050
7547
|
routePath: entry.routePath,
|
|
7051
7548
|
...entry.mount !== void 0 ? { mount: entry.mount } : {},
|
|
@@ -7062,7 +7559,10 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7062
7559
|
responseShape: readResponseModel(pattern, classification, module2, ctx),
|
|
7063
7560
|
statusCode: defaultedStatus(
|
|
7064
7561
|
declaredOrReturnedStatus(
|
|
7065
|
-
readStatusCode(pattern, classification
|
|
7562
|
+
readStatusCode(pattern, classification, {
|
|
7563
|
+
module: module2,
|
|
7564
|
+
facts: options.facts
|
|
7565
|
+
}),
|
|
7066
7566
|
readReturnedStatus(pattern, functionNode, {
|
|
7067
7567
|
module: module2,
|
|
7068
7568
|
facts: options.facts
|
|
@@ -7073,14 +7573,7 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7073
7573
|
definitionsCtx: ctx,
|
|
7074
7574
|
storage: options.storage,
|
|
7075
7575
|
importedDefinition: options.importedDefinition,
|
|
7076
|
-
wrappers
|
|
7077
|
-
pattern,
|
|
7078
|
-
pack,
|
|
7079
|
-
classification,
|
|
7080
|
-
functionNode,
|
|
7081
|
-
module2,
|
|
7082
|
-
options
|
|
7083
|
-
)
|
|
7576
|
+
wrappers
|
|
7084
7577
|
},
|
|
7085
7578
|
options
|
|
7086
7579
|
)
|
|
@@ -7099,11 +7592,43 @@ function wrappersAround(pattern, pack, classification, definitionNode, module2,
|
|
|
7099
7592
|
definitionNode
|
|
7100
7593
|
});
|
|
7101
7594
|
}
|
|
7595
|
+
function declaredStatusesOf(pattern, pack, classification, definitionNode, module2, options) {
|
|
7596
|
+
const keyword = pattern.responsesKeyword;
|
|
7597
|
+
if (keyword === void 0) {
|
|
7598
|
+
return [];
|
|
7599
|
+
}
|
|
7600
|
+
const above = options.wrappers?.callsAbove({
|
|
7601
|
+
pack,
|
|
7602
|
+
pattern,
|
|
7603
|
+
file: options.absoluteFile ?? options.filePath,
|
|
7604
|
+
module: module2,
|
|
7605
|
+
classification,
|
|
7606
|
+
definitionNode
|
|
7607
|
+
}) ?? [];
|
|
7608
|
+
const dictionaries = [
|
|
7609
|
+
classification.keywordArgs[keyword]?.node,
|
|
7610
|
+
...above.map(
|
|
7611
|
+
(call) => readCallArguments(field(call, "arguments")).keywordArgs[keyword]?.node
|
|
7612
|
+
)
|
|
7613
|
+
].filter((node) => node?.type === "dictionary");
|
|
7614
|
+
const statuses = dictionaries.flatMap(
|
|
7615
|
+
(dictionary) => children(dictionary).flatMap((pair) => {
|
|
7616
|
+
const key = pair?.type === "pair" ? field(pair, "key") : null;
|
|
7617
|
+
const status = key === null ? null : statusNumberOf(key, {
|
|
7618
|
+
module: moduleOf(key),
|
|
7619
|
+
facts: options.facts,
|
|
7620
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
7621
|
+
});
|
|
7622
|
+
return status === null ? [] : [status];
|
|
7623
|
+
})
|
|
7624
|
+
);
|
|
7625
|
+
return [...new Set(statuses)].sort((a, b) => a - b);
|
|
7626
|
+
}
|
|
7102
7627
|
function readResponseShape(declared, readAnnotation) {
|
|
7103
7628
|
if (declared.kind === "written") {
|
|
7104
7629
|
return { reading: declared, passedOver: [] };
|
|
7105
7630
|
}
|
|
7106
|
-
return (0,
|
|
7631
|
+
return (0, import_extractor9.firstWrittenReading)([declared, readAnnotation()]);
|
|
7107
7632
|
}
|
|
7108
7633
|
function routeUnitOrAbstention(unitOptions, options) {
|
|
7109
7634
|
try {
|
|
@@ -7131,7 +7656,7 @@ function unbuiltRouteUnit(unitOptions, error) {
|
|
|
7131
7656
|
exportName: unitOptions.exportPath[0] ?? unitOptions.name,
|
|
7132
7657
|
exportPath: unitOptions.exportPath
|
|
7133
7658
|
},
|
|
7134
|
-
boundaryBinding: (0,
|
|
7659
|
+
boundaryBinding: (0, import_behavioral_ir6.restBinding)({
|
|
7135
7660
|
transport: unitOptions.pack.protocol,
|
|
7136
7661
|
method: nullIfEmpty(unitOptions.method),
|
|
7137
7662
|
path: null,
|
|
@@ -7143,7 +7668,7 @@ function unbuiltRouteUnit(unitOptions, error) {
|
|
|
7143
7668
|
dependencyCalls: [],
|
|
7144
7669
|
declaredContract: null,
|
|
7145
7670
|
readings: [
|
|
7146
|
-
(0,
|
|
7671
|
+
(0, import_extractor9.unreadableReading)(
|
|
7147
7672
|
`This route could not be read into a unit (${message}), so the binding names no path and nothing pairs with it`,
|
|
7148
7673
|
range
|
|
7149
7674
|
)
|
|
@@ -7169,7 +7694,7 @@ function buildRouteUnit(options) {
|
|
|
7169
7694
|
definitionsCtx,
|
|
7170
7695
|
storage: storageLookup
|
|
7171
7696
|
} = options;
|
|
7172
|
-
const template = (0,
|
|
7697
|
+
const template = (0, import_extractor9.valueToReadFurtherFrom)(routePath);
|
|
7173
7698
|
const ctx = definitionsCtx ?? createAnnotationContext(
|
|
7174
7699
|
module2.scopeFor,
|
|
7175
7700
|
options.importedDefinition ?? null
|
|
@@ -7182,6 +7707,8 @@ function buildRouteUnit(options) {
|
|
|
7182
7707
|
pathParamNames: template?.paramNames ?? null,
|
|
7183
7708
|
requestBodyFromAnnotatedClass,
|
|
7184
7709
|
injectedCallees,
|
|
7710
|
+
injectedTypes: new Set(pattern.injectedParameterTypes ?? []),
|
|
7711
|
+
module: module2,
|
|
7185
7712
|
sources: pattern.parameterSources ?? {},
|
|
7186
7713
|
aliasKeyword: pattern.parameterAliasKeyword
|
|
7187
7714
|
},
|
|
@@ -7238,6 +7765,22 @@ function buildRouteUnit(options) {
|
|
|
7238
7765
|
};
|
|
7239
7766
|
branches.push(withBodyEffects(bare, extra));
|
|
7240
7767
|
}
|
|
7768
|
+
if (branches.length > 0) {
|
|
7769
|
+
branches.push(
|
|
7770
|
+
...validationFailureBranches(
|
|
7771
|
+
pattern,
|
|
7772
|
+
readsTheRequest(
|
|
7773
|
+
parameters,
|
|
7774
|
+
template,
|
|
7775
|
+
options.dependencyParameters ?? {
|
|
7776
|
+
names: /* @__PURE__ */ new Set(),
|
|
7777
|
+
declaresSource: false
|
|
7778
|
+
}
|
|
7779
|
+
),
|
|
7780
|
+
rangeOf(definitionNode)
|
|
7781
|
+
)
|
|
7782
|
+
);
|
|
7783
|
+
}
|
|
7241
7784
|
const bodyNode = field(definitionNode, "body");
|
|
7242
7785
|
return {
|
|
7243
7786
|
identity: {
|
|
@@ -7250,7 +7793,7 @@ function buildRouteUnit(options) {
|
|
|
7250
7793
|
exportName: exportPath[0] ?? name,
|
|
7251
7794
|
exportPath
|
|
7252
7795
|
},
|
|
7253
|
-
boundaryBinding: (0,
|
|
7796
|
+
boundaryBinding: (0, import_behavioral_ir6.restBinding)({
|
|
7254
7797
|
transport: pack.protocol,
|
|
7255
7798
|
method,
|
|
7256
7799
|
path: template?.path ?? null,
|
|
@@ -7269,15 +7812,57 @@ function buildRouteUnit(options) {
|
|
|
7269
7812
|
...collectedDefinitions(ctx) !== null ? { definitions: collectedDefinitions(ctx) } : {},
|
|
7270
7813
|
...options.mount !== void 0 ? { mount: options.mount } : {},
|
|
7271
7814
|
...options.wrappers !== void 0 && options.wrappers.length > 0 ? { wrappers: options.wrappers } : {},
|
|
7272
|
-
...pack.requestSpelling === void 0 ? {} : { requestSpelling: pack.requestSpelling }
|
|
7815
|
+
...pack.requestSpelling === void 0 ? {} : { requestSpelling: pack.requestSpelling },
|
|
7816
|
+
...options.declaredStatuses !== void 0 && options.declaredStatuses.length > 0 ? { declaredStatuses: options.declaredStatuses } : {}
|
|
7273
7817
|
};
|
|
7274
7818
|
}
|
|
7819
|
+
function readsTheRequest(parameters, template, dependencies) {
|
|
7820
|
+
if (dependencies.declaresSource || parameters.some((parameter) => parameter.role !== null)) {
|
|
7821
|
+
return true;
|
|
7822
|
+
}
|
|
7823
|
+
return [...template?.paramNames ?? []].some(
|
|
7824
|
+
(name) => dependencies.names.has(name)
|
|
7825
|
+
);
|
|
7826
|
+
}
|
|
7827
|
+
function validationFailureBranches(pattern, readsRequest, range) {
|
|
7828
|
+
const status = pattern.validationFailureStatus;
|
|
7829
|
+
if (status === void 0 || !readsRequest) {
|
|
7830
|
+
return [];
|
|
7831
|
+
}
|
|
7832
|
+
return [
|
|
7833
|
+
{
|
|
7834
|
+
conditions: [
|
|
7835
|
+
{
|
|
7836
|
+
sourceText: "request input fails validation",
|
|
7837
|
+
structured: null,
|
|
7838
|
+
polarity: "positive",
|
|
7839
|
+
source: "earlyThrow"
|
|
7840
|
+
}
|
|
7841
|
+
],
|
|
7842
|
+
terminal: {
|
|
7843
|
+
kind: "response",
|
|
7844
|
+
statusCode: { type: "literal", value: status },
|
|
7845
|
+
body: null,
|
|
7846
|
+
exceptionType: null,
|
|
7847
|
+
message: null,
|
|
7848
|
+
component: null,
|
|
7849
|
+
renderTree: null,
|
|
7850
|
+
delegateTarget: null,
|
|
7851
|
+
emitEvent: null,
|
|
7852
|
+
location: range
|
|
7853
|
+
},
|
|
7854
|
+
effects: [],
|
|
7855
|
+
location: range,
|
|
7856
|
+
isDefault: false
|
|
7857
|
+
}
|
|
7858
|
+
];
|
|
7859
|
+
}
|
|
7275
7860
|
function unreadRoleReadings(parameters, range) {
|
|
7276
7861
|
if (!parameters.some((parameter) => parameter.role === null)) {
|
|
7277
7862
|
return [];
|
|
7278
7863
|
}
|
|
7279
7864
|
return [
|
|
7280
|
-
(0,
|
|
7865
|
+
(0, import_extractor9.unreadableReading)(
|
|
7281
7866
|
"Nothing read this route's path, so its parameters name no role and a path parameter here does not read as one",
|
|
7282
7867
|
range
|
|
7283
7868
|
)
|
|
@@ -7338,10 +7923,7 @@ function readParameters(definitionNode, reading, skipReceiverParam) {
|
|
|
7338
7923
|
}
|
|
7339
7924
|
const out = [];
|
|
7340
7925
|
let position = 0;
|
|
7341
|
-
for (const param of parametersNode
|
|
7342
|
-
if (param === null) {
|
|
7343
|
-
continue;
|
|
7344
|
-
}
|
|
7926
|
+
for (const param of children(parametersNode)) {
|
|
7345
7927
|
if (skipReceiverParam && position === 0 && isReceiverParam(param)) {
|
|
7346
7928
|
position += 1;
|
|
7347
7929
|
continue;
|
|
@@ -7365,7 +7947,7 @@ function readParameter(param, reading, position) {
|
|
|
7365
7947
|
const { name, typeNode } = info;
|
|
7366
7948
|
const shape = typeNode !== null ? annotationToShape(typeNode, reading.scope, reading.ctx) : null;
|
|
7367
7949
|
const typeText = typeNode !== null ? typeNode.text : null;
|
|
7368
|
-
if (isInjectedParameter(param, reading)) {
|
|
7950
|
+
if (isInjectedParameter(param, reading) || isInjectedType(typeNode, reading)) {
|
|
7369
7951
|
return { name, position, role: null, typeText };
|
|
7370
7952
|
}
|
|
7371
7953
|
const declared = declaringCall(
|
|
@@ -7445,6 +8027,14 @@ function calleeName2(call) {
|
|
|
7445
8027
|
function isInjectedParameter(param, reading) {
|
|
7446
8028
|
return declaringCall(param, reading.injectedCallees, reading) !== null;
|
|
7447
8029
|
}
|
|
8030
|
+
function isInjectedType(typeNode, reading) {
|
|
8031
|
+
if (typeNode === null || reading.injectedTypes.size === 0) {
|
|
8032
|
+
return false;
|
|
8033
|
+
}
|
|
8034
|
+
const written = typeNode.type === "type" ? typeNode.namedChild(0) ?? null : typeNode;
|
|
8035
|
+
const origin = written === null ? null : originOf(written, reading.module);
|
|
8036
|
+
return origin !== null && reading.injectedTypes.has(`${origin.module}.${origin.name}`);
|
|
8037
|
+
}
|
|
7448
8038
|
function declaringCall(param, callees, reading) {
|
|
7449
8039
|
if (callees.size === 0) {
|
|
7450
8040
|
return null;
|
|
@@ -7668,15 +8258,15 @@ function parseWith(language, source) {
|
|
|
7668
8258
|
// src/project.ts
|
|
7669
8259
|
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
7670
8260
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
7671
|
-
var
|
|
8261
|
+
var import_behavioral_ir10 = require("@suss/behavioral-ir");
|
|
7672
8262
|
var import_datalog2 = require("@suss/datalog");
|
|
7673
|
-
var
|
|
8263
|
+
var import_extractor18 = require("@suss/extractor");
|
|
7674
8264
|
var import_resolution18 = require("@suss/resolution");
|
|
7675
8265
|
|
|
7676
8266
|
// src/diagnostics.ts
|
|
7677
|
-
var
|
|
8267
|
+
var import_extractor10 = require("@suss/extractor");
|
|
7678
8268
|
function buildPythonExtractionReport(args) {
|
|
7679
|
-
return (0,
|
|
8269
|
+
return (0, import_extractor10.buildUngatedExtractionReport)({
|
|
7680
8270
|
packs: args.packs.map((pack) => ({
|
|
7681
8271
|
name: pack.name,
|
|
7682
8272
|
version: pack.version ?? null,
|
|
@@ -7689,14 +8279,14 @@ function buildPythonExtractionReport(args) {
|
|
|
7689
8279
|
}
|
|
7690
8280
|
|
|
7691
8281
|
// src/exits.ts
|
|
7692
|
-
var
|
|
8282
|
+
var import_extractor11 = require("@suss/extractor");
|
|
7693
8283
|
var import_resolution9 = require("@suss/resolution");
|
|
7694
|
-
var
|
|
8284
|
+
var import_values21 = require("@suss/values");
|
|
7695
8285
|
var DEFERRED_BODY_TYPES3 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
7696
8286
|
function exitSites(root, module2) {
|
|
7697
8287
|
const found = [];
|
|
7698
8288
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
7699
|
-
(0,
|
|
8289
|
+
(0, import_extractor11.walkDescendants)(root, startScope, children, {
|
|
7700
8290
|
at: (node, scope) => {
|
|
7701
8291
|
const site = exitSiteAt(node, scope);
|
|
7702
8292
|
if (site !== null) {
|
|
@@ -7705,7 +8295,7 @@ function exitSites(root, module2) {
|
|
|
7705
8295
|
},
|
|
7706
8296
|
into: (node, scope) => {
|
|
7707
8297
|
if (DEFERRED_BODY_TYPES3.has(node.type)) {
|
|
7708
|
-
return
|
|
8298
|
+
return import_extractor11.SKIP_CHILDREN;
|
|
7709
8299
|
}
|
|
7710
8300
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
7711
8301
|
}
|
|
@@ -7713,7 +8303,7 @@ function exitSites(root, module2) {
|
|
|
7713
8303
|
return found;
|
|
7714
8304
|
}
|
|
7715
8305
|
function exitSiteAt(statement, scope) {
|
|
7716
|
-
const expression = statement.
|
|
8306
|
+
const expression = statement.namedChild(0) ?? null;
|
|
7717
8307
|
if (expression === null) {
|
|
7718
8308
|
return null;
|
|
7719
8309
|
}
|
|
@@ -7727,12 +8317,12 @@ function exitSiteAt(statement, scope) {
|
|
|
7727
8317
|
return endsTheProcess(callee, scope) ? { statement, code, raised: false } : null;
|
|
7728
8318
|
}
|
|
7729
8319
|
if (statement.type === "raise_statement") {
|
|
7730
|
-
return
|
|
8320
|
+
return isBuiltin2(callee, scope, "SystemExit") ? { statement, code, raised: true } : null;
|
|
7731
8321
|
}
|
|
7732
8322
|
return null;
|
|
7733
8323
|
}
|
|
7734
8324
|
function endsTheProcess(callee, scope) {
|
|
7735
|
-
return isStdlibMember(callee, scope, "sys", "exit") ||
|
|
8325
|
+
return isStdlibMember(callee, scope, "sys", "exit") || isBuiltin2(callee, scope, "exit") || isBuiltin2(callee, scope, "quit");
|
|
7736
8326
|
}
|
|
7737
8327
|
function firstArgument(call) {
|
|
7738
8328
|
return callArguments(call).find(
|
|
@@ -7760,7 +8350,7 @@ function exitCodeOf(code, facts) {
|
|
|
7760
8350
|
if (stringLiteralValue(code) !== null) {
|
|
7761
8351
|
return { type: "literal", value: 1 };
|
|
7762
8352
|
}
|
|
7763
|
-
const value = (0,
|
|
8353
|
+
const value = (0, import_values21.constantOf)(evaluatedValue(code, facts));
|
|
7764
8354
|
return typeof value === "number" ? { type: "literal", value } : { type: "dynamic", sourceText: code.text };
|
|
7765
8355
|
}
|
|
7766
8356
|
function exitingBranches(definition, module2, effects, facts) {
|
|
@@ -7794,7 +8384,7 @@ function markExitCodeFunctions(summaries, exits, facts, workspaceRoot) {
|
|
|
7794
8384
|
(site) => site.code === null ? [] : [nodeId(file, site.code)]
|
|
7795
8385
|
)
|
|
7796
8386
|
);
|
|
7797
|
-
(0,
|
|
8387
|
+
(0, import_extractor11.markReturnsAsExitCode)(
|
|
7798
8388
|
summaries,
|
|
7799
8389
|
(0, import_resolution9.exitCodeFunctions)(facts, sinks),
|
|
7800
8390
|
workspaceRoot
|
|
@@ -7879,25 +8469,25 @@ function definedNodeOf(binding) {
|
|
|
7879
8469
|
}
|
|
7880
8470
|
|
|
7881
8471
|
// src/moduleSurface.ts
|
|
7882
|
-
var
|
|
7883
|
-
var
|
|
8472
|
+
var import_behavioral_ir8 = require("@suss/behavioral-ir");
|
|
8473
|
+
var import_extractor14 = require("@suss/extractor");
|
|
7884
8474
|
var import_resolution13 = require("@suss/resolution");
|
|
7885
8475
|
|
|
7886
8476
|
// src/reach/closure.ts
|
|
7887
|
-
var
|
|
8477
|
+
var import_behavioral_ir7 = require("@suss/behavioral-ir");
|
|
7888
8478
|
var import_datalog = require("@suss/datalog");
|
|
7889
|
-
var
|
|
8479
|
+
var import_extractor13 = require("@suss/extractor");
|
|
7890
8480
|
var import_resolution12 = require("@suss/resolution");
|
|
7891
8481
|
|
|
7892
8482
|
// src/flags.ts
|
|
7893
|
-
var
|
|
8483
|
+
var import_extractor12 = require("@suss/extractor");
|
|
7894
8484
|
var PARSE_METHODS = /* @__PURE__ */ new Set(["parse_args", "parse_known_args"]);
|
|
7895
8485
|
var DEFERRED_BODY_TYPES4 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
7896
8486
|
function argparseFlagReads(definition, module2, parameterNames2) {
|
|
7897
8487
|
const parsers = /* @__PURE__ */ new Map();
|
|
7898
8488
|
const handedTo = /* @__PURE__ */ new Map();
|
|
7899
8489
|
const startScope = module2.scopeFor.get(definition.id) ?? module2.moduleScope;
|
|
7900
|
-
(0,
|
|
8490
|
+
(0, import_extractor12.walkDescendants)(definition, startScope, children, {
|
|
7901
8491
|
at: (node, scope) => {
|
|
7902
8492
|
noteParser(node, scope, parsers);
|
|
7903
8493
|
noteArgument(node, parsers);
|
|
@@ -7905,7 +8495,7 @@ function argparseFlagReads(definition, module2, parameterNames2) {
|
|
|
7905
8495
|
},
|
|
7906
8496
|
into: (node, scope) => {
|
|
7907
8497
|
if (DEFERRED_BODY_TYPES4.has(node.type)) {
|
|
7908
|
-
return
|
|
8498
|
+
return import_extractor12.SKIP_CHILDREN;
|
|
7909
8499
|
}
|
|
7910
8500
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
7911
8501
|
}
|
|
@@ -7999,11 +8589,77 @@ function resolveCallee2(call, site, ctx, read) {
|
|
|
7999
8589
|
return spelling;
|
|
8000
8590
|
}
|
|
8001
8591
|
const outcome = read?.outcomes.get(spelling.key) ?? (0, import_resolution11.calleeOutcomeOf)(ctx.facts, spelling.key);
|
|
8592
|
+
if (selfCallInMixin(call, outcome, site, ctx)) {
|
|
8593
|
+
return { kind: "stopped", reason: "selfCallInMixin" };
|
|
8594
|
+
}
|
|
8002
8595
|
return asCallee(outcome, site.owner, ctx);
|
|
8003
8596
|
}
|
|
8597
|
+
function selfCallInMixin(call, outcome, site, ctx) {
|
|
8598
|
+
if (outcome.kind !== "callerSupplied" || !outcome.key.startsWith(`${site.owner}#`)) {
|
|
8599
|
+
return false;
|
|
8600
|
+
}
|
|
8601
|
+
const callee = readThrough(field(call, "function"));
|
|
8602
|
+
const receiver = callee?.type === "attribute" ? field(callee, "object") : null;
|
|
8603
|
+
const name = callee === null ? null : field(callee, "attribute")?.text;
|
|
8604
|
+
if (receiver?.type !== "identifier" || name === void 0 || name === null) {
|
|
8605
|
+
return false;
|
|
8606
|
+
}
|
|
8607
|
+
if (outcome.key !== `${site.owner}#${receiver.text}`) {
|
|
8608
|
+
return false;
|
|
8609
|
+
}
|
|
8610
|
+
return ctx.facts.lookup("instanceOf", 0, outcome.key).some((row) => {
|
|
8611
|
+
const classKey = String(row[1]);
|
|
8612
|
+
return ctx.facts.has("plainClass", [classKey]) && !instancesHaveAttribute(ctx.facts, classKey, name);
|
|
8613
|
+
});
|
|
8614
|
+
}
|
|
8615
|
+
var FALLBACK_ATTRIBUTE = "__getattr__";
|
|
8616
|
+
function instancesHaveAttribute(facts, classKey, name) {
|
|
8617
|
+
return facts.lookup("holdsProperty", 0, classKey).some((member) => {
|
|
8618
|
+
if (String(member[1]) === FALLBACK_ATTRIBUTE) {
|
|
8619
|
+
return true;
|
|
8620
|
+
}
|
|
8621
|
+
return facts.lookup("storesProperty", 0, String(member[2])).some(
|
|
8622
|
+
(store) => String(store[1]) === name && store[3] === import_resolution11.RECEIVER_STORE_NAME
|
|
8623
|
+
);
|
|
8624
|
+
});
|
|
8625
|
+
}
|
|
8004
8626
|
function namedOutcomes(keys, ctx) {
|
|
8005
8627
|
return (0, import_resolution11.calleeOutcomes)(ctx.facts, [...new Set(keys)]);
|
|
8006
8628
|
}
|
|
8629
|
+
function dispatchedCalls(calls, ctx) {
|
|
8630
|
+
const byKey = new Map(
|
|
8631
|
+
calls.map(({ call, site }) => [nodeId(site.file.file, call), call])
|
|
8632
|
+
);
|
|
8633
|
+
const found = /* @__PURE__ */ new Map();
|
|
8634
|
+
for (const [key, outcome] of (0, import_resolution11.dispatchOutcomes)(ctx.facts, [...byKey.keys()])) {
|
|
8635
|
+
const call = byKey.get(key);
|
|
8636
|
+
if (call === void 0) {
|
|
8637
|
+
continue;
|
|
8638
|
+
}
|
|
8639
|
+
const targets = /* @__PURE__ */ new Map();
|
|
8640
|
+
for (const fn of outcome.functions) {
|
|
8641
|
+
for (const target of reachedThrough(fn, outcome.through, ctx)) {
|
|
8642
|
+
targets.set(nodeId(target.file.file, target.node), target);
|
|
8643
|
+
}
|
|
8644
|
+
}
|
|
8645
|
+
found.set(call.id, {
|
|
8646
|
+
targets: [...targets.values()],
|
|
8647
|
+
certain: outcome.certain && outcome.functions.every((fn) => !isLambda(fn, ctx)),
|
|
8648
|
+
unresolved: outcome.unresolved
|
|
8649
|
+
});
|
|
8650
|
+
}
|
|
8651
|
+
return found;
|
|
8652
|
+
}
|
|
8653
|
+
function reachedThrough(key, through, ctx) {
|
|
8654
|
+
const keys = isLambda(key, ctx) ? through.get(key) ?? [] : [key];
|
|
8655
|
+
return keys.flatMap((one) => {
|
|
8656
|
+
const target = isLambda(one, ctx) ? null : functionAt(one, ctx);
|
|
8657
|
+
return target === null ? [] : [target];
|
|
8658
|
+
});
|
|
8659
|
+
}
|
|
8660
|
+
function isLambda(key, ctx) {
|
|
8661
|
+
return ctx.definitions.get(key)?.type === "lambda";
|
|
8662
|
+
}
|
|
8007
8663
|
function functionNamed(nameKey2, ctx, read) {
|
|
8008
8664
|
if (assignedElsewhere(ctx.facts, nameKey2)) {
|
|
8009
8665
|
return null;
|
|
@@ -8222,6 +8878,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8222
8878
|
const targetsByKey = /* @__PURE__ */ new Map();
|
|
8223
8879
|
const stopsByKey = /* @__PURE__ */ new Map();
|
|
8224
8880
|
const argTargetsByKey = /* @__PURE__ */ new Map();
|
|
8881
|
+
const possibleTargetsByKey = /* @__PURE__ */ new Map();
|
|
8225
8882
|
const parameterCallsByKey = /* @__PURE__ */ new Map();
|
|
8226
8883
|
const callsByKey = /* @__PURE__ */ new Map();
|
|
8227
8884
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
@@ -8284,6 +8941,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8284
8941
|
}
|
|
8285
8942
|
targetsByKey.set(key, scan.targets);
|
|
8286
8943
|
argTargetsByKey.set(key, scan.argTargets);
|
|
8944
|
+
possibleTargetsByKey.set(key, scan.possibleTargets);
|
|
8287
8945
|
if (scan.parameterCalls.length > 0) {
|
|
8288
8946
|
parameterCallsByKey.set(key, scan.parameterCalls);
|
|
8289
8947
|
}
|
|
@@ -8324,17 +8982,18 @@ function reachedFunctions(seeds, options) {
|
|
|
8324
8982
|
continue;
|
|
8325
8983
|
}
|
|
8326
8984
|
const build = () => {
|
|
8327
|
-
const summary2 = (0,
|
|
8985
|
+
const summary2 = (0, import_extractor13.assembleSummary)(libraryUnit(target, options), {
|
|
8328
8986
|
gapHandling: options.gapHandling
|
|
8329
8987
|
});
|
|
8330
8988
|
if (options.gapHandling !== "silent") {
|
|
8331
8989
|
summary2.gaps.push(
|
|
8332
|
-
...(stopsByKey.get(key) ?? []).map(
|
|
8990
|
+
...(stopsByKey.get(key) ?? []).map(import_behavioral_ir7.unfollowedCallGap)
|
|
8333
8991
|
);
|
|
8334
8992
|
}
|
|
8335
|
-
(0,
|
|
8336
|
-
(0,
|
|
8337
|
-
(0,
|
|
8993
|
+
(0, import_behavioral_ir7.placeCalls)(summary2, targetsByKey.get(key));
|
|
8994
|
+
(0, import_behavioral_ir7.placeArgTargets)(summary2, argTargetsByKey.get(key));
|
|
8995
|
+
(0, import_behavioral_ir7.placePossibleCalls)(summary2, possibleTargetsByKey.get(key));
|
|
8996
|
+
(0, import_behavioral_ir7.placeCalleeParameters)(summary2, parameterCallsByKey.get(key));
|
|
8338
8997
|
return summary2;
|
|
8339
8998
|
};
|
|
8340
8999
|
const summary = ledger === void 0 ? build() : ledger.charging(chargeOf(charges, key), () => {
|
|
@@ -8350,13 +9009,14 @@ function reachedFunctions(seeds, options) {
|
|
|
8350
9009
|
summaries.push(summary);
|
|
8351
9010
|
}
|
|
8352
9011
|
if (options.gapHandling !== "silent") {
|
|
8353
|
-
(0,
|
|
9012
|
+
(0, import_behavioral_ir7.recordParameterGaps)(parameterCallsByKey, summariesByKey, passedPositions);
|
|
8354
9013
|
}
|
|
8355
9014
|
return {
|
|
8356
9015
|
summaries,
|
|
8357
9016
|
targetsByKey,
|
|
8358
9017
|
stopsByKey,
|
|
8359
9018
|
argTargetsByKey,
|
|
9019
|
+
possibleTargetsByKey,
|
|
8360
9020
|
parameterCallsByKey,
|
|
8361
9021
|
callsByKey,
|
|
8362
9022
|
passedPositions,
|
|
@@ -8380,24 +9040,42 @@ function chargeOf(charges, key) {
|
|
|
8380
9040
|
}
|
|
8381
9041
|
return charge;
|
|
8382
9042
|
}
|
|
9043
|
+
function dispatchedAmong(written, spellings, ctx) {
|
|
9044
|
+
return dispatchedCalls(
|
|
9045
|
+
written.filter(({ call, site }) => {
|
|
9046
|
+
if (!ENTRY_CALLEE_TYPES.has(field(call, "function")?.type ?? "")) {
|
|
9047
|
+
return false;
|
|
9048
|
+
}
|
|
9049
|
+
const outcome = resolveCallee2(call, site, ctx, spellings);
|
|
9050
|
+
return outcome.kind === "stopped" && outcome.reason !== "callerSupplied";
|
|
9051
|
+
}),
|
|
9052
|
+
ctx
|
|
9053
|
+
);
|
|
9054
|
+
}
|
|
9055
|
+
var ENTRY_CALLEE_TYPES = /* @__PURE__ */ new Set(["subscript", "call", "identifier"]);
|
|
8383
9056
|
function batchedReads(round, ctx) {
|
|
8384
9057
|
const bodies = round.flatMap(
|
|
8385
9058
|
(entry) => "source" in entry ? [{ key: entry.key, source: entry.source, ...bodyOf(entry.source) }] : []
|
|
8386
9059
|
);
|
|
8387
|
-
const
|
|
8388
|
-
|
|
8389
|
-
ctx
|
|
8390
|
-
);
|
|
9060
|
+
const written = bodies.flatMap((body) => body.written);
|
|
9061
|
+
const spellings = calleeSpellings(written, ctx);
|
|
8391
9062
|
const passed = namedOutcomes(
|
|
8392
9063
|
bodies.flatMap(
|
|
8393
|
-
({ source, written }) =>
|
|
9064
|
+
({ source, written: written2 }) => written2.flatMap(({ call }) => passedNameKeys(source.file, call))
|
|
8394
9065
|
),
|
|
8395
9066
|
ctx
|
|
8396
9067
|
);
|
|
9068
|
+
const dispatched = dispatchedAmong(written, spellings, ctx);
|
|
8397
9069
|
return new Map(
|
|
8398
9070
|
bodies.map((body) => [
|
|
8399
9071
|
body.key,
|
|
8400
|
-
{
|
|
9072
|
+
{
|
|
9073
|
+
body: body.body,
|
|
9074
|
+
written: body.written,
|
|
9075
|
+
spellings,
|
|
9076
|
+
passed,
|
|
9077
|
+
dispatched
|
|
9078
|
+
}
|
|
8401
9079
|
])
|
|
8402
9080
|
);
|
|
8403
9081
|
}
|
|
@@ -8428,13 +9106,15 @@ function scanOnce(source, key, ctx, options, read, charges) {
|
|
|
8428
9106
|
}
|
|
8429
9107
|
function ownReads(source, ctx) {
|
|
8430
9108
|
const body = bodyOf(source);
|
|
9109
|
+
const spellings = calleeSpellings(body.written, ctx);
|
|
8431
9110
|
return {
|
|
8432
9111
|
...body,
|
|
8433
|
-
spellings
|
|
9112
|
+
spellings,
|
|
8434
9113
|
passed: namedOutcomes(
|
|
8435
9114
|
body.written.flatMap(({ call }) => passedNameKeys(source.file, call)),
|
|
8436
9115
|
ctx
|
|
8437
|
-
)
|
|
9116
|
+
),
|
|
9117
|
+
dispatched: dispatchedAmong(body.written, spellings, ctx)
|
|
8438
9118
|
};
|
|
8439
9119
|
}
|
|
8440
9120
|
function storedScan(scan) {
|
|
@@ -8450,6 +9130,10 @@ function storedScan(scan) {
|
|
|
8450
9130
|
callee,
|
|
8451
9131
|
[...byPosition]
|
|
8452
9132
|
]),
|
|
9133
|
+
possibleTargets: [...scan.possibleTargets].map(([callee, places]) => [
|
|
9134
|
+
callee,
|
|
9135
|
+
[...places]
|
|
9136
|
+
]),
|
|
8453
9137
|
parameterCalls: [...scan.parameterCalls],
|
|
8454
9138
|
passedPositions: [...scan.passedPositions]
|
|
8455
9139
|
};
|
|
@@ -8465,6 +9149,7 @@ function scanFromStored(stored, functionFor) {
|
|
|
8465
9149
|
new Map(byPosition)
|
|
8466
9150
|
])
|
|
8467
9151
|
),
|
|
9152
|
+
possibleTargets: new Map(stored.possibleTargets),
|
|
8468
9153
|
parameterCalls: stored.parameterCalls,
|
|
8469
9154
|
passedPositions: new Set(stored.passedPositions)
|
|
8470
9155
|
};
|
|
@@ -8493,6 +9178,7 @@ var EMPTY_SCAN = {
|
|
|
8493
9178
|
stops: [],
|
|
8494
9179
|
targets: /* @__PURE__ */ new Map(),
|
|
8495
9180
|
argTargets: /* @__PURE__ */ new Map(),
|
|
9181
|
+
possibleTargets: /* @__PURE__ */ new Map(),
|
|
8496
9182
|
parameterCalls: [],
|
|
8497
9183
|
passedPositions: /* @__PURE__ */ new Set()
|
|
8498
9184
|
};
|
|
@@ -8550,15 +9236,15 @@ function passedNameKeys(file, call) {
|
|
|
8550
9236
|
if (args === null) {
|
|
8551
9237
|
return [];
|
|
8552
9238
|
}
|
|
8553
|
-
return args.
|
|
9239
|
+
return children(args).flatMap((arg) => {
|
|
8554
9240
|
const key = passedNameKeyOf(file, arg);
|
|
8555
9241
|
return key === null ? [] : [key];
|
|
8556
9242
|
});
|
|
8557
9243
|
}
|
|
8558
9244
|
function scanBody(source, ctx, recognized, read, implied) {
|
|
8559
9245
|
const followed = [];
|
|
8560
|
-
const stops =
|
|
8561
|
-
const placements = new
|
|
9246
|
+
const stops = new import_behavioral_ir7.StopList();
|
|
9247
|
+
const placements = new import_behavioral_ir7.TargetPlacements();
|
|
8562
9248
|
const parameterCalls = [];
|
|
8563
9249
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
8564
9250
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8569,12 +9255,25 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8569
9255
|
return EMPTY_SCAN;
|
|
8570
9256
|
}
|
|
8571
9257
|
const ownParameters = callParameterNames(node, source.exportPath.length > 1);
|
|
9258
|
+
const follow = (target) => {
|
|
9259
|
+
const key = keyOf2(target);
|
|
9260
|
+
if (!seen.has(key)) {
|
|
9261
|
+
seen.add(key);
|
|
9262
|
+
followed.push(target);
|
|
9263
|
+
}
|
|
9264
|
+
};
|
|
8572
9265
|
const recordPassedArgs = (call, callee, calleeKey2) => {
|
|
8573
9266
|
const args = field(call, "arguments");
|
|
8574
9267
|
if (args === null) {
|
|
8575
9268
|
return;
|
|
8576
9269
|
}
|
|
8577
|
-
args.
|
|
9270
|
+
children(args).forEach((arg, position) => {
|
|
9271
|
+
if (arg.type === "lambda") {
|
|
9272
|
+
if (calleeKey2 !== null) {
|
|
9273
|
+
passedPositions.add(`${calleeKey2}#${position}`);
|
|
9274
|
+
}
|
|
9275
|
+
return;
|
|
9276
|
+
}
|
|
8578
9277
|
const nameKey2 = passedNameKeyOf(file, arg);
|
|
8579
9278
|
if (nameKey2 === null) {
|
|
8580
9279
|
return;
|
|
@@ -8583,11 +9282,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8583
9282
|
if (resolved === null) {
|
|
8584
9283
|
return;
|
|
8585
9284
|
}
|
|
8586
|
-
|
|
8587
|
-
if (!seen.has(key)) {
|
|
8588
|
-
seen.add(key);
|
|
8589
|
-
followed.push(resolved);
|
|
8590
|
-
}
|
|
9285
|
+
follow(resolved);
|
|
8591
9286
|
placements.placeArg(callee, position, {
|
|
8592
9287
|
file: resolved.file.displayPath,
|
|
8593
9288
|
span: spanOf(resolved.node)
|
|
@@ -8597,9 +9292,30 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8597
9292
|
}
|
|
8598
9293
|
});
|
|
8599
9294
|
};
|
|
9295
|
+
const recordPossible = (call, callee, dispatched) => {
|
|
9296
|
+
dispatched.targets.forEach(follow);
|
|
9297
|
+
placements.placePossible(
|
|
9298
|
+
callee,
|
|
9299
|
+
dispatched.targets.map((target) => ({
|
|
9300
|
+
file: target.file.displayPath,
|
|
9301
|
+
span: spanOf(target.node)
|
|
9302
|
+
}))
|
|
9303
|
+
);
|
|
9304
|
+
recordPassedArgs(call, callee, null);
|
|
9305
|
+
if (dispatched.unresolved > 0 && !recognized.has(call.id)) {
|
|
9306
|
+
stops.add({ callee, reason: "unsettledValue" });
|
|
9307
|
+
}
|
|
9308
|
+
};
|
|
8600
9309
|
const record = (call, site) => {
|
|
8601
9310
|
const callee = calleeText(call);
|
|
8602
|
-
const
|
|
9311
|
+
const settled = resolveCallee2(call, site, ctx, spellings);
|
|
9312
|
+
const dispatched = settled.kind === "stopped" ? read.dispatched.get(call.id) : void 0;
|
|
9313
|
+
const [only] = dispatched?.targets ?? [];
|
|
9314
|
+
if (dispatched !== void 0 && only !== void 0 && !dispatched.certain) {
|
|
9315
|
+
recordPossible(call, callee, dispatched);
|
|
9316
|
+
return;
|
|
9317
|
+
}
|
|
9318
|
+
const outcome = only === void 0 ? settled : { kind: "followed", target: only };
|
|
8603
9319
|
placeCallee(placements, callee, outcome, call, file);
|
|
8604
9320
|
recordPassedArgs(
|
|
8605
9321
|
call,
|
|
@@ -8607,10 +9323,12 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8607
9323
|
outcome.kind === "followed" ? keyOf2(outcome.target) : null
|
|
8608
9324
|
);
|
|
8609
9325
|
if (outcome.kind === "stopped") {
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
9326
|
+
if (!recognized.has(call.id) && (0, import_behavioral_ir7.worthRecording)(outcome.reason)) {
|
|
9327
|
+
stops.add({
|
|
9328
|
+
callee,
|
|
9329
|
+
reason: outcome.reason,
|
|
9330
|
+
...resultUsedAsValue(call) ? { usedAsValue: true } : {}
|
|
9331
|
+
});
|
|
8614
9332
|
}
|
|
8615
9333
|
if (outcome.reason === "callerSupplied" && !parameterCallsSeen.has(callee)) {
|
|
8616
9334
|
const parameterIndex = ownParameters.indexOf(callee);
|
|
@@ -8621,11 +9339,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8621
9339
|
}
|
|
8622
9340
|
return;
|
|
8623
9341
|
}
|
|
8624
|
-
|
|
8625
|
-
if (!seen.has(key)) {
|
|
8626
|
-
seen.add(key);
|
|
8627
|
-
followed.push(outcome.target);
|
|
8628
|
-
}
|
|
9342
|
+
follow(outcome.target);
|
|
8629
9343
|
};
|
|
8630
9344
|
for (const { call, site } of written) {
|
|
8631
9345
|
record(call, site);
|
|
@@ -8635,30 +9349,27 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8635
9349
|
file: target.file.displayPath,
|
|
8636
9350
|
span: spanOf(target.node)
|
|
8637
9351
|
});
|
|
8638
|
-
|
|
8639
|
-
if (!seen.has(key)) {
|
|
8640
|
-
seen.add(key);
|
|
8641
|
-
followed.push(target);
|
|
8642
|
-
}
|
|
9352
|
+
follow(target);
|
|
8643
9353
|
}
|
|
8644
9354
|
return {
|
|
8645
9355
|
followed,
|
|
8646
|
-
stops,
|
|
9356
|
+
stops: stops.stops,
|
|
8647
9357
|
targets: placements.targets,
|
|
8648
9358
|
argTargets: placements.argTargets,
|
|
9359
|
+
possibleTargets: placements.possibleTargets,
|
|
8649
9360
|
parameterCalls,
|
|
8650
9361
|
passedPositions
|
|
8651
9362
|
};
|
|
8652
9363
|
}
|
|
8653
9364
|
function callsWritten(file, body, outer, owner, limit) {
|
|
8654
9365
|
const found = [];
|
|
8655
|
-
(0,
|
|
9366
|
+
(0, import_extractor13.walkDescendants)(body, outer, children, {
|
|
8656
9367
|
at: (child, scope) => {
|
|
8657
9368
|
if (child.type === "call") {
|
|
8658
9369
|
found.push({ call: child, site: { file, scope, owner } });
|
|
8659
9370
|
}
|
|
8660
9371
|
},
|
|
8661
|
-
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope :
|
|
9372
|
+
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope : import_extractor13.SKIP_CHILDREN
|
|
8662
9373
|
});
|
|
8663
9374
|
return found;
|
|
8664
9375
|
}
|
|
@@ -8678,14 +9389,14 @@ function identifiersUnder(node, found = []) {
|
|
|
8678
9389
|
found.push(node.text);
|
|
8679
9390
|
return found;
|
|
8680
9391
|
}
|
|
8681
|
-
for (const child of node
|
|
9392
|
+
for (const child of children(node)) {
|
|
8682
9393
|
if (child !== null && child.type !== "attribute" && child.type !== "subscript") {
|
|
8683
9394
|
identifiersUnder(child, found);
|
|
8684
9395
|
}
|
|
8685
9396
|
}
|
|
8686
9397
|
return found;
|
|
8687
9398
|
}
|
|
8688
|
-
function libraryUnit(target, options, binding = (0,
|
|
9399
|
+
function libraryUnit(target, options, binding = (0, import_behavioral_ir7.functionCallBinding)({
|
|
8689
9400
|
transport: "in-process",
|
|
8690
9401
|
recognition: "reachable"
|
|
8691
9402
|
})) {
|
|
@@ -8779,10 +9490,7 @@ function positionalParameters(node, isMethod2) {
|
|
|
8779
9490
|
}
|
|
8780
9491
|
const out = [];
|
|
8781
9492
|
let position = 0;
|
|
8782
|
-
for (const param of parameters
|
|
8783
|
-
if (param === null) {
|
|
8784
|
-
continue;
|
|
8785
|
-
}
|
|
9493
|
+
for (const param of children(parameters)) {
|
|
8786
9494
|
const name = parameterName2(param);
|
|
8787
9495
|
if (name === null) {
|
|
8788
9496
|
continue;
|
|
@@ -8802,10 +9510,7 @@ function callParameterNames(node, isMethod2) {
|
|
|
8802
9510
|
return [];
|
|
8803
9511
|
}
|
|
8804
9512
|
const names = [];
|
|
8805
|
-
for (const param of parameters
|
|
8806
|
-
if (param === null) {
|
|
8807
|
-
continue;
|
|
8808
|
-
}
|
|
9513
|
+
for (const param of children(parameters)) {
|
|
8809
9514
|
const name = parameterName2(param);
|
|
8810
9515
|
if (name === null) {
|
|
8811
9516
|
continue;
|
|
@@ -8830,10 +9535,10 @@ function parameterName2(param) {
|
|
|
8830
9535
|
|
|
8831
9536
|
// src/moduleSurface.ts
|
|
8832
9537
|
function settlePythonModules(modules) {
|
|
8833
|
-
return (0,
|
|
9538
|
+
return (0, import_extractor14.settleModules)(modules, ["__init__.py"]);
|
|
8834
9539
|
}
|
|
8835
9540
|
function moduleExportUnits(file, options) {
|
|
8836
|
-
const module2 = (0,
|
|
9541
|
+
const module2 = (0, import_extractor14.moduleOfFile)(options.modules, file.file);
|
|
8837
9542
|
if (module2 === void 0) {
|
|
8838
9543
|
return [];
|
|
8839
9544
|
}
|
|
@@ -8855,8 +9560,8 @@ function moduleExportUnits(file, options) {
|
|
|
8855
9560
|
exportPath: [...one.exportPath]
|
|
8856
9561
|
},
|
|
8857
9562
|
options,
|
|
8858
|
-
(0,
|
|
8859
|
-
recognition:
|
|
9563
|
+
(0, import_behavioral_ir8.moduleExportBinding)({
|
|
9564
|
+
recognition: import_extractor14.MODULE_SURFACE_RECOGNITION,
|
|
8860
9565
|
module: module2.name,
|
|
8861
9566
|
exportName
|
|
8862
9567
|
})
|
|
@@ -8902,7 +9607,7 @@ function exportsOf(file, node, exportName) {
|
|
|
8902
9607
|
if (node.type !== "class_definition" || body === null) {
|
|
8903
9608
|
return [];
|
|
8904
9609
|
}
|
|
8905
|
-
return body.
|
|
9610
|
+
return children(body).flatMap((child) => {
|
|
8906
9611
|
if (child === null) {
|
|
8907
9612
|
return [];
|
|
8908
9613
|
}
|
|
@@ -8975,6 +9680,10 @@ var PackPositions = class {
|
|
|
8975
9680
|
const [packAt, patternAt] = id.split("/").map(Number);
|
|
8976
9681
|
return this.packs[packAt ?? -1]?.discovery[patternAt ?? -1];
|
|
8977
9682
|
}
|
|
9683
|
+
packOf(id) {
|
|
9684
|
+
const [packAt] = id.split("/").map(Number);
|
|
9685
|
+
return this.packs[packAt ?? -1];
|
|
9686
|
+
}
|
|
8978
9687
|
formAt(at) {
|
|
8979
9688
|
const pack = this.packs[at[0]];
|
|
8980
9689
|
const pattern = pack?.discovery[at[1]];
|
|
@@ -9025,6 +9734,11 @@ function watchRouterIndex(index, db, positions, fileOfModule) {
|
|
|
9025
9734
|
found
|
|
9026
9735
|
);
|
|
9027
9736
|
return found;
|
|
9737
|
+
},
|
|
9738
|
+
// The wrapper index notes what it reads through the mounts, in terms
|
|
9739
|
+
// it can look up again.
|
|
9740
|
+
mountsAbove(pattern, constructionKey) {
|
|
9741
|
+
return index.mountsAbove(pattern, constructionKey);
|
|
9028
9742
|
}
|
|
9029
9743
|
};
|
|
9030
9744
|
}
|
|
@@ -9129,9 +9843,33 @@ function buildRouterIndex(files, packs, resolverOptions) {
|
|
|
9129
9843
|
};
|
|
9130
9844
|
}
|
|
9131
9845
|
return NOT_ROUTER;
|
|
9846
|
+
},
|
|
9847
|
+
mountsAbove(pattern, constructionKey) {
|
|
9848
|
+
const index = byPattern.get(pattern);
|
|
9849
|
+
return index === void 0 ? null : hopsAbove(index, constructionKey);
|
|
9132
9850
|
}
|
|
9133
9851
|
};
|
|
9134
9852
|
}
|
|
9853
|
+
function hopsAbove(index, key) {
|
|
9854
|
+
const hops = [];
|
|
9855
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9856
|
+
let current = key;
|
|
9857
|
+
while (current !== null) {
|
|
9858
|
+
const construction = index.byValueKey.get(current);
|
|
9859
|
+
if (construction === void 0 || seen.has(current)) {
|
|
9860
|
+
return null;
|
|
9861
|
+
}
|
|
9862
|
+
seen.add(current);
|
|
9863
|
+
const states = index.mounts.get(construction) ?? [];
|
|
9864
|
+
const only = states.length === 1 ? states[0] : void 0;
|
|
9865
|
+
if (only?.kind !== "mounted" || only.written === void 0) {
|
|
9866
|
+
return null;
|
|
9867
|
+
}
|
|
9868
|
+
hops.push({ ...only.written, parentKey: only.parentValueKey });
|
|
9869
|
+
current = only.parentValueKey;
|
|
9870
|
+
}
|
|
9871
|
+
return hops;
|
|
9872
|
+
}
|
|
9135
9873
|
function composedPrefixOf(index, construction, routerPath) {
|
|
9136
9874
|
const ownPrefix = composedOwnPrefix(construction.prefix, index.composition);
|
|
9137
9875
|
if (ownPrefix.kind === "abstain") {
|
|
@@ -9414,8 +10152,8 @@ function constructionStatement(stmt, module2, importModule) {
|
|
|
9414
10152
|
if (stmt.type !== "expression_statement") {
|
|
9415
10153
|
return null;
|
|
9416
10154
|
}
|
|
9417
|
-
const assignment2 = stmt.
|
|
9418
|
-
(child) => child
|
|
10155
|
+
const assignment2 = children(stmt).find(
|
|
10156
|
+
(child) => child.type === "assignment"
|
|
9419
10157
|
);
|
|
9420
10158
|
if (assignment2 === void 0) {
|
|
9421
10159
|
return null;
|
|
@@ -9489,7 +10227,7 @@ function collectReturnedConstructions(bound, importModule, composition, index) {
|
|
|
9489
10227
|
if (inner.type !== "return_statement") {
|
|
9490
10228
|
continue;
|
|
9491
10229
|
}
|
|
9492
|
-
const returned = inner.
|
|
10230
|
+
const returned = inner.namedChild(0);
|
|
9493
10231
|
if (returned?.type !== "call") {
|
|
9494
10232
|
continue;
|
|
9495
10233
|
}
|
|
@@ -9669,7 +10407,7 @@ function sequenceElementNames(node) {
|
|
|
9669
10407
|
return null;
|
|
9670
10408
|
}
|
|
9671
10409
|
const names = [];
|
|
9672
|
-
for (const child of node
|
|
10410
|
+
for (const child of children(node)) {
|
|
9673
10411
|
if (child?.type !== "identifier") {
|
|
9674
10412
|
return null;
|
|
9675
10413
|
}
|
|
@@ -9882,8 +10620,9 @@ function recordMountStatement(stmt, position, scan) {
|
|
|
9882
10620
|
scan.index.facts
|
|
9883
10621
|
);
|
|
9884
10622
|
const mounted = args[0] ?? (scan.composition.routerKeyword === void 0 ? void 0 : keywordArgs[scan.composition.routerKeyword]);
|
|
10623
|
+
const recorded = state.kind === "mounted" ? { ...state, written: { call: mountCall.call, file: scan.bound.file } } : state;
|
|
9885
10624
|
for (const target of mountedConstructions(mounted, position, scan)) {
|
|
9886
|
-
recordMount(scan.index, target,
|
|
10625
|
+
recordMount(scan.index, target, recorded);
|
|
9887
10626
|
}
|
|
9888
10627
|
}
|
|
9889
10628
|
function mountStateOf(includerConstructorName, includer, keywordArgs, objectPrefix, composition, site, facts) {
|
|
@@ -10324,10 +11063,10 @@ function poetryPackages(pyproject) {
|
|
|
10324
11063
|
|
|
10325
11064
|
// src/testCases.ts
|
|
10326
11065
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
10327
|
-
var
|
|
10328
|
-
var
|
|
11066
|
+
var import_behavioral_ir9 = require("@suss/behavioral-ir");
|
|
11067
|
+
var import_extractor15 = require("@suss/extractor");
|
|
10329
11068
|
var import_resolution16 = require("@suss/resolution");
|
|
10330
|
-
var
|
|
11069
|
+
var import_values27 = require("@suss/values");
|
|
10331
11070
|
function pythonTestIndex(packs, context) {
|
|
10332
11071
|
const patterns = packs.flatMap((pack) => pack.tests ?? []);
|
|
10333
11072
|
return patterns.length === 0 ? null : new PythonTestIndex(patterns, context);
|
|
@@ -10344,7 +11083,7 @@ var PythonTestIndex = class {
|
|
|
10344
11083
|
implied = /* @__PURE__ */ new Map();
|
|
10345
11084
|
/** The tests in one file, when the file is collected and listed. */
|
|
10346
11085
|
unitsIn(file, options) {
|
|
10347
|
-
return this.testsIn(file).filter((test) => (0,
|
|
11086
|
+
return this.testsIn(file).filter((test) => (0, import_extractor15.isListedTestFile)(file.file, test.pattern.files)).map((test) => this.testUnit(file, test, options));
|
|
10348
11087
|
}
|
|
10349
11088
|
/** What pytest calls before this function runs, when it is a test or a fixture. */
|
|
10350
11089
|
impliedCalls(source) {
|
|
@@ -10394,7 +11133,7 @@ var PythonTestIndex = class {
|
|
|
10394
11133
|
)
|
|
10395
11134
|
).flatMap(
|
|
10396
11135
|
(marker) => positionalArguments(marker).flatMap((arg) => {
|
|
10397
|
-
const name = (0,
|
|
11136
|
+
const name = (0, import_values27.literalOf)(evaluatedValue(arg, this.context.facts));
|
|
10398
11137
|
return name === null ? [] : [name];
|
|
10399
11138
|
})
|
|
10400
11139
|
);
|
|
@@ -10418,7 +11157,7 @@ var PythonTestIndex = class {
|
|
|
10418
11157
|
...raw,
|
|
10419
11158
|
identity: {
|
|
10420
11159
|
...raw.identity,
|
|
10421
|
-
name: (0,
|
|
11160
|
+
name: (0, import_behavioral_ir9.testUnitName)(test.titles),
|
|
10422
11161
|
nameKind: "label",
|
|
10423
11162
|
kind: "test",
|
|
10424
11163
|
exportName: null,
|
|
@@ -10430,7 +11169,7 @@ var PythonTestIndex = class {
|
|
|
10430
11169
|
}
|
|
10431
11170
|
patternFor(file) {
|
|
10432
11171
|
return this.patterns.find(
|
|
10433
|
-
(pattern) => (0,
|
|
11172
|
+
(pattern) => (0, import_extractor15.matchesTestFileName)(file.file, pattern.filePatterns)
|
|
10434
11173
|
) ?? null;
|
|
10435
11174
|
}
|
|
10436
11175
|
testsIn(file) {
|
|
@@ -10808,11 +11547,11 @@ var PythonTestIndex = class {
|
|
|
10808
11547
|
return null;
|
|
10809
11548
|
}
|
|
10810
11549
|
const written = oneLine(call.text);
|
|
10811
|
-
const target = (0,
|
|
11550
|
+
const target = (0, import_values27.literalOf)(evaluatedValue(first, this.context.facts));
|
|
10812
11551
|
if (target !== null) {
|
|
10813
11552
|
return { ...this.dottedTarget(target), written };
|
|
10814
11553
|
}
|
|
10815
|
-
const member = second === void 0 ? null : (0,
|
|
11554
|
+
const member = second === void 0 ? null : (0, import_values27.literalOf)(evaluatedValue(second, this.context.facts));
|
|
10816
11555
|
if (member === null) {
|
|
10817
11556
|
return null;
|
|
10818
11557
|
}
|
|
@@ -10950,8 +11689,8 @@ function fixtureDeclaration(definition, file, pattern, facts) {
|
|
|
10950
11689
|
const renamed = keywordArgument(decorator, pattern.fixtureNameKeyword);
|
|
10951
11690
|
const autouse = keywordArgument(decorator, pattern.autouseKeyword);
|
|
10952
11691
|
return {
|
|
10953
|
-
name: (renamed === null ? null : (0,
|
|
10954
|
-
autouse: autouse !== null && (0,
|
|
11692
|
+
name: (renamed === null ? null : (0, import_values27.literalOf)(evaluatedValue(renamed, facts))) ?? defName,
|
|
11693
|
+
autouse: autouse !== null && (0, import_values27.constantOf)(evaluatedValue(autouse, facts)) === true
|
|
10955
11694
|
};
|
|
10956
11695
|
}
|
|
10957
11696
|
function keywordArgument(call, name) {
|
|
@@ -10983,18 +11722,20 @@ function oneLine(text2) {
|
|
|
10983
11722
|
}
|
|
10984
11723
|
|
|
10985
11724
|
// src/version.ts
|
|
10986
|
-
var
|
|
11725
|
+
var import_extractor16 = require("@suss/extractor");
|
|
10987
11726
|
var ADAPTER_VERSION = "0.1.0";
|
|
10988
|
-
var adapterStamp = (0,
|
|
11727
|
+
var adapterStamp = (0, import_extractor16.createAdapterStamp)({
|
|
10989
11728
|
moduleUrl: importMetaUrl,
|
|
10990
11729
|
version: ADAPTER_VERSION
|
|
10991
11730
|
});
|
|
10992
11731
|
|
|
10993
11732
|
// src/wrappers.ts
|
|
10994
|
-
var
|
|
11733
|
+
var import_extractor17 = require("@suss/extractor");
|
|
10995
11734
|
var import_resolution17 = require("@suss/resolution");
|
|
10996
11735
|
var EVERY_ROUTE = "wrapEvery ";
|
|
10997
11736
|
var OWN_ROUTES = "wrapOwn ";
|
|
11737
|
+
var MOUNTED = "wrapMounted ";
|
|
11738
|
+
var MOUNTED_SEPARATOR = "\0";
|
|
10998
11739
|
function describeRegistered(found) {
|
|
10999
11740
|
return (found ?? []).map(
|
|
11000
11741
|
({ reference }) => `${reference.file}:${reference.name}:${reference.onThrow === true}`
|
|
@@ -11032,8 +11773,15 @@ var PythonWrapperIndex = class {
|
|
|
11032
11773
|
/** By construction key: what a router or a blueprint registered. */
|
|
11033
11774
|
ownRoutes = /* @__PURE__ */ new Map();
|
|
11034
11775
|
unitsByKey = /* @__PURE__ */ new Map();
|
|
11776
|
+
/** By pack name: the app constructions its routes run under. */
|
|
11777
|
+
appCalls = /* @__PURE__ */ new Map();
|
|
11778
|
+
/** By wrapper reference: the parameters a dependency function declares, and its file. */
|
|
11779
|
+
dependencyParameterTable = /* @__PURE__ */ new Map();
|
|
11035
11780
|
unitsByFile = /* @__PURE__ */ new Map();
|
|
11036
|
-
/**
|
|
11781
|
+
/**
|
|
11782
|
+
* Told about every registration, a pack's form or a project decorator's
|
|
11783
|
+
* closure, so a cache can repeat the ones a file's discovery made.
|
|
11784
|
+
*/
|
|
11037
11785
|
onRegistered = null;
|
|
11038
11786
|
/**
|
|
11039
11787
|
* The same lookup `wrappersFor` noted under `id`, made again over this
|
|
@@ -11050,6 +11798,12 @@ var PythonWrapperIndex = class {
|
|
|
11050
11798
|
this.ownRoutes.get(id.slice(OWN_ROUTES.length))
|
|
11051
11799
|
);
|
|
11052
11800
|
}
|
|
11801
|
+
if (id.startsWith(MOUNTED)) {
|
|
11802
|
+
const [packName, position, key] = id.slice(MOUNTED.length).split(MOUNTED_SEPARATOR);
|
|
11803
|
+
const pack = this.options.packs.find((one) => one.name === packName);
|
|
11804
|
+
const pattern = pack?.discovery[Number(position)];
|
|
11805
|
+
return pack === void 0 || pattern === void 0 || key === void 0 ? describeRegistered([]) : describeRegistered(this.registeredAbove(pack, pattern, key));
|
|
11806
|
+
}
|
|
11053
11807
|
return null;
|
|
11054
11808
|
}
|
|
11055
11809
|
noted(kind, key, found) {
|
|
@@ -11091,14 +11845,65 @@ var PythonWrapperIndex = class {
|
|
|
11091
11845
|
inFile.push(unit);
|
|
11092
11846
|
this.unitsByFile.set(target.file.file, inFile);
|
|
11093
11847
|
}
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
...isThrowForm(declared.form) ? { onThrow: true } : {}
|
|
11099
|
-
},
|
|
11100
|
-
form: declared.form
|
|
11848
|
+
const reference = {
|
|
11849
|
+
file: target.file.displayPath,
|
|
11850
|
+
name: target.name,
|
|
11851
|
+
...isThrowForm(declared.form) ? { onThrow: true } : {}
|
|
11101
11852
|
};
|
|
11853
|
+
if (declared.form.type === "dependency") {
|
|
11854
|
+
this.dependencyParameterTable.set(referenceKey(reference), {
|
|
11855
|
+
file: target.file.file,
|
|
11856
|
+
names: parameterNamesOf(target.node),
|
|
11857
|
+
declaresSource: declaresSourcedParameter(
|
|
11858
|
+
target.node,
|
|
11859
|
+
Object.keys(declared.pattern.parameterSources ?? {})
|
|
11860
|
+
)
|
|
11861
|
+
});
|
|
11862
|
+
}
|
|
11863
|
+
return { reference, form: declared.form };
|
|
11864
|
+
}
|
|
11865
|
+
/**
|
|
11866
|
+
* The unit for the closure a project's decorator hands back, built once
|
|
11867
|
+
* however many routes the decorator is written on. Its name is what
|
|
11868
|
+
* calling the decorator writes, since the decorator may have a summary
|
|
11869
|
+
* of its own under its name.
|
|
11870
|
+
*/
|
|
11871
|
+
registeredClosure(target, closure) {
|
|
11872
|
+
this.onRegistered?.(target, closure);
|
|
11873
|
+
const span = spanOf(target.node);
|
|
11874
|
+
const key = `${target.file.file}:${span.start}-${span.end}`;
|
|
11875
|
+
if (!this.unitsByKey.has(key)) {
|
|
11876
|
+
const unit = closureUnit(target, closure, this.options);
|
|
11877
|
+
this.unitsByKey.set(key, unit);
|
|
11878
|
+
const inFile = this.unitsByFile.get(target.file.file) ?? [];
|
|
11879
|
+
inFile.push(unit);
|
|
11880
|
+
this.unitsByFile.set(target.file.file, inFile);
|
|
11881
|
+
}
|
|
11882
|
+
return { file: target.file.displayPath, name: target.name };
|
|
11883
|
+
}
|
|
11884
|
+
/**
|
|
11885
|
+
* The parameters the dependencies among these wrappers declare, and
|
|
11886
|
+
* whether one is declared through a parameter source such as `Query()`.
|
|
11887
|
+
* The library fills those from the request and validates them, the same
|
|
11888
|
+
* as parameters the route declares.
|
|
11889
|
+
*/
|
|
11890
|
+
dependencyParameters(references) {
|
|
11891
|
+
const names = /* @__PURE__ */ new Set();
|
|
11892
|
+
let declaresSource = false;
|
|
11893
|
+
for (const reference of references) {
|
|
11894
|
+
const found = this.dependencyParameterTable.get(referenceKey(reference));
|
|
11895
|
+
if (found === void 0) {
|
|
11896
|
+
continue;
|
|
11897
|
+
}
|
|
11898
|
+
if (this.options.facts !== void 0) {
|
|
11899
|
+
(0, import_resolution17.noteKeyRead)(this.options.facts, found.file);
|
|
11900
|
+
}
|
|
11901
|
+
for (const name of found.names) {
|
|
11902
|
+
names.add(name);
|
|
11903
|
+
}
|
|
11904
|
+
declaresSource ||= found.declaresSource;
|
|
11905
|
+
}
|
|
11906
|
+
return { names, declaresSource };
|
|
11102
11907
|
}
|
|
11103
11908
|
wrappersFor(query) {
|
|
11104
11909
|
const file = this.filesByPath.get(query.file);
|
|
@@ -11107,16 +11912,22 @@ var PythonWrapperIndex = class {
|
|
|
11107
11912
|
pattern: query.pattern,
|
|
11108
11913
|
form
|
|
11109
11914
|
}));
|
|
11110
|
-
if (file === void 0
|
|
11915
|
+
if (file === void 0) {
|
|
11111
11916
|
return [];
|
|
11112
11917
|
}
|
|
11918
|
+
const decorators = this.decoratorLayers(query, file);
|
|
11919
|
+
if (forms.length === 0) {
|
|
11920
|
+
return decorators;
|
|
11921
|
+
}
|
|
11922
|
+
const own = this.ownRoutesOf(query);
|
|
11113
11923
|
const found = [
|
|
11114
11924
|
...this.noted(
|
|
11115
11925
|
EVERY_ROUTE,
|
|
11116
11926
|
query.pack.name,
|
|
11117
11927
|
this.everyRoute.get(query.pack.name)
|
|
11118
11928
|
),
|
|
11119
|
-
...this.
|
|
11929
|
+
...own === null ? [] : this.mountedAbove(query, own.key),
|
|
11930
|
+
...own?.registered ?? []
|
|
11120
11931
|
];
|
|
11121
11932
|
for (const declared of forms) {
|
|
11122
11933
|
if (declared.form.type !== "dependency") {
|
|
@@ -11145,13 +11956,128 @@ var PythonWrapperIndex = class {
|
|
|
11145
11956
|
seen.add(key);
|
|
11146
11957
|
ordered.push(wrapper.reference);
|
|
11147
11958
|
}
|
|
11148
|
-
return
|
|
11959
|
+
return [
|
|
11960
|
+
...ordered.filter((one) => one.onThrow !== true),
|
|
11961
|
+
...decorators,
|
|
11962
|
+
...ordered.filter((one) => one.onThrow === true)
|
|
11963
|
+
];
|
|
11964
|
+
}
|
|
11965
|
+
/**
|
|
11966
|
+
* The decorators written on the route's function below the one that
|
|
11967
|
+
* registers it, outermost first. Each wraps the function the library
|
|
11968
|
+
* calls. None has a summary: a library's has no body in the run, and a
|
|
11969
|
+
* project's own is not composed into the route yet, so a project
|
|
11970
|
+
* decorator goes by what calling it writes, `require_admin(fn)`, which
|
|
11971
|
+
* no summary is named. The decorators the packs read, such as the
|
|
11972
|
+
* route's own and the namespace's `@ns.doc`, are left out.
|
|
11973
|
+
*/
|
|
11974
|
+
decoratorLayers(query, file) {
|
|
11975
|
+
const decorated = query.definitionNode.parent;
|
|
11976
|
+
if (decorated === null || decorated.type !== "decorated_definition") {
|
|
11977
|
+
return [];
|
|
11978
|
+
}
|
|
11979
|
+
const written = stripDecorators(decorated).decorators;
|
|
11980
|
+
const routeAt = written.findIndex(
|
|
11981
|
+
(decorator) => sameRange(rangeOf(decorator), query.classification.range)
|
|
11982
|
+
);
|
|
11983
|
+
return written.slice(routeAt + 1).flatMap((decorator) => this.decoratorLayer(decorator, query, file));
|
|
11984
|
+
}
|
|
11985
|
+
decoratorLayer(decorator, query, file) {
|
|
11986
|
+
const facts = this.options.facts;
|
|
11987
|
+
const direct = classifyDecorator(decorator, query.module, facts);
|
|
11988
|
+
const written = decoratorCallee(decorator);
|
|
11989
|
+
if (written === null || direct.module !== null && readByAPack(direct.module, this.options) || direct.objectName !== null && direct.objectName === query.classification.objectName || unwrapDecorator(decorator, facts) !== null) {
|
|
11990
|
+
return [];
|
|
11991
|
+
}
|
|
11992
|
+
const project = written.type === "identifier" ? this.functionCalled(file.file, written.text) : null;
|
|
11993
|
+
if (project !== null) {
|
|
11994
|
+
if (facts !== void 0) {
|
|
11995
|
+
(0, import_resolution17.noteKeyRead)(facts, project.file.file);
|
|
11996
|
+
}
|
|
11997
|
+
return [this.projectDecoratorLayer(project, query)];
|
|
11998
|
+
}
|
|
11999
|
+
return [{ file: direct.module ?? file.displayPath, name: written.text }];
|
|
12000
|
+
}
|
|
12001
|
+
/**
|
|
12002
|
+
* The layer a project's own decorator puts around the route. When it
|
|
12003
|
+
* hands back a closure written inside it that returns what calling the
|
|
12004
|
+
* function it was given returns, the closure is summarized and
|
|
12005
|
+
* composed into the route. Any other decorator, including one whose
|
|
12006
|
+
* closure keeps going after that call, goes by the same name with no
|
|
12007
|
+
* summary behind it.
|
|
12008
|
+
*/
|
|
12009
|
+
projectDecoratorLayer(decorator, query) {
|
|
12010
|
+
const continuation = parameterNamesOf(decorator.node)[0] ?? "";
|
|
12011
|
+
const name = `${decorator.name}(${continuation})`;
|
|
12012
|
+
const closure = closureReturnedBy(decorator.node);
|
|
12013
|
+
const handsOn = closure === null || continuation === "" ? [] : callsThrough(closure, continuation);
|
|
12014
|
+
if (closure === null || handsOn.length === 0 || !handsOn.every((statement) => returnsCallTo(statement, continuation))) {
|
|
12015
|
+
return { file: decorator.file.displayPath, name };
|
|
12016
|
+
}
|
|
12017
|
+
return this.registeredClosure(
|
|
12018
|
+
{ file: decorator.file, node: closure, name, exportPath: [] },
|
|
12019
|
+
{ pack: query.pack, pattern: query.pattern, continuation }
|
|
12020
|
+
);
|
|
12021
|
+
}
|
|
12022
|
+
/**
|
|
12023
|
+
* What the mounts above the route's router register on the way down:
|
|
12024
|
+
* the dependencies an `include_router` call lists, and those of each
|
|
12025
|
+
* router it is mounted onto, outermost first, the order they run in.
|
|
12026
|
+
*/
|
|
12027
|
+
mountedAbove(query, key) {
|
|
12028
|
+
const position = query.pack.discovery.indexOf(query.pattern);
|
|
12029
|
+
return [
|
|
12030
|
+
...this.noted(
|
|
12031
|
+
MOUNTED,
|
|
12032
|
+
[query.pack.name, position, key].join(MOUNTED_SEPARATOR),
|
|
12033
|
+
this.registeredAbove(query.pack, query.pattern, key)
|
|
12034
|
+
)
|
|
12035
|
+
];
|
|
12036
|
+
}
|
|
12037
|
+
registeredAbove(pack, pattern, key) {
|
|
12038
|
+
const hops = this.options.routers?.mountsAbove(pattern, key) ?? null;
|
|
12039
|
+
if (hops === null) {
|
|
12040
|
+
return [];
|
|
12041
|
+
}
|
|
12042
|
+
const forms = (pattern.wrappers ?? []).flatMap(
|
|
12043
|
+
(form) => form.type === "dependency" ? [{ pack, pattern, form }] : []
|
|
12044
|
+
);
|
|
12045
|
+
const found = [];
|
|
12046
|
+
for (const hop of [...hops].reverse()) {
|
|
12047
|
+
found.push(
|
|
12048
|
+
...hop.parentKey === null ? [] : this.ownRoutes.get(hop.parentKey) ?? []
|
|
12049
|
+
);
|
|
12050
|
+
const { keywordArgs } = readCallArguments(field(hop.call, "arguments"));
|
|
12051
|
+
for (const declared of forms) {
|
|
12052
|
+
const listed = keywordArgs[declared.form.keyword];
|
|
12053
|
+
const names = listed === void 0 ? [] : dependencyNamesIn(listed.node, declared.form);
|
|
12054
|
+
for (const name of names) {
|
|
12055
|
+
const target = this.functionCalled(hop.file, name);
|
|
12056
|
+
if (target !== null) {
|
|
12057
|
+
found.push(this.registered(target, declared));
|
|
12058
|
+
}
|
|
12059
|
+
}
|
|
12060
|
+
}
|
|
12061
|
+
}
|
|
12062
|
+
return found;
|
|
11149
12063
|
}
|
|
11150
12064
|
ownRoutesOf(query) {
|
|
12065
|
+
const match = this.ownRouterOf(query);
|
|
12066
|
+
return match === null ? null : {
|
|
12067
|
+
key: match.key,
|
|
12068
|
+
registered: this.noted(
|
|
12069
|
+
OWN_ROUTES,
|
|
12070
|
+
match.key,
|
|
12071
|
+
this.ownRoutes.get(match.key)
|
|
12072
|
+
)
|
|
12073
|
+
};
|
|
12074
|
+
}
|
|
12075
|
+
/** The construction call of the router a route is decorated on, when a registrar reads it. */
|
|
12076
|
+
ownRouterOf(query) {
|
|
11151
12077
|
const site = this.objectSiteOf(query);
|
|
11152
12078
|
const bound = site === null ? void 0 : this.filesByPath.get(site.file);
|
|
11153
12079
|
if (site === null || bound === void 0) {
|
|
11154
|
-
return
|
|
12080
|
+
return null;
|
|
11155
12081
|
}
|
|
11156
12082
|
if (this.options.facts !== void 0) {
|
|
11157
12083
|
(0, import_resolution17.noteKeyRead)(this.options.facts, site.file);
|
|
@@ -11165,12 +12091,46 @@ var PythonWrapperIndex = class {
|
|
|
11165
12091
|
{ pack: query.pack, pattern: query.pattern, form }
|
|
11166
12092
|
);
|
|
11167
12093
|
if (match !== null && match.registrar.covers === "ownRoutes") {
|
|
11168
|
-
return
|
|
11169
|
-
...this.noted(OWN_ROUTES, match.key, this.ownRoutes.get(match.key))
|
|
11170
|
-
];
|
|
12094
|
+
return match;
|
|
11171
12095
|
}
|
|
11172
12096
|
}
|
|
11173
|
-
return
|
|
12097
|
+
return null;
|
|
12098
|
+
}
|
|
12099
|
+
/** Records the app a pack's routes run under, for the keywords written on its construction. */
|
|
12100
|
+
recordApp(pack, call, file) {
|
|
12101
|
+
const calls = this.appCalls.get(pack) ?? [];
|
|
12102
|
+
if (!calls.some((one) => one.call === call)) {
|
|
12103
|
+
calls.push({ call, file });
|
|
12104
|
+
}
|
|
12105
|
+
this.appCalls.set(pack, calls);
|
|
12106
|
+
}
|
|
12107
|
+
/**
|
|
12108
|
+
* Every call that registers something for a route on the way to it:
|
|
12109
|
+
* the app's construction, the mount calls and the routers they mount
|
|
12110
|
+
* onto, and the route's own router. A caller reads a keyword off each.
|
|
12111
|
+
*/
|
|
12112
|
+
callsAbove(query) {
|
|
12113
|
+
const own = this.ownRouterOf(query);
|
|
12114
|
+
const hops = own === null ? [] : this.options.routers?.mountsAbove(query.pattern, own.key) ?? [];
|
|
12115
|
+
const parents = hops.flatMap((hop) => {
|
|
12116
|
+
const node = hop.parentKey === null ? null : nodeOfResolutionKey(hop.parentKey, this.options.facts);
|
|
12117
|
+
return node === null ? [] : [node];
|
|
12118
|
+
});
|
|
12119
|
+
const files = [
|
|
12120
|
+
...(this.appCalls.get(query.pack.name) ?? []).map((one) => one.file),
|
|
12121
|
+
...hops.map((hop) => hop.file)
|
|
12122
|
+
];
|
|
12123
|
+
if (this.options.facts !== void 0) {
|
|
12124
|
+
for (const file of files) {
|
|
12125
|
+
(0, import_resolution17.noteKeyRead)(this.options.facts, file);
|
|
12126
|
+
}
|
|
12127
|
+
}
|
|
12128
|
+
return [
|
|
12129
|
+
...(this.appCalls.get(query.pack.name) ?? []).map((one) => one.call),
|
|
12130
|
+
...hops.map((hop) => hop.call),
|
|
12131
|
+
...parents,
|
|
12132
|
+
...own === null ? [] : [own.call]
|
|
12133
|
+
];
|
|
11174
12134
|
}
|
|
11175
12135
|
/**
|
|
11176
12136
|
* Where the decorator's object was built: the route's own file, the file
|
|
@@ -11215,6 +12175,38 @@ var PythonWrapperIndex = class {
|
|
|
11215
12175
|
return this.unitsByFile.get(file) ?? [];
|
|
11216
12176
|
}
|
|
11217
12177
|
};
|
|
12178
|
+
function referenceKey(reference) {
|
|
12179
|
+
return `${reference.file}::${reference.name}`;
|
|
12180
|
+
}
|
|
12181
|
+
function readByAPack(module2, options) {
|
|
12182
|
+
return options.packs.some(
|
|
12183
|
+
(pack) => pack.discovery.some((pattern) => pattern.importModule.includes(module2))
|
|
12184
|
+
);
|
|
12185
|
+
}
|
|
12186
|
+
function decoratorCallee(decorator) {
|
|
12187
|
+
const written = decorator.namedChild(0);
|
|
12188
|
+
if (written === null) {
|
|
12189
|
+
return null;
|
|
12190
|
+
}
|
|
12191
|
+
return written.type === "call" ? field(written, "function") : written;
|
|
12192
|
+
}
|
|
12193
|
+
function sameRange(a, b) {
|
|
12194
|
+
return a.start === b.start && a.end === b.end;
|
|
12195
|
+
}
|
|
12196
|
+
function parameterNamesOf(definition) {
|
|
12197
|
+
return children(field(definition, "parameters")).flatMap((parameter) => {
|
|
12198
|
+
const named = parameterNameAndType(parameter);
|
|
12199
|
+
return named === null ? [] : [named.name];
|
|
12200
|
+
});
|
|
12201
|
+
}
|
|
12202
|
+
function declaresSourcedParameter(definition, sources) {
|
|
12203
|
+
return children(field(definition, "parameters")).some((parameter) => {
|
|
12204
|
+
const value = field(parameter, "value");
|
|
12205
|
+
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
12206
|
+
const name = callee?.type === "attribute" ? field(callee, "attribute")?.text : callee?.text;
|
|
12207
|
+
return name !== void 0 && sources.includes(name);
|
|
12208
|
+
});
|
|
12209
|
+
}
|
|
11218
12210
|
function isThrowForm(form) {
|
|
11219
12211
|
return form.type === "decoratedWrapper" && form.throwParam !== void 0;
|
|
11220
12212
|
}
|
|
@@ -11261,8 +12253,8 @@ function registerFrom(file, declared, index) {
|
|
|
11261
12253
|
}
|
|
11262
12254
|
function registerConstructorDependencies(file, declared, form, index) {
|
|
11263
12255
|
const scope = file.module.moduleScope;
|
|
11264
|
-
for (const stmt of file.root
|
|
11265
|
-
const assignment2 = stmt?.type === "expression_statement" ? stmt.
|
|
12256
|
+
for (const stmt of children(file.root)) {
|
|
12257
|
+
const assignment2 = stmt?.type === "expression_statement" ? children(stmt).find((child) => child?.type === "assignment") : void 0;
|
|
11266
12258
|
const left = assignment2 === void 0 || assignment2 === null ? null : field(assignment2, "left");
|
|
11267
12259
|
if (left?.type !== "identifier") {
|
|
11268
12260
|
continue;
|
|
@@ -11277,6 +12269,9 @@ function registerConstructorDependencies(file, declared, form, index) {
|
|
|
11277
12269
|
if (match === null) {
|
|
11278
12270
|
continue;
|
|
11279
12271
|
}
|
|
12272
|
+
if (match.registrar.covers === "everyRoute") {
|
|
12273
|
+
index.recordApp(declared.pack.name, match.call, file.file);
|
|
12274
|
+
}
|
|
11280
12275
|
const { keywordArgs } = readCallArguments(field(match.call, "arguments"));
|
|
11281
12276
|
const listed = keywordArgs[form.keyword];
|
|
11282
12277
|
if (listed === void 0) {
|
|
@@ -11294,7 +12289,7 @@ function coverageOf(match, pack) {
|
|
|
11294
12289
|
return match.registrar.covers === "everyRoute" ? { kind: "everyRoute", pack: pack.name } : { kind: "ownRoutes", key: match.key };
|
|
11295
12290
|
}
|
|
11296
12291
|
function registerDecorated(file, declared, form, index) {
|
|
11297
|
-
(0,
|
|
12292
|
+
(0, import_extractor17.walkDescendants)(file.root, file.module.moduleScope, children, {
|
|
11298
12293
|
at: (node, scope) => {
|
|
11299
12294
|
if (node.type !== "decorated_definition") {
|
|
11300
12295
|
return;
|
|
@@ -11330,7 +12325,7 @@ function registerDecorated(file, declared, form, index) {
|
|
|
11330
12325
|
});
|
|
11331
12326
|
}
|
|
11332
12327
|
function dependencyNamesIn(node, form) {
|
|
11333
|
-
const calls = node.type === "list" ? node
|
|
12328
|
+
const calls = node.type === "list" ? children(node) : [node];
|
|
11334
12329
|
const names = [];
|
|
11335
12330
|
for (const call of calls) {
|
|
11336
12331
|
const name = call === null ? null : dependencyNameOf(call, form);
|
|
@@ -11349,7 +12344,7 @@ function dependencyNameOf(node, form) {
|
|
|
11349
12344
|
if (calleeName3 === null || !form.callees.includes(calleeName3)) {
|
|
11350
12345
|
return null;
|
|
11351
12346
|
}
|
|
11352
|
-
const first = field(node, "arguments")?.
|
|
12347
|
+
const first = field(node, "arguments")?.namedChild(0);
|
|
11353
12348
|
return first?.type === "identifier" ? first.text : null;
|
|
11354
12349
|
}
|
|
11355
12350
|
function decoratorDependencies(classification, form) {
|
|
@@ -11367,7 +12362,7 @@ function parameterDependencies(definitionNode, form) {
|
|
|
11367
12362
|
if (direct !== null) {
|
|
11368
12363
|
return direct;
|
|
11369
12364
|
}
|
|
11370
|
-
for (const child of node
|
|
12365
|
+
for (const child of children(node)) {
|
|
11371
12366
|
const found = findIn(child, depth + 1);
|
|
11372
12367
|
if (found !== null) {
|
|
11373
12368
|
return found;
|
|
@@ -11375,10 +12370,7 @@ function parameterDependencies(definitionNode, form) {
|
|
|
11375
12370
|
}
|
|
11376
12371
|
return null;
|
|
11377
12372
|
};
|
|
11378
|
-
for (const param of field(definitionNode, "parameters")
|
|
11379
|
-
if (param === null) {
|
|
11380
|
-
continue;
|
|
11381
|
-
}
|
|
12373
|
+
for (const param of children(field(definitionNode, "parameters"))) {
|
|
11382
12374
|
const inDefault = field(param, "value");
|
|
11383
12375
|
const found = inDefault === null ? findIn(field(param, "type"), 0) : dependencyNameOf(inDefault, form);
|
|
11384
12376
|
if (found !== null) {
|
|
@@ -11388,15 +12380,42 @@ function parameterDependencies(definitionNode, form) {
|
|
|
11388
12380
|
return names;
|
|
11389
12381
|
}
|
|
11390
12382
|
function wrapperUnit(target, declared, options) {
|
|
12383
|
+
return unitAround(
|
|
12384
|
+
target,
|
|
12385
|
+
declared.pattern,
|
|
12386
|
+
{
|
|
12387
|
+
continuations: continuationStatements(target.node, declared.form),
|
|
12388
|
+
continuationName: null,
|
|
12389
|
+
form: declared.form,
|
|
12390
|
+
nameKind: "binding"
|
|
12391
|
+
},
|
|
12392
|
+
options
|
|
12393
|
+
);
|
|
12394
|
+
}
|
|
12395
|
+
function closureUnit(target, closure, options) {
|
|
12396
|
+
return unitAround(
|
|
12397
|
+
target,
|
|
12398
|
+
closure.pattern,
|
|
12399
|
+
{
|
|
12400
|
+
continuations: callsThrough(target.node, closure.continuation),
|
|
12401
|
+
continuationName: closure.continuation,
|
|
12402
|
+
form: null,
|
|
12403
|
+
nameKind: "label"
|
|
12404
|
+
},
|
|
12405
|
+
options
|
|
12406
|
+
);
|
|
12407
|
+
}
|
|
12408
|
+
function unitAround(target, pattern, reading, options) {
|
|
11391
12409
|
const { file, node, name, exportPath } = target;
|
|
11392
12410
|
const body = field(node, "body");
|
|
11393
12411
|
const range = rangeOf(node);
|
|
11394
12412
|
const raised = raisedResponses(body, {
|
|
11395
|
-
calls:
|
|
12413
|
+
calls: pattern.responseStatusCalls ?? [],
|
|
11396
12414
|
module: file.module,
|
|
11397
|
-
facts: options.facts
|
|
12415
|
+
facts: options.facts,
|
|
12416
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
11398
12417
|
});
|
|
11399
|
-
const continuations =
|
|
12418
|
+
const continuations = reading.continuations;
|
|
11400
12419
|
const terminals = bodyTerminals(body, raised, continuations);
|
|
11401
12420
|
const effects = invocationEffects(node, options.facts);
|
|
11402
12421
|
const extra = recognizedBodyEffects(
|
|
@@ -11405,7 +12424,7 @@ function wrapperUnit(target, declared, options) {
|
|
|
11405
12424
|
options.storageFor(file),
|
|
11406
12425
|
options.facts
|
|
11407
12426
|
);
|
|
11408
|
-
const delegate = (at) => ({
|
|
12427
|
+
const delegate = (at, to = null) => ({
|
|
11409
12428
|
terminal: {
|
|
11410
12429
|
kind: "delegate",
|
|
11411
12430
|
statusCode: null,
|
|
@@ -11414,18 +12433,18 @@ function wrapperUnit(target, declared, options) {
|
|
|
11414
12433
|
message: null,
|
|
11415
12434
|
component: null,
|
|
11416
12435
|
renderTree: null,
|
|
11417
|
-
delegateTarget:
|
|
12436
|
+
delegateTarget: to,
|
|
11418
12437
|
emitEvent: null,
|
|
11419
12438
|
location: rangeOf(at)
|
|
11420
12439
|
},
|
|
11421
12440
|
location: rangeOf(at)
|
|
11422
12441
|
});
|
|
11423
12442
|
const respond = (statement) => returnBranch(statement, {
|
|
11424
|
-
pattern
|
|
11425
|
-
responseShape: { reading:
|
|
12443
|
+
pattern,
|
|
12444
|
+
responseShape: { reading: import_extractor17.absentReading },
|
|
11426
12445
|
declaredStatus: {
|
|
11427
|
-
reading:
|
|
11428
|
-
...
|
|
12446
|
+
reading: import_extractor17.absentReading,
|
|
12447
|
+
...pattern.defaultStatusCode !== void 0 ? { libraryDefault: pattern.defaultStatusCode } : {}
|
|
11429
12448
|
},
|
|
11430
12449
|
module: file.module,
|
|
11431
12450
|
facts: options.facts
|
|
@@ -11437,7 +12456,10 @@ function wrapperUnit(target, declared, options) {
|
|
|
11437
12456
|
location: rangeOf(terminal.statement)
|
|
11438
12457
|
};
|
|
11439
12458
|
}
|
|
11440
|
-
if (terminal.type === "continuation"
|
|
12459
|
+
if (terminal.type === "continuation") {
|
|
12460
|
+
return delegate(terminal.statement, reading.continuationName);
|
|
12461
|
+
}
|
|
12462
|
+
if (reading.form !== null && returnHandsOn(terminal.statement, reading.form)) {
|
|
11441
12463
|
return delegate(terminal.statement);
|
|
11442
12464
|
}
|
|
11443
12465
|
return respond(terminal.statement);
|
|
@@ -11454,7 +12476,7 @@ function wrapperUnit(target, declared, options) {
|
|
|
11454
12476
|
return {
|
|
11455
12477
|
identity: {
|
|
11456
12478
|
name,
|
|
11457
|
-
nameKind:
|
|
12479
|
+
nameKind: reading.nameKind,
|
|
11458
12480
|
kind: "middleware",
|
|
11459
12481
|
file: file.displayPath,
|
|
11460
12482
|
range,
|
|
@@ -11478,7 +12500,7 @@ function returnHandsOn(statement, form) {
|
|
|
11478
12500
|
return false;
|
|
11479
12501
|
}
|
|
11480
12502
|
if (form.returnedValueResponds === true) {
|
|
11481
|
-
const returned = statement.
|
|
12503
|
+
const returned = statement.namedChild(0);
|
|
11482
12504
|
return returned === void 0 || returned === null || returned.type === "none";
|
|
11483
12505
|
}
|
|
11484
12506
|
return true;
|
|
@@ -11487,32 +12509,52 @@ function continuationStatements(node, form) {
|
|
|
11487
12509
|
if (form.type !== "decoratedWrapper" || form.continuationParam === void 0) {
|
|
11488
12510
|
return [];
|
|
11489
12511
|
}
|
|
11490
|
-
const params = (field(node, "parameters")
|
|
11491
|
-
(param2) => param2 !== null
|
|
11492
|
-
);
|
|
12512
|
+
const params = children(field(node, "parameters"));
|
|
11493
12513
|
const param = params[form.continuationParam];
|
|
11494
12514
|
const continuation = param === void 0 ? null : field(param, "name")?.text ?? (param.type === "identifier" ? param.text : null);
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
12515
|
+
return continuation === null ? [] : callsThrough(node, continuation);
|
|
12516
|
+
}
|
|
12517
|
+
function callsThrough(node, callee) {
|
|
11498
12518
|
const body = field(node, "body");
|
|
11499
12519
|
if (body === null) {
|
|
11500
12520
|
return [];
|
|
11501
12521
|
}
|
|
11502
12522
|
const found = [];
|
|
11503
12523
|
for (const call of bodyCalls(body)) {
|
|
11504
|
-
const
|
|
11505
|
-
const statement =
|
|
12524
|
+
const called = field(call, "function");
|
|
12525
|
+
const statement = called?.type === "identifier" && called.text === callee ? enclosingStatement(call, body) : null;
|
|
11506
12526
|
if (statement !== null) {
|
|
11507
12527
|
found.push(statement);
|
|
11508
12528
|
}
|
|
11509
12529
|
}
|
|
11510
12530
|
return found;
|
|
11511
12531
|
}
|
|
12532
|
+
function returnsCallTo(statement, callee) {
|
|
12533
|
+
if (statement.type !== "return_statement") {
|
|
12534
|
+
return false;
|
|
12535
|
+
}
|
|
12536
|
+
const value = statement.namedChild(0);
|
|
12537
|
+
const call = value?.type === "await" ? value.namedChild(0) : value;
|
|
12538
|
+
return call?.type === "call" && field(call, "function")?.text === callee;
|
|
12539
|
+
}
|
|
12540
|
+
function closureReturnedBy(decorator) {
|
|
12541
|
+
const statements = children(field(decorator, "body"));
|
|
12542
|
+
const returned = statements.find((statement) => statement.type === "return_statement")?.namedChild(0);
|
|
12543
|
+
if (returned?.type !== "identifier") {
|
|
12544
|
+
return null;
|
|
12545
|
+
}
|
|
12546
|
+
for (const statement of statements) {
|
|
12547
|
+
const { definition } = stripDecorators(statement);
|
|
12548
|
+
if (definition.type === "function_definition" && field(definition, "name")?.text === returned.text) {
|
|
12549
|
+
return definition;
|
|
12550
|
+
}
|
|
12551
|
+
}
|
|
12552
|
+
return null;
|
|
12553
|
+
}
|
|
11512
12554
|
|
|
11513
12555
|
// src/project.ts
|
|
11514
12556
|
function keptPythonParses() {
|
|
11515
|
-
return new
|
|
12557
|
+
return new import_extractor18.KeptParses(({ root }) => root.tree.delete());
|
|
11516
12558
|
}
|
|
11517
12559
|
async function parsePythonAhead(files, kept) {
|
|
11518
12560
|
for (const file of files) {
|
|
@@ -11601,16 +12643,16 @@ function factsForFile(options) {
|
|
|
11601
12643
|
}
|
|
11602
12644
|
async function extractPythonProject(options) {
|
|
11603
12645
|
const { roots, unreadManifests } = rootsOfRun(options);
|
|
11604
|
-
const timer = options.onTiming !== void 0 ? (0,
|
|
12646
|
+
const timer = options.onTiming !== void 0 ? (0, import_extractor18.createTimer)() : (0, import_extractor18.noopTimer)();
|
|
11605
12647
|
const cacheDir = adapterStamp.declineWhenRunFromSource(
|
|
11606
|
-
options.cacheDir === null ? null : options.cacheDir ?? (options.projectRoot !== void 0 ?
|
|
12648
|
+
options.cacheDir === null ? null : options.cacheDir ?? (options.projectRoot !== void 0 ? (0, import_extractor18.extractionCacheDirFor)(options.projectRoot) : null)
|
|
11607
12649
|
);
|
|
11608
|
-
const layer = (0,
|
|
12650
|
+
const layer = (0, import_extractor18.createCacheLayer)(cacheDir);
|
|
11609
12651
|
const packsDigest = `${adapterStamp.packsDigest(
|
|
11610
12652
|
options.packs.map(
|
|
11611
12653
|
(pack) => pack.version !== void 0 ? { name: pack.name, version: pack.version } : { name: pack.name }
|
|
11612
12654
|
)
|
|
11613
|
-
)}|${(0,
|
|
12655
|
+
)}|${(0, import_extractor18.extractionConfigStamp)({
|
|
11614
12656
|
gapHandling: options.gapHandling,
|
|
11615
12657
|
workspaceRoot: options.workspaceRoot,
|
|
11616
12658
|
projectRoot: options.projectRoot,
|
|
@@ -11620,17 +12662,20 @@ async function extractPythonProject(options) {
|
|
|
11620
12662
|
})}`;
|
|
11621
12663
|
const input = {
|
|
11622
12664
|
files: cacheDir === null ? [] : options.files,
|
|
11623
|
-
adapterPacksDigest: cacheDir === null ? packsDigest : (0,
|
|
12665
|
+
adapterPacksDigest: cacheDir === null ? packsDigest : (0, import_extractor18.runDigest)(packsDigest, options.packs, options.files)
|
|
11624
12666
|
};
|
|
11625
12667
|
const lookup = await timer.timeAsync(
|
|
11626
12668
|
"cache.lookup",
|
|
11627
12669
|
() => layer.lookup(input)
|
|
11628
12670
|
);
|
|
12671
|
+
const composed = (stored) => (0, import_extractor18.composeWrappers)(stored, {
|
|
12672
|
+
gapHandling: options.gapHandling ?? "permissive"
|
|
12673
|
+
});
|
|
11629
12674
|
if (lookup.kind === "hit") {
|
|
11630
12675
|
options.onCacheDiagnostic?.(lookup.diagnostic);
|
|
11631
12676
|
options.onTiming?.(timer.report());
|
|
11632
12677
|
return {
|
|
11633
|
-
summaries: lookup.summaries,
|
|
12678
|
+
summaries: composed(lookup.summaries),
|
|
11634
12679
|
facts: new import_datalog2.Database(),
|
|
11635
12680
|
roots,
|
|
11636
12681
|
unreadManifests
|
|
@@ -11645,7 +12690,7 @@ async function extractPythonProject(options) {
|
|
|
11645
12690
|
options.onCacheDiagnostic?.({ kind: "hit" });
|
|
11646
12691
|
options.onTiming?.(timer.report());
|
|
11647
12692
|
return {
|
|
11648
|
-
summaries: plan.allSummaries(),
|
|
12693
|
+
summaries: composed(plan.allSummaries()),
|
|
11649
12694
|
facts: new import_datalog2.Database(),
|
|
11650
12695
|
roots,
|
|
11651
12696
|
unreadManifests
|
|
@@ -11682,7 +12727,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11682
12727
|
const db = new import_datalog2.Database();
|
|
11683
12728
|
const summaries = [];
|
|
11684
12729
|
const gapHandling = options.gapHandling ?? "permissive";
|
|
11685
|
-
const tallies = (0,
|
|
12730
|
+
const tallies = (0, import_extractor10.createPackTallies)(options.packs);
|
|
11686
12731
|
const ledger = cacheDir === null ? null : new import_resolution18.DependencyLedger(options.files);
|
|
11687
12732
|
const log = ledger === null ? null : new import_resolution18.FactLog(db, ledger);
|
|
11688
12733
|
if (ledger !== null) {
|
|
@@ -11790,7 +12835,8 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11790
12835
|
roots,
|
|
11791
12836
|
facts: needsValues ? db : void 0,
|
|
11792
12837
|
definitions,
|
|
11793
|
-
storageFor
|
|
12838
|
+
storageFor,
|
|
12839
|
+
routers: plainRouterIndex
|
|
11794
12840
|
})
|
|
11795
12841
|
);
|
|
11796
12842
|
const importedDefinition2 = importedDefinitionLookup(db, bound);
|
|
@@ -11826,15 +12872,10 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11826
12872
|
});
|
|
11827
12873
|
let registering = null;
|
|
11828
12874
|
if (ledger !== null) {
|
|
11829
|
-
wrapperIndex.onRegistered = (target,
|
|
11830
|
-
const
|
|
11831
|
-
if (registering !== null &&
|
|
11832
|
-
registering.push(
|
|
11833
|
-
key: nodeId(target.file.file, target.node),
|
|
11834
|
-
name: target.name,
|
|
11835
|
-
exportPath: target.exportPath,
|
|
11836
|
-
form
|
|
11837
|
-
});
|
|
12875
|
+
wrapperIndex.onRegistered = (target, how) => {
|
|
12876
|
+
const stored = storedRegistration(target, how, positions);
|
|
12877
|
+
if (registering !== null && stored !== null) {
|
|
12878
|
+
registering.push(stored);
|
|
11838
12879
|
}
|
|
11839
12880
|
};
|
|
11840
12881
|
}
|
|
@@ -11847,12 +12888,11 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11847
12888
|
if (record !== void 0) {
|
|
11848
12889
|
discoveries.set(file, record);
|
|
11849
12890
|
for (const registration of record.registrations) {
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
|
|
11854
|
-
}
|
|
11855
|
-
wrapperIndex.registered(target, declared);
|
|
12891
|
+
registerAgain(registration, {
|
|
12892
|
+
positions,
|
|
12893
|
+
wrapperIndex,
|
|
12894
|
+
target: storedFunction(registration, definitions, filesByPath)
|
|
12895
|
+
});
|
|
11856
12896
|
}
|
|
11857
12897
|
continue;
|
|
11858
12898
|
}
|
|
@@ -11937,11 +12977,11 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11937
12977
|
const assemble = (raw, boundFile) => {
|
|
11938
12978
|
const summary = timer.time(
|
|
11939
12979
|
"summarize",
|
|
11940
|
-
() => (0,
|
|
12980
|
+
() => (0, import_extractor18.assembleSummary)(raw, { gapHandling })
|
|
11941
12981
|
);
|
|
11942
12982
|
summaries.push(summary);
|
|
11943
12983
|
assembledHere.add(summary);
|
|
11944
|
-
(0,
|
|
12984
|
+
(0, import_extractor10.tallyUnit)(tallies, raw.boundaryBinding?.recognition);
|
|
11945
12985
|
const span = raw.identity.span;
|
|
11946
12986
|
const key = span === void 0 ? null : `${boundFile.file}:${span.start}-${span.end}`;
|
|
11947
12987
|
if (key !== null) {
|
|
@@ -11958,7 +12998,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11958
12998
|
const summary = structuredClone(unit.summary);
|
|
11959
12999
|
summariesReused += 1;
|
|
11960
13000
|
summaries.push(summary);
|
|
11961
|
-
(0,
|
|
13001
|
+
(0, import_extractor10.tallyUnit)(tallies, unit.recognition);
|
|
11962
13002
|
if (unit.seedKey !== void 0) {
|
|
11963
13003
|
seedFrom(unit.seedKey, boundFile, summary);
|
|
11964
13004
|
}
|
|
@@ -12016,12 +13056,13 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12016
13056
|
const placeWhatItReached = (summary, key) => {
|
|
12017
13057
|
if (gapHandling !== "silent") {
|
|
12018
13058
|
summary.gaps.push(
|
|
12019
|
-
...(reached.stopsByKey.get(key) ?? []).map(
|
|
13059
|
+
...(reached.stopsByKey.get(key) ?? []).map(import_behavioral_ir10.unfollowedCallGap)
|
|
12020
13060
|
);
|
|
12021
13061
|
}
|
|
12022
|
-
(0,
|
|
12023
|
-
(0,
|
|
12024
|
-
(0,
|
|
13062
|
+
(0, import_behavioral_ir10.placeCalls)(summary, reached.targetsByKey.get(key));
|
|
13063
|
+
(0, import_behavioral_ir10.placeArgTargets)(summary, reached.argTargetsByKey.get(key));
|
|
13064
|
+
(0, import_behavioral_ir10.placePossibleCalls)(summary, reached.possibleTargetsByKey.get(key));
|
|
13065
|
+
(0, import_behavioral_ir10.placeCalleeParameters)(summary, reached.parameterCallsByKey.get(key));
|
|
12025
13066
|
};
|
|
12026
13067
|
for (const [key, owners] of summariesBySeed) {
|
|
12027
13068
|
for (const summary of owners) {
|
|
@@ -12038,7 +13079,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12038
13079
|
}
|
|
12039
13080
|
}
|
|
12040
13081
|
if (gapHandling !== "silent") {
|
|
12041
|
-
(0,
|
|
13082
|
+
(0, import_behavioral_ir10.recordParameterGaps)(
|
|
12042
13083
|
reached.parameterCallsByKey,
|
|
12043
13084
|
summariesBySeed,
|
|
12044
13085
|
reached.passedPositions
|
|
@@ -12062,8 +13103,8 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12062
13103
|
}
|
|
12063
13104
|
const summary = timer.time(
|
|
12064
13105
|
"summarize",
|
|
12065
|
-
() => (0,
|
|
12066
|
-
(0,
|
|
13106
|
+
() => (0, import_extractor18.assembleSummary)(
|
|
13107
|
+
(0, import_extractor18.moduleInitStructure)({
|
|
12067
13108
|
name: import_node_path5.default.basename(displayPath),
|
|
12068
13109
|
file: displayPath,
|
|
12069
13110
|
range: rangeOf(boundFile.root),
|
|
@@ -12072,7 +13113,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12072
13113
|
...charged(
|
|
12073
13114
|
boundFile.file,
|
|
12074
13115
|
() => moduleLoadInvocationEffects(boundFile.root, db)
|
|
12075
|
-
).map(
|
|
13116
|
+
).map(import_extractor18.effectToIR)
|
|
12076
13117
|
]
|
|
12077
13118
|
}),
|
|
12078
13119
|
{ gapHandling }
|
|
@@ -12092,34 +13133,38 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12092
13133
|
throw new ReplayFailed("");
|
|
12093
13134
|
}
|
|
12094
13135
|
const resolvedImports = (0, import_resolution18.importedFilesByFile)(db, displayPathOf);
|
|
12095
|
-
(0,
|
|
12096
|
-
(0,
|
|
13136
|
+
(0, import_extractor18.stampModuleImports)(summaries, (file) => resolvedImports.get(file) ?? []);
|
|
13137
|
+
(0, import_extractor18.stampModules)(summaries, declaredModules, options.workspaceRoot);
|
|
12097
13138
|
const idRoot = options.projectRoot ?? options.workspaceRoot;
|
|
12098
13139
|
for (const summary of summaries) {
|
|
12099
13140
|
const absoluteFile = options.workspaceRoot === void 0 ? summary.location.file : import_node_path5.default.resolve(options.workspaceRoot, summary.location.file);
|
|
12100
|
-
summary.identity.id = (0,
|
|
13141
|
+
summary.identity.id = (0, import_behavioral_ir10.summaryIdFromParts)({
|
|
12101
13142
|
workspace: void 0,
|
|
12102
13143
|
file: idRoot === void 0 ? absoluteFile : import_node_path5.default.relative(idRoot, absoluteFile),
|
|
12103
13144
|
name: summary.identity.name,
|
|
12104
13145
|
exportPath: summary.identity.exportPath
|
|
12105
13146
|
});
|
|
12106
13147
|
}
|
|
12107
|
-
(0,
|
|
12108
|
-
(0,
|
|
13148
|
+
(0, import_behavioral_ir10.disambiguateSummaryIds)(summaries);
|
|
13149
|
+
(0, import_behavioral_ir10.linkCallsToSummaries)(summaries);
|
|
12109
13150
|
const composed = timer.time("summarize", () => {
|
|
12110
13151
|
markExitCodeFunctions(summaries, exits, db, options.workspaceRoot);
|
|
12111
|
-
return (0,
|
|
13152
|
+
return (0, import_extractor18.composeWrappers)(summaries, { gapHandling });
|
|
12112
13153
|
});
|
|
13154
|
+
const walkedFiles = new Map(
|
|
13155
|
+
bound.map(({ file, displayPath }) => [displayPath, file])
|
|
13156
|
+
);
|
|
12113
13157
|
await timer.timeAsync("cache.write", async () => {
|
|
12114
|
-
if (cacheDir === null ||
|
|
13158
|
+
if (cacheDir === null || summaries.length === 0) {
|
|
12115
13159
|
return;
|
|
12116
13160
|
}
|
|
12117
13161
|
try {
|
|
12118
13162
|
await cache.layer.write(
|
|
12119
13163
|
cache.input,
|
|
12120
|
-
|
|
13164
|
+
summaries,
|
|
12121
13165
|
log === null || ledger === null || overBudget ? void 0 : pythonAttribution({
|
|
12122
|
-
|
|
13166
|
+
summaries,
|
|
13167
|
+
walkedFileOf: (locationFile) => walkedFiles.get(locationFile),
|
|
12123
13168
|
discoveries,
|
|
12124
13169
|
charges,
|
|
12125
13170
|
unitDrafts,
|
|
@@ -12174,6 +13219,39 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12174
13219
|
options.onTiming?.(timer.report());
|
|
12175
13220
|
return { summaries: composed, facts: db };
|
|
12176
13221
|
}
|
|
13222
|
+
function storedRegistration(target, how, positions) {
|
|
13223
|
+
const at = {
|
|
13224
|
+
key: nodeId(target.file.file, target.node),
|
|
13225
|
+
name: target.name,
|
|
13226
|
+
exportPath: target.exportPath
|
|
13227
|
+
};
|
|
13228
|
+
if ("continuation" in how) {
|
|
13229
|
+
const pattern = positions.idOf(how.pattern);
|
|
13230
|
+
return pattern === void 0 ? null : { ...at, pattern, continuation: how.continuation };
|
|
13231
|
+
}
|
|
13232
|
+
const form = positions.positionOf(how);
|
|
13233
|
+
return form === void 0 ? null : { ...at, form };
|
|
13234
|
+
}
|
|
13235
|
+
function registerAgain(registration, context) {
|
|
13236
|
+
const { positions, wrapperIndex, target } = context;
|
|
13237
|
+
const how = howRegistered(registration, positions);
|
|
13238
|
+
if (target === null || how === null) {
|
|
13239
|
+
throw new ReplayFailed(registration.key);
|
|
13240
|
+
}
|
|
13241
|
+
if ("continuation" in how) {
|
|
13242
|
+
wrapperIndex.registeredClosure(target, how);
|
|
13243
|
+
return;
|
|
13244
|
+
}
|
|
13245
|
+
wrapperIndex.registered(target, how);
|
|
13246
|
+
}
|
|
13247
|
+
function howRegistered(registration, positions) {
|
|
13248
|
+
if (!("continuation" in registration)) {
|
|
13249
|
+
return positions.formAt(registration.form) ?? null;
|
|
13250
|
+
}
|
|
13251
|
+
const pack = positions.packOf(registration.pattern);
|
|
13252
|
+
const pattern = positions.patternOf(registration.pattern);
|
|
13253
|
+
return pack === void 0 || pattern === void 0 ? null : { pack, pattern, continuation: registration.continuation };
|
|
13254
|
+
}
|
|
12177
13255
|
function pythonAttribution(args) {
|
|
12178
13256
|
const walkedByFile = (0, import_resolution18.walkRecordsByFile)({
|
|
12179
13257
|
scans: args.reached.scans,
|
|
@@ -12202,7 +13280,10 @@ function pythonAttribution(args) {
|
|
|
12202
13280
|
}
|
|
12203
13281
|
};
|
|
12204
13282
|
});
|
|
12205
|
-
return {
|
|
13283
|
+
return {
|
|
13284
|
+
roots,
|
|
13285
|
+
owners: (0, import_extractor18.ownersWhereWritten)(args.summaries, args.walkedFileOf)
|
|
13286
|
+
};
|
|
12206
13287
|
}
|
|
12207
13288
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
12208
13289
|
"__pycache__",
|
|
@@ -12233,7 +13314,7 @@ function indexDefinitions(into, file, node) {
|
|
|
12233
13314
|
if (isFunction(node)) {
|
|
12234
13315
|
into.set(nodeId(file, node), node);
|
|
12235
13316
|
}
|
|
12236
|
-
for (const child of node
|
|
13317
|
+
for (const child of children(node)) {
|
|
12237
13318
|
if (child !== null) {
|
|
12238
13319
|
indexDefinitions(into, file, child);
|
|
12239
13320
|
}
|
|
@@ -12499,7 +13580,7 @@ function importSitesIn(root) {
|
|
|
12499
13580
|
found.push({ module: entry.module, name: entry.name, line });
|
|
12500
13581
|
}
|
|
12501
13582
|
}
|
|
12502
|
-
for (const child of node
|
|
13583
|
+
for (const child of children(node)) {
|
|
12503
13584
|
if (child !== null) {
|
|
12504
13585
|
visit(child);
|
|
12505
13586
|
}
|