@suss/adapter-ruby 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +175 -53
- package/dist/index.d.cts +43 -13
- package/dist/index.d.ts +43 -13
- package/dist/index.js +175 -54
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
inheritedStatements: () => inheritedStatements,
|
|
52
52
|
methodDefinitionsIn: () => methodDefinitionsIn,
|
|
53
53
|
methodInAncestry: () => methodInAncestry,
|
|
54
|
+
nestedStatements: () => nestedStatements,
|
|
54
55
|
nodeId: () => nodeId,
|
|
55
56
|
parseRuby: () => parseRuby,
|
|
56
57
|
parseRubySync: () => parseRubySync,
|
|
@@ -94,6 +95,45 @@ function field(node, name) {
|
|
|
94
95
|
function bodyStatements(body) {
|
|
95
96
|
return body.namedChildren.filter((child) => child !== null);
|
|
96
97
|
}
|
|
98
|
+
var BRANCH_FIELDS = {
|
|
99
|
+
if: ["consequence", "alternative"],
|
|
100
|
+
unless: ["consequence", "alternative"],
|
|
101
|
+
elsif: ["consequence", "alternative"],
|
|
102
|
+
if_modifier: ["body"],
|
|
103
|
+
unless_modifier: ["body"],
|
|
104
|
+
while: ["body"],
|
|
105
|
+
until: ["body"],
|
|
106
|
+
while_modifier: ["body"],
|
|
107
|
+
until_modifier: ["body"],
|
|
108
|
+
when: ["body"],
|
|
109
|
+
rescue: ["body"]
|
|
110
|
+
};
|
|
111
|
+
var STATEMENT_LISTS = /* @__PURE__ */ new Set(["then", "else", "do", "ensure", "begin"]);
|
|
112
|
+
var CLAUSE_TYPES = /* @__PURE__ */ new Set(["elsif", "else", "when", "rescue", "ensure"]);
|
|
113
|
+
function nestedStatements(stmt) {
|
|
114
|
+
const branchFields = BRANCH_FIELDS[stmt.type];
|
|
115
|
+
if (branchFields !== void 0) {
|
|
116
|
+
return branchFields.flatMap((name) => {
|
|
117
|
+
const branch = field(stmt, name);
|
|
118
|
+
return branch === null ? [] : statementsRunBy(branch);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (STATEMENT_LISTS.has(stmt.type)) {
|
|
122
|
+
return bodyStatements(stmt).flatMap(
|
|
123
|
+
(child) => CLAUSE_TYPES.has(child.type) ? nestedStatements(child) : [child]
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
if (stmt.type === "case") {
|
|
127
|
+
return bodyStatements(stmt).filter((child) => CLAUSE_TYPES.has(child.type)).flatMap(nestedStatements);
|
|
128
|
+
}
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
function statementsRunBy(branch) {
|
|
132
|
+
if (STATEMENT_LISTS.has(branch.type) || CLAUSE_TYPES.has(branch.type)) {
|
|
133
|
+
return nestedStatements(branch);
|
|
134
|
+
}
|
|
135
|
+
return [branch];
|
|
136
|
+
}
|
|
97
137
|
var OWN_BODY_TYPES = /* @__PURE__ */ new Set([
|
|
98
138
|
"method",
|
|
99
139
|
"singleton_method",
|
|
@@ -157,8 +197,8 @@ var VISIBILITY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
157
197
|
"protected",
|
|
158
198
|
"public"
|
|
159
199
|
]);
|
|
160
|
-
function visibilityKeyword(
|
|
161
|
-
return VISIBILITY_KEYWORDS.has(
|
|
200
|
+
function visibilityKeyword(text2) {
|
|
201
|
+
return VISIBILITY_KEYWORDS.has(text2) ? text2 : null;
|
|
162
202
|
}
|
|
163
203
|
function setVisibility(visibility, name, keyword) {
|
|
164
204
|
if (keyword === "public") {
|
|
@@ -281,14 +321,31 @@ var NodeMap = class extends import_extractor.IdMap {
|
|
|
281
321
|
// src/constantPath.ts
|
|
282
322
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
283
323
|
var import_node_path = __toESM(require("path"), 1);
|
|
284
|
-
function underscoreConstantPath(qualifiedName) {
|
|
285
|
-
return qualifiedName.replaceAll("::", "/").replace(/([A-Z\d]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replaceAll("-", "_").toLowerCase();
|
|
324
|
+
function underscoreConstantPath(qualifiedName, acronyms = []) {
|
|
325
|
+
return lowerAcronyms(qualifiedName.replaceAll("::", "/"), acronyms).replace(/([A-Z\d]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replaceAll("-", "_").toLowerCase();
|
|
326
|
+
}
|
|
327
|
+
function lowerAcronyms(word, acronyms) {
|
|
328
|
+
if (acronyms.length === 0) {
|
|
329
|
+
return word;
|
|
330
|
+
}
|
|
331
|
+
const alternatives = acronyms.map(escapeRegExp).join("|");
|
|
332
|
+
const acronymRegex = new RegExp(
|
|
333
|
+
`(?:(?<=([A-Za-z\\d]))|\\b)(${alternatives})(?=\\b|[^a-z])`,
|
|
334
|
+
"g"
|
|
335
|
+
);
|
|
336
|
+
return word.replace(
|
|
337
|
+
acronymRegex,
|
|
338
|
+
(_match, before, acronym) => `${before === void 0 ? "" : "_"}${acronym.toLowerCase()}`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
function escapeRegExp(text2) {
|
|
342
|
+
return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
286
343
|
}
|
|
287
344
|
var PATH_CONVENTIONS = {
|
|
288
345
|
railsUnderscore: underscoreConstantPath
|
|
289
346
|
};
|
|
290
|
-
function resolveConstantFile(root, qualifiedName, convention) {
|
|
291
|
-
const relative = `${PATH_CONVENTIONS[convention](qualifiedName)}.rb`;
|
|
347
|
+
function resolveConstantFile(root, qualifiedName, convention, acronyms = []) {
|
|
348
|
+
const relative = `${PATH_CONVENTIONS[convention](qualifiedName, acronyms)}.rb`;
|
|
292
349
|
for (const candidate of [root, ...autoloadDirectories(root)]) {
|
|
293
350
|
const file = import_node_path.default.join(candidate, relative);
|
|
294
351
|
if (import_node_fs.default.existsSync(file)) {
|
|
@@ -362,12 +419,19 @@ function walkBody(statements, nesting, visit) {
|
|
|
362
419
|
}
|
|
363
420
|
}
|
|
364
421
|
function ownIdentity(nameNode, outerNesting) {
|
|
365
|
-
const qualifiedName =
|
|
422
|
+
const qualifiedName = definedName(nameNode, outerNesting);
|
|
366
423
|
if (qualifiedName === null) {
|
|
367
424
|
return null;
|
|
368
425
|
}
|
|
369
426
|
return { qualifiedName, bodyNesting: [qualifiedName, ...outerNesting] };
|
|
370
427
|
}
|
|
428
|
+
function definedName(nameNode, outerNesting) {
|
|
429
|
+
const innermost = outerNesting[0] ?? null;
|
|
430
|
+
if (nameNode.type === "scope_resolution" && innermost !== null && !nameNode.text.startsWith("::")) {
|
|
431
|
+
return `${innermost}::${nameNode.text}`;
|
|
432
|
+
}
|
|
433
|
+
return qualifyConstantRef(nameNode, outerNesting);
|
|
434
|
+
}
|
|
371
435
|
function visitClass(node, nesting, visit) {
|
|
372
436
|
const nameNode = field(node, "name");
|
|
373
437
|
const identity = nameNode !== null ? ownIdentity(nameNode, nesting) : null;
|
|
@@ -431,7 +495,8 @@ async function reachDefinition(qualifiedName, lookup) {
|
|
|
431
495
|
const filePath = resolveConstantFile(
|
|
432
496
|
lookup.root,
|
|
433
497
|
qualifiedName,
|
|
434
|
-
lookup.pathConvention
|
|
498
|
+
lookup.pathConvention,
|
|
499
|
+
lookup.acronyms
|
|
435
500
|
);
|
|
436
501
|
if (filePath === null) {
|
|
437
502
|
return null;
|
|
@@ -473,7 +538,10 @@ async function chainOf(self, lookup, active) {
|
|
|
473
538
|
async function superclassChain(self, lookup, active) {
|
|
474
539
|
const candidates = superclassCandidatesOf(self.blocks);
|
|
475
540
|
for (const candidate of candidates) {
|
|
476
|
-
if (lookup.ancestryRootClassNames.includes(candidate)
|
|
541
|
+
if (lookup.ancestryRootClassNames.includes(candidate)) {
|
|
542
|
+
return [{ type: "root", name: candidate }];
|
|
543
|
+
}
|
|
544
|
+
if (active.has(candidate)) {
|
|
477
545
|
return [];
|
|
478
546
|
}
|
|
479
547
|
const blocks = await definitionOf(candidate, lookup);
|
|
@@ -551,6 +619,9 @@ function superclassCandidatesOf(blocks) {
|
|
|
551
619
|
}
|
|
552
620
|
function methodInAncestry(ancestry, name) {
|
|
553
621
|
for (const entry of ancestry) {
|
|
622
|
+
if (entry.type === "root") {
|
|
623
|
+
return { type: "none" };
|
|
624
|
+
}
|
|
554
625
|
if (entry.type === "unfollowed") {
|
|
555
626
|
return {
|
|
556
627
|
type: "unsettled",
|
|
@@ -2623,11 +2694,18 @@ function bindEvaluator(db, nodes) {
|
|
|
2623
2694
|
)
|
|
2624
2695
|
);
|
|
2625
2696
|
}
|
|
2626
|
-
function evaluatedValue(node, db) {
|
|
2627
|
-
|
|
2697
|
+
function evaluatedValue(node, db, bindings) {
|
|
2698
|
+
const evaluator = evaluatorFor(node, db);
|
|
2699
|
+
if (bindings === void 0) {
|
|
2700
|
+
return (0, import_values2.force)(evaluator.evaluate(node));
|
|
2701
|
+
}
|
|
2702
|
+
const supplied = new Map(
|
|
2703
|
+
[...bindings].map(([name, value]) => [name, (0, import_values2.text)(value)])
|
|
2704
|
+
);
|
|
2705
|
+
return (0, import_values2.force)(evaluator.evaluate(node, { bindings: supplied }));
|
|
2628
2706
|
}
|
|
2629
|
-
function stringValueOf(node, db) {
|
|
2630
|
-
return (0, import_values2.literalOf)(evaluatedValue(node, db));
|
|
2707
|
+
function stringValueOf(node, db, bindings) {
|
|
2708
|
+
return (0, import_values2.literalOf)(evaluatedValue(node, db, bindings));
|
|
2631
2709
|
}
|
|
2632
2710
|
function methodDefinitionsIn(file, root) {
|
|
2633
2711
|
const found = /* @__PURE__ */ new Map();
|
|
@@ -3288,8 +3366,7 @@ function controllerFilters(pattern, ancestry) {
|
|
|
3288
3366
|
skipNames.set(form.skippedBy, form.name);
|
|
3289
3367
|
}
|
|
3290
3368
|
}
|
|
3291
|
-
|
|
3292
|
-
const skips = [];
|
|
3369
|
+
let declared = [];
|
|
3293
3370
|
for (const { statement } of inheritedStatements(ancestry)) {
|
|
3294
3371
|
const called = calledName(statement);
|
|
3295
3372
|
if (called === null) {
|
|
@@ -3297,16 +3374,21 @@ function controllerFilters(pattern, ancestry) {
|
|
|
3297
3374
|
}
|
|
3298
3375
|
const form = byName.get(called);
|
|
3299
3376
|
if (form !== void 0) {
|
|
3300
|
-
|
|
3377
|
+
for (const declaration of declarationsOf(statement, form)) {
|
|
3378
|
+
declared = [
|
|
3379
|
+
...declared.filter((earlier) => !sameFilter(earlier, declaration)),
|
|
3380
|
+
declaration
|
|
3381
|
+
];
|
|
3382
|
+
}
|
|
3301
3383
|
continue;
|
|
3302
3384
|
}
|
|
3303
3385
|
const skipped = skipNames.get(called);
|
|
3304
3386
|
if (skipped !== void 0) {
|
|
3305
|
-
|
|
3387
|
+
declared = applySkips(declared, skipsOf(statement, skipped));
|
|
3306
3388
|
}
|
|
3307
3389
|
}
|
|
3308
3390
|
const resolved = [];
|
|
3309
|
-
for (const declaration of
|
|
3391
|
+
for (const declaration of declared) {
|
|
3310
3392
|
const found = methodInAncestry(ancestry, declaration.methodName);
|
|
3311
3393
|
if (found.type !== "found") {
|
|
3312
3394
|
continue;
|
|
@@ -3419,6 +3501,9 @@ function skipsOf(statement, filterName) {
|
|
|
3419
3501
|
const actions = namesUnder(args.keyword.only);
|
|
3420
3502
|
return args.positional.map((arg) => symbolValue(arg)).filter((name) => name !== null).map((methodName) => ({ filterName, methodName, actions }));
|
|
3421
3503
|
}
|
|
3504
|
+
function sameFilter(one, other) {
|
|
3505
|
+
return one.filter.name === other.filter.name && one.methodName === other.methodName;
|
|
3506
|
+
}
|
|
3422
3507
|
function applySkips(declared, skips) {
|
|
3423
3508
|
const left = [];
|
|
3424
3509
|
for (const declaration of declared) {
|
|
@@ -3542,7 +3627,7 @@ function storageEffect(call, model, pattern, kind, selector) {
|
|
|
3542
3627
|
binding: (0, import_ir_core.storageBinding)({
|
|
3543
3628
|
recognition: "ruby-storage",
|
|
3544
3629
|
storageSystem: pattern.storageSystem,
|
|
3545
|
-
scope:
|
|
3630
|
+
scope: "default",
|
|
3546
3631
|
container: constantName(model)
|
|
3547
3632
|
}),
|
|
3548
3633
|
callee: call.text,
|
|
@@ -3710,6 +3795,7 @@ function fieldReadContext(pattern, cache, fileBlocks, bodyRead) {
|
|
|
3710
3795
|
lookup: {
|
|
3711
3796
|
root: pattern.root,
|
|
3712
3797
|
pathConvention: pattern.pathConvention,
|
|
3798
|
+
acronyms: pattern.acronyms ?? [],
|
|
3713
3799
|
ancestryRootClassNames: pattern.ancestryRootClassNames,
|
|
3714
3800
|
parsedFile: (absPath) => cache.get(absPath),
|
|
3715
3801
|
localDefinition: (name) => sameFileBlocks(name, fileBlocks)
|
|
@@ -3824,12 +3910,16 @@ async function controllerActionUnits(pattern, pack, info, ownBlocks, fileBlocks,
|
|
|
3824
3910
|
const lookup = {
|
|
3825
3911
|
root: pattern.root,
|
|
3826
3912
|
pathConvention: pattern.pathConvention,
|
|
3913
|
+
acronyms: pattern.acronyms ?? [],
|
|
3827
3914
|
ancestryRootClassNames: pattern.ancestryRootClassNames,
|
|
3828
3915
|
parsedFile: (absPath) => options.cache.get(absPath),
|
|
3829
3916
|
localDefinition: (name) => sameFileBlocks(name, fileBlocks)
|
|
3830
3917
|
};
|
|
3831
3918
|
const ancestry = await ancestryOf(info.qualifiedName, ownBlocks, lookup);
|
|
3832
|
-
if (!reachesConfiguredBase(ancestry, info.qualifiedName,
|
|
3919
|
+
if (!reachesConfiguredBase(ancestry, info.qualifiedName, [
|
|
3920
|
+
...pattern.baseClassNames,
|
|
3921
|
+
...pattern.ancestryRootClassNames
|
|
3922
|
+
])) {
|
|
3833
3923
|
return [];
|
|
3834
3924
|
}
|
|
3835
3925
|
const filters = controllerFilters(pattern, ancestry);
|
|
@@ -3849,43 +3939,73 @@ async function controllerActionUnits(pattern, pack, info, ownBlocks, fileBlocks,
|
|
|
3849
3939
|
enclosingQualifiedName: filter.enclosingQualifiedName
|
|
3850
3940
|
});
|
|
3851
3941
|
}
|
|
3852
|
-
|
|
3853
|
-
|
|
3942
|
+
const emitAction = (actionName, method, block) => {
|
|
3943
|
+
const around = filters.filter((filter) => filterCoversAction(filter, actionName)).map(
|
|
3944
|
+
(filter) => filterReference(
|
|
3945
|
+
filter,
|
|
3946
|
+
options.displayPathOf?.(filter.file) ?? filter.file
|
|
3947
|
+
)
|
|
3948
|
+
);
|
|
3949
|
+
const raw = buildControllerActionUnit(
|
|
3950
|
+
pack,
|
|
3951
|
+
pattern,
|
|
3952
|
+
info.qualifiedName,
|
|
3953
|
+
actionName,
|
|
3954
|
+
method,
|
|
3955
|
+
{
|
|
3956
|
+
display: block.file === (options.absoluteFile ?? options.filePath) ? options.filePath : options.displayPathOf?.(block.file) ?? block.file,
|
|
3957
|
+
absolute: block.file
|
|
3958
|
+
},
|
|
3959
|
+
options,
|
|
3960
|
+
around
|
|
3961
|
+
);
|
|
3962
|
+
units.push(raw);
|
|
3963
|
+
options.onReachSeed?.(raw, {
|
|
3964
|
+
file: block.file,
|
|
3965
|
+
node: method,
|
|
3966
|
+
enclosingQualifiedName: block.info.qualifiedName
|
|
3967
|
+
});
|
|
3968
|
+
};
|
|
3969
|
+
const own = /* @__PURE__ */ new Set();
|
|
3970
|
+
for (const [actionName, method, block] of publicInstanceMethods(ownBlocks)) {
|
|
3971
|
+
own.add(actionName);
|
|
3972
|
+
emitAction(actionName, method, block);
|
|
3973
|
+
}
|
|
3974
|
+
const seen = new Set(own);
|
|
3975
|
+
for (const entry of ancestry) {
|
|
3976
|
+
if (entry.type !== "bodies" || entry.name === info.qualifiedName) {
|
|
3854
3977
|
continue;
|
|
3855
3978
|
}
|
|
3856
|
-
const
|
|
3857
|
-
|
|
3858
|
-
block.info.bodyNode
|
|
3979
|
+
for (const [actionName, method, block] of publicInstanceMethods(
|
|
3980
|
+
entry.blocks
|
|
3859
3981
|
)) {
|
|
3860
|
-
if (
|
|
3982
|
+
if (seen.has(actionName)) {
|
|
3861
3983
|
continue;
|
|
3862
3984
|
}
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
);
|
|
3869
|
-
const raw = buildControllerActionUnit(
|
|
3870
|
-
pack,
|
|
3871
|
-
pattern,
|
|
3872
|
-
info.qualifiedName,
|
|
3873
|
-
actionName,
|
|
3874
|
-
method,
|
|
3875
|
-
{ display: options.filePath, absolute: block.file },
|
|
3876
|
-
options,
|
|
3877
|
-
around
|
|
3878
|
-
);
|
|
3879
|
-
units.push(raw);
|
|
3880
|
-
options.onReachSeed?.(raw, {
|
|
3881
|
-
file: block.file,
|
|
3882
|
-
node: method,
|
|
3883
|
-
enclosingQualifiedName: info.qualifiedName
|
|
3884
|
-
});
|
|
3985
|
+
seen.add(actionName);
|
|
3986
|
+
if (pattern.routeFor(info.qualifiedName, actionName) === null) {
|
|
3987
|
+
continue;
|
|
3988
|
+
}
|
|
3989
|
+
emitAction(actionName, method, block);
|
|
3885
3990
|
}
|
|
3886
3991
|
}
|
|
3887
3992
|
return units;
|
|
3888
3993
|
}
|
|
3994
|
+
function publicInstanceMethods(blocks) {
|
|
3995
|
+
const found = [];
|
|
3996
|
+
for (const block of blocks) {
|
|
3997
|
+
if (block.info.bodyNode === null) {
|
|
3998
|
+
continue;
|
|
3999
|
+
}
|
|
4000
|
+
const visibility = instanceMethodVisibility(block.info.bodyNode);
|
|
4001
|
+
for (const [name, method] of instanceMethodsByName(block.info.bodyNode)) {
|
|
4002
|
+
if ((visibility.get(name) ?? "public") === "public") {
|
|
4003
|
+
found.push([name, method, block]);
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
return found;
|
|
4008
|
+
}
|
|
3889
4009
|
function buildControllerActionUnit(pack, pattern, controllerQualifiedName, actionName, method, file, bodyRead, wrappers = []) {
|
|
3890
4010
|
const range = rangeOf(method);
|
|
3891
4011
|
const route = pattern.routeFor(controllerQualifiedName, actionName);
|
|
@@ -5109,7 +5229,8 @@ function inheritedMethodsIn(packs) {
|
|
|
5109
5229
|
return found;
|
|
5110
5230
|
}
|
|
5111
5231
|
function alreadyDiscovered(seen, raw) {
|
|
5112
|
-
const
|
|
5232
|
+
const reported = raw.identity.exportPath?.join(".") ?? raw.identity.name;
|
|
5233
|
+
const key = `${raw.identity.file}::${reported}::${raw.identity.range.start}`;
|
|
5113
5234
|
if (seen.has(key)) {
|
|
5114
5235
|
return true;
|
|
5115
5236
|
}
|
|
@@ -5408,8 +5529,8 @@ function displayNameOf(node) {
|
|
|
5408
5529
|
if (node.type === "class" || node.type === "module") {
|
|
5409
5530
|
return field(node, "name")?.text ?? node.text;
|
|
5410
5531
|
}
|
|
5411
|
-
const
|
|
5412
|
-
return
|
|
5532
|
+
const text2 = node.text.split("\n")[0].trim();
|
|
5533
|
+
return text2.length > 40 ? `${text2.slice(0, 40)}...` : text2;
|
|
5413
5534
|
}
|
|
5414
5535
|
function width(node) {
|
|
5415
5536
|
return node.endIndex - node.startIndex;
|
|
@@ -5436,14 +5557,14 @@ var RubyWhySession = class {
|
|
|
5436
5557
|
* The smallest expression on `line` of `file` whose text is exactly
|
|
5437
5558
|
* `text`, or null.
|
|
5438
5559
|
*/
|
|
5439
|
-
findExpression(file, line,
|
|
5560
|
+
findExpression(file, line, text2) {
|
|
5440
5561
|
const root = this.rootOf(file);
|
|
5441
5562
|
if (root === null) {
|
|
5442
5563
|
return null;
|
|
5443
5564
|
}
|
|
5444
5565
|
let found = null;
|
|
5445
5566
|
const visit = (node) => {
|
|
5446
|
-
if (node.startPosition.row + 1 === line && node.text ===
|
|
5567
|
+
if (node.startPosition.row + 1 === line && node.text === text2) {
|
|
5447
5568
|
if (found === null || width(node) <= width(found)) {
|
|
5448
5569
|
found = node;
|
|
5449
5570
|
}
|
|
@@ -5614,6 +5735,7 @@ async function rubyStubEvidence(options) {
|
|
|
5614
5735
|
inheritedStatements,
|
|
5615
5736
|
methodDefinitionsIn,
|
|
5616
5737
|
methodInAncestry,
|
|
5738
|
+
nestedStatements,
|
|
5617
5739
|
nodeId,
|
|
5618
5740
|
parseRuby,
|
|
5619
5741
|
parseRubySync,
|
package/dist/index.d.cts
CHANGED
|
@@ -31,6 +31,13 @@ interface Range {
|
|
|
31
31
|
}
|
|
32
32
|
declare function field(node: Node, name: string): Node | null;
|
|
33
33
|
declare function bodyStatements(body: Node): Node[];
|
|
34
|
+
/**
|
|
35
|
+
* Every statement written directly inside a branching statement's
|
|
36
|
+
* branches, across its `elsif`, `else`, `when`, `rescue` and `ensure`
|
|
37
|
+
* clauses. A statement inside a nested branching statement is not
|
|
38
|
+
* included; the caller descends into that one itself.
|
|
39
|
+
*/
|
|
40
|
+
declare function nestedStatements(stmt: Node): Node[];
|
|
34
41
|
/** A call whose block is the thing being configured rather than a place statements run. */
|
|
35
42
|
type BlockConfigures = (call: Node) => boolean;
|
|
36
43
|
/**
|
|
@@ -68,8 +75,14 @@ declare function readCallArgs(argumentList: Node | null): CallArgs;
|
|
|
68
75
|
*/
|
|
69
76
|
/** A pack picks a convention by name, and the code for each one lives here. */
|
|
70
77
|
type ConstantPathConvention = "railsUnderscore";
|
|
71
|
-
/**
|
|
72
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Ported from ActiveSupport's own `String#underscore`, which is what
|
|
80
|
+
* Rails autoloading runs a constant path through. An acronym the
|
|
81
|
+
* project registers with the inflector is one word to it, so with
|
|
82
|
+
* `ActivityPub` registered the path is `activitypub`, not
|
|
83
|
+
* `activity_pub`.
|
|
84
|
+
*/
|
|
85
|
+
declare function underscoreConstantPath(qualifiedName: string, acronyms?: readonly string[]): string;
|
|
73
86
|
/**
|
|
74
87
|
* Null when there is no file at that path. Rails autoloads from every
|
|
75
88
|
* directory directly under `app`, so `ApplicationController` is
|
|
@@ -77,14 +90,14 @@ declare function underscoreConstantPath(qualifiedName: string): string;
|
|
|
77
90
|
* `app/application_controller.rb`; those directories are tried after
|
|
78
91
|
* the root itself, in name order, and no other spelling is tried.
|
|
79
92
|
*/
|
|
80
|
-
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention): string | null;
|
|
93
|
+
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention, acronyms?: readonly string[]): string | null;
|
|
81
94
|
|
|
82
95
|
/**
|
|
83
96
|
* Resolves Ruby constant paths against lexical nesting.
|
|
84
97
|
*
|
|
85
|
-
* A compound path
|
|
86
|
-
*
|
|
87
|
-
*
|
|
98
|
+
* A compound path referenced, like `Data::Record`, is read as absolute. A
|
|
99
|
+
* bare name is relative to the nesting it is written inside, and so is a
|
|
100
|
+
* compound name `class` or `module` opens. `require` is never resolved,
|
|
88
101
|
* because Rails autoloads by naming convention rather than through a load graph
|
|
89
102
|
* a static reader could follow, so a constant that nesting alone cannot qualify
|
|
90
103
|
* keeps whatever name the source wrote and callers treat it as unresolved.
|
|
@@ -141,7 +154,13 @@ interface ReachedBody {
|
|
|
141
154
|
/** Absolute path of the file the block is written in. */
|
|
142
155
|
file: string;
|
|
143
156
|
}
|
|
144
|
-
/**
|
|
157
|
+
/**
|
|
158
|
+
* One ancestor: every block reopening its name, the name alone when
|
|
159
|
+
* nothing reached it, or the library's own class the walk stopped at.
|
|
160
|
+
* Blocks stay together because Ruby treats a reopened class as one
|
|
161
|
+
* place in the chain. The root is kept by name so a caller can tell a
|
|
162
|
+
* chain that ended at the library from one that ended at nothing.
|
|
163
|
+
*/
|
|
145
164
|
type AncestorEntry = {
|
|
146
165
|
type: "bodies";
|
|
147
166
|
name: string;
|
|
@@ -149,6 +168,9 @@ type AncestorEntry = {
|
|
|
149
168
|
} | {
|
|
150
169
|
type: "unfollowed";
|
|
151
170
|
name: string;
|
|
171
|
+
} | {
|
|
172
|
+
type: "root";
|
|
173
|
+
name: string;
|
|
152
174
|
};
|
|
153
175
|
/** A class and everything it inherits from, in Ruby's own method-lookup order. */
|
|
154
176
|
type Ancestry = readonly AncestorEntry[];
|
|
@@ -157,6 +179,8 @@ interface AncestorLookup {
|
|
|
157
179
|
/** Directory the constant-to-path convention resolves an ancestor's name against. */
|
|
158
180
|
root: string;
|
|
159
181
|
pathConvention: ConstantPathConvention;
|
|
182
|
+
/** Acronyms the convention keeps as one word, `ActivityPub` to `activitypub`. */
|
|
183
|
+
acronyms?: readonly string[];
|
|
160
184
|
/**
|
|
161
185
|
* The library's own classes a project's chain ends at. Reaching one
|
|
162
186
|
* ends a walk with nothing left unfollowed.
|
|
@@ -324,15 +348,17 @@ interface RbLoaderPattern {
|
|
|
324
348
|
shortcuts: string[];
|
|
325
349
|
}
|
|
326
350
|
type RubyDiscoveryPattern = GraphqlObjectFields | ControllerActions;
|
|
327
|
-
/** A class whose ancestry reaches one of `baseClassNames` is a controller, and every instance method it defines directly is one of its actions, bound by `routeFor` to the method and path a project's own routing gives it, or discovered with no boundary binding when `routeFor` finds none. */
|
|
351
|
+
/** A class whose ancestry reaches one of `baseClassNames` or `ancestryRootClassNames` is a controller, and every instance method it defines directly is one of its actions, bound by `routeFor` to the method and path a project's own routing gives it, or discovered with no boundary binding when `routeFor` finds none. */
|
|
328
352
|
interface ControllerActions {
|
|
329
353
|
type: "controllerActions";
|
|
330
|
-
/**
|
|
354
|
+
/** A base a project's controllers extend, `ApplicationController` say. The base itself is not a controller. */
|
|
331
355
|
baseClassNames: string[];
|
|
332
356
|
/** The directory a bare superclass name is looked up under, the project's own layout. */
|
|
333
357
|
root: string;
|
|
334
358
|
pathConvention: ConstantPathConvention;
|
|
335
|
-
/**
|
|
359
|
+
/** Acronyms the project registers with the inflector, which the path convention keeps as one word: `ActivityPub` is `activitypub`, not `activity_pub`. */
|
|
360
|
+
acronyms?: string[];
|
|
361
|
+
/** The library's own classes a project's controller chain ends at. A class extending one directly is a controller too. */
|
|
336
362
|
ancestryRootClassNames: string[];
|
|
337
363
|
/** Status code a wire response gets when the action does not say otherwise. */
|
|
338
364
|
defaultStatusCode: number;
|
|
@@ -412,6 +438,8 @@ interface GraphqlObjectFields {
|
|
|
412
438
|
/** The directory a wiring keyword's referenced class is looked up under. That is the project's own layout, not the library's. */
|
|
413
439
|
root: string;
|
|
414
440
|
pathConvention: ConstantPathConvention;
|
|
441
|
+
/** Acronyms the project registers with the inflector, which the path convention keeps as one word. */
|
|
442
|
+
acronyms?: string[];
|
|
415
443
|
/** The DSL call declaring one schema field in an object type's body. */
|
|
416
444
|
fieldCallName: string;
|
|
417
445
|
/** The DSL call declaring a referenced class's own return type. */
|
|
@@ -754,10 +782,12 @@ interface ProjectNodes {
|
|
|
754
782
|
}
|
|
755
783
|
/** Register the parsed project, so reads through `db` can follow the facts back to nodes. */
|
|
756
784
|
declare function bindEvaluator(db: Database, nodes: ProjectNodes): void;
|
|
785
|
+
/** Strings to read for the parameters of the block or method `node` is written in, the way a caller would supply them. */
|
|
786
|
+
type ParameterBindings = ReadonlyMap<string, string>;
|
|
757
787
|
/** The abstract value `node` comes down to, through the facts when `db` was bound. */
|
|
758
|
-
declare function evaluatedValue(node: Node, db?: Database): Value;
|
|
788
|
+
declare function evaluatedValue(node: Node, db?: Database, bindings?: ParameterBindings): Value;
|
|
759
789
|
/** The one string `node` comes down to, or null when it does not settle on one. */
|
|
760
|
-
declare function stringValueOf(node: Node, db?: Database): string | null;
|
|
790
|
+
declare function stringValueOf(node: Node, db?: Database, bindings?: ParameterBindings): string | null;
|
|
761
791
|
/** Every method a file defines, keyed the way the facts key it, for `bindEvaluator`. */
|
|
762
792
|
declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node>;
|
|
763
793
|
|
|
@@ -771,4 +801,4 @@ declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node
|
|
|
771
801
|
*/
|
|
772
802
|
declare const ADAPTER_VERSION = "0.1.0";
|
|
773
803
|
|
|
774
|
-
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type GraphqlObjectFields, type GraphqlTypeNameConvention, type MethodLookup, type ProjectNodes, type Range, type RbStatusCall, type RbStoragePattern, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createFileCache, discoverUnits, emitConstantBindings, emitEntryFact, emitValueFacts, evaluatedValue, extractRubyProject, field, findRubyFiles, graphqlTypeNameFromQualified, hashKeySymbolName, inheritedStatements, methodDefinitionsIn, methodInAncestry, nodeId, parseRuby, parseRubySync, preloadRubyGrammar, qualifyConstantRef, reachDefinition, readCallArgs, readKey, resolveConstantFile, rubyStubEvidence, runStatements, stringLiteralValue, stringValueOf, symbolValue, typeShapeFromNode, underscoreConstantPath, unitKey, walkClasses, walkDefinitions };
|
|
804
|
+
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type GraphqlObjectFields, type GraphqlTypeNameConvention, type MethodLookup, type ParameterBindings, type ProjectNodes, type Range, type RbStatusCall, type RbStoragePattern, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createFileCache, discoverUnits, emitConstantBindings, emitEntryFact, emitValueFacts, evaluatedValue, extractRubyProject, field, findRubyFiles, graphqlTypeNameFromQualified, hashKeySymbolName, inheritedStatements, methodDefinitionsIn, methodInAncestry, nestedStatements, nodeId, parseRuby, parseRubySync, preloadRubyGrammar, qualifyConstantRef, reachDefinition, readCallArgs, readKey, resolveConstantFile, rubyStubEvidence, runStatements, stringLiteralValue, stringValueOf, symbolValue, typeShapeFromNode, underscoreConstantPath, unitKey, walkClasses, walkDefinitions };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,13 @@ interface Range {
|
|
|
31
31
|
}
|
|
32
32
|
declare function field(node: Node, name: string): Node | null;
|
|
33
33
|
declare function bodyStatements(body: Node): Node[];
|
|
34
|
+
/**
|
|
35
|
+
* Every statement written directly inside a branching statement's
|
|
36
|
+
* branches, across its `elsif`, `else`, `when`, `rescue` and `ensure`
|
|
37
|
+
* clauses. A statement inside a nested branching statement is not
|
|
38
|
+
* included; the caller descends into that one itself.
|
|
39
|
+
*/
|
|
40
|
+
declare function nestedStatements(stmt: Node): Node[];
|
|
34
41
|
/** A call whose block is the thing being configured rather than a place statements run. */
|
|
35
42
|
type BlockConfigures = (call: Node) => boolean;
|
|
36
43
|
/**
|
|
@@ -68,8 +75,14 @@ declare function readCallArgs(argumentList: Node | null): CallArgs;
|
|
|
68
75
|
*/
|
|
69
76
|
/** A pack picks a convention by name, and the code for each one lives here. */
|
|
70
77
|
type ConstantPathConvention = "railsUnderscore";
|
|
71
|
-
/**
|
|
72
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Ported from ActiveSupport's own `String#underscore`, which is what
|
|
80
|
+
* Rails autoloading runs a constant path through. An acronym the
|
|
81
|
+
* project registers with the inflector is one word to it, so with
|
|
82
|
+
* `ActivityPub` registered the path is `activitypub`, not
|
|
83
|
+
* `activity_pub`.
|
|
84
|
+
*/
|
|
85
|
+
declare function underscoreConstantPath(qualifiedName: string, acronyms?: readonly string[]): string;
|
|
73
86
|
/**
|
|
74
87
|
* Null when there is no file at that path. Rails autoloads from every
|
|
75
88
|
* directory directly under `app`, so `ApplicationController` is
|
|
@@ -77,14 +90,14 @@ declare function underscoreConstantPath(qualifiedName: string): string;
|
|
|
77
90
|
* `app/application_controller.rb`; those directories are tried after
|
|
78
91
|
* the root itself, in name order, and no other spelling is tried.
|
|
79
92
|
*/
|
|
80
|
-
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention): string | null;
|
|
93
|
+
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention, acronyms?: readonly string[]): string | null;
|
|
81
94
|
|
|
82
95
|
/**
|
|
83
96
|
* Resolves Ruby constant paths against lexical nesting.
|
|
84
97
|
*
|
|
85
|
-
* A compound path
|
|
86
|
-
*
|
|
87
|
-
*
|
|
98
|
+
* A compound path referenced, like `Data::Record`, is read as absolute. A
|
|
99
|
+
* bare name is relative to the nesting it is written inside, and so is a
|
|
100
|
+
* compound name `class` or `module` opens. `require` is never resolved,
|
|
88
101
|
* because Rails autoloads by naming convention rather than through a load graph
|
|
89
102
|
* a static reader could follow, so a constant that nesting alone cannot qualify
|
|
90
103
|
* keeps whatever name the source wrote and callers treat it as unresolved.
|
|
@@ -141,7 +154,13 @@ interface ReachedBody {
|
|
|
141
154
|
/** Absolute path of the file the block is written in. */
|
|
142
155
|
file: string;
|
|
143
156
|
}
|
|
144
|
-
/**
|
|
157
|
+
/**
|
|
158
|
+
* One ancestor: every block reopening its name, the name alone when
|
|
159
|
+
* nothing reached it, or the library's own class the walk stopped at.
|
|
160
|
+
* Blocks stay together because Ruby treats a reopened class as one
|
|
161
|
+
* place in the chain. The root is kept by name so a caller can tell a
|
|
162
|
+
* chain that ended at the library from one that ended at nothing.
|
|
163
|
+
*/
|
|
145
164
|
type AncestorEntry = {
|
|
146
165
|
type: "bodies";
|
|
147
166
|
name: string;
|
|
@@ -149,6 +168,9 @@ type AncestorEntry = {
|
|
|
149
168
|
} | {
|
|
150
169
|
type: "unfollowed";
|
|
151
170
|
name: string;
|
|
171
|
+
} | {
|
|
172
|
+
type: "root";
|
|
173
|
+
name: string;
|
|
152
174
|
};
|
|
153
175
|
/** A class and everything it inherits from, in Ruby's own method-lookup order. */
|
|
154
176
|
type Ancestry = readonly AncestorEntry[];
|
|
@@ -157,6 +179,8 @@ interface AncestorLookup {
|
|
|
157
179
|
/** Directory the constant-to-path convention resolves an ancestor's name against. */
|
|
158
180
|
root: string;
|
|
159
181
|
pathConvention: ConstantPathConvention;
|
|
182
|
+
/** Acronyms the convention keeps as one word, `ActivityPub` to `activitypub`. */
|
|
183
|
+
acronyms?: readonly string[];
|
|
160
184
|
/**
|
|
161
185
|
* The library's own classes a project's chain ends at. Reaching one
|
|
162
186
|
* ends a walk with nothing left unfollowed.
|
|
@@ -324,15 +348,17 @@ interface RbLoaderPattern {
|
|
|
324
348
|
shortcuts: string[];
|
|
325
349
|
}
|
|
326
350
|
type RubyDiscoveryPattern = GraphqlObjectFields | ControllerActions;
|
|
327
|
-
/** A class whose ancestry reaches one of `baseClassNames` is a controller, and every instance method it defines directly is one of its actions, bound by `routeFor` to the method and path a project's own routing gives it, or discovered with no boundary binding when `routeFor` finds none. */
|
|
351
|
+
/** A class whose ancestry reaches one of `baseClassNames` or `ancestryRootClassNames` is a controller, and every instance method it defines directly is one of its actions, bound by `routeFor` to the method and path a project's own routing gives it, or discovered with no boundary binding when `routeFor` finds none. */
|
|
328
352
|
interface ControllerActions {
|
|
329
353
|
type: "controllerActions";
|
|
330
|
-
/**
|
|
354
|
+
/** A base a project's controllers extend, `ApplicationController` say. The base itself is not a controller. */
|
|
331
355
|
baseClassNames: string[];
|
|
332
356
|
/** The directory a bare superclass name is looked up under, the project's own layout. */
|
|
333
357
|
root: string;
|
|
334
358
|
pathConvention: ConstantPathConvention;
|
|
335
|
-
/**
|
|
359
|
+
/** Acronyms the project registers with the inflector, which the path convention keeps as one word: `ActivityPub` is `activitypub`, not `activity_pub`. */
|
|
360
|
+
acronyms?: string[];
|
|
361
|
+
/** The library's own classes a project's controller chain ends at. A class extending one directly is a controller too. */
|
|
336
362
|
ancestryRootClassNames: string[];
|
|
337
363
|
/** Status code a wire response gets when the action does not say otherwise. */
|
|
338
364
|
defaultStatusCode: number;
|
|
@@ -412,6 +438,8 @@ interface GraphqlObjectFields {
|
|
|
412
438
|
/** The directory a wiring keyword's referenced class is looked up under. That is the project's own layout, not the library's. */
|
|
413
439
|
root: string;
|
|
414
440
|
pathConvention: ConstantPathConvention;
|
|
441
|
+
/** Acronyms the project registers with the inflector, which the path convention keeps as one word. */
|
|
442
|
+
acronyms?: string[];
|
|
415
443
|
/** The DSL call declaring one schema field in an object type's body. */
|
|
416
444
|
fieldCallName: string;
|
|
417
445
|
/** The DSL call declaring a referenced class's own return type. */
|
|
@@ -754,10 +782,12 @@ interface ProjectNodes {
|
|
|
754
782
|
}
|
|
755
783
|
/** Register the parsed project, so reads through `db` can follow the facts back to nodes. */
|
|
756
784
|
declare function bindEvaluator(db: Database, nodes: ProjectNodes): void;
|
|
785
|
+
/** Strings to read for the parameters of the block or method `node` is written in, the way a caller would supply them. */
|
|
786
|
+
type ParameterBindings = ReadonlyMap<string, string>;
|
|
757
787
|
/** The abstract value `node` comes down to, through the facts when `db` was bound. */
|
|
758
|
-
declare function evaluatedValue(node: Node, db?: Database): Value;
|
|
788
|
+
declare function evaluatedValue(node: Node, db?: Database, bindings?: ParameterBindings): Value;
|
|
759
789
|
/** The one string `node` comes down to, or null when it does not settle on one. */
|
|
760
|
-
declare function stringValueOf(node: Node, db?: Database): string | null;
|
|
790
|
+
declare function stringValueOf(node: Node, db?: Database, bindings?: ParameterBindings): string | null;
|
|
761
791
|
/** Every method a file defines, keyed the way the facts key it, for `bindEvaluator`. */
|
|
762
792
|
declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node>;
|
|
763
793
|
|
|
@@ -771,4 +801,4 @@ declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node
|
|
|
771
801
|
*/
|
|
772
802
|
declare const ADAPTER_VERSION = "0.1.0";
|
|
773
803
|
|
|
774
|
-
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type GraphqlObjectFields, type GraphqlTypeNameConvention, type MethodLookup, type ProjectNodes, type Range, type RbStatusCall, type RbStoragePattern, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createFileCache, discoverUnits, emitConstantBindings, emitEntryFact, emitValueFacts, evaluatedValue, extractRubyProject, field, findRubyFiles, graphqlTypeNameFromQualified, hashKeySymbolName, inheritedStatements, methodDefinitionsIn, methodInAncestry, nodeId, parseRuby, parseRubySync, preloadRubyGrammar, qualifyConstantRef, reachDefinition, readCallArgs, readKey, resolveConstantFile, rubyStubEvidence, runStatements, stringLiteralValue, stringValueOf, symbolValue, typeShapeFromNode, underscoreConstantPath, unitKey, walkClasses, walkDefinitions };
|
|
804
|
+
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type GraphqlObjectFields, type GraphqlTypeNameConvention, type MethodLookup, type ParameterBindings, type ProjectNodes, type Range, type RbStatusCall, type RbStoragePattern, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createFileCache, discoverUnits, emitConstantBindings, emitEntryFact, emitValueFacts, evaluatedValue, extractRubyProject, field, findRubyFiles, graphqlTypeNameFromQualified, hashKeySymbolName, inheritedStatements, methodDefinitionsIn, methodInAncestry, nestedStatements, nodeId, parseRuby, parseRubySync, preloadRubyGrammar, qualifyConstantRef, reachDefinition, readCallArgs, readKey, resolveConstantFile, rubyStubEvidence, runStatements, stringLiteralValue, stringValueOf, symbolValue, typeShapeFromNode, underscoreConstantPath, unitKey, walkClasses, walkDefinitions };
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,45 @@ function field(node, name) {
|
|
|
15
15
|
function bodyStatements(body) {
|
|
16
16
|
return body.namedChildren.filter((child) => child !== null);
|
|
17
17
|
}
|
|
18
|
+
var BRANCH_FIELDS = {
|
|
19
|
+
if: ["consequence", "alternative"],
|
|
20
|
+
unless: ["consequence", "alternative"],
|
|
21
|
+
elsif: ["consequence", "alternative"],
|
|
22
|
+
if_modifier: ["body"],
|
|
23
|
+
unless_modifier: ["body"],
|
|
24
|
+
while: ["body"],
|
|
25
|
+
until: ["body"],
|
|
26
|
+
while_modifier: ["body"],
|
|
27
|
+
until_modifier: ["body"],
|
|
28
|
+
when: ["body"],
|
|
29
|
+
rescue: ["body"]
|
|
30
|
+
};
|
|
31
|
+
var STATEMENT_LISTS = /* @__PURE__ */ new Set(["then", "else", "do", "ensure", "begin"]);
|
|
32
|
+
var CLAUSE_TYPES = /* @__PURE__ */ new Set(["elsif", "else", "when", "rescue", "ensure"]);
|
|
33
|
+
function nestedStatements(stmt) {
|
|
34
|
+
const branchFields = BRANCH_FIELDS[stmt.type];
|
|
35
|
+
if (branchFields !== void 0) {
|
|
36
|
+
return branchFields.flatMap((name) => {
|
|
37
|
+
const branch = field(stmt, name);
|
|
38
|
+
return branch === null ? [] : statementsRunBy(branch);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (STATEMENT_LISTS.has(stmt.type)) {
|
|
42
|
+
return bodyStatements(stmt).flatMap(
|
|
43
|
+
(child) => CLAUSE_TYPES.has(child.type) ? nestedStatements(child) : [child]
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (stmt.type === "case") {
|
|
47
|
+
return bodyStatements(stmt).filter((child) => CLAUSE_TYPES.has(child.type)).flatMap(nestedStatements);
|
|
48
|
+
}
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
function statementsRunBy(branch) {
|
|
52
|
+
if (STATEMENT_LISTS.has(branch.type) || CLAUSE_TYPES.has(branch.type)) {
|
|
53
|
+
return nestedStatements(branch);
|
|
54
|
+
}
|
|
55
|
+
return [branch];
|
|
56
|
+
}
|
|
18
57
|
var OWN_BODY_TYPES = /* @__PURE__ */ new Set([
|
|
19
58
|
"method",
|
|
20
59
|
"singleton_method",
|
|
@@ -78,8 +117,8 @@ var VISIBILITY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
78
117
|
"protected",
|
|
79
118
|
"public"
|
|
80
119
|
]);
|
|
81
|
-
function visibilityKeyword(
|
|
82
|
-
return VISIBILITY_KEYWORDS.has(
|
|
120
|
+
function visibilityKeyword(text2) {
|
|
121
|
+
return VISIBILITY_KEYWORDS.has(text2) ? text2 : null;
|
|
83
122
|
}
|
|
84
123
|
function setVisibility(visibility, name, keyword) {
|
|
85
124
|
if (keyword === "public") {
|
|
@@ -202,14 +241,31 @@ var NodeMap = class extends IdMap {
|
|
|
202
241
|
// src/constantPath.ts
|
|
203
242
|
import fs from "fs";
|
|
204
243
|
import path from "path";
|
|
205
|
-
function underscoreConstantPath(qualifiedName) {
|
|
206
|
-
return qualifiedName.replaceAll("::", "/").replace(/([A-Z\d]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replaceAll("-", "_").toLowerCase();
|
|
244
|
+
function underscoreConstantPath(qualifiedName, acronyms = []) {
|
|
245
|
+
return lowerAcronyms(qualifiedName.replaceAll("::", "/"), acronyms).replace(/([A-Z\d]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replaceAll("-", "_").toLowerCase();
|
|
246
|
+
}
|
|
247
|
+
function lowerAcronyms(word, acronyms) {
|
|
248
|
+
if (acronyms.length === 0) {
|
|
249
|
+
return word;
|
|
250
|
+
}
|
|
251
|
+
const alternatives = acronyms.map(escapeRegExp).join("|");
|
|
252
|
+
const acronymRegex = new RegExp(
|
|
253
|
+
`(?:(?<=([A-Za-z\\d]))|\\b)(${alternatives})(?=\\b|[^a-z])`,
|
|
254
|
+
"g"
|
|
255
|
+
);
|
|
256
|
+
return word.replace(
|
|
257
|
+
acronymRegex,
|
|
258
|
+
(_match, before, acronym) => `${before === void 0 ? "" : "_"}${acronym.toLowerCase()}`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
function escapeRegExp(text2) {
|
|
262
|
+
return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
207
263
|
}
|
|
208
264
|
var PATH_CONVENTIONS = {
|
|
209
265
|
railsUnderscore: underscoreConstantPath
|
|
210
266
|
};
|
|
211
|
-
function resolveConstantFile(root, qualifiedName, convention) {
|
|
212
|
-
const relative = `${PATH_CONVENTIONS[convention](qualifiedName)}.rb`;
|
|
267
|
+
function resolveConstantFile(root, qualifiedName, convention, acronyms = []) {
|
|
268
|
+
const relative = `${PATH_CONVENTIONS[convention](qualifiedName, acronyms)}.rb`;
|
|
213
269
|
for (const candidate of [root, ...autoloadDirectories(root)]) {
|
|
214
270
|
const file = path.join(candidate, relative);
|
|
215
271
|
if (fs.existsSync(file)) {
|
|
@@ -283,12 +339,19 @@ function walkBody(statements, nesting, visit) {
|
|
|
283
339
|
}
|
|
284
340
|
}
|
|
285
341
|
function ownIdentity(nameNode, outerNesting) {
|
|
286
|
-
const qualifiedName =
|
|
342
|
+
const qualifiedName = definedName(nameNode, outerNesting);
|
|
287
343
|
if (qualifiedName === null) {
|
|
288
344
|
return null;
|
|
289
345
|
}
|
|
290
346
|
return { qualifiedName, bodyNesting: [qualifiedName, ...outerNesting] };
|
|
291
347
|
}
|
|
348
|
+
function definedName(nameNode, outerNesting) {
|
|
349
|
+
const innermost = outerNesting[0] ?? null;
|
|
350
|
+
if (nameNode.type === "scope_resolution" && innermost !== null && !nameNode.text.startsWith("::")) {
|
|
351
|
+
return `${innermost}::${nameNode.text}`;
|
|
352
|
+
}
|
|
353
|
+
return qualifyConstantRef(nameNode, outerNesting);
|
|
354
|
+
}
|
|
292
355
|
function visitClass(node, nesting, visit) {
|
|
293
356
|
const nameNode = field(node, "name");
|
|
294
357
|
const identity = nameNode !== null ? ownIdentity(nameNode, nesting) : null;
|
|
@@ -352,7 +415,8 @@ async function reachDefinition(qualifiedName, lookup) {
|
|
|
352
415
|
const filePath = resolveConstantFile(
|
|
353
416
|
lookup.root,
|
|
354
417
|
qualifiedName,
|
|
355
|
-
lookup.pathConvention
|
|
418
|
+
lookup.pathConvention,
|
|
419
|
+
lookup.acronyms
|
|
356
420
|
);
|
|
357
421
|
if (filePath === null) {
|
|
358
422
|
return null;
|
|
@@ -394,7 +458,10 @@ async function chainOf(self, lookup, active) {
|
|
|
394
458
|
async function superclassChain(self, lookup, active) {
|
|
395
459
|
const candidates = superclassCandidatesOf(self.blocks);
|
|
396
460
|
for (const candidate of candidates) {
|
|
397
|
-
if (lookup.ancestryRootClassNames.includes(candidate)
|
|
461
|
+
if (lookup.ancestryRootClassNames.includes(candidate)) {
|
|
462
|
+
return [{ type: "root", name: candidate }];
|
|
463
|
+
}
|
|
464
|
+
if (active.has(candidate)) {
|
|
398
465
|
return [];
|
|
399
466
|
}
|
|
400
467
|
const blocks = await definitionOf(candidate, lookup);
|
|
@@ -472,6 +539,9 @@ function superclassCandidatesOf(blocks) {
|
|
|
472
539
|
}
|
|
473
540
|
function methodInAncestry(ancestry, name) {
|
|
474
541
|
for (const entry of ancestry) {
|
|
542
|
+
if (entry.type === "root") {
|
|
543
|
+
return { type: "none" };
|
|
544
|
+
}
|
|
475
545
|
if (entry.type === "unfollowed") {
|
|
476
546
|
return {
|
|
477
547
|
type: "unsettled",
|
|
@@ -1207,7 +1277,7 @@ function calledMethod(node) {
|
|
|
1207
1277
|
|
|
1208
1278
|
// src/values/evaluator.ts
|
|
1209
1279
|
import { nodeOfKey } from "@suss/resolution";
|
|
1210
|
-
import { Evaluator, force, literalOf as literalOf2 } from "@suss/values";
|
|
1280
|
+
import { Evaluator, force, literalOf as literalOf2, text } from "@suss/values";
|
|
1211
1281
|
|
|
1212
1282
|
// src/facts/resolve.ts
|
|
1213
1283
|
import {
|
|
@@ -2585,11 +2655,18 @@ function bindEvaluator(db, nodes) {
|
|
|
2585
2655
|
)
|
|
2586
2656
|
);
|
|
2587
2657
|
}
|
|
2588
|
-
function evaluatedValue(node, db) {
|
|
2589
|
-
|
|
2658
|
+
function evaluatedValue(node, db, bindings) {
|
|
2659
|
+
const evaluator = evaluatorFor(node, db);
|
|
2660
|
+
if (bindings === void 0) {
|
|
2661
|
+
return force(evaluator.evaluate(node));
|
|
2662
|
+
}
|
|
2663
|
+
const supplied = new Map(
|
|
2664
|
+
[...bindings].map(([name, value]) => [name, text(value)])
|
|
2665
|
+
);
|
|
2666
|
+
return force(evaluator.evaluate(node, { bindings: supplied }));
|
|
2590
2667
|
}
|
|
2591
|
-
function stringValueOf(node, db) {
|
|
2592
|
-
return literalOf2(evaluatedValue(node, db));
|
|
2668
|
+
function stringValueOf(node, db, bindings) {
|
|
2669
|
+
return literalOf2(evaluatedValue(node, db, bindings));
|
|
2593
2670
|
}
|
|
2594
2671
|
function methodDefinitionsIn(file, root) {
|
|
2595
2672
|
const found = /* @__PURE__ */ new Map();
|
|
@@ -3250,8 +3327,7 @@ function controllerFilters(pattern, ancestry) {
|
|
|
3250
3327
|
skipNames.set(form.skippedBy, form.name);
|
|
3251
3328
|
}
|
|
3252
3329
|
}
|
|
3253
|
-
|
|
3254
|
-
const skips = [];
|
|
3330
|
+
let declared = [];
|
|
3255
3331
|
for (const { statement } of inheritedStatements(ancestry)) {
|
|
3256
3332
|
const called = calledName(statement);
|
|
3257
3333
|
if (called === null) {
|
|
@@ -3259,16 +3335,21 @@ function controllerFilters(pattern, ancestry) {
|
|
|
3259
3335
|
}
|
|
3260
3336
|
const form = byName.get(called);
|
|
3261
3337
|
if (form !== void 0) {
|
|
3262
|
-
|
|
3338
|
+
for (const declaration of declarationsOf(statement, form)) {
|
|
3339
|
+
declared = [
|
|
3340
|
+
...declared.filter((earlier) => !sameFilter(earlier, declaration)),
|
|
3341
|
+
declaration
|
|
3342
|
+
];
|
|
3343
|
+
}
|
|
3263
3344
|
continue;
|
|
3264
3345
|
}
|
|
3265
3346
|
const skipped = skipNames.get(called);
|
|
3266
3347
|
if (skipped !== void 0) {
|
|
3267
|
-
|
|
3348
|
+
declared = applySkips(declared, skipsOf(statement, skipped));
|
|
3268
3349
|
}
|
|
3269
3350
|
}
|
|
3270
3351
|
const resolved = [];
|
|
3271
|
-
for (const declaration of
|
|
3352
|
+
for (const declaration of declared) {
|
|
3272
3353
|
const found = methodInAncestry(ancestry, declaration.methodName);
|
|
3273
3354
|
if (found.type !== "found") {
|
|
3274
3355
|
continue;
|
|
@@ -3381,6 +3462,9 @@ function skipsOf(statement, filterName) {
|
|
|
3381
3462
|
const actions = namesUnder(args.keyword.only);
|
|
3382
3463
|
return args.positional.map((arg) => symbolValue(arg)).filter((name) => name !== null).map((methodName) => ({ filterName, methodName, actions }));
|
|
3383
3464
|
}
|
|
3465
|
+
function sameFilter(one, other) {
|
|
3466
|
+
return one.filter.name === other.filter.name && one.methodName === other.methodName;
|
|
3467
|
+
}
|
|
3384
3468
|
function applySkips(declared, skips) {
|
|
3385
3469
|
const left = [];
|
|
3386
3470
|
for (const declaration of declared) {
|
|
@@ -3508,7 +3592,7 @@ function storageEffect(call, model, pattern, kind, selector) {
|
|
|
3508
3592
|
binding: storageBinding({
|
|
3509
3593
|
recognition: "ruby-storage",
|
|
3510
3594
|
storageSystem: pattern.storageSystem,
|
|
3511
|
-
scope:
|
|
3595
|
+
scope: "default",
|
|
3512
3596
|
container: constantName(model)
|
|
3513
3597
|
}),
|
|
3514
3598
|
callee: call.text,
|
|
@@ -3676,6 +3760,7 @@ function fieldReadContext(pattern, cache, fileBlocks, bodyRead) {
|
|
|
3676
3760
|
lookup: {
|
|
3677
3761
|
root: pattern.root,
|
|
3678
3762
|
pathConvention: pattern.pathConvention,
|
|
3763
|
+
acronyms: pattern.acronyms ?? [],
|
|
3679
3764
|
ancestryRootClassNames: pattern.ancestryRootClassNames,
|
|
3680
3765
|
parsedFile: (absPath) => cache.get(absPath),
|
|
3681
3766
|
localDefinition: (name) => sameFileBlocks(name, fileBlocks)
|
|
@@ -3790,12 +3875,16 @@ async function controllerActionUnits(pattern, pack, info, ownBlocks, fileBlocks,
|
|
|
3790
3875
|
const lookup = {
|
|
3791
3876
|
root: pattern.root,
|
|
3792
3877
|
pathConvention: pattern.pathConvention,
|
|
3878
|
+
acronyms: pattern.acronyms ?? [],
|
|
3793
3879
|
ancestryRootClassNames: pattern.ancestryRootClassNames,
|
|
3794
3880
|
parsedFile: (absPath) => options.cache.get(absPath),
|
|
3795
3881
|
localDefinition: (name) => sameFileBlocks(name, fileBlocks)
|
|
3796
3882
|
};
|
|
3797
3883
|
const ancestry = await ancestryOf(info.qualifiedName, ownBlocks, lookup);
|
|
3798
|
-
if (!reachesConfiguredBase(ancestry, info.qualifiedName,
|
|
3884
|
+
if (!reachesConfiguredBase(ancestry, info.qualifiedName, [
|
|
3885
|
+
...pattern.baseClassNames,
|
|
3886
|
+
...pattern.ancestryRootClassNames
|
|
3887
|
+
])) {
|
|
3799
3888
|
return [];
|
|
3800
3889
|
}
|
|
3801
3890
|
const filters = controllerFilters(pattern, ancestry);
|
|
@@ -3815,43 +3904,73 @@ async function controllerActionUnits(pattern, pack, info, ownBlocks, fileBlocks,
|
|
|
3815
3904
|
enclosingQualifiedName: filter.enclosingQualifiedName
|
|
3816
3905
|
});
|
|
3817
3906
|
}
|
|
3818
|
-
|
|
3819
|
-
|
|
3907
|
+
const emitAction = (actionName, method, block) => {
|
|
3908
|
+
const around = filters.filter((filter) => filterCoversAction(filter, actionName)).map(
|
|
3909
|
+
(filter) => filterReference(
|
|
3910
|
+
filter,
|
|
3911
|
+
options.displayPathOf?.(filter.file) ?? filter.file
|
|
3912
|
+
)
|
|
3913
|
+
);
|
|
3914
|
+
const raw = buildControllerActionUnit(
|
|
3915
|
+
pack,
|
|
3916
|
+
pattern,
|
|
3917
|
+
info.qualifiedName,
|
|
3918
|
+
actionName,
|
|
3919
|
+
method,
|
|
3920
|
+
{
|
|
3921
|
+
display: block.file === (options.absoluteFile ?? options.filePath) ? options.filePath : options.displayPathOf?.(block.file) ?? block.file,
|
|
3922
|
+
absolute: block.file
|
|
3923
|
+
},
|
|
3924
|
+
options,
|
|
3925
|
+
around
|
|
3926
|
+
);
|
|
3927
|
+
units.push(raw);
|
|
3928
|
+
options.onReachSeed?.(raw, {
|
|
3929
|
+
file: block.file,
|
|
3930
|
+
node: method,
|
|
3931
|
+
enclosingQualifiedName: block.info.qualifiedName
|
|
3932
|
+
});
|
|
3933
|
+
};
|
|
3934
|
+
const own = /* @__PURE__ */ new Set();
|
|
3935
|
+
for (const [actionName, method, block] of publicInstanceMethods(ownBlocks)) {
|
|
3936
|
+
own.add(actionName);
|
|
3937
|
+
emitAction(actionName, method, block);
|
|
3938
|
+
}
|
|
3939
|
+
const seen = new Set(own);
|
|
3940
|
+
for (const entry of ancestry) {
|
|
3941
|
+
if (entry.type !== "bodies" || entry.name === info.qualifiedName) {
|
|
3820
3942
|
continue;
|
|
3821
3943
|
}
|
|
3822
|
-
const
|
|
3823
|
-
|
|
3824
|
-
block.info.bodyNode
|
|
3944
|
+
for (const [actionName, method, block] of publicInstanceMethods(
|
|
3945
|
+
entry.blocks
|
|
3825
3946
|
)) {
|
|
3826
|
-
if (
|
|
3947
|
+
if (seen.has(actionName)) {
|
|
3827
3948
|
continue;
|
|
3828
3949
|
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
);
|
|
3835
|
-
const raw = buildControllerActionUnit(
|
|
3836
|
-
pack,
|
|
3837
|
-
pattern,
|
|
3838
|
-
info.qualifiedName,
|
|
3839
|
-
actionName,
|
|
3840
|
-
method,
|
|
3841
|
-
{ display: options.filePath, absolute: block.file },
|
|
3842
|
-
options,
|
|
3843
|
-
around
|
|
3844
|
-
);
|
|
3845
|
-
units.push(raw);
|
|
3846
|
-
options.onReachSeed?.(raw, {
|
|
3847
|
-
file: block.file,
|
|
3848
|
-
node: method,
|
|
3849
|
-
enclosingQualifiedName: info.qualifiedName
|
|
3850
|
-
});
|
|
3950
|
+
seen.add(actionName);
|
|
3951
|
+
if (pattern.routeFor(info.qualifiedName, actionName) === null) {
|
|
3952
|
+
continue;
|
|
3953
|
+
}
|
|
3954
|
+
emitAction(actionName, method, block);
|
|
3851
3955
|
}
|
|
3852
3956
|
}
|
|
3853
3957
|
return units;
|
|
3854
3958
|
}
|
|
3959
|
+
function publicInstanceMethods(blocks) {
|
|
3960
|
+
const found = [];
|
|
3961
|
+
for (const block of blocks) {
|
|
3962
|
+
if (block.info.bodyNode === null) {
|
|
3963
|
+
continue;
|
|
3964
|
+
}
|
|
3965
|
+
const visibility = instanceMethodVisibility(block.info.bodyNode);
|
|
3966
|
+
for (const [name, method] of instanceMethodsByName(block.info.bodyNode)) {
|
|
3967
|
+
if ((visibility.get(name) ?? "public") === "public") {
|
|
3968
|
+
found.push([name, method, block]);
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
return found;
|
|
3973
|
+
}
|
|
3855
3974
|
function buildControllerActionUnit(pack, pattern, controllerQualifiedName, actionName, method, file, bodyRead, wrappers = []) {
|
|
3856
3975
|
const range = rangeOf(method);
|
|
3857
3976
|
const route = pattern.routeFor(controllerQualifiedName, actionName);
|
|
@@ -5106,7 +5225,8 @@ function inheritedMethodsIn(packs) {
|
|
|
5106
5225
|
return found;
|
|
5107
5226
|
}
|
|
5108
5227
|
function alreadyDiscovered(seen, raw) {
|
|
5109
|
-
const
|
|
5228
|
+
const reported = raw.identity.exportPath?.join(".") ?? raw.identity.name;
|
|
5229
|
+
const key = `${raw.identity.file}::${reported}::${raw.identity.range.start}`;
|
|
5110
5230
|
if (seen.has(key)) {
|
|
5111
5231
|
return true;
|
|
5112
5232
|
}
|
|
@@ -5405,8 +5525,8 @@ function displayNameOf(node) {
|
|
|
5405
5525
|
if (node.type === "class" || node.type === "module") {
|
|
5406
5526
|
return field(node, "name")?.text ?? node.text;
|
|
5407
5527
|
}
|
|
5408
|
-
const
|
|
5409
|
-
return
|
|
5528
|
+
const text2 = node.text.split("\n")[0].trim();
|
|
5529
|
+
return text2.length > 40 ? `${text2.slice(0, 40)}...` : text2;
|
|
5410
5530
|
}
|
|
5411
5531
|
function width(node) {
|
|
5412
5532
|
return node.endIndex - node.startIndex;
|
|
@@ -5433,14 +5553,14 @@ var RubyWhySession = class {
|
|
|
5433
5553
|
* The smallest expression on `line` of `file` whose text is exactly
|
|
5434
5554
|
* `text`, or null.
|
|
5435
5555
|
*/
|
|
5436
|
-
findExpression(file, line,
|
|
5556
|
+
findExpression(file, line, text2) {
|
|
5437
5557
|
const root = this.rootOf(file);
|
|
5438
5558
|
if (root === null) {
|
|
5439
5559
|
return null;
|
|
5440
5560
|
}
|
|
5441
5561
|
let found = null;
|
|
5442
5562
|
const visit = (node) => {
|
|
5443
|
-
if (node.startPosition.row + 1 === line && node.text ===
|
|
5563
|
+
if (node.startPosition.row + 1 === line && node.text === text2) {
|
|
5444
5564
|
if (found === null || width(node) <= width(found)) {
|
|
5445
5565
|
found = node;
|
|
5446
5566
|
}
|
|
@@ -5610,6 +5730,7 @@ export {
|
|
|
5610
5730
|
inheritedStatements,
|
|
5611
5731
|
methodDefinitionsIn,
|
|
5612
5732
|
methodInAncestry,
|
|
5733
|
+
nestedStatements,
|
|
5613
5734
|
nodeId,
|
|
5614
5735
|
parseRuby,
|
|
5615
5736
|
parseRubySync,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-ruby",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Read a Ruby codebase with suss and check what each Rails action or graphql-ruby resolver returns against the code that calls it.",
|
|
6
6
|
"keywords": [
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"typecheck": "tsc --noEmit"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@suss/behavioral-ir": "0.
|
|
53
|
-
"@suss/datalog": "0.
|
|
54
|
-
"@suss/extractor": "0.
|
|
55
|
-
"@suss/ir-core": "0.
|
|
56
|
-
"@suss/resolution": "0.
|
|
57
|
-
"@suss/values": "0.
|
|
52
|
+
"@suss/behavioral-ir": "0.27.0",
|
|
53
|
+
"@suss/datalog": "0.27.0",
|
|
54
|
+
"@suss/extractor": "0.27.0",
|
|
55
|
+
"@suss/ir-core": "0.27.0",
|
|
56
|
+
"@suss/resolution": "0.27.0",
|
|
57
|
+
"@suss/values": "0.27.0",
|
|
58
58
|
"web-tree-sitter": "^0.26.11"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|