@suss/adapter-typescript 0.35.0 → 0.36.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 +854 -375
- package/dist/index.d.cts +44 -2
- package/dist/index.d.ts +44 -2
- package/dist/index.js +843 -359
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/adapter.ts
|
|
2
2
|
import path14 from "path";
|
|
3
3
|
import {
|
|
4
|
-
Node as
|
|
4
|
+
Node as Node82,
|
|
5
5
|
Project as Project2
|
|
6
6
|
} from "ts-morph";
|
|
7
7
|
import {
|
|
@@ -26,17 +26,18 @@ import {
|
|
|
26
26
|
createCacheLayer,
|
|
27
27
|
extractionCacheDirFor,
|
|
28
28
|
extractionConfigStamp,
|
|
29
|
+
libraryEnvReadMarker,
|
|
29
30
|
mergeReadShapes as mergeReadShapes2,
|
|
30
31
|
runDigest,
|
|
31
32
|
splitAtHandOffs as splitAtHandOffs2,
|
|
32
33
|
stampModuleImports,
|
|
33
34
|
stampModules
|
|
34
35
|
} from "@suss/extractor";
|
|
35
|
-
import { force as
|
|
36
|
+
import { force as force8, hostOf as hostOf2, literalOf as literalOf6, pathOf as pathOf2 } from "@suss/values";
|
|
36
37
|
|
|
37
38
|
// src/assembly.ts
|
|
38
39
|
import { Node as Node67 } from "ts-morph";
|
|
39
|
-
import {
|
|
40
|
+
import { firesOn, runsBefore, splitAtHandOffs } from "@suss/extractor";
|
|
40
41
|
|
|
41
42
|
// src/conditions.ts
|
|
42
43
|
import {
|
|
@@ -1116,11 +1117,11 @@ function settledDepthsFor(project) {
|
|
|
1116
1117
|
}
|
|
1117
1118
|
var depthsByProject = /* @__PURE__ */ new WeakMap();
|
|
1118
1119
|
function readSpecifierPaths(project, filePath, options, host) {
|
|
1119
|
-
const
|
|
1120
|
-
if (
|
|
1120
|
+
const text3 = readFileText(project, filePath);
|
|
1121
|
+
if (text3 === null) {
|
|
1121
1122
|
return [];
|
|
1122
1123
|
}
|
|
1123
|
-
const scanned = ts.preProcessFile(
|
|
1124
|
+
const scanned = ts.preProcessFile(text3, true, true);
|
|
1124
1125
|
const cache = resolutionCacheFor(project, options);
|
|
1125
1126
|
const paths = [];
|
|
1126
1127
|
for (const imported of scanned.importedFiles) {
|
|
@@ -1292,12 +1293,12 @@ async function readImportsConcurrently(paths, marks) {
|
|
|
1292
1293
|
}
|
|
1293
1294
|
const p = paths[i];
|
|
1294
1295
|
try {
|
|
1295
|
-
const
|
|
1296
|
-
const pre = ts.preProcessFile(
|
|
1296
|
+
const text3 = await fs2.readFile(p, "utf-8");
|
|
1297
|
+
const pre = ts.preProcessFile(text3, true, false);
|
|
1297
1298
|
results[i] = {
|
|
1298
1299
|
path: p,
|
|
1299
1300
|
importedModules: pre.importedFiles.map((f) => f.fileName),
|
|
1300
|
-
marked: marks.some((mark) =>
|
|
1301
|
+
marked: marks.some((mark) => text3.includes(mark))
|
|
1301
1302
|
};
|
|
1302
1303
|
} catch {
|
|
1303
1304
|
results[i] = { path: p, importedModules: [], marked: false };
|
|
@@ -2290,8 +2291,8 @@ function spellingsHandedOn(paths, sourceFile) {
|
|
|
2290
2291
|
if (paths.length === 0) {
|
|
2291
2292
|
return [];
|
|
2292
2293
|
}
|
|
2293
|
-
const
|
|
2294
|
-
if (!paths.some((path17) =>
|
|
2294
|
+
const text3 = sourceFile.getFullText();
|
|
2295
|
+
if (!paths.some((path17) => text3.includes(path17))) {
|
|
2295
2296
|
return [];
|
|
2296
2297
|
}
|
|
2297
2298
|
return sourceFile.getDescendantsOfKind(SyntaxKind2.PropertyAccessExpression).filter((node) => spellsOneOf(paths, node) && flowsOnward(node));
|
|
@@ -2310,6 +2311,10 @@ function dottedPathOf(expression) {
|
|
|
2310
2311
|
if (Node7.isIdentifier(expression)) {
|
|
2311
2312
|
return expression.getText();
|
|
2312
2313
|
}
|
|
2314
|
+
if (Node7.isMetaProperty(expression)) {
|
|
2315
|
+
const keyword = ts2.tokenToString(expression.getKeywordToken());
|
|
2316
|
+
return `${keyword}.${expression.getName()}`;
|
|
2317
|
+
}
|
|
2313
2318
|
if (!Node7.isPropertyAccessExpression(expression)) {
|
|
2314
2319
|
return null;
|
|
2315
2320
|
}
|
|
@@ -4342,8 +4347,8 @@ var ResolutionStore = class _ResolutionStore {
|
|
|
4342
4347
|
if (one.isInNodeModules()) {
|
|
4343
4348
|
return false;
|
|
4344
4349
|
}
|
|
4345
|
-
const
|
|
4346
|
-
return spellings.some((spelling) =>
|
|
4350
|
+
const text3 = one.getFullText();
|
|
4351
|
+
return spellings.some((spelling) => text3.includes(spelling));
|
|
4347
4352
|
});
|
|
4348
4353
|
if (siteFiles.length === 0) {
|
|
4349
4354
|
return [];
|
|
@@ -5750,10 +5755,13 @@ function parametersOf(parameter, position) {
|
|
|
5750
5755
|
}
|
|
5751
5756
|
];
|
|
5752
5757
|
}
|
|
5753
|
-
if (!Node12.isObjectBindingPattern(nameNode)
|
|
5758
|
+
if (!Node12.isObjectBindingPattern(nameNode)) {
|
|
5754
5759
|
return [];
|
|
5755
5760
|
}
|
|
5756
|
-
|
|
5761
|
+
const patternDefault = parameter.getInitializer();
|
|
5762
|
+
return destructuredNames(nameNode, position, []).map(
|
|
5763
|
+
(entry) => patternDefault === void 0 ? entry : { ...entry, patternDefault }
|
|
5764
|
+
);
|
|
5757
5765
|
}
|
|
5758
5766
|
function destructuredNames(pattern, position, prefix) {
|
|
5759
5767
|
return pattern.getElements().flatMap((element) => {
|
|
@@ -6060,6 +6068,18 @@ function evaluatedValue(node, resolution, site) {
|
|
|
6060
6068
|
function evaluatedValueUnder(node, resolution, bindings) {
|
|
6061
6069
|
return bindings.size === 0 ? evaluatedValue(node, resolution) : force(evaluatorFor(node, resolution).evaluate(node, { bindings }));
|
|
6062
6070
|
}
|
|
6071
|
+
function evaluatedValueThrough(node, calls, resolution, given) {
|
|
6072
|
+
const evaluator = evaluatorFor(node, resolution);
|
|
6073
|
+
let bindings = /* @__PURE__ */ new Map();
|
|
6074
|
+
for (const call of [...calls].reverse()) {
|
|
6075
|
+
const bound = evaluator.argumentsAt(call, { bindings, given });
|
|
6076
|
+
if (bound === null) {
|
|
6077
|
+
return null;
|
|
6078
|
+
}
|
|
6079
|
+
bindings = bound;
|
|
6080
|
+
}
|
|
6081
|
+
return evaluator.evaluate(node, { bindings, given });
|
|
6082
|
+
}
|
|
6063
6083
|
|
|
6064
6084
|
// src/resolve/routePath.ts
|
|
6065
6085
|
function pathFromArgument(arg, resolution, site) {
|
|
@@ -7475,8 +7495,8 @@ function declaredChannelOf(source, decorator, resolution) {
|
|
|
7475
7495
|
if (arg === void 0) {
|
|
7476
7496
|
return null;
|
|
7477
7497
|
}
|
|
7478
|
-
const
|
|
7479
|
-
return
|
|
7498
|
+
const text3 = stringValueOf(arg, resolution);
|
|
7499
|
+
return text3 === null || text3 === "" ? null : text3;
|
|
7480
7500
|
}
|
|
7481
7501
|
function statusCodeDecoratedOn(routeDecorator, statusDecorators, constants, resolution) {
|
|
7482
7502
|
const member = routeDecorator.getParent();
|
|
@@ -7932,28 +7952,28 @@ function assembledTemplateText(template, assembly) {
|
|
|
7932
7952
|
if (!Node24.isTemplateExpression(template)) {
|
|
7933
7953
|
return null;
|
|
7934
7954
|
}
|
|
7935
|
-
let
|
|
7955
|
+
let text3 = template.getHead().getLiteralText();
|
|
7936
7956
|
for (const span of template.getTemplateSpans()) {
|
|
7937
7957
|
const spliced = interpolatedDocumentText(span.getExpression(), assembly);
|
|
7938
7958
|
if (spliced === null) {
|
|
7939
7959
|
assembly.unresolvedInterpolations.push(
|
|
7940
7960
|
singleLine(span.getExpression().getText())
|
|
7941
7961
|
);
|
|
7942
|
-
if (openBraceDepth(
|
|
7962
|
+
if (openBraceDepth(text3) > 0) {
|
|
7943
7963
|
assembly.unresolvedInsideSelection = true;
|
|
7944
7964
|
}
|
|
7945
7965
|
} else {
|
|
7946
|
-
|
|
7966
|
+
text3 += `
|
|
7947
7967
|
${spliced}
|
|
7948
7968
|
`;
|
|
7949
7969
|
}
|
|
7950
|
-
|
|
7970
|
+
text3 += span.getLiteral().getLiteralText();
|
|
7951
7971
|
}
|
|
7952
|
-
return
|
|
7972
|
+
return text3;
|
|
7953
7973
|
}
|
|
7954
|
-
function openBraceDepth(
|
|
7974
|
+
function openBraceDepth(text3) {
|
|
7955
7975
|
let depth = 0;
|
|
7956
|
-
for (const char of
|
|
7976
|
+
for (const char of text3) {
|
|
7957
7977
|
if (char === "{") {
|
|
7958
7978
|
depth += 1;
|
|
7959
7979
|
} else if (char === "}") {
|
|
@@ -7985,16 +8005,16 @@ function interpolatedDocumentText(expr, assembly) {
|
|
|
7985
8005
|
function resolveGraphqlDocument(arg, resolution) {
|
|
7986
8006
|
const assembly = startAssembly(resolution);
|
|
7987
8007
|
const stripped = peelSyntax(arg);
|
|
7988
|
-
const
|
|
7989
|
-
if (
|
|
7990
|
-
return assembledDocumentResolution(
|
|
8008
|
+
const text3 = documentTextFromExpression(stripped, assembly) ?? resolveGqlTemplateText(stripped, assembly) ?? resolveTypedDocumentSource(stripped) ?? resolveThroughFacts(stripped, assembly);
|
|
8009
|
+
if (text3 !== null) {
|
|
8010
|
+
return assembledDocumentResolution(text3, stripped, assembly);
|
|
7991
8011
|
}
|
|
7992
8012
|
return resolveTypedDocumentHeader(stripped);
|
|
7993
8013
|
}
|
|
7994
|
-
function assembledDocumentResolution(
|
|
8014
|
+
function assembledDocumentResolution(text3, arg, assembly) {
|
|
7995
8015
|
const interpolations = assembly.unresolvedInterpolations;
|
|
7996
8016
|
if (assembly.unresolvedInsideSelection) {
|
|
7997
|
-
const header = parseGraphqlOperation(
|
|
8017
|
+
const header = parseGraphqlOperation(text3);
|
|
7998
8018
|
return {
|
|
7999
8019
|
...header !== null ? { operationType: header.operationType } : {},
|
|
8000
8020
|
...header?.operationName !== void 0 ? { operationName: header.operationName } : {},
|
|
@@ -8004,10 +8024,10 @@ function assembledDocumentResolution(text2, arg, assembly) {
|
|
|
8004
8024
|
}
|
|
8005
8025
|
};
|
|
8006
8026
|
}
|
|
8007
|
-
const spreads = fragmentSpreadsIn(
|
|
8027
|
+
const spreads = fragmentSpreadsIn(text3);
|
|
8008
8028
|
if (spreads === null) {
|
|
8009
8029
|
if (interpolations.length === 0) {
|
|
8010
|
-
return { document:
|
|
8030
|
+
return { document: text3 };
|
|
8011
8031
|
}
|
|
8012
8032
|
return {
|
|
8013
8033
|
unresolved: {
|
|
@@ -8016,7 +8036,7 @@ function assembledDocumentResolution(text2, arg, assembly) {
|
|
|
8016
8036
|
}
|
|
8017
8037
|
};
|
|
8018
8038
|
}
|
|
8019
|
-
const filled = fillDanglingSpreads(
|
|
8039
|
+
const filled = fillDanglingSpreads(text3, spreads, arg, assembly);
|
|
8020
8040
|
if (filled.unresolved.length > 0) {
|
|
8021
8041
|
return {
|
|
8022
8042
|
document: filled.text,
|
|
@@ -8035,15 +8055,15 @@ function assembledDocumentResolution(text2, arg, assembly) {
|
|
|
8035
8055
|
}
|
|
8036
8056
|
return { document: filled.text };
|
|
8037
8057
|
}
|
|
8038
|
-
function fillDanglingSpreads(
|
|
8058
|
+
function fillDanglingSpreads(text3, spreads, arg, assembly) {
|
|
8039
8059
|
if (spreads.dangling.length === 0 || assembly.tagOrigin !== "project") {
|
|
8040
|
-
return { text:
|
|
8060
|
+
return { text: text3, unresolved: spreads.dangling, ambiguous: [] };
|
|
8041
8061
|
}
|
|
8042
8062
|
const definitions = projectFragmentDefinitions(arg.getProject());
|
|
8043
8063
|
const settled3 = new Set(spreads.defined);
|
|
8044
8064
|
const unresolved = /* @__PURE__ */ new Set();
|
|
8045
8065
|
const ambiguous = /* @__PURE__ */ new Set();
|
|
8046
|
-
let filled =
|
|
8066
|
+
let filled = text3;
|
|
8047
8067
|
let pending = spreads.dangling;
|
|
8048
8068
|
while (pending.length > 0) {
|
|
8049
8069
|
const brought = [];
|
|
@@ -8107,12 +8127,12 @@ function buildFragmentIndex(project) {
|
|
|
8107
8127
|
if (!FRAGMENT_DEFINITION_TEXT.test(sourceFile.getFullText())) {
|
|
8108
8128
|
continue;
|
|
8109
8129
|
}
|
|
8110
|
-
for (const
|
|
8111
|
-
recordFragmentDefinitions(
|
|
8130
|
+
for (const text3 of documentTextsIn(sourceFile)) {
|
|
8131
|
+
recordFragmentDefinitions(text3, definitions);
|
|
8112
8132
|
}
|
|
8113
8133
|
}
|
|
8114
|
-
for (const
|
|
8115
|
-
recordFragmentDefinitions(
|
|
8134
|
+
for (const text3 of graphqlFileTextsNear(sourceFiles)) {
|
|
8135
|
+
recordFragmentDefinitions(text3, definitions);
|
|
8116
8136
|
}
|
|
8117
8137
|
return definitions;
|
|
8118
8138
|
}
|
|
@@ -8149,17 +8169,17 @@ function documentTextsIn(sourceFile) {
|
|
|
8149
8169
|
if (!Node24.isTaggedTemplateExpression(node) && !Node24.isCallExpression(node)) {
|
|
8150
8170
|
return;
|
|
8151
8171
|
}
|
|
8152
|
-
const
|
|
8153
|
-
if (
|
|
8154
|
-
texts.push(
|
|
8172
|
+
const text3 = documentTextFromExpression(node, startAssembly(void 0));
|
|
8173
|
+
if (text3 !== null && text3 !== "") {
|
|
8174
|
+
texts.push(text3);
|
|
8155
8175
|
}
|
|
8156
8176
|
});
|
|
8157
8177
|
return texts;
|
|
8158
8178
|
}
|
|
8159
|
-
function recordFragmentDefinitions(
|
|
8179
|
+
function recordFragmentDefinitions(text3, definitions) {
|
|
8160
8180
|
let doc;
|
|
8161
8181
|
try {
|
|
8162
|
-
doc = graphqlParse(
|
|
8182
|
+
doc = graphqlParse(text3);
|
|
8163
8183
|
} catch {
|
|
8164
8184
|
return;
|
|
8165
8185
|
}
|
|
@@ -8183,13 +8203,13 @@ function recordFragmentDefinitions(text2, definitions) {
|
|
|
8183
8203
|
}
|
|
8184
8204
|
var NO_NAMES = /* @__PURE__ */ new Set();
|
|
8185
8205
|
function describeInterpolations(interpolations) {
|
|
8186
|
-
const quoted = interpolations.map((
|
|
8206
|
+
const quoted = interpolations.map((text3) => `\`${text3}\``).join(", ");
|
|
8187
8207
|
return interpolations.length === 1 ? `expression ${quoted}` : `expressions ${quoted}`;
|
|
8188
8208
|
}
|
|
8189
|
-
function fragmentSpreadsIn(
|
|
8209
|
+
function fragmentSpreadsIn(text3) {
|
|
8190
8210
|
let doc;
|
|
8191
8211
|
try {
|
|
8192
|
-
doc = graphqlParse(
|
|
8212
|
+
doc = graphqlParse(text3);
|
|
8193
8213
|
} catch {
|
|
8194
8214
|
return null;
|
|
8195
8215
|
}
|
|
@@ -8341,9 +8361,9 @@ function resolveThroughFacts(arg, assembly) {
|
|
|
8341
8361
|
if (written === null) {
|
|
8342
8362
|
return null;
|
|
8343
8363
|
}
|
|
8344
|
-
const
|
|
8345
|
-
if (
|
|
8346
|
-
return
|
|
8364
|
+
const text3 = documentTextFromExpression(written, assembly);
|
|
8365
|
+
if (text3 !== null) {
|
|
8366
|
+
return text3;
|
|
8347
8367
|
}
|
|
8348
8368
|
return typedDocumentSourceOf(written);
|
|
8349
8369
|
}
|
|
@@ -8379,8 +8399,8 @@ function unreadableDocument(arg, reason) {
|
|
|
8379
8399
|
}
|
|
8380
8400
|
};
|
|
8381
8401
|
}
|
|
8382
|
-
function singleLine(
|
|
8383
|
-
const collapsed =
|
|
8402
|
+
function singleLine(text3) {
|
|
8403
|
+
const collapsed = text3.replace(/\s+/g, " ").trim();
|
|
8384
8404
|
return collapsed.length > 80 ? `${collapsed.slice(0, 79)}\u2026` : collapsed;
|
|
8385
8405
|
}
|
|
8386
8406
|
function importedVariableInitializers(identifier) {
|
|
@@ -8424,9 +8444,9 @@ function resolveGqlTemplateText(arg, assembly) {
|
|
|
8424
8444
|
}
|
|
8425
8445
|
}
|
|
8426
8446
|
for (const init of importedVariableInitializers(arg)) {
|
|
8427
|
-
const
|
|
8428
|
-
if (
|
|
8429
|
-
return
|
|
8447
|
+
const text3 = documentTextFromExpression(peelSyntax(init), assembly);
|
|
8448
|
+
if (text3 !== null) {
|
|
8449
|
+
return text3;
|
|
8430
8450
|
}
|
|
8431
8451
|
}
|
|
8432
8452
|
return null;
|
|
@@ -9029,7 +9049,8 @@ function expandDocumentParameterCallers(documentArgument, libraryCall, context)
|
|
|
9029
9049
|
context.store.returnsCall(wrapper, libraryCall),
|
|
9030
9050
|
0,
|
|
9031
9051
|
/* @__PURE__ */ new Set([parameter]),
|
|
9032
|
-
context
|
|
9052
|
+
context,
|
|
9053
|
+
{ library: libraryCall, through: [] }
|
|
9033
9054
|
);
|
|
9034
9055
|
return {
|
|
9035
9056
|
units: expanded.units,
|
|
@@ -9042,7 +9063,7 @@ function documentBehindWrapper(value, store, wrapperReason) {
|
|
|
9042
9063
|
}
|
|
9043
9064
|
return resolveGraphqlDocument(value, store) ?? unreadableDocument(value);
|
|
9044
9065
|
}
|
|
9045
|
-
function expandParameter(parameter, forwardsResult, depth, expanded, context) {
|
|
9066
|
+
function expandParameter(parameter, forwardsResult, depth, expanded, context, chain) {
|
|
9046
9067
|
const passed = context.store.argumentsPassedTo(parameter);
|
|
9047
9068
|
if (passed.length === 0) {
|
|
9048
9069
|
return { units: [], unfollowed: 1 };
|
|
@@ -9055,6 +9076,7 @@ function expandParameter(parameter, forwardsResult, depth, expanded, context) {
|
|
|
9055
9076
|
unfollowed++;
|
|
9056
9077
|
continue;
|
|
9057
9078
|
}
|
|
9079
|
+
const outward = { ...chain, through: [...chain.through, call] };
|
|
9058
9080
|
const nested = parameterBehind(argument, caller);
|
|
9059
9081
|
if (nested !== null) {
|
|
9060
9082
|
const deeper = expandNested(
|
|
@@ -9062,13 +9084,21 @@ function expandParameter(parameter, forwardsResult, depth, expanded, context) {
|
|
|
9062
9084
|
forwardsResult && context.store.returnsCall(caller, call),
|
|
9063
9085
|
depth,
|
|
9064
9086
|
expanded,
|
|
9065
|
-
context
|
|
9087
|
+
context,
|
|
9088
|
+
outward
|
|
9066
9089
|
);
|
|
9067
9090
|
units.push(...deeper.units);
|
|
9068
9091
|
unfollowed += deeper.unfollowed;
|
|
9069
9092
|
continue;
|
|
9070
9093
|
}
|
|
9071
|
-
const unit = callerUnit(
|
|
9094
|
+
const unit = callerUnit(
|
|
9095
|
+
caller,
|
|
9096
|
+
call,
|
|
9097
|
+
argument,
|
|
9098
|
+
forwardsResult,
|
|
9099
|
+
context,
|
|
9100
|
+
outward
|
|
9101
|
+
);
|
|
9072
9102
|
if (unit === null) {
|
|
9073
9103
|
unfollowed++;
|
|
9074
9104
|
continue;
|
|
@@ -9077,7 +9107,7 @@ function expandParameter(parameter, forwardsResult, depth, expanded, context) {
|
|
|
9077
9107
|
}
|
|
9078
9108
|
return { units, unfollowed };
|
|
9079
9109
|
}
|
|
9080
|
-
function expandNested(parameter, forwardsResult, depth, expanded, context) {
|
|
9110
|
+
function expandNested(parameter, forwardsResult, depth, expanded, context, chain) {
|
|
9081
9111
|
if (depth + 1 >= MAX_WRAPPER_DEPTH || expanded.has(parameter)) {
|
|
9082
9112
|
return { units: [], unfollowed: 1 };
|
|
9083
9113
|
}
|
|
@@ -9086,10 +9116,11 @@ function expandNested(parameter, forwardsResult, depth, expanded, context) {
|
|
|
9086
9116
|
forwardsResult,
|
|
9087
9117
|
depth + 1,
|
|
9088
9118
|
/* @__PURE__ */ new Set([...expanded, parameter]),
|
|
9089
|
-
context
|
|
9119
|
+
context,
|
|
9120
|
+
chain
|
|
9090
9121
|
);
|
|
9091
9122
|
}
|
|
9092
|
-
function callerUnit(caller, call, argument, forwardsResult, context) {
|
|
9123
|
+
function callerUnit(caller, call, argument, forwardsResult, context, chain) {
|
|
9093
9124
|
const document = resolveGraphqlDocument(argument, context.store) ?? unreadableDocument(argument);
|
|
9094
9125
|
const operationInfo = operationInfoFromResolution(
|
|
9095
9126
|
document,
|
|
@@ -9106,7 +9137,14 @@ function callerUnit(caller, call, argument, forwardsResult, context) {
|
|
|
9106
9137
|
// A wrapper handing back something of its own leaves the caller
|
|
9107
9138
|
// none of the library's result to read.
|
|
9108
9139
|
...forwardsResult ? { callSite: { callExpression: call, methodName: context.methodName } } : {},
|
|
9109
|
-
operationInfo
|
|
9140
|
+
operationInfo,
|
|
9141
|
+
...context.client === void 0 ? {} : {
|
|
9142
|
+
graphqlCall: {
|
|
9143
|
+
call: chain.library,
|
|
9144
|
+
through: chain.through,
|
|
9145
|
+
client: context.client
|
|
9146
|
+
}
|
|
9147
|
+
}
|
|
9110
9148
|
};
|
|
9111
9149
|
}
|
|
9112
9150
|
function unfollowedReason(followed, unfollowed) {
|
|
@@ -9208,7 +9246,8 @@ function discoverGraphqlHookCalls(sourceFile, match, kind, resolution) {
|
|
|
9208
9246
|
kind,
|
|
9209
9247
|
operationType: spec.operationType,
|
|
9210
9248
|
methodName: spec.canonical,
|
|
9211
|
-
store
|
|
9249
|
+
store,
|
|
9250
|
+
...match.clientOption === void 0 ? {} : { client: match.clientOption }
|
|
9212
9251
|
});
|
|
9213
9252
|
if (expansion !== null) {
|
|
9214
9253
|
results.push(...expansion.units);
|
|
@@ -9238,7 +9277,14 @@ function discoverGraphqlHookCalls(sourceFile, match, kind, resolution) {
|
|
|
9238
9277
|
kind,
|
|
9239
9278
|
name: `${functionNameOrAnon(enclosing)}.${nameToken}`,
|
|
9240
9279
|
callSite: { callExpression: node, methodName: spec.canonical },
|
|
9241
|
-
operationInfo
|
|
9280
|
+
operationInfo,
|
|
9281
|
+
...match.clientOption === void 0 ? {} : {
|
|
9282
|
+
graphqlCall: {
|
|
9283
|
+
call: node,
|
|
9284
|
+
through: [],
|
|
9285
|
+
client: match.clientOption
|
|
9286
|
+
}
|
|
9287
|
+
}
|
|
9242
9288
|
});
|
|
9243
9289
|
}
|
|
9244
9290
|
return results;
|
|
@@ -9289,7 +9335,8 @@ function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
|
9289
9335
|
kind,
|
|
9290
9336
|
operationType: spec.operationType,
|
|
9291
9337
|
methodName,
|
|
9292
|
-
store: resolution
|
|
9338
|
+
store: resolution,
|
|
9339
|
+
client: "receiver"
|
|
9293
9340
|
});
|
|
9294
9341
|
if (expansion !== null) {
|
|
9295
9342
|
results.push(...expansion.units);
|
|
@@ -9319,7 +9366,8 @@ function discoverGraphqlImperativeCalls(sourceFile, match, kind, resolution) {
|
|
|
9319
9366
|
kind,
|
|
9320
9367
|
name: `${functionNameOrAnon(enclosing)}.${nameToken}`,
|
|
9321
9368
|
callSite: { callExpression: node, methodName },
|
|
9322
|
-
operationInfo
|
|
9369
|
+
operationInfo,
|
|
9370
|
+
graphqlCall: { call: node, through: [], client: "receiver" }
|
|
9323
9371
|
});
|
|
9324
9372
|
});
|
|
9325
9373
|
return results;
|
|
@@ -10332,6 +10380,7 @@ function discoverRegistrationCalls(sourceFile, match, kind, bindingExtraction, r
|
|
|
10332
10380
|
if (registrationSubjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution, registrationMethods)) {
|
|
10333
10381
|
return results;
|
|
10334
10382
|
}
|
|
10383
|
+
const anonymousLabels = /* @__PURE__ */ new Map();
|
|
10335
10384
|
sourceFile.forEachDescendant((node) => {
|
|
10336
10385
|
if (!Node36.isCallExpression(node)) {
|
|
10337
10386
|
return;
|
|
@@ -10433,7 +10482,8 @@ function discoverRegistrationCalls(sourceFile, match, kind, bindingExtraction, r
|
|
|
10433
10482
|
routeWrapperPattern,
|
|
10434
10483
|
methodName,
|
|
10435
10484
|
routeInfo,
|
|
10436
|
-
resolution
|
|
10485
|
+
resolution,
|
|
10486
|
+
anonymousLabels
|
|
10437
10487
|
);
|
|
10438
10488
|
results.push({
|
|
10439
10489
|
func: handler,
|
|
@@ -10494,9 +10544,8 @@ function declinedRegistration(call, callee, methodName, kind, receiver, resoluti
|
|
|
10494
10544
|
}
|
|
10495
10545
|
];
|
|
10496
10546
|
}
|
|
10497
|
-
function routeChainOf(listed, pattern, methodName, routeInfo, resolution) {
|
|
10547
|
+
function routeChainOf(listed, pattern, methodName, routeInfo, resolution, anonymousLabels) {
|
|
10498
10548
|
const chain = { units: [], references: [], unfollowed: [] };
|
|
10499
|
-
const anonymousLabels = /* @__PURE__ */ new Map();
|
|
10500
10549
|
for (const arg of listed) {
|
|
10501
10550
|
const elements = Node36.isArrayLiteralExpression(arg) ? arg.getElements() : [arg];
|
|
10502
10551
|
for (const element of elements) {
|
|
@@ -10510,12 +10559,12 @@ function routeChainOf(listed, pattern, methodName, routeInfo, resolution) {
|
|
|
10510
10559
|
}
|
|
10511
10560
|
const ownName = functionNameOrAnon(target);
|
|
10512
10561
|
const named2 = ownName !== "<anon>";
|
|
10513
|
-
const label = factoryNameOf(element) ?? methodName
|
|
10562
|
+
const label = `${factoryNameOf(element) ?? methodName}@${routeWhere(routeInfo)}`;
|
|
10514
10563
|
const seen = anonymousLabels.get(label) ?? 0;
|
|
10515
10564
|
if (!named2) {
|
|
10516
10565
|
anonymousLabels.set(label, seen + 1);
|
|
10517
10566
|
}
|
|
10518
|
-
const name = named2 ? ownName :
|
|
10567
|
+
const name = named2 ? ownName : numberedLabel(label, seen);
|
|
10519
10568
|
chain.units.push({
|
|
10520
10569
|
func: target,
|
|
10521
10570
|
kind: pattern.kind,
|
|
@@ -10531,9 +10580,11 @@ function routeChainOf(listed, pattern, methodName, routeInfo, resolution) {
|
|
|
10531
10580
|
}
|
|
10532
10581
|
return chain;
|
|
10533
10582
|
}
|
|
10534
|
-
function
|
|
10535
|
-
|
|
10536
|
-
|
|
10583
|
+
function routeWhere(routeInfo) {
|
|
10584
|
+
return routeInfo === null ? "?" : `${routeInfo.method} ${routeInfo.path}`;
|
|
10585
|
+
}
|
|
10586
|
+
function numberedLabel(label, seen) {
|
|
10587
|
+
return seen === 0 ? label : `${label}#${seen + 1}`;
|
|
10537
10588
|
}
|
|
10538
10589
|
function withMountPrefix(routeInfo, subjectNode, mountPrefixes) {
|
|
10539
10590
|
if (routeInfo === null || mountPrefixes === void 0) {
|
|
@@ -11471,8 +11522,8 @@ function mockOf(call, match, sourceFile, resolution) {
|
|
|
11471
11522
|
const module = Node40.isIdentifier(first) ? moduleImportedWholeAs(sourceFile, first.getText()) : null;
|
|
11472
11523
|
return { ...module !== null ? { module } : {}, name, written };
|
|
11473
11524
|
}
|
|
11474
|
-
function oneLine(
|
|
11475
|
-
const flat =
|
|
11525
|
+
function oneLine(text3) {
|
|
11526
|
+
const flat = text3.replace(/\s*\n\s*/g, "");
|
|
11476
11527
|
const factory = flat.search(/,\s*(async\s*)?\(/);
|
|
11477
11528
|
return factory === -1 ? flat : `${flat.slice(0, factory)})`;
|
|
11478
11529
|
}
|
|
@@ -12049,8 +12100,8 @@ function receiverIsPromiseTyped(receiver) {
|
|
|
12049
12100
|
if (symbolName === "Promise") {
|
|
12050
12101
|
return true;
|
|
12051
12102
|
}
|
|
12052
|
-
const
|
|
12053
|
-
return
|
|
12103
|
+
const text3 = type.getText();
|
|
12104
|
+
return text3 === "Promise" || text3.startsWith("Promise<");
|
|
12054
12105
|
}
|
|
12055
12106
|
function callbackReturnExpression(node) {
|
|
12056
12107
|
if (node === void 0 || !(Node43.isArrowFunction(node) || Node43.isFunctionExpression(node))) {
|
|
@@ -12687,6 +12738,7 @@ import { Node as Node48 } from "ts-morph";
|
|
|
12687
12738
|
import {
|
|
12688
12739
|
enumerateStructuredPaths,
|
|
12689
12740
|
PathBudgetExceeded,
|
|
12741
|
+
placeTerminals,
|
|
12690
12742
|
UnmodeledFlow as UnmodeledFlow2
|
|
12691
12743
|
} from "@suss/extractor";
|
|
12692
12744
|
|
|
@@ -12741,9 +12793,9 @@ function getLoopBody(stmt) {
|
|
|
12741
12793
|
return void 0;
|
|
12742
12794
|
}
|
|
12743
12795
|
var loopHeaderText = (stmt) => {
|
|
12744
|
-
const
|
|
12745
|
-
const bodyStart =
|
|
12746
|
-
const header = bodyStart === -1 ?
|
|
12796
|
+
const text3 = stmt.getText();
|
|
12797
|
+
const bodyStart = text3.indexOf("{");
|
|
12798
|
+
const header = bodyStart === -1 ? text3 : text3.slice(0, bodyStart);
|
|
12747
12799
|
return header.trim();
|
|
12748
12800
|
};
|
|
12749
12801
|
var conditionOf = (expr) => ({
|
|
@@ -12854,7 +12906,8 @@ function buildStructured(stmt, ctx) {
|
|
|
12854
12906
|
kind: "loop",
|
|
12855
12907
|
condition: { sourceText: loopHeaderText(stmt), expression: null },
|
|
12856
12908
|
body: lowerList(statementsOf(getLoopBody(stmt)), ctx),
|
|
12857
|
-
exitKind
|
|
12909
|
+
exitKind,
|
|
12910
|
+
lines: lineRangeOf(stmt)
|
|
12858
12911
|
};
|
|
12859
12912
|
}
|
|
12860
12913
|
if (Node47.isTryStatement(stmt)) {
|
|
@@ -12862,6 +12915,7 @@ function buildStructured(stmt, ctx) {
|
|
|
12862
12915
|
const finallyBlock = stmt.getFinallyBlock();
|
|
12863
12916
|
return {
|
|
12864
12917
|
kind: "try",
|
|
12918
|
+
lines: lineRangeOf(stmt),
|
|
12865
12919
|
tryBody: lowerList(stmt.getTryBlock().getStatements(), ctx),
|
|
12866
12920
|
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(), ctx),
|
|
12867
12921
|
finallyBody: finallyBlock === void 0 ? null : lowerList(finallyBlock.getStatements(), ctx),
|
|
@@ -13022,13 +13076,14 @@ function loweredExpressionBody(body, terminalNodes, func, barriers) {
|
|
|
13022
13076
|
function computePathConditions(func, terminalNodes, barriers = NO_BARRIERS, endings = NO_ENDINGS, keepsArms) {
|
|
13023
13077
|
const body = func.getBody();
|
|
13024
13078
|
if (body === void 0) {
|
|
13025
|
-
return { byTerminal: /* @__PURE__ */ new Map(), fallthrough: [] };
|
|
13079
|
+
return { byTerminal: /* @__PURE__ */ new Map(), fallthrough: [], placement: /* @__PURE__ */ new Map() };
|
|
13026
13080
|
}
|
|
13027
13081
|
if (containsUnmodeledFlow(body, func, barriers)) {
|
|
13028
13082
|
return degradedResult(func, terminalNodes, "labeled statement");
|
|
13029
13083
|
}
|
|
13084
|
+
let lowered;
|
|
13030
13085
|
try {
|
|
13031
|
-
|
|
13086
|
+
lowered = Node48.isBlock(body) ? lowerFunctionBody(body, terminalNodes, func, barriers, endings) : loweredExpressionBody(body, terminalNodes, func, barriers);
|
|
13032
13087
|
const result = enumerateStructuredPaths({
|
|
13033
13088
|
statements: lowered.statements,
|
|
13034
13089
|
terminalsByStmt: lowered.terminalsByStmt,
|
|
@@ -13036,15 +13091,17 @@ function computePathConditions(func, terminalNodes, barriers = NO_BARRIERS, endi
|
|
|
13036
13091
|
});
|
|
13037
13092
|
return composeExpressionLevel(func, result, lowered.terminalHomeRaw);
|
|
13038
13093
|
} catch (error) {
|
|
13094
|
+
const placement = lowered === void 0 ? /* @__PURE__ */ new Map() : placeTerminals(lowered);
|
|
13039
13095
|
if (error instanceof PathBudgetExceeded) {
|
|
13040
13096
|
return degradedResult(
|
|
13041
13097
|
func,
|
|
13042
13098
|
terminalNodes,
|
|
13043
|
-
error.message === "" ? "path budget exceeded" : error.message
|
|
13099
|
+
error.message === "" ? "path budget exceeded" : error.message,
|
|
13100
|
+
placement
|
|
13044
13101
|
);
|
|
13045
13102
|
}
|
|
13046
13103
|
if (error instanceof UnmodeledFlow2) {
|
|
13047
|
-
return degradedResult(func, terminalNodes, error.message);
|
|
13104
|
+
return degradedResult(func, terminalNodes, error.message, placement);
|
|
13048
13105
|
}
|
|
13049
13106
|
throw error;
|
|
13050
13107
|
}
|
|
@@ -13059,9 +13116,13 @@ function composeExpressionLevel(func, result, terminalHomeRaw) {
|
|
|
13059
13116
|
paths.map((statementLevel) => [...statementLevel, ...expressionLevel])
|
|
13060
13117
|
);
|
|
13061
13118
|
}
|
|
13062
|
-
return {
|
|
13119
|
+
return {
|
|
13120
|
+
byTerminal,
|
|
13121
|
+
fallthrough: result.fallthrough,
|
|
13122
|
+
placement: result.placement
|
|
13123
|
+
};
|
|
13063
13124
|
}
|
|
13064
|
-
function degradedResult(func, terminalNodes, reason) {
|
|
13125
|
+
function degradedResult(func, terminalNodes, reason, placement = /* @__PURE__ */ new Map()) {
|
|
13065
13126
|
const marker = {
|
|
13066
13127
|
sourceText: `unmodeled control flow (${reason})`,
|
|
13067
13128
|
polarity: "positive",
|
|
@@ -13078,7 +13139,7 @@ function degradedResult(func, terminalNodes, reason) {
|
|
|
13078
13139
|
[...collectAncestorConditionInfosBelow(terminal, func), marker]
|
|
13079
13140
|
]);
|
|
13080
13141
|
}
|
|
13081
|
-
return { byTerminal, fallthrough: [[marker]] };
|
|
13142
|
+
return { byTerminal, fallthrough: [[marker]], placement };
|
|
13082
13143
|
}
|
|
13083
13144
|
|
|
13084
13145
|
// src/provenance.ts
|
|
@@ -13161,9 +13222,13 @@ function literalAt(node, resolution) {
|
|
|
13161
13222
|
|
|
13162
13223
|
// src/resolve/invocationEffects.ts
|
|
13163
13224
|
import {
|
|
13164
|
-
Node as Node54
|
|
13225
|
+
Node as Node54,
|
|
13226
|
+
VariableDeclarationKind as VariableDeclarationKind2
|
|
13165
13227
|
} from "ts-morph";
|
|
13166
|
-
import {
|
|
13228
|
+
import {
|
|
13229
|
+
numberRepeatedCallSites,
|
|
13230
|
+
rawConditionToPredicate
|
|
13231
|
+
} from "@suss/extractor";
|
|
13167
13232
|
|
|
13168
13233
|
// src/resolve/callOps.ts
|
|
13169
13234
|
import { Node as Node53 } from "ts-morph";
|
|
@@ -13207,7 +13272,7 @@ function stableTypeText(type, reader, enclosing, flags) {
|
|
|
13207
13272
|
return withoutImportQualifiers(printed(ordered, file));
|
|
13208
13273
|
}
|
|
13209
13274
|
var IMPORT_QUALIFIER = /import\("[^"]*"\)\./g;
|
|
13210
|
-
var withoutImportQualifiers = (
|
|
13275
|
+
var withoutImportQualifiers = (text3) => text3.replace(IMPORT_QUALIFIER, "");
|
|
13211
13276
|
function printed(node, file) {
|
|
13212
13277
|
return PRINTER.printNode(ts3.EmitHint.Unspecified, node, file).replace(
|
|
13213
13278
|
/\n/g,
|
|
@@ -13249,11 +13314,11 @@ function inStableOrder(members, file) {
|
|
|
13249
13314
|
function compareMembers(a, b) {
|
|
13250
13315
|
return nullishRank(a) - nullishRank(b) || compareText(a, b);
|
|
13251
13316
|
}
|
|
13252
|
-
function nullishRank(
|
|
13253
|
-
if (
|
|
13317
|
+
function nullishRank(text3) {
|
|
13318
|
+
if (text3 === "null") {
|
|
13254
13319
|
return 1;
|
|
13255
13320
|
}
|
|
13256
|
-
if (
|
|
13321
|
+
if (text3 === "undefined") {
|
|
13257
13322
|
return 2;
|
|
13258
13323
|
}
|
|
13259
13324
|
return 0;
|
|
@@ -14248,11 +14313,12 @@ function invocationAt(call, func) {
|
|
|
14248
14313
|
callee: call.getExpression().getText(),
|
|
14249
14314
|
args: extractArgs(call),
|
|
14250
14315
|
async: isAwaited(call),
|
|
14251
|
-
...preconditions.length > 0 ? { preconditions } : {}
|
|
14316
|
+
...preconditions.length > 0 ? { preconditions } : {},
|
|
14317
|
+
location: lineRangeOf(call)
|
|
14252
14318
|
},
|
|
14253
14319
|
node: call,
|
|
14254
14320
|
line: enclosingStatementLine(call),
|
|
14255
|
-
|
|
14321
|
+
cleansUpFrom: cleanupStartLine(call, func)
|
|
14256
14322
|
};
|
|
14257
14323
|
}
|
|
14258
14324
|
function isAwaited(call) {
|
|
@@ -14263,7 +14329,7 @@ function runInvocationRecognizers(func, recognizers, barriers = NO_BARRIERS, res
|
|
|
14263
14329
|
if (recognizers.length === 0) {
|
|
14264
14330
|
return [];
|
|
14265
14331
|
}
|
|
14266
|
-
const
|
|
14332
|
+
const sites = [];
|
|
14267
14333
|
const sourceFile = func.getSourceFile();
|
|
14268
14334
|
const calls = [];
|
|
14269
14335
|
func.forEachDescendant((node, traversal) => {
|
|
@@ -14288,7 +14354,8 @@ function runInvocationRecognizers(func, recognizers, barriers = NO_BARRIERS, res
|
|
|
14288
14354
|
);
|
|
14289
14355
|
const line = enclosingStatementLine(node);
|
|
14290
14356
|
const preconditions = collectPreconditions(node, func);
|
|
14291
|
-
const
|
|
14357
|
+
const cleansUpFrom = cleanupStartLine(node, func);
|
|
14358
|
+
const site = [];
|
|
14292
14359
|
for (const recognizer of recognizers) {
|
|
14293
14360
|
let emitted = null;
|
|
14294
14361
|
try {
|
|
@@ -14306,17 +14373,18 @@ function runInvocationRecognizers(func, recognizers, barriers = NO_BARRIERS, res
|
|
|
14306
14373
|
continue;
|
|
14307
14374
|
}
|
|
14308
14375
|
for (const eff of emitted) {
|
|
14309
|
-
|
|
14310
|
-
effect: withPreconditions(eff, preconditions),
|
|
14376
|
+
site.push({
|
|
14377
|
+
effect: placedAt(withPreconditions(eff, preconditions), node),
|
|
14311
14378
|
line,
|
|
14312
14379
|
preconditions,
|
|
14313
|
-
|
|
14380
|
+
cleansUpFrom,
|
|
14314
14381
|
...stated?.of(eff)
|
|
14315
14382
|
});
|
|
14316
14383
|
}
|
|
14317
14384
|
}
|
|
14385
|
+
sites.push(site);
|
|
14318
14386
|
}
|
|
14319
|
-
return
|
|
14387
|
+
return numberRepeatedCallSites(sites).flat();
|
|
14320
14388
|
}
|
|
14321
14389
|
function runAccessRecognizers(func, recognizers, barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf) {
|
|
14322
14390
|
return dispatchAccessRecognizers(
|
|
@@ -14401,7 +14469,7 @@ function dispatchAccessRecognizers(root, recognizers, isStop, resolution, origin
|
|
|
14401
14469
|
);
|
|
14402
14470
|
const line = enclosingStatementLine(node);
|
|
14403
14471
|
const preconditions = collectPreconditions(node, root);
|
|
14404
|
-
const
|
|
14472
|
+
const cleansUpFrom = cleanupStartLine(node, root);
|
|
14405
14473
|
for (const recognizer of recognizers) {
|
|
14406
14474
|
let emitted = null;
|
|
14407
14475
|
try {
|
|
@@ -14426,10 +14494,10 @@ function dispatchAccessRecognizers(root, recognizers, isStop, resolution, origin
|
|
|
14426
14494
|
}
|
|
14427
14495
|
seenEffects.add(key);
|
|
14428
14496
|
out.push({
|
|
14429
|
-
effect,
|
|
14497
|
+
effect: placedAt(effect, node),
|
|
14430
14498
|
line,
|
|
14431
14499
|
preconditions,
|
|
14432
|
-
|
|
14500
|
+
cleansUpFrom,
|
|
14433
14501
|
...stated?.of(eff)
|
|
14434
14502
|
});
|
|
14435
14503
|
}
|
|
@@ -14463,6 +14531,12 @@ function extractArg(node, depth) {
|
|
|
14463
14531
|
if (Node54.isFalseLiteral(node)) {
|
|
14464
14532
|
return { kind: "boolean", value: false };
|
|
14465
14533
|
}
|
|
14534
|
+
if (Node54.isNullLiteral(node)) {
|
|
14535
|
+
return { kind: "null" };
|
|
14536
|
+
}
|
|
14537
|
+
if (Node54.isIdentifier(node) && node.getText() === "undefined") {
|
|
14538
|
+
return { kind: "undefined" };
|
|
14539
|
+
}
|
|
14466
14540
|
if (Node54.isTemplateExpression(node)) {
|
|
14467
14541
|
return { kind: "template", sourceText: node.getText() };
|
|
14468
14542
|
}
|
|
@@ -14554,16 +14628,20 @@ function collectPreconditions(node, root) {
|
|
|
14554
14628
|
conditionInfoToRawCondition
|
|
14555
14629
|
);
|
|
14556
14630
|
}
|
|
14557
|
-
function
|
|
14631
|
+
function cleanupStartLine(node, root) {
|
|
14632
|
+
let found;
|
|
14558
14633
|
let current2 = node;
|
|
14559
14634
|
while (current2 !== void 0 && current2 !== root) {
|
|
14560
14635
|
const parent = current2.getParent();
|
|
14561
14636
|
if (parent !== void 0 && Node54.isTryStatement(parent) && parent.getFinallyBlock() === current2) {
|
|
14562
|
-
|
|
14637
|
+
found = startLineOf(parent);
|
|
14563
14638
|
}
|
|
14564
14639
|
current2 = parent;
|
|
14565
14640
|
}
|
|
14566
|
-
return
|
|
14641
|
+
return found;
|
|
14642
|
+
}
|
|
14643
|
+
function placedAt(effect, node) {
|
|
14644
|
+
return { ...effect, location: lineRangeOf(node) };
|
|
14567
14645
|
}
|
|
14568
14646
|
function withPreconditions(effect, preconditions) {
|
|
14569
14647
|
if (preconditions.length === 0) {
|
|
@@ -14595,6 +14673,9 @@ function inlineModuleBinding(ident, depth) {
|
|
|
14595
14673
|
if (!isModuleScoped(decl)) {
|
|
14596
14674
|
continue;
|
|
14597
14675
|
}
|
|
14676
|
+
if (decl.getVariableStatement()?.getDeclarationKind() !== VariableDeclarationKind2.Const) {
|
|
14677
|
+
continue;
|
|
14678
|
+
}
|
|
14598
14679
|
const init = decl.getInitializer();
|
|
14599
14680
|
if (init === void 0) {
|
|
14600
14681
|
continue;
|
|
@@ -15311,8 +15392,8 @@ function typeToShape(type, ctx) {
|
|
|
15311
15392
|
return { type: "number" };
|
|
15312
15393
|
}
|
|
15313
15394
|
if (type.isBooleanLiteral()) {
|
|
15314
|
-
const
|
|
15315
|
-
return { type: "literal", value:
|
|
15395
|
+
const text4 = type.getText(ctx.enclosing);
|
|
15396
|
+
return { type: "literal", value: text4 === "true" };
|
|
15316
15397
|
}
|
|
15317
15398
|
if (type.isString()) {
|
|
15318
15399
|
return { type: "text" };
|
|
@@ -15376,9 +15457,9 @@ function typeToShape(type, ctx) {
|
|
|
15376
15457
|
if (type.isEnum() || type.isEnumLiteral()) {
|
|
15377
15458
|
return enumToShape(type, ctx);
|
|
15378
15459
|
}
|
|
15379
|
-
const
|
|
15380
|
-
if (
|
|
15381
|
-
return { type: "ref", name:
|
|
15460
|
+
const text3 = printedTypeName(type, ctx);
|
|
15461
|
+
if (text3 && text3.length > 0 && text3 !== "__type") {
|
|
15462
|
+
return { type: "ref", name: text3 };
|
|
15382
15463
|
}
|
|
15383
15464
|
return null;
|
|
15384
15465
|
}
|
|
@@ -15521,8 +15602,8 @@ function opaqueNamedRef(type, ctx) {
|
|
|
15521
15602
|
if (!OPAQUE_NAMED_TYPES.has(name)) {
|
|
15522
15603
|
return null;
|
|
15523
15604
|
}
|
|
15524
|
-
const
|
|
15525
|
-
return { type: "ref", name:
|
|
15605
|
+
const text3 = printedTypeName(type, ctx);
|
|
15606
|
+
return { type: "ref", name: text3 && text3.length > 0 ? text3 : name };
|
|
15526
15607
|
}
|
|
15527
15608
|
function outsideProjectRef(type, ctx) {
|
|
15528
15609
|
const symbol = type.getSymbol();
|
|
@@ -15588,8 +15669,8 @@ function definitionKeyFor(type, name, reader) {
|
|
|
15588
15669
|
const written = stableTypeText(type, reader);
|
|
15589
15670
|
return `${name}@${shortHash(written)}`;
|
|
15590
15671
|
}
|
|
15591
|
-
function shortHash(
|
|
15592
|
-
return createHash("sha1").update(
|
|
15672
|
+
function shortHash(text3) {
|
|
15673
|
+
return createHash("sha1").update(text3).digest("hex").slice(0, 12);
|
|
15593
15674
|
}
|
|
15594
15675
|
function refFromType(type, ctx) {
|
|
15595
15676
|
const symbol = type.getAliasSymbol() ?? type.getSymbol();
|
|
@@ -16271,11 +16352,11 @@ function collectJsxAttributes(opening) {
|
|
|
16271
16352
|
}
|
|
16272
16353
|
function jsxChildToRenderNode(child) {
|
|
16273
16354
|
if (Node61.isJsxText(child)) {
|
|
16274
|
-
const
|
|
16275
|
-
if (
|
|
16355
|
+
const text3 = child.getLiteralText().trim();
|
|
16356
|
+
if (text3.length === 0) {
|
|
16276
16357
|
return null;
|
|
16277
16358
|
}
|
|
16278
|
-
return { type: "text", value:
|
|
16359
|
+
return { type: "text", value: text3 };
|
|
16279
16360
|
}
|
|
16280
16361
|
if (Node61.isJsxExpression(child)) {
|
|
16281
16362
|
const inner = child.getExpression();
|
|
@@ -17274,11 +17355,12 @@ function makeFallthroughTerminal(func, pattern) {
|
|
|
17274
17355
|
|
|
17275
17356
|
// src/assembly.ts
|
|
17276
17357
|
var preconditionsOf = (effect) => effect.type === "invocation" ? effect.preconditions : void 0;
|
|
17277
|
-
function
|
|
17278
|
-
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17358
|
+
function invocationSite(call) {
|
|
17359
|
+
return {
|
|
17360
|
+
line: call.line,
|
|
17361
|
+
preconditions: preconditionsOf(call.effect),
|
|
17362
|
+
cleansUpFrom: call.cleansUpFrom
|
|
17363
|
+
};
|
|
17282
17364
|
}
|
|
17283
17365
|
function writesTerminal(call, terminalNodes) {
|
|
17284
17366
|
let current2 = call;
|
|
@@ -17376,7 +17458,7 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
17376
17458
|
const endings = new Set(
|
|
17377
17459
|
terminals.filter(({ terminal }) => terminal.kind === "exit").map(({ node }) => node)
|
|
17378
17460
|
);
|
|
17379
|
-
const { byTerminal } = computePathConditions(
|
|
17461
|
+
const { byTerminal, placement } = computePathConditions(
|
|
17380
17462
|
func,
|
|
17381
17463
|
terminals.map(({ node }) => node),
|
|
17382
17464
|
barriers,
|
|
@@ -17409,6 +17491,7 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
17409
17491
|
const rawBranches = terminals.flatMap(
|
|
17410
17492
|
({ node, terminal, whenAlso }) => {
|
|
17411
17493
|
const conditionLists = byTerminal.get(node) ?? [];
|
|
17494
|
+
const loopAround = placement.get(node)?.loopAround;
|
|
17412
17495
|
return conditionLists.map((infos) => {
|
|
17413
17496
|
const conditions = [
|
|
17414
17497
|
...infos.map(conditionInfoToRawCondition),
|
|
@@ -17419,6 +17502,7 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
17419
17502
|
terminal,
|
|
17420
17503
|
effects: [],
|
|
17421
17504
|
location: terminal.location,
|
|
17505
|
+
...loopAround === void 0 ? {} : { loopAround },
|
|
17422
17506
|
isDefault: isDefaultConditionList(infos)
|
|
17423
17507
|
};
|
|
17424
17508
|
});
|
|
@@ -17445,9 +17529,7 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
17445
17529
|
(i) => !writesTerminal(i.node, terminalNodes)
|
|
17446
17530
|
);
|
|
17447
17531
|
for (const branch of distinctBranches) {
|
|
17448
|
-
branch.effects = sideEffects.filter(
|
|
17449
|
-
(i) => firesOn({ ...i, preconditions: preconditionsOf(i.effect) }, branch)
|
|
17450
|
-
).map((i) => i.effect);
|
|
17532
|
+
branch.effects = sideEffects.filter((i) => firesOn(invocationSite(i), branch)).map((i) => i.effect);
|
|
17451
17533
|
}
|
|
17452
17534
|
}
|
|
17453
17535
|
const firing = /* @__PURE__ */ new Map();
|
|
@@ -17492,11 +17574,9 @@ function handOffSites(invocations, terminalNodes, handOff, reading) {
|
|
|
17492
17574
|
continue;
|
|
17493
17575
|
}
|
|
17494
17576
|
sites.push({
|
|
17577
|
+
...invocationSite(site),
|
|
17495
17578
|
helper,
|
|
17496
|
-
|
|
17497
|
-
line: site.line,
|
|
17498
|
-
at: lineRangeOf(site.node),
|
|
17499
|
-
alwaysRuns: site.alwaysRuns
|
|
17579
|
+
at: lineRangeOf(site.node)
|
|
17500
17580
|
});
|
|
17501
17581
|
}
|
|
17502
17582
|
return sites;
|
|
@@ -17522,16 +17602,12 @@ function accountFor(site, terminalNodes, branches) {
|
|
|
17522
17602
|
if (writesTerminal(node, terminalNodes)) {
|
|
17523
17603
|
return { node, callee, line, outcome: "terminal" };
|
|
17524
17604
|
}
|
|
17525
|
-
const call =
|
|
17526
|
-
line,
|
|
17527
|
-
alwaysRuns: site.alwaysRuns,
|
|
17528
|
-
preconditions: preconditionsOf(site.effect)
|
|
17529
|
-
};
|
|
17605
|
+
const call = invocationSite(site);
|
|
17530
17606
|
if (branches.some((branch) => firesOn(call, branch))) {
|
|
17531
17607
|
return { node, callee, line, outcome: "invocation" };
|
|
17532
17608
|
}
|
|
17533
17609
|
const reachable = branches.some(
|
|
17534
|
-
(branch) =>
|
|
17610
|
+
(branch) => runsBefore(call.cleansUpFrom ?? line, branch.terminal.location.end)
|
|
17535
17611
|
);
|
|
17536
17612
|
return {
|
|
17537
17613
|
node,
|
|
@@ -18220,6 +18296,10 @@ function parameterName(segment, convention) {
|
|
|
18220
18296
|
return null;
|
|
18221
18297
|
}
|
|
18222
18298
|
|
|
18299
|
+
// src/discovery/graphqlCallClient.ts
|
|
18300
|
+
import { Node as Node70 } from "ts-morph";
|
|
18301
|
+
import { force as force6, hole, text as text2 } from "@suss/values";
|
|
18302
|
+
|
|
18223
18303
|
// src/discovery/graphqlClientConstruction.ts
|
|
18224
18304
|
import picomatch2 from "picomatch";
|
|
18225
18305
|
import {
|
|
@@ -18231,34 +18311,123 @@ import {
|
|
|
18231
18311
|
withGraphqlMetadata
|
|
18232
18312
|
} from "@suss/behavioral-ir";
|
|
18233
18313
|
function stampGraphqlClientRefs(summaries, sourceFiles, packs, resolution) {
|
|
18234
|
-
const
|
|
18314
|
+
const constructions = graphqlClientConstructions(
|
|
18315
|
+
sourceFiles,
|
|
18316
|
+
packs.flatMap((pack) => pack.graphqlClients ?? []),
|
|
18317
|
+
resolution
|
|
18318
|
+
);
|
|
18235
18319
|
const sole = soleGraphqlClientRef(
|
|
18236
|
-
|
|
18320
|
+
constructionRefs(constructions, resolution)
|
|
18237
18321
|
);
|
|
18238
|
-
const
|
|
18239
|
-
|
|
18322
|
+
const grounding = {
|
|
18323
|
+
packs,
|
|
18324
|
+
scopes: compileOperationScopes(packs),
|
|
18325
|
+
sole,
|
|
18326
|
+
soleClient: withBoundWorkspace(sole, packs),
|
|
18327
|
+
clientsBuilt: constructions.filter(
|
|
18328
|
+
(construction) => construction.spec.linkProperty !== void 0
|
|
18329
|
+
).length,
|
|
18330
|
+
pairWithAll: packs.some(
|
|
18331
|
+
(pack) => pack.graphqlUnboundClients === "pairWithAll"
|
|
18332
|
+
)
|
|
18333
|
+
};
|
|
18240
18334
|
let registry = null;
|
|
18241
18335
|
for (const summary of summaries) {
|
|
18242
18336
|
if (!isGraphqlOperationBinding(summary.identity.boundaryBinding)) {
|
|
18243
18337
|
continue;
|
|
18244
18338
|
}
|
|
18245
18339
|
const existing = readGraphqlMetadata(summary) ?? {};
|
|
18246
|
-
const
|
|
18247
|
-
const client = scoped !== null ? { uri: null, uriRef: null, workspace: scoped } : soleClient;
|
|
18340
|
+
const decided = clientFor(summary, existing, grounding);
|
|
18248
18341
|
const dangling = (existing.unresolvedFragments?.length ?? 0) > 0;
|
|
18249
|
-
if (
|
|
18342
|
+
if (decided === null && !dangling) {
|
|
18250
18343
|
continue;
|
|
18251
18344
|
}
|
|
18252
18345
|
if (dangling && registry === null) {
|
|
18253
18346
|
registry = fragmentRegistryStatus(sourceFiles, packs, resolution);
|
|
18254
18347
|
}
|
|
18255
18348
|
summary.metadata = withGraphqlMetadata(summary.metadata, {
|
|
18256
|
-
...existing,
|
|
18257
|
-
...
|
|
18349
|
+
...decided === null ? existing : withoutClient(existing),
|
|
18350
|
+
...decided ?? {},
|
|
18258
18351
|
...dangling && registry !== null ? { fragmentRegistry: registry } : {}
|
|
18259
18352
|
});
|
|
18260
18353
|
}
|
|
18261
18354
|
}
|
|
18355
|
+
function withBoundWorkspace(sole, packs) {
|
|
18356
|
+
if (sole === null) {
|
|
18357
|
+
return null;
|
|
18358
|
+
}
|
|
18359
|
+
const workspace = boundWorkspaceFor(sole, packs);
|
|
18360
|
+
return workspace === null ? sole : { ...sole, workspace };
|
|
18361
|
+
}
|
|
18362
|
+
function underUnboundSetting(unresolved, grounding) {
|
|
18363
|
+
return grounding.pairWithAll ? { ...unresolved, pairWithAll: true } : unresolved;
|
|
18364
|
+
}
|
|
18365
|
+
function clientFor(summary, existing, grounding) {
|
|
18366
|
+
const scoped = scopedWorkspaceFor(summary.location.file, grounding.scopes);
|
|
18367
|
+
const chosen = existing.client?.chosenAtCall === true ? existing.client : null;
|
|
18368
|
+
if (chosen === null) {
|
|
18369
|
+
const open = existing.unresolvedClient !== void 0;
|
|
18370
|
+
if (existing.unresolvedClient !== void 0 && !oneEndpointToChoose(grounding)) {
|
|
18371
|
+
return grounding.pairWithAll ? {
|
|
18372
|
+
unresolvedClient: {
|
|
18373
|
+
...existing.unresolvedClient,
|
|
18374
|
+
pairWithAll: true
|
|
18375
|
+
}
|
|
18376
|
+
} : null;
|
|
18377
|
+
}
|
|
18378
|
+
const client = scoped !== null ? { uri: null, uriRef: null, workspace: scoped } : grounding.soleClient;
|
|
18379
|
+
if (client === null) {
|
|
18380
|
+
return open ? {} : null;
|
|
18381
|
+
}
|
|
18382
|
+
return { client };
|
|
18383
|
+
}
|
|
18384
|
+
const passed = {
|
|
18385
|
+
uri: chosen.uri,
|
|
18386
|
+
uriRef: chosen.uriRef,
|
|
18387
|
+
chosenAtCall: true
|
|
18388
|
+
};
|
|
18389
|
+
const bound = boundWorkspaceFor(passed, grounding.packs) ?? scoped;
|
|
18390
|
+
if (bound !== null) {
|
|
18391
|
+
return { client: { ...passed, workspace: bound } };
|
|
18392
|
+
}
|
|
18393
|
+
if (isTheAppsClient(passed, grounding)) {
|
|
18394
|
+
return { client: passed };
|
|
18395
|
+
}
|
|
18396
|
+
return {
|
|
18397
|
+
client: passed,
|
|
18398
|
+
unresolvedClient: underUnboundSetting(unboundClient(passed), grounding)
|
|
18399
|
+
};
|
|
18400
|
+
}
|
|
18401
|
+
function isTheAppsClient(passed, grounding) {
|
|
18402
|
+
if (grounding.clientsBuilt === 1) {
|
|
18403
|
+
return true;
|
|
18404
|
+
}
|
|
18405
|
+
const key = endpointKeyOf(passed);
|
|
18406
|
+
return key !== null && grounding.sole !== null && key === endpointKeyOf(grounding.sole);
|
|
18407
|
+
}
|
|
18408
|
+
function oneEndpointToChoose(grounding) {
|
|
18409
|
+
return grounding.clientsBuilt <= 1 || grounding.sole !== null;
|
|
18410
|
+
}
|
|
18411
|
+
function unboundClient(passed) {
|
|
18412
|
+
const key = endpointKeyOf(passed);
|
|
18413
|
+
if (key === null) {
|
|
18414
|
+
return {
|
|
18415
|
+
reference: "the client it passes",
|
|
18416
|
+
reason: "it passes a client whose endpoint suss could not read, and the project builds more than one client, so suss cannot tell which service this one talks to"
|
|
18417
|
+
};
|
|
18418
|
+
}
|
|
18419
|
+
return {
|
|
18420
|
+
reference: key,
|
|
18421
|
+
reason: `it passes the client built with ${key}, the project builds more than one client, and no \`clients\` entry in the pack options says which service ${key} talks to`
|
|
18422
|
+
};
|
|
18423
|
+
}
|
|
18424
|
+
function endpointKeyOf(ref) {
|
|
18425
|
+
return ref.uri ?? ref.uriRef;
|
|
18426
|
+
}
|
|
18427
|
+
function withoutClient(existing) {
|
|
18428
|
+
const { client: _client, unresolvedClient: _unresolved, ...rest } = existing;
|
|
18429
|
+
return rest;
|
|
18430
|
+
}
|
|
18262
18431
|
function compileOperationScopes(packs) {
|
|
18263
18432
|
return packs.flatMap((pack) => pack.graphqlOperationScopes ?? []).map((scope) => {
|
|
18264
18433
|
const matchers2 = scope.files.map(
|
|
@@ -18291,13 +18460,22 @@ function boundWorkspaceFor(ref, packs) {
|
|
|
18291
18460
|
}
|
|
18292
18461
|
return null;
|
|
18293
18462
|
}
|
|
18294
|
-
function
|
|
18295
|
-
|
|
18463
|
+
function constructionRefs(constructions, resolution) {
|
|
18464
|
+
return constructions.flatMap((construction) => {
|
|
18465
|
+
const found = constructionRef(
|
|
18466
|
+
construction.node,
|
|
18467
|
+
construction.spec.uriProperty,
|
|
18468
|
+
resolution
|
|
18469
|
+
);
|
|
18470
|
+
return found === null ? [] : [found];
|
|
18471
|
+
});
|
|
18472
|
+
}
|
|
18473
|
+
function graphqlClientConstructions(sourceFiles, specs, resolution) {
|
|
18296
18474
|
if (specs.length === 0) {
|
|
18297
18475
|
return [];
|
|
18298
18476
|
}
|
|
18299
18477
|
const store = resolution ?? new ResolutionStore();
|
|
18300
|
-
const
|
|
18478
|
+
const found = [];
|
|
18301
18479
|
for (const sourceFile of sourceFiles) {
|
|
18302
18480
|
for (const spec of specs) {
|
|
18303
18481
|
const constructions = callsByOriginName(
|
|
@@ -18307,14 +18485,27 @@ function collectGraphqlClientRefs(sourceFiles, packs, resolution) {
|
|
|
18307
18485
|
/* @__PURE__ */ new Set([spec.importName])
|
|
18308
18486
|
);
|
|
18309
18487
|
for (const node of constructions.keys()) {
|
|
18310
|
-
|
|
18311
|
-
if (found !== null) {
|
|
18312
|
-
refs.push(found);
|
|
18313
|
-
}
|
|
18488
|
+
found.push({ node, spec });
|
|
18314
18489
|
}
|
|
18315
18490
|
}
|
|
18316
18491
|
}
|
|
18317
|
-
return
|
|
18492
|
+
return found;
|
|
18493
|
+
}
|
|
18494
|
+
function constructionEndpoint(construction, transports, resolution) {
|
|
18495
|
+
const own = constructionRef(
|
|
18496
|
+
construction.node,
|
|
18497
|
+
construction.spec.uriProperty,
|
|
18498
|
+
resolution
|
|
18499
|
+
);
|
|
18500
|
+
const linkProperty = construction.spec.linkProperty;
|
|
18501
|
+
if (own !== null || linkProperty === void 0) {
|
|
18502
|
+
return own;
|
|
18503
|
+
}
|
|
18504
|
+
const options = firstArgumentObject(construction.node, resolution);
|
|
18505
|
+
const link = options === null ? null : propertyOf(options, linkProperty, resolution);
|
|
18506
|
+
const transport = link === null ? null : writtenNodeOf(link, resolution);
|
|
18507
|
+
const built = transports.find((one) => one.node === transport);
|
|
18508
|
+
return built === void 0 ? null : constructionRef(built.node, built.spec.uriProperty, resolution);
|
|
18318
18509
|
}
|
|
18319
18510
|
function soleGraphqlClientRef(refs) {
|
|
18320
18511
|
const distinct = /* @__PURE__ */ new Map();
|
|
@@ -18437,11 +18628,153 @@ function constructionRef(node, uriProperty, resolution) {
|
|
|
18437
18628
|
return { uri: null, uriRef: value.getText() };
|
|
18438
18629
|
}
|
|
18439
18630
|
|
|
18631
|
+
// src/discovery/graphqlCallClient.ts
|
|
18632
|
+
var REFERENCE_LIMIT = 80;
|
|
18633
|
+
function clientChosenAt(site, specs, resolution) {
|
|
18634
|
+
const store = resolution ?? new ResolutionStore();
|
|
18635
|
+
const written = writtenClientOf(site, store);
|
|
18636
|
+
if (written === null) {
|
|
18637
|
+
return null;
|
|
18638
|
+
}
|
|
18639
|
+
const constructions = constructionsInProject(
|
|
18640
|
+
site.call.getSourceFile(),
|
|
18641
|
+
specs,
|
|
18642
|
+
store
|
|
18643
|
+
);
|
|
18644
|
+
const tokens = new Map(
|
|
18645
|
+
constructions.map((construction, at) => [
|
|
18646
|
+
construction.node,
|
|
18647
|
+
text2(`suss:client#${at}`)
|
|
18648
|
+
])
|
|
18649
|
+
);
|
|
18650
|
+
const value = evaluatedValueThrough(
|
|
18651
|
+
written.node,
|
|
18652
|
+
site.through,
|
|
18653
|
+
store,
|
|
18654
|
+
tokens
|
|
18655
|
+
);
|
|
18656
|
+
const chosen = value === null ? unreadChain(written, store) : clientValueOf(value, written.property);
|
|
18657
|
+
if (chosen === void 0) {
|
|
18658
|
+
return null;
|
|
18659
|
+
}
|
|
18660
|
+
const picked = tokensIn(chosen, constructions.length);
|
|
18661
|
+
if (picked !== null && picked.length === 1) {
|
|
18662
|
+
const construction = constructions[picked[0]];
|
|
18663
|
+
const endpoint = construction === void 0 ? null : constructionEndpoint(construction, constructions, store);
|
|
18664
|
+
return {
|
|
18665
|
+
kind: "settled",
|
|
18666
|
+
client: endpoint ?? { uri: null, uriRef: null }
|
|
18667
|
+
};
|
|
18668
|
+
}
|
|
18669
|
+
if (picked === null && written.property === null) {
|
|
18670
|
+
return null;
|
|
18671
|
+
}
|
|
18672
|
+
const reference = referenceOf(written.node, written.property, store);
|
|
18673
|
+
const passes = written.property === null ? "the client it is called on" : "the client it passes";
|
|
18674
|
+
if (picked !== null && picked.length > 1) {
|
|
18675
|
+
return {
|
|
18676
|
+
kind: "unresolved",
|
|
18677
|
+
reference,
|
|
18678
|
+
reason: `${passes}, ${reference}, can be any of ${picked.length} clients, and nothing the call passes settles which`
|
|
18679
|
+
};
|
|
18680
|
+
}
|
|
18681
|
+
return {
|
|
18682
|
+
kind: "unresolved",
|
|
18683
|
+
reference,
|
|
18684
|
+
reason: `${passes}, ${reference}, does not come out as one client construction suss can read`
|
|
18685
|
+
};
|
|
18686
|
+
}
|
|
18687
|
+
function writtenClientOf(site, store) {
|
|
18688
|
+
if (site.client === "receiver") {
|
|
18689
|
+
const callee = site.call.getExpression();
|
|
18690
|
+
return Node70.isPropertyAccessExpression(callee) ? { node: callee.getExpression(), property: null } : null;
|
|
18691
|
+
}
|
|
18692
|
+
const options = site.call.getArguments()[site.client.argument];
|
|
18693
|
+
if (options === void 0) {
|
|
18694
|
+
return null;
|
|
18695
|
+
}
|
|
18696
|
+
const direct = site.through.length === 0;
|
|
18697
|
+
if (direct && optionWritten(options, site.client.property, store) === null) {
|
|
18698
|
+
return null;
|
|
18699
|
+
}
|
|
18700
|
+
return { node: options, property: site.client.property };
|
|
18701
|
+
}
|
|
18702
|
+
function clientValueOf(value, property) {
|
|
18703
|
+
const forced = force6(value);
|
|
18704
|
+
if (property === null) {
|
|
18705
|
+
return isUndefined(forced) ? void 0 : forced;
|
|
18706
|
+
}
|
|
18707
|
+
if (forced.kind !== "record") {
|
|
18708
|
+
return void 0;
|
|
18709
|
+
}
|
|
18710
|
+
const field = forced.fields.get(property);
|
|
18711
|
+
if (field === void 0 || isUndefined(force6(field.value))) {
|
|
18712
|
+
return void 0;
|
|
18713
|
+
}
|
|
18714
|
+
return force6(field.value);
|
|
18715
|
+
}
|
|
18716
|
+
function unreadChain(written, store) {
|
|
18717
|
+
if (written.property === null) {
|
|
18718
|
+
return hole("client");
|
|
18719
|
+
}
|
|
18720
|
+
return optionWritten(written.node, written.property, store) === null ? void 0 : hole("client");
|
|
18721
|
+
}
|
|
18722
|
+
function isUndefined(value) {
|
|
18723
|
+
return value.kind === "constant" && value.options.every((option) => option === void 0);
|
|
18724
|
+
}
|
|
18725
|
+
function tokensIn(value, count) {
|
|
18726
|
+
if (value.kind !== "string" || value.pieces.length !== 1) {
|
|
18727
|
+
return null;
|
|
18728
|
+
}
|
|
18729
|
+
const piece = value.pieces[0];
|
|
18730
|
+
if (piece?.kind !== "text") {
|
|
18731
|
+
return null;
|
|
18732
|
+
}
|
|
18733
|
+
const picked = [];
|
|
18734
|
+
for (const option of piece.options) {
|
|
18735
|
+
const at = /^suss:client#(\d+)$/.exec(option)?.[1];
|
|
18736
|
+
if (at === void 0 || Number(at) >= count) {
|
|
18737
|
+
return null;
|
|
18738
|
+
}
|
|
18739
|
+
picked.push(Number(at));
|
|
18740
|
+
}
|
|
18741
|
+
return picked;
|
|
18742
|
+
}
|
|
18743
|
+
function referenceOf(node, property, store) {
|
|
18744
|
+
const written = property === null ? node : optionWritten(node, property, store);
|
|
18745
|
+
const shown = written === null ? `${node.getText()}.${property}` : writtenText(written, store);
|
|
18746
|
+
return shown.length > REFERENCE_LIMIT ? `${shown.slice(0, REFERENCE_LIMIT - 3)}...` : shown;
|
|
18747
|
+
}
|
|
18748
|
+
function optionWritten(options, property, store) {
|
|
18749
|
+
const literal = objectLiteralOf(options, store);
|
|
18750
|
+
return literal === null ? null : propertyOf(literal, property, store);
|
|
18751
|
+
}
|
|
18752
|
+
function writtenText(node, store) {
|
|
18753
|
+
if (!Node70.isIdentifier(node)) {
|
|
18754
|
+
return node.getText();
|
|
18755
|
+
}
|
|
18756
|
+
const value = store.resolveWrittenValue(node);
|
|
18757
|
+
return value === null ? node.getText() : value.getText();
|
|
18758
|
+
}
|
|
18759
|
+
var constructionsByStore = /* @__PURE__ */ new WeakMap();
|
|
18760
|
+
function constructionsInProject(sourceFile, specs, store) {
|
|
18761
|
+
const bySpecs = constructionsByStore.get(store) ?? /* @__PURE__ */ new WeakMap();
|
|
18762
|
+
constructionsByStore.set(store, bySpecs);
|
|
18763
|
+
const known = bySpecs.get(specs);
|
|
18764
|
+
if (known !== void 0) {
|
|
18765
|
+
return known;
|
|
18766
|
+
}
|
|
18767
|
+
const files = sourceFile.getProject().getSourceFiles().filter((file) => !file.isDeclarationFile() && !file.isInNodeModules());
|
|
18768
|
+
const found = graphqlClientConstructions(files, specs, store);
|
|
18769
|
+
bySpecs.set(specs, found);
|
|
18770
|
+
return found;
|
|
18771
|
+
}
|
|
18772
|
+
|
|
18440
18773
|
// src/discovery/helperIndex.ts
|
|
18441
|
-
import { Node as
|
|
18774
|
+
import { Node as Node72 } from "ts-morph";
|
|
18442
18775
|
|
|
18443
18776
|
// src/discovery/helperReading.ts
|
|
18444
|
-
import { Node as
|
|
18777
|
+
import { Node as Node71 } from "ts-morph";
|
|
18445
18778
|
var UNREAD = { as: "unread" };
|
|
18446
18779
|
function readHelperSinks(helper) {
|
|
18447
18780
|
const positions = parameterPositions(helper);
|
|
@@ -18451,11 +18784,11 @@ function readHelperSinks(helper) {
|
|
|
18451
18784
|
return sinks;
|
|
18452
18785
|
}
|
|
18453
18786
|
body.forEachDescendant((node) => {
|
|
18454
|
-
if (!
|
|
18787
|
+
if (!Node71.isCallExpression(node)) {
|
|
18455
18788
|
return;
|
|
18456
18789
|
}
|
|
18457
18790
|
const callee = node.getExpression();
|
|
18458
|
-
const [method, receiver] =
|
|
18791
|
+
const [method, receiver] = Node71.isPropertyAccessExpression(callee) ? [callee.getName(), readValue(callee.getExpression(), positions)] : [null, UNREAD];
|
|
18459
18792
|
sinks.push({
|
|
18460
18793
|
method,
|
|
18461
18794
|
receiver,
|
|
@@ -18475,25 +18808,25 @@ function parameterPositions(helper) {
|
|
|
18475
18808
|
return positions;
|
|
18476
18809
|
}
|
|
18477
18810
|
function readValue(node, positions) {
|
|
18478
|
-
if (
|
|
18811
|
+
if (Node71.isStringLiteral(node) || Node71.isNoSubstitutionTemplateLiteral(node)) {
|
|
18479
18812
|
return { as: "text", text: node.getLiteralValue() };
|
|
18480
18813
|
}
|
|
18481
|
-
if (
|
|
18814
|
+
if (Node71.isTemplateExpression(node)) {
|
|
18482
18815
|
return templateText(node, positions);
|
|
18483
18816
|
}
|
|
18484
|
-
if (
|
|
18817
|
+
if (Node71.isIdentifier(node)) {
|
|
18485
18818
|
const position = positions.get(node.getText());
|
|
18486
18819
|
return position === void 0 ? UNREAD : { as: "parameter", position };
|
|
18487
18820
|
}
|
|
18488
|
-
if (
|
|
18821
|
+
if (Node71.isPropertyAccessExpression(node)) {
|
|
18489
18822
|
const target = node.getExpression();
|
|
18490
|
-
const position =
|
|
18823
|
+
const position = Node71.isIdentifier(target) ? positions.get(target.getText()) : void 0;
|
|
18491
18824
|
return position === void 0 ? UNREAD : { as: "parameter", position, property: node.getName() };
|
|
18492
18825
|
}
|
|
18493
|
-
if (
|
|
18826
|
+
if (Node71.isObjectLiteralExpression(node)) {
|
|
18494
18827
|
return objectValue(node, positions);
|
|
18495
18828
|
}
|
|
18496
|
-
if (
|
|
18829
|
+
if (Node71.isCallExpression(node)) {
|
|
18497
18830
|
return {
|
|
18498
18831
|
as: "call",
|
|
18499
18832
|
callee: node.getExpression().getText(),
|
|
@@ -18503,27 +18836,27 @@ function readValue(node, positions) {
|
|
|
18503
18836
|
return UNREAD;
|
|
18504
18837
|
}
|
|
18505
18838
|
function templateText(node, positions) {
|
|
18506
|
-
if (!
|
|
18839
|
+
if (!Node71.isTemplateExpression(node)) {
|
|
18507
18840
|
return UNREAD;
|
|
18508
18841
|
}
|
|
18509
|
-
let
|
|
18842
|
+
let text3 = node.getHead().getLiteralText();
|
|
18510
18843
|
for (const span of node.getTemplateSpans()) {
|
|
18511
18844
|
const expression = span.getExpression();
|
|
18512
|
-
const position =
|
|
18845
|
+
const position = Node71.isIdentifier(expression) ? positions.get(expression.getText()) : void 0;
|
|
18513
18846
|
if (position === void 0) {
|
|
18514
18847
|
return UNREAD;
|
|
18515
18848
|
}
|
|
18516
|
-
|
|
18849
|
+
text3 += `{${position}}${span.getLiteral().getLiteralText()}`;
|
|
18517
18850
|
}
|
|
18518
|
-
return { as: "text", text:
|
|
18851
|
+
return { as: "text", text: text3 };
|
|
18519
18852
|
}
|
|
18520
18853
|
function objectValue(node, positions) {
|
|
18521
|
-
if (!
|
|
18854
|
+
if (!Node71.isObjectLiteralExpression(node)) {
|
|
18522
18855
|
return UNREAD;
|
|
18523
18856
|
}
|
|
18524
18857
|
const properties = {};
|
|
18525
18858
|
for (const property of node.getProperties()) {
|
|
18526
|
-
if (!
|
|
18859
|
+
if (!Node71.isPropertyAssignment(property)) {
|
|
18527
18860
|
continue;
|
|
18528
18861
|
}
|
|
18529
18862
|
const initializer = property.getInitializer();
|
|
@@ -18538,7 +18871,7 @@ function objectValue(node, positions) {
|
|
|
18538
18871
|
return { as: "object", properties };
|
|
18539
18872
|
}
|
|
18540
18873
|
function propertyKey(name) {
|
|
18541
|
-
return
|
|
18874
|
+
return Node71.isStringLiteral(name) ? name.getLiteralValue() : name.getText();
|
|
18542
18875
|
}
|
|
18543
18876
|
|
|
18544
18877
|
// src/discovery/helperIndex.ts
|
|
@@ -18622,8 +18955,8 @@ function noteExpanded(expanded, readings, discovery) {
|
|
|
18622
18955
|
}
|
|
18623
18956
|
}
|
|
18624
18957
|
function mentionsAnyOf(file, written) {
|
|
18625
|
-
const
|
|
18626
|
-
return written.some((word) =>
|
|
18958
|
+
const text3 = file.getFullText();
|
|
18959
|
+
return written.some((word) => text3.includes(word));
|
|
18627
18960
|
}
|
|
18628
18961
|
function readSubjectHelpers(pack, packsByFile, resolution) {
|
|
18629
18962
|
const matches = registrationMatchesOf(pack);
|
|
@@ -18668,11 +19001,11 @@ function registrationMatchesOf(pack) {
|
|
|
18668
19001
|
}
|
|
18669
19002
|
function collectHandOffs(sourceFile, subjects, match, resolution, found) {
|
|
18670
19003
|
sourceFile.forEachDescendant((node) => {
|
|
18671
|
-
if (!
|
|
19004
|
+
if (!Node72.isCallExpression(node)) {
|
|
18672
19005
|
return;
|
|
18673
19006
|
}
|
|
18674
19007
|
const callee = node.getExpression();
|
|
18675
|
-
if (!
|
|
19008
|
+
if (!Node72.isIdentifier(callee)) {
|
|
18676
19009
|
return;
|
|
18677
19010
|
}
|
|
18678
19011
|
const handedOver = subjectArgument(node, subjects, match, resolution);
|
|
@@ -18687,12 +19020,12 @@ function collectHandOffs(sourceFile, subjects, match, resolution, found) {
|
|
|
18687
19020
|
});
|
|
18688
19021
|
}
|
|
18689
19022
|
function subjectArgument(call, subjects, match, resolution) {
|
|
18690
|
-
if (!
|
|
19023
|
+
if (!Node72.isCallExpression(call)) {
|
|
18691
19024
|
return -1;
|
|
18692
19025
|
}
|
|
18693
19026
|
const args = call.getArguments();
|
|
18694
19027
|
for (const [position, argument] of args.entries()) {
|
|
18695
|
-
if (!
|
|
19028
|
+
if (!Node72.isIdentifier(argument) && !Node72.isPropertyAccessExpression(argument)) {
|
|
18696
19029
|
continue;
|
|
18697
19030
|
}
|
|
18698
19031
|
if (subjectNodeFor(argument, subjects, match, resolution) !== void 0) {
|
|
@@ -18724,8 +19057,8 @@ function record(found, helper, name, subjectParameter) {
|
|
|
18724
19057
|
function readTextHelpers(sourceFiles, contains) {
|
|
18725
19058
|
const readings = [];
|
|
18726
19059
|
for (const sourceFile of sourceFiles) {
|
|
18727
|
-
const
|
|
18728
|
-
if (!contains.some((mark) =>
|
|
19060
|
+
const text3 = sourceFile.getFullText();
|
|
19061
|
+
if (!contains.some((mark) => text3.includes(mark))) {
|
|
18729
19062
|
continue;
|
|
18730
19063
|
}
|
|
18731
19064
|
for (const [name, declaration] of declaredFunctions(sourceFile)) {
|
|
@@ -18753,7 +19086,7 @@ function declaredFunctions(sourceFile) {
|
|
|
18753
19086
|
}
|
|
18754
19087
|
for (const variable3 of sourceFile.getVariableDeclarations()) {
|
|
18755
19088
|
const initializer = variable3.getInitializer();
|
|
18756
|
-
if (initializer !== void 0 && (
|
|
19089
|
+
if (initializer !== void 0 && (Node72.isArrowFunction(initializer) || Node72.isFunctionExpression(initializer))) {
|
|
18757
19090
|
found.push([variable3.getName(), initializer]);
|
|
18758
19091
|
}
|
|
18759
19092
|
}
|
|
@@ -18924,8 +19257,8 @@ function recordEdge(edgesByChild, candidate) {
|
|
|
18924
19257
|
}
|
|
18925
19258
|
|
|
18926
19259
|
// src/discovery/restWrapper.ts
|
|
18927
|
-
import { Node as
|
|
18928
|
-
import { hole } from "@suss/values";
|
|
19260
|
+
import { Node as Node73 } from "ts-morph";
|
|
19261
|
+
import { hole as hole2 } from "@suss/values";
|
|
18929
19262
|
var MAX_WRAPPER_DEPTH2 = 3;
|
|
18930
19263
|
function expandRestWrapperCallers(wrapper, readSink, store) {
|
|
18931
19264
|
return expandFrom(
|
|
@@ -18941,8 +19274,8 @@ function parametersAsHoles(func) {
|
|
|
18941
19274
|
const bindings = /* @__PURE__ */ new Map();
|
|
18942
19275
|
for (const parameter of func.getParameters()) {
|
|
18943
19276
|
const nameNode = parameter.getNameNode();
|
|
18944
|
-
if (
|
|
18945
|
-
bindings.set(nameNode.getText(),
|
|
19277
|
+
if (Node73.isIdentifier(nameNode)) {
|
|
19278
|
+
bindings.set(nameNode.getText(), hole2(nameNode.getText()));
|
|
18946
19279
|
}
|
|
18947
19280
|
}
|
|
18948
19281
|
return bindings;
|
|
@@ -18981,11 +19314,11 @@ function callSitesOf(func, store) {
|
|
|
18981
19314
|
const byCall = /* @__PURE__ */ new Map();
|
|
18982
19315
|
for (const parameter of func.getParameters()) {
|
|
18983
19316
|
const nameNode = parameter.getNameNode();
|
|
18984
|
-
if (!
|
|
19317
|
+
if (!Node73.isIdentifier(nameNode)) {
|
|
18985
19318
|
continue;
|
|
18986
19319
|
}
|
|
18987
19320
|
for (const passed of store.argumentsPassedTo(parameter)) {
|
|
18988
|
-
if (!
|
|
19321
|
+
if (!Node73.isCallExpression(passed.call)) {
|
|
18989
19322
|
continue;
|
|
18990
19323
|
}
|
|
18991
19324
|
const key = siteKey(passed.call);
|
|
@@ -19011,7 +19344,7 @@ function valuesAt(site, bindings, store) {
|
|
|
19011
19344
|
}
|
|
19012
19345
|
|
|
19013
19346
|
// src/discovery/wrapperIndex.ts
|
|
19014
|
-
import { Node as
|
|
19347
|
+
import { Node as Node74 } from "ts-morph";
|
|
19015
19348
|
import { joinMountedPath as joinMountedPath3 } from "@suss/resolution";
|
|
19016
19349
|
var NO_WRAPPERS = {
|
|
19017
19350
|
wrappersFor: () => [],
|
|
@@ -19135,11 +19468,11 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
|
|
|
19135
19468
|
const candidates = [];
|
|
19136
19469
|
const unresolved = [];
|
|
19137
19470
|
sourceFile.forEachDescendant((node) => {
|
|
19138
|
-
if (!
|
|
19471
|
+
if (!Node74.isCallExpression(node)) {
|
|
19139
19472
|
return;
|
|
19140
19473
|
}
|
|
19141
19474
|
const callee = node.getExpression();
|
|
19142
|
-
if (!
|
|
19475
|
+
if (!Node74.isPropertyAccessExpression(callee) || callee.getName() !== wraps.method) {
|
|
19143
19476
|
return;
|
|
19144
19477
|
}
|
|
19145
19478
|
const subjectNode = subjectNodeFor(
|
|
@@ -19234,7 +19567,7 @@ function discoverConstructorOptions(sourceFile, pattern, wraps, subjects, resolu
|
|
|
19234
19567
|
return { candidates, unresolved };
|
|
19235
19568
|
}
|
|
19236
19569
|
function constructorOptionOf(construction, wraps, resolution) {
|
|
19237
|
-
if (!(
|
|
19570
|
+
if (!(Node74.isNewExpression(construction) || Node74.isCallExpression(construction))) {
|
|
19238
19571
|
return void 0;
|
|
19239
19572
|
}
|
|
19240
19573
|
const optionsArg = construction.getArguments()[wraps.targetPosition];
|
|
@@ -19289,7 +19622,7 @@ function scopeOf(args, wraps, resolution) {
|
|
|
19289
19622
|
}
|
|
19290
19623
|
|
|
19291
19624
|
// src/discoveryContext.ts
|
|
19292
|
-
import { Node as
|
|
19625
|
+
import { Node as Node75 } from "ts-morph";
|
|
19293
19626
|
function createTsDiscoveryContext(resolution) {
|
|
19294
19627
|
const store = resolution ?? new ResolutionStore();
|
|
19295
19628
|
return {
|
|
@@ -19325,7 +19658,7 @@ function exportedFunctions(sourceFile, resolution) {
|
|
|
19325
19658
|
return out;
|
|
19326
19659
|
}
|
|
19327
19660
|
function exportedFunction(decl, resolution) {
|
|
19328
|
-
const writtenAgain =
|
|
19661
|
+
const writtenAgain = Node75.isVariableDeclaration(decl) && isWrittenAgain(decl);
|
|
19329
19662
|
if (!writtenAgain) {
|
|
19330
19663
|
const declared = resolveDeclarationToFunction(decl);
|
|
19331
19664
|
if (declared !== null) {
|
|
@@ -19346,7 +19679,7 @@ function valueToAskAbout(decl, writtenAgain) {
|
|
|
19346
19679
|
if (writtenAgain) {
|
|
19347
19680
|
return decl;
|
|
19348
19681
|
}
|
|
19349
|
-
const value =
|
|
19682
|
+
const value = Node75.isVariableDeclaration(decl) ? decl.getInitializer() ?? decl : decl;
|
|
19350
19683
|
return couldStillNameAFunction(value) ? value : null;
|
|
19351
19684
|
}
|
|
19352
19685
|
function resolveDeclarationToFunction(decl) {
|
|
@@ -19354,18 +19687,18 @@ function resolveDeclarationToFunction(decl) {
|
|
|
19354
19687
|
if (fn !== null) {
|
|
19355
19688
|
return fn;
|
|
19356
19689
|
}
|
|
19357
|
-
if (
|
|
19690
|
+
if (Node75.isVariableDeclaration(decl)) {
|
|
19358
19691
|
const init = decl.getInitializer();
|
|
19359
|
-
if (init !== void 0 && (
|
|
19692
|
+
if (init !== void 0 && (Node75.isArrowFunction(init) || Node75.isFunctionExpression(init))) {
|
|
19360
19693
|
return init;
|
|
19361
19694
|
}
|
|
19362
19695
|
}
|
|
19363
19696
|
return null;
|
|
19364
19697
|
}
|
|
19365
19698
|
function hasJsxReturn(func) {
|
|
19366
|
-
if (
|
|
19699
|
+
if (Node75.isArrowFunction(func)) {
|
|
19367
19700
|
const body2 = func.getBody();
|
|
19368
|
-
if (
|
|
19701
|
+
if (Node75.isExpression(body2) && isJsxOrFragment(body2)) {
|
|
19369
19702
|
return true;
|
|
19370
19703
|
}
|
|
19371
19704
|
}
|
|
@@ -19379,11 +19712,11 @@ function hasJsxReturn(func) {
|
|
|
19379
19712
|
traversal.stop();
|
|
19380
19713
|
return;
|
|
19381
19714
|
}
|
|
19382
|
-
if (node !== func && (
|
|
19715
|
+
if (node !== func && (Node75.isFunctionDeclaration(node) || Node75.isFunctionExpression(node) || Node75.isArrowFunction(node) || Node75.isMethodDeclaration(node))) {
|
|
19383
19716
|
traversal.skip();
|
|
19384
19717
|
return;
|
|
19385
19718
|
}
|
|
19386
|
-
if (
|
|
19719
|
+
if (Node75.isReturnStatement(node)) {
|
|
19387
19720
|
const expr = node.getExpression();
|
|
19388
19721
|
if (expr !== void 0 && isJsxOrFragment(expr)) {
|
|
19389
19722
|
found = true;
|
|
@@ -19394,7 +19727,7 @@ function hasJsxReturn(func) {
|
|
|
19394
19727
|
}
|
|
19395
19728
|
function isJsxOrFragment(node) {
|
|
19396
19729
|
const current2 = peelParens(node);
|
|
19397
|
-
return
|
|
19730
|
+
return Node75.isJsxElement(current2) || Node75.isJsxSelfClosingElement(current2) || Node75.isJsxFragment(current2);
|
|
19398
19731
|
}
|
|
19399
19732
|
|
|
19400
19733
|
// src/everyUnit.ts
|
|
@@ -19421,7 +19754,7 @@ function stampExitCodeFrom(summaries, project, resolution) {
|
|
|
19421
19754
|
}
|
|
19422
19755
|
|
|
19423
19756
|
// src/flagReads.ts
|
|
19424
|
-
import { Node as
|
|
19757
|
+
import { Node as Node76 } from "ts-morph";
|
|
19425
19758
|
function flagReads(func, parameterNames2, parsers, resolution, barriers = NO_BARRIERS) {
|
|
19426
19759
|
if (parsers.length === 0 || parameterNames2.length === 0 || resolution === void 0) {
|
|
19427
19760
|
return [];
|
|
@@ -19454,11 +19787,11 @@ function namedCallsIn(func, barriers) {
|
|
|
19454
19787
|
traversal.skip();
|
|
19455
19788
|
return;
|
|
19456
19789
|
}
|
|
19457
|
-
if (!
|
|
19790
|
+
if (!Node76.isCallExpression(node)) {
|
|
19458
19791
|
return;
|
|
19459
19792
|
}
|
|
19460
19793
|
const callee = node.getExpression();
|
|
19461
|
-
if (
|
|
19794
|
+
if (Node76.isIdentifier(callee) || Node76.isPropertyAccessExpression(callee)) {
|
|
19462
19795
|
calls.push(node);
|
|
19463
19796
|
}
|
|
19464
19797
|
});
|
|
@@ -19682,7 +20015,7 @@ function createReferenceIndex(sourceFiles) {
|
|
|
19682
20015
|
}
|
|
19683
20016
|
|
|
19684
20017
|
// src/resolve/clientBasePath.ts
|
|
19685
|
-
import { Node as
|
|
20018
|
+
import { Node as Node77 } from "ts-morph";
|
|
19686
20019
|
import { hasNameHole as hasNameHole2 } from "@suss/behavioral-ir";
|
|
19687
20020
|
function clientBasePath(call, match, resolution, site) {
|
|
19688
20021
|
if (match?.type !== "clientCall" || match.basePathOption === void 0) {
|
|
@@ -19724,13 +20057,14 @@ function clientConstructionConfig(call, match, resolution) {
|
|
|
19724
20057
|
}
|
|
19725
20058
|
function receiverOf2(call) {
|
|
19726
20059
|
const callee = call.getExpression();
|
|
19727
|
-
if (
|
|
20060
|
+
if (Node77.isPropertyAccessExpression(callee)) {
|
|
19728
20061
|
return callee.getExpression();
|
|
19729
20062
|
}
|
|
19730
|
-
return
|
|
20063
|
+
return Node77.isIdentifier(callee) ? callee : null;
|
|
19731
20064
|
}
|
|
19732
20065
|
|
|
19733
20066
|
// src/resolve/closureRecords.ts
|
|
20067
|
+
import { plainKeyOf } from "@suss/resolution";
|
|
19734
20068
|
function fromScanRecord(unit) {
|
|
19735
20069
|
const files = [unit.file, ...unit.deps];
|
|
19736
20070
|
const placeOf = ([file, start, end]) => {
|
|
@@ -19798,7 +20132,7 @@ function closureUnitRecords(scans, stillValid, references) {
|
|
|
19798
20132
|
continue;
|
|
19799
20133
|
}
|
|
19800
20134
|
const file = fileOfOffsetKey(key);
|
|
19801
|
-
if (file === null) {
|
|
20135
|
+
if (file === null || reachesASubclass(key, scan.findings)) {
|
|
19802
20136
|
continue;
|
|
19803
20137
|
}
|
|
19804
20138
|
const deps = depsOf(file, scan.findings, scan.read, references);
|
|
@@ -19814,6 +20148,9 @@ function closureUnitRecords(scans, stillValid, references) {
|
|
|
19814
20148
|
}
|
|
19815
20149
|
return units;
|
|
19816
20150
|
}
|
|
20151
|
+
function reachesASubclass(key, findings) {
|
|
20152
|
+
return key !== plainKeyOf(key) || findings.calls.some((call) => call.key !== plainKeyOf(call.key));
|
|
20153
|
+
}
|
|
19817
20154
|
function filesNamedBy(findings) {
|
|
19818
20155
|
const files = [];
|
|
19819
20156
|
for (const call of findings.calls) {
|
|
@@ -19902,15 +20239,108 @@ function placeOfKey(key) {
|
|
|
19902
20239
|
}
|
|
19903
20240
|
|
|
19904
20241
|
// src/resolve/reachableClosure.ts
|
|
19905
|
-
import { Node as
|
|
20242
|
+
import { Node as Node79 } from "ts-morph";
|
|
19906
20243
|
import {
|
|
19907
20244
|
functionCallBinding,
|
|
19908
20245
|
normalizeCalleeText as normalizeCalleeText2,
|
|
19909
20246
|
placePossibleCalls,
|
|
20247
|
+
sameDeclarations,
|
|
19910
20248
|
TargetPlacements
|
|
19911
20249
|
} from "@suss/behavioral-ir";
|
|
19912
20250
|
import { Database as Database3, evaluate as evaluate3, lit as lit2, rule as rule2, variable } from "@suss/datalog";
|
|
19913
20251
|
import { assembleSummary as assembleSummary2 } from "@suss/extractor";
|
|
20252
|
+
import { keptVariants, plainKeyOf as plainKeyOf2, variantKey } from "@suss/resolution";
|
|
20253
|
+
|
|
20254
|
+
// src/resolve/receiverClass.ts
|
|
20255
|
+
import { Node as Node78 } from "ts-morph";
|
|
20256
|
+
function candidateOnReceiver(callee, checked, scan) {
|
|
20257
|
+
if (!Node78.isPropertyAccessExpression(callee)) {
|
|
20258
|
+
return null;
|
|
20259
|
+
}
|
|
20260
|
+
const receiver = callee.getExpression();
|
|
20261
|
+
const name = callee.getName();
|
|
20262
|
+
const { scanning } = scan;
|
|
20263
|
+
const own = scanning === void 0 ? null : ownForm(receiver, scanning, scan.resolution, 0);
|
|
20264
|
+
const selfClass = scan.runsOn ?? (scanning === void 0 ? null : classOf(scanning));
|
|
20265
|
+
if (own !== null && selfClass !== null) {
|
|
20266
|
+
return memberOn(selfClass, name, own);
|
|
20267
|
+
}
|
|
20268
|
+
if (checked === null || !Node78.isClassDeclaration(checked.func.getParent())) {
|
|
20269
|
+
return null;
|
|
20270
|
+
}
|
|
20271
|
+
const sentTo = classSentTo(receiver);
|
|
20272
|
+
return sentTo === null ? null : runningOn(checked, sentTo);
|
|
20273
|
+
}
|
|
20274
|
+
function runningOn(candidate, cls) {
|
|
20275
|
+
const owner = candidate.func.getParent();
|
|
20276
|
+
if (!Node78.isClassDeclaration(owner) || owner === cls.node) {
|
|
20277
|
+
return candidate;
|
|
20278
|
+
}
|
|
20279
|
+
return { ...candidate, receiverClass: cls };
|
|
20280
|
+
}
|
|
20281
|
+
function subclassPlace(cls) {
|
|
20282
|
+
return { name: cls.name, file: cls.file };
|
|
20283
|
+
}
|
|
20284
|
+
function ownThis(node, scanning) {
|
|
20285
|
+
const owner = node.getFirstAncestor(
|
|
20286
|
+
(at) => Node78.isFunctionDeclaration(at) || Node78.isFunctionExpression(at) || Node78.isMethodDeclaration(at) || Node78.isConstructorDeclaration(at)
|
|
20287
|
+
);
|
|
20288
|
+
return owner === scanning;
|
|
20289
|
+
}
|
|
20290
|
+
function ownForm(value, scanning, resolution, depth) {
|
|
20291
|
+
const written = peelSyntax(value);
|
|
20292
|
+
if (Node78.isThisExpression(written)) {
|
|
20293
|
+
if (!ownThis(written, scanning) || !Node78.isMethodDeclaration(scanning)) {
|
|
20294
|
+
return null;
|
|
20295
|
+
}
|
|
20296
|
+
return scanning.isStatic() ? "class" : "instance";
|
|
20297
|
+
}
|
|
20298
|
+
if (Node78.isNewExpression(written)) {
|
|
20299
|
+
return ownForm(written.getExpression(), scanning, resolution, depth) === "class" ? "instance" : null;
|
|
20300
|
+
}
|
|
20301
|
+
if (!Node78.isIdentifier(written) || depth > 0) {
|
|
20302
|
+
return null;
|
|
20303
|
+
}
|
|
20304
|
+
const behind = writtenNodeOf(written, resolution);
|
|
20305
|
+
return behind === null || behind === written ? null : ownForm(behind, scanning, resolution, depth + 1);
|
|
20306
|
+
}
|
|
20307
|
+
function classOf(scanning) {
|
|
20308
|
+
const owner = scanning.getParent();
|
|
20309
|
+
return Node78.isClassDeclaration(owner) ? subclassOf(owner) : null;
|
|
20310
|
+
}
|
|
20311
|
+
function subclassOf(node) {
|
|
20312
|
+
const name = node.getName();
|
|
20313
|
+
return name === void 0 ? null : { node, name, file: node.getSourceFile().getFilePath() };
|
|
20314
|
+
}
|
|
20315
|
+
function classSentTo(receiver) {
|
|
20316
|
+
const written = peelSyntax(receiver);
|
|
20317
|
+
const named2 = classDeclarationOf(declarationsBehind(written.getSymbol()));
|
|
20318
|
+
if (named2 !== null) {
|
|
20319
|
+
return subclassOf(named2);
|
|
20320
|
+
}
|
|
20321
|
+
const typed = classDeclarationOf(
|
|
20322
|
+
written.getType().getSymbol()?.getDeclarations() ?? []
|
|
20323
|
+
);
|
|
20324
|
+
return typed === null ? null : subclassOf(typed);
|
|
20325
|
+
}
|
|
20326
|
+
function classDeclarationOf(declarations) {
|
|
20327
|
+
const classes = declarations.filter((one) => Node78.isClassDeclaration(one));
|
|
20328
|
+
const [only] = classes;
|
|
20329
|
+
return classes.length === 1 && only !== void 0 ? only : null;
|
|
20330
|
+
}
|
|
20331
|
+
function memberOn(cls, name, form) {
|
|
20332
|
+
const member = typeOf(cls, form).getProperty(name);
|
|
20333
|
+
const found = member === void 0 ? null : functionAmong(member.getDeclarations(), name);
|
|
20334
|
+
return found === null ? null : runningOn(found, cls);
|
|
20335
|
+
}
|
|
20336
|
+
function typeOf(cls, form) {
|
|
20337
|
+
if (form === "instance") {
|
|
20338
|
+
return cls.node.getType();
|
|
20339
|
+
}
|
|
20340
|
+
return cls.node.getProject().getTypeChecker().getTypeOfSymbolAtLocation(cls.node.getSymbolOrThrow(), cls.node);
|
|
20341
|
+
}
|
|
20342
|
+
|
|
20343
|
+
// src/resolve/reachableClosure.ts
|
|
19914
20344
|
var GENERIC_TERMINALS = [
|
|
19915
20345
|
{ kind: "return", match: { type: "returnStatement" }, extraction: {} },
|
|
19916
20346
|
{ kind: "throw", match: { type: "throwExpression" }, extraction: {} },
|
|
@@ -19945,19 +20375,35 @@ function targetOf(node) {
|
|
|
19945
20375
|
span: { start: node.getStart(), end: node.getEnd() }
|
|
19946
20376
|
};
|
|
19947
20377
|
}
|
|
20378
|
+
function placeOfCandidate(candidate) {
|
|
20379
|
+
const place = targetOf(candidate.func);
|
|
20380
|
+
return candidate.receiverClass === void 0 ? place : { ...place, receiverClass: subclassPlace(candidate.receiverClass) };
|
|
20381
|
+
}
|
|
20382
|
+
function candidateKey(candidate) {
|
|
20383
|
+
const key = nodeKey(candidate.func);
|
|
20384
|
+
return candidate.receiverClass === void 0 ? key : variantKey(key, subclassPlace(candidate.receiverClass));
|
|
20385
|
+
}
|
|
19948
20386
|
function resolveCallee(call, calleeName, scan) {
|
|
19949
|
-
if (!
|
|
20387
|
+
if (!Node79.isCallExpression(call)) {
|
|
19950
20388
|
return null;
|
|
19951
20389
|
}
|
|
19952
20390
|
const callee = call.getExpression();
|
|
19953
20391
|
const symbol = callee.getSymbol();
|
|
19954
20392
|
const declarations = declarationsBehind(symbol);
|
|
19955
20393
|
const direct = functionAmong(declarations, calleeName);
|
|
20394
|
+
const onReceiver = candidateOnReceiver(callee, direct, {
|
|
20395
|
+
scanning: scan.scanning,
|
|
20396
|
+
runsOn: scan.receiverClass,
|
|
20397
|
+
resolution: scan.resolution
|
|
20398
|
+
});
|
|
20399
|
+
if (onReceiver !== null) {
|
|
20400
|
+
return { kind: "followed", candidate: onReceiver };
|
|
20401
|
+
}
|
|
19956
20402
|
if (direct !== null) {
|
|
19957
20403
|
return { kind: "followed", candidate: direct };
|
|
19958
20404
|
}
|
|
19959
20405
|
const resolveSources = scan.resolveCallableSources;
|
|
19960
|
-
if (resolveSources !== void 0 &&
|
|
20406
|
+
if (resolveSources !== void 0 && Node79.isPropertyAccessExpression(callee) && declarations.some(isDeclaredShape)) {
|
|
19961
20407
|
if (scan.sourcesAsked !== void 0) {
|
|
19962
20408
|
scan.sourcesAsked.asked = true;
|
|
19963
20409
|
}
|
|
@@ -19986,7 +20432,7 @@ function resolveCallee(call, calleeName, scan) {
|
|
|
19986
20432
|
);
|
|
19987
20433
|
}
|
|
19988
20434
|
function stopFor(callee, declarations, stop, scan, parameterIndex) {
|
|
19989
|
-
const asks = scan.resolution !== void 0 && (stop.reason === "unsettledValue" ||
|
|
20435
|
+
const asks = scan.resolution !== void 0 && (stop.reason === "unsettledValue" || Node79.isElementAccessExpression(callee));
|
|
19990
20436
|
return {
|
|
19991
20437
|
kind: "stopped",
|
|
19992
20438
|
stop,
|
|
@@ -19996,7 +20442,7 @@ function stopFor(callee, declarations, stop, scan, parameterIndex) {
|
|
|
19996
20442
|
};
|
|
19997
20443
|
}
|
|
19998
20444
|
function storeKeyOf(callee) {
|
|
19999
|
-
const declarations =
|
|
20445
|
+
const declarations = Node79.isIdentifier(callee) ? declarationsBehind(callee.getSymbol()) : [];
|
|
20000
20446
|
return declarations.length === 1 ? declarations[0] : callee;
|
|
20001
20447
|
}
|
|
20002
20448
|
function settleThroughStore(outcomes, scan) {
|
|
@@ -20055,7 +20501,7 @@ function declarationToReport(declarations, calleeName, scan) {
|
|
|
20055
20501
|
}
|
|
20056
20502
|
function declaredAtOf(outcome) {
|
|
20057
20503
|
if (outcome.kind === "followed") {
|
|
20058
|
-
return
|
|
20504
|
+
return placeOfCandidate(outcome.candidate);
|
|
20059
20505
|
}
|
|
20060
20506
|
if (outcome.kind === "possible") {
|
|
20061
20507
|
return null;
|
|
@@ -20081,7 +20527,7 @@ function mayDispatch(one) {
|
|
|
20081
20527
|
if (one.outcome.askStore !== void 0) {
|
|
20082
20528
|
return true;
|
|
20083
20529
|
}
|
|
20084
|
-
return
|
|
20530
|
+
return Node79.isCallExpression(one.node) && Node79.isCallExpression(one.node.getExpression());
|
|
20085
20531
|
}
|
|
20086
20532
|
function dispatchOutcome(answer, stopped) {
|
|
20087
20533
|
const { callee } = stopped.stop;
|
|
@@ -20104,18 +20550,18 @@ function dispatchOutcome(answer, stopped) {
|
|
|
20104
20550
|
}
|
|
20105
20551
|
function entryNameOf(func) {
|
|
20106
20552
|
const property = func.getParent();
|
|
20107
|
-
const key = property === void 0 || !
|
|
20553
|
+
const key = property === void 0 || !Node79.isPropertyAssignment(property) ? null : propertyNameOf(property);
|
|
20108
20554
|
if (property === void 0 || key === null) {
|
|
20109
20555
|
return null;
|
|
20110
20556
|
}
|
|
20111
20557
|
const holder = climbSyntax(property.getParentOrThrow()).getParent();
|
|
20112
|
-
return holder !== void 0 &&
|
|
20558
|
+
return holder !== void 0 && Node79.isVariableDeclaration(holder) ? `${holder.getName()}.${key}` : key;
|
|
20113
20559
|
}
|
|
20114
20560
|
function placeCallee(placements, calleeText, call, outcome) {
|
|
20115
20561
|
if (outcome.kind === "possible") {
|
|
20116
20562
|
placements.placePossible(
|
|
20117
20563
|
calleeText,
|
|
20118
|
-
outcome.candidates.map(
|
|
20564
|
+
outcome.candidates.map(placeOfCandidate)
|
|
20119
20565
|
);
|
|
20120
20566
|
return;
|
|
20121
20567
|
}
|
|
@@ -20129,24 +20575,24 @@ function placeCallee(placements, calleeText, call, outcome) {
|
|
|
20129
20575
|
}
|
|
20130
20576
|
}
|
|
20131
20577
|
function isCallOnOtherValue(call) {
|
|
20132
|
-
if (!
|
|
20578
|
+
if (!Node79.isCallExpression(call)) {
|
|
20133
20579
|
return false;
|
|
20134
20580
|
}
|
|
20135
20581
|
const callee = call.getExpression();
|
|
20136
|
-
if (!
|
|
20582
|
+
if (!Node79.isPropertyAccessExpression(callee) && !Node79.isElementAccessExpression(callee)) {
|
|
20137
20583
|
return false;
|
|
20138
20584
|
}
|
|
20139
|
-
return !
|
|
20585
|
+
return !Node79.isThisExpression(callee.getExpression());
|
|
20140
20586
|
}
|
|
20141
20587
|
function passedPositionKey(target, position) {
|
|
20142
20588
|
return `${offsetKeyFor(target.file, target.span)}#${position}`;
|
|
20143
20589
|
}
|
|
20144
20590
|
function resolveJsxReference(node, scan) {
|
|
20145
|
-
if (!
|
|
20591
|
+
if (!Node79.isJsxOpeningElement(node) && !Node79.isJsxSelfClosingElement(node)) {
|
|
20146
20592
|
return null;
|
|
20147
20593
|
}
|
|
20148
20594
|
const tag = node.getTagNameNode();
|
|
20149
|
-
if (!
|
|
20595
|
+
if (!Node79.isIdentifier(tag) || !/^[A-Z]/.test(tag.getText())) {
|
|
20150
20596
|
return null;
|
|
20151
20597
|
}
|
|
20152
20598
|
const name = tag.getText();
|
|
@@ -20168,7 +20614,7 @@ function resolveJsxReference(node, scan) {
|
|
|
20168
20614
|
};
|
|
20169
20615
|
}
|
|
20170
20616
|
function collectReachable(root, scan) {
|
|
20171
|
-
const atModuleScope =
|
|
20617
|
+
const atModuleScope = Node79.isSourceFile(root);
|
|
20172
20618
|
const inFunc = atModuleScope ? { ...scan } : { ...scan, scanning: root };
|
|
20173
20619
|
const calls = [];
|
|
20174
20620
|
const stops = [];
|
|
@@ -20185,7 +20631,7 @@ function collectReachable(root, scan) {
|
|
|
20185
20631
|
}
|
|
20186
20632
|
};
|
|
20187
20633
|
const recordFollowed = (candidate) => {
|
|
20188
|
-
const key =
|
|
20634
|
+
const key = candidateKey(candidate);
|
|
20189
20635
|
if (seen.has(key)) {
|
|
20190
20636
|
return;
|
|
20191
20637
|
}
|
|
@@ -20207,18 +20653,18 @@ function collectReachable(root, scan) {
|
|
|
20207
20653
|
recordFollowed(outcome.candidate);
|
|
20208
20654
|
};
|
|
20209
20655
|
const recordPassedArgs = (call, calleeText, calleeOutcome) => {
|
|
20210
|
-
if (!
|
|
20656
|
+
if (!Node79.isCallExpression(call)) {
|
|
20211
20657
|
return;
|
|
20212
20658
|
}
|
|
20213
20659
|
const calleeTarget = declaredAtOf(calleeOutcome);
|
|
20214
20660
|
call.getArguments().forEach((arg, position) => {
|
|
20215
|
-
if (
|
|
20661
|
+
if (Node79.isArrowFunction(arg) || Node79.isFunctionExpression(arg)) {
|
|
20216
20662
|
if (calleeTarget !== null) {
|
|
20217
20663
|
passedPositions.add(passedPositionKey(calleeTarget, position));
|
|
20218
20664
|
}
|
|
20219
20665
|
return;
|
|
20220
20666
|
}
|
|
20221
|
-
if (!
|
|
20667
|
+
if (!Node79.isIdentifier(arg)) {
|
|
20222
20668
|
return;
|
|
20223
20669
|
}
|
|
20224
20670
|
const resolved = functionTargetOf(arg);
|
|
@@ -20243,7 +20689,7 @@ function collectReachable(root, scan) {
|
|
|
20243
20689
|
found.push({ node, outcome: jsx.outcome });
|
|
20244
20690
|
return;
|
|
20245
20691
|
}
|
|
20246
|
-
if (!
|
|
20692
|
+
if (!Node79.isCallExpression(node)) {
|
|
20247
20693
|
return;
|
|
20248
20694
|
}
|
|
20249
20695
|
const calleeText = normalizeCalleeText2(node.getExpression().getText());
|
|
@@ -20347,7 +20793,7 @@ function recognizerOnlyRoots(packsByFile) {
|
|
|
20347
20793
|
}
|
|
20348
20794
|
for (const declaration of variableStatement.getDeclarations()) {
|
|
20349
20795
|
const init = declaration.getInitializer();
|
|
20350
|
-
if (init !== void 0 && (
|
|
20796
|
+
if (init !== void 0 && (Node79.isArrowFunction(init) || Node79.isFunctionExpression(init)) && hasBody(init)) {
|
|
20351
20797
|
roots.push({ func: init, name: declaration.getName() });
|
|
20352
20798
|
}
|
|
20353
20799
|
}
|
|
@@ -20377,6 +20823,8 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
20377
20823
|
const passedPositions = /* @__PURE__ */ new Set();
|
|
20378
20824
|
const summariesByKey = /* @__PURE__ */ new Map();
|
|
20379
20825
|
const reachedFrom = /* @__PURE__ */ new Map();
|
|
20826
|
+
const receiverByKey = /* @__PURE__ */ new Map();
|
|
20827
|
+
const callsByKey = /* @__PURE__ */ new Map();
|
|
20380
20828
|
const finding = {
|
|
20381
20829
|
project,
|
|
20382
20830
|
lookup,
|
|
@@ -20385,7 +20833,8 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
20385
20833
|
storeAnswers: /* @__PURE__ */ new Map(),
|
|
20386
20834
|
funcByKey,
|
|
20387
20835
|
moduleByKey,
|
|
20388
|
-
reachedFrom
|
|
20836
|
+
reachedFrom,
|
|
20837
|
+
receiverByKey
|
|
20389
20838
|
};
|
|
20390
20839
|
for (const seed of seeds) {
|
|
20391
20840
|
const func = lookup.functionAt(seed.location);
|
|
@@ -20443,25 +20892,53 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
20443
20892
|
for (const position of found.passedPositions) {
|
|
20444
20893
|
passedPositions.add(position);
|
|
20445
20894
|
}
|
|
20446
|
-
const callerFile = fileOfOffsetKey(key);
|
|
20447
|
-
|
|
20895
|
+
const callerFile = fileOfOffsetKey(plainKeyOf2(key));
|
|
20896
|
+
const calledHere = found.calls.flatMap(
|
|
20897
|
+
(call) => call.receiverClass === void 0 ? [call] : [
|
|
20898
|
+
{ ...call, key: plainKeyOf2(call.key), receiverClass: void 0 },
|
|
20899
|
+
call
|
|
20900
|
+
]
|
|
20901
|
+
);
|
|
20902
|
+
const called = [];
|
|
20903
|
+
for (const call of calledHere) {
|
|
20448
20904
|
if (!nameByKey.has(call.key)) {
|
|
20449
20905
|
nameByKey.set(call.key, call.name);
|
|
20450
20906
|
}
|
|
20451
20907
|
if (call.func !== void 0 && !funcByKey.has(call.key)) {
|
|
20452
20908
|
funcByKey.set(call.key, call.func);
|
|
20453
20909
|
}
|
|
20910
|
+
if (call.receiverClass !== void 0) {
|
|
20911
|
+
receiverByKey.set(call.key, call.receiverClass);
|
|
20912
|
+
}
|
|
20454
20913
|
if (callerFile !== null && !reachedFrom.has(call.key)) {
|
|
20455
20914
|
reachedFrom.set(call.key, callerFile);
|
|
20456
20915
|
}
|
|
20457
20916
|
db.add("calls", [key, call.key]);
|
|
20917
|
+
called.push(call.key);
|
|
20458
20918
|
}
|
|
20919
|
+
callsByKey.set(key, called);
|
|
20459
20920
|
}
|
|
20460
20921
|
}
|
|
20922
|
+
const placementsOf = (key) => ({
|
|
20923
|
+
targets: targetsByKey.get(key),
|
|
20924
|
+
argTargets: argTargetsByKey.get(key),
|
|
20925
|
+
possibleTargets: possibleTargetsByKey.get(key)
|
|
20926
|
+
});
|
|
20927
|
+
const onSubclass = keptVariants(
|
|
20928
|
+
[...receiverByKey.keys()].map((key) => ({
|
|
20929
|
+
key,
|
|
20930
|
+
differs: !sameDeclarations(
|
|
20931
|
+
placementsOf(key),
|
|
20932
|
+
placementsOf(plainKeyOf2(key))
|
|
20933
|
+
),
|
|
20934
|
+
calls: callsByKey.get(key) ?? []
|
|
20935
|
+
}))
|
|
20936
|
+
);
|
|
20461
20937
|
const reached = [];
|
|
20462
20938
|
for (const [keyAtom] of db.facts("reachable")) {
|
|
20463
20939
|
const key = String(keyAtom);
|
|
20464
|
-
|
|
20940
|
+
const receiverClass = receiverByKey.get(key);
|
|
20941
|
+
if (known.has(key) || seedKeys.has(key) || receiverClass !== void 0 && !onSubclass.has(key)) {
|
|
20465
20942
|
continue;
|
|
20466
20943
|
}
|
|
20467
20944
|
const name = nameByKey.get(key);
|
|
@@ -20472,7 +20949,7 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
20472
20949
|
if (projectFileSet !== void 0) {
|
|
20473
20950
|
lazyAddSourceFile(project, projectFileSet, file);
|
|
20474
20951
|
}
|
|
20475
|
-
const func = funcByKey.get(key) ?? functionAtKey(key, lookup);
|
|
20952
|
+
const func = funcByKey.get(key) ?? functionAtKey(plainKeyOf2(key), lookup);
|
|
20476
20953
|
if (func === void 0) {
|
|
20477
20954
|
continue;
|
|
20478
20955
|
}
|
|
@@ -20482,6 +20959,10 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
20482
20959
|
facts,
|
|
20483
20960
|
() => extractReachableSummary(candidate, options, recognizers)
|
|
20484
20961
|
);
|
|
20962
|
+
if (receiverClass !== void 0) {
|
|
20963
|
+
summary.receiverClass = subclassPlace(receiverClass);
|
|
20964
|
+
summary.identity.exportPath = [receiverClass.name, name];
|
|
20965
|
+
}
|
|
20485
20966
|
facts?.unitKeyBySummary.set(summary, key);
|
|
20486
20967
|
rememberSummary(summariesByKey, key, summary);
|
|
20487
20968
|
reached.push(summary);
|
|
@@ -20538,14 +21019,15 @@ function knownUnits(summaries, lookup, facts) {
|
|
|
20538
21019
|
}
|
|
20539
21020
|
function findingsFor(key, ctx) {
|
|
20540
21021
|
const cameFrom = ctx.reachedFrom.get(key);
|
|
20541
|
-
const
|
|
21022
|
+
const receiverClass = ctx.receiverByKey.get(key);
|
|
21023
|
+
const stored = receiverClass === void 0 ? ctx.facts?.previousScans?.get(key) : void 0;
|
|
20542
21024
|
const recorded = stored !== void 0 && recordValidFrom(stored.data, cameFrom) ? fromScanRecord(stored) : null;
|
|
20543
21025
|
if (stored !== void 0 && recorded !== null) {
|
|
20544
21026
|
ctx.facts?.scans?.set(key, { kind: "reused", unit: stored });
|
|
20545
21027
|
noteFilesRead(key, ctx.facts, stored.deps);
|
|
20546
21028
|
return recorded;
|
|
20547
21029
|
}
|
|
20548
|
-
const root = ctx.funcByKey.get(key) ?? ctx.moduleByKey.get(key) ?? functionAtKey(key, ctx.lookup);
|
|
21030
|
+
const root = ctx.funcByKey.get(key) ?? ctx.moduleByKey.get(key) ?? functionAtKey(plainKeyOf2(key), ctx.lookup);
|
|
20549
21031
|
if (root === void 0) {
|
|
20550
21032
|
return null;
|
|
20551
21033
|
}
|
|
@@ -20556,7 +21038,8 @@ function findingsFor(key, ctx) {
|
|
|
20556
21038
|
...resolution === void 0 ? {} : { resolution, storeAnswers: ctx.storeAnswers },
|
|
20557
21039
|
...resolveCallableSources === void 0 ? {} : { resolveCallableSources, sourcesAsked },
|
|
20558
21040
|
...sourceDeclarationsBehind2 === void 0 ? {} : { sourceDeclarationsBehind: sourceDeclarationsBehind2 },
|
|
20559
|
-
...reachedFrom === void 0 ? {} : { reachedFrom }
|
|
21041
|
+
...reachedFrom === void 0 ? {} : { reachedFrom },
|
|
21042
|
+
...receiverClass === void 0 ? {} : { receiverClass }
|
|
20560
21043
|
};
|
|
20561
21044
|
const scanned = scanOrReport(key, ctx.facts, root, scan);
|
|
20562
21045
|
if (scanned === null) {
|
|
@@ -20576,7 +21059,7 @@ function scanOrReport(key, facts, root, scan) {
|
|
|
20576
21059
|
return scanWithRecording(key, facts, () => collectReachable(root, scan));
|
|
20577
21060
|
} catch (error) {
|
|
20578
21061
|
const message = error instanceof Error ? error.message : String(error);
|
|
20579
|
-
const where =
|
|
21062
|
+
const where = Node79.isSourceFile(root) ? root.getFilePath() : `${root.getSourceFile().getFilePath()}:${root.getStartLineNumber()}`;
|
|
20580
21063
|
process.stderr.write(
|
|
20581
21064
|
`[suss] could not scan the function at ${where} for the calls it makes, so nothing it calls is followed from it: ${message}
|
|
20582
21065
|
`
|
|
@@ -20700,7 +21183,7 @@ function recordParameterGaps(parameterCallsByKey, summariesByKey, passedPosition
|
|
|
20700
21183
|
}
|
|
20701
21184
|
for (const [key, parameterCalls] of parameterCallsByKey) {
|
|
20702
21185
|
const unbound = parameterCalls.filter(
|
|
20703
|
-
({ parameterIndex }) => !passedPositions.has(`${key}#${parameterIndex}`)
|
|
21186
|
+
({ parameterIndex }) => !passedPositions.has(`${plainKeyOf2(key)}#${parameterIndex}`)
|
|
20704
21187
|
);
|
|
20705
21188
|
if (unbound.length === 0) {
|
|
20706
21189
|
continue;
|
|
@@ -20717,7 +21200,7 @@ function recordParameterGaps(parameterCallsByKey, summariesByKey, passedPosition
|
|
|
20717
21200
|
|
|
20718
21201
|
// src/resolve/redirectDelivery.ts
|
|
20719
21202
|
import { redirectDeliveryWhenSet } from "@suss/extractor";
|
|
20720
|
-
import { force as
|
|
21203
|
+
import { force as force7, scalarOf } from "@suss/values";
|
|
20721
21204
|
function settingOf(object, name, resolution, site) {
|
|
20722
21205
|
if (object === void 0) {
|
|
20723
21206
|
return { kind: "absent" };
|
|
@@ -20733,7 +21216,7 @@ function settingOf(object, name, resolution, site) {
|
|
|
20733
21216
|
if (field.presence !== "one") {
|
|
20734
21217
|
return { kind: "unknown" };
|
|
20735
21218
|
}
|
|
20736
|
-
const settled3 = scalarOf(
|
|
21219
|
+
const settled3 = scalarOf(force7(field.value));
|
|
20737
21220
|
return settled3 === null ? { kind: "unknown" } : { kind: "settled", value: settled3 };
|
|
20738
21221
|
}
|
|
20739
21222
|
function redirectDeliveryAtCall(callSite, pattern, pack, resolution) {
|
|
@@ -20758,7 +21241,7 @@ function redirectDeliveryAtCall(callSite, pattern, pack, resolution) {
|
|
|
20758
21241
|
}
|
|
20759
21242
|
|
|
20760
21243
|
// src/resolve/rethrowEnrichment.ts
|
|
20761
|
-
import { Node as
|
|
21244
|
+
import { Node as Node80 } from "ts-morph";
|
|
20762
21245
|
import { Database as Database4, evaluate as evaluate4, lit as lit3, rule as rule3, variable as variable2 } from "@suss/datalog";
|
|
20763
21246
|
var RETHROW_RULES = [
|
|
20764
21247
|
rule3(
|
|
@@ -20895,7 +21378,7 @@ function findBareRethrow(func, location) {
|
|
|
20895
21378
|
traversal.stop();
|
|
20896
21379
|
return;
|
|
20897
21380
|
}
|
|
20898
|
-
if (!
|
|
21381
|
+
if (!Node80.isThrowStatement(node)) {
|
|
20899
21382
|
return;
|
|
20900
21383
|
}
|
|
20901
21384
|
if (startLineOf(node) !== location.start) {
|
|
@@ -20905,7 +21388,7 @@ function findBareRethrow(func, location) {
|
|
|
20905
21388
|
return;
|
|
20906
21389
|
}
|
|
20907
21390
|
const thrown = node.getExpression();
|
|
20908
|
-
if (thrown !== void 0 &&
|
|
21391
|
+
if (thrown !== void 0 && Node80.isIdentifier(thrown)) {
|
|
20909
21392
|
found = node;
|
|
20910
21393
|
}
|
|
20911
21394
|
});
|
|
@@ -20915,13 +21398,13 @@ function enclosingTry(throwStmt) {
|
|
|
20915
21398
|
let current2 = throwStmt.getParent();
|
|
20916
21399
|
let sawCatchClause = false;
|
|
20917
21400
|
while (current2 !== void 0) {
|
|
20918
|
-
if (
|
|
21401
|
+
if (Node80.isCatchClause(current2)) {
|
|
20919
21402
|
sawCatchClause = true;
|
|
20920
21403
|
}
|
|
20921
|
-
if (
|
|
21404
|
+
if (Node80.isTryStatement(current2)) {
|
|
20922
21405
|
return sawCatchClause ? current2 : null;
|
|
20923
21406
|
}
|
|
20924
|
-
if (
|
|
21407
|
+
if (Node80.isFunctionDeclaration(current2) || Node80.isFunctionExpression(current2) || Node80.isArrowFunction(current2) || Node80.isMethodDeclaration(current2)) {
|
|
20925
21408
|
return null;
|
|
20926
21409
|
}
|
|
20927
21410
|
current2 = current2.getParent();
|
|
@@ -20929,14 +21412,14 @@ function enclosingTry(throwStmt) {
|
|
|
20929
21412
|
return null;
|
|
20930
21413
|
}
|
|
20931
21414
|
function collectTryBodyCallees(tryStmt, index, keyFor) {
|
|
20932
|
-
if (!
|
|
21415
|
+
if (!Node80.isTryStatement(tryStmt)) {
|
|
20933
21416
|
return [];
|
|
20934
21417
|
}
|
|
20935
21418
|
const tryBlock = tryStmt.getTryBlock();
|
|
20936
21419
|
const callees = [];
|
|
20937
21420
|
const seen = /* @__PURE__ */ new Set();
|
|
20938
21421
|
tryBlock.forEachDescendant((node) => {
|
|
20939
|
-
if (!
|
|
21422
|
+
if (!Node80.isCallExpression(node)) {
|
|
20940
21423
|
return;
|
|
20941
21424
|
}
|
|
20942
21425
|
const calleeSummary = resolveCalleeSummary(node, index);
|
|
@@ -20953,7 +21436,7 @@ function collectTryBodyCallees(tryStmt, index, keyFor) {
|
|
|
20953
21436
|
return callees;
|
|
20954
21437
|
}
|
|
20955
21438
|
function resolveCalleeSummary(call, index) {
|
|
20956
|
-
if (!
|
|
21439
|
+
if (!Node80.isCallExpression(call)) {
|
|
20957
21440
|
return null;
|
|
20958
21441
|
}
|
|
20959
21442
|
const callee = call.getExpression();
|
|
@@ -20986,7 +21469,7 @@ function resolveCalleeSummary(call, index) {
|
|
|
20986
21469
|
|
|
20987
21470
|
// src/subUnitContext.ts
|
|
20988
21471
|
import {
|
|
20989
|
-
Node as
|
|
21472
|
+
Node as Node81
|
|
20990
21473
|
} from "ts-morph";
|
|
20991
21474
|
function createTsSubUnitContext() {
|
|
20992
21475
|
return {
|
|
@@ -21014,18 +21497,18 @@ function findJsxAttributes(parent) {
|
|
|
21014
21497
|
if (skip(node, traversal)) {
|
|
21015
21498
|
return;
|
|
21016
21499
|
}
|
|
21017
|
-
if (!
|
|
21500
|
+
if (!Node81.isJsxOpeningElement(node) && !Node81.isJsxSelfClosingElement(node)) {
|
|
21018
21501
|
return;
|
|
21019
21502
|
}
|
|
21020
21503
|
const tag = node.getTagNameNode().getText();
|
|
21021
21504
|
for (const attr of node.getAttributes()) {
|
|
21022
|
-
if (!
|
|
21505
|
+
if (!Node81.isJsxAttribute(attr)) {
|
|
21023
21506
|
continue;
|
|
21024
21507
|
}
|
|
21025
21508
|
const initializer = attr.getInitializer();
|
|
21026
21509
|
let valueExpression = null;
|
|
21027
21510
|
if (initializer !== void 0) {
|
|
21028
|
-
if (
|
|
21511
|
+
if (Node81.isJsxExpression(initializer)) {
|
|
21029
21512
|
const inner = initializer.getExpression();
|
|
21030
21513
|
valueExpression = inner ?? null;
|
|
21031
21514
|
} else {
|
|
@@ -21048,11 +21531,11 @@ function findCallExpressionsByName(parent, name) {
|
|
|
21048
21531
|
if (skip(node, traversal)) {
|
|
21049
21532
|
return;
|
|
21050
21533
|
}
|
|
21051
|
-
if (!
|
|
21534
|
+
if (!Node81.isCallExpression(node)) {
|
|
21052
21535
|
return;
|
|
21053
21536
|
}
|
|
21054
21537
|
const callee = node.getExpression();
|
|
21055
|
-
if (
|
|
21538
|
+
if (Node81.isIdentifier(callee) && callee.getText() === name) {
|
|
21056
21539
|
out.push(node);
|
|
21057
21540
|
}
|
|
21058
21541
|
});
|
|
@@ -21063,10 +21546,10 @@ function resolveAttributeValueFunction(attr, parent) {
|
|
|
21063
21546
|
if (expr === null) {
|
|
21064
21547
|
return null;
|
|
21065
21548
|
}
|
|
21066
|
-
if (
|
|
21549
|
+
if (Node81.isArrowFunction(expr) || Node81.isFunctionExpression(expr)) {
|
|
21067
21550
|
return { func: expr, localName: null };
|
|
21068
21551
|
}
|
|
21069
|
-
if (
|
|
21552
|
+
if (Node81.isIdentifier(expr)) {
|
|
21070
21553
|
const symbol = expr.getSymbol();
|
|
21071
21554
|
if (symbol === void 0) {
|
|
21072
21555
|
return null;
|
|
@@ -21099,7 +21582,7 @@ function getCallArgumentFunction(call, position) {
|
|
|
21099
21582
|
if (arg === void 0) {
|
|
21100
21583
|
return null;
|
|
21101
21584
|
}
|
|
21102
|
-
if (
|
|
21585
|
+
if (Node81.isArrowFunction(arg) || Node81.isFunctionExpression(arg)) {
|
|
21103
21586
|
return arg;
|
|
21104
21587
|
}
|
|
21105
21588
|
return null;
|
|
@@ -21111,7 +21594,7 @@ function readArrayLiteralText(node) {
|
|
|
21111
21594
|
if (node === null) {
|
|
21112
21595
|
return null;
|
|
21113
21596
|
}
|
|
21114
|
-
if (
|
|
21597
|
+
if (Node81.isArrayLiteralExpression(node)) {
|
|
21115
21598
|
return node.getElements().map((e) => e.getText());
|
|
21116
21599
|
}
|
|
21117
21600
|
return [node.getText()];
|
|
@@ -21163,7 +21646,12 @@ var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
|
21163
21646
|
".turbo",
|
|
21164
21647
|
".next",
|
|
21165
21648
|
".suss",
|
|
21166
|
-
"vendor"
|
|
21649
|
+
"vendor",
|
|
21650
|
+
"__pycache__",
|
|
21651
|
+
".venv",
|
|
21652
|
+
"venv",
|
|
21653
|
+
".tox",
|
|
21654
|
+
"tmp"
|
|
21167
21655
|
]);
|
|
21168
21656
|
function findSourceFiles(rootDir, depth = 0) {
|
|
21169
21657
|
if (depth > 12) {
|
|
@@ -21522,13 +22010,13 @@ var raise = (msg) => {
|
|
|
21522
22010
|
throw new Error(msg);
|
|
21523
22011
|
};
|
|
21524
22012
|
function bindingPatternNames(nameNode) {
|
|
21525
|
-
if (
|
|
22013
|
+
if (Node82.isObjectBindingPattern(nameNode)) {
|
|
21526
22014
|
return nameNode.getElements().map((e) => e.getName());
|
|
21527
22015
|
}
|
|
21528
|
-
if (
|
|
22016
|
+
if (Node82.isArrayBindingPattern(nameNode)) {
|
|
21529
22017
|
const names = [];
|
|
21530
22018
|
for (const element of nameNode.getElements()) {
|
|
21531
|
-
if (
|
|
22019
|
+
if (Node82.isOmittedExpression(element)) {
|
|
21532
22020
|
continue;
|
|
21533
22021
|
}
|
|
21534
22022
|
names.push(element.getName());
|
|
@@ -21558,7 +22046,7 @@ function objectParamInputs(param, position, mapping) {
|
|
|
21558
22046
|
}
|
|
21559
22047
|
function componentPropsParameters(param, mapping) {
|
|
21560
22048
|
const nameNode = param.getNameNode();
|
|
21561
|
-
if (!
|
|
22049
|
+
if (!Node82.isObjectBindingPattern(nameNode)) {
|
|
21562
22050
|
const type = param.getType();
|
|
21563
22051
|
return [
|
|
21564
22052
|
{
|
|
@@ -21585,15 +22073,15 @@ function componentPropsParameters(param, mapping) {
|
|
|
21585
22073
|
}
|
|
21586
22074
|
function namesBoundUnder(element, field) {
|
|
21587
22075
|
const inner = element.getNameNode();
|
|
21588
|
-
if (
|
|
22076
|
+
if (Node82.isObjectBindingPattern(inner)) {
|
|
21589
22077
|
return inner.getElements().flatMap((nested) => {
|
|
21590
22078
|
const property = nested.getDotDotDotToken() === void 0 ? bindingRole(nested, nested.getName()) : void 0;
|
|
21591
22079
|
return namesBoundUnder(nested, field ?? property);
|
|
21592
22080
|
});
|
|
21593
22081
|
}
|
|
21594
|
-
if (
|
|
22082
|
+
if (Node82.isArrayBindingPattern(inner)) {
|
|
21595
22083
|
return inner.getElements().flatMap(
|
|
21596
|
-
(nested) =>
|
|
22084
|
+
(nested) => Node82.isBindingElement(nested) ? namesBoundUnder(nested, field) : []
|
|
21597
22085
|
);
|
|
21598
22086
|
}
|
|
21599
22087
|
return [{ binding: element, field }];
|
|
@@ -21606,7 +22094,7 @@ function bindingRole(element, name) {
|
|
|
21606
22094
|
if (property === void 0) {
|
|
21607
22095
|
return name;
|
|
21608
22096
|
}
|
|
21609
|
-
if (
|
|
22097
|
+
if (Node82.isStringLiteral(property)) {
|
|
21610
22098
|
return property.getLiteralValue();
|
|
21611
22099
|
}
|
|
21612
22100
|
return property.getText();
|
|
@@ -21638,7 +22126,7 @@ function extractParameters(func, inputMapping) {
|
|
|
21638
22126
|
const param = params[i];
|
|
21639
22127
|
const nameNode = param.getNameNode();
|
|
21640
22128
|
const boundNames = bindingPatternNames(nameNode);
|
|
21641
|
-
if (
|
|
22129
|
+
if (Node82.isObjectBindingPattern(nameNode)) {
|
|
21642
22130
|
for (const element of nameNode.getElements()) {
|
|
21643
22131
|
result.push({
|
|
21644
22132
|
name: element.getName(),
|
|
@@ -21705,7 +22193,7 @@ function extractDependencyCalls(func, barriers = NO_BARRIERS) {
|
|
|
21705
22193
|
traversal.skip();
|
|
21706
22194
|
return;
|
|
21707
22195
|
}
|
|
21708
|
-
if (!
|
|
22196
|
+
if (!Node82.isVariableDeclaration(node)) {
|
|
21709
22197
|
return;
|
|
21710
22198
|
}
|
|
21711
22199
|
const init = node.getInitializer();
|
|
@@ -21714,19 +22202,19 @@ function extractDependencyCalls(func, barriers = NO_BARRIERS) {
|
|
|
21714
22202
|
}
|
|
21715
22203
|
let isAsync = false;
|
|
21716
22204
|
let callExpr = init;
|
|
21717
|
-
if (
|
|
22205
|
+
if (Node82.isAwaitExpression(init)) {
|
|
21718
22206
|
isAsync = true;
|
|
21719
22207
|
callExpr = init.getExpression();
|
|
21720
22208
|
}
|
|
21721
|
-
if (!
|
|
22209
|
+
if (!Node82.isCallExpression(callExpr)) {
|
|
21722
22210
|
return;
|
|
21723
22211
|
}
|
|
21724
22212
|
const calleeName = callExpr.getExpression().getText();
|
|
21725
22213
|
const nameNode = node.getNameNode();
|
|
21726
|
-
const assignedTo =
|
|
22214
|
+
const assignedTo = Node82.isIdentifier(nameNode) ? nameNode.getText() : null;
|
|
21727
22215
|
const declList = node.getParent();
|
|
21728
22216
|
const varStmt = declList?.getParent();
|
|
21729
|
-
const locationNode = varStmt !== void 0 &&
|
|
22217
|
+
const locationNode = varStmt !== void 0 && Node82.isVariableStatement(varStmt) ? varStmt : node;
|
|
21730
22218
|
results.push({
|
|
21731
22219
|
name: calleeName,
|
|
21732
22220
|
assignedTo,
|
|
@@ -22467,6 +22955,7 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
22467
22955
|
if (unit.operationInfo.unresolved !== void 0) {
|
|
22468
22956
|
raw.graphqlUnresolvedDocument = unit.operationInfo.unresolved;
|
|
22469
22957
|
}
|
|
22958
|
+
stampClientChosenAtCall(raw, unit, pack, resolution);
|
|
22470
22959
|
for (const v2 of unit.operationInfo.variables) {
|
|
22471
22960
|
raw.parameters.push({
|
|
22472
22961
|
name: v2.name,
|
|
@@ -22507,17 +22996,18 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
22507
22996
|
if (binding.semantics.name === "rest" && binding.semantics.method !== null) {
|
|
22508
22997
|
const defaultBranch = raw.branches.find((b) => b.isDefault);
|
|
22509
22998
|
if (defaultBranch !== void 0) {
|
|
22510
|
-
const
|
|
22999
|
+
const call = unit.callSite.callExpression;
|
|
22511
23000
|
defaultBranch.extraEffects = [
|
|
22512
23001
|
...defaultBranch.extraEffects ?? [],
|
|
22513
23002
|
{
|
|
22514
23003
|
type: "interaction",
|
|
22515
23004
|
binding,
|
|
22516
|
-
callee:
|
|
23005
|
+
callee: call.getExpression().getText(),
|
|
22517
23006
|
interaction: {
|
|
22518
23007
|
class: "service-call",
|
|
22519
23008
|
method: binding.semantics.method
|
|
22520
|
-
}
|
|
23009
|
+
},
|
|
23010
|
+
location: lineRangeOf(call)
|
|
22521
23011
|
}
|
|
22522
23012
|
];
|
|
22523
23013
|
}
|
|
@@ -22641,6 +23131,23 @@ function stampRequestSpelling(raw, pack) {
|
|
|
22641
23131
|
}
|
|
22642
23132
|
raw.requestSpelling = pack.requestSpelling;
|
|
22643
23133
|
}
|
|
23134
|
+
function stampClientChosenAtCall(raw, unit, pack, resolution) {
|
|
23135
|
+
const specs = pack.graphqlClients ?? [];
|
|
23136
|
+
if (unit.graphqlCall === void 0 || specs.length === 0) {
|
|
23137
|
+
return;
|
|
23138
|
+
}
|
|
23139
|
+
const chosen = clientChosenAt(unit.graphqlCall, specs, resolution);
|
|
23140
|
+
if (chosen?.kind === "settled") {
|
|
23141
|
+
raw.graphqlClient = { ...chosen.client, chosenAtCall: true };
|
|
23142
|
+
return;
|
|
23143
|
+
}
|
|
23144
|
+
if (chosen?.kind === "unresolved") {
|
|
23145
|
+
raw.graphqlUnresolvedClient = {
|
|
23146
|
+
reference: chosen.reference,
|
|
23147
|
+
reason: chosen.reason
|
|
23148
|
+
};
|
|
23149
|
+
}
|
|
23150
|
+
}
|
|
22644
23151
|
function unfollowedStopsOf(unit, wrappers) {
|
|
22645
23152
|
const stops = [
|
|
22646
23153
|
...unit.unfollowed === void 0 ? [] : [unit.unfollowed],
|
|
@@ -22658,7 +23165,7 @@ function emitLibraryEnvReadMarkers(summaries, project, frameworks) {
|
|
|
22658
23165
|
if (importer === void 0) {
|
|
22659
23166
|
continue;
|
|
22660
23167
|
}
|
|
22661
|
-
summaries.push(libraryEnvReadMarker(pack, declared, importer));
|
|
23168
|
+
summaries.push(libraryEnvReadMarker(pack.name, declared, importer));
|
|
22662
23169
|
}
|
|
22663
23170
|
}
|
|
22664
23171
|
}
|
|
@@ -22706,31 +23213,6 @@ function schemaDocumentSummary(label, schemaSdl) {
|
|
|
22706
23213
|
)
|
|
22707
23214
|
};
|
|
22708
23215
|
}
|
|
22709
|
-
function libraryEnvReadMarker(pack, declared, importer) {
|
|
22710
|
-
return {
|
|
22711
|
-
kind: "library",
|
|
22712
|
-
location: { file: importer, range: { start: 0, end: 0 }, exportName: null },
|
|
22713
|
-
identity: {
|
|
22714
|
-
name: `${declared.module} env reads`,
|
|
22715
|
-
exportPath: null,
|
|
22716
|
-
boundaryBinding: functionCallBinding2({
|
|
22717
|
-
transport: "in-process",
|
|
22718
|
-
recognition: pack.name
|
|
22719
|
-
})
|
|
22720
|
-
},
|
|
22721
|
-
inputs: [],
|
|
22722
|
-
transitions: [],
|
|
22723
|
-
gaps: [],
|
|
22724
|
-
confidence: { source: "declared", level: "high" },
|
|
22725
|
-
metadata: {
|
|
22726
|
-
libraryEnvReads: {
|
|
22727
|
-
module: declared.module,
|
|
22728
|
-
...declared.prefixes !== void 0 ? { prefixes: declared.prefixes } : {},
|
|
22729
|
-
...declared.names !== void 0 ? { names: declared.names } : {}
|
|
22730
|
-
}
|
|
22731
|
-
}
|
|
22732
|
-
};
|
|
22733
|
-
}
|
|
22734
23216
|
function internalImportsOf(project, file) {
|
|
22735
23217
|
const sourceFile = project.getSourceFile(file);
|
|
22736
23218
|
if (sourceFile === void 0) {
|
|
@@ -22843,7 +23325,7 @@ function fieldValue2(record2, name) {
|
|
|
22843
23325
|
return void 0;
|
|
22844
23326
|
}
|
|
22845
23327
|
const field = record2.fields.get(name);
|
|
22846
|
-
return field === void 0 ? void 0 :
|
|
23328
|
+
return field === void 0 ? void 0 : force8(field.value);
|
|
22847
23329
|
}
|
|
22848
23330
|
function sinkUrl(sink, bindings, resolution) {
|
|
22849
23331
|
const p = sink.extraction.path;
|
|
@@ -22903,17 +23385,17 @@ function synthesizeCallerSummaries(wrapper, resolution, options) {
|
|
|
22903
23385
|
return out;
|
|
22904
23386
|
}
|
|
22905
23387
|
function callerName(func) {
|
|
22906
|
-
if (
|
|
23388
|
+
if (Node82.isFunctionDeclaration(func) || Node82.isMethodDeclaration(func)) {
|
|
22907
23389
|
return func.getName() ?? "anonymous";
|
|
22908
23390
|
}
|
|
22909
23391
|
const parent = func.getParent();
|
|
22910
|
-
if (parent !== void 0 &&
|
|
23392
|
+
if (parent !== void 0 && Node82.isVariableDeclaration(parent)) {
|
|
22911
23393
|
const nameNode = parent.getNameNode();
|
|
22912
|
-
if (
|
|
23394
|
+
if (Node82.isIdentifier(nameNode)) {
|
|
22913
23395
|
return nameNode.getText();
|
|
22914
23396
|
}
|
|
22915
23397
|
}
|
|
22916
|
-
if (parent !== void 0 &&
|
|
23398
|
+
if (parent !== void 0 && Node82.isPropertyAssignment(parent)) {
|
|
22917
23399
|
return parent.getName();
|
|
22918
23400
|
}
|
|
22919
23401
|
return "anonymous";
|
|
@@ -23953,7 +24435,7 @@ function buildSubUnitSummary(subUnit, parent, parentFunc, recognizers, everyUnit
|
|
|
23953
24435
|
|
|
23954
24436
|
// src/facts/why.ts
|
|
23955
24437
|
import path15 from "path";
|
|
23956
|
-
import { Node as
|
|
24438
|
+
import { Node as Node83, Project as Project3, SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
23957
24439
|
import { explainResolutionProof, renderExplanation } from "@suss/resolution";
|
|
23958
24440
|
var TypeScriptWhySession = class {
|
|
23959
24441
|
project;
|
|
@@ -23970,14 +24452,14 @@ var TypeScriptWhySession = class {
|
|
|
23970
24452
|
* `text`, or null. Spelled from the person's side: the name as
|
|
23971
24453
|
* written, not a node id.
|
|
23972
24454
|
*/
|
|
23973
|
-
findExpression(file, line,
|
|
24455
|
+
findExpression(file, line, text3) {
|
|
23974
24456
|
const sourceFile = this.sourceFileAt(file);
|
|
23975
24457
|
if (sourceFile === null) {
|
|
23976
24458
|
return null;
|
|
23977
24459
|
}
|
|
23978
24460
|
let found = null;
|
|
23979
24461
|
sourceFile.forEachDescendant((node) => {
|
|
23980
|
-
if (
|
|
24462
|
+
if (Node83.isExpression(node) && node.getStartLineNumber() === line && node.getText() === text3 && (found === null || node.getWidth() <= found.getWidth())) {
|
|
23981
24463
|
found = node;
|
|
23982
24464
|
}
|
|
23983
24465
|
});
|
|
@@ -24066,26 +24548,26 @@ var TypeScriptWhySession = class {
|
|
|
24066
24548
|
}
|
|
24067
24549
|
};
|
|
24068
24550
|
function displayNameOf(node) {
|
|
24069
|
-
if (
|
|
24551
|
+
if (Node83.isIdentifier(node) || Node83.isPropertyAccessExpression(node)) {
|
|
24070
24552
|
return node.getText();
|
|
24071
24553
|
}
|
|
24072
|
-
if (
|
|
24554
|
+
if (Node83.isCallExpression(node) || Node83.isNewExpression(node)) {
|
|
24073
24555
|
return `${node.getExpression()?.getText() ?? "call"}(...)`;
|
|
24074
24556
|
}
|
|
24075
|
-
if (
|
|
24557
|
+
if (Node83.isFunctionDeclaration(node) || Node83.isClassDeclaration(node) || Node83.isMethodDeclaration(node) || Node83.isVariableDeclaration(node)) {
|
|
24076
24558
|
const name = node.getName();
|
|
24077
24559
|
if (name !== void 0) {
|
|
24078
24560
|
return name;
|
|
24079
24561
|
}
|
|
24080
24562
|
}
|
|
24081
|
-
if (
|
|
24563
|
+
if (Node83.isArrowFunction(node) || Node83.isFunctionExpression(node)) {
|
|
24082
24564
|
const parent = node.getParent();
|
|
24083
|
-
if (parent !== void 0 &&
|
|
24565
|
+
if (parent !== void 0 && Node83.isVariableDeclaration(parent)) {
|
|
24084
24566
|
return parent.getName();
|
|
24085
24567
|
}
|
|
24086
24568
|
}
|
|
24087
|
-
const
|
|
24088
|
-
return
|
|
24569
|
+
const text3 = node.getText().split("\n")[0].trim();
|
|
24570
|
+
return text3.length > 40 ? `${text3.slice(0, 40)}...` : text3;
|
|
24089
24571
|
}
|
|
24090
24572
|
|
|
24091
24573
|
// src/stubEvidence.ts
|
|
@@ -24131,9 +24613,9 @@ function stubEvidence(options) {
|
|
|
24131
24613
|
}
|
|
24132
24614
|
|
|
24133
24615
|
// src/walk/defaulted.ts
|
|
24134
|
-
import { Node as
|
|
24616
|
+
import { Node as Node84, SyntaxKind as SyntaxKind16 } from "ts-morph";
|
|
24135
24617
|
function isDefaultedAt(node) {
|
|
24136
|
-
if (!
|
|
24618
|
+
if (!Node84.isBindingElement(node)) {
|
|
24137
24619
|
const read2 = climbSyntax(node);
|
|
24138
24620
|
const inner = peelSyntax(read2);
|
|
24139
24621
|
const subject = {
|
|
@@ -24150,7 +24632,7 @@ function isDefaultedAt(node) {
|
|
|
24150
24632
|
}
|
|
24151
24633
|
function isSubject(subject, expression) {
|
|
24152
24634
|
if (subject.kind === "local") {
|
|
24153
|
-
return
|
|
24635
|
+
return Node84.isIdentifier(expression) && refersTo(expression, subject.local);
|
|
24154
24636
|
}
|
|
24155
24637
|
return expression.getText() === subject.text;
|
|
24156
24638
|
}
|
|
@@ -24164,7 +24646,7 @@ function hasFallbackOperand(node) {
|
|
|
24164
24646
|
let child = climbSyntax(node);
|
|
24165
24647
|
let parent = child.getParent();
|
|
24166
24648
|
while (parent !== void 0) {
|
|
24167
|
-
if (!
|
|
24649
|
+
if (!Node84.isBinaryExpression(parent)) {
|
|
24168
24650
|
return false;
|
|
24169
24651
|
}
|
|
24170
24652
|
const operator = parent.getOperatorToken().getText();
|
|
@@ -24185,8 +24667,8 @@ function isPresenceTest(node, subject) {
|
|
|
24185
24667
|
let throughLogical = false;
|
|
24186
24668
|
let parent = child.getParent();
|
|
24187
24669
|
while (parent !== void 0) {
|
|
24188
|
-
if (!
|
|
24189
|
-
if (negatedOperand(parent) === null && !
|
|
24670
|
+
if (!Node84.isBinaryExpression(parent)) {
|
|
24671
|
+
if (negatedOperand(parent) === null && !Node84.isTypeOfExpression(parent)) {
|
|
24190
24672
|
return isTestedAt(parent, child, subject, { tested, throughLogical });
|
|
24191
24673
|
}
|
|
24192
24674
|
tested = true;
|
|
@@ -24212,22 +24694,22 @@ function logicalStep(parent, child) {
|
|
|
24212
24694
|
return null;
|
|
24213
24695
|
}
|
|
24214
24696
|
const operand2 = peelSyntax(child);
|
|
24215
|
-
return
|
|
24697
|
+
return Node84.isTypeOfExpression(operand2) || missingSideOf(parent) === operand2 ? "tested" : null;
|
|
24216
24698
|
}
|
|
24217
24699
|
function isTestedAt(parent, child, subject, seen) {
|
|
24218
24700
|
if (conditionOf2(parent) === child) {
|
|
24219
24701
|
return !absentPathThrows(parent, subject);
|
|
24220
24702
|
}
|
|
24221
|
-
if (seen.throughLogical &&
|
|
24703
|
+
if (seen.throughLogical && Node84.isExpressionStatement(parent)) {
|
|
24222
24704
|
return !continuationThrows(parent);
|
|
24223
24705
|
}
|
|
24224
24706
|
return seen.tested;
|
|
24225
24707
|
}
|
|
24226
24708
|
function conditionOf2(node) {
|
|
24227
|
-
if (
|
|
24709
|
+
if (Node84.isIfStatement(node) || Node84.isWhileStatement(node) || Node84.isDoStatement(node)) {
|
|
24228
24710
|
return node.getExpression();
|
|
24229
24711
|
}
|
|
24230
|
-
if (
|
|
24712
|
+
if (Node84.isConditionalExpression(node) || Node84.isForStatement(node)) {
|
|
24231
24713
|
return node.getCondition();
|
|
24232
24714
|
}
|
|
24233
24715
|
return void 0;
|
|
@@ -24245,24 +24727,24 @@ function isPresentAt(node, subject) {
|
|
|
24245
24727
|
return false;
|
|
24246
24728
|
}
|
|
24247
24729
|
function isBranchWherePresent(parent, child, subject) {
|
|
24248
|
-
if (
|
|
24730
|
+
if (Node84.isIfStatement(parent)) {
|
|
24249
24731
|
return isBranchTaken(parent.getExpression(), child, subject, {
|
|
24250
24732
|
whenTrue: parent.getThenStatement(),
|
|
24251
24733
|
whenFalse: parent.getElseStatement()
|
|
24252
24734
|
});
|
|
24253
24735
|
}
|
|
24254
|
-
if (
|
|
24736
|
+
if (Node84.isConditionalExpression(parent)) {
|
|
24255
24737
|
return isBranchTaken(parent.getCondition(), child, subject, {
|
|
24256
24738
|
whenTrue: parent.getWhenTrue(),
|
|
24257
24739
|
whenFalse: parent.getWhenFalse()
|
|
24258
24740
|
});
|
|
24259
24741
|
}
|
|
24260
|
-
if (
|
|
24742
|
+
if (Node84.isWhileStatement(parent)) {
|
|
24261
24743
|
return isBranchTaken(parent.getExpression(), child, subject, {
|
|
24262
24744
|
whenTrue: parent.getStatement()
|
|
24263
24745
|
});
|
|
24264
24746
|
}
|
|
24265
|
-
if (!
|
|
24747
|
+
if (!Node84.isBinaryExpression(parent) || parent.getRight() !== child) {
|
|
24266
24748
|
return false;
|
|
24267
24749
|
}
|
|
24268
24750
|
const operator = parent.getOperatorToken().getText();
|
|
@@ -24275,16 +24757,16 @@ function isBranchTaken(test, child, subject, branches) {
|
|
|
24275
24757
|
return child === branches.whenFalse && isPresentWhen(test, false, subject);
|
|
24276
24758
|
}
|
|
24277
24759
|
function followsExitWhenAbsent(parent, child, subject) {
|
|
24278
|
-
if (!(
|
|
24760
|
+
if (!(Node84.isBlock(parent) || Node84.isSourceFile(parent))) {
|
|
24279
24761
|
return false;
|
|
24280
24762
|
}
|
|
24281
24763
|
const statements = parent.getStatements();
|
|
24282
24764
|
return statements.slice(0, statements.indexOf(child)).some(
|
|
24283
|
-
(statement) =>
|
|
24765
|
+
(statement) => Node84.isIfStatement(statement) && exitOf(statement.getThenStatement()) === "leave" && isPresentWhen(statement.getExpression(), false, subject)
|
|
24284
24766
|
);
|
|
24285
24767
|
}
|
|
24286
24768
|
function absentPathThrows(owner, subject) {
|
|
24287
|
-
if (!
|
|
24769
|
+
if (!Node84.isIfStatement(owner)) {
|
|
24288
24770
|
return continuationThrows(owner);
|
|
24289
24771
|
}
|
|
24290
24772
|
const test = owner.getExpression();
|
|
@@ -24298,7 +24780,7 @@ function absentPathThrows(owner, subject) {
|
|
|
24298
24780
|
return arms.some((arm) => armThrows(arm, owner, subject));
|
|
24299
24781
|
}
|
|
24300
24782
|
function armThrows(arm, owner, subject) {
|
|
24301
|
-
if (arm !== void 0 &&
|
|
24783
|
+
if (arm !== void 0 && Node84.isIfStatement(arm)) {
|
|
24302
24784
|
return absentPathThrows(arm, subject);
|
|
24303
24785
|
}
|
|
24304
24786
|
const exit = arm === void 0 ? null : exitOf(arm);
|
|
@@ -24308,7 +24790,7 @@ function continuationThrows(from) {
|
|
|
24308
24790
|
let current2 = from;
|
|
24309
24791
|
let parent = current2.getParent();
|
|
24310
24792
|
while (parent !== void 0) {
|
|
24311
|
-
if (
|
|
24793
|
+
if (Node84.isBlock(parent) || Node84.isSourceFile(parent)) {
|
|
24312
24794
|
const statements = parent.getStatements();
|
|
24313
24795
|
const after = statements.slice(
|
|
24314
24796
|
statements.indexOf(current2) + 1
|
|
@@ -24327,7 +24809,7 @@ function continuationThrows(from) {
|
|
|
24327
24809
|
return false;
|
|
24328
24810
|
}
|
|
24329
24811
|
function endsThePath(node) {
|
|
24330
|
-
return isFunctionRoot(node) ||
|
|
24812
|
+
return isFunctionRoot(node) || Node84.isIterationStatement(node) || Node84.isReturnStatement(node);
|
|
24331
24813
|
}
|
|
24332
24814
|
function firstExit(statements) {
|
|
24333
24815
|
for (const statement of statements) {
|
|
@@ -24339,13 +24821,13 @@ function firstExit(statements) {
|
|
|
24339
24821
|
return null;
|
|
24340
24822
|
}
|
|
24341
24823
|
function exitOf(statement) {
|
|
24342
|
-
if (
|
|
24824
|
+
if (Node84.isThrowStatement(statement)) {
|
|
24343
24825
|
return "throw";
|
|
24344
24826
|
}
|
|
24345
|
-
if (
|
|
24827
|
+
if (Node84.isReturnStatement(statement) || Node84.isContinueStatement(statement) || Node84.isBreakStatement(statement)) {
|
|
24346
24828
|
return "leave";
|
|
24347
24829
|
}
|
|
24348
|
-
return
|
|
24830
|
+
return Node84.isBlock(statement) ? firstExit(statement.getStatements()) : null;
|
|
24349
24831
|
}
|
|
24350
24832
|
function isPresentWhen(test, outcome, subject) {
|
|
24351
24833
|
const expression = peelSyntax(test);
|
|
@@ -24356,7 +24838,7 @@ function isPresentWhen(test, outcome, subject) {
|
|
|
24356
24838
|
if (negated2 !== null) {
|
|
24357
24839
|
return isPresentWhen(negated2, !outcome, subject);
|
|
24358
24840
|
}
|
|
24359
|
-
if (!
|
|
24841
|
+
if (!Node84.isBinaryExpression(expression)) {
|
|
24360
24842
|
return false;
|
|
24361
24843
|
}
|
|
24362
24844
|
const operator = expression.getOperatorToken().getText();
|
|
@@ -24387,24 +24869,24 @@ function missingSideOf(comparison) {
|
|
|
24387
24869
|
return comparedValue(left, right, loose) ?? comparedValue(right, left, loose);
|
|
24388
24870
|
}
|
|
24389
24871
|
function comparedValue(operand2, other, loose) {
|
|
24390
|
-
if (
|
|
24391
|
-
return
|
|
24872
|
+
if (Node84.isTypeOfExpression(operand2)) {
|
|
24873
|
+
return Node84.isStringLiteral(other) && other.getLiteralValue() === "undefined" ? peelSyntax(operand2.getExpression()) : null;
|
|
24392
24874
|
}
|
|
24393
|
-
const missing =
|
|
24875
|
+
const missing = Node84.isIdentifier(other) && other.getText() === "undefined" || loose && Node84.isNullLiteral(other);
|
|
24394
24876
|
return missing ? operand2 : null;
|
|
24395
24877
|
}
|
|
24396
24878
|
function negatedOperand(node) {
|
|
24397
|
-
if (
|
|
24879
|
+
if (Node84.isPrefixUnaryExpression(node) && node.getOperatorToken() === SyntaxKind16.ExclamationToken) {
|
|
24398
24880
|
return node.getOperand();
|
|
24399
24881
|
}
|
|
24400
24882
|
return null;
|
|
24401
24883
|
}
|
|
24402
24884
|
function isKeyOfRead(read2, key, container) {
|
|
24403
|
-
return (
|
|
24885
|
+
return (Node84.isPropertyAccessExpression(read2) || Node84.isElementAccessExpression(read2)) && read2.getExpression().getText() === container.getText() && isKeyReadBy(read2, key);
|
|
24404
24886
|
}
|
|
24405
24887
|
function isKeyReadBy(read2, key) {
|
|
24406
|
-
if (
|
|
24407
|
-
return
|
|
24888
|
+
if (Node84.isPropertyAccessExpression(read2)) {
|
|
24889
|
+
return Node84.isStringLiteral(key) && key.getLiteralValue() === read2.getName();
|
|
24408
24890
|
}
|
|
24409
24891
|
return read2.getArgumentExpression()?.getText() === key.getText();
|
|
24410
24892
|
}
|
|
@@ -24418,19 +24900,19 @@ function localNamedBy(node) {
|
|
|
24418
24900
|
}
|
|
24419
24901
|
const name = declaration.getNameNode();
|
|
24420
24902
|
const scope = findEnclosingFunction(declaration);
|
|
24421
|
-
if (!
|
|
24903
|
+
if (!Node84.isIdentifier(name) || scope === null) {
|
|
24422
24904
|
return null;
|
|
24423
24905
|
}
|
|
24424
24906
|
const symbol = symbolBehind(name);
|
|
24425
24907
|
return symbol === void 0 ? null : { name, symbol, scope };
|
|
24426
24908
|
}
|
|
24427
24909
|
function declarationInitializedBy(node) {
|
|
24428
|
-
if (
|
|
24910
|
+
if (Node84.isBindingElement(node)) {
|
|
24429
24911
|
return node;
|
|
24430
24912
|
}
|
|
24431
24913
|
const read2 = climbSyntax(node);
|
|
24432
24914
|
const parent = read2.getParent();
|
|
24433
|
-
if (parent !== void 0 &&
|
|
24915
|
+
if (parent !== void 0 && Node84.isVariableDeclaration(parent) && parent.getInitializer() === read2) {
|
|
24434
24916
|
return parent;
|
|
24435
24917
|
}
|
|
24436
24918
|
return null;
|
|
@@ -24445,6 +24927,7 @@ export {
|
|
|
24445
24927
|
GENERIC_TERMINALS,
|
|
24446
24928
|
NO_BARRIERS,
|
|
24447
24929
|
ResolutionStore,
|
|
24930
|
+
SKIP_DIRECTORIES,
|
|
24448
24931
|
SOURCE_SUFFIXES,
|
|
24449
24932
|
TSCONFIG_NAMES,
|
|
24450
24933
|
TypeScriptWhySession,
|
|
@@ -24464,6 +24947,7 @@ export {
|
|
|
24464
24947
|
createTypeScriptAdapter,
|
|
24465
24948
|
declarationsBehind,
|
|
24466
24949
|
discoverUnits,
|
|
24950
|
+
dottedPathOf,
|
|
24467
24951
|
exportedDeclarationsOf,
|
|
24468
24952
|
extractCodeStructure,
|
|
24469
24953
|
extractRawBranches,
|