@suss/adapter-typescript 0.5.11 → 0.7.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 +354 -25
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +352 -25
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -49,10 +49,12 @@ __export(index_exports, {
|
|
|
49
49
|
findTerminals: () => findTerminals,
|
|
50
50
|
formatPackHealth: () => formatPackHealth,
|
|
51
51
|
isImportedFrom: () => isImportedFrom,
|
|
52
|
+
methodDeclaredIn: () => methodDeclaredIn,
|
|
52
53
|
parseConditionExpression: () => parseConditionExpression,
|
|
53
54
|
readConfiguredCall: () => readConfiguredCall,
|
|
54
55
|
readContract: () => readContract,
|
|
55
56
|
readContractForClientCall: () => readContractForClientCall,
|
|
57
|
+
readName: () => readName,
|
|
56
58
|
resolveAliasedSymbol: () => resolveAliasedSymbol,
|
|
57
59
|
resolveSubject: () => resolveSubject,
|
|
58
60
|
rootIdentifier: () => rootIdentifier
|
|
@@ -1488,9 +1490,9 @@ var ModuleGraph = class {
|
|
|
1488
1490
|
if (known !== void 0) {
|
|
1489
1491
|
return known;
|
|
1490
1492
|
}
|
|
1491
|
-
const
|
|
1492
|
-
this.specifiers.set(filePath,
|
|
1493
|
-
return
|
|
1493
|
+
const read2 = readModuleSpecifiers(sourceFile);
|
|
1494
|
+
this.specifiers.set(filePath, read2);
|
|
1495
|
+
return read2;
|
|
1494
1496
|
}
|
|
1495
1497
|
/**
|
|
1496
1498
|
* Collect what the rules need in order to settle this file and this
|
|
@@ -2253,6 +2255,15 @@ function isImportedFrom(identifier, expectedModule) {
|
|
|
2253
2255
|
(decl) => decl.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2254
2256
|
);
|
|
2255
2257
|
}
|
|
2258
|
+
function methodDeclaredIn(callee, expectedModule) {
|
|
2259
|
+
if (!import_ts_morph12.Node.isPropertyAccessExpression(callee)) {
|
|
2260
|
+
return false;
|
|
2261
|
+
}
|
|
2262
|
+
const declarations = callee.getNameNode().getSymbol()?.getDeclarations();
|
|
2263
|
+
return declarations !== void 0 && declarations.some(
|
|
2264
|
+
(declaration) => declaration.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2256
2267
|
function importSpecifierMatches(decl, expectedModule) {
|
|
2257
2268
|
if (import_ts_morph12.Node.isImportSpecifier(decl)) {
|
|
2258
2269
|
return decl.getImportDeclaration().getModuleSpecifierValue() === expectedModule;
|
|
@@ -2431,7 +2442,7 @@ function dispatchAccessRecognizers(root, recognizers, isStop, resolveWrittenValu
|
|
|
2431
2442
|
traversal.skip();
|
|
2432
2443
|
return;
|
|
2433
2444
|
}
|
|
2434
|
-
if (!import_ts_morph12.Node.isPropertyAccessExpression(node) && !import_ts_morph12.Node.isCallExpression(node)) {
|
|
2445
|
+
if (!import_ts_morph12.Node.isPropertyAccessExpression(node) && !import_ts_morph12.Node.isCallExpression(node) && !import_ts_morph12.Node.isTaggedTemplateExpression(node)) {
|
|
2435
2446
|
return;
|
|
2436
2447
|
}
|
|
2437
2448
|
const ctx = {
|
|
@@ -2856,12 +2867,12 @@ function createDefinitionTable() {
|
|
|
2856
2867
|
}
|
|
2857
2868
|
};
|
|
2858
2869
|
}
|
|
2859
|
-
function withDefinitions(
|
|
2870
|
+
function withDefinitions(read2) {
|
|
2860
2871
|
const table = createDefinitionTable();
|
|
2861
2872
|
const outer = current;
|
|
2862
2873
|
current = table;
|
|
2863
2874
|
try {
|
|
2864
|
-
return { value:
|
|
2875
|
+
return { value: read2(), definitions: table.collected() };
|
|
2865
2876
|
} finally {
|
|
2866
2877
|
current = outer;
|
|
2867
2878
|
}
|
|
@@ -4005,10 +4016,59 @@ function writesToBindingUncached(declaration) {
|
|
|
4005
4016
|
}
|
|
4006
4017
|
return { values, inOrder: writesRunInOrder(declaration, writes) };
|
|
4007
4018
|
}
|
|
4019
|
+
function writesToField(declaration) {
|
|
4020
|
+
const remembered = byDeclaration.get(declaration);
|
|
4021
|
+
if (remembered !== void 0) {
|
|
4022
|
+
return remembered;
|
|
4023
|
+
}
|
|
4024
|
+
const answer = writesToFieldUncached(declaration);
|
|
4025
|
+
byDeclaration.set(declaration, answer);
|
|
4026
|
+
return answer;
|
|
4027
|
+
}
|
|
4028
|
+
function writesToFieldUncached(declaration) {
|
|
4029
|
+
const initializer = declaration.getInitializer();
|
|
4030
|
+
const assignments = assignmentsTo(declaration);
|
|
4031
|
+
if (assignments.length === 0) {
|
|
4032
|
+
return {
|
|
4033
|
+
values: initializer === void 0 ? [] : [initializer],
|
|
4034
|
+
inOrder: true
|
|
4035
|
+
};
|
|
4036
|
+
}
|
|
4037
|
+
const values = [];
|
|
4038
|
+
for (const write of assignments) {
|
|
4039
|
+
if (write.value === null) {
|
|
4040
|
+
return { values: [], inOrder: false };
|
|
4041
|
+
}
|
|
4042
|
+
values.push(write.value);
|
|
4043
|
+
}
|
|
4044
|
+
const withInitializer = initializer === void 0 ? values : [initializer, ...values];
|
|
4045
|
+
return {
|
|
4046
|
+
values: withInitializer,
|
|
4047
|
+
inOrder: assignments.every(
|
|
4048
|
+
(write) => writeRunsInConstructor(declaration, write)
|
|
4049
|
+
)
|
|
4050
|
+
};
|
|
4051
|
+
}
|
|
4052
|
+
function writeRunsInConstructor(declaration, write) {
|
|
4053
|
+
const statement = statementOf(write.node);
|
|
4054
|
+
if (statement === null) {
|
|
4055
|
+
return false;
|
|
4056
|
+
}
|
|
4057
|
+
const body = statement.getParent();
|
|
4058
|
+
if (body === void 0 || !import_ts_morph18.Node.isBlock(body)) {
|
|
4059
|
+
return false;
|
|
4060
|
+
}
|
|
4061
|
+
const owner = body.getParent();
|
|
4062
|
+
return owner !== void 0 && import_ts_morph18.Node.isConstructorDeclaration(owner) && owner.getParent() === declaration.getParent();
|
|
4063
|
+
}
|
|
4008
4064
|
function isWrittenAgain(declaration) {
|
|
4009
4065
|
return assignmentsTo(declaration).length > 0;
|
|
4010
4066
|
}
|
|
4011
4067
|
function assignmentsTo(declaration) {
|
|
4068
|
+
if (import_ts_morph18.Node.isPropertyDeclaration(declaration)) {
|
|
4069
|
+
const sourceFile2 = declaration.getSourceFile();
|
|
4070
|
+
return sourceFile2.isDeclarationFile() ? [] : assignmentsInFile(sourceFile2).get(declaration) ?? [];
|
|
4071
|
+
}
|
|
4012
4072
|
if (declaration.getVariableStatement()?.getDeclarationKind() === import_ts_morph18.VariableDeclarationKind.Const) {
|
|
4013
4073
|
return [];
|
|
4014
4074
|
}
|
|
@@ -4048,7 +4108,7 @@ function writeAt(node) {
|
|
|
4048
4108
|
if (import_ts_morph18.Node.isBinaryExpression(node)) {
|
|
4049
4109
|
const operator = node.getOperatorToken().getKind();
|
|
4050
4110
|
const target = node.getLeft();
|
|
4051
|
-
if (!isAssignmentOperator(operator) || !import_ts_morph18.Node.isIdentifier(target)) {
|
|
4111
|
+
if (!isAssignmentOperator(operator) || !(import_ts_morph18.Node.isIdentifier(target) || import_ts_morph18.Node.isPropertyAccessExpression(target))) {
|
|
4052
4112
|
return null;
|
|
4053
4113
|
}
|
|
4054
4114
|
const value = operator === import_ts_morph18.SyntaxKind.EqualsToken ? node.getRight() : null;
|
|
@@ -4065,13 +4125,14 @@ function writeAt(node) {
|
|
|
4065
4125
|
return null;
|
|
4066
4126
|
}
|
|
4067
4127
|
function declarationsOf(name) {
|
|
4068
|
-
const
|
|
4128
|
+
const nameNode = import_ts_morph18.Node.isPropertyAccessExpression(name) ? name.getNameNode() : name;
|
|
4129
|
+
const symbol = nameNode.getSymbol();
|
|
4069
4130
|
if (symbol === void 0) {
|
|
4070
4131
|
return [];
|
|
4071
4132
|
}
|
|
4072
4133
|
const declarations = [];
|
|
4073
4134
|
for (const declaration of symbol.getDeclarations()) {
|
|
4074
|
-
if (import_ts_morph18.Node.isVariableDeclaration(declaration)) {
|
|
4135
|
+
if (import_ts_morph18.Node.isVariableDeclaration(declaration) || import_ts_morph18.Node.isPropertyDeclaration(declaration)) {
|
|
4075
4136
|
declarations.push(declaration);
|
|
4076
4137
|
}
|
|
4077
4138
|
}
|
|
@@ -4101,9 +4162,9 @@ function statementOf(node) {
|
|
|
4101
4162
|
function isReadBefore(declaration, position) {
|
|
4102
4163
|
const name = declaration.getName();
|
|
4103
4164
|
const sourceFile = declaration.getSourceFile();
|
|
4104
|
-
let
|
|
4165
|
+
let read2 = false;
|
|
4105
4166
|
sourceFile.forEachDescendant((node, traversal) => {
|
|
4106
|
-
if (
|
|
4167
|
+
if (read2) {
|
|
4107
4168
|
traversal.stop();
|
|
4108
4169
|
return;
|
|
4109
4170
|
}
|
|
@@ -4122,10 +4183,10 @@ function isReadBefore(declaration, position) {
|
|
|
4122
4183
|
return;
|
|
4123
4184
|
}
|
|
4124
4185
|
if (declarationsOf(node).includes(declaration)) {
|
|
4125
|
-
|
|
4186
|
+
read2 = true;
|
|
4126
4187
|
}
|
|
4127
4188
|
});
|
|
4128
|
-
return
|
|
4189
|
+
return read2;
|
|
4129
4190
|
}
|
|
4130
4191
|
function startsItsOwnBody(node) {
|
|
4131
4192
|
return import_ts_morph18.Node.isFunctionDeclaration(node) || import_ts_morph18.Node.isFunctionExpression(node) || import_ts_morph18.Node.isArrowFunction(node) || import_ts_morph18.Node.isMethodDeclaration(node) || import_ts_morph18.Node.isClassDeclaration(node);
|
|
@@ -6093,6 +6154,14 @@ function emitBindingValues(db, table, declaration) {
|
|
|
6093
6154
|
}
|
|
6094
6155
|
fact(db, "endsHolding", declarationId, emitValue(db, table, last));
|
|
6095
6156
|
}
|
|
6157
|
+
function emitFieldValues(db, table, declaration) {
|
|
6158
|
+
const { values, inOrder } = writesToField(declaration);
|
|
6159
|
+
const last = values[values.length - 1];
|
|
6160
|
+
if (!inOrder || last === void 0) {
|
|
6161
|
+
return;
|
|
6162
|
+
}
|
|
6163
|
+
fact(db, "binds", nodeId(declaration), emitValue(db, table, last));
|
|
6164
|
+
}
|
|
6096
6165
|
function emitBindingElementFacts(db, table, element) {
|
|
6097
6166
|
const id = nodeId(element);
|
|
6098
6167
|
table.byId.set(id, element);
|
|
@@ -6168,6 +6237,11 @@ function emitReferenceFacts(db, table, reference) {
|
|
|
6168
6237
|
emitBindingValues(db, table, declaration);
|
|
6169
6238
|
continue;
|
|
6170
6239
|
}
|
|
6240
|
+
if (import_ts_morph28.Node.isPropertyDeclaration(declaration)) {
|
|
6241
|
+
fact(db, "binds", referenceId, declarationId);
|
|
6242
|
+
emitFieldValues(db, table, declaration);
|
|
6243
|
+
continue;
|
|
6244
|
+
}
|
|
6171
6245
|
if (import_ts_morph28.Node.isParameterDeclaration(declaration)) {
|
|
6172
6246
|
fact(db, "binds", referenceId, declarationId);
|
|
6173
6247
|
continue;
|
|
@@ -6402,9 +6476,9 @@ function propertyValueOf(property) {
|
|
|
6402
6476
|
}
|
|
6403
6477
|
function functionValueOf(value, resolution) {
|
|
6404
6478
|
const written = factKeyOf(value);
|
|
6405
|
-
const
|
|
6406
|
-
if (
|
|
6407
|
-
return
|
|
6479
|
+
const here2 = toFunctionRoot(written);
|
|
6480
|
+
if (here2 !== null) {
|
|
6481
|
+
return here2;
|
|
6408
6482
|
}
|
|
6409
6483
|
if (resolution === void 0 || !couldNameAValue(written)) {
|
|
6410
6484
|
return null;
|
|
@@ -8160,7 +8234,7 @@ function unitsOfArrayElements(array, match, kind, resolution, prefix, ancestry)
|
|
|
8160
8234
|
}
|
|
8161
8235
|
function unitsForRouteObject(object, match, kind, resolution, prefix, ancestry) {
|
|
8162
8236
|
const own = ownPathOfObject(object, match);
|
|
8163
|
-
const
|
|
8237
|
+
const here2 = unitForRouteObject(object, match, kind, resolution, prefix, own);
|
|
8164
8238
|
const nested = unitsUnderRouteObject(
|
|
8165
8239
|
object,
|
|
8166
8240
|
match,
|
|
@@ -8169,7 +8243,7 @@ function unitsForRouteObject(object, match, kind, resolution, prefix, ancestry)
|
|
|
8169
8243
|
prefixUnder(prefix, own),
|
|
8170
8244
|
ancestry
|
|
8171
8245
|
);
|
|
8172
|
-
return
|
|
8246
|
+
return here2 === null ? nested : [here2, ...nested];
|
|
8173
8247
|
}
|
|
8174
8248
|
function unitForRouteObject(object, match, kind, resolution, prefix, own) {
|
|
8175
8249
|
const target = elementTargetOfValue(
|
|
@@ -8657,6 +8731,9 @@ function trackFactoryBindings(sourceFile, recognize) {
|
|
|
8657
8731
|
}
|
|
8658
8732
|
|
|
8659
8733
|
// src/discovery/packageImport.ts
|
|
8734
|
+
function isLanguageLib(file) {
|
|
8735
|
+
return /[\\/]typescript[\\/]lib[\\/]lib\..*\.d\.ts$/.test(file.getFilePath());
|
|
8736
|
+
}
|
|
8660
8737
|
function splitPackageSpec(spec) {
|
|
8661
8738
|
if (spec.startsWith("@")) {
|
|
8662
8739
|
const parts2 = spec.split("/");
|
|
@@ -8774,6 +8851,9 @@ function discoverPackageImports(sourceFile, match, kind) {
|
|
|
8774
8851
|
if (subjectProvenance === null) {
|
|
8775
8852
|
return null;
|
|
8776
8853
|
}
|
|
8854
|
+
if (!methodComesFromSource(callee)) {
|
|
8855
|
+
return subjectProvenance;
|
|
8856
|
+
}
|
|
8777
8857
|
return {
|
|
8778
8858
|
packageName: subjectProvenance.packageName,
|
|
8779
8859
|
exportPath: [...subjectProvenance.exportPath, callee.getName()]
|
|
@@ -8781,6 +8861,15 @@ function discoverPackageImports(sourceFile, match, kind) {
|
|
|
8781
8861
|
}
|
|
8782
8862
|
return null;
|
|
8783
8863
|
}
|
|
8864
|
+
function methodComesFromSource(callee) {
|
|
8865
|
+
const declarations = callee.getNameNode().getSymbol()?.getDeclarations();
|
|
8866
|
+
if (declarations === void 0 || declarations.length === 0) {
|
|
8867
|
+
return true;
|
|
8868
|
+
}
|
|
8869
|
+
return declarations.some(
|
|
8870
|
+
(declaration) => !isLanguageLib(declaration.getSourceFile())
|
|
8871
|
+
);
|
|
8872
|
+
}
|
|
8784
8873
|
const results = [];
|
|
8785
8874
|
const seen = /* @__PURE__ */ new Set();
|
|
8786
8875
|
sourceFile.forEachDescendant((node) => {
|
|
@@ -10381,8 +10470,8 @@ function bindingLabel(binding) {
|
|
|
10381
10470
|
if (semantics.name === "rest") {
|
|
10382
10471
|
return `${semantics.method} ${semantics.path}`;
|
|
10383
10472
|
}
|
|
10384
|
-
if (semantics.name === "storage
|
|
10385
|
-
return `${semantics.storageSystem}:${semantics.
|
|
10473
|
+
if (semantics.name === "storage") {
|
|
10474
|
+
return `${semantics.storageSystem}:${semantics.container}`;
|
|
10386
10475
|
}
|
|
10387
10476
|
if (semantics.name === "message-bus") {
|
|
10388
10477
|
return `${semantics.messageBus}:${semantics.channel}`;
|
|
@@ -10616,7 +10705,9 @@ function extractReachableSummary(candidate, options, recognizers) {
|
|
|
10616
10705
|
unit,
|
|
10617
10706
|
reachablePack,
|
|
10618
10707
|
recognizers.invocation,
|
|
10619
|
-
recognizers.access
|
|
10708
|
+
recognizers.access,
|
|
10709
|
+
void 0,
|
|
10710
|
+
recognizers.resolveWrittenValue
|
|
10620
10711
|
);
|
|
10621
10712
|
raw.boundaryBinding = (0, import_behavioral_ir4.functionCallBinding)({
|
|
10622
10713
|
transport: "in-process",
|
|
@@ -11921,7 +12012,7 @@ function announcedBoundaryStructure(unit) {
|
|
|
11921
12012
|
};
|
|
11922
12013
|
}
|
|
11923
12014
|
function extractCodeStructure(unit, pack, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolveWrittenValue) {
|
|
11924
|
-
const
|
|
12015
|
+
const read2 = withDefinitions(
|
|
11925
12016
|
() => readCodeStructure(
|
|
11926
12017
|
unit,
|
|
11927
12018
|
pack,
|
|
@@ -11931,7 +12022,7 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
11931
12022
|
resolveWrittenValue
|
|
11932
12023
|
)
|
|
11933
12024
|
);
|
|
11934
|
-
return
|
|
12025
|
+
return read2.definitions === null ? read2.value : { ...read2.value, definitions: read2.definitions };
|
|
11935
12026
|
}
|
|
11936
12027
|
function responseAccessorNames(pack, kind) {
|
|
11937
12028
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
@@ -13056,7 +13147,8 @@ function createTypeScriptAdapter(config) {
|
|
|
13056
13147
|
config.frameworks,
|
|
13057
13148
|
tallies
|
|
13058
13149
|
),
|
|
13059
|
-
access: collectAccessRecognizers(config.frameworks, tallies)
|
|
13150
|
+
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13151
|
+
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value)
|
|
13060
13152
|
}
|
|
13061
13153
|
)
|
|
13062
13154
|
) : withSubUnits;
|
|
@@ -13435,7 +13527,7 @@ function threwWhileReading(packs) {
|
|
|
13435
13527
|
return packs.filter((funnel) => funnel.failures.length > 0).map((funnel) => {
|
|
13436
13528
|
const first = funnel.failures[0];
|
|
13437
13529
|
const rest = funnel.failures.length - 1;
|
|
13438
|
-
const alsoIn = rest > 0 ? ` and on ${rest}
|
|
13530
|
+
const alsoIn = rest > 0 ? ` and on ${rest} ${rest === 1 ? "other file" : "other files"}` : "";
|
|
13439
13531
|
return {
|
|
13440
13532
|
label: funnel.pack,
|
|
13441
13533
|
detail: `threw from ${first.hook} on ${first.file}${alsoIn}, so its counts below are a floor: ${first.message}`
|
|
@@ -13487,6 +13579,241 @@ function formatPackHealth(checks, audiences) {
|
|
|
13487
13579
|
return `${lines.join("\n")}
|
|
13488
13580
|
`;
|
|
13489
13581
|
}
|
|
13582
|
+
|
|
13583
|
+
// src/resolve/readName.ts
|
|
13584
|
+
var import_ts_morph58 = require("ts-morph");
|
|
13585
|
+
var MAX_HELPER_HOPS = 2;
|
|
13586
|
+
var UNNAMED_HOLE = "param";
|
|
13587
|
+
function readName(expr, options = {}) {
|
|
13588
|
+
const name = read(expr, {
|
|
13589
|
+
resolve: options.resolve ?? (() => null),
|
|
13590
|
+
bindings: /* @__PURE__ */ new Map(),
|
|
13591
|
+
hops: 0,
|
|
13592
|
+
seen: /* @__PURE__ */ new Set(),
|
|
13593
|
+
insideHole: false
|
|
13594
|
+
});
|
|
13595
|
+
if (name !== null || options.unsettled !== "reference") {
|
|
13596
|
+
return name;
|
|
13597
|
+
}
|
|
13598
|
+
const asked = holeName(expr, {
|
|
13599
|
+
resolve: () => null,
|
|
13600
|
+
bindings: /* @__PURE__ */ new Map(),
|
|
13601
|
+
hops: 0,
|
|
13602
|
+
seen: /* @__PURE__ */ new Set(),
|
|
13603
|
+
insideHole: true
|
|
13604
|
+
});
|
|
13605
|
+
return asked === UNNAMED_HOLE ? null : `{${asked}}`;
|
|
13606
|
+
}
|
|
13607
|
+
function read(expr, ctx) {
|
|
13608
|
+
if (ctx.seen.has(expr)) {
|
|
13609
|
+
return null;
|
|
13610
|
+
}
|
|
13611
|
+
const seen = new Set(ctx.seen).add(expr);
|
|
13612
|
+
const inner = { ...ctx, seen };
|
|
13613
|
+
if (import_ts_morph58.Node.isStringLiteral(expr) || import_ts_morph58.Node.isNoSubstitutionTemplateLiteral(expr)) {
|
|
13614
|
+
return expr.getLiteralValue();
|
|
13615
|
+
}
|
|
13616
|
+
if (import_ts_morph58.Node.isNumericLiteral(expr)) {
|
|
13617
|
+
return expr.getLiteralText();
|
|
13618
|
+
}
|
|
13619
|
+
if (import_ts_morph58.Node.isTemplateExpression(expr)) {
|
|
13620
|
+
return fromTemplate(expr, inner);
|
|
13621
|
+
}
|
|
13622
|
+
if (import_ts_morph58.Node.isParenthesizedExpression(expr)) {
|
|
13623
|
+
return read(expr.getExpression(), inner);
|
|
13624
|
+
}
|
|
13625
|
+
if (import_ts_morph58.Node.isBinaryExpression(expr)) {
|
|
13626
|
+
return fromBinary(expr, inner);
|
|
13627
|
+
}
|
|
13628
|
+
if (import_ts_morph58.Node.isCallExpression(expr)) {
|
|
13629
|
+
return fromCall(expr, inner);
|
|
13630
|
+
}
|
|
13631
|
+
if (import_ts_morph58.Node.isIdentifier(expr)) {
|
|
13632
|
+
const only = boundOnce(expr, ctx);
|
|
13633
|
+
if (only !== null) {
|
|
13634
|
+
return read(only.node, { ...inner, bindings: only.scope });
|
|
13635
|
+
}
|
|
13636
|
+
}
|
|
13637
|
+
const written = ctx.resolve(expr);
|
|
13638
|
+
return written === null || written === expr ? null : read(written, inner);
|
|
13639
|
+
}
|
|
13640
|
+
function fromTemplate(expr, ctx) {
|
|
13641
|
+
if (!import_ts_morph58.Node.isTemplateExpression(expr)) {
|
|
13642
|
+
return null;
|
|
13643
|
+
}
|
|
13644
|
+
let name = expr.getHead().getLiteralText();
|
|
13645
|
+
for (const span of expr.getTemplateSpans()) {
|
|
13646
|
+
name += readOrHole(span.getExpression(), { ...ctx, insideHole: true });
|
|
13647
|
+
name += span.getLiteral().getLiteralText();
|
|
13648
|
+
}
|
|
13649
|
+
return name;
|
|
13650
|
+
}
|
|
13651
|
+
function fromBinary(expr, ctx) {
|
|
13652
|
+
if (!import_ts_morph58.Node.isBinaryExpression(expr)) {
|
|
13653
|
+
return null;
|
|
13654
|
+
}
|
|
13655
|
+
const operator = expr.getOperatorToken().getKind();
|
|
13656
|
+
if (operator === import_ts_morph58.SyntaxKind.BarBarToken || operator === import_ts_morph58.SyntaxKind.QuestionQuestionToken) {
|
|
13657
|
+
return ctx.insideHole ? null : read(expr.getRight(), ctx);
|
|
13658
|
+
}
|
|
13659
|
+
if (operator !== import_ts_morph58.SyntaxKind.PlusToken) {
|
|
13660
|
+
return null;
|
|
13661
|
+
}
|
|
13662
|
+
const parts = { ...ctx, insideHole: true };
|
|
13663
|
+
return readOrHole(expr.getLeft(), parts) + readOrHole(expr.getRight(), parts);
|
|
13664
|
+
}
|
|
13665
|
+
function fromCall(expr, ctx) {
|
|
13666
|
+
if (!import_ts_morph58.Node.isCallExpression(expr)) {
|
|
13667
|
+
return null;
|
|
13668
|
+
}
|
|
13669
|
+
const callee = expr.getExpression();
|
|
13670
|
+
if (import_ts_morph58.Node.isPropertyAccessExpression(callee) && callee.getName() === "join") {
|
|
13671
|
+
return fromJoin(callee.getExpression(), expr.getArguments(), ctx);
|
|
13672
|
+
}
|
|
13673
|
+
if (import_ts_morph58.Node.isIdentifier(callee) && callee.getText() === "String") {
|
|
13674
|
+
const only = expr.getArguments()[0];
|
|
13675
|
+
return only === void 0 ? null : readOrHole(only, ctx);
|
|
13676
|
+
}
|
|
13677
|
+
if (ctx.hops >= MAX_HELPER_HOPS) {
|
|
13678
|
+
return null;
|
|
13679
|
+
}
|
|
13680
|
+
const helper = singleReturnBody(callee, ctx);
|
|
13681
|
+
if (helper === null) {
|
|
13682
|
+
return null;
|
|
13683
|
+
}
|
|
13684
|
+
return read(helper.returned, {
|
|
13685
|
+
...ctx,
|
|
13686
|
+
hops: ctx.hops + 1,
|
|
13687
|
+
bindings: bind(helper.parameters, expr.getArguments(), ctx.bindings)
|
|
13688
|
+
});
|
|
13689
|
+
}
|
|
13690
|
+
function fromJoin(subject, args, ctx) {
|
|
13691
|
+
const separator = args[0];
|
|
13692
|
+
if (separator === void 0 || !import_ts_morph58.Node.isStringLiteral(separator)) {
|
|
13693
|
+
return null;
|
|
13694
|
+
}
|
|
13695
|
+
const parts = elementsOf(subject, ctx);
|
|
13696
|
+
if (parts === null) {
|
|
13697
|
+
return null;
|
|
13698
|
+
}
|
|
13699
|
+
return parts.map(
|
|
13700
|
+
(part) => readOrHole(part.node, {
|
|
13701
|
+
...ctx,
|
|
13702
|
+
bindings: part.scope,
|
|
13703
|
+
insideHole: true
|
|
13704
|
+
})
|
|
13705
|
+
).join(separator.getLiteralValue());
|
|
13706
|
+
}
|
|
13707
|
+
function elementsOf(subject, ctx) {
|
|
13708
|
+
if (import_ts_morph58.Node.isArrayLiteralExpression(subject)) {
|
|
13709
|
+
return subject.getElements().map((element) => here(element, ctx));
|
|
13710
|
+
}
|
|
13711
|
+
if (import_ts_morph58.Node.isCallExpression(subject)) {
|
|
13712
|
+
const callee = subject.getExpression();
|
|
13713
|
+
if (import_ts_morph58.Node.isPropertyAccessExpression(callee) && callee.getName() === "map") {
|
|
13714
|
+
return elementsOf(callee.getExpression(), ctx);
|
|
13715
|
+
}
|
|
13716
|
+
return null;
|
|
13717
|
+
}
|
|
13718
|
+
if (!import_ts_morph58.Node.isIdentifier(subject)) {
|
|
13719
|
+
return null;
|
|
13720
|
+
}
|
|
13721
|
+
const bound = ctx.bindings.get(subject.getText());
|
|
13722
|
+
if (bound === void 0) {
|
|
13723
|
+
return null;
|
|
13724
|
+
}
|
|
13725
|
+
const only = bound.length === 1 ? bound[0] : void 0;
|
|
13726
|
+
return only !== void 0 && import_ts_morph58.Node.isArrayLiteralExpression(only.node) ? only.node.getElements().map((element) => here(element, ctx)) : bound;
|
|
13727
|
+
}
|
|
13728
|
+
function singleReturnBody(callee, ctx) {
|
|
13729
|
+
const declaration = declarationOf2(callee, ctx);
|
|
13730
|
+
if (declaration === null) {
|
|
13731
|
+
return null;
|
|
13732
|
+
}
|
|
13733
|
+
const parameters = declaration.getParameters().map((parameter) => ({
|
|
13734
|
+
name: parameter.getName(),
|
|
13735
|
+
rest: parameter.isRestParameter()
|
|
13736
|
+
}));
|
|
13737
|
+
const body = declaration.getBody();
|
|
13738
|
+
if (body === void 0) {
|
|
13739
|
+
return null;
|
|
13740
|
+
}
|
|
13741
|
+
if (import_ts_morph58.Node.isExpression(body)) {
|
|
13742
|
+
return { parameters, returned: body };
|
|
13743
|
+
}
|
|
13744
|
+
if (!import_ts_morph58.Node.isBlock(body)) {
|
|
13745
|
+
return null;
|
|
13746
|
+
}
|
|
13747
|
+
const statements = body.getStatements();
|
|
13748
|
+
const only = statements[0];
|
|
13749
|
+
if (statements.length !== 1 || only === void 0 || !import_ts_morph58.Node.isReturnStatement(only)) {
|
|
13750
|
+
return null;
|
|
13751
|
+
}
|
|
13752
|
+
const returned = only.getExpression();
|
|
13753
|
+
return returned === void 0 ? null : { parameters, returned };
|
|
13754
|
+
}
|
|
13755
|
+
function declarationOf2(callee, ctx) {
|
|
13756
|
+
const symbol = import_ts_morph58.Node.isPropertyAccessExpression(callee) ? callee.getNameNode().getSymbol() : callee.getSymbol();
|
|
13757
|
+
const declarations = symbol?.getAliasedSymbol()?.getDeclarations() ?? symbol?.getDeclarations() ?? [];
|
|
13758
|
+
for (const declaration of declarations) {
|
|
13759
|
+
const callable = asCallable(declaration);
|
|
13760
|
+
if (callable !== null) {
|
|
13761
|
+
return callable;
|
|
13762
|
+
}
|
|
13763
|
+
}
|
|
13764
|
+
const written = ctx.resolve(callee);
|
|
13765
|
+
return written === null || written === callee ? null : declarationOf2(written, { ...ctx, resolve: () => null });
|
|
13766
|
+
}
|
|
13767
|
+
function asCallable(declaration) {
|
|
13768
|
+
if (import_ts_morph58.Node.isFunctionDeclaration(declaration) || import_ts_morph58.Node.isMethodDeclaration(declaration) || import_ts_morph58.Node.isArrowFunction(declaration) || import_ts_morph58.Node.isFunctionExpression(declaration)) {
|
|
13769
|
+
return declaration;
|
|
13770
|
+
}
|
|
13771
|
+
if (!import_ts_morph58.Node.isVariableDeclaration(declaration)) {
|
|
13772
|
+
return null;
|
|
13773
|
+
}
|
|
13774
|
+
const initializer = declaration.getInitializer();
|
|
13775
|
+
if (initializer !== void 0 && (import_ts_morph58.Node.isArrowFunction(initializer) || import_ts_morph58.Node.isFunctionExpression(initializer))) {
|
|
13776
|
+
return initializer;
|
|
13777
|
+
}
|
|
13778
|
+
return null;
|
|
13779
|
+
}
|
|
13780
|
+
function bind(parameters, args, scope) {
|
|
13781
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
13782
|
+
parameters.forEach((parameter, index) => {
|
|
13783
|
+
const passed = parameter.rest ? args.slice(index) : args.slice(index, index + 1);
|
|
13784
|
+
if (passed.length > 0) {
|
|
13785
|
+
bindings.set(
|
|
13786
|
+
parameter.name,
|
|
13787
|
+
passed.map((node) => ({ node, scope }))
|
|
13788
|
+
);
|
|
13789
|
+
}
|
|
13790
|
+
});
|
|
13791
|
+
return bindings;
|
|
13792
|
+
}
|
|
13793
|
+
function here(node, ctx) {
|
|
13794
|
+
return { node, scope: ctx.bindings };
|
|
13795
|
+
}
|
|
13796
|
+
function boundOnce(expr, ctx) {
|
|
13797
|
+
const bound = import_ts_morph58.Node.isIdentifier(expr) ? ctx.bindings.get(expr.getText()) : void 0;
|
|
13798
|
+
return bound !== void 0 && bound.length === 1 ? bound[0] : null;
|
|
13799
|
+
}
|
|
13800
|
+
function readOrHole(expr, ctx) {
|
|
13801
|
+
const name = read(expr, ctx);
|
|
13802
|
+
return name ?? `{${holeName(expr, ctx)}}`;
|
|
13803
|
+
}
|
|
13804
|
+
function holeName(expr, ctx) {
|
|
13805
|
+
const bound = boundOnce(expr, ctx);
|
|
13806
|
+
if (bound !== null) {
|
|
13807
|
+
return holeName(bound.node, { ...ctx, bindings: bound.scope });
|
|
13808
|
+
}
|
|
13809
|
+
if (import_ts_morph58.Node.isIdentifier(expr)) {
|
|
13810
|
+
return expr.getText();
|
|
13811
|
+
}
|
|
13812
|
+
if (import_ts_morph58.Node.isPropertyAccessExpression(expr)) {
|
|
13813
|
+
return expr.getName();
|
|
13814
|
+
}
|
|
13815
|
+
return UNNAMED_HOLE;
|
|
13816
|
+
}
|
|
13490
13817
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13491
13818
|
0 && (module.exports = {
|
|
13492
13819
|
ADAPTER_VERSION,
|
|
@@ -13508,10 +13835,12 @@ function formatPackHealth(checks, audiences) {
|
|
|
13508
13835
|
findTerminals,
|
|
13509
13836
|
formatPackHealth,
|
|
13510
13837
|
isImportedFrom,
|
|
13838
|
+
methodDeclaredIn,
|
|
13511
13839
|
parseConditionExpression,
|
|
13512
13840
|
readConfiguredCall,
|
|
13513
13841
|
readContract,
|
|
13514
13842
|
readContractForClientCall,
|
|
13843
|
+
readName,
|
|
13515
13844
|
resolveAliasedSymbol,
|
|
13516
13845
|
resolveSubject,
|
|
13517
13846
|
rootIdentifier
|
package/dist/index.d.cts
CHANGED
|
@@ -820,6 +820,39 @@ declare function formatPackHealth(checks: ReadonlyArray<HealthCheck>, audiences:
|
|
|
820
820
|
declare function parseConditionExpression(expr: Expression, depth?: number): Predicate | null;
|
|
821
821
|
|
|
822
822
|
declare function isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
823
|
+
/**
|
|
824
|
+
* Whether `expectedModule` declares the method a call goes to. A pack
|
|
825
|
+
* asks this when the receiver came from somewhere the source does not
|
|
826
|
+
* spell out: `const redis = await this.getClient()` says nothing about
|
|
827
|
+
* ioredis, and the type of `redis.get` says everything.
|
|
828
|
+
*/
|
|
829
|
+
declare function methodDeclaredIn(callee: Node, expectedModule: string): boolean;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* What a name-valued expression says, as fixed text with a hole for
|
|
833
|
+
* each part built at run time. A table name, a bucket, a queue URL and
|
|
834
|
+
* a cache key are all built the same handful of ways, and each storage
|
|
835
|
+
* pack had its own copy of this before it existed. The README beside
|
|
836
|
+
* this file says what each shape reads as.
|
|
837
|
+
*/
|
|
838
|
+
|
|
839
|
+
interface ReadNameOptions {
|
|
840
|
+
/**
|
|
841
|
+
* What to say about a name nothing here settles. `"nothing"` gives
|
|
842
|
+
* null. `"reference"` gives a hole named after what the source asked
|
|
843
|
+
* for, `{location.bucket}`, which says which value to go and ask
|
|
844
|
+
* about rather than which bucket this is.
|
|
845
|
+
*/
|
|
846
|
+
unsettled?: "nothing" | "reference";
|
|
847
|
+
/**
|
|
848
|
+
* The expression a value was written as, from the run's facts. A
|
|
849
|
+
* caller with no store passes nothing, and the read runs on what the
|
|
850
|
+
* source spells at the call site.
|
|
851
|
+
*/
|
|
852
|
+
resolve?: (value: Node) => Node | null;
|
|
853
|
+
}
|
|
854
|
+
/** The name an expression states, or null when nothing settles it. */
|
|
855
|
+
declare function readName(expr: Node, options?: ReadNameOptions): string | null;
|
|
823
856
|
|
|
824
857
|
interface BranchFieldAccesses {
|
|
825
858
|
/** Terminal location (start, end lines): used to match back to transitions */
|
|
@@ -952,4 +985,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
|
|
|
952
985
|
version?: string;
|
|
953
986
|
}>): string;
|
|
954
987
|
|
|
955
|
-
export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, resolveAliasedSymbol, resolveSubject, rootIdentifier };
|
|
988
|
+
export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier };
|
package/dist/index.d.ts
CHANGED
|
@@ -820,6 +820,39 @@ declare function formatPackHealth(checks: ReadonlyArray<HealthCheck>, audiences:
|
|
|
820
820
|
declare function parseConditionExpression(expr: Expression, depth?: number): Predicate | null;
|
|
821
821
|
|
|
822
822
|
declare function isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
823
|
+
/**
|
|
824
|
+
* Whether `expectedModule` declares the method a call goes to. A pack
|
|
825
|
+
* asks this when the receiver came from somewhere the source does not
|
|
826
|
+
* spell out: `const redis = await this.getClient()` says nothing about
|
|
827
|
+
* ioredis, and the type of `redis.get` says everything.
|
|
828
|
+
*/
|
|
829
|
+
declare function methodDeclaredIn(callee: Node, expectedModule: string): boolean;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* What a name-valued expression says, as fixed text with a hole for
|
|
833
|
+
* each part built at run time. A table name, a bucket, a queue URL and
|
|
834
|
+
* a cache key are all built the same handful of ways, and each storage
|
|
835
|
+
* pack had its own copy of this before it existed. The README beside
|
|
836
|
+
* this file says what each shape reads as.
|
|
837
|
+
*/
|
|
838
|
+
|
|
839
|
+
interface ReadNameOptions {
|
|
840
|
+
/**
|
|
841
|
+
* What to say about a name nothing here settles. `"nothing"` gives
|
|
842
|
+
* null. `"reference"` gives a hole named after what the source asked
|
|
843
|
+
* for, `{location.bucket}`, which says which value to go and ask
|
|
844
|
+
* about rather than which bucket this is.
|
|
845
|
+
*/
|
|
846
|
+
unsettled?: "nothing" | "reference";
|
|
847
|
+
/**
|
|
848
|
+
* The expression a value was written as, from the run's facts. A
|
|
849
|
+
* caller with no store passes nothing, and the read runs on what the
|
|
850
|
+
* source spells at the call site.
|
|
851
|
+
*/
|
|
852
|
+
resolve?: (value: Node) => Node | null;
|
|
853
|
+
}
|
|
854
|
+
/** The name an expression states, or null when nothing settles it. */
|
|
855
|
+
declare function readName(expr: Node, options?: ReadNameOptions): string | null;
|
|
823
856
|
|
|
824
857
|
interface BranchFieldAccesses {
|
|
825
858
|
/** Terminal location (start, end lines): used to match back to transitions */
|
|
@@ -952,4 +985,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
|
|
|
952
985
|
version?: string;
|
|
953
986
|
}>): string;
|
|
954
987
|
|
|
955
|
-
export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, resolveAliasedSymbol, resolveSubject, rootIdentifier };
|
|
988
|
+
export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier };
|
package/dist/index.js
CHANGED
|
@@ -1451,9 +1451,9 @@ var ModuleGraph = class {
|
|
|
1451
1451
|
if (known !== void 0) {
|
|
1452
1452
|
return known;
|
|
1453
1453
|
}
|
|
1454
|
-
const
|
|
1455
|
-
this.specifiers.set(filePath,
|
|
1456
|
-
return
|
|
1454
|
+
const read2 = readModuleSpecifiers(sourceFile);
|
|
1455
|
+
this.specifiers.set(filePath, read2);
|
|
1456
|
+
return read2;
|
|
1457
1457
|
}
|
|
1458
1458
|
/**
|
|
1459
1459
|
* Collect what the rules need in order to settle this file and this
|
|
@@ -2216,6 +2216,15 @@ function isImportedFrom(identifier, expectedModule) {
|
|
|
2216
2216
|
(decl) => decl.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2217
2217
|
);
|
|
2218
2218
|
}
|
|
2219
|
+
function methodDeclaredIn(callee, expectedModule) {
|
|
2220
|
+
if (!Node11.isPropertyAccessExpression(callee)) {
|
|
2221
|
+
return false;
|
|
2222
|
+
}
|
|
2223
|
+
const declarations = callee.getNameNode().getSymbol()?.getDeclarations();
|
|
2224
|
+
return declarations !== void 0 && declarations.some(
|
|
2225
|
+
(declaration) => declaration.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2226
|
+
);
|
|
2227
|
+
}
|
|
2219
2228
|
function importSpecifierMatches(decl, expectedModule) {
|
|
2220
2229
|
if (Node11.isImportSpecifier(decl)) {
|
|
2221
2230
|
return decl.getImportDeclaration().getModuleSpecifierValue() === expectedModule;
|
|
@@ -2394,7 +2403,7 @@ function dispatchAccessRecognizers(root, recognizers, isStop, resolveWrittenValu
|
|
|
2394
2403
|
traversal.skip();
|
|
2395
2404
|
return;
|
|
2396
2405
|
}
|
|
2397
|
-
if (!Node11.isPropertyAccessExpression(node) && !Node11.isCallExpression(node)) {
|
|
2406
|
+
if (!Node11.isPropertyAccessExpression(node) && !Node11.isCallExpression(node) && !Node11.isTaggedTemplateExpression(node)) {
|
|
2398
2407
|
return;
|
|
2399
2408
|
}
|
|
2400
2409
|
const ctx = {
|
|
@@ -2824,12 +2833,12 @@ function createDefinitionTable() {
|
|
|
2824
2833
|
}
|
|
2825
2834
|
};
|
|
2826
2835
|
}
|
|
2827
|
-
function withDefinitions(
|
|
2836
|
+
function withDefinitions(read2) {
|
|
2828
2837
|
const table = createDefinitionTable();
|
|
2829
2838
|
const outer = current;
|
|
2830
2839
|
current = table;
|
|
2831
2840
|
try {
|
|
2832
|
-
return { value:
|
|
2841
|
+
return { value: read2(), definitions: table.collected() };
|
|
2833
2842
|
} finally {
|
|
2834
2843
|
current = outer;
|
|
2835
2844
|
}
|
|
@@ -3975,10 +3984,59 @@ function writesToBindingUncached(declaration) {
|
|
|
3975
3984
|
}
|
|
3976
3985
|
return { values, inOrder: writesRunInOrder(declaration, writes) };
|
|
3977
3986
|
}
|
|
3987
|
+
function writesToField(declaration) {
|
|
3988
|
+
const remembered = byDeclaration.get(declaration);
|
|
3989
|
+
if (remembered !== void 0) {
|
|
3990
|
+
return remembered;
|
|
3991
|
+
}
|
|
3992
|
+
const answer = writesToFieldUncached(declaration);
|
|
3993
|
+
byDeclaration.set(declaration, answer);
|
|
3994
|
+
return answer;
|
|
3995
|
+
}
|
|
3996
|
+
function writesToFieldUncached(declaration) {
|
|
3997
|
+
const initializer = declaration.getInitializer();
|
|
3998
|
+
const assignments = assignmentsTo(declaration);
|
|
3999
|
+
if (assignments.length === 0) {
|
|
4000
|
+
return {
|
|
4001
|
+
values: initializer === void 0 ? [] : [initializer],
|
|
4002
|
+
inOrder: true
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
const values = [];
|
|
4006
|
+
for (const write of assignments) {
|
|
4007
|
+
if (write.value === null) {
|
|
4008
|
+
return { values: [], inOrder: false };
|
|
4009
|
+
}
|
|
4010
|
+
values.push(write.value);
|
|
4011
|
+
}
|
|
4012
|
+
const withInitializer = initializer === void 0 ? values : [initializer, ...values];
|
|
4013
|
+
return {
|
|
4014
|
+
values: withInitializer,
|
|
4015
|
+
inOrder: assignments.every(
|
|
4016
|
+
(write) => writeRunsInConstructor(declaration, write)
|
|
4017
|
+
)
|
|
4018
|
+
};
|
|
4019
|
+
}
|
|
4020
|
+
function writeRunsInConstructor(declaration, write) {
|
|
4021
|
+
const statement = statementOf(write.node);
|
|
4022
|
+
if (statement === null) {
|
|
4023
|
+
return false;
|
|
4024
|
+
}
|
|
4025
|
+
const body = statement.getParent();
|
|
4026
|
+
if (body === void 0 || !Node17.isBlock(body)) {
|
|
4027
|
+
return false;
|
|
4028
|
+
}
|
|
4029
|
+
const owner = body.getParent();
|
|
4030
|
+
return owner !== void 0 && Node17.isConstructorDeclaration(owner) && owner.getParent() === declaration.getParent();
|
|
4031
|
+
}
|
|
3978
4032
|
function isWrittenAgain(declaration) {
|
|
3979
4033
|
return assignmentsTo(declaration).length > 0;
|
|
3980
4034
|
}
|
|
3981
4035
|
function assignmentsTo(declaration) {
|
|
4036
|
+
if (Node17.isPropertyDeclaration(declaration)) {
|
|
4037
|
+
const sourceFile2 = declaration.getSourceFile();
|
|
4038
|
+
return sourceFile2.isDeclarationFile() ? [] : assignmentsInFile(sourceFile2).get(declaration) ?? [];
|
|
4039
|
+
}
|
|
3982
4040
|
if (declaration.getVariableStatement()?.getDeclarationKind() === VariableDeclarationKind.Const) {
|
|
3983
4041
|
return [];
|
|
3984
4042
|
}
|
|
@@ -4018,7 +4076,7 @@ function writeAt(node) {
|
|
|
4018
4076
|
if (Node17.isBinaryExpression(node)) {
|
|
4019
4077
|
const operator = node.getOperatorToken().getKind();
|
|
4020
4078
|
const target = node.getLeft();
|
|
4021
|
-
if (!isAssignmentOperator(operator) || !Node17.isIdentifier(target)) {
|
|
4079
|
+
if (!isAssignmentOperator(operator) || !(Node17.isIdentifier(target) || Node17.isPropertyAccessExpression(target))) {
|
|
4022
4080
|
return null;
|
|
4023
4081
|
}
|
|
4024
4082
|
const value = operator === SyntaxKind5.EqualsToken ? node.getRight() : null;
|
|
@@ -4035,13 +4093,14 @@ function writeAt(node) {
|
|
|
4035
4093
|
return null;
|
|
4036
4094
|
}
|
|
4037
4095
|
function declarationsOf(name) {
|
|
4038
|
-
const
|
|
4096
|
+
const nameNode = Node17.isPropertyAccessExpression(name) ? name.getNameNode() : name;
|
|
4097
|
+
const symbol = nameNode.getSymbol();
|
|
4039
4098
|
if (symbol === void 0) {
|
|
4040
4099
|
return [];
|
|
4041
4100
|
}
|
|
4042
4101
|
const declarations = [];
|
|
4043
4102
|
for (const declaration of symbol.getDeclarations()) {
|
|
4044
|
-
if (Node17.isVariableDeclaration(declaration)) {
|
|
4103
|
+
if (Node17.isVariableDeclaration(declaration) || Node17.isPropertyDeclaration(declaration)) {
|
|
4045
4104
|
declarations.push(declaration);
|
|
4046
4105
|
}
|
|
4047
4106
|
}
|
|
@@ -4071,9 +4130,9 @@ function statementOf(node) {
|
|
|
4071
4130
|
function isReadBefore(declaration, position) {
|
|
4072
4131
|
const name = declaration.getName();
|
|
4073
4132
|
const sourceFile = declaration.getSourceFile();
|
|
4074
|
-
let
|
|
4133
|
+
let read2 = false;
|
|
4075
4134
|
sourceFile.forEachDescendant((node, traversal) => {
|
|
4076
|
-
if (
|
|
4135
|
+
if (read2) {
|
|
4077
4136
|
traversal.stop();
|
|
4078
4137
|
return;
|
|
4079
4138
|
}
|
|
@@ -4092,10 +4151,10 @@ function isReadBefore(declaration, position) {
|
|
|
4092
4151
|
return;
|
|
4093
4152
|
}
|
|
4094
4153
|
if (declarationsOf(node).includes(declaration)) {
|
|
4095
|
-
|
|
4154
|
+
read2 = true;
|
|
4096
4155
|
}
|
|
4097
4156
|
});
|
|
4098
|
-
return
|
|
4157
|
+
return read2;
|
|
4099
4158
|
}
|
|
4100
4159
|
function startsItsOwnBody(node) {
|
|
4101
4160
|
return Node17.isFunctionDeclaration(node) || Node17.isFunctionExpression(node) || Node17.isArrowFunction(node) || Node17.isMethodDeclaration(node) || Node17.isClassDeclaration(node);
|
|
@@ -6070,6 +6129,14 @@ function emitBindingValues(db, table, declaration) {
|
|
|
6070
6129
|
}
|
|
6071
6130
|
fact(db, "endsHolding", declarationId, emitValue(db, table, last));
|
|
6072
6131
|
}
|
|
6132
|
+
function emitFieldValues(db, table, declaration) {
|
|
6133
|
+
const { values, inOrder } = writesToField(declaration);
|
|
6134
|
+
const last = values[values.length - 1];
|
|
6135
|
+
if (!inOrder || last === void 0) {
|
|
6136
|
+
return;
|
|
6137
|
+
}
|
|
6138
|
+
fact(db, "binds", nodeId(declaration), emitValue(db, table, last));
|
|
6139
|
+
}
|
|
6073
6140
|
function emitBindingElementFacts(db, table, element) {
|
|
6074
6141
|
const id = nodeId(element);
|
|
6075
6142
|
table.byId.set(id, element);
|
|
@@ -6145,6 +6212,11 @@ function emitReferenceFacts(db, table, reference) {
|
|
|
6145
6212
|
emitBindingValues(db, table, declaration);
|
|
6146
6213
|
continue;
|
|
6147
6214
|
}
|
|
6215
|
+
if (Node26.isPropertyDeclaration(declaration)) {
|
|
6216
|
+
fact(db, "binds", referenceId, declarationId);
|
|
6217
|
+
emitFieldValues(db, table, declaration);
|
|
6218
|
+
continue;
|
|
6219
|
+
}
|
|
6148
6220
|
if (Node26.isParameterDeclaration(declaration)) {
|
|
6149
6221
|
fact(db, "binds", referenceId, declarationId);
|
|
6150
6222
|
continue;
|
|
@@ -6379,9 +6451,9 @@ function propertyValueOf(property) {
|
|
|
6379
6451
|
}
|
|
6380
6452
|
function functionValueOf(value, resolution) {
|
|
6381
6453
|
const written = factKeyOf(value);
|
|
6382
|
-
const
|
|
6383
|
-
if (
|
|
6384
|
-
return
|
|
6454
|
+
const here2 = toFunctionRoot(written);
|
|
6455
|
+
if (here2 !== null) {
|
|
6456
|
+
return here2;
|
|
6385
6457
|
}
|
|
6386
6458
|
if (resolution === void 0 || !couldNameAValue(written)) {
|
|
6387
6459
|
return null;
|
|
@@ -8143,7 +8215,7 @@ function unitsOfArrayElements(array, match, kind, resolution, prefix, ancestry)
|
|
|
8143
8215
|
}
|
|
8144
8216
|
function unitsForRouteObject(object, match, kind, resolution, prefix, ancestry) {
|
|
8145
8217
|
const own = ownPathOfObject(object, match);
|
|
8146
|
-
const
|
|
8218
|
+
const here2 = unitForRouteObject(object, match, kind, resolution, prefix, own);
|
|
8147
8219
|
const nested = unitsUnderRouteObject(
|
|
8148
8220
|
object,
|
|
8149
8221
|
match,
|
|
@@ -8152,7 +8224,7 @@ function unitsForRouteObject(object, match, kind, resolution, prefix, ancestry)
|
|
|
8152
8224
|
prefixUnder(prefix, own),
|
|
8153
8225
|
ancestry
|
|
8154
8226
|
);
|
|
8155
|
-
return
|
|
8227
|
+
return here2 === null ? nested : [here2, ...nested];
|
|
8156
8228
|
}
|
|
8157
8229
|
function unitForRouteObject(object, match, kind, resolution, prefix, own) {
|
|
8158
8230
|
const target = elementTargetOfValue(
|
|
@@ -8640,6 +8712,9 @@ function trackFactoryBindings(sourceFile, recognize) {
|
|
|
8640
8712
|
}
|
|
8641
8713
|
|
|
8642
8714
|
// src/discovery/packageImport.ts
|
|
8715
|
+
function isLanguageLib(file) {
|
|
8716
|
+
return /[\\/]typescript[\\/]lib[\\/]lib\..*\.d\.ts$/.test(file.getFilePath());
|
|
8717
|
+
}
|
|
8643
8718
|
function splitPackageSpec(spec) {
|
|
8644
8719
|
if (spec.startsWith("@")) {
|
|
8645
8720
|
const parts2 = spec.split("/");
|
|
@@ -8757,6 +8832,9 @@ function discoverPackageImports(sourceFile, match, kind) {
|
|
|
8757
8832
|
if (subjectProvenance === null) {
|
|
8758
8833
|
return null;
|
|
8759
8834
|
}
|
|
8835
|
+
if (!methodComesFromSource(callee)) {
|
|
8836
|
+
return subjectProvenance;
|
|
8837
|
+
}
|
|
8760
8838
|
return {
|
|
8761
8839
|
packageName: subjectProvenance.packageName,
|
|
8762
8840
|
exportPath: [...subjectProvenance.exportPath, callee.getName()]
|
|
@@ -8764,6 +8842,15 @@ function discoverPackageImports(sourceFile, match, kind) {
|
|
|
8764
8842
|
}
|
|
8765
8843
|
return null;
|
|
8766
8844
|
}
|
|
8845
|
+
function methodComesFromSource(callee) {
|
|
8846
|
+
const declarations = callee.getNameNode().getSymbol()?.getDeclarations();
|
|
8847
|
+
if (declarations === void 0 || declarations.length === 0) {
|
|
8848
|
+
return true;
|
|
8849
|
+
}
|
|
8850
|
+
return declarations.some(
|
|
8851
|
+
(declaration) => !isLanguageLib(declaration.getSourceFile())
|
|
8852
|
+
);
|
|
8853
|
+
}
|
|
8767
8854
|
const results = [];
|
|
8768
8855
|
const seen = /* @__PURE__ */ new Set();
|
|
8769
8856
|
sourceFile.forEachDescendant((node) => {
|
|
@@ -10381,8 +10468,8 @@ function bindingLabel(binding) {
|
|
|
10381
10468
|
if (semantics.name === "rest") {
|
|
10382
10469
|
return `${semantics.method} ${semantics.path}`;
|
|
10383
10470
|
}
|
|
10384
|
-
if (semantics.name === "storage
|
|
10385
|
-
return `${semantics.storageSystem}:${semantics.
|
|
10471
|
+
if (semantics.name === "storage") {
|
|
10472
|
+
return `${semantics.storageSystem}:${semantics.container}`;
|
|
10386
10473
|
}
|
|
10387
10474
|
if (semantics.name === "message-bus") {
|
|
10388
10475
|
return `${semantics.messageBus}:${semantics.channel}`;
|
|
@@ -10616,7 +10703,9 @@ function extractReachableSummary(candidate, options, recognizers) {
|
|
|
10616
10703
|
unit,
|
|
10617
10704
|
reachablePack,
|
|
10618
10705
|
recognizers.invocation,
|
|
10619
|
-
recognizers.access
|
|
10706
|
+
recognizers.access,
|
|
10707
|
+
void 0,
|
|
10708
|
+
recognizers.resolveWrittenValue
|
|
10620
10709
|
);
|
|
10621
10710
|
raw.boundaryBinding = functionCallBinding({
|
|
10622
10711
|
transport: "in-process",
|
|
@@ -11927,7 +12016,7 @@ function announcedBoundaryStructure(unit) {
|
|
|
11927
12016
|
};
|
|
11928
12017
|
}
|
|
11929
12018
|
function extractCodeStructure(unit, pack, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolveWrittenValue) {
|
|
11930
|
-
const
|
|
12019
|
+
const read2 = withDefinitions(
|
|
11931
12020
|
() => readCodeStructure(
|
|
11932
12021
|
unit,
|
|
11933
12022
|
pack,
|
|
@@ -11937,7 +12026,7 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
11937
12026
|
resolveWrittenValue
|
|
11938
12027
|
)
|
|
11939
12028
|
);
|
|
11940
|
-
return
|
|
12029
|
+
return read2.definitions === null ? read2.value : { ...read2.value, definitions: read2.definitions };
|
|
11941
12030
|
}
|
|
11942
12031
|
function responseAccessorNames(pack, kind) {
|
|
11943
12032
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
@@ -13062,7 +13151,8 @@ function createTypeScriptAdapter(config) {
|
|
|
13062
13151
|
config.frameworks,
|
|
13063
13152
|
tallies
|
|
13064
13153
|
),
|
|
13065
|
-
access: collectAccessRecognizers(config.frameworks, tallies)
|
|
13154
|
+
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13155
|
+
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value)
|
|
13066
13156
|
}
|
|
13067
13157
|
)
|
|
13068
13158
|
) : withSubUnits;
|
|
@@ -13446,7 +13536,7 @@ function threwWhileReading(packs) {
|
|
|
13446
13536
|
return packs.filter((funnel) => funnel.failures.length > 0).map((funnel) => {
|
|
13447
13537
|
const first = funnel.failures[0];
|
|
13448
13538
|
const rest = funnel.failures.length - 1;
|
|
13449
|
-
const alsoIn = rest > 0 ? ` and on ${rest}
|
|
13539
|
+
const alsoIn = rest > 0 ? ` and on ${rest} ${rest === 1 ? "other file" : "other files"}` : "";
|
|
13450
13540
|
return {
|
|
13451
13541
|
label: funnel.pack,
|
|
13452
13542
|
detail: `threw from ${first.hook} on ${first.file}${alsoIn}, so its counts below are a floor: ${first.message}`
|
|
@@ -13498,6 +13588,241 @@ function formatPackHealth(checks, audiences) {
|
|
|
13498
13588
|
return `${lines.join("\n")}
|
|
13499
13589
|
`;
|
|
13500
13590
|
}
|
|
13591
|
+
|
|
13592
|
+
// src/resolve/readName.ts
|
|
13593
|
+
import { Node as Node55, SyntaxKind as SyntaxKind10 } from "ts-morph";
|
|
13594
|
+
var MAX_HELPER_HOPS = 2;
|
|
13595
|
+
var UNNAMED_HOLE = "param";
|
|
13596
|
+
function readName(expr, options = {}) {
|
|
13597
|
+
const name = read(expr, {
|
|
13598
|
+
resolve: options.resolve ?? (() => null),
|
|
13599
|
+
bindings: /* @__PURE__ */ new Map(),
|
|
13600
|
+
hops: 0,
|
|
13601
|
+
seen: /* @__PURE__ */ new Set(),
|
|
13602
|
+
insideHole: false
|
|
13603
|
+
});
|
|
13604
|
+
if (name !== null || options.unsettled !== "reference") {
|
|
13605
|
+
return name;
|
|
13606
|
+
}
|
|
13607
|
+
const asked = holeName(expr, {
|
|
13608
|
+
resolve: () => null,
|
|
13609
|
+
bindings: /* @__PURE__ */ new Map(),
|
|
13610
|
+
hops: 0,
|
|
13611
|
+
seen: /* @__PURE__ */ new Set(),
|
|
13612
|
+
insideHole: true
|
|
13613
|
+
});
|
|
13614
|
+
return asked === UNNAMED_HOLE ? null : `{${asked}}`;
|
|
13615
|
+
}
|
|
13616
|
+
function read(expr, ctx) {
|
|
13617
|
+
if (ctx.seen.has(expr)) {
|
|
13618
|
+
return null;
|
|
13619
|
+
}
|
|
13620
|
+
const seen = new Set(ctx.seen).add(expr);
|
|
13621
|
+
const inner = { ...ctx, seen };
|
|
13622
|
+
if (Node55.isStringLiteral(expr) || Node55.isNoSubstitutionTemplateLiteral(expr)) {
|
|
13623
|
+
return expr.getLiteralValue();
|
|
13624
|
+
}
|
|
13625
|
+
if (Node55.isNumericLiteral(expr)) {
|
|
13626
|
+
return expr.getLiteralText();
|
|
13627
|
+
}
|
|
13628
|
+
if (Node55.isTemplateExpression(expr)) {
|
|
13629
|
+
return fromTemplate(expr, inner);
|
|
13630
|
+
}
|
|
13631
|
+
if (Node55.isParenthesizedExpression(expr)) {
|
|
13632
|
+
return read(expr.getExpression(), inner);
|
|
13633
|
+
}
|
|
13634
|
+
if (Node55.isBinaryExpression(expr)) {
|
|
13635
|
+
return fromBinary(expr, inner);
|
|
13636
|
+
}
|
|
13637
|
+
if (Node55.isCallExpression(expr)) {
|
|
13638
|
+
return fromCall(expr, inner);
|
|
13639
|
+
}
|
|
13640
|
+
if (Node55.isIdentifier(expr)) {
|
|
13641
|
+
const only = boundOnce(expr, ctx);
|
|
13642
|
+
if (only !== null) {
|
|
13643
|
+
return read(only.node, { ...inner, bindings: only.scope });
|
|
13644
|
+
}
|
|
13645
|
+
}
|
|
13646
|
+
const written = ctx.resolve(expr);
|
|
13647
|
+
return written === null || written === expr ? null : read(written, inner);
|
|
13648
|
+
}
|
|
13649
|
+
function fromTemplate(expr, ctx) {
|
|
13650
|
+
if (!Node55.isTemplateExpression(expr)) {
|
|
13651
|
+
return null;
|
|
13652
|
+
}
|
|
13653
|
+
let name = expr.getHead().getLiteralText();
|
|
13654
|
+
for (const span of expr.getTemplateSpans()) {
|
|
13655
|
+
name += readOrHole(span.getExpression(), { ...ctx, insideHole: true });
|
|
13656
|
+
name += span.getLiteral().getLiteralText();
|
|
13657
|
+
}
|
|
13658
|
+
return name;
|
|
13659
|
+
}
|
|
13660
|
+
function fromBinary(expr, ctx) {
|
|
13661
|
+
if (!Node55.isBinaryExpression(expr)) {
|
|
13662
|
+
return null;
|
|
13663
|
+
}
|
|
13664
|
+
const operator = expr.getOperatorToken().getKind();
|
|
13665
|
+
if (operator === SyntaxKind10.BarBarToken || operator === SyntaxKind10.QuestionQuestionToken) {
|
|
13666
|
+
return ctx.insideHole ? null : read(expr.getRight(), ctx);
|
|
13667
|
+
}
|
|
13668
|
+
if (operator !== SyntaxKind10.PlusToken) {
|
|
13669
|
+
return null;
|
|
13670
|
+
}
|
|
13671
|
+
const parts = { ...ctx, insideHole: true };
|
|
13672
|
+
return readOrHole(expr.getLeft(), parts) + readOrHole(expr.getRight(), parts);
|
|
13673
|
+
}
|
|
13674
|
+
function fromCall(expr, ctx) {
|
|
13675
|
+
if (!Node55.isCallExpression(expr)) {
|
|
13676
|
+
return null;
|
|
13677
|
+
}
|
|
13678
|
+
const callee = expr.getExpression();
|
|
13679
|
+
if (Node55.isPropertyAccessExpression(callee) && callee.getName() === "join") {
|
|
13680
|
+
return fromJoin(callee.getExpression(), expr.getArguments(), ctx);
|
|
13681
|
+
}
|
|
13682
|
+
if (Node55.isIdentifier(callee) && callee.getText() === "String") {
|
|
13683
|
+
const only = expr.getArguments()[0];
|
|
13684
|
+
return only === void 0 ? null : readOrHole(only, ctx);
|
|
13685
|
+
}
|
|
13686
|
+
if (ctx.hops >= MAX_HELPER_HOPS) {
|
|
13687
|
+
return null;
|
|
13688
|
+
}
|
|
13689
|
+
const helper = singleReturnBody(callee, ctx);
|
|
13690
|
+
if (helper === null) {
|
|
13691
|
+
return null;
|
|
13692
|
+
}
|
|
13693
|
+
return read(helper.returned, {
|
|
13694
|
+
...ctx,
|
|
13695
|
+
hops: ctx.hops + 1,
|
|
13696
|
+
bindings: bind(helper.parameters, expr.getArguments(), ctx.bindings)
|
|
13697
|
+
});
|
|
13698
|
+
}
|
|
13699
|
+
function fromJoin(subject, args, ctx) {
|
|
13700
|
+
const separator = args[0];
|
|
13701
|
+
if (separator === void 0 || !Node55.isStringLiteral(separator)) {
|
|
13702
|
+
return null;
|
|
13703
|
+
}
|
|
13704
|
+
const parts = elementsOf(subject, ctx);
|
|
13705
|
+
if (parts === null) {
|
|
13706
|
+
return null;
|
|
13707
|
+
}
|
|
13708
|
+
return parts.map(
|
|
13709
|
+
(part) => readOrHole(part.node, {
|
|
13710
|
+
...ctx,
|
|
13711
|
+
bindings: part.scope,
|
|
13712
|
+
insideHole: true
|
|
13713
|
+
})
|
|
13714
|
+
).join(separator.getLiteralValue());
|
|
13715
|
+
}
|
|
13716
|
+
function elementsOf(subject, ctx) {
|
|
13717
|
+
if (Node55.isArrayLiteralExpression(subject)) {
|
|
13718
|
+
return subject.getElements().map((element) => here(element, ctx));
|
|
13719
|
+
}
|
|
13720
|
+
if (Node55.isCallExpression(subject)) {
|
|
13721
|
+
const callee = subject.getExpression();
|
|
13722
|
+
if (Node55.isPropertyAccessExpression(callee) && callee.getName() === "map") {
|
|
13723
|
+
return elementsOf(callee.getExpression(), ctx);
|
|
13724
|
+
}
|
|
13725
|
+
return null;
|
|
13726
|
+
}
|
|
13727
|
+
if (!Node55.isIdentifier(subject)) {
|
|
13728
|
+
return null;
|
|
13729
|
+
}
|
|
13730
|
+
const bound = ctx.bindings.get(subject.getText());
|
|
13731
|
+
if (bound === void 0) {
|
|
13732
|
+
return null;
|
|
13733
|
+
}
|
|
13734
|
+
const only = bound.length === 1 ? bound[0] : void 0;
|
|
13735
|
+
return only !== void 0 && Node55.isArrayLiteralExpression(only.node) ? only.node.getElements().map((element) => here(element, ctx)) : bound;
|
|
13736
|
+
}
|
|
13737
|
+
function singleReturnBody(callee, ctx) {
|
|
13738
|
+
const declaration = declarationOf2(callee, ctx);
|
|
13739
|
+
if (declaration === null) {
|
|
13740
|
+
return null;
|
|
13741
|
+
}
|
|
13742
|
+
const parameters = declaration.getParameters().map((parameter) => ({
|
|
13743
|
+
name: parameter.getName(),
|
|
13744
|
+
rest: parameter.isRestParameter()
|
|
13745
|
+
}));
|
|
13746
|
+
const body = declaration.getBody();
|
|
13747
|
+
if (body === void 0) {
|
|
13748
|
+
return null;
|
|
13749
|
+
}
|
|
13750
|
+
if (Node55.isExpression(body)) {
|
|
13751
|
+
return { parameters, returned: body };
|
|
13752
|
+
}
|
|
13753
|
+
if (!Node55.isBlock(body)) {
|
|
13754
|
+
return null;
|
|
13755
|
+
}
|
|
13756
|
+
const statements = body.getStatements();
|
|
13757
|
+
const only = statements[0];
|
|
13758
|
+
if (statements.length !== 1 || only === void 0 || !Node55.isReturnStatement(only)) {
|
|
13759
|
+
return null;
|
|
13760
|
+
}
|
|
13761
|
+
const returned = only.getExpression();
|
|
13762
|
+
return returned === void 0 ? null : { parameters, returned };
|
|
13763
|
+
}
|
|
13764
|
+
function declarationOf2(callee, ctx) {
|
|
13765
|
+
const symbol = Node55.isPropertyAccessExpression(callee) ? callee.getNameNode().getSymbol() : callee.getSymbol();
|
|
13766
|
+
const declarations = symbol?.getAliasedSymbol()?.getDeclarations() ?? symbol?.getDeclarations() ?? [];
|
|
13767
|
+
for (const declaration of declarations) {
|
|
13768
|
+
const callable = asCallable(declaration);
|
|
13769
|
+
if (callable !== null) {
|
|
13770
|
+
return callable;
|
|
13771
|
+
}
|
|
13772
|
+
}
|
|
13773
|
+
const written = ctx.resolve(callee);
|
|
13774
|
+
return written === null || written === callee ? null : declarationOf2(written, { ...ctx, resolve: () => null });
|
|
13775
|
+
}
|
|
13776
|
+
function asCallable(declaration) {
|
|
13777
|
+
if (Node55.isFunctionDeclaration(declaration) || Node55.isMethodDeclaration(declaration) || Node55.isArrowFunction(declaration) || Node55.isFunctionExpression(declaration)) {
|
|
13778
|
+
return declaration;
|
|
13779
|
+
}
|
|
13780
|
+
if (!Node55.isVariableDeclaration(declaration)) {
|
|
13781
|
+
return null;
|
|
13782
|
+
}
|
|
13783
|
+
const initializer = declaration.getInitializer();
|
|
13784
|
+
if (initializer !== void 0 && (Node55.isArrowFunction(initializer) || Node55.isFunctionExpression(initializer))) {
|
|
13785
|
+
return initializer;
|
|
13786
|
+
}
|
|
13787
|
+
return null;
|
|
13788
|
+
}
|
|
13789
|
+
function bind(parameters, args, scope) {
|
|
13790
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
13791
|
+
parameters.forEach((parameter, index) => {
|
|
13792
|
+
const passed = parameter.rest ? args.slice(index) : args.slice(index, index + 1);
|
|
13793
|
+
if (passed.length > 0) {
|
|
13794
|
+
bindings.set(
|
|
13795
|
+
parameter.name,
|
|
13796
|
+
passed.map((node) => ({ node, scope }))
|
|
13797
|
+
);
|
|
13798
|
+
}
|
|
13799
|
+
});
|
|
13800
|
+
return bindings;
|
|
13801
|
+
}
|
|
13802
|
+
function here(node, ctx) {
|
|
13803
|
+
return { node, scope: ctx.bindings };
|
|
13804
|
+
}
|
|
13805
|
+
function boundOnce(expr, ctx) {
|
|
13806
|
+
const bound = Node55.isIdentifier(expr) ? ctx.bindings.get(expr.getText()) : void 0;
|
|
13807
|
+
return bound !== void 0 && bound.length === 1 ? bound[0] : null;
|
|
13808
|
+
}
|
|
13809
|
+
function readOrHole(expr, ctx) {
|
|
13810
|
+
const name = read(expr, ctx);
|
|
13811
|
+
return name ?? `{${holeName(expr, ctx)}}`;
|
|
13812
|
+
}
|
|
13813
|
+
function holeName(expr, ctx) {
|
|
13814
|
+
const bound = boundOnce(expr, ctx);
|
|
13815
|
+
if (bound !== null) {
|
|
13816
|
+
return holeName(bound.node, { ...ctx, bindings: bound.scope });
|
|
13817
|
+
}
|
|
13818
|
+
if (Node55.isIdentifier(expr)) {
|
|
13819
|
+
return expr.getText();
|
|
13820
|
+
}
|
|
13821
|
+
if (Node55.isPropertyAccessExpression(expr)) {
|
|
13822
|
+
return expr.getName();
|
|
13823
|
+
}
|
|
13824
|
+
return UNNAMED_HOLE;
|
|
13825
|
+
}
|
|
13501
13826
|
export {
|
|
13502
13827
|
ADAPTER_VERSION,
|
|
13503
13828
|
ResolutionStore,
|
|
@@ -13518,10 +13843,12 @@ export {
|
|
|
13518
13843
|
findTerminals,
|
|
13519
13844
|
formatPackHealth,
|
|
13520
13845
|
isImportedFrom,
|
|
13846
|
+
methodDeclaredIn,
|
|
13521
13847
|
parseConditionExpression,
|
|
13522
13848
|
readConfiguredCall,
|
|
13523
13849
|
readContract,
|
|
13524
13850
|
readContractForClientCall,
|
|
13851
|
+
readName,
|
|
13525
13852
|
resolveAliasedSymbol,
|
|
13526
13853
|
resolveSubject,
|
|
13527
13854
|
rootIdentifier
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-typescript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TypeScript adapter for suss — walks source files with ts-morph and emits raw extractions for the suss pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@suss/behavioral-ir": "0.
|
|
50
|
-
"@suss/datalog": "0.
|
|
51
|
-
"@suss/extractor": "0.
|
|
52
|
-
"@suss/resolution": "0.
|
|
49
|
+
"@suss/behavioral-ir": "0.7.0",
|
|
50
|
+
"@suss/datalog": "0.7.0",
|
|
51
|
+
"@suss/extractor": "0.7.0",
|
|
52
|
+
"@suss/resolution": "0.7.0",
|
|
53
53
|
"graphql": "^16.8.0",
|
|
54
54
|
"picomatch": "^4.0.4",
|
|
55
55
|
"ts-morph": "^23.0.0"
|