@suss/adapter-ruby 0.20.0 → 0.21.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 +276 -77
- package/dist/index.d.cts +12 -9
- package/dist/index.d.ts +12 -9
- package/dist/index.js +280 -81
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/ast.ts
|
|
8
|
-
import { IdMap, IdSet } from "@suss/extractor";
|
|
8
|
+
import { IdMap, IdSet, SKIP_CHILDREN, walkDescendants } from "@suss/extractor";
|
|
9
9
|
function rangeOf(node) {
|
|
10
10
|
return {
|
|
11
11
|
start: node.startPosition.row + 1,
|
|
@@ -21,12 +21,37 @@ function field(node, name) {
|
|
|
21
21
|
function bodyStatements(body) {
|
|
22
22
|
return body.namedChildren.filter((child) => child !== null);
|
|
23
23
|
}
|
|
24
|
+
var OWN_BODY_TYPES = /* @__PURE__ */ new Set([
|
|
25
|
+
"method",
|
|
26
|
+
"singleton_method",
|
|
27
|
+
"lambda",
|
|
28
|
+
"class",
|
|
29
|
+
"module",
|
|
30
|
+
"singleton_class"
|
|
31
|
+
]);
|
|
32
|
+
var ARGUMENT_LIST_TYPE = "argument_list";
|
|
33
|
+
function runStatements(body, blockConfigures = () => false) {
|
|
34
|
+
const found = [];
|
|
35
|
+
const readsItsChildren = (node) => {
|
|
36
|
+
if (OWN_BODY_TYPES.has(node.type) || node.type === ARGUMENT_LIST_TYPE) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return !(node.type === "call" && blockConfigures(node));
|
|
40
|
+
};
|
|
41
|
+
walkDescendants(body, null, {
|
|
42
|
+
at: (node) => {
|
|
43
|
+
found.push(node);
|
|
44
|
+
},
|
|
45
|
+
into: (node) => readsItsChildren(node) ? null : SKIP_CHILDREN
|
|
46
|
+
});
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
24
49
|
function symbolValue(node) {
|
|
25
50
|
return node.type === "simple_symbol" ? node.text.slice(1) : null;
|
|
26
51
|
}
|
|
27
52
|
function instanceMethodsByName(body) {
|
|
28
53
|
const methods = /* @__PURE__ */ new Map();
|
|
29
|
-
for (const stmt of
|
|
54
|
+
for (const stmt of runStatements(body)) {
|
|
30
55
|
if (stmt.type !== "method") {
|
|
31
56
|
continue;
|
|
32
57
|
}
|
|
@@ -39,7 +64,7 @@ function instanceMethodsByName(body) {
|
|
|
39
64
|
}
|
|
40
65
|
function bareCallArgumentGroups(body, name) {
|
|
41
66
|
const groups = [];
|
|
42
|
-
for (const stmt of
|
|
67
|
+
for (const stmt of runStatements(body)) {
|
|
43
68
|
if (stmt.type !== "call" || field(stmt, "receiver") !== null) {
|
|
44
69
|
continue;
|
|
45
70
|
}
|
|
@@ -142,7 +167,7 @@ function walkClasses(root, visit) {
|
|
|
142
167
|
});
|
|
143
168
|
}
|
|
144
169
|
function walkDefinitions(root, visit) {
|
|
145
|
-
walkBody(
|
|
170
|
+
walkBody(runStatements(root), [], visit);
|
|
146
171
|
}
|
|
147
172
|
function walkBody(statements, nesting, visit) {
|
|
148
173
|
for (const stmt of statements) {
|
|
@@ -181,7 +206,7 @@ function visitClass(node, nesting, visit) {
|
|
|
181
206
|
bodyNesting: identity.bodyNesting
|
|
182
207
|
});
|
|
183
208
|
if (bodyNode !== null) {
|
|
184
|
-
walkBody(
|
|
209
|
+
walkBody(runStatements(bodyNode), identity.bodyNesting, visit);
|
|
185
210
|
}
|
|
186
211
|
}
|
|
187
212
|
function visitModule(node, nesting, visit) {
|
|
@@ -200,7 +225,7 @@ function visitModule(node, nesting, visit) {
|
|
|
200
225
|
bodyNesting: identity.bodyNesting
|
|
201
226
|
});
|
|
202
227
|
if (bodyNode !== null) {
|
|
203
|
-
walkBody(
|
|
228
|
+
walkBody(runStatements(bodyNode), identity.bodyNesting, visit);
|
|
204
229
|
}
|
|
205
230
|
}
|
|
206
231
|
function stripTypeSuffixName(qualifiedName) {
|
|
@@ -356,7 +381,7 @@ function definitionIn(blocks, name) {
|
|
|
356
381
|
}
|
|
357
382
|
return { method, dynamic };
|
|
358
383
|
}
|
|
359
|
-
function inheritedStatements(ancestry) {
|
|
384
|
+
function inheritedStatements(ancestry, blockConfigures) {
|
|
360
385
|
const statements = [];
|
|
361
386
|
for (const entry of [...ancestry].reverse()) {
|
|
362
387
|
if (entry.type !== "bodies") {
|
|
@@ -367,7 +392,7 @@ function inheritedStatements(ancestry) {
|
|
|
367
392
|
if (body === null) {
|
|
368
393
|
continue;
|
|
369
394
|
}
|
|
370
|
-
for (const statement of
|
|
395
|
+
for (const statement of runStatements(body, blockConfigures)) {
|
|
371
396
|
statements.push({ block, statement });
|
|
372
397
|
}
|
|
373
398
|
}
|
|
@@ -376,7 +401,7 @@ function inheritedStatements(ancestry) {
|
|
|
376
401
|
}
|
|
377
402
|
|
|
378
403
|
// src/discovery.ts
|
|
379
|
-
import { dispatchByType, graphqlResolverBinding } from "@suss/behavioral-ir";
|
|
404
|
+
import { dispatchByType as dispatchByType2, graphqlResolverBinding } from "@suss/behavioral-ir";
|
|
380
405
|
import { unreadableReading } from "@suss/extractor";
|
|
381
406
|
|
|
382
407
|
// src/paths/effects.ts
|
|
@@ -593,14 +618,6 @@ function lowerRubyBody(body, terminals) {
|
|
|
593
618
|
}
|
|
594
619
|
|
|
595
620
|
// src/paths/effects.ts
|
|
596
|
-
var DECLARATION_TYPES = /* @__PURE__ */ new Set([
|
|
597
|
-
"method",
|
|
598
|
-
"singleton_method",
|
|
599
|
-
"lambda",
|
|
600
|
-
"class",
|
|
601
|
-
"module",
|
|
602
|
-
"singleton_class"
|
|
603
|
-
]);
|
|
604
621
|
var RAISE_NAMES2 = /* @__PURE__ */ new Set(["raise", "fail"]);
|
|
605
622
|
var BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
606
623
|
"body_statement",
|
|
@@ -648,7 +665,7 @@ function isRaise2(node) {
|
|
|
648
665
|
}
|
|
649
666
|
function bodyCalls(node, found = []) {
|
|
650
667
|
for (const child of children(node)) {
|
|
651
|
-
if (
|
|
668
|
+
if (OWN_BODY_TYPES.has(child.type)) {
|
|
652
669
|
continue;
|
|
653
670
|
}
|
|
654
671
|
if (child.type === "call" && !isPropertyRead(child) && !isRaise2(child)) {
|
|
@@ -15251,7 +15268,7 @@ function date4(params) {
|
|
|
15251
15268
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
15252
15269
|
config(en_default());
|
|
15253
15270
|
|
|
15254
|
-
// ../../ir-core/dist/chunk-
|
|
15271
|
+
// ../../ir-core/dist/chunk-PPQWK62O.js
|
|
15255
15272
|
function gqlIdentityKey(typeName, fieldName) {
|
|
15256
15273
|
return `gql:${typeName}.${fieldName}`;
|
|
15257
15274
|
}
|
|
@@ -15261,6 +15278,9 @@ function fnIdentityKey(packageName, exportPath) {
|
|
|
15261
15278
|
function busIdentityKey(messageBus, subject) {
|
|
15262
15279
|
return `bus:${messageBus} ${subject}`;
|
|
15263
15280
|
}
|
|
15281
|
+
function unitIdentityKey(deploymentTarget, instanceName) {
|
|
15282
|
+
return `unit:${deploymentTarget} ${instanceName}`;
|
|
15283
|
+
}
|
|
15264
15284
|
function metricIdentityKey(metricSystem, metricType) {
|
|
15265
15285
|
return `metric:${metricSystem} ${metricType}`;
|
|
15266
15286
|
}
|
|
@@ -15534,6 +15554,42 @@ var metricSemantics = defineBoundarySemantics({
|
|
|
15534
15554
|
}
|
|
15535
15555
|
}
|
|
15536
15556
|
});
|
|
15557
|
+
var HOLE_SPLIT = /(\{[^}]*\})/;
|
|
15558
|
+
function isHole(piece) {
|
|
15559
|
+
return piece.startsWith("{") && piece.endsWith("}");
|
|
15560
|
+
}
|
|
15561
|
+
function parseBoundaryName(name) {
|
|
15562
|
+
const parts = name.split(HOLE_SPLIT).filter((piece) => piece !== "").map(
|
|
15563
|
+
(piece) => isHole(piece) ? { type: "hole", label: piece.slice(1, -1) } : { type: "text", text: piece }
|
|
15564
|
+
);
|
|
15565
|
+
const only = parts.length === 1 ? parts[0] : void 0;
|
|
15566
|
+
if (only !== void 0 && only.type === "hole") {
|
|
15567
|
+
return { type: "reference", path: only.label.split(".") };
|
|
15568
|
+
}
|
|
15569
|
+
if (parts.some((part) => part.type === "hole")) {
|
|
15570
|
+
return { type: "pattern", parts };
|
|
15571
|
+
}
|
|
15572
|
+
return { type: "literal", value: name };
|
|
15573
|
+
}
|
|
15574
|
+
function patternHole(label) {
|
|
15575
|
+
return `{${label}}`;
|
|
15576
|
+
}
|
|
15577
|
+
function namesNothing(name) {
|
|
15578
|
+
return parseBoundaryName(name).type === "reference";
|
|
15579
|
+
}
|
|
15580
|
+
function referenceOf(name) {
|
|
15581
|
+
if (name.type !== "reference") {
|
|
15582
|
+
return null;
|
|
15583
|
+
}
|
|
15584
|
+
const root = name.path[0];
|
|
15585
|
+
if (root === void 0 || name.path.some((part) => part === "")) {
|
|
15586
|
+
return null;
|
|
15587
|
+
}
|
|
15588
|
+
return { root, fields: name.path.slice(1) };
|
|
15589
|
+
}
|
|
15590
|
+
function referenceFromName(name) {
|
|
15591
|
+
return referenceOf(parseBoundaryName(name));
|
|
15592
|
+
}
|
|
15537
15593
|
var SCHEME_ORIGIN = /^[a-zA-Z][a-zA-Z\d+.-]*:\/\/[^/]*/;
|
|
15538
15594
|
var PROTOCOL_RELATIVE_ORIGIN = /^\/\/[^/]*/;
|
|
15539
15595
|
function pathAfterOrigin(text) {
|
|
@@ -15560,9 +15616,9 @@ var RestSemanticsSchema = external_exports.object({
|
|
|
15560
15616
|
declaredResponses: external_exports.array(external_exports.number()).optional()
|
|
15561
15617
|
});
|
|
15562
15618
|
var OPENING_HOLE = /^\{([^{}]+)\}(.*)$/;
|
|
15563
|
-
function
|
|
15564
|
-
const
|
|
15565
|
-
return
|
|
15619
|
+
function baseUrlReference(semantics) {
|
|
15620
|
+
const label = OPENING_HOLE.exec(semantics.path ?? "")?.[1];
|
|
15621
|
+
return label === void 0 ? null : referenceFromName(patternHole(label));
|
|
15566
15622
|
}
|
|
15567
15623
|
function normalizePath(path4) {
|
|
15568
15624
|
let normalized = path4.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
|
|
@@ -15673,6 +15729,14 @@ var restSemantics = defineBoundarySemantics({
|
|
|
15673
15729
|
}
|
|
15674
15730
|
return routePathAdmits(semantics.path, path4) ? "match" : "nomatch";
|
|
15675
15731
|
},
|
|
15732
|
+
/**
|
|
15733
|
+
* A route the registration pattern admits is inside it. A route
|
|
15734
|
+
* whose path this source never gave is left outside, because
|
|
15735
|
+
* nothing here can show it is one the pattern covers.
|
|
15736
|
+
*/
|
|
15737
|
+
withinScope(semantics, scope) {
|
|
15738
|
+
return semantics.path !== null && routePathAdmits(scope, semantics.path);
|
|
15739
|
+
},
|
|
15676
15740
|
/**
|
|
15677
15741
|
* A call whose base URL the deployment fills in, resolved to the
|
|
15678
15742
|
* path it reaches.
|
|
@@ -15688,22 +15752,20 @@ var restSemantics = defineBoundarySemantics({
|
|
|
15688
15752
|
* route parameter, and `/orders/{id}` means every id rather than a
|
|
15689
15753
|
* variable somebody set.
|
|
15690
15754
|
*/
|
|
15691
|
-
groundName(semantics,
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
}
|
|
15695
|
-
const opening = OPENING_HOLE.exec(semantics.path);
|
|
15696
|
-
if (opening === null) {
|
|
15755
|
+
groundName(semantics, deployment) {
|
|
15756
|
+
const reference = baseUrlReference(semantics);
|
|
15757
|
+
if (reference === null) {
|
|
15697
15758
|
return null;
|
|
15698
15759
|
}
|
|
15699
|
-
const
|
|
15700
|
-
const base = deployedAs(variableOf(label));
|
|
15760
|
+
const base = deployment.setTo(reference);
|
|
15701
15761
|
if (base === null) {
|
|
15702
15762
|
return null;
|
|
15703
15763
|
}
|
|
15764
|
+
const rest = OPENING_HOLE.exec(semantics.path ?? "")?.[2] ?? "";
|
|
15704
15765
|
const grounded = pathAfterOrigin(`${base}${rest}`);
|
|
15705
15766
|
return { ...semantics, path: grounded === "" ? "/" : grounded };
|
|
15706
15767
|
},
|
|
15768
|
+
nameReference: baseUrlReference,
|
|
15707
15769
|
ruleBoundary: {
|
|
15708
15770
|
// "METHOD /path": one leading token, then an absolute path.
|
|
15709
15771
|
claims(raw) {
|
|
@@ -15779,6 +15841,9 @@ var StorageSemanticsSchema = external_exports.object({
|
|
|
15779
15841
|
*/
|
|
15780
15842
|
accessPath: external_exports.string().nullable()
|
|
15781
15843
|
});
|
|
15844
|
+
function containerReference(semantics) {
|
|
15845
|
+
return semantics.container === null ? null : referenceFromName(semantics.container);
|
|
15846
|
+
}
|
|
15782
15847
|
var storageSemantics = defineBoundarySemantics({
|
|
15783
15848
|
name: "storage",
|
|
15784
15849
|
schema: StorageSemanticsSchema,
|
|
@@ -15794,7 +15859,100 @@ var storageSemantics = defineBoundarySemantics({
|
|
|
15794
15859
|
/** A query returns rows or items, not a status and a body. */
|
|
15795
15860
|
exchangesHttpResponses: false,
|
|
15796
15861
|
reportsUnpairedItself: false,
|
|
15797
|
-
identityKey: () => null
|
|
15862
|
+
identityKey: () => null,
|
|
15863
|
+
displayLabel: storageLabel,
|
|
15864
|
+
/**
|
|
15865
|
+
* A container the source states as a variable is whatever the
|
|
15866
|
+
* deployment sets that variable to. `{SUBSCRIBERS_TABLE}` in the
|
|
15867
|
+
* code and `prod-subscribers-v1` in the manifest are one table.
|
|
15868
|
+
*/
|
|
15869
|
+
groundName(semantics, deployment) {
|
|
15870
|
+
const reference = containerReference(semantics);
|
|
15871
|
+
if (reference === null) {
|
|
15872
|
+
return null;
|
|
15873
|
+
}
|
|
15874
|
+
const name = deployment.setTo(reference);
|
|
15875
|
+
return name === null ? null : { ...semantics, container: name };
|
|
15876
|
+
},
|
|
15877
|
+
nameReference: containerReference
|
|
15878
|
+
}
|
|
15879
|
+
});
|
|
15880
|
+
function storageLabel(semantics) {
|
|
15881
|
+
return `${semantics.storageSystem}:${storageContainerLabel(semantics)}`;
|
|
15882
|
+
}
|
|
15883
|
+
function storageContainerLabel(semantics) {
|
|
15884
|
+
const container = semantics.container ?? "<unnamed container>";
|
|
15885
|
+
const addressed = semantics.accessPath === null ? container : `${container}#${semantics.accessPath}`;
|
|
15886
|
+
return semantics.scope === "default" ? addressed : `${semantics.scope}/${addressed}`;
|
|
15887
|
+
}
|
|
15888
|
+
var UnitInvocationSemanticsSchema = DeployableUnitSchema.extend({
|
|
15889
|
+
name: external_exports.literal("unit-invocation"),
|
|
15890
|
+
instanceName: DeployableUnitSchema.shape.instanceName.nullable()
|
|
15891
|
+
});
|
|
15892
|
+
function calleeReference(semantics) {
|
|
15893
|
+
return semantics.instanceName === null ? null : referenceFromName(semantics.instanceName);
|
|
15894
|
+
}
|
|
15895
|
+
var unitInvocationSemantics = defineBoundarySemantics({
|
|
15896
|
+
name: "unit-invocation",
|
|
15897
|
+
schema: UnitInvocationSemanticsSchema,
|
|
15898
|
+
// faas.name is the deployed function's own name and instanceName is
|
|
15899
|
+
// the deployment template's logical id, which is a different string.
|
|
15900
|
+
// Runtime config leaves the pair off for the same reason.
|
|
15901
|
+
semconv: {},
|
|
15902
|
+
behavior: {
|
|
15903
|
+
/**
|
|
15904
|
+
* A synchronous invoke gives back whatever the handler returned,
|
|
15905
|
+
* which is a value rather than a status and a body. A handler's
|
|
15906
|
+
* return only becomes an HTTP response under a proxy integration,
|
|
15907
|
+
* and that route gets a REST binding instead of this one.
|
|
15908
|
+
*/
|
|
15909
|
+
exchangesHttpResponses: false,
|
|
15910
|
+
/**
|
|
15911
|
+
* A unit nothing in the run invokes is the ordinary case, since
|
|
15912
|
+
* most services are reached from a stack suss never read. So an
|
|
15913
|
+
* uninvoked unit stays in the generic unmatched list rather than
|
|
15914
|
+
* being reported as a problem here.
|
|
15915
|
+
*/
|
|
15916
|
+
reportsUnpairedItself: false,
|
|
15917
|
+
/**
|
|
15918
|
+
* A callee the source states only as a variable is not a name for
|
|
15919
|
+
* anything until the deployment fills it in, so it keys as nothing
|
|
15920
|
+
* rather than as a bucket that would agree with itself alone.
|
|
15921
|
+
*/
|
|
15922
|
+
identityKey(semantics) {
|
|
15923
|
+
if (semantics.instanceName === null || namesNothing(semantics.instanceName)) {
|
|
15924
|
+
return null;
|
|
15925
|
+
}
|
|
15926
|
+
return unitIdentityKey(
|
|
15927
|
+
semantics.deploymentTarget,
|
|
15928
|
+
semantics.instanceName
|
|
15929
|
+
);
|
|
15930
|
+
},
|
|
15931
|
+
displayLabel(semantics) {
|
|
15932
|
+
if (semantics.instanceName === null) {
|
|
15933
|
+
return `unit:${semantics.deploymentTarget} (named at runtime)`;
|
|
15934
|
+
}
|
|
15935
|
+
return unitIdentityKey(
|
|
15936
|
+
semantics.deploymentTarget,
|
|
15937
|
+
semantics.instanceName
|
|
15938
|
+
);
|
|
15939
|
+
},
|
|
15940
|
+
/**
|
|
15941
|
+
* A call that reads its callee's name out of the environment
|
|
15942
|
+
* reaches whichever resource the template wires that variable to.
|
|
15943
|
+
* The logical id is the answer rather than the deployed name,
|
|
15944
|
+
* because the invoked unit's own summary is keyed by the logical
|
|
15945
|
+
* id and neither side ever writes the other's string.
|
|
15946
|
+
*/
|
|
15947
|
+
groundName(semantics, deployment) {
|
|
15948
|
+
const reference = calleeReference(semantics);
|
|
15949
|
+
if (reference === null) {
|
|
15950
|
+
return null;
|
|
15951
|
+
}
|
|
15952
|
+
const logicalId = deployment.pointsAt(reference);
|
|
15953
|
+
return logicalId === null ? null : { ...semantics, instanceName: logicalId };
|
|
15954
|
+
},
|
|
15955
|
+
nameReference: calleeReference
|
|
15798
15956
|
}
|
|
15799
15957
|
});
|
|
15800
15958
|
var SemanticsSchema = external_exports.discriminatedUnion("name", [
|
|
@@ -15805,7 +15963,8 @@ var SemanticsSchema = external_exports.discriminatedUnion("name", [
|
|
|
15805
15963
|
runtimeConfigSemantics.schema,
|
|
15806
15964
|
storageSemantics.schema,
|
|
15807
15965
|
messageBusSemantics.schema,
|
|
15808
|
-
metricSemantics.schema
|
|
15966
|
+
metricSemantics.schema,
|
|
15967
|
+
unitInvocationSemantics.schema
|
|
15809
15968
|
]);
|
|
15810
15969
|
var DEFINITIONS = [
|
|
15811
15970
|
restSemantics,
|
|
@@ -15815,7 +15974,8 @@ var DEFINITIONS = [
|
|
|
15815
15974
|
runtimeConfigSemantics,
|
|
15816
15975
|
storageSemantics,
|
|
15817
15976
|
messageBusSemantics,
|
|
15818
|
-
metricSemantics
|
|
15977
|
+
metricSemantics,
|
|
15978
|
+
unitInvocationSemantics
|
|
15819
15979
|
];
|
|
15820
15980
|
var BY_NAME = new Map(
|
|
15821
15981
|
DEFINITIONS.map((d) => [d.name, d])
|
|
@@ -15905,6 +16065,13 @@ var TypeShapeSchema = external_exports.lazy(
|
|
|
15905
16065
|
);
|
|
15906
16066
|
|
|
15907
16067
|
// ../../ir-core/dist/index.js
|
|
16068
|
+
var RelationSchema = external_exports.enum([
|
|
16069
|
+
"provides",
|
|
16070
|
+
"reads",
|
|
16071
|
+
"writes",
|
|
16072
|
+
"invokes"
|
|
16073
|
+
]);
|
|
16074
|
+
var EffectRelationSchema = RelationSchema.exclude(["provides"]);
|
|
15908
16075
|
var SuppressionSideSchema = external_exports.object({
|
|
15909
16076
|
summary: external_exports.string().optional(),
|
|
15910
16077
|
transitionId: external_exports.string().optional()
|
|
@@ -16093,9 +16260,9 @@ var RESOLUTION_RULES = [
|
|
|
16093
16260
|
[lit("invokes", v("r"), v("f")), lit("returnsValue", v("f"), v("ret"))],
|
|
16094
16261
|
"call result"
|
|
16095
16262
|
),
|
|
16096
|
-
// Where a walk gets to, and whether it ran a call on the way.
|
|
16097
|
-
//
|
|
16098
|
-
//
|
|
16263
|
+
// Where a walk gets to, and whether it ran a call on the way. The walk
|
|
16264
|
+
// so far comes first, so demand stays on the value asked about; the
|
|
16265
|
+
// README says what the other order cost.
|
|
16099
16266
|
rule(
|
|
16100
16267
|
"reaches",
|
|
16101
16268
|
[v("x"), v("z"), v("kind")],
|
|
@@ -16105,27 +16272,27 @@ var RESOLUTION_RULES = [
|
|
|
16105
16272
|
"reaches",
|
|
16106
16273
|
[v("x"), v("z"), v("kind")],
|
|
16107
16274
|
[
|
|
16108
|
-
lit("
|
|
16109
|
-
lit("
|
|
16275
|
+
lit("reaches", v("x"), v("y"), VALUE_STEP),
|
|
16276
|
+
lit("stepsTo", v("y"), v("z"), v("kind"))
|
|
16110
16277
|
]
|
|
16111
16278
|
),
|
|
16112
|
-
// Two rules rather than one leaving the
|
|
16113
|
-
//
|
|
16279
|
+
// Two rules rather than one leaving the next step's kind free. A free
|
|
16280
|
+
// kind is a second question about the same relation, and a
|
|
16114
16281
|
// demand-driven run then derives both to answer either.
|
|
16115
16282
|
rule(
|
|
16116
16283
|
"reaches",
|
|
16117
16284
|
[v("x"), v("z"), RESULT_STEP],
|
|
16118
16285
|
[
|
|
16119
|
-
lit("
|
|
16120
|
-
lit("
|
|
16286
|
+
lit("reaches", v("x"), v("y"), RESULT_STEP),
|
|
16287
|
+
lit("stepsTo", v("y"), v("z"), VALUE_STEP)
|
|
16121
16288
|
]
|
|
16122
16289
|
),
|
|
16123
16290
|
rule(
|
|
16124
16291
|
"reaches",
|
|
16125
16292
|
[v("x"), v("z"), RESULT_STEP],
|
|
16126
16293
|
[
|
|
16127
|
-
lit("
|
|
16128
|
-
lit("
|
|
16294
|
+
lit("reaches", v("x"), v("y"), RESULT_STEP),
|
|
16295
|
+
lit("stepsTo", v("y"), v("z"), RESULT_STEP)
|
|
16129
16296
|
]
|
|
16130
16297
|
),
|
|
16131
16298
|
// What a value comes down to: the walk that never ran a call, stopped
|
|
@@ -16471,29 +16638,14 @@ var RESOLUTION_QUESTIONS = [
|
|
|
16471
16638
|
// here demands reaches or callsInto. The chains are closures with
|
|
16472
16639
|
// no depth bound: an alias run of any length resolves.
|
|
16473
16640
|
rule("callOriginChain", [v("x"), v("x")], [lit("wantedCallOrigin", v("x"))]),
|
|
16641
|
+
// The chain with at least one hop taken, which is what tells a
|
|
16642
|
+
// destructured binding apart from asking about a node directly. The
|
|
16643
|
+
// whole chain is the seed plus those hops.
|
|
16474
16644
|
rule(
|
|
16475
16645
|
"callOriginChain",
|
|
16476
16646
|
[v("x"), v("z")],
|
|
16477
|
-
[lit("
|
|
16478
|
-
),
|
|
16479
|
-
rule(
|
|
16480
|
-
"callOriginChain",
|
|
16481
|
-
[v("x"), v("z")],
|
|
16482
|
-
[
|
|
16483
|
-
lit("callOriginChain", v("x"), v("y")),
|
|
16484
|
-
lit("endsHolding", v("y"), v("z"))
|
|
16485
|
-
]
|
|
16486
|
-
),
|
|
16487
|
-
rule(
|
|
16488
|
-
"callOriginChain",
|
|
16489
|
-
[v("x"), v("z")],
|
|
16490
|
-
[
|
|
16491
|
-
lit("callOriginChain", v("x"), v("y")),
|
|
16492
|
-
lit("fallbackBranch", v("y"), v("z"))
|
|
16493
|
-
]
|
|
16647
|
+
[lit("callOriginChainStepped", v("x"), v("z"))]
|
|
16494
16648
|
),
|
|
16495
|
-
// The chain with at least one hop taken, which is what tells a
|
|
16496
|
-
// destructured binding apart from asking about a node directly.
|
|
16497
16649
|
rule(
|
|
16498
16650
|
"callOriginChainStepped",
|
|
16499
16651
|
[v("x"), v("z")],
|
|
@@ -16624,6 +16776,23 @@ var RESOLUTION_QUESTIONS = [
|
|
|
16624
16776
|
lit("callsInto", v("g"), v("m"), v("n"))
|
|
16625
16777
|
]
|
|
16626
16778
|
),
|
|
16779
|
+
// Subject identity, its own demand class; the README's subject
|
|
16780
|
+
// section says why the origin pair rides on the written-value walk.
|
|
16781
|
+
rule(
|
|
16782
|
+
"wantedSubjectWritten",
|
|
16783
|
+
[v("x"), v("r")],
|
|
16784
|
+
[lit("wantedSubject", v("x")), lit("isWrittenAs", v("x"), v("r"))]
|
|
16785
|
+
),
|
|
16786
|
+
rule(
|
|
16787
|
+
"wantedSubjectConstruction",
|
|
16788
|
+
[v("x"), v("r"), v("m"), v("n")],
|
|
16789
|
+
[
|
|
16790
|
+
lit("wantedSubject", v("x")),
|
|
16791
|
+
lit("isWrittenAs", v("x"), v("r")),
|
|
16792
|
+
lit("call", v("r"), v("c")),
|
|
16793
|
+
lit("comesFrom", v("c"), v("m"), v("n"))
|
|
16794
|
+
]
|
|
16795
|
+
),
|
|
16627
16796
|
// The export table of one module, keyed by the module asked about.
|
|
16628
16797
|
// The moduleExport rules flatten re-export chains of any length, and
|
|
16629
16798
|
// the demand cone stays on export facts alone.
|
|
@@ -16948,7 +17117,7 @@ function unitsFor(pattern, pack, info, ownBlocks, fileBlocks, options) {
|
|
|
16948
17117
|
const table = {
|
|
16949
17118
|
graphqlObjectFields: (p) => graphqlObjectFieldUnits(p, pack, info, ownBlocks, fileBlocks, options)
|
|
16950
17119
|
};
|
|
16951
|
-
return
|
|
17120
|
+
return dispatchByType2(table, pattern);
|
|
16952
17121
|
}
|
|
16953
17122
|
async function graphqlObjectFieldUnits(pattern, pack, info, ownBlocks, fileBlocks, options) {
|
|
16954
17123
|
if (info.bodyNode === null || pattern.baseClassNames.includes(info.qualifiedName)) {
|
|
@@ -16971,7 +17140,10 @@ async function graphqlObjectFieldUnits(pattern, pack, info, ownBlocks, fileBlock
|
|
|
16971
17140
|
const knownClasses = ownBlocks[0]?.knownClasses ?? /* @__PURE__ */ new Set();
|
|
16972
17141
|
const scope = { nesting: info.bodyNesting, knownClasses };
|
|
16973
17142
|
const declsByName = /* @__PURE__ */ new Map();
|
|
16974
|
-
for (const stmt of
|
|
17143
|
+
for (const stmt of runStatements(
|
|
17144
|
+
info.bodyNode,
|
|
17145
|
+
blockConfiguresCall(pattern)
|
|
17146
|
+
)) {
|
|
16975
17147
|
const decl = await readFieldCall(stmt, scope, ctx, ancestry);
|
|
16976
17148
|
if (decl !== null) {
|
|
16977
17149
|
declsByName.set(decl.fieldName, decl);
|
|
@@ -16981,6 +17153,17 @@ async function graphqlObjectFieldUnits(pattern, pack, info, ownBlocks, fileBlock
|
|
|
16981
17153
|
(decl) => buildFieldUnit(pack, typeName, decl, options.filePath)
|
|
16982
17154
|
);
|
|
16983
17155
|
}
|
|
17156
|
+
function blockConfiguresCall(pattern) {
|
|
17157
|
+
const names = /* @__PURE__ */ new Set([
|
|
17158
|
+
pattern.fieldCallName,
|
|
17159
|
+
pattern.typeCallName,
|
|
17160
|
+
pattern.argumentCallName
|
|
17161
|
+
]);
|
|
17162
|
+
return (call) => {
|
|
17163
|
+
const method = field(call, "method")?.text;
|
|
17164
|
+
return field(call, "receiver") === null && method !== void 0 && names.has(method);
|
|
17165
|
+
};
|
|
17166
|
+
}
|
|
16984
17167
|
function branchesFor(body, range) {
|
|
16985
17168
|
if (body.effects === void 0 && body.extraEffects === void 0) {
|
|
16986
17169
|
return [];
|
|
@@ -17045,7 +17228,7 @@ function bodyFromLookup(found, range, subject, nothingThere, storage) {
|
|
|
17045
17228
|
),
|
|
17046
17229
|
none: () => nothingThere
|
|
17047
17230
|
};
|
|
17048
|
-
return
|
|
17231
|
+
return dispatchByType2(table, found);
|
|
17049
17232
|
}
|
|
17050
17233
|
async function readFieldCall(stmt, scope, ctx, ancestry) {
|
|
17051
17234
|
if (stmt.type !== "call" || field(stmt, "receiver") !== null) {
|
|
@@ -17056,10 +17239,13 @@ async function readFieldCall(stmt, scope, ctx, ancestry) {
|
|
|
17056
17239
|
}
|
|
17057
17240
|
const callArgs = readCallArgs(field(stmt, "arguments"));
|
|
17058
17241
|
const nameArg = callArgs.positional[0];
|
|
17059
|
-
|
|
17060
|
-
if (symbol2 === null) {
|
|
17242
|
+
if (nameArg === void 0) {
|
|
17061
17243
|
return null;
|
|
17062
17244
|
}
|
|
17245
|
+
const symbol2 = symbolValue(nameArg);
|
|
17246
|
+
if (symbol2 === null) {
|
|
17247
|
+
return computedNameDeclaration(stmt, nameArg);
|
|
17248
|
+
}
|
|
17063
17249
|
const read = await readFieldShape(
|
|
17064
17250
|
symbol2,
|
|
17065
17251
|
callArgs,
|
|
@@ -17070,11 +17256,29 @@ async function readFieldCall(stmt, scope, ctx, ancestry) {
|
|
|
17070
17256
|
);
|
|
17071
17257
|
return {
|
|
17072
17258
|
fieldName: resolvedName(symbol2, callArgs, ctx.pattern),
|
|
17259
|
+
namedOnTheWire: true,
|
|
17073
17260
|
node: stmt,
|
|
17074
17261
|
contract: read.contract,
|
|
17075
17262
|
body: read.body
|
|
17076
17263
|
};
|
|
17077
17264
|
}
|
|
17265
|
+
function computedNameDeclaration(stmt, nameArg) {
|
|
17266
|
+
const range = rangeOf(stmt);
|
|
17267
|
+
return {
|
|
17268
|
+
fieldName: nameArg.text,
|
|
17269
|
+
namedOnTheWire: false,
|
|
17270
|
+
node: stmt,
|
|
17271
|
+
contract: null,
|
|
17272
|
+
body: {
|
|
17273
|
+
readings: [
|
|
17274
|
+
unreadableReading(
|
|
17275
|
+
`This field is named by ${nameArg.text}, which is worked out when the class body runs, so the name the schema exposes it under was not read here`,
|
|
17276
|
+
range
|
|
17277
|
+
)
|
|
17278
|
+
]
|
|
17279
|
+
}
|
|
17280
|
+
};
|
|
17281
|
+
}
|
|
17078
17282
|
function wiringReference(callArgs, wiringKeywords) {
|
|
17079
17283
|
for (const keyword of wiringKeywords) {
|
|
17080
17284
|
const ref = callArgs.keyword[keyword];
|
|
@@ -17199,7 +17403,10 @@ function readClassContract(ancestry, pattern) {
|
|
|
17199
17403
|
args: /* @__PURE__ */ new Map()
|
|
17200
17404
|
};
|
|
17201
17405
|
const handlers = classCallHandlers(pattern);
|
|
17202
|
-
for (const { block, statement } of inheritedStatements(
|
|
17406
|
+
for (const { block, statement } of inheritedStatements(
|
|
17407
|
+
ancestry,
|
|
17408
|
+
blockConfiguresCall(pattern)
|
|
17409
|
+
)) {
|
|
17203
17410
|
if (statement.type !== "call" || field(statement, "receiver") !== null) {
|
|
17204
17411
|
continue;
|
|
17205
17412
|
}
|
|
@@ -17290,12 +17497,12 @@ function buildFieldUnit(pack, typeName, decl, filePath) {
|
|
|
17290
17497
|
exportName: null,
|
|
17291
17498
|
exportPath: null
|
|
17292
17499
|
},
|
|
17293
|
-
boundaryBinding: graphqlResolverBinding({
|
|
17500
|
+
boundaryBinding: decl.namedOnTheWire ? graphqlResolverBinding({
|
|
17294
17501
|
transport: pack.protocol,
|
|
17295
17502
|
recognition: pack.name,
|
|
17296
17503
|
typeName,
|
|
17297
17504
|
fieldName: decl.fieldName
|
|
17298
|
-
}),
|
|
17505
|
+
}) : null,
|
|
17299
17506
|
parameters,
|
|
17300
17507
|
branches: branchesFor(decl.body, rangeOf(decl.node)),
|
|
17301
17508
|
...decl.body.bodyContent !== void 0 ? { bodyContent: decl.body.bodyContent } : {},
|
|
@@ -17366,14 +17573,6 @@ function nodeId(filePath, node) {
|
|
|
17366
17573
|
function nameId(filePath, name) {
|
|
17367
17574
|
return `${filePath}#${name}`;
|
|
17368
17575
|
}
|
|
17369
|
-
var DECLARATION_TYPES2 = /* @__PURE__ */ new Set([
|
|
17370
|
-
"method",
|
|
17371
|
-
"singleton_method",
|
|
17372
|
-
"lambda",
|
|
17373
|
-
"class",
|
|
17374
|
-
"module",
|
|
17375
|
-
"singleton_class"
|
|
17376
|
-
]);
|
|
17377
17576
|
var WRITTEN_VALUE_TYPES = /* @__PURE__ */ new Set([
|
|
17378
17577
|
"string",
|
|
17379
17578
|
"integer",
|
|
@@ -17511,7 +17710,7 @@ function emitHash(emitter, hash2) {
|
|
|
17511
17710
|
}
|
|
17512
17711
|
function walkExpressions(node, visit) {
|
|
17513
17712
|
for (const child of children3(node)) {
|
|
17514
|
-
if (
|
|
17713
|
+
if (OWN_BODY_TYPES.has(child.type)) {
|
|
17515
17714
|
continue;
|
|
17516
17715
|
}
|
|
17517
17716
|
visit(child);
|
|
@@ -17569,7 +17768,7 @@ function emitMethodFacts(emitter, method) {
|
|
|
17569
17768
|
}
|
|
17570
17769
|
const recordNested = (node) => {
|
|
17571
17770
|
for (const child of children3(node)) {
|
|
17572
|
-
if (
|
|
17771
|
+
if (OWN_BODY_TYPES.has(child.type)) {
|
|
17573
17772
|
add(emitter, "containsFn", funcKey, nodeId(emitter.filePath, child));
|
|
17574
17773
|
continue;
|
|
17575
17774
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-ruby",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruby language adapter for suss, parsing source with tree-sitter (WASM), resolving constant nesting with a lexical binder, and emitting raw extractions for the suss pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"typecheck": "tsc --noEmit"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@suss/behavioral-ir": "0.
|
|
51
|
-
"@suss/datalog": "0.
|
|
52
|
-
"@suss/extractor": "0.
|
|
50
|
+
"@suss/behavioral-ir": "0.21.1",
|
|
51
|
+
"@suss/datalog": "0.21.1",
|
|
52
|
+
"@suss/extractor": "0.21.1",
|
|
53
53
|
"web-tree-sitter": "^0.26.11"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|