@suss/adapter-python 0.34.0 → 0.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1123 -512
- package/dist/index.d.cts +83 -3
- package/dist/index.d.ts +83 -3
- package/dist/index.js +1030 -411
- 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]);
|
|
@@ -1480,10 +1578,10 @@ function emitExpressionFacts(emitter, node) {
|
|
|
1480
1578
|
});
|
|
1481
1579
|
}
|
|
1482
1580
|
function yieldedValue(node) {
|
|
1483
|
-
if (node.
|
|
1581
|
+
if (allChildren(node).some((child) => child.type === "from")) {
|
|
1484
1582
|
return null;
|
|
1485
1583
|
}
|
|
1486
|
-
return node.
|
|
1584
|
+
return children(node).find((child) => child?.type !== "comment") ?? null;
|
|
1487
1585
|
}
|
|
1488
1586
|
function emitFunctionFacts(emitter, fn, classKey) {
|
|
1489
1587
|
const funcKey = nodeId(emitter.filePath, fn);
|
|
@@ -1555,7 +1653,7 @@ function emitFunctionFacts(emitter, fn, classKey) {
|
|
|
1555
1653
|
const stores = /* @__PURE__ */ new Map();
|
|
1556
1654
|
const visit = (child, type) => {
|
|
1557
1655
|
if (type === "return_statement") {
|
|
1558
|
-
const returned = child.
|
|
1656
|
+
const returned = child.namedChild(0);
|
|
1559
1657
|
if (returned != null) {
|
|
1560
1658
|
add(inside, "returnsValue", funcKey, valueKey(inside, returned));
|
|
1561
1659
|
statesReturn = true;
|
|
@@ -2593,9 +2691,7 @@ function stringExpression(node) {
|
|
|
2593
2691
|
}
|
|
2594
2692
|
function comparisonExpression(node) {
|
|
2595
2693
|
const operands = children(node);
|
|
2596
|
-
const operators = node.
|
|
2597
|
-
(child) => child !== null && !child.isNamed
|
|
2598
|
-
);
|
|
2694
|
+
const operators = allChildren(node).filter((child) => !child.isNamed);
|
|
2599
2695
|
const operator = operators[0];
|
|
2600
2696
|
if (operands.length !== 2 || operators.length !== 1 || operator === void 0) {
|
|
2601
2697
|
return { kind: "opaque" };
|
|
@@ -2689,6 +2785,7 @@ var STATEMENT_TYPES = {
|
|
|
2689
2785
|
kind: "return",
|
|
2690
2786
|
value: children(node)[0] ?? null
|
|
2691
2787
|
}),
|
|
2788
|
+
raise_statement: (node) => caughtInSameFunction(node) ? OPAQUE : { kind: "throw" },
|
|
2692
2789
|
try_statement: (node) => ({
|
|
2693
2790
|
kind: "block",
|
|
2694
2791
|
body: [
|
|
@@ -2777,6 +2874,19 @@ function blockStatements(block) {
|
|
|
2777
2874
|
function isRoot(node) {
|
|
2778
2875
|
return ROOT_TYPES.has(node.type);
|
|
2779
2876
|
}
|
|
2877
|
+
var EXCEPT_CLAUSE_TYPES = /* @__PURE__ */ new Set(["except_clause", "except_group_clause"]);
|
|
2878
|
+
function caughtInSameFunction(node) {
|
|
2879
|
+
let child = node;
|
|
2880
|
+
let parent = node.parent;
|
|
2881
|
+
while (parent !== null && !isRoot(parent)) {
|
|
2882
|
+
if (parent.type === "try_statement" && field(parent, "body")?.id === child.id && children(parent).some((clause) => EXCEPT_CLAUSE_TYPES.has(clause.type))) {
|
|
2883
|
+
return true;
|
|
2884
|
+
}
|
|
2885
|
+
child = parent;
|
|
2886
|
+
parent = parent.parent;
|
|
2887
|
+
}
|
|
2888
|
+
return false;
|
|
2889
|
+
}
|
|
2780
2890
|
function isPathStatement(node, parent) {
|
|
2781
2891
|
return parent.type === "module" || parent.type === "block" || node.type === "elif_clause";
|
|
2782
2892
|
}
|
|
@@ -3167,6 +3277,10 @@ function writtenNodeOf(node, db) {
|
|
|
3167
3277
|
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3168
3278
|
return bound?.context.writtenTo(node) ?? null;
|
|
3169
3279
|
}
|
|
3280
|
+
function calledDefinition(call, db) {
|
|
3281
|
+
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3282
|
+
return bound?.context.callable(call) ?? null;
|
|
3283
|
+
}
|
|
3170
3284
|
function resolutionKeyOf(node, db) {
|
|
3171
3285
|
const bound = db === void 0 ? void 0 : projects.get(db);
|
|
3172
3286
|
return bound?.keyOf(node) ?? null;
|
|
@@ -3389,7 +3503,7 @@ function argShapeOf(node) {
|
|
|
3389
3503
|
if (node.type === "list") {
|
|
3390
3504
|
return {
|
|
3391
3505
|
kind: "list",
|
|
3392
|
-
items: node
|
|
3506
|
+
items: children(node).map(readArg)
|
|
3393
3507
|
};
|
|
3394
3508
|
}
|
|
3395
3509
|
return { kind: "other" };
|
|
@@ -3400,10 +3514,7 @@ function readCallArguments(argumentList) {
|
|
|
3400
3514
|
if (argumentList === null) {
|
|
3401
3515
|
return { args, keywordArgs };
|
|
3402
3516
|
}
|
|
3403
|
-
for (const child of argumentList
|
|
3404
|
-
if (child === null) {
|
|
3405
|
-
continue;
|
|
3406
|
-
}
|
|
3517
|
+
for (const child of children(argumentList)) {
|
|
3407
3518
|
if (child.type === "keyword_argument") {
|
|
3408
3519
|
const nameNode = field(child, "name");
|
|
3409
3520
|
const valueNode = field(child, "value");
|
|
@@ -3447,7 +3558,7 @@ function builtObjectCallee(built, attributeName, objectName) {
|
|
|
3447
3558
|
return { importedName: attributeName, module: agreed, objectName };
|
|
3448
3559
|
}
|
|
3449
3560
|
};
|
|
3450
|
-
return (0,
|
|
3561
|
+
return (0, import_behavioral_ir2.dispatchByType)(table, built);
|
|
3451
3562
|
}
|
|
3452
3563
|
function resolveCallee(expr, module2, facts) {
|
|
3453
3564
|
if (expr.type === "identifier") {
|
|
@@ -3529,10 +3640,10 @@ function unwrapDecorator(decoratorNode, facts) {
|
|
|
3529
3640
|
}
|
|
3530
3641
|
function passesParametersThrough(def, inner) {
|
|
3531
3642
|
const params = field(def, "parameters");
|
|
3532
|
-
const names = (params
|
|
3643
|
+
const names = children(params).filter((child) => child.type === "identifier").map((child) => child.text);
|
|
3533
3644
|
const argumentList = field(inner, "arguments");
|
|
3534
|
-
const positional = (argumentList
|
|
3535
|
-
(child) => child
|
|
3645
|
+
const positional = children(argumentList).filter(
|
|
3646
|
+
(child) => child.type !== "keyword_argument"
|
|
3536
3647
|
);
|
|
3537
3648
|
return positional.length === names.length && positional.every(
|
|
3538
3649
|
(argument, at) => argument.type === "identifier" && argument.text === names[at]
|
|
@@ -3540,13 +3651,14 @@ function passesParametersThrough(def, inner) {
|
|
|
3540
3651
|
}
|
|
3541
3652
|
|
|
3542
3653
|
// src/discovery.ts
|
|
3543
|
-
var
|
|
3544
|
-
var
|
|
3545
|
-
var
|
|
3654
|
+
var import_behavioral_ir6 = require("@suss/behavioral-ir");
|
|
3655
|
+
var import_extractor9 = require("@suss/extractor");
|
|
3656
|
+
var import_values20 = require("@suss/values");
|
|
3546
3657
|
|
|
3547
3658
|
// src/clientCalls.ts
|
|
3548
|
-
var
|
|
3549
|
-
var
|
|
3659
|
+
var import_behavioral_ir3 = require("@suss/behavioral-ir");
|
|
3660
|
+
var import_extractor6 = require("@suss/extractor");
|
|
3661
|
+
var import_values14 = require("@suss/values");
|
|
3550
3662
|
|
|
3551
3663
|
// src/paths/bodyBranches.ts
|
|
3552
3664
|
var import_extractor4 = require("@suss/extractor");
|
|
@@ -3567,7 +3679,7 @@ var COMPARISONS = {
|
|
|
3567
3679
|
"<=": "lte"
|
|
3568
3680
|
};
|
|
3569
3681
|
function operatorText(node) {
|
|
3570
|
-
return node.
|
|
3682
|
+
return allChildren(node).filter((child) => !child.isNamed).map((child) => child.text).join(" ");
|
|
3571
3683
|
}
|
|
3572
3684
|
function valueRefOf(node, facts, inputs) {
|
|
3573
3685
|
const value = evaluatedValue(node, facts);
|
|
@@ -3619,7 +3731,7 @@ function nullCheckOf(subject, negated2, facts, inputs) {
|
|
|
3619
3731
|
};
|
|
3620
3732
|
}
|
|
3621
3733
|
function comparisonOf(node, facts, inputs) {
|
|
3622
|
-
const [left, right] = node.
|
|
3734
|
+
const [left, right] = children(node).filter(
|
|
3623
3735
|
(child) => child !== null
|
|
3624
3736
|
);
|
|
3625
3737
|
if (left === void 0 || right === void 0) {
|
|
@@ -3648,14 +3760,14 @@ function comparisonOf(node, facts, inputs) {
|
|
|
3648
3760
|
}
|
|
3649
3761
|
function predicateOf(node, facts, inputs) {
|
|
3650
3762
|
if (node.type === "parenthesized_expression") {
|
|
3651
|
-
const inner = node.
|
|
3763
|
+
const inner = node.namedChild(0);
|
|
3652
3764
|
return inner == null ? opaqueOf(node) : predicateOf(inner, facts, inputs);
|
|
3653
3765
|
}
|
|
3654
3766
|
if (node.type === "comparison_operator") {
|
|
3655
3767
|
return comparisonOf(node, facts, inputs);
|
|
3656
3768
|
}
|
|
3657
3769
|
if (node.type === "not_operator") {
|
|
3658
|
-
const operand2 = field(node, "argument") ?? node.
|
|
3770
|
+
const operand2 = field(node, "argument") ?? node.namedChild(0);
|
|
3659
3771
|
return operand2 == null ? opaqueOf(node) : { type: "negation", operand: predicateOf(operand2, facts, inputs) };
|
|
3660
3772
|
}
|
|
3661
3773
|
if (node.type === "identifier" || node.type === "attribute" || inputs?.has(node.id) === true) {
|
|
@@ -3670,11 +3782,11 @@ function predicateOf(node, facts, inputs) {
|
|
|
3670
3782
|
var SUBJECT_TYPES = /* @__PURE__ */ new Set(["identifier", "attribute", "subscript"]);
|
|
3671
3783
|
function operandsOf(node) {
|
|
3672
3784
|
if (node.type === "parenthesized_expression" || node.type === "not_operator") {
|
|
3673
|
-
const inner = field(node, "argument") ?? node.
|
|
3785
|
+
const inner = field(node, "argument") ?? node.namedChild(0);
|
|
3674
3786
|
return inner == null ? [] : operandsOf(inner);
|
|
3675
3787
|
}
|
|
3676
3788
|
if (node.type === "comparison_operator") {
|
|
3677
|
-
return node.
|
|
3789
|
+
return children(node).filter(
|
|
3678
3790
|
(child) => child !== null && SUBJECT_TYPES.has(child.type)
|
|
3679
3791
|
);
|
|
3680
3792
|
}
|
|
@@ -3700,7 +3812,7 @@ var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set(["function_definition", "lam
|
|
|
3700
3812
|
function exitKindOf(node, thrown) {
|
|
3701
3813
|
let sawReturn = false;
|
|
3702
3814
|
const raises = (current) => {
|
|
3703
|
-
for (const child of current
|
|
3815
|
+
for (const child of children(current)) {
|
|
3704
3816
|
if (child === null || NESTED_FUNCTION_TYPES.has(child.type)) {
|
|
3705
3817
|
continue;
|
|
3706
3818
|
}
|
|
@@ -3728,12 +3840,10 @@ function blockStatements2(block) {
|
|
|
3728
3840
|
if (block === null) {
|
|
3729
3841
|
return [];
|
|
3730
3842
|
}
|
|
3731
|
-
return block
|
|
3843
|
+
return children(block);
|
|
3732
3844
|
}
|
|
3733
3845
|
function childBlock(node) {
|
|
3734
|
-
return node.
|
|
3735
|
-
(child) => child !== null && child.type === "block"
|
|
3736
|
-
) ?? null;
|
|
3846
|
+
return children(node).find((child) => child.type === "block") ?? null;
|
|
3737
3847
|
}
|
|
3738
3848
|
var Lowerer = class {
|
|
3739
3849
|
// tree-sitter hands back a fresh wrapper object each time a child is
|
|
@@ -3782,7 +3892,7 @@ var Lowerer = class {
|
|
|
3782
3892
|
return [nested];
|
|
3783
3893
|
}
|
|
3784
3894
|
lowerIf(node) {
|
|
3785
|
-
const clauses = node.
|
|
3895
|
+
const clauses = children(node).filter(
|
|
3786
3896
|
(child) => child !== null && (child.type === "elif_clause" || child.type === "else_clause")
|
|
3787
3897
|
);
|
|
3788
3898
|
return {
|
|
@@ -3794,10 +3904,10 @@ var Lowerer = class {
|
|
|
3794
3904
|
};
|
|
3795
3905
|
}
|
|
3796
3906
|
lowerTry(node) {
|
|
3797
|
-
const excepts = node.
|
|
3907
|
+
const excepts = children(node).filter(
|
|
3798
3908
|
(child) => child !== null && (child.type === "except_clause" || child.type === "except_group_clause")
|
|
3799
3909
|
);
|
|
3800
|
-
const finallyClause = node.
|
|
3910
|
+
const finallyClause = children(node).find(
|
|
3801
3911
|
(child) => child !== null && child.type === "finally_clause"
|
|
3802
3912
|
) ?? null;
|
|
3803
3913
|
return {
|
|
@@ -3813,7 +3923,7 @@ var Lowerer = class {
|
|
|
3813
3923
|
(child) => child.type === "case_clause"
|
|
3814
3924
|
);
|
|
3815
3925
|
const groups = cases.map((clause) => {
|
|
3816
|
-
const pattern = clause.
|
|
3926
|
+
const pattern = children(clause).find(
|
|
3817
3927
|
(child) => child !== null && child.type === "case_pattern"
|
|
3818
3928
|
) ?? null;
|
|
3819
3929
|
return {
|
|
@@ -3894,7 +4004,7 @@ function literalArgOf(node, facts) {
|
|
|
3894
4004
|
return null;
|
|
3895
4005
|
}
|
|
3896
4006
|
function bodyCalls(node, found = []) {
|
|
3897
|
-
for (const child of node
|
|
4007
|
+
for (const child of children(node)) {
|
|
3898
4008
|
if (child === null || NESTED_DEFINITION_TYPES.has(child.type)) {
|
|
3899
4009
|
continue;
|
|
3900
4010
|
}
|
|
@@ -3906,7 +4016,7 @@ function bodyCalls(node, found = []) {
|
|
|
3906
4016
|
return found;
|
|
3907
4017
|
}
|
|
3908
4018
|
function moduleLoadCalls(node, found = []) {
|
|
3909
|
-
for (const child of node
|
|
4019
|
+
for (const child of children(node)) {
|
|
3910
4020
|
if (child === null || !runsAtModuleLoad(child)) {
|
|
3911
4021
|
continue;
|
|
3912
4022
|
}
|
|
@@ -3946,7 +4056,7 @@ function argumentNodes(call) {
|
|
|
3946
4056
|
if (args === null) {
|
|
3947
4057
|
return [];
|
|
3948
4058
|
}
|
|
3949
|
-
return args
|
|
4059
|
+
return children(args).map(
|
|
3950
4060
|
(child) => child.type === "keyword_argument" ? field(child, "value") ?? child : child
|
|
3951
4061
|
);
|
|
3952
4062
|
}
|
|
@@ -3957,6 +4067,9 @@ function calleeText(call) {
|
|
|
3957
4067
|
return field(call, "function")?.text ?? call.text;
|
|
3958
4068
|
}
|
|
3959
4069
|
function invocationEffects(definitionNode, facts) {
|
|
4070
|
+
return invocationSites(definitionNode, facts).map((site) => site.effect);
|
|
4071
|
+
}
|
|
4072
|
+
function invocationSites(definitionNode, facts) {
|
|
3960
4073
|
const body = field(definitionNode, "body");
|
|
3961
4074
|
if (body === null) {
|
|
3962
4075
|
return [];
|
|
@@ -3964,14 +4077,18 @@ function invocationEffects(definitionNode, facts) {
|
|
|
3964
4077
|
return invocationEffectsIn(body, bodyCalls(body), facts);
|
|
3965
4078
|
}
|
|
3966
4079
|
function moduleLoadInvocationEffects(moduleNode, facts) {
|
|
3967
|
-
return invocationEffectsIn(
|
|
4080
|
+
return invocationEffectsIn(
|
|
4081
|
+
moduleNode,
|
|
4082
|
+
moduleLoadCalls(moduleNode),
|
|
4083
|
+
facts
|
|
4084
|
+
).map((site) => site.effect);
|
|
3968
4085
|
}
|
|
3969
4086
|
var ASKED_ABOUT_TYPES = /* @__PURE__ */ new Set(["identifier", "attribute", "call"]);
|
|
3970
4087
|
function askedNodesUnder(node, found = []) {
|
|
3971
4088
|
if (ASKED_ABOUT_TYPES.has(node.type)) {
|
|
3972
4089
|
found.push(node);
|
|
3973
4090
|
}
|
|
3974
|
-
for (const child of node
|
|
4091
|
+
for (const child of children(node)) {
|
|
3975
4092
|
if (child !== null && !NESTED_DEFINITION_TYPES.has(child.type)) {
|
|
3976
4093
|
askedNodesUnder(child, found);
|
|
3977
4094
|
}
|
|
@@ -4045,11 +4162,14 @@ function invocationEffectsIn(body, written, facts) {
|
|
|
4045
4162
|
(condition) => predicateOf(condition, facts, inputs)
|
|
4046
4163
|
);
|
|
4047
4164
|
return {
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4165
|
+
call,
|
|
4166
|
+
effect: {
|
|
4167
|
+
type: "invocation",
|
|
4168
|
+
callee: calleeText(call),
|
|
4169
|
+
args: argsOf(call, facts),
|
|
4170
|
+
async: false,
|
|
4171
|
+
...conditions.length > 0 ? { preconditions: conditions } : {}
|
|
4172
|
+
}
|
|
4053
4173
|
};
|
|
4054
4174
|
});
|
|
4055
4175
|
}
|
|
@@ -4084,7 +4204,7 @@ function statedBy(statement, name) {
|
|
|
4084
4204
|
}
|
|
4085
4205
|
if (statement.type === "as_pattern") {
|
|
4086
4206
|
const alias = field(statement, "alias");
|
|
4087
|
-
const value = statement.
|
|
4207
|
+
const value = statement.namedChild(0) ?? null;
|
|
4088
4208
|
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
4089
4209
|
return alias?.text === name ? callee : null;
|
|
4090
4210
|
}
|
|
@@ -4280,7 +4400,7 @@ function importedFunctionMatch(call, options) {
|
|
|
4280
4400
|
return null;
|
|
4281
4401
|
}
|
|
4282
4402
|
const args = field(call, "arguments");
|
|
4283
|
-
const first = args
|
|
4403
|
+
const first = children(args)[0] ?? null;
|
|
4284
4404
|
const statement = first === null ? null : writtenStatement(first, void 0, options.facts);
|
|
4285
4405
|
if (statement === null) {
|
|
4286
4406
|
return null;
|
|
@@ -4644,7 +4764,7 @@ function columnComparisons(node) {
|
|
|
4644
4764
|
const args = field(node, "arguments");
|
|
4645
4765
|
return (args === null ? [] : children(args)).flatMap(columnComparisons);
|
|
4646
4766
|
}
|
|
4647
|
-
const operator = node.
|
|
4767
|
+
const operator = allChildren(node).find((child) => !child.isNamed);
|
|
4648
4768
|
const [left, right, ...rest] = children(node);
|
|
4649
4769
|
if (node.type !== "comparison_operator" || operator?.type !== "==" || left === void 0 || right === void 0 || rest.length > 0) {
|
|
4650
4770
|
return [];
|
|
@@ -5017,10 +5137,7 @@ function literalAt(key, facts) {
|
|
|
5017
5137
|
|
|
5018
5138
|
// src/paths/bodyBranches.ts
|
|
5019
5139
|
function returnStatements(node, found = []) {
|
|
5020
|
-
for (const child of node
|
|
5021
|
-
if (child === null) {
|
|
5022
|
-
continue;
|
|
5023
|
-
}
|
|
5140
|
+
for (const child of children(node)) {
|
|
5024
5141
|
if (child.type === "function_definition" || child.type === "lambda") {
|
|
5025
5142
|
continue;
|
|
5026
5143
|
}
|
|
@@ -5077,7 +5194,8 @@ function enumerateBodyBranches(options) {
|
|
|
5077
5194
|
const enumerated = (0, import_extractor4.enumerateOrDegrade)(
|
|
5078
5195
|
{
|
|
5079
5196
|
statements: lowered.statements,
|
|
5080
|
-
terminalsByStmt: lowered.terminalsByStmt
|
|
5197
|
+
terminalsByStmt: lowered.terminalsByStmt,
|
|
5198
|
+
...options.keepsArms === void 0 ? {} : { keepsArms: options.keepsArms }
|
|
5081
5199
|
},
|
|
5082
5200
|
statements
|
|
5083
5201
|
);
|
|
@@ -5114,6 +5232,236 @@ function enumerateBodyBranches(options) {
|
|
|
5114
5232
|
return branches;
|
|
5115
5233
|
}
|
|
5116
5234
|
|
|
5235
|
+
// src/paths/raisedResponses.ts
|
|
5236
|
+
var import_values12 = require("@suss/values");
|
|
5237
|
+
function statusNumberOf(node, options) {
|
|
5238
|
+
const value = (0, import_values12.constantOf)(evaluatedValue(node, options.facts));
|
|
5239
|
+
if (typeof value === "number") {
|
|
5240
|
+
return value;
|
|
5241
|
+
}
|
|
5242
|
+
const origin = originOf(node, options.module);
|
|
5243
|
+
return origin === null ? null : options.constants?.[`${origin.module}.${origin.name}`] ?? null;
|
|
5244
|
+
}
|
|
5245
|
+
var NESTED_DEFINITION_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
5246
|
+
function raisedResponses(body, options) {
|
|
5247
|
+
if (options.calls.length === 0) {
|
|
5248
|
+
return [];
|
|
5249
|
+
}
|
|
5250
|
+
return raisesIn(body, options);
|
|
5251
|
+
}
|
|
5252
|
+
function raisesIn(body, options) {
|
|
5253
|
+
if (body === null) {
|
|
5254
|
+
return [];
|
|
5255
|
+
}
|
|
5256
|
+
const found = [];
|
|
5257
|
+
const walk = (node) => {
|
|
5258
|
+
for (const child of children(node)) {
|
|
5259
|
+
if (child === null || NESTED_DEFINITION_TYPES2.has(child.type)) {
|
|
5260
|
+
continue;
|
|
5261
|
+
}
|
|
5262
|
+
const response = raisedResponseOf(child, options);
|
|
5263
|
+
if (response !== null) {
|
|
5264
|
+
found.push(response);
|
|
5265
|
+
}
|
|
5266
|
+
walk(child);
|
|
5267
|
+
}
|
|
5268
|
+
};
|
|
5269
|
+
walk(body);
|
|
5270
|
+
return found;
|
|
5271
|
+
}
|
|
5272
|
+
var ENDING_EXPRESSION = {
|
|
5273
|
+
raise_statement: (statement) => statement.namedChild(0) ?? null,
|
|
5274
|
+
expression_statement: (statement) => {
|
|
5275
|
+
const only = statement.namedChild(0);
|
|
5276
|
+
return only?.type === "call" ? only : null;
|
|
5277
|
+
}
|
|
5278
|
+
};
|
|
5279
|
+
function raisedResponseOf(statement, options) {
|
|
5280
|
+
const expression = ENDING_EXPRESSION[statement.type]?.(statement) ?? null;
|
|
5281
|
+
if (expression === null) {
|
|
5282
|
+
return null;
|
|
5283
|
+
}
|
|
5284
|
+
const thrownByCall = statement.type !== "raise_statement";
|
|
5285
|
+
const prebuilt = thrownByCall ? null : prebuiltCallOf(expression, options);
|
|
5286
|
+
if (prebuilt !== null) {
|
|
5287
|
+
return {
|
|
5288
|
+
statement,
|
|
5289
|
+
thrownByCall,
|
|
5290
|
+
terminal: terminalOf(
|
|
5291
|
+
statement,
|
|
5292
|
+
calleeOf(prebuilt.call, prebuilt.call),
|
|
5293
|
+
prebuilt.call,
|
|
5294
|
+
prebuilt.declared,
|
|
5295
|
+
prebuilt.options
|
|
5296
|
+
)
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
const call = expression.type === "call" ? expression : null;
|
|
5300
|
+
const callee = calleeOf(expression, call);
|
|
5301
|
+
const declared = declaredCallFor(callee, options);
|
|
5302
|
+
if (declared === void 0 && thrownByCall) {
|
|
5303
|
+
return null;
|
|
5304
|
+
}
|
|
5305
|
+
return {
|
|
5306
|
+
statement,
|
|
5307
|
+
thrownByCall,
|
|
5308
|
+
terminal: terminalOf(statement, callee, call, declared, options)
|
|
5309
|
+
};
|
|
5310
|
+
}
|
|
5311
|
+
function prebuiltCallOf(expression, options) {
|
|
5312
|
+
if (expression.type !== "identifier" && expression.type !== "attribute") {
|
|
5313
|
+
return null;
|
|
5314
|
+
}
|
|
5315
|
+
const written = writtenNodeOf(expression, options.facts);
|
|
5316
|
+
if (written === null || written.type !== "call") {
|
|
5317
|
+
return null;
|
|
5318
|
+
}
|
|
5319
|
+
const inItsFile = { ...options, module: moduleOf(written) };
|
|
5320
|
+
const declared = declaredCallFor(calleeOf(written, written), inItsFile);
|
|
5321
|
+
return declared === void 0 ? null : { call: written, declared, options: inItsFile };
|
|
5322
|
+
}
|
|
5323
|
+
function returnedResponseStatus(statement, options) {
|
|
5324
|
+
const returned = statement.namedChild(0);
|
|
5325
|
+
if (options.calls.length === 0 || returned === void 0 || returned === null || returned.type !== "call") {
|
|
5326
|
+
return null;
|
|
5327
|
+
}
|
|
5328
|
+
const callee = field(returned, "function");
|
|
5329
|
+
if (callee === null) {
|
|
5330
|
+
return null;
|
|
5331
|
+
}
|
|
5332
|
+
const declared = declaredCallFor(callee, options);
|
|
5333
|
+
return declared === void 0 ? null : statusOf(declared, returned, options);
|
|
5334
|
+
}
|
|
5335
|
+
function calleeOf(expression, call) {
|
|
5336
|
+
return call === null ? expression : field(call, "function") ?? expression;
|
|
5337
|
+
}
|
|
5338
|
+
function declaredCallFor(callee, options) {
|
|
5339
|
+
const origin = originOf(callee, options.module);
|
|
5340
|
+
if (origin === null) {
|
|
5341
|
+
return void 0;
|
|
5342
|
+
}
|
|
5343
|
+
const qualified = `${origin.module}.${origin.name}`;
|
|
5344
|
+
return options.calls.find((call) => call.callee === qualified);
|
|
5345
|
+
}
|
|
5346
|
+
function terminalOf(statement, callee, call, declared, options) {
|
|
5347
|
+
return {
|
|
5348
|
+
kind: "throw",
|
|
5349
|
+
statusCode: declared === void 0 ? null : statusOf(declared, call, options),
|
|
5350
|
+
body: null,
|
|
5351
|
+
exceptionType: lastSegmentOf(declared?.callee ?? callee.text),
|
|
5352
|
+
message: call === null ? null : writtenMessageOf(call),
|
|
5353
|
+
...declared === void 0 ? {} : { producesResponse: true },
|
|
5354
|
+
component: null,
|
|
5355
|
+
renderTree: null,
|
|
5356
|
+
delegateTarget: null,
|
|
5357
|
+
emitEvent: null,
|
|
5358
|
+
location: rangeOf(statement)
|
|
5359
|
+
};
|
|
5360
|
+
}
|
|
5361
|
+
function lastSegmentOf(dotted) {
|
|
5362
|
+
const segment = dotted.split(".").pop();
|
|
5363
|
+
return segment === void 0 || segment === "" ? null : segment;
|
|
5364
|
+
}
|
|
5365
|
+
function statusOf(declared, call, options) {
|
|
5366
|
+
const written = call === null ? null : statusArgumentOf(declared, call);
|
|
5367
|
+
if (written === null) {
|
|
5368
|
+
return declared.defaultStatusCode === void 0 ? null : { type: "literal", value: declared.defaultStatusCode };
|
|
5369
|
+
}
|
|
5370
|
+
const value = statusNumberOf(written, options);
|
|
5371
|
+
return value === null ? { type: "dynamic", sourceText: written.text } : { type: "literal", value };
|
|
5372
|
+
}
|
|
5373
|
+
function argumentsOf2(call) {
|
|
5374
|
+
return children(field(call, "arguments"));
|
|
5375
|
+
}
|
|
5376
|
+
function statusArgumentOf(declared, call) {
|
|
5377
|
+
const args = argumentsOf2(call);
|
|
5378
|
+
const keyed = args.find(
|
|
5379
|
+
(arg) => arg.type === "keyword_argument" && field(arg, "name")?.text === declared.statusKeyword
|
|
5380
|
+
);
|
|
5381
|
+
if (keyed !== void 0) {
|
|
5382
|
+
return field(keyed, "value");
|
|
5383
|
+
}
|
|
5384
|
+
if (declared.statusArgument === void 0) {
|
|
5385
|
+
return null;
|
|
5386
|
+
}
|
|
5387
|
+
const positional = args.filter((arg) => arg.type !== "keyword_argument");
|
|
5388
|
+
return positional[declared.statusArgument] ?? null;
|
|
5389
|
+
}
|
|
5390
|
+
function writtenMessageOf(call) {
|
|
5391
|
+
for (const arg of argumentsOf2(call)) {
|
|
5392
|
+
const value = arg.type === "keyword_argument" ? field(arg, "value") : arg;
|
|
5393
|
+
const literal = value === null ? null : stringLiteralValue(value);
|
|
5394
|
+
if (literal !== null) {
|
|
5395
|
+
return literal;
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
return null;
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
// src/responseHandOff.ts
|
|
5402
|
+
var import_extractor5 = require("@suss/extractor");
|
|
5403
|
+
function throughResponseHelpers(branches, sites, options) {
|
|
5404
|
+
const handOffs = [];
|
|
5405
|
+
for (const { call, effect } of sites) {
|
|
5406
|
+
const helper = helperBranchesAt(call, options);
|
|
5407
|
+
if (helper !== null) {
|
|
5408
|
+
handOffs.push({
|
|
5409
|
+
helper,
|
|
5410
|
+
preconditions: effect.preconditions,
|
|
5411
|
+
line: rangeOf(call).start,
|
|
5412
|
+
at: rangeOf(call)
|
|
5413
|
+
});
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
return handOffs.length === 0 ? [...branches] : branches.flatMap((branch) => (0, import_extractor5.splitAtHandOffs)(branch, handOffs));
|
|
5417
|
+
}
|
|
5418
|
+
function helperBranchesAt(call, options) {
|
|
5419
|
+
const handed = callArguments(call).filter(
|
|
5420
|
+
(argument) => argument.node.type === "identifier" && refersToResponse(argument.node, options)
|
|
5421
|
+
);
|
|
5422
|
+
if (handed.length === 0) {
|
|
5423
|
+
return null;
|
|
5424
|
+
}
|
|
5425
|
+
const helper = calledDefinition(call, options.facts);
|
|
5426
|
+
if (helper === null || helper.type !== "function_definition") {
|
|
5427
|
+
return null;
|
|
5428
|
+
}
|
|
5429
|
+
const passed = /* @__PURE__ */ new Map();
|
|
5430
|
+
const parameters = parameterShapes(helper, isMethod(helper) ? 1 : 0);
|
|
5431
|
+
for (const argument of handed) {
|
|
5432
|
+
const parameter = parameters.find(
|
|
5433
|
+
(one) => argument.kind === "positional" ? one.position === argument.position : one.name === argument.name
|
|
5434
|
+
);
|
|
5435
|
+
if (parameter !== void 0) {
|
|
5436
|
+
passed.set(parameter.name, argument.node.text);
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5439
|
+
return passed.size === 0 ? null : (0, import_extractor5.helperPathsOnVariables)(options.readHelper(helper), passed);
|
|
5440
|
+
}
|
|
5441
|
+
function refersToResponse(name, options) {
|
|
5442
|
+
const written = awaited(writtenNodeOf(name, options.facts));
|
|
5443
|
+
if (written === null) {
|
|
5444
|
+
return false;
|
|
5445
|
+
}
|
|
5446
|
+
if (sameNode(written, options.request)) {
|
|
5447
|
+
return true;
|
|
5448
|
+
}
|
|
5449
|
+
const callee = written.type === "call" ? field(written, "function") : null;
|
|
5450
|
+
const method = callee === null ? null : field(callee, "attribute");
|
|
5451
|
+
const receiver = callee === null ? null : field(callee, "object");
|
|
5452
|
+
if (method === null || receiver?.type !== "identifier" || !options.bodyMethods.includes(method.text)) {
|
|
5453
|
+
return false;
|
|
5454
|
+
}
|
|
5455
|
+
const parsedFrom = awaited(writtenNodeOf(receiver, options.facts));
|
|
5456
|
+
return parsedFrom !== null && sameNode(parsedFrom, options.request);
|
|
5457
|
+
}
|
|
5458
|
+
function awaited(node) {
|
|
5459
|
+
return node?.type === "await" ? node.namedChild(0) ?? null : node;
|
|
5460
|
+
}
|
|
5461
|
+
function sameNode(a, b) {
|
|
5462
|
+
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.tree === b.tree;
|
|
5463
|
+
}
|
|
5464
|
+
|
|
5117
5465
|
// src/clientCalls.ts
|
|
5118
5466
|
function clientCallUnits(root, module2, pack, pattern, options) {
|
|
5119
5467
|
const units = [];
|
|
@@ -5164,7 +5512,7 @@ function requestCalls(call, pattern, module2, options) {
|
|
|
5164
5512
|
return [];
|
|
5165
5513
|
}
|
|
5166
5514
|
const plain = requestCall(call, attribute, pattern, options);
|
|
5167
|
-
if (plain !== null && !(0,
|
|
5515
|
+
if (plain !== null && !(0, import_behavioral_ir3.hasNameHole)(plain.path)) {
|
|
5168
5516
|
return [plain];
|
|
5169
5517
|
}
|
|
5170
5518
|
const byBoundary = /* @__PURE__ */ new Map();
|
|
@@ -5173,7 +5521,7 @@ function requestCalls(call, pattern, module2, options) {
|
|
|
5173
5521
|
if (stated === null) {
|
|
5174
5522
|
continue;
|
|
5175
5523
|
}
|
|
5176
|
-
const key = `${stated.method} ${stated.path}`;
|
|
5524
|
+
const key = `${stated.method} ${stated.host ?? ""} ${stated.path}`;
|
|
5177
5525
|
if (!byBoundary.has(key)) {
|
|
5178
5526
|
byBoundary.set(key, stated);
|
|
5179
5527
|
}
|
|
@@ -5184,16 +5532,33 @@ function requestCalls(call, pattern, module2, options) {
|
|
|
5184
5532
|
return plain === null ? [] : [plain];
|
|
5185
5533
|
}
|
|
5186
5534
|
function requestCall(call, attribute, pattern, options, site) {
|
|
5535
|
+
const stated = methodAndPath(call, attribute, pattern, options, site);
|
|
5536
|
+
if (stated === null) {
|
|
5537
|
+
return null;
|
|
5538
|
+
}
|
|
5539
|
+
const redirectDelivery = redirectDeliveryAt(call, pattern, options, site);
|
|
5540
|
+
return redirectDelivery === void 0 ? stated : { ...stated, redirectDelivery };
|
|
5541
|
+
}
|
|
5542
|
+
function redirectDeliveryAt(call, pattern, options, site) {
|
|
5543
|
+
const option = pattern.response?.redirectOption;
|
|
5544
|
+
const argument = option === void 0 ? null : argumentAt(call, null, option.name);
|
|
5545
|
+
if (option === void 0 || argument === null) {
|
|
5546
|
+
return void 0;
|
|
5547
|
+
}
|
|
5548
|
+
const value = (0, import_values14.scalarOf)(evaluatedValue(argument, options.facts, site));
|
|
5549
|
+
return value === null ? void 0 : (0, import_extractor6.redirectDeliveryWhenSet)(option, value);
|
|
5550
|
+
}
|
|
5551
|
+
function methodAndPath(call, attribute, pattern, options, site) {
|
|
5187
5552
|
const verb = pattern.verbAttributeNames[attribute];
|
|
5188
5553
|
if (verb !== void 0) {
|
|
5189
|
-
const
|
|
5554
|
+
const target2 = urlAt(
|
|
5190
5555
|
call,
|
|
5191
5556
|
pattern.url.position,
|
|
5192
5557
|
pattern.url.keyword,
|
|
5193
5558
|
options,
|
|
5194
5559
|
site
|
|
5195
5560
|
);
|
|
5196
|
-
return
|
|
5561
|
+
return target2 === null ? null : { method: verb, ...target2, range: rangeOf(call), node: call };
|
|
5197
5562
|
}
|
|
5198
5563
|
const methodCall = pattern.methodCall;
|
|
5199
5564
|
if (methodCall === void 0 || methodCall.attribute !== attribute) {
|
|
@@ -5208,14 +5573,19 @@ function requestCall(call, attribute, pattern, options, site) {
|
|
|
5208
5573
|
if (method === null) {
|
|
5209
5574
|
return null;
|
|
5210
5575
|
}
|
|
5211
|
-
const
|
|
5576
|
+
const target = urlAt(
|
|
5212
5577
|
call,
|
|
5213
5578
|
methodCall.urlPosition,
|
|
5214
5579
|
pattern.url.keyword,
|
|
5215
5580
|
options,
|
|
5216
5581
|
site
|
|
5217
5582
|
);
|
|
5218
|
-
return
|
|
5583
|
+
return target === null ? null : {
|
|
5584
|
+
method: method.toUpperCase(),
|
|
5585
|
+
...target,
|
|
5586
|
+
range: rangeOf(call),
|
|
5587
|
+
node: call
|
|
5588
|
+
};
|
|
5219
5589
|
}
|
|
5220
5590
|
function calledAttribute(callee, pattern, module2, facts) {
|
|
5221
5591
|
const origin = originOf(callee, module2);
|
|
@@ -5248,7 +5618,9 @@ function urlAt(call, position, keyword, options, site) {
|
|
|
5248
5618
|
if (argument === null) {
|
|
5249
5619
|
return null;
|
|
5250
5620
|
}
|
|
5251
|
-
|
|
5621
|
+
const value = evaluatedValue(argument, options.facts, site);
|
|
5622
|
+
const path8 = (0, import_values14.pathOf)(value);
|
|
5623
|
+
return path8 === void 0 ? null : { path: path8, host: (0, import_values14.hostOf)(value) };
|
|
5252
5624
|
}
|
|
5253
5625
|
function argumentAt(call, position, keyword) {
|
|
5254
5626
|
const args = field(call, "arguments");
|
|
@@ -5266,25 +5638,33 @@ function argumentAt(call, position, keyword) {
|
|
|
5266
5638
|
}
|
|
5267
5639
|
positional.push(child);
|
|
5268
5640
|
}
|
|
5269
|
-
return positional[position] ?? null;
|
|
5641
|
+
return position === null ? null : positional[position] ?? null;
|
|
5270
5642
|
}
|
|
5271
|
-
function callerBranches(definition,
|
|
5643
|
+
function callerBranches(definition, reading) {
|
|
5644
|
+
const range = rangeOf(definition);
|
|
5272
5645
|
const body = field(definition, "body");
|
|
5273
|
-
const
|
|
5274
|
-
const
|
|
5275
|
-
if (body === null
|
|
5646
|
+
const sites = invocationSites(definition, reading.facts);
|
|
5647
|
+
const effects = sites.map((site) => site.effect);
|
|
5648
|
+
if (body === null) {
|
|
5276
5649
|
return [handsBack(range, effects)];
|
|
5277
5650
|
}
|
|
5651
|
+
const raised = raisesIn(body, {
|
|
5652
|
+
calls: [],
|
|
5653
|
+
module: moduleOf(definition),
|
|
5654
|
+
facts: reading.facts
|
|
5655
|
+
});
|
|
5278
5656
|
const branches = enumerateBodyBranches({
|
|
5279
5657
|
body,
|
|
5280
|
-
terminals,
|
|
5281
|
-
raised
|
|
5658
|
+
terminals: bodyTerminals(body, raised),
|
|
5659
|
+
raised,
|
|
5282
5660
|
effects,
|
|
5283
|
-
branchOf: (
|
|
5661
|
+
branchOf: (found2) => found2.type === "raise" ? { terminal: found2.terminal, location: rangeOf(found2.statement) } : handsBackAt(rangeOf(found2.statement)),
|
|
5284
5662
|
fallthrough: handsBackAt(range),
|
|
5285
|
-
facts
|
|
5663
|
+
facts: reading.facts,
|
|
5664
|
+
keepsArms: (condition) => (0, import_behavioral_ir3.testsStatus)(predicateOf(condition, reading.facts), reading.statusMembers)
|
|
5286
5665
|
});
|
|
5287
|
-
|
|
5666
|
+
const found = branches.length === 0 ? [handsBack(range, effects)] : branches;
|
|
5667
|
+
return reading.handOff === void 0 ? found : throughResponseHelpers(found, sites, reading.handOff);
|
|
5288
5668
|
}
|
|
5289
5669
|
function handsBackAt(range) {
|
|
5290
5670
|
return {
|
|
@@ -5320,11 +5700,24 @@ function responseAccessors(pattern) {
|
|
|
5320
5700
|
...response.body === void 0 ? {} : { bodyAccessors: response.body },
|
|
5321
5701
|
...response.statusCode === void 0 ? {} : { statusAccessors: response.statusCode },
|
|
5322
5702
|
...response.success === void 0 ? {} : { successAccessors: response.success },
|
|
5323
|
-
...response.failureDelivery === void 0 ? {} : { failureDelivery: response.failureDelivery }
|
|
5703
|
+
...response.failureDelivery === void 0 ? {} : { failureDelivery: response.failureDelivery },
|
|
5704
|
+
...response.redirectDelivery === void 0 ? {} : { redirectDelivery: response.redirectDelivery }
|
|
5324
5705
|
};
|
|
5325
5706
|
}
|
|
5326
5707
|
function clientUnit(definition, name, request, pattern, pack, options) {
|
|
5327
5708
|
const range = rangeOf(definition);
|
|
5709
|
+
const accessors = responseAccessors(pattern);
|
|
5710
|
+
const statusMembers = (0, import_behavioral_ir3.statusMembersOf)(accessors);
|
|
5711
|
+
const reading = {
|
|
5712
|
+
facts: options.facts,
|
|
5713
|
+
statusMembers,
|
|
5714
|
+
handOff: {
|
|
5715
|
+
request: request.node,
|
|
5716
|
+
bodyMethods: accessors.bodyAccessors ?? [],
|
|
5717
|
+
facts: options.facts,
|
|
5718
|
+
readHelper: (helper) => callerBranches(helper, { facts: options.facts, statusMembers })
|
|
5719
|
+
}
|
|
5720
|
+
};
|
|
5328
5721
|
return {
|
|
5329
5722
|
identity: {
|
|
5330
5723
|
name,
|
|
@@ -5336,15 +5729,17 @@ function clientUnit(definition, name, request, pattern, pack, options) {
|
|
|
5336
5729
|
exportName: name,
|
|
5337
5730
|
exportPath: [name]
|
|
5338
5731
|
},
|
|
5339
|
-
boundaryBinding: (0,
|
|
5732
|
+
boundaryBinding: (0, import_behavioral_ir3.restBinding)({
|
|
5340
5733
|
transport: pack.protocol,
|
|
5341
5734
|
method: request.method,
|
|
5342
5735
|
path: request.path,
|
|
5736
|
+
host: request.host,
|
|
5343
5737
|
recognition: pack.name
|
|
5344
5738
|
}),
|
|
5345
5739
|
parameters: [],
|
|
5346
|
-
branches: callerBranches(definition,
|
|
5347
|
-
...
|
|
5740
|
+
branches: callerBranches(definition, reading),
|
|
5741
|
+
...accessors,
|
|
5742
|
+
...request.redirectDelivery === void 0 ? {} : { redirectDelivery: request.redirectDelivery },
|
|
5348
5743
|
bodyContent: "statements",
|
|
5349
5744
|
dependencyCalls: [],
|
|
5350
5745
|
declaredContract: null
|
|
@@ -5388,8 +5783,8 @@ function routeOnDroppedApp(facts, object, constructionKey, pattern) {
|
|
|
5388
5783
|
}
|
|
5389
5784
|
|
|
5390
5785
|
// src/envReads.ts
|
|
5391
|
-
var
|
|
5392
|
-
var
|
|
5786
|
+
var import_behavioral_ir4 = require("@suss/behavioral-ir");
|
|
5787
|
+
var import_extractor7 = require("@suss/extractor");
|
|
5393
5788
|
var import_resolution7 = require("@suss/resolution");
|
|
5394
5789
|
|
|
5395
5790
|
// src/envSpellings.ts
|
|
@@ -5567,7 +5962,7 @@ function isTestedAt(parent, child, subject, seen) {
|
|
|
5567
5962
|
}
|
|
5568
5963
|
function conditionOf(node) {
|
|
5569
5964
|
if (node.type === "conditional_expression") {
|
|
5570
|
-
return node.
|
|
5965
|
+
return node.namedChild(1) ?? null;
|
|
5571
5966
|
}
|
|
5572
5967
|
return CONDITIONED_TYPES.has(node.type) ? field(node, "condition") : null;
|
|
5573
5968
|
}
|
|
@@ -5590,7 +5985,7 @@ function isPresentAt(node, subject) {
|
|
|
5590
5985
|
}
|
|
5591
5986
|
function isBranchWherePresent(parent, child, subject) {
|
|
5592
5987
|
if (parent.type === "conditional_expression") {
|
|
5593
|
-
const [whenTrue, test2, whenFalse] = parent
|
|
5988
|
+
const [whenTrue, test2, whenFalse] = children(parent);
|
|
5594
5989
|
return test2 !== void 0 && test2 !== null && (whenTrue?.id === child.id && isPresentWhen(test2, true, subject) || whenFalse?.id === child.id && isPresentWhen(test2, false, subject));
|
|
5595
5990
|
}
|
|
5596
5991
|
if (parent.type === "boolean_operator") {
|
|
@@ -5628,7 +6023,7 @@ function followsExitWhenAbsent(parent, child, subject) {
|
|
|
5628
6023
|
if (parent.type !== "block" && parent.type !== "module") {
|
|
5629
6024
|
return false;
|
|
5630
6025
|
}
|
|
5631
|
-
const statements = parent
|
|
6026
|
+
const statements = children(parent);
|
|
5632
6027
|
const at = statements.findIndex((statement) => statement?.id === child.id);
|
|
5633
6028
|
return statements.slice(0, at).some(
|
|
5634
6029
|
(statement) => statement !== null && leavesWhenAbsent(statement, subject)
|
|
@@ -5672,7 +6067,7 @@ function continuationRaises(from) {
|
|
|
5672
6067
|
let parent = current.parent;
|
|
5673
6068
|
while (parent !== null) {
|
|
5674
6069
|
if (parent.type === "block" || parent.type === "module") {
|
|
5675
|
-
const statements = parent
|
|
6070
|
+
const statements = children(parent);
|
|
5676
6071
|
const at = statements.findIndex((one) => one?.id === current.id);
|
|
5677
6072
|
const exit = firstExit(statements.slice(at + 1));
|
|
5678
6073
|
if (exit !== null) {
|
|
@@ -5716,7 +6111,7 @@ function exitOf(statement) {
|
|
|
5716
6111
|
if (LEAVING_TYPES.has(statement.type)) {
|
|
5717
6112
|
return "leave";
|
|
5718
6113
|
}
|
|
5719
|
-
return statement.type === "block" ? firstExit(statement
|
|
6114
|
+
return statement.type === "block" ? firstExit(children(statement)) : null;
|
|
5720
6115
|
}
|
|
5721
6116
|
function isPresentWhen(test, outcome, subject) {
|
|
5722
6117
|
const expression = peelParens(test);
|
|
@@ -5756,7 +6151,7 @@ function isPresentAfterComparison(comparison, outcome, subject) {
|
|
|
5756
6151
|
}
|
|
5757
6152
|
function comparisonParts(comparison) {
|
|
5758
6153
|
const operators = fields(comparison, "operators");
|
|
5759
|
-
const operands = comparison.
|
|
6154
|
+
const operands = children(comparison).filter(
|
|
5760
6155
|
(child) => child !== null && !operators.some((one) => one.id === child.id)
|
|
5761
6156
|
);
|
|
5762
6157
|
const [left, right] = operands;
|
|
@@ -5779,7 +6174,7 @@ function comparedWithNone(comparison) {
|
|
|
5779
6174
|
}
|
|
5780
6175
|
var NONE_OPERATORS = /* @__PURE__ */ new Set(["is", "is not", "==", "!="]);
|
|
5781
6176
|
function peelParens(node) {
|
|
5782
|
-
const inner = node.type === "parenthesized_expression" ? node.
|
|
6177
|
+
const inner = node.type === "parenthesized_expression" ? node.namedChild(0) : null;
|
|
5783
6178
|
return inner === null || inner === void 0 ? node : peelParens(inner);
|
|
5784
6179
|
}
|
|
5785
6180
|
function climbParens(node) {
|
|
@@ -5837,7 +6232,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5837
6232
|
const slots = [];
|
|
5838
6233
|
const readsHelpers = facts !== void 0 && sitesByDb.has(facts);
|
|
5839
6234
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
5840
|
-
(0,
|
|
6235
|
+
(0, import_extractor7.walkDescendants)(root, startScope, children, {
|
|
5841
6236
|
at: (node, scope) => {
|
|
5842
6237
|
const syntax = envReadSyntaxAt(node, scope);
|
|
5843
6238
|
if (syntax !== null) {
|
|
@@ -5853,7 +6248,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5853
6248
|
},
|
|
5854
6249
|
into: (node, scope) => {
|
|
5855
6250
|
if (DEFERRED_BODY_TYPES.has(node.type)) {
|
|
5856
|
-
return
|
|
6251
|
+
return import_extractor7.SKIP_CHILDREN;
|
|
5857
6252
|
}
|
|
5858
6253
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
5859
6254
|
}
|
|
@@ -5872,7 +6267,7 @@ function envReadEffects(root, module2, facts) {
|
|
|
5872
6267
|
function configReadEffect(read) {
|
|
5873
6268
|
return {
|
|
5874
6269
|
type: "interaction",
|
|
5875
|
-
binding: (0,
|
|
6270
|
+
binding: (0, import_behavioral_ir4.runtimeConfigBinding)({ recognition: PYTHON_ENV_RECOGNITION }),
|
|
5876
6271
|
callee: `os.environ["${read.name}"]`,
|
|
5877
6272
|
interaction: {
|
|
5878
6273
|
class: "config-read",
|
|
@@ -5896,7 +6291,7 @@ function hasFallback(node, spelling, scope) {
|
|
|
5896
6291
|
}
|
|
5897
6292
|
function envFactsIn(filePath, root, module2) {
|
|
5898
6293
|
const found = { sites: [], objects: [] };
|
|
5899
|
-
(0,
|
|
6294
|
+
(0, import_extractor7.walkDescendants)(root, module2.moduleScope, children, {
|
|
5900
6295
|
at: (node, scope) => {
|
|
5901
6296
|
if (isEnviron(node, scope) && handsOnward(node)) {
|
|
5902
6297
|
found.objects.push(keyOf(filePath, node));
|
|
@@ -6077,172 +6472,41 @@ function argumentsByParameter(db, call, calleeKey2) {
|
|
|
6077
6472
|
}
|
|
6078
6473
|
for (const row of db.lookup("paramNamed", 0, callee)) {
|
|
6079
6474
|
const at = byName.get(String(row[1]));
|
|
6080
|
-
if (at !== void 0) {
|
|
6081
|
-
argumentAt2.set(String(row[2]), at);
|
|
6082
|
-
}
|
|
6083
|
-
}
|
|
6084
|
-
}
|
|
6085
|
-
return argumentAt2;
|
|
6086
|
-
}
|
|
6087
|
-
function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
6088
|
-
const reads = /* @__PURE__ */ new Map();
|
|
6089
|
-
for (const [parameter, argument] of argumentAt2) {
|
|
6090
|
-
const sites = named.get(parameter);
|
|
6091
|
-
(0, import_resolution7.noteLookup)(
|
|
6092
|
-
db,
|
|
6093
|
-
`${NAMED_PARAMETER}${parameter}`,
|
|
6094
|
-
describeSites(sites, siteById)
|
|
6095
|
-
);
|
|
6096
|
-
if (sites === void 0) {
|
|
6097
|
-
continue;
|
|
6098
|
-
}
|
|
6099
|
-
const name = stringLiteralValue(argument) ?? stringValueOf(argument, db);
|
|
6100
|
-
if (name === null) {
|
|
6101
|
-
continue;
|
|
6102
|
-
}
|
|
6103
|
-
for (const id of sites) {
|
|
6104
|
-
const defaulted = siteById.get(id)?.defaulted ?? false;
|
|
6105
|
-
reads.set(name, (reads.get(name) ?? true) && defaulted);
|
|
6106
|
-
}
|
|
6107
|
-
}
|
|
6108
|
-
if (reads.size === 0) {
|
|
6109
|
-
return [];
|
|
6110
|
-
}
|
|
6111
|
-
const defaultedAtCall = isDefaultedAt(call);
|
|
6112
|
-
return [...reads].map(
|
|
6113
|
-
([name, defaulted]) => configReadEffect({ name, defaulted: defaulted || defaultedAtCall })
|
|
6114
|
-
);
|
|
6115
|
-
}
|
|
6116
|
-
|
|
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;
|
|
6475
|
+
if (at !== void 0) {
|
|
6476
|
+
argumentAt2.set(String(row[2]), at);
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6233
6479
|
}
|
|
6234
|
-
|
|
6235
|
-
return positional[declared.statusArgument] ?? null;
|
|
6480
|
+
return argumentAt2;
|
|
6236
6481
|
}
|
|
6237
|
-
function
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
const
|
|
6241
|
-
|
|
6242
|
-
|
|
6482
|
+
function readsThroughHelper(db, call, argumentAt2, siteById, named) {
|
|
6483
|
+
const reads = /* @__PURE__ */ new Map();
|
|
6484
|
+
for (const [parameter, argument] of argumentAt2) {
|
|
6485
|
+
const sites = named.get(parameter);
|
|
6486
|
+
(0, import_resolution7.noteLookup)(
|
|
6487
|
+
db,
|
|
6488
|
+
`${NAMED_PARAMETER}${parameter}`,
|
|
6489
|
+
describeSites(sites, siteById)
|
|
6490
|
+
);
|
|
6491
|
+
if (sites === void 0) {
|
|
6492
|
+
continue;
|
|
6493
|
+
}
|
|
6494
|
+
const name = stringLiteralValue(argument) ?? stringValueOf(argument, db);
|
|
6495
|
+
if (name === null) {
|
|
6496
|
+
continue;
|
|
6497
|
+
}
|
|
6498
|
+
for (const id of sites) {
|
|
6499
|
+
const defaulted = siteById.get(id)?.defaulted ?? false;
|
|
6500
|
+
reads.set(name, (reads.get(name) ?? true) && defaulted);
|
|
6243
6501
|
}
|
|
6244
6502
|
}
|
|
6245
|
-
|
|
6503
|
+
if (reads.size === 0) {
|
|
6504
|
+
return [];
|
|
6505
|
+
}
|
|
6506
|
+
const defaultedAtCall = isDefaultedAt(call);
|
|
6507
|
+
return [...reads].map(
|
|
6508
|
+
([name, defaulted]) => configReadEffect({ name, defaulted: defaulted || defaultedAtCall })
|
|
6509
|
+
);
|
|
6246
6510
|
}
|
|
6247
6511
|
|
|
6248
6512
|
// src/paths/returnedShape.ts
|
|
@@ -6304,7 +6568,7 @@ function shapeOfReturned(node, depth = 0) {
|
|
|
6304
6568
|
return { type: "unknown" };
|
|
6305
6569
|
}
|
|
6306
6570
|
function returnedBodyShape(statement) {
|
|
6307
|
-
const returned = statement.
|
|
6571
|
+
const returned = statement.namedChild(0);
|
|
6308
6572
|
if (returned == null) {
|
|
6309
6573
|
return null;
|
|
6310
6574
|
}
|
|
@@ -6317,8 +6581,8 @@ function returnedBodyShape(statement) {
|
|
|
6317
6581
|
}
|
|
6318
6582
|
|
|
6319
6583
|
// src/streamWrites.ts
|
|
6320
|
-
var
|
|
6321
|
-
var
|
|
6584
|
+
var import_behavioral_ir5 = require("@suss/behavioral-ir");
|
|
6585
|
+
var import_extractor8 = require("@suss/extractor");
|
|
6322
6586
|
|
|
6323
6587
|
// src/stdlibNames.ts
|
|
6324
6588
|
function isStdlibModule(node, scope, module2) {
|
|
@@ -6350,7 +6614,7 @@ var DEFERRED_BODY_TYPES2 = /* @__PURE__ */ new Set(["function_definition", "lamb
|
|
|
6350
6614
|
function streamWriteEffects(root, module2) {
|
|
6351
6615
|
const found = [];
|
|
6352
6616
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
6353
|
-
(0,
|
|
6617
|
+
(0, import_extractor8.walkDescendants)(root, startScope, children, {
|
|
6354
6618
|
at: (node, scope) => {
|
|
6355
6619
|
if (node.type !== "call") {
|
|
6356
6620
|
return;
|
|
@@ -6362,7 +6626,7 @@ function streamWriteEffects(root, module2) {
|
|
|
6362
6626
|
},
|
|
6363
6627
|
into: (node, scope) => {
|
|
6364
6628
|
if (DEFERRED_BODY_TYPES2.has(node.type)) {
|
|
6365
|
-
return
|
|
6629
|
+
return import_extractor8.SKIP_CHILDREN;
|
|
6366
6630
|
}
|
|
6367
6631
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
6368
6632
|
}
|
|
@@ -6398,7 +6662,7 @@ function writeEffect(site) {
|
|
|
6398
6662
|
const { call, callee, target } = site;
|
|
6399
6663
|
return {
|
|
6400
6664
|
type: "interaction",
|
|
6401
|
-
binding: (0,
|
|
6665
|
+
binding: (0, import_behavioral_ir5.ioBinding)({ recognition: PYTHON_STREAM_RECOGNITION, target }),
|
|
6402
6666
|
callee,
|
|
6403
6667
|
groupId: `${call.startPosition.row + 1}:${call.startPosition.column + 1}`,
|
|
6404
6668
|
interaction: {
|
|
@@ -6437,7 +6701,7 @@ function jsonDumped(node, scope) {
|
|
|
6437
6701
|
// src/discovery.ts
|
|
6438
6702
|
function decoratedNodes(root) {
|
|
6439
6703
|
const found = [];
|
|
6440
|
-
(0,
|
|
6704
|
+
(0, import_extractor9.walkDescendants)(root, null, children, {
|
|
6441
6705
|
at: (node) => {
|
|
6442
6706
|
if (node.type !== "decorated_definition") {
|
|
6443
6707
|
return;
|
|
@@ -6588,18 +6852,18 @@ function unitsFor(pattern, pack, decoratorModule, classification, definition, mo
|
|
|
6588
6852
|
);
|
|
6589
6853
|
}
|
|
6590
6854
|
};
|
|
6591
|
-
return (0,
|
|
6855
|
+
return (0, import_behavioral_ir6.dispatchByType)(table, pattern);
|
|
6592
6856
|
}
|
|
6593
6857
|
function readPathArgument(classification, options) {
|
|
6594
6858
|
const first = classification.args[0];
|
|
6595
6859
|
if (first !== void 0) {
|
|
6596
6860
|
const value = evaluatedValue(first.node, options.facts);
|
|
6597
|
-
const path8 = (0,
|
|
6861
|
+
const path8 = (0, import_values20.literalOf)(value) ?? (0, import_values20.pathOf)(value);
|
|
6598
6862
|
if (path8 !== void 0) {
|
|
6599
|
-
return (0,
|
|
6863
|
+
return (0, import_extractor9.writtenReading)(path8, classification.range);
|
|
6600
6864
|
}
|
|
6601
6865
|
}
|
|
6602
|
-
return (0,
|
|
6866
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6603
6867
|
"The path in this route's decorator is not a string literal, so the binding names no path and nothing pairs with it",
|
|
6604
6868
|
classification.range
|
|
6605
6869
|
);
|
|
@@ -6624,16 +6888,16 @@ var PATH_TEMPLATE_READERS = {
|
|
|
6624
6888
|
function readPathTemplate(pattern, path8, range) {
|
|
6625
6889
|
const syntax = pattern.pathParamSyntax;
|
|
6626
6890
|
if (syntax === void 0) {
|
|
6627
|
-
return (0,
|
|
6891
|
+
return (0, import_extractor9.writtenReading)({ path: path8, paramNames: NO_PATH_PARAMS }, range);
|
|
6628
6892
|
}
|
|
6629
6893
|
const reader = PATH_TEMPLATE_READERS[syntax];
|
|
6630
6894
|
if (reader === void 0) {
|
|
6631
|
-
return (0,
|
|
6895
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6632
6896
|
`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
6897
|
range
|
|
6634
6898
|
);
|
|
6635
6899
|
}
|
|
6636
|
-
return (0,
|
|
6900
|
+
return (0, import_extractor9.writtenReading)(reader(path8), range);
|
|
6637
6901
|
}
|
|
6638
6902
|
function classRouteUnits(pattern, pack, classification, classNode, module2, options) {
|
|
6639
6903
|
const pathArgument = readPathArgument(classification, options);
|
|
@@ -6684,7 +6948,7 @@ function classRouteUnits(pattern, pack, classification, classNode, module2, opti
|
|
|
6684
6948
|
module: module2,
|
|
6685
6949
|
filePath: options.filePath,
|
|
6686
6950
|
skipReceiverParam: true,
|
|
6687
|
-
responseShape:
|
|
6951
|
+
responseShape: import_extractor9.absentReading,
|
|
6688
6952
|
statusCode: defaultedStatus(
|
|
6689
6953
|
readReturnedStatus(pattern, maybeMethod, {
|
|
6690
6954
|
module: module2,
|
|
@@ -6711,11 +6975,11 @@ function classRouteUnits(pattern, pack, classification, classNode, module2, opti
|
|
|
6711
6975
|
return units;
|
|
6712
6976
|
}
|
|
6713
6977
|
function readRoutePath(pattern, pathArgument, classification, module2, options) {
|
|
6714
|
-
const composed = (0,
|
|
6978
|
+
const composed = (0, import_extractor9.andThenReading)(
|
|
6715
6979
|
pathArgument,
|
|
6716
6980
|
(literal, range) => composeRoutePath(pattern, classification, module2, options, literal, range)
|
|
6717
6981
|
);
|
|
6718
|
-
return (0,
|
|
6982
|
+
return (0, import_extractor9.andThenReading)(
|
|
6719
6983
|
composed,
|
|
6720
6984
|
(path8, range) => readPathTemplate(pattern, path8, range)
|
|
6721
6985
|
);
|
|
@@ -6741,10 +7005,10 @@ function readRoutePaths(pattern, pathArgument, classification, module2, options)
|
|
|
6741
7005
|
];
|
|
6742
7006
|
}
|
|
6743
7007
|
return resolution.values.map((prefix) => ({
|
|
6744
|
-
routePath: (0,
|
|
6745
|
-
(0,
|
|
7008
|
+
routePath: (0, import_extractor9.andThenReading)(
|
|
7009
|
+
(0, import_extractor9.andThenReading)(
|
|
6746
7010
|
pathArgument,
|
|
6747
|
-
(literal, range) => (0,
|
|
7011
|
+
(literal, range) => (0, import_extractor9.writtenReading)(servedSpelling(pattern, prefix + literal), range)
|
|
6748
7012
|
),
|
|
6749
7013
|
(path8, range) => readPathTemplate(pattern, path8, range)
|
|
6750
7014
|
),
|
|
@@ -6785,9 +7049,9 @@ function composeRoutePath(pattern, classification, module2, options, literal, ra
|
|
|
6785
7049
|
range
|
|
6786
7050
|
);
|
|
6787
7051
|
if (prefix.kind === "absent") {
|
|
6788
|
-
return (0,
|
|
7052
|
+
return (0, import_extractor9.writtenReading)(servedSpelling(pattern, literal), range);
|
|
6789
7053
|
}
|
|
6790
|
-
return (0,
|
|
7054
|
+
return (0, import_extractor9.mapReading)(
|
|
6791
7055
|
prefix,
|
|
6792
7056
|
(value) => servedSpelling(pattern, value + literal)
|
|
6793
7057
|
);
|
|
@@ -6807,32 +7071,36 @@ function readRouterPrefix(pattern, classification, module2, options, range) {
|
|
|
6807
7071
|
options
|
|
6808
7072
|
);
|
|
6809
7073
|
if (resolution === null) {
|
|
6810
|
-
return
|
|
7074
|
+
return import_extractor9.absentReading;
|
|
6811
7075
|
}
|
|
6812
7076
|
if (resolution.kind === "abstain") {
|
|
6813
|
-
return (0,
|
|
7077
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6814
7078
|
`The router this route is declared on ${resolution.reason}, so the binding names no path and nothing pairs with it`,
|
|
6815
7079
|
range
|
|
6816
7080
|
);
|
|
6817
7081
|
}
|
|
6818
7082
|
if (resolution.kind === "composed") {
|
|
6819
|
-
return (0,
|
|
7083
|
+
return (0, import_extractor9.writtenReading)(resolution.value, range);
|
|
6820
7084
|
}
|
|
6821
|
-
return
|
|
7085
|
+
return import_extractor9.absentReading;
|
|
6822
7086
|
}
|
|
6823
|
-
function readStatusCode(pattern, classification) {
|
|
7087
|
+
function readStatusCode(pattern, classification, options) {
|
|
6824
7088
|
if (pattern.statusCodeKeyword === void 0) {
|
|
6825
|
-
return
|
|
7089
|
+
return import_extractor9.absentReading;
|
|
6826
7090
|
}
|
|
6827
7091
|
const arg = classification.keywordArgs[pattern.statusCodeKeyword];
|
|
6828
7092
|
if (arg === void 0) {
|
|
6829
|
-
return
|
|
7093
|
+
return import_extractor9.absentReading;
|
|
6830
7094
|
}
|
|
6831
|
-
|
|
6832
|
-
|
|
7095
|
+
const status = statusNumberOf(arg.node, {
|
|
7096
|
+
...options,
|
|
7097
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
7098
|
+
});
|
|
7099
|
+
if (status !== null) {
|
|
7100
|
+
return (0, import_extractor9.writtenReading)(status, classification.range);
|
|
6833
7101
|
}
|
|
6834
|
-
return (0,
|
|
6835
|
-
"The status this route's decorator states
|
|
7102
|
+
return (0, import_extractor9.unreadableReading)(
|
|
7103
|
+
"The status this route's decorator states does not come to a number here, so the response claims no status",
|
|
6836
7104
|
classification.range
|
|
6837
7105
|
);
|
|
6838
7106
|
}
|
|
@@ -6841,11 +7109,11 @@ function statusFromReturnedValue(node, facts) {
|
|
|
6841
7109
|
return null;
|
|
6842
7110
|
}
|
|
6843
7111
|
const value = evaluatedValue(node, facts);
|
|
6844
|
-
const number = (0,
|
|
7112
|
+
const number = (0, import_values20.constantOf)(value);
|
|
6845
7113
|
if (typeof number === "number") {
|
|
6846
7114
|
return Number.isInteger(number) ? number : null;
|
|
6847
7115
|
}
|
|
6848
|
-
const text2 = (0,
|
|
7116
|
+
const text2 = (0, import_values20.literalOf)(value);
|
|
6849
7117
|
if (text2 === null) {
|
|
6850
7118
|
return null;
|
|
6851
7119
|
}
|
|
@@ -6853,30 +7121,49 @@ function statusFromReturnedValue(node, facts) {
|
|
|
6853
7121
|
return digits === null ? null : Number.parseInt(digits[1], 10);
|
|
6854
7122
|
}
|
|
6855
7123
|
function statusOfReturn(statement, facts) {
|
|
6856
|
-
const returned = statement.
|
|
7124
|
+
const returned = statement.namedChild(0);
|
|
6857
7125
|
if (returned?.type !== "expression_list") {
|
|
6858
7126
|
return { kind: "none" };
|
|
6859
7127
|
}
|
|
6860
|
-
const status = statusFromReturnedValue(
|
|
7128
|
+
const status = statusFromReturnedValue(
|
|
7129
|
+
returned.namedChild(1) ?? void 0,
|
|
7130
|
+
facts
|
|
7131
|
+
);
|
|
6861
7132
|
return status === null ? { kind: "unreadable" } : { kind: "status", value: status };
|
|
6862
7133
|
}
|
|
6863
7134
|
function returnStatusReading(statement, ctx) {
|
|
6864
7135
|
const read = statusOfReturnIn(statement, ctx.pattern, ctx);
|
|
6865
7136
|
const range = rangeOf(statement);
|
|
6866
7137
|
if (read.kind === "status") {
|
|
6867
|
-
return (0,
|
|
7138
|
+
return (0, import_extractor9.writtenReading)(read.value, range);
|
|
6868
7139
|
}
|
|
6869
7140
|
if (read.kind === "unreadable") {
|
|
6870
|
-
return (0,
|
|
7141
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6871
7142
|
"This return gives a status this reading cannot resolve to a number, so this outcome claims none",
|
|
6872
7143
|
range
|
|
6873
7144
|
);
|
|
6874
7145
|
}
|
|
6875
|
-
return ctx.pattern.statusFromReturnedTuple === true ?
|
|
7146
|
+
return ctx.pattern.statusFromReturnedTuple === true ? import_extractor9.absentReading : ctx.declaredStatus.reading;
|
|
6876
7147
|
}
|
|
6877
7148
|
function returnBranch(statement, ctx) {
|
|
6878
7149
|
const range = rangeOf(statement);
|
|
6879
7150
|
const writtenBody = returnedBodyShape(statement);
|
|
7151
|
+
return responseBranchAt(
|
|
7152
|
+
range,
|
|
7153
|
+
returnStatusReading(statement, ctx),
|
|
7154
|
+
writtenBody === null ? ctx.responseShape.reading : (0, import_extractor9.writtenReading)(writtenBody, range),
|
|
7155
|
+
ctx
|
|
7156
|
+
);
|
|
7157
|
+
}
|
|
7158
|
+
function fallthroughBranch(definitionNode, ctx) {
|
|
7159
|
+
return responseBranchAt(
|
|
7160
|
+
rangeOf(definitionNode),
|
|
7161
|
+
ctx.pattern.statusFromReturnedTuple === true ? import_extractor9.absentReading : ctx.declaredStatus.reading,
|
|
7162
|
+
ctx.responseShape.reading,
|
|
7163
|
+
ctx
|
|
7164
|
+
);
|
|
7165
|
+
}
|
|
7166
|
+
function responseBranchAt(range, status, body, ctx) {
|
|
6880
7167
|
return {
|
|
6881
7168
|
terminal: {
|
|
6882
7169
|
kind: "response",
|
|
@@ -6893,12 +7180,10 @@ function returnBranch(statement, ctx) {
|
|
|
6893
7180
|
location: range
|
|
6894
7181
|
},
|
|
6895
7182
|
statusCodeReading: {
|
|
6896
|
-
reading:
|
|
7183
|
+
reading: status,
|
|
6897
7184
|
...ctx.declaredStatus.libraryDefault !== void 0 ? { libraryDefault: ctx.declaredStatus.libraryDefault } : {}
|
|
6898
7185
|
},
|
|
6899
|
-
bodyShapeReading: {
|
|
6900
|
-
reading: writtenBody === null ? ctx.responseShape.reading : (0, import_extractor7.writtenReading)(writtenBody, range)
|
|
6901
|
-
},
|
|
7186
|
+
bodyShapeReading: { reading: body },
|
|
6902
7187
|
location: range
|
|
6903
7188
|
};
|
|
6904
7189
|
}
|
|
@@ -6912,18 +7197,19 @@ function terminalBranchOf(found, ctx) {
|
|
|
6912
7197
|
// A route has no continuation, so none is ever collected for it.
|
|
6913
7198
|
continuation: (variant) => returnBranch(variant.statement, ctx)
|
|
6914
7199
|
};
|
|
6915
|
-
return (0,
|
|
7200
|
+
return (0, import_behavioral_ir6.dispatchByType)(table, found);
|
|
6916
7201
|
}
|
|
6917
7202
|
function branchesPerTerminal(options) {
|
|
6918
7203
|
const body = field(options.definitionNode, "body");
|
|
6919
7204
|
const raised = raisedResponses(body, {
|
|
6920
7205
|
calls: options.responseStatusCalls,
|
|
6921
7206
|
module: options.ctx.module,
|
|
6922
|
-
facts: options.ctx.facts
|
|
7207
|
+
facts: options.ctx.facts,
|
|
7208
|
+
constants: options.ctx.pattern.statusCodeConstants ?? {}
|
|
6923
7209
|
});
|
|
6924
7210
|
const terminals = bodyTerminals(body, raised);
|
|
6925
7211
|
const soleReturnWritesBody = terminals.length === 1 && terminals[0]?.type === "return" && returnedBodyShape(terminals[0].statement) !== null;
|
|
6926
|
-
if (terminals.length
|
|
7212
|
+
if (terminals.length === 0) {
|
|
6927
7213
|
return null;
|
|
6928
7214
|
}
|
|
6929
7215
|
const branches = enumerateBodyBranches({
|
|
@@ -6932,6 +7218,7 @@ function branchesPerTerminal(options) {
|
|
|
6932
7218
|
raised,
|
|
6933
7219
|
effects: options.effects,
|
|
6934
7220
|
branchOf: (found) => terminalBranchOf(found, options.ctx),
|
|
7221
|
+
fallthrough: fallthroughBranch(options.definitionNode, options.ctx),
|
|
6935
7222
|
facts: options.ctx.facts
|
|
6936
7223
|
});
|
|
6937
7224
|
return branches.length > 1 || soleReturnWritesBody ? branches : null;
|
|
@@ -6940,7 +7227,8 @@ function statusOfReturnIn(statement, pattern, options) {
|
|
|
6940
7227
|
const constructed = returnedResponseStatus(statement, {
|
|
6941
7228
|
calls: pattern.responseConstructors ?? [],
|
|
6942
7229
|
module: options.module,
|
|
6943
|
-
facts: options.facts
|
|
7230
|
+
facts: options.facts,
|
|
7231
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
6944
7232
|
});
|
|
6945
7233
|
if (constructed !== null) {
|
|
6946
7234
|
return constructed.type === "literal" ? { kind: "status", value: constructed.value } : { kind: "unreadable" };
|
|
@@ -6952,7 +7240,7 @@ function statusOfReturnIn(statement, pattern, options) {
|
|
|
6952
7240
|
}
|
|
6953
7241
|
function readReturnedStatus(pattern, definitionNode, options) {
|
|
6954
7242
|
if (pattern.statusFromReturnedTuple !== true && (pattern.responseConstructors ?? []).length === 0) {
|
|
6955
|
-
return
|
|
7243
|
+
return import_extractor9.absentReading;
|
|
6956
7244
|
}
|
|
6957
7245
|
const range = rangeOf(definitionNode);
|
|
6958
7246
|
const statuses = /* @__PURE__ */ new Set();
|
|
@@ -6969,23 +7257,23 @@ function readReturnedStatus(pattern, definitionNode, options) {
|
|
|
6969
7257
|
}
|
|
6970
7258
|
}
|
|
6971
7259
|
if (unreadable > 0) {
|
|
6972
|
-
return (0,
|
|
7260
|
+
return (0, import_extractor9.unreadableReading)(
|
|
6973
7261
|
"This route returns a status this reading cannot resolve to a number, so no status is claimed for it",
|
|
6974
7262
|
range
|
|
6975
7263
|
);
|
|
6976
7264
|
}
|
|
6977
7265
|
if (statuses.size === 0) {
|
|
6978
|
-
return
|
|
7266
|
+
return import_extractor9.absentReading;
|
|
6979
7267
|
}
|
|
6980
7268
|
const candidates = [...statuses];
|
|
6981
7269
|
if (statuses.size > 1 || plainReturns > 0) {
|
|
6982
|
-
return (0,
|
|
7270
|
+
return (0, import_extractor9.ambiguousReading)(
|
|
6983
7271
|
candidates,
|
|
6984
7272
|
"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
7273
|
range
|
|
6986
7274
|
);
|
|
6987
7275
|
}
|
|
6988
|
-
return (0,
|
|
7276
|
+
return (0, import_extractor9.writtenReading)(candidates[0], range);
|
|
6989
7277
|
}
|
|
6990
7278
|
function declaredOrReturnedStatus(declared, returned) {
|
|
6991
7279
|
return declared.kind === "absent" ? returned : declared;
|
|
@@ -6998,19 +7286,19 @@ function defaultedStatus(reading, pattern) {
|
|
|
6998
7286
|
}
|
|
6999
7287
|
function readResponseModel(pattern, classification, module2, ctx) {
|
|
7000
7288
|
if (pattern.responseModelKeyword === void 0) {
|
|
7001
|
-
return
|
|
7289
|
+
return import_extractor9.absentReading;
|
|
7002
7290
|
}
|
|
7003
7291
|
const arg = classification.keywordArgs[pattern.responseModelKeyword];
|
|
7004
7292
|
if (arg === void 0) {
|
|
7005
|
-
return
|
|
7293
|
+
return import_extractor9.absentReading;
|
|
7006
7294
|
}
|
|
7007
7295
|
if (arg.kind === "identifier") {
|
|
7008
|
-
return (0,
|
|
7296
|
+
return (0, import_extractor9.writtenReading)(
|
|
7009
7297
|
shapeFromName(arg.name, module2.moduleScope, ctx),
|
|
7010
7298
|
classification.range
|
|
7011
7299
|
);
|
|
7012
7300
|
}
|
|
7013
|
-
return (0,
|
|
7301
|
+
return (0, import_extractor9.unreadableReading)(
|
|
7014
7302
|
"The response model this route's decorator states is not a name, so the response claims no body shape",
|
|
7015
7303
|
classification.range
|
|
7016
7304
|
);
|
|
@@ -7018,9 +7306,9 @@ function readResponseModel(pattern, classification, module2, ctx) {
|
|
|
7018
7306
|
function readReturnAnnotation(definitionNode, scope, ctx) {
|
|
7019
7307
|
const returnTypeNode = field(definitionNode, "return_type");
|
|
7020
7308
|
if (returnTypeNode === null) {
|
|
7021
|
-
return
|
|
7309
|
+
return import_extractor9.absentReading;
|
|
7022
7310
|
}
|
|
7023
|
-
return (0,
|
|
7311
|
+
return (0, import_extractor9.writtenReading)(
|
|
7024
7312
|
annotationToShape(returnTypeNode, scope, ctx),
|
|
7025
7313
|
rangeOf(returnTypeNode)
|
|
7026
7314
|
);
|
|
@@ -7034,6 +7322,25 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7034
7322
|
module2.scopeFor,
|
|
7035
7323
|
options.importedDefinition ?? null
|
|
7036
7324
|
);
|
|
7325
|
+
const wrappers = wrappersAround(
|
|
7326
|
+
pattern,
|
|
7327
|
+
pack,
|
|
7328
|
+
classification,
|
|
7329
|
+
functionNode,
|
|
7330
|
+
module2,
|
|
7331
|
+
options
|
|
7332
|
+
);
|
|
7333
|
+
const dependencyParameters = options.wrappers?.dependencyParameters(
|
|
7334
|
+
wrappers
|
|
7335
|
+
) ?? { names: /* @__PURE__ */ new Set(), declaresSource: false };
|
|
7336
|
+
const declaredStatuses = declaredStatusesOf(
|
|
7337
|
+
pattern,
|
|
7338
|
+
pack,
|
|
7339
|
+
classification,
|
|
7340
|
+
functionNode,
|
|
7341
|
+
module2,
|
|
7342
|
+
options
|
|
7343
|
+
);
|
|
7037
7344
|
return readRoutePaths(
|
|
7038
7345
|
pattern,
|
|
7039
7346
|
readPathArgument(classification, options),
|
|
@@ -7046,6 +7353,8 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7046
7353
|
pack,
|
|
7047
7354
|
name: functionName,
|
|
7048
7355
|
exportPath: [functionName],
|
|
7356
|
+
dependencyParameters,
|
|
7357
|
+
declaredStatuses,
|
|
7049
7358
|
method: verb,
|
|
7050
7359
|
routePath: entry.routePath,
|
|
7051
7360
|
...entry.mount !== void 0 ? { mount: entry.mount } : {},
|
|
@@ -7062,7 +7371,10 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7062
7371
|
responseShape: readResponseModel(pattern, classification, module2, ctx),
|
|
7063
7372
|
statusCode: defaultedStatus(
|
|
7064
7373
|
declaredOrReturnedStatus(
|
|
7065
|
-
readStatusCode(pattern, classification
|
|
7374
|
+
readStatusCode(pattern, classification, {
|
|
7375
|
+
module: module2,
|
|
7376
|
+
facts: options.facts
|
|
7377
|
+
}),
|
|
7066
7378
|
readReturnedStatus(pattern, functionNode, {
|
|
7067
7379
|
module: module2,
|
|
7068
7380
|
facts: options.facts
|
|
@@ -7073,14 +7385,7 @@ function functionRouteUnits(pattern, pack, verb, classification, functionNode, m
|
|
|
7073
7385
|
definitionsCtx: ctx,
|
|
7074
7386
|
storage: options.storage,
|
|
7075
7387
|
importedDefinition: options.importedDefinition,
|
|
7076
|
-
wrappers
|
|
7077
|
-
pattern,
|
|
7078
|
-
pack,
|
|
7079
|
-
classification,
|
|
7080
|
-
functionNode,
|
|
7081
|
-
module2,
|
|
7082
|
-
options
|
|
7083
|
-
)
|
|
7388
|
+
wrappers
|
|
7084
7389
|
},
|
|
7085
7390
|
options
|
|
7086
7391
|
)
|
|
@@ -7099,11 +7404,43 @@ function wrappersAround(pattern, pack, classification, definitionNode, module2,
|
|
|
7099
7404
|
definitionNode
|
|
7100
7405
|
});
|
|
7101
7406
|
}
|
|
7407
|
+
function declaredStatusesOf(pattern, pack, classification, definitionNode, module2, options) {
|
|
7408
|
+
const keyword = pattern.responsesKeyword;
|
|
7409
|
+
if (keyword === void 0) {
|
|
7410
|
+
return [];
|
|
7411
|
+
}
|
|
7412
|
+
const above = options.wrappers?.callsAbove({
|
|
7413
|
+
pack,
|
|
7414
|
+
pattern,
|
|
7415
|
+
file: options.absoluteFile ?? options.filePath,
|
|
7416
|
+
module: module2,
|
|
7417
|
+
classification,
|
|
7418
|
+
definitionNode
|
|
7419
|
+
}) ?? [];
|
|
7420
|
+
const dictionaries = [
|
|
7421
|
+
classification.keywordArgs[keyword]?.node,
|
|
7422
|
+
...above.map(
|
|
7423
|
+
(call) => readCallArguments(field(call, "arguments")).keywordArgs[keyword]?.node
|
|
7424
|
+
)
|
|
7425
|
+
].filter((node) => node?.type === "dictionary");
|
|
7426
|
+
const statuses = dictionaries.flatMap(
|
|
7427
|
+
(dictionary) => children(dictionary).flatMap((pair) => {
|
|
7428
|
+
const key = pair?.type === "pair" ? field(pair, "key") : null;
|
|
7429
|
+
const status = key === null ? null : statusNumberOf(key, {
|
|
7430
|
+
module: moduleOf(key),
|
|
7431
|
+
facts: options.facts,
|
|
7432
|
+
constants: pattern.statusCodeConstants ?? {}
|
|
7433
|
+
});
|
|
7434
|
+
return status === null ? [] : [status];
|
|
7435
|
+
})
|
|
7436
|
+
);
|
|
7437
|
+
return [...new Set(statuses)].sort((a, b) => a - b);
|
|
7438
|
+
}
|
|
7102
7439
|
function readResponseShape(declared, readAnnotation) {
|
|
7103
7440
|
if (declared.kind === "written") {
|
|
7104
7441
|
return { reading: declared, passedOver: [] };
|
|
7105
7442
|
}
|
|
7106
|
-
return (0,
|
|
7443
|
+
return (0, import_extractor9.firstWrittenReading)([declared, readAnnotation()]);
|
|
7107
7444
|
}
|
|
7108
7445
|
function routeUnitOrAbstention(unitOptions, options) {
|
|
7109
7446
|
try {
|
|
@@ -7131,7 +7468,7 @@ function unbuiltRouteUnit(unitOptions, error) {
|
|
|
7131
7468
|
exportName: unitOptions.exportPath[0] ?? unitOptions.name,
|
|
7132
7469
|
exportPath: unitOptions.exportPath
|
|
7133
7470
|
},
|
|
7134
|
-
boundaryBinding: (0,
|
|
7471
|
+
boundaryBinding: (0, import_behavioral_ir6.restBinding)({
|
|
7135
7472
|
transport: unitOptions.pack.protocol,
|
|
7136
7473
|
method: nullIfEmpty(unitOptions.method),
|
|
7137
7474
|
path: null,
|
|
@@ -7143,7 +7480,7 @@ function unbuiltRouteUnit(unitOptions, error) {
|
|
|
7143
7480
|
dependencyCalls: [],
|
|
7144
7481
|
declaredContract: null,
|
|
7145
7482
|
readings: [
|
|
7146
|
-
(0,
|
|
7483
|
+
(0, import_extractor9.unreadableReading)(
|
|
7147
7484
|
`This route could not be read into a unit (${message}), so the binding names no path and nothing pairs with it`,
|
|
7148
7485
|
range
|
|
7149
7486
|
)
|
|
@@ -7169,7 +7506,7 @@ function buildRouteUnit(options) {
|
|
|
7169
7506
|
definitionsCtx,
|
|
7170
7507
|
storage: storageLookup
|
|
7171
7508
|
} = options;
|
|
7172
|
-
const template = (0,
|
|
7509
|
+
const template = (0, import_extractor9.valueToReadFurtherFrom)(routePath);
|
|
7173
7510
|
const ctx = definitionsCtx ?? createAnnotationContext(
|
|
7174
7511
|
module2.scopeFor,
|
|
7175
7512
|
options.importedDefinition ?? null
|
|
@@ -7182,6 +7519,8 @@ function buildRouteUnit(options) {
|
|
|
7182
7519
|
pathParamNames: template?.paramNames ?? null,
|
|
7183
7520
|
requestBodyFromAnnotatedClass,
|
|
7184
7521
|
injectedCallees,
|
|
7522
|
+
injectedTypes: new Set(pattern.injectedParameterTypes ?? []),
|
|
7523
|
+
module: module2,
|
|
7185
7524
|
sources: pattern.parameterSources ?? {},
|
|
7186
7525
|
aliasKeyword: pattern.parameterAliasKeyword
|
|
7187
7526
|
},
|
|
@@ -7238,6 +7577,22 @@ function buildRouteUnit(options) {
|
|
|
7238
7577
|
};
|
|
7239
7578
|
branches.push(withBodyEffects(bare, extra));
|
|
7240
7579
|
}
|
|
7580
|
+
if (branches.length > 0) {
|
|
7581
|
+
branches.push(
|
|
7582
|
+
...validationFailureBranches(
|
|
7583
|
+
pattern,
|
|
7584
|
+
readsTheRequest(
|
|
7585
|
+
parameters,
|
|
7586
|
+
template,
|
|
7587
|
+
options.dependencyParameters ?? {
|
|
7588
|
+
names: /* @__PURE__ */ new Set(),
|
|
7589
|
+
declaresSource: false
|
|
7590
|
+
}
|
|
7591
|
+
),
|
|
7592
|
+
rangeOf(definitionNode)
|
|
7593
|
+
)
|
|
7594
|
+
);
|
|
7595
|
+
}
|
|
7241
7596
|
const bodyNode = field(definitionNode, "body");
|
|
7242
7597
|
return {
|
|
7243
7598
|
identity: {
|
|
@@ -7250,7 +7605,7 @@ function buildRouteUnit(options) {
|
|
|
7250
7605
|
exportName: exportPath[0] ?? name,
|
|
7251
7606
|
exportPath
|
|
7252
7607
|
},
|
|
7253
|
-
boundaryBinding: (0,
|
|
7608
|
+
boundaryBinding: (0, import_behavioral_ir6.restBinding)({
|
|
7254
7609
|
transport: pack.protocol,
|
|
7255
7610
|
method,
|
|
7256
7611
|
path: template?.path ?? null,
|
|
@@ -7269,15 +7624,57 @@ function buildRouteUnit(options) {
|
|
|
7269
7624
|
...collectedDefinitions(ctx) !== null ? { definitions: collectedDefinitions(ctx) } : {},
|
|
7270
7625
|
...options.mount !== void 0 ? { mount: options.mount } : {},
|
|
7271
7626
|
...options.wrappers !== void 0 && options.wrappers.length > 0 ? { wrappers: options.wrappers } : {},
|
|
7272
|
-
...pack.requestSpelling === void 0 ? {} : { requestSpelling: pack.requestSpelling }
|
|
7627
|
+
...pack.requestSpelling === void 0 ? {} : { requestSpelling: pack.requestSpelling },
|
|
7628
|
+
...options.declaredStatuses !== void 0 && options.declaredStatuses.length > 0 ? { declaredStatuses: options.declaredStatuses } : {}
|
|
7273
7629
|
};
|
|
7274
7630
|
}
|
|
7631
|
+
function readsTheRequest(parameters, template, dependencies) {
|
|
7632
|
+
if (dependencies.declaresSource || parameters.some((parameter) => parameter.role !== null)) {
|
|
7633
|
+
return true;
|
|
7634
|
+
}
|
|
7635
|
+
return [...template?.paramNames ?? []].some(
|
|
7636
|
+
(name) => dependencies.names.has(name)
|
|
7637
|
+
);
|
|
7638
|
+
}
|
|
7639
|
+
function validationFailureBranches(pattern, readsRequest, range) {
|
|
7640
|
+
const status = pattern.validationFailureStatus;
|
|
7641
|
+
if (status === void 0 || !readsRequest) {
|
|
7642
|
+
return [];
|
|
7643
|
+
}
|
|
7644
|
+
return [
|
|
7645
|
+
{
|
|
7646
|
+
conditions: [
|
|
7647
|
+
{
|
|
7648
|
+
sourceText: "request input fails validation",
|
|
7649
|
+
structured: null,
|
|
7650
|
+
polarity: "positive",
|
|
7651
|
+
source: "earlyThrow"
|
|
7652
|
+
}
|
|
7653
|
+
],
|
|
7654
|
+
terminal: {
|
|
7655
|
+
kind: "response",
|
|
7656
|
+
statusCode: { type: "literal", value: status },
|
|
7657
|
+
body: null,
|
|
7658
|
+
exceptionType: null,
|
|
7659
|
+
message: null,
|
|
7660
|
+
component: null,
|
|
7661
|
+
renderTree: null,
|
|
7662
|
+
delegateTarget: null,
|
|
7663
|
+
emitEvent: null,
|
|
7664
|
+
location: range
|
|
7665
|
+
},
|
|
7666
|
+
effects: [],
|
|
7667
|
+
location: range,
|
|
7668
|
+
isDefault: false
|
|
7669
|
+
}
|
|
7670
|
+
];
|
|
7671
|
+
}
|
|
7275
7672
|
function unreadRoleReadings(parameters, range) {
|
|
7276
7673
|
if (!parameters.some((parameter) => parameter.role === null)) {
|
|
7277
7674
|
return [];
|
|
7278
7675
|
}
|
|
7279
7676
|
return [
|
|
7280
|
-
(0,
|
|
7677
|
+
(0, import_extractor9.unreadableReading)(
|
|
7281
7678
|
"Nothing read this route's path, so its parameters name no role and a path parameter here does not read as one",
|
|
7282
7679
|
range
|
|
7283
7680
|
)
|
|
@@ -7338,10 +7735,7 @@ function readParameters(definitionNode, reading, skipReceiverParam) {
|
|
|
7338
7735
|
}
|
|
7339
7736
|
const out = [];
|
|
7340
7737
|
let position = 0;
|
|
7341
|
-
for (const param of parametersNode
|
|
7342
|
-
if (param === null) {
|
|
7343
|
-
continue;
|
|
7344
|
-
}
|
|
7738
|
+
for (const param of children(parametersNode)) {
|
|
7345
7739
|
if (skipReceiverParam && position === 0 && isReceiverParam(param)) {
|
|
7346
7740
|
position += 1;
|
|
7347
7741
|
continue;
|
|
@@ -7365,7 +7759,7 @@ function readParameter(param, reading, position) {
|
|
|
7365
7759
|
const { name, typeNode } = info;
|
|
7366
7760
|
const shape = typeNode !== null ? annotationToShape(typeNode, reading.scope, reading.ctx) : null;
|
|
7367
7761
|
const typeText = typeNode !== null ? typeNode.text : null;
|
|
7368
|
-
if (isInjectedParameter(param, reading)) {
|
|
7762
|
+
if (isInjectedParameter(param, reading) || isInjectedType(typeNode, reading)) {
|
|
7369
7763
|
return { name, position, role: null, typeText };
|
|
7370
7764
|
}
|
|
7371
7765
|
const declared = declaringCall(
|
|
@@ -7445,6 +7839,14 @@ function calleeName2(call) {
|
|
|
7445
7839
|
function isInjectedParameter(param, reading) {
|
|
7446
7840
|
return declaringCall(param, reading.injectedCallees, reading) !== null;
|
|
7447
7841
|
}
|
|
7842
|
+
function isInjectedType(typeNode, reading) {
|
|
7843
|
+
if (typeNode === null || reading.injectedTypes.size === 0) {
|
|
7844
|
+
return false;
|
|
7845
|
+
}
|
|
7846
|
+
const written = typeNode.type === "type" ? typeNode.namedChild(0) ?? null : typeNode;
|
|
7847
|
+
const origin = written === null ? null : originOf(written, reading.module);
|
|
7848
|
+
return origin !== null && reading.injectedTypes.has(`${origin.module}.${origin.name}`);
|
|
7849
|
+
}
|
|
7448
7850
|
function declaringCall(param, callees, reading) {
|
|
7449
7851
|
if (callees.size === 0) {
|
|
7450
7852
|
return null;
|
|
@@ -7668,15 +8070,15 @@ function parseWith(language, source) {
|
|
|
7668
8070
|
// src/project.ts
|
|
7669
8071
|
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
7670
8072
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
7671
|
-
var
|
|
8073
|
+
var import_behavioral_ir10 = require("@suss/behavioral-ir");
|
|
7672
8074
|
var import_datalog2 = require("@suss/datalog");
|
|
7673
|
-
var
|
|
8075
|
+
var import_extractor18 = require("@suss/extractor");
|
|
7674
8076
|
var import_resolution18 = require("@suss/resolution");
|
|
7675
8077
|
|
|
7676
8078
|
// src/diagnostics.ts
|
|
7677
|
-
var
|
|
8079
|
+
var import_extractor10 = require("@suss/extractor");
|
|
7678
8080
|
function buildPythonExtractionReport(args) {
|
|
7679
|
-
return (0,
|
|
8081
|
+
return (0, import_extractor10.buildUngatedExtractionReport)({
|
|
7680
8082
|
packs: args.packs.map((pack) => ({
|
|
7681
8083
|
name: pack.name,
|
|
7682
8084
|
version: pack.version ?? null,
|
|
@@ -7689,14 +8091,14 @@ function buildPythonExtractionReport(args) {
|
|
|
7689
8091
|
}
|
|
7690
8092
|
|
|
7691
8093
|
// src/exits.ts
|
|
7692
|
-
var
|
|
8094
|
+
var import_extractor11 = require("@suss/extractor");
|
|
7693
8095
|
var import_resolution9 = require("@suss/resolution");
|
|
7694
|
-
var
|
|
8096
|
+
var import_values21 = require("@suss/values");
|
|
7695
8097
|
var DEFERRED_BODY_TYPES3 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
7696
8098
|
function exitSites(root, module2) {
|
|
7697
8099
|
const found = [];
|
|
7698
8100
|
const startScope = module2.scopeFor.get(root.id) ?? module2.moduleScope;
|
|
7699
|
-
(0,
|
|
8101
|
+
(0, import_extractor11.walkDescendants)(root, startScope, children, {
|
|
7700
8102
|
at: (node, scope) => {
|
|
7701
8103
|
const site = exitSiteAt(node, scope);
|
|
7702
8104
|
if (site !== null) {
|
|
@@ -7705,7 +8107,7 @@ function exitSites(root, module2) {
|
|
|
7705
8107
|
},
|
|
7706
8108
|
into: (node, scope) => {
|
|
7707
8109
|
if (DEFERRED_BODY_TYPES3.has(node.type)) {
|
|
7708
|
-
return
|
|
8110
|
+
return import_extractor11.SKIP_CHILDREN;
|
|
7709
8111
|
}
|
|
7710
8112
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
7711
8113
|
}
|
|
@@ -7713,7 +8115,7 @@ function exitSites(root, module2) {
|
|
|
7713
8115
|
return found;
|
|
7714
8116
|
}
|
|
7715
8117
|
function exitSiteAt(statement, scope) {
|
|
7716
|
-
const expression = statement.
|
|
8118
|
+
const expression = statement.namedChild(0) ?? null;
|
|
7717
8119
|
if (expression === null) {
|
|
7718
8120
|
return null;
|
|
7719
8121
|
}
|
|
@@ -7760,7 +8162,7 @@ function exitCodeOf(code, facts) {
|
|
|
7760
8162
|
if (stringLiteralValue(code) !== null) {
|
|
7761
8163
|
return { type: "literal", value: 1 };
|
|
7762
8164
|
}
|
|
7763
|
-
const value = (0,
|
|
8165
|
+
const value = (0, import_values21.constantOf)(evaluatedValue(code, facts));
|
|
7764
8166
|
return typeof value === "number" ? { type: "literal", value } : { type: "dynamic", sourceText: code.text };
|
|
7765
8167
|
}
|
|
7766
8168
|
function exitingBranches(definition, module2, effects, facts) {
|
|
@@ -7794,7 +8196,7 @@ function markExitCodeFunctions(summaries, exits, facts, workspaceRoot) {
|
|
|
7794
8196
|
(site) => site.code === null ? [] : [nodeId(file, site.code)]
|
|
7795
8197
|
)
|
|
7796
8198
|
);
|
|
7797
|
-
(0,
|
|
8199
|
+
(0, import_extractor11.markReturnsAsExitCode)(
|
|
7798
8200
|
summaries,
|
|
7799
8201
|
(0, import_resolution9.exitCodeFunctions)(facts, sinks),
|
|
7800
8202
|
workspaceRoot
|
|
@@ -7879,25 +8281,25 @@ function definedNodeOf(binding) {
|
|
|
7879
8281
|
}
|
|
7880
8282
|
|
|
7881
8283
|
// src/moduleSurface.ts
|
|
7882
|
-
var
|
|
7883
|
-
var
|
|
8284
|
+
var import_behavioral_ir8 = require("@suss/behavioral-ir");
|
|
8285
|
+
var import_extractor14 = require("@suss/extractor");
|
|
7884
8286
|
var import_resolution13 = require("@suss/resolution");
|
|
7885
8287
|
|
|
7886
8288
|
// src/reach/closure.ts
|
|
7887
|
-
var
|
|
8289
|
+
var import_behavioral_ir7 = require("@suss/behavioral-ir");
|
|
7888
8290
|
var import_datalog = require("@suss/datalog");
|
|
7889
|
-
var
|
|
8291
|
+
var import_extractor13 = require("@suss/extractor");
|
|
7890
8292
|
var import_resolution12 = require("@suss/resolution");
|
|
7891
8293
|
|
|
7892
8294
|
// src/flags.ts
|
|
7893
|
-
var
|
|
8295
|
+
var import_extractor12 = require("@suss/extractor");
|
|
7894
8296
|
var PARSE_METHODS = /* @__PURE__ */ new Set(["parse_args", "parse_known_args"]);
|
|
7895
8297
|
var DEFERRED_BODY_TYPES4 = /* @__PURE__ */ new Set(["function_definition", "lambda"]);
|
|
7896
8298
|
function argparseFlagReads(definition, module2, parameterNames2) {
|
|
7897
8299
|
const parsers = /* @__PURE__ */ new Map();
|
|
7898
8300
|
const handedTo = /* @__PURE__ */ new Map();
|
|
7899
8301
|
const startScope = module2.scopeFor.get(definition.id) ?? module2.moduleScope;
|
|
7900
|
-
(0,
|
|
8302
|
+
(0, import_extractor12.walkDescendants)(definition, startScope, children, {
|
|
7901
8303
|
at: (node, scope) => {
|
|
7902
8304
|
noteParser(node, scope, parsers);
|
|
7903
8305
|
noteArgument(node, parsers);
|
|
@@ -7905,7 +8307,7 @@ function argparseFlagReads(definition, module2, parameterNames2) {
|
|
|
7905
8307
|
},
|
|
7906
8308
|
into: (node, scope) => {
|
|
7907
8309
|
if (DEFERRED_BODY_TYPES4.has(node.type)) {
|
|
7908
|
-
return
|
|
8310
|
+
return import_extractor12.SKIP_CHILDREN;
|
|
7909
8311
|
}
|
|
7910
8312
|
return module2.scopeFor.get(node.id) ?? scope;
|
|
7911
8313
|
}
|
|
@@ -7999,8 +8401,40 @@ function resolveCallee2(call, site, ctx, read) {
|
|
|
7999
8401
|
return spelling;
|
|
8000
8402
|
}
|
|
8001
8403
|
const outcome = read?.outcomes.get(spelling.key) ?? (0, import_resolution11.calleeOutcomeOf)(ctx.facts, spelling.key);
|
|
8404
|
+
if (selfCallInMixin(call, outcome, site, ctx)) {
|
|
8405
|
+
return { kind: "stopped", reason: "selfCallInMixin" };
|
|
8406
|
+
}
|
|
8002
8407
|
return asCallee(outcome, site.owner, ctx);
|
|
8003
8408
|
}
|
|
8409
|
+
function selfCallInMixin(call, outcome, site, ctx) {
|
|
8410
|
+
if (outcome.kind !== "callerSupplied" || !outcome.key.startsWith(`${site.owner}#`)) {
|
|
8411
|
+
return false;
|
|
8412
|
+
}
|
|
8413
|
+
const callee = readThrough(field(call, "function"));
|
|
8414
|
+
const receiver = callee?.type === "attribute" ? field(callee, "object") : null;
|
|
8415
|
+
const name = callee === null ? null : field(callee, "attribute")?.text;
|
|
8416
|
+
if (receiver?.type !== "identifier" || name === void 0 || name === null) {
|
|
8417
|
+
return false;
|
|
8418
|
+
}
|
|
8419
|
+
if (outcome.key !== `${site.owner}#${receiver.text}`) {
|
|
8420
|
+
return false;
|
|
8421
|
+
}
|
|
8422
|
+
return ctx.facts.lookup("instanceOf", 0, outcome.key).some((row) => {
|
|
8423
|
+
const classKey = String(row[1]);
|
|
8424
|
+
return ctx.facts.has("plainClass", [classKey]) && !instancesHaveAttribute(ctx.facts, classKey, name);
|
|
8425
|
+
});
|
|
8426
|
+
}
|
|
8427
|
+
var FALLBACK_ATTRIBUTE = "__getattr__";
|
|
8428
|
+
function instancesHaveAttribute(facts, classKey, name) {
|
|
8429
|
+
return facts.lookup("holdsProperty", 0, classKey).some((member) => {
|
|
8430
|
+
if (String(member[1]) === FALLBACK_ATTRIBUTE) {
|
|
8431
|
+
return true;
|
|
8432
|
+
}
|
|
8433
|
+
return facts.lookup("storesProperty", 0, String(member[2])).some(
|
|
8434
|
+
(store) => String(store[1]) === name && store[3] === import_resolution11.RECEIVER_STORE_NAME
|
|
8435
|
+
);
|
|
8436
|
+
});
|
|
8437
|
+
}
|
|
8004
8438
|
function namedOutcomes(keys, ctx) {
|
|
8005
8439
|
return (0, import_resolution11.calleeOutcomes)(ctx.facts, [...new Set(keys)]);
|
|
8006
8440
|
}
|
|
@@ -8324,17 +8758,17 @@ function reachedFunctions(seeds, options) {
|
|
|
8324
8758
|
continue;
|
|
8325
8759
|
}
|
|
8326
8760
|
const build = () => {
|
|
8327
|
-
const summary2 = (0,
|
|
8761
|
+
const summary2 = (0, import_extractor13.assembleSummary)(libraryUnit(target, options), {
|
|
8328
8762
|
gapHandling: options.gapHandling
|
|
8329
8763
|
});
|
|
8330
8764
|
if (options.gapHandling !== "silent") {
|
|
8331
8765
|
summary2.gaps.push(
|
|
8332
|
-
...(stopsByKey.get(key) ?? []).map(
|
|
8766
|
+
...(stopsByKey.get(key) ?? []).map(import_behavioral_ir7.unfollowedCallGap)
|
|
8333
8767
|
);
|
|
8334
8768
|
}
|
|
8335
|
-
(0,
|
|
8336
|
-
(0,
|
|
8337
|
-
(0,
|
|
8769
|
+
(0, import_behavioral_ir7.placeCalls)(summary2, targetsByKey.get(key));
|
|
8770
|
+
(0, import_behavioral_ir7.placeArgTargets)(summary2, argTargetsByKey.get(key));
|
|
8771
|
+
(0, import_behavioral_ir7.placeCalleeParameters)(summary2, parameterCallsByKey.get(key));
|
|
8338
8772
|
return summary2;
|
|
8339
8773
|
};
|
|
8340
8774
|
const summary = ledger === void 0 ? build() : ledger.charging(chargeOf(charges, key), () => {
|
|
@@ -8350,7 +8784,7 @@ function reachedFunctions(seeds, options) {
|
|
|
8350
8784
|
summaries.push(summary);
|
|
8351
8785
|
}
|
|
8352
8786
|
if (options.gapHandling !== "silent") {
|
|
8353
|
-
(0,
|
|
8787
|
+
(0, import_behavioral_ir7.recordParameterGaps)(parameterCallsByKey, summariesByKey, passedPositions);
|
|
8354
8788
|
}
|
|
8355
8789
|
return {
|
|
8356
8790
|
summaries,
|
|
@@ -8550,15 +8984,15 @@ function passedNameKeys(file, call) {
|
|
|
8550
8984
|
if (args === null) {
|
|
8551
8985
|
return [];
|
|
8552
8986
|
}
|
|
8553
|
-
return args.
|
|
8987
|
+
return children(args).flatMap((arg) => {
|
|
8554
8988
|
const key = passedNameKeyOf(file, arg);
|
|
8555
8989
|
return key === null ? [] : [key];
|
|
8556
8990
|
});
|
|
8557
8991
|
}
|
|
8558
8992
|
function scanBody(source, ctx, recognized, read, implied) {
|
|
8559
8993
|
const followed = [];
|
|
8560
|
-
const stops =
|
|
8561
|
-
const placements = new
|
|
8994
|
+
const stops = new import_behavioral_ir7.StopList();
|
|
8995
|
+
const placements = new import_behavioral_ir7.TargetPlacements();
|
|
8562
8996
|
const parameterCalls = [];
|
|
8563
8997
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
8564
8998
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8574,7 +9008,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8574
9008
|
if (args === null) {
|
|
8575
9009
|
return;
|
|
8576
9010
|
}
|
|
8577
|
-
args.
|
|
9011
|
+
children(args).forEach((arg, position) => {
|
|
8578
9012
|
const nameKey2 = passedNameKeyOf(file, arg);
|
|
8579
9013
|
if (nameKey2 === null) {
|
|
8580
9014
|
return;
|
|
@@ -8607,10 +9041,12 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8607
9041
|
outcome.kind === "followed" ? keyOf2(outcome.target) : null
|
|
8608
9042
|
);
|
|
8609
9043
|
if (outcome.kind === "stopped") {
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
9044
|
+
if (!recognized.has(call.id) && (0, import_behavioral_ir7.worthRecording)(outcome.reason)) {
|
|
9045
|
+
stops.add({
|
|
9046
|
+
callee,
|
|
9047
|
+
reason: outcome.reason,
|
|
9048
|
+
...resultUsedAsValue(call) ? { usedAsValue: true } : {}
|
|
9049
|
+
});
|
|
8614
9050
|
}
|
|
8615
9051
|
if (outcome.reason === "callerSupplied" && !parameterCallsSeen.has(callee)) {
|
|
8616
9052
|
const parameterIndex = ownParameters.indexOf(callee);
|
|
@@ -8643,7 +9079,7 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8643
9079
|
}
|
|
8644
9080
|
return {
|
|
8645
9081
|
followed,
|
|
8646
|
-
stops,
|
|
9082
|
+
stops: stops.stops,
|
|
8647
9083
|
targets: placements.targets,
|
|
8648
9084
|
argTargets: placements.argTargets,
|
|
8649
9085
|
parameterCalls,
|
|
@@ -8652,13 +9088,13 @@ function scanBody(source, ctx, recognized, read, implied) {
|
|
|
8652
9088
|
}
|
|
8653
9089
|
function callsWritten(file, body, outer, owner, limit) {
|
|
8654
9090
|
const found = [];
|
|
8655
|
-
(0,
|
|
9091
|
+
(0, import_extractor13.walkDescendants)(body, outer, children, {
|
|
8656
9092
|
at: (child, scope) => {
|
|
8657
9093
|
if (child.type === "call") {
|
|
8658
9094
|
found.push({ call: child, site: { file, scope, owner } });
|
|
8659
9095
|
}
|
|
8660
9096
|
},
|
|
8661
|
-
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope :
|
|
9097
|
+
into: (child, scope) => limit.descendsInto(child) ? file.module.scopeFor.get(child.id) ?? scope : import_extractor13.SKIP_CHILDREN
|
|
8662
9098
|
});
|
|
8663
9099
|
return found;
|
|
8664
9100
|
}
|
|
@@ -8678,14 +9114,14 @@ function identifiersUnder(node, found = []) {
|
|
|
8678
9114
|
found.push(node.text);
|
|
8679
9115
|
return found;
|
|
8680
9116
|
}
|
|
8681
|
-
for (const child of node
|
|
9117
|
+
for (const child of children(node)) {
|
|
8682
9118
|
if (child !== null && child.type !== "attribute" && child.type !== "subscript") {
|
|
8683
9119
|
identifiersUnder(child, found);
|
|
8684
9120
|
}
|
|
8685
9121
|
}
|
|
8686
9122
|
return found;
|
|
8687
9123
|
}
|
|
8688
|
-
function libraryUnit(target, options, binding = (0,
|
|
9124
|
+
function libraryUnit(target, options, binding = (0, import_behavioral_ir7.functionCallBinding)({
|
|
8689
9125
|
transport: "in-process",
|
|
8690
9126
|
recognition: "reachable"
|
|
8691
9127
|
})) {
|
|
@@ -8779,10 +9215,7 @@ function positionalParameters(node, isMethod2) {
|
|
|
8779
9215
|
}
|
|
8780
9216
|
const out = [];
|
|
8781
9217
|
let position = 0;
|
|
8782
|
-
for (const param of parameters
|
|
8783
|
-
if (param === null) {
|
|
8784
|
-
continue;
|
|
8785
|
-
}
|
|
9218
|
+
for (const param of children(parameters)) {
|
|
8786
9219
|
const name = parameterName2(param);
|
|
8787
9220
|
if (name === null) {
|
|
8788
9221
|
continue;
|
|
@@ -8802,10 +9235,7 @@ function callParameterNames(node, isMethod2) {
|
|
|
8802
9235
|
return [];
|
|
8803
9236
|
}
|
|
8804
9237
|
const names = [];
|
|
8805
|
-
for (const param of parameters
|
|
8806
|
-
if (param === null) {
|
|
8807
|
-
continue;
|
|
8808
|
-
}
|
|
9238
|
+
for (const param of children(parameters)) {
|
|
8809
9239
|
const name = parameterName2(param);
|
|
8810
9240
|
if (name === null) {
|
|
8811
9241
|
continue;
|
|
@@ -8830,10 +9260,10 @@ function parameterName2(param) {
|
|
|
8830
9260
|
|
|
8831
9261
|
// src/moduleSurface.ts
|
|
8832
9262
|
function settlePythonModules(modules) {
|
|
8833
|
-
return (0,
|
|
9263
|
+
return (0, import_extractor14.settleModules)(modules, ["__init__.py"]);
|
|
8834
9264
|
}
|
|
8835
9265
|
function moduleExportUnits(file, options) {
|
|
8836
|
-
const module2 = (0,
|
|
9266
|
+
const module2 = (0, import_extractor14.moduleOfFile)(options.modules, file.file);
|
|
8837
9267
|
if (module2 === void 0) {
|
|
8838
9268
|
return [];
|
|
8839
9269
|
}
|
|
@@ -8855,8 +9285,8 @@ function moduleExportUnits(file, options) {
|
|
|
8855
9285
|
exportPath: [...one.exportPath]
|
|
8856
9286
|
},
|
|
8857
9287
|
options,
|
|
8858
|
-
(0,
|
|
8859
|
-
recognition:
|
|
9288
|
+
(0, import_behavioral_ir8.moduleExportBinding)({
|
|
9289
|
+
recognition: import_extractor14.MODULE_SURFACE_RECOGNITION,
|
|
8860
9290
|
module: module2.name,
|
|
8861
9291
|
exportName
|
|
8862
9292
|
})
|
|
@@ -8902,7 +9332,7 @@ function exportsOf(file, node, exportName) {
|
|
|
8902
9332
|
if (node.type !== "class_definition" || body === null) {
|
|
8903
9333
|
return [];
|
|
8904
9334
|
}
|
|
8905
|
-
return body.
|
|
9335
|
+
return children(body).flatMap((child) => {
|
|
8906
9336
|
if (child === null) {
|
|
8907
9337
|
return [];
|
|
8908
9338
|
}
|
|
@@ -9025,6 +9455,11 @@ function watchRouterIndex(index, db, positions, fileOfModule) {
|
|
|
9025
9455
|
found
|
|
9026
9456
|
);
|
|
9027
9457
|
return found;
|
|
9458
|
+
},
|
|
9459
|
+
// The wrapper index notes what it reads through the mounts, in terms
|
|
9460
|
+
// it can look up again.
|
|
9461
|
+
mountsAbove(pattern, constructionKey) {
|
|
9462
|
+
return index.mountsAbove(pattern, constructionKey);
|
|
9028
9463
|
}
|
|
9029
9464
|
};
|
|
9030
9465
|
}
|
|
@@ -9129,9 +9564,33 @@ function buildRouterIndex(files, packs, resolverOptions) {
|
|
|
9129
9564
|
};
|
|
9130
9565
|
}
|
|
9131
9566
|
return NOT_ROUTER;
|
|
9567
|
+
},
|
|
9568
|
+
mountsAbove(pattern, constructionKey) {
|
|
9569
|
+
const index = byPattern.get(pattern);
|
|
9570
|
+
return index === void 0 ? null : hopsAbove(index, constructionKey);
|
|
9132
9571
|
}
|
|
9133
9572
|
};
|
|
9134
9573
|
}
|
|
9574
|
+
function hopsAbove(index, key) {
|
|
9575
|
+
const hops = [];
|
|
9576
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9577
|
+
let current = key;
|
|
9578
|
+
while (current !== null) {
|
|
9579
|
+
const construction = index.byValueKey.get(current);
|
|
9580
|
+
if (construction === void 0 || seen.has(current)) {
|
|
9581
|
+
return null;
|
|
9582
|
+
}
|
|
9583
|
+
seen.add(current);
|
|
9584
|
+
const states = index.mounts.get(construction) ?? [];
|
|
9585
|
+
const only = states.length === 1 ? states[0] : void 0;
|
|
9586
|
+
if (only?.kind !== "mounted" || only.written === void 0) {
|
|
9587
|
+
return null;
|
|
9588
|
+
}
|
|
9589
|
+
hops.push({ ...only.written, parentKey: only.parentValueKey });
|
|
9590
|
+
current = only.parentValueKey;
|
|
9591
|
+
}
|
|
9592
|
+
return hops;
|
|
9593
|
+
}
|
|
9135
9594
|
function composedPrefixOf(index, construction, routerPath) {
|
|
9136
9595
|
const ownPrefix = composedOwnPrefix(construction.prefix, index.composition);
|
|
9137
9596
|
if (ownPrefix.kind === "abstain") {
|
|
@@ -9414,8 +9873,8 @@ function constructionStatement(stmt, module2, importModule) {
|
|
|
9414
9873
|
if (stmt.type !== "expression_statement") {
|
|
9415
9874
|
return null;
|
|
9416
9875
|
}
|
|
9417
|
-
const assignment2 = stmt.
|
|
9418
|
-
(child) => child
|
|
9876
|
+
const assignment2 = children(stmt).find(
|
|
9877
|
+
(child) => child.type === "assignment"
|
|
9419
9878
|
);
|
|
9420
9879
|
if (assignment2 === void 0) {
|
|
9421
9880
|
return null;
|
|
@@ -9489,7 +9948,7 @@ function collectReturnedConstructions(bound, importModule, composition, index) {
|
|
|
9489
9948
|
if (inner.type !== "return_statement") {
|
|
9490
9949
|
continue;
|
|
9491
9950
|
}
|
|
9492
|
-
const returned = inner.
|
|
9951
|
+
const returned = inner.namedChild(0);
|
|
9493
9952
|
if (returned?.type !== "call") {
|
|
9494
9953
|
continue;
|
|
9495
9954
|
}
|
|
@@ -9669,7 +10128,7 @@ function sequenceElementNames(node) {
|
|
|
9669
10128
|
return null;
|
|
9670
10129
|
}
|
|
9671
10130
|
const names = [];
|
|
9672
|
-
for (const child of node
|
|
10131
|
+
for (const child of children(node)) {
|
|
9673
10132
|
if (child?.type !== "identifier") {
|
|
9674
10133
|
return null;
|
|
9675
10134
|
}
|
|
@@ -9882,8 +10341,9 @@ function recordMountStatement(stmt, position, scan) {
|
|
|
9882
10341
|
scan.index.facts
|
|
9883
10342
|
);
|
|
9884
10343
|
const mounted = args[0] ?? (scan.composition.routerKeyword === void 0 ? void 0 : keywordArgs[scan.composition.routerKeyword]);
|
|
10344
|
+
const recorded = state.kind === "mounted" ? { ...state, written: { call: mountCall.call, file: scan.bound.file } } : state;
|
|
9885
10345
|
for (const target of mountedConstructions(mounted, position, scan)) {
|
|
9886
|
-
recordMount(scan.index, target,
|
|
10346
|
+
recordMount(scan.index, target, recorded);
|
|
9887
10347
|
}
|
|
9888
10348
|
}
|
|
9889
10349
|
function mountStateOf(includerConstructorName, includer, keywordArgs, objectPrefix, composition, site, facts) {
|
|
@@ -10324,10 +10784,10 @@ function poetryPackages(pyproject) {
|
|
|
10324
10784
|
|
|
10325
10785
|
// src/testCases.ts
|
|
10326
10786
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
10327
|
-
var
|
|
10328
|
-
var
|
|
10787
|
+
var import_behavioral_ir9 = require("@suss/behavioral-ir");
|
|
10788
|
+
var import_extractor15 = require("@suss/extractor");
|
|
10329
10789
|
var import_resolution16 = require("@suss/resolution");
|
|
10330
|
-
var
|
|
10790
|
+
var import_values27 = require("@suss/values");
|
|
10331
10791
|
function pythonTestIndex(packs, context) {
|
|
10332
10792
|
const patterns = packs.flatMap((pack) => pack.tests ?? []);
|
|
10333
10793
|
return patterns.length === 0 ? null : new PythonTestIndex(patterns, context);
|
|
@@ -10344,7 +10804,7 @@ var PythonTestIndex = class {
|
|
|
10344
10804
|
implied = /* @__PURE__ */ new Map();
|
|
10345
10805
|
/** The tests in one file, when the file is collected and listed. */
|
|
10346
10806
|
unitsIn(file, options) {
|
|
10347
|
-
return this.testsIn(file).filter((test) => (0,
|
|
10807
|
+
return this.testsIn(file).filter((test) => (0, import_extractor15.isListedTestFile)(file.file, test.pattern.files)).map((test) => this.testUnit(file, test, options));
|
|
10348
10808
|
}
|
|
10349
10809
|
/** What pytest calls before this function runs, when it is a test or a fixture. */
|
|
10350
10810
|
impliedCalls(source) {
|
|
@@ -10394,7 +10854,7 @@ var PythonTestIndex = class {
|
|
|
10394
10854
|
)
|
|
10395
10855
|
).flatMap(
|
|
10396
10856
|
(marker) => positionalArguments(marker).flatMap((arg) => {
|
|
10397
|
-
const name = (0,
|
|
10857
|
+
const name = (0, import_values27.literalOf)(evaluatedValue(arg, this.context.facts));
|
|
10398
10858
|
return name === null ? [] : [name];
|
|
10399
10859
|
})
|
|
10400
10860
|
);
|
|
@@ -10418,7 +10878,7 @@ var PythonTestIndex = class {
|
|
|
10418
10878
|
...raw,
|
|
10419
10879
|
identity: {
|
|
10420
10880
|
...raw.identity,
|
|
10421
|
-
name: (0,
|
|
10881
|
+
name: (0, import_behavioral_ir9.testUnitName)(test.titles),
|
|
10422
10882
|
nameKind: "label",
|
|
10423
10883
|
kind: "test",
|
|
10424
10884
|
exportName: null,
|
|
@@ -10430,7 +10890,7 @@ var PythonTestIndex = class {
|
|
|
10430
10890
|
}
|
|
10431
10891
|
patternFor(file) {
|
|
10432
10892
|
return this.patterns.find(
|
|
10433
|
-
(pattern) => (0,
|
|
10893
|
+
(pattern) => (0, import_extractor15.matchesTestFileName)(file.file, pattern.filePatterns)
|
|
10434
10894
|
) ?? null;
|
|
10435
10895
|
}
|
|
10436
10896
|
testsIn(file) {
|
|
@@ -10808,11 +11268,11 @@ var PythonTestIndex = class {
|
|
|
10808
11268
|
return null;
|
|
10809
11269
|
}
|
|
10810
11270
|
const written = oneLine(call.text);
|
|
10811
|
-
const target = (0,
|
|
11271
|
+
const target = (0, import_values27.literalOf)(evaluatedValue(first, this.context.facts));
|
|
10812
11272
|
if (target !== null) {
|
|
10813
11273
|
return { ...this.dottedTarget(target), written };
|
|
10814
11274
|
}
|
|
10815
|
-
const member = second === void 0 ? null : (0,
|
|
11275
|
+
const member = second === void 0 ? null : (0, import_values27.literalOf)(evaluatedValue(second, this.context.facts));
|
|
10816
11276
|
if (member === null) {
|
|
10817
11277
|
return null;
|
|
10818
11278
|
}
|
|
@@ -10950,8 +11410,8 @@ function fixtureDeclaration(definition, file, pattern, facts) {
|
|
|
10950
11410
|
const renamed = keywordArgument(decorator, pattern.fixtureNameKeyword);
|
|
10951
11411
|
const autouse = keywordArgument(decorator, pattern.autouseKeyword);
|
|
10952
11412
|
return {
|
|
10953
|
-
name: (renamed === null ? null : (0,
|
|
10954
|
-
autouse: autouse !== null && (0,
|
|
11413
|
+
name: (renamed === null ? null : (0, import_values27.literalOf)(evaluatedValue(renamed, facts))) ?? defName,
|
|
11414
|
+
autouse: autouse !== null && (0, import_values27.constantOf)(evaluatedValue(autouse, facts)) === true
|
|
10955
11415
|
};
|
|
10956
11416
|
}
|
|
10957
11417
|
function keywordArgument(call, name) {
|
|
@@ -10983,18 +11443,20 @@ function oneLine(text2) {
|
|
|
10983
11443
|
}
|
|
10984
11444
|
|
|
10985
11445
|
// src/version.ts
|
|
10986
|
-
var
|
|
11446
|
+
var import_extractor16 = require("@suss/extractor");
|
|
10987
11447
|
var ADAPTER_VERSION = "0.1.0";
|
|
10988
|
-
var adapterStamp = (0,
|
|
11448
|
+
var adapterStamp = (0, import_extractor16.createAdapterStamp)({
|
|
10989
11449
|
moduleUrl: importMetaUrl,
|
|
10990
11450
|
version: ADAPTER_VERSION
|
|
10991
11451
|
});
|
|
10992
11452
|
|
|
10993
11453
|
// src/wrappers.ts
|
|
10994
|
-
var
|
|
11454
|
+
var import_extractor17 = require("@suss/extractor");
|
|
10995
11455
|
var import_resolution17 = require("@suss/resolution");
|
|
10996
11456
|
var EVERY_ROUTE = "wrapEvery ";
|
|
10997
11457
|
var OWN_ROUTES = "wrapOwn ";
|
|
11458
|
+
var MOUNTED = "wrapMounted ";
|
|
11459
|
+
var MOUNTED_SEPARATOR = "\0";
|
|
10998
11460
|
function describeRegistered(found) {
|
|
10999
11461
|
return (found ?? []).map(
|
|
11000
11462
|
({ reference }) => `${reference.file}:${reference.name}:${reference.onThrow === true}`
|
|
@@ -11032,6 +11494,10 @@ var PythonWrapperIndex = class {
|
|
|
11032
11494
|
/** By construction key: what a router or a blueprint registered. */
|
|
11033
11495
|
ownRoutes = /* @__PURE__ */ new Map();
|
|
11034
11496
|
unitsByKey = /* @__PURE__ */ new Map();
|
|
11497
|
+
/** By pack name: the app constructions its routes run under. */
|
|
11498
|
+
appCalls = /* @__PURE__ */ new Map();
|
|
11499
|
+
/** By wrapper reference: the parameters a dependency function declares, and its file. */
|
|
11500
|
+
dependencyParameterTable = /* @__PURE__ */ new Map();
|
|
11035
11501
|
unitsByFile = /* @__PURE__ */ new Map();
|
|
11036
11502
|
/** Told about every registration, so a cache can repeat the ones a file's discovery made. */
|
|
11037
11503
|
onRegistered = null;
|
|
@@ -11050,6 +11516,12 @@ var PythonWrapperIndex = class {
|
|
|
11050
11516
|
this.ownRoutes.get(id.slice(OWN_ROUTES.length))
|
|
11051
11517
|
);
|
|
11052
11518
|
}
|
|
11519
|
+
if (id.startsWith(MOUNTED)) {
|
|
11520
|
+
const [packName, position, key] = id.slice(MOUNTED.length).split(MOUNTED_SEPARATOR);
|
|
11521
|
+
const pack = this.options.packs.find((one) => one.name === packName);
|
|
11522
|
+
const pattern = pack?.discovery[Number(position)];
|
|
11523
|
+
return pack === void 0 || pattern === void 0 || key === void 0 ? describeRegistered([]) : describeRegistered(this.registeredAbove(pack, pattern, key));
|
|
11524
|
+
}
|
|
11053
11525
|
return null;
|
|
11054
11526
|
}
|
|
11055
11527
|
noted(kind, key, found) {
|
|
@@ -11091,14 +11563,46 @@ var PythonWrapperIndex = class {
|
|
|
11091
11563
|
inFile.push(unit);
|
|
11092
11564
|
this.unitsByFile.set(target.file.file, inFile);
|
|
11093
11565
|
}
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
...isThrowForm(declared.form) ? { onThrow: true } : {}
|
|
11099
|
-
},
|
|
11100
|
-
form: declared.form
|
|
11566
|
+
const reference = {
|
|
11567
|
+
file: target.file.displayPath,
|
|
11568
|
+
name: target.name,
|
|
11569
|
+
...isThrowForm(declared.form) ? { onThrow: true } : {}
|
|
11101
11570
|
};
|
|
11571
|
+
if (declared.form.type === "dependency") {
|
|
11572
|
+
this.dependencyParameterTable.set(referenceKey(reference), {
|
|
11573
|
+
file: target.file.file,
|
|
11574
|
+
names: parameterNamesOf(target.node),
|
|
11575
|
+
declaresSource: declaresSourcedParameter(
|
|
11576
|
+
target.node,
|
|
11577
|
+
Object.keys(declared.pattern.parameterSources ?? {})
|
|
11578
|
+
)
|
|
11579
|
+
});
|
|
11580
|
+
}
|
|
11581
|
+
return { reference, form: declared.form };
|
|
11582
|
+
}
|
|
11583
|
+
/**
|
|
11584
|
+
* The parameters the dependencies among these wrappers declare, and
|
|
11585
|
+
* whether one is declared through a parameter source such as `Query()`.
|
|
11586
|
+
* The library fills those from the request and validates them, the same
|
|
11587
|
+
* as parameters the route declares.
|
|
11588
|
+
*/
|
|
11589
|
+
dependencyParameters(references) {
|
|
11590
|
+
const names = /* @__PURE__ */ new Set();
|
|
11591
|
+
let declaresSource = false;
|
|
11592
|
+
for (const reference of references) {
|
|
11593
|
+
const found = this.dependencyParameterTable.get(referenceKey(reference));
|
|
11594
|
+
if (found === void 0) {
|
|
11595
|
+
continue;
|
|
11596
|
+
}
|
|
11597
|
+
if (this.options.facts !== void 0) {
|
|
11598
|
+
(0, import_resolution17.noteKeyRead)(this.options.facts, found.file);
|
|
11599
|
+
}
|
|
11600
|
+
for (const name of found.names) {
|
|
11601
|
+
names.add(name);
|
|
11602
|
+
}
|
|
11603
|
+
declaresSource ||= found.declaresSource;
|
|
11604
|
+
}
|
|
11605
|
+
return { names, declaresSource };
|
|
11102
11606
|
}
|
|
11103
11607
|
wrappersFor(query) {
|
|
11104
11608
|
const file = this.filesByPath.get(query.file);
|
|
@@ -11110,13 +11614,15 @@ var PythonWrapperIndex = class {
|
|
|
11110
11614
|
if (file === void 0 || forms.length === 0) {
|
|
11111
11615
|
return [];
|
|
11112
11616
|
}
|
|
11617
|
+
const own = this.ownRoutesOf(query);
|
|
11113
11618
|
const found = [
|
|
11114
11619
|
...this.noted(
|
|
11115
11620
|
EVERY_ROUTE,
|
|
11116
11621
|
query.pack.name,
|
|
11117
11622
|
this.everyRoute.get(query.pack.name)
|
|
11118
11623
|
),
|
|
11119
|
-
...this.
|
|
11624
|
+
...own === null ? [] : this.mountedAbove(query, own.key),
|
|
11625
|
+
...own?.registered ?? []
|
|
11120
11626
|
];
|
|
11121
11627
|
for (const declared of forms) {
|
|
11122
11628
|
if (declared.form.type !== "dependency") {
|
|
@@ -11147,11 +11653,65 @@ var PythonWrapperIndex = class {
|
|
|
11147
11653
|
}
|
|
11148
11654
|
return ordered;
|
|
11149
11655
|
}
|
|
11656
|
+
/**
|
|
11657
|
+
* What the mounts above the route's router register on the way down:
|
|
11658
|
+
* the dependencies an `include_router` call lists, and those of each
|
|
11659
|
+
* router it is mounted onto, outermost first, the order they run in.
|
|
11660
|
+
*/
|
|
11661
|
+
mountedAbove(query, key) {
|
|
11662
|
+
const position = query.pack.discovery.indexOf(query.pattern);
|
|
11663
|
+
return [
|
|
11664
|
+
...this.noted(
|
|
11665
|
+
MOUNTED,
|
|
11666
|
+
[query.pack.name, position, key].join(MOUNTED_SEPARATOR),
|
|
11667
|
+
this.registeredAbove(query.pack, query.pattern, key)
|
|
11668
|
+
)
|
|
11669
|
+
];
|
|
11670
|
+
}
|
|
11671
|
+
registeredAbove(pack, pattern, key) {
|
|
11672
|
+
const hops = this.options.routers?.mountsAbove(pattern, key) ?? null;
|
|
11673
|
+
if (hops === null) {
|
|
11674
|
+
return [];
|
|
11675
|
+
}
|
|
11676
|
+
const forms = (pattern.wrappers ?? []).flatMap(
|
|
11677
|
+
(form) => form.type === "dependency" ? [{ pack, pattern, form }] : []
|
|
11678
|
+
);
|
|
11679
|
+
const found = [];
|
|
11680
|
+
for (const hop of [...hops].reverse()) {
|
|
11681
|
+
found.push(
|
|
11682
|
+
...hop.parentKey === null ? [] : this.ownRoutes.get(hop.parentKey) ?? []
|
|
11683
|
+
);
|
|
11684
|
+
const { keywordArgs } = readCallArguments(field(hop.call, "arguments"));
|
|
11685
|
+
for (const declared of forms) {
|
|
11686
|
+
const listed = keywordArgs[declared.form.keyword];
|
|
11687
|
+
const names = listed === void 0 ? [] : dependencyNamesIn(listed.node, declared.form);
|
|
11688
|
+
for (const name of names) {
|
|
11689
|
+
const target = this.functionCalled(hop.file, name);
|
|
11690
|
+
if (target !== null) {
|
|
11691
|
+
found.push(this.registered(target, declared));
|
|
11692
|
+
}
|
|
11693
|
+
}
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
return found;
|
|
11697
|
+
}
|
|
11150
11698
|
ownRoutesOf(query) {
|
|
11699
|
+
const match = this.ownRouterOf(query);
|
|
11700
|
+
return match === null ? null : {
|
|
11701
|
+
key: match.key,
|
|
11702
|
+
registered: this.noted(
|
|
11703
|
+
OWN_ROUTES,
|
|
11704
|
+
match.key,
|
|
11705
|
+
this.ownRoutes.get(match.key)
|
|
11706
|
+
)
|
|
11707
|
+
};
|
|
11708
|
+
}
|
|
11709
|
+
/** The construction call of the router a route is decorated on, when a registrar reads it. */
|
|
11710
|
+
ownRouterOf(query) {
|
|
11151
11711
|
const site = this.objectSiteOf(query);
|
|
11152
11712
|
const bound = site === null ? void 0 : this.filesByPath.get(site.file);
|
|
11153
11713
|
if (site === null || bound === void 0) {
|
|
11154
|
-
return
|
|
11714
|
+
return null;
|
|
11155
11715
|
}
|
|
11156
11716
|
if (this.options.facts !== void 0) {
|
|
11157
11717
|
(0, import_resolution17.noteKeyRead)(this.options.facts, site.file);
|
|
@@ -11165,12 +11725,46 @@ var PythonWrapperIndex = class {
|
|
|
11165
11725
|
{ pack: query.pack, pattern: query.pattern, form }
|
|
11166
11726
|
);
|
|
11167
11727
|
if (match !== null && match.registrar.covers === "ownRoutes") {
|
|
11168
|
-
return
|
|
11169
|
-
...this.noted(OWN_ROUTES, match.key, this.ownRoutes.get(match.key))
|
|
11170
|
-
];
|
|
11728
|
+
return match;
|
|
11171
11729
|
}
|
|
11172
11730
|
}
|
|
11173
|
-
return
|
|
11731
|
+
return null;
|
|
11732
|
+
}
|
|
11733
|
+
/** Records the app a pack's routes run under, for the keywords written on its construction. */
|
|
11734
|
+
recordApp(pack, call, file) {
|
|
11735
|
+
const calls = this.appCalls.get(pack) ?? [];
|
|
11736
|
+
if (!calls.some((one) => one.call === call)) {
|
|
11737
|
+
calls.push({ call, file });
|
|
11738
|
+
}
|
|
11739
|
+
this.appCalls.set(pack, calls);
|
|
11740
|
+
}
|
|
11741
|
+
/**
|
|
11742
|
+
* Every call that registers something for a route on the way to it:
|
|
11743
|
+
* the app's construction, the mount calls and the routers they mount
|
|
11744
|
+
* onto, and the route's own router. A caller reads a keyword off each.
|
|
11745
|
+
*/
|
|
11746
|
+
callsAbove(query) {
|
|
11747
|
+
const own = this.ownRouterOf(query);
|
|
11748
|
+
const hops = own === null ? [] : this.options.routers?.mountsAbove(query.pattern, own.key) ?? [];
|
|
11749
|
+
const parents = hops.flatMap((hop) => {
|
|
11750
|
+
const node = hop.parentKey === null ? null : nodeOfResolutionKey(hop.parentKey, this.options.facts);
|
|
11751
|
+
return node === null ? [] : [node];
|
|
11752
|
+
});
|
|
11753
|
+
const files = [
|
|
11754
|
+
...(this.appCalls.get(query.pack.name) ?? []).map((one) => one.file),
|
|
11755
|
+
...hops.map((hop) => hop.file)
|
|
11756
|
+
];
|
|
11757
|
+
if (this.options.facts !== void 0) {
|
|
11758
|
+
for (const file of files) {
|
|
11759
|
+
(0, import_resolution17.noteKeyRead)(this.options.facts, file);
|
|
11760
|
+
}
|
|
11761
|
+
}
|
|
11762
|
+
return [
|
|
11763
|
+
...(this.appCalls.get(query.pack.name) ?? []).map((one) => one.call),
|
|
11764
|
+
...hops.map((hop) => hop.call),
|
|
11765
|
+
...parents,
|
|
11766
|
+
...own === null ? [] : [own.call]
|
|
11767
|
+
];
|
|
11174
11768
|
}
|
|
11175
11769
|
/**
|
|
11176
11770
|
* Where the decorator's object was built: the route's own file, the file
|
|
@@ -11215,6 +11809,23 @@ var PythonWrapperIndex = class {
|
|
|
11215
11809
|
return this.unitsByFile.get(file) ?? [];
|
|
11216
11810
|
}
|
|
11217
11811
|
};
|
|
11812
|
+
function referenceKey(reference) {
|
|
11813
|
+
return `${reference.file}::${reference.name}`;
|
|
11814
|
+
}
|
|
11815
|
+
function parameterNamesOf(definition) {
|
|
11816
|
+
return children(field(definition, "parameters")).flatMap((parameter) => {
|
|
11817
|
+
const named = parameterNameAndType(parameter);
|
|
11818
|
+
return named === null ? [] : [named.name];
|
|
11819
|
+
});
|
|
11820
|
+
}
|
|
11821
|
+
function declaresSourcedParameter(definition, sources) {
|
|
11822
|
+
return children(field(definition, "parameters")).some((parameter) => {
|
|
11823
|
+
const value = field(parameter, "value");
|
|
11824
|
+
const callee = value?.type === "call" ? field(value, "function") : null;
|
|
11825
|
+
const name = callee?.type === "attribute" ? field(callee, "attribute")?.text : callee?.text;
|
|
11826
|
+
return name !== void 0 && sources.includes(name);
|
|
11827
|
+
});
|
|
11828
|
+
}
|
|
11218
11829
|
function isThrowForm(form) {
|
|
11219
11830
|
return form.type === "decoratedWrapper" && form.throwParam !== void 0;
|
|
11220
11831
|
}
|
|
@@ -11261,8 +11872,8 @@ function registerFrom(file, declared, index) {
|
|
|
11261
11872
|
}
|
|
11262
11873
|
function registerConstructorDependencies(file, declared, form, index) {
|
|
11263
11874
|
const scope = file.module.moduleScope;
|
|
11264
|
-
for (const stmt of file.root
|
|
11265
|
-
const assignment2 = stmt?.type === "expression_statement" ? stmt.
|
|
11875
|
+
for (const stmt of children(file.root)) {
|
|
11876
|
+
const assignment2 = stmt?.type === "expression_statement" ? children(stmt).find((child) => child?.type === "assignment") : void 0;
|
|
11266
11877
|
const left = assignment2 === void 0 || assignment2 === null ? null : field(assignment2, "left");
|
|
11267
11878
|
if (left?.type !== "identifier") {
|
|
11268
11879
|
continue;
|
|
@@ -11277,6 +11888,9 @@ function registerConstructorDependencies(file, declared, form, index) {
|
|
|
11277
11888
|
if (match === null) {
|
|
11278
11889
|
continue;
|
|
11279
11890
|
}
|
|
11891
|
+
if (match.registrar.covers === "everyRoute") {
|
|
11892
|
+
index.recordApp(declared.pack.name, match.call, file.file);
|
|
11893
|
+
}
|
|
11280
11894
|
const { keywordArgs } = readCallArguments(field(match.call, "arguments"));
|
|
11281
11895
|
const listed = keywordArgs[form.keyword];
|
|
11282
11896
|
if (listed === void 0) {
|
|
@@ -11294,7 +11908,7 @@ function coverageOf(match, pack) {
|
|
|
11294
11908
|
return match.registrar.covers === "everyRoute" ? { kind: "everyRoute", pack: pack.name } : { kind: "ownRoutes", key: match.key };
|
|
11295
11909
|
}
|
|
11296
11910
|
function registerDecorated(file, declared, form, index) {
|
|
11297
|
-
(0,
|
|
11911
|
+
(0, import_extractor17.walkDescendants)(file.root, file.module.moduleScope, children, {
|
|
11298
11912
|
at: (node, scope) => {
|
|
11299
11913
|
if (node.type !== "decorated_definition") {
|
|
11300
11914
|
return;
|
|
@@ -11330,7 +11944,7 @@ function registerDecorated(file, declared, form, index) {
|
|
|
11330
11944
|
});
|
|
11331
11945
|
}
|
|
11332
11946
|
function dependencyNamesIn(node, form) {
|
|
11333
|
-
const calls = node.type === "list" ? node
|
|
11947
|
+
const calls = node.type === "list" ? children(node) : [node];
|
|
11334
11948
|
const names = [];
|
|
11335
11949
|
for (const call of calls) {
|
|
11336
11950
|
const name = call === null ? null : dependencyNameOf(call, form);
|
|
@@ -11349,7 +11963,7 @@ function dependencyNameOf(node, form) {
|
|
|
11349
11963
|
if (calleeName3 === null || !form.callees.includes(calleeName3)) {
|
|
11350
11964
|
return null;
|
|
11351
11965
|
}
|
|
11352
|
-
const first = field(node, "arguments")?.
|
|
11966
|
+
const first = field(node, "arguments")?.namedChild(0);
|
|
11353
11967
|
return first?.type === "identifier" ? first.text : null;
|
|
11354
11968
|
}
|
|
11355
11969
|
function decoratorDependencies(classification, form) {
|
|
@@ -11367,7 +11981,7 @@ function parameterDependencies(definitionNode, form) {
|
|
|
11367
11981
|
if (direct !== null) {
|
|
11368
11982
|
return direct;
|
|
11369
11983
|
}
|
|
11370
|
-
for (const child of node
|
|
11984
|
+
for (const child of children(node)) {
|
|
11371
11985
|
const found = findIn(child, depth + 1);
|
|
11372
11986
|
if (found !== null) {
|
|
11373
11987
|
return found;
|
|
@@ -11375,10 +11989,7 @@ function parameterDependencies(definitionNode, form) {
|
|
|
11375
11989
|
}
|
|
11376
11990
|
return null;
|
|
11377
11991
|
};
|
|
11378
|
-
for (const param of field(definitionNode, "parameters")
|
|
11379
|
-
if (param === null) {
|
|
11380
|
-
continue;
|
|
11381
|
-
}
|
|
11992
|
+
for (const param of children(field(definitionNode, "parameters"))) {
|
|
11382
11993
|
const inDefault = field(param, "value");
|
|
11383
11994
|
const found = inDefault === null ? findIn(field(param, "type"), 0) : dependencyNameOf(inDefault, form);
|
|
11384
11995
|
if (found !== null) {
|
|
@@ -11394,7 +12005,8 @@ function wrapperUnit(target, declared, options) {
|
|
|
11394
12005
|
const raised = raisedResponses(body, {
|
|
11395
12006
|
calls: declared.pattern.responseStatusCalls ?? [],
|
|
11396
12007
|
module: file.module,
|
|
11397
|
-
facts: options.facts
|
|
12008
|
+
facts: options.facts,
|
|
12009
|
+
constants: declared.pattern.statusCodeConstants ?? {}
|
|
11398
12010
|
});
|
|
11399
12011
|
const continuations = continuationStatements(node, declared.form);
|
|
11400
12012
|
const terminals = bodyTerminals(body, raised, continuations);
|
|
@@ -11422,9 +12034,9 @@ function wrapperUnit(target, declared, options) {
|
|
|
11422
12034
|
});
|
|
11423
12035
|
const respond = (statement) => returnBranch(statement, {
|
|
11424
12036
|
pattern: declared.pattern,
|
|
11425
|
-
responseShape: { reading:
|
|
12037
|
+
responseShape: { reading: import_extractor17.absentReading },
|
|
11426
12038
|
declaredStatus: {
|
|
11427
|
-
reading:
|
|
12039
|
+
reading: import_extractor17.absentReading,
|
|
11428
12040
|
...declared.pattern.defaultStatusCode !== void 0 ? { libraryDefault: declared.pattern.defaultStatusCode } : {}
|
|
11429
12041
|
},
|
|
11430
12042
|
module: file.module,
|
|
@@ -11478,7 +12090,7 @@ function returnHandsOn(statement, form) {
|
|
|
11478
12090
|
return false;
|
|
11479
12091
|
}
|
|
11480
12092
|
if (form.returnedValueResponds === true) {
|
|
11481
|
-
const returned = statement.
|
|
12093
|
+
const returned = statement.namedChild(0);
|
|
11482
12094
|
return returned === void 0 || returned === null || returned.type === "none";
|
|
11483
12095
|
}
|
|
11484
12096
|
return true;
|
|
@@ -11487,9 +12099,7 @@ function continuationStatements(node, form) {
|
|
|
11487
12099
|
if (form.type !== "decoratedWrapper" || form.continuationParam === void 0) {
|
|
11488
12100
|
return [];
|
|
11489
12101
|
}
|
|
11490
|
-
const params = (field(node, "parameters")
|
|
11491
|
-
(param2) => param2 !== null
|
|
11492
|
-
);
|
|
12102
|
+
const params = children(field(node, "parameters"));
|
|
11493
12103
|
const param = params[form.continuationParam];
|
|
11494
12104
|
const continuation = param === void 0 ? null : field(param, "name")?.text ?? (param.type === "identifier" ? param.text : null);
|
|
11495
12105
|
if (continuation === null) {
|
|
@@ -11512,7 +12122,7 @@ function continuationStatements(node, form) {
|
|
|
11512
12122
|
|
|
11513
12123
|
// src/project.ts
|
|
11514
12124
|
function keptPythonParses() {
|
|
11515
|
-
return new
|
|
12125
|
+
return new import_extractor18.KeptParses(({ root }) => root.tree.delete());
|
|
11516
12126
|
}
|
|
11517
12127
|
async function parsePythonAhead(files, kept) {
|
|
11518
12128
|
for (const file of files) {
|
|
@@ -11601,16 +12211,16 @@ function factsForFile(options) {
|
|
|
11601
12211
|
}
|
|
11602
12212
|
async function extractPythonProject(options) {
|
|
11603
12213
|
const { roots, unreadManifests } = rootsOfRun(options);
|
|
11604
|
-
const timer = options.onTiming !== void 0 ? (0,
|
|
12214
|
+
const timer = options.onTiming !== void 0 ? (0, import_extractor18.createTimer)() : (0, import_extractor18.noopTimer)();
|
|
11605
12215
|
const cacheDir = adapterStamp.declineWhenRunFromSource(
|
|
11606
12216
|
options.cacheDir === null ? null : options.cacheDir ?? (options.projectRoot !== void 0 ? import_node_path5.default.join(options.projectRoot, ".suss", "cache") : null)
|
|
11607
12217
|
);
|
|
11608
|
-
const layer = (0,
|
|
12218
|
+
const layer = (0, import_extractor18.createCacheLayer)(cacheDir);
|
|
11609
12219
|
const packsDigest = `${adapterStamp.packsDigest(
|
|
11610
12220
|
options.packs.map(
|
|
11611
12221
|
(pack) => pack.version !== void 0 ? { name: pack.name, version: pack.version } : { name: pack.name }
|
|
11612
12222
|
)
|
|
11613
|
-
)}|${(0,
|
|
12223
|
+
)}|${(0, import_extractor18.extractionConfigStamp)({
|
|
11614
12224
|
gapHandling: options.gapHandling,
|
|
11615
12225
|
workspaceRoot: options.workspaceRoot,
|
|
11616
12226
|
projectRoot: options.projectRoot,
|
|
@@ -11620,7 +12230,7 @@ async function extractPythonProject(options) {
|
|
|
11620
12230
|
})}`;
|
|
11621
12231
|
const input = {
|
|
11622
12232
|
files: cacheDir === null ? [] : options.files,
|
|
11623
|
-
adapterPacksDigest: cacheDir === null ? packsDigest : (0,
|
|
12233
|
+
adapterPacksDigest: cacheDir === null ? packsDigest : (0, import_extractor18.runDigest)(packsDigest, options.packs, options.files)
|
|
11624
12234
|
};
|
|
11625
12235
|
const lookup = await timer.timeAsync(
|
|
11626
12236
|
"cache.lookup",
|
|
@@ -11682,7 +12292,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11682
12292
|
const db = new import_datalog2.Database();
|
|
11683
12293
|
const summaries = [];
|
|
11684
12294
|
const gapHandling = options.gapHandling ?? "permissive";
|
|
11685
|
-
const tallies = (0,
|
|
12295
|
+
const tallies = (0, import_extractor10.createPackTallies)(options.packs);
|
|
11686
12296
|
const ledger = cacheDir === null ? null : new import_resolution18.DependencyLedger(options.files);
|
|
11687
12297
|
const log = ledger === null ? null : new import_resolution18.FactLog(db, ledger);
|
|
11688
12298
|
if (ledger !== null) {
|
|
@@ -11790,7 +12400,8 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11790
12400
|
roots,
|
|
11791
12401
|
facts: needsValues ? db : void 0,
|
|
11792
12402
|
definitions,
|
|
11793
|
-
storageFor
|
|
12403
|
+
storageFor,
|
|
12404
|
+
routers: plainRouterIndex
|
|
11794
12405
|
})
|
|
11795
12406
|
);
|
|
11796
12407
|
const importedDefinition2 = importedDefinitionLookup(db, bound);
|
|
@@ -11937,11 +12548,11 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11937
12548
|
const assemble = (raw, boundFile) => {
|
|
11938
12549
|
const summary = timer.time(
|
|
11939
12550
|
"summarize",
|
|
11940
|
-
() => (0,
|
|
12551
|
+
() => (0, import_extractor18.assembleSummary)(raw, { gapHandling })
|
|
11941
12552
|
);
|
|
11942
12553
|
summaries.push(summary);
|
|
11943
12554
|
assembledHere.add(summary);
|
|
11944
|
-
(0,
|
|
12555
|
+
(0, import_extractor10.tallyUnit)(tallies, raw.boundaryBinding?.recognition);
|
|
11945
12556
|
const span = raw.identity.span;
|
|
11946
12557
|
const key = span === void 0 ? null : `${boundFile.file}:${span.start}-${span.end}`;
|
|
11947
12558
|
if (key !== null) {
|
|
@@ -11958,7 +12569,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
11958
12569
|
const summary = structuredClone(unit.summary);
|
|
11959
12570
|
summariesReused += 1;
|
|
11960
12571
|
summaries.push(summary);
|
|
11961
|
-
(0,
|
|
12572
|
+
(0, import_extractor10.tallyUnit)(tallies, unit.recognition);
|
|
11962
12573
|
if (unit.seedKey !== void 0) {
|
|
11963
12574
|
seedFrom(unit.seedKey, boundFile, summary);
|
|
11964
12575
|
}
|
|
@@ -12016,12 +12627,12 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12016
12627
|
const placeWhatItReached = (summary, key) => {
|
|
12017
12628
|
if (gapHandling !== "silent") {
|
|
12018
12629
|
summary.gaps.push(
|
|
12019
|
-
...(reached.stopsByKey.get(key) ?? []).map(
|
|
12630
|
+
...(reached.stopsByKey.get(key) ?? []).map(import_behavioral_ir10.unfollowedCallGap)
|
|
12020
12631
|
);
|
|
12021
12632
|
}
|
|
12022
|
-
(0,
|
|
12023
|
-
(0,
|
|
12024
|
-
(0,
|
|
12633
|
+
(0, import_behavioral_ir10.placeCalls)(summary, reached.targetsByKey.get(key));
|
|
12634
|
+
(0, import_behavioral_ir10.placeArgTargets)(summary, reached.argTargetsByKey.get(key));
|
|
12635
|
+
(0, import_behavioral_ir10.placeCalleeParameters)(summary, reached.parameterCallsByKey.get(key));
|
|
12025
12636
|
};
|
|
12026
12637
|
for (const [key, owners] of summariesBySeed) {
|
|
12027
12638
|
for (const summary of owners) {
|
|
@@ -12038,7 +12649,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12038
12649
|
}
|
|
12039
12650
|
}
|
|
12040
12651
|
if (gapHandling !== "silent") {
|
|
12041
|
-
(0,
|
|
12652
|
+
(0, import_behavioral_ir10.recordParameterGaps)(
|
|
12042
12653
|
reached.parameterCallsByKey,
|
|
12043
12654
|
summariesBySeed,
|
|
12044
12655
|
reached.passedPositions
|
|
@@ -12062,8 +12673,8 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12062
12673
|
}
|
|
12063
12674
|
const summary = timer.time(
|
|
12064
12675
|
"summarize",
|
|
12065
|
-
() => (0,
|
|
12066
|
-
(0,
|
|
12676
|
+
() => (0, import_extractor18.assembleSummary)(
|
|
12677
|
+
(0, import_extractor18.moduleInitStructure)({
|
|
12067
12678
|
name: import_node_path5.default.basename(displayPath),
|
|
12068
12679
|
file: displayPath,
|
|
12069
12680
|
range: rangeOf(boundFile.root),
|
|
@@ -12072,7 +12683,7 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12072
12683
|
...charged(
|
|
12073
12684
|
boundFile.file,
|
|
12074
12685
|
() => moduleLoadInvocationEffects(boundFile.root, db)
|
|
12075
|
-
).map(
|
|
12686
|
+
).map(import_extractor18.effectToIR)
|
|
12076
12687
|
]
|
|
12077
12688
|
}),
|
|
12078
12689
|
{ gapHandling }
|
|
@@ -12092,23 +12703,23 @@ async function runPython(options, roots, cache, previous) {
|
|
|
12092
12703
|
throw new ReplayFailed("");
|
|
12093
12704
|
}
|
|
12094
12705
|
const resolvedImports = (0, import_resolution18.importedFilesByFile)(db, displayPathOf);
|
|
12095
|
-
(0,
|
|
12096
|
-
(0,
|
|
12706
|
+
(0, import_extractor18.stampModuleImports)(summaries, (file) => resolvedImports.get(file) ?? []);
|
|
12707
|
+
(0, import_extractor18.stampModules)(summaries, declaredModules, options.workspaceRoot);
|
|
12097
12708
|
const idRoot = options.projectRoot ?? options.workspaceRoot;
|
|
12098
12709
|
for (const summary of summaries) {
|
|
12099
12710
|
const absoluteFile = options.workspaceRoot === void 0 ? summary.location.file : import_node_path5.default.resolve(options.workspaceRoot, summary.location.file);
|
|
12100
|
-
summary.identity.id = (0,
|
|
12711
|
+
summary.identity.id = (0, import_behavioral_ir10.summaryIdFromParts)({
|
|
12101
12712
|
workspace: void 0,
|
|
12102
12713
|
file: idRoot === void 0 ? absoluteFile : import_node_path5.default.relative(idRoot, absoluteFile),
|
|
12103
12714
|
name: summary.identity.name,
|
|
12104
12715
|
exportPath: summary.identity.exportPath
|
|
12105
12716
|
});
|
|
12106
12717
|
}
|
|
12107
|
-
(0,
|
|
12108
|
-
(0,
|
|
12718
|
+
(0, import_behavioral_ir10.disambiguateSummaryIds)(summaries);
|
|
12719
|
+
(0, import_behavioral_ir10.linkCallsToSummaries)(summaries);
|
|
12109
12720
|
const composed = timer.time("summarize", () => {
|
|
12110
12721
|
markExitCodeFunctions(summaries, exits, db, options.workspaceRoot);
|
|
12111
|
-
return (0,
|
|
12722
|
+
return (0, import_extractor18.composeWrappers)(summaries, { gapHandling });
|
|
12112
12723
|
});
|
|
12113
12724
|
await timer.timeAsync("cache.write", async () => {
|
|
12114
12725
|
if (cacheDir === null || composed.length === 0) {
|
|
@@ -12233,7 +12844,7 @@ function indexDefinitions(into, file, node) {
|
|
|
12233
12844
|
if (isFunction(node)) {
|
|
12234
12845
|
into.set(nodeId(file, node), node);
|
|
12235
12846
|
}
|
|
12236
|
-
for (const child of node
|
|
12847
|
+
for (const child of children(node)) {
|
|
12237
12848
|
if (child !== null) {
|
|
12238
12849
|
indexDefinitions(into, file, child);
|
|
12239
12850
|
}
|
|
@@ -12499,7 +13110,7 @@ function importSitesIn(root) {
|
|
|
12499
13110
|
found.push({ module: entry.module, name: entry.name, line });
|
|
12500
13111
|
}
|
|
12501
13112
|
}
|
|
12502
|
-
for (const child of node
|
|
13113
|
+
for (const child of children(node)) {
|
|
12503
13114
|
if (child !== null) {
|
|
12504
13115
|
visit(child);
|
|
12505
13116
|
}
|