@suss/adapter-typescript 0.9.0 → 0.11.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/README.md +36 -0
- package/dist/index.cjs +1735 -364
- package/dist/index.d.cts +198 -15
- package/dist/index.d.ts +198 -15
- package/dist/index.js +1726 -351
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -11,7 +11,11 @@ import {
|
|
|
11
11
|
graphqlResolverBinding,
|
|
12
12
|
messageBusBinding,
|
|
13
13
|
packageExportBinding,
|
|
14
|
-
|
|
14
|
+
readGraphqlMetadata as readGraphqlMetadata2,
|
|
15
|
+
readSourceDocumentMetadata,
|
|
16
|
+
restBinding as restBinding2,
|
|
17
|
+
withGraphqlMetadata as withGraphqlMetadata2,
|
|
18
|
+
withSourceDocumentMetadata
|
|
15
19
|
} from "@suss/behavioral-ir";
|
|
16
20
|
import { Database as Database5 } from "@suss/datalog";
|
|
17
21
|
import {
|
|
@@ -1030,32 +1034,72 @@ function collectFallthroughCaseLabels(caseClause) {
|
|
|
1030
1034
|
}
|
|
1031
1035
|
|
|
1032
1036
|
// src/paths/pathConditions.ts
|
|
1033
|
-
import { Node as
|
|
1037
|
+
import { Node as Node9 } from "ts-morph";
|
|
1034
1038
|
import {
|
|
1035
1039
|
enumerateStructuredPaths,
|
|
1036
1040
|
PathBudgetExceeded,
|
|
1037
1041
|
UnmodeledFlow as UnmodeledFlow2
|
|
1038
1042
|
} from "@suss/extractor";
|
|
1039
1043
|
|
|
1044
|
+
// src/walk/descent.ts
|
|
1045
|
+
import { Node as Node7 } from "ts-morph";
|
|
1046
|
+
var NO_BARRIERS = /* @__PURE__ */ new Set();
|
|
1047
|
+
function isDescentStop(node, func, barriers = NO_BARRIERS) {
|
|
1048
|
+
if (node === func) {
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
if (Node7.isFunctionDeclaration(node) || Node7.isMethodDeclaration(node)) {
|
|
1052
|
+
return true;
|
|
1053
|
+
}
|
|
1054
|
+
if (Node7.isArrowFunction(node) || Node7.isFunctionExpression(node)) {
|
|
1055
|
+
return barriers.has(node);
|
|
1056
|
+
}
|
|
1057
|
+
return false;
|
|
1058
|
+
}
|
|
1059
|
+
function isInlineCallback(node, func, barriers = NO_BARRIERS) {
|
|
1060
|
+
if (node === func) {
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
if (!(Node7.isArrowFunction(node) || Node7.isFunctionExpression(node))) {
|
|
1064
|
+
return false;
|
|
1065
|
+
}
|
|
1066
|
+
return !barriers.has(node);
|
|
1067
|
+
}
|
|
1068
|
+
function isModuleScopeStop(node) {
|
|
1069
|
+
return Node7.isFunctionDeclaration(node) || Node7.isMethodDeclaration(node) || Node7.isArrowFunction(node) || Node7.isFunctionExpression(node) || Node7.isClassDeclaration(node) || Node7.isClassExpression(node);
|
|
1070
|
+
}
|
|
1071
|
+
function crossesNestedFunctionScope(node, func) {
|
|
1072
|
+
let current2 = node;
|
|
1073
|
+
while (current2 !== void 0 && current2 !== func) {
|
|
1074
|
+
if (startsItsOwnScope(current2)) {
|
|
1075
|
+
return true;
|
|
1076
|
+
}
|
|
1077
|
+
current2 = current2.getParent();
|
|
1078
|
+
}
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
function startsItsOwnScope(node) {
|
|
1082
|
+
return Node7.isArrowFunction(node) || Node7.isFunctionExpression(node) || Node7.isFunctionDeclaration(node) || Node7.isMethodDeclaration(node) || Node7.isGetAccessorDeclaration(node) || Node7.isSetAccessorDeclaration(node) || Node7.isConstructorDeclaration(node);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1040
1085
|
// src/paths/lowering.ts
|
|
1041
1086
|
import {
|
|
1042
|
-
Node as
|
|
1087
|
+
Node as Node8
|
|
1043
1088
|
} from "ts-morph";
|
|
1044
1089
|
import {
|
|
1045
1090
|
UnmodeledFlow
|
|
1046
1091
|
} from "@suss/extractor";
|
|
1047
|
-
var isFunctionBoundary = (node) => Node7.isFunctionDeclaration(node) || Node7.isFunctionExpression(node) || Node7.isArrowFunction(node) || Node7.isMethodDeclaration(node);
|
|
1048
1092
|
function exitKindOf(stmt) {
|
|
1049
1093
|
let sawReturn = false;
|
|
1050
1094
|
let sawThrow = false;
|
|
1051
1095
|
const visit = (node) => {
|
|
1052
|
-
if (node !== stmt &&
|
|
1096
|
+
if (node !== stmt && startsItsOwnScope(node)) {
|
|
1053
1097
|
return;
|
|
1054
1098
|
}
|
|
1055
|
-
if (
|
|
1099
|
+
if (Node8.isReturnStatement(node)) {
|
|
1056
1100
|
sawReturn = true;
|
|
1057
1101
|
}
|
|
1058
|
-
if (
|
|
1102
|
+
if (Node8.isThrowStatement(node)) {
|
|
1059
1103
|
sawThrow = true;
|
|
1060
1104
|
}
|
|
1061
1105
|
for (const child of node.getChildren()) {
|
|
@@ -1072,14 +1116,14 @@ var statementsOf = (stmt) => {
|
|
|
1072
1116
|
if (stmt === void 0) {
|
|
1073
1117
|
return [];
|
|
1074
1118
|
}
|
|
1075
|
-
if (
|
|
1119
|
+
if (Node8.isBlock(stmt)) {
|
|
1076
1120
|
return stmt.getStatements();
|
|
1077
1121
|
}
|
|
1078
1122
|
return [stmt];
|
|
1079
1123
|
};
|
|
1080
|
-
var isLoop = (stmt) =>
|
|
1124
|
+
var isLoop = (stmt) => Node8.isForOfStatement(stmt) || Node8.isForInStatement(stmt) || Node8.isForStatement(stmt) || Node8.isWhileStatement(stmt) || Node8.isDoStatement(stmt);
|
|
1081
1125
|
function getLoopBody(stmt) {
|
|
1082
|
-
if (
|
|
1126
|
+
if (Node8.isForOfStatement(stmt) || Node8.isForInStatement(stmt) || Node8.isForStatement(stmt) || Node8.isWhileStatement(stmt) || Node8.isDoStatement(stmt)) {
|
|
1083
1127
|
return stmt.getStatement();
|
|
1084
1128
|
}
|
|
1085
1129
|
return void 0;
|
|
@@ -1094,37 +1138,97 @@ var conditionOf = (expr) => ({
|
|
|
1094
1138
|
sourceText: expr.getText(),
|
|
1095
1139
|
expression: expr
|
|
1096
1140
|
});
|
|
1097
|
-
function lowerStatement(stmt,
|
|
1098
|
-
const structured =
|
|
1099
|
-
|
|
1141
|
+
function lowerStatement(stmt, ctx) {
|
|
1142
|
+
const structured = {
|
|
1143
|
+
...buildStructured(stmt, ctx),
|
|
1144
|
+
callbacks: lowerCallbacksIn(ownExpressionsOf(stmt), ctx)
|
|
1145
|
+
};
|
|
1146
|
+
ctx.rawToStructured.set(stmt, structured);
|
|
1100
1147
|
return structured;
|
|
1101
1148
|
}
|
|
1102
|
-
function lowerList(stmts,
|
|
1103
|
-
return spliceBlocks(stmts).map((s) => lowerStatement(s,
|
|
1149
|
+
function lowerList(stmts, ctx) {
|
|
1150
|
+
return spliceBlocks(stmts).map((s) => lowerStatement(s, ctx));
|
|
1151
|
+
}
|
|
1152
|
+
function ownExpressionsOf(stmt) {
|
|
1153
|
+
if (Node8.isIfStatement(stmt) || Node8.isSwitchStatement(stmt)) {
|
|
1154
|
+
return [stmt.getExpression()];
|
|
1155
|
+
}
|
|
1156
|
+
if (Node8.isWhileStatement(stmt) || Node8.isDoStatement(stmt)) {
|
|
1157
|
+
return [stmt.getExpression()];
|
|
1158
|
+
}
|
|
1159
|
+
if (Node8.isForOfStatement(stmt) || Node8.isForInStatement(stmt)) {
|
|
1160
|
+
return [stmt.getInitializer(), stmt.getExpression()];
|
|
1161
|
+
}
|
|
1162
|
+
if (Node8.isForStatement(stmt)) {
|
|
1163
|
+
return [
|
|
1164
|
+
stmt.getInitializer(),
|
|
1165
|
+
stmt.getCondition(),
|
|
1166
|
+
stmt.getIncrementor()
|
|
1167
|
+
].filter((n) => n !== void 0);
|
|
1168
|
+
}
|
|
1169
|
+
if (Node8.isTryStatement(stmt)) {
|
|
1170
|
+
return [];
|
|
1171
|
+
}
|
|
1172
|
+
if (Node8.isReturnStatement(stmt) || Node8.isThrowStatement(stmt)) {
|
|
1173
|
+
const value = stmt.getExpression();
|
|
1174
|
+
return value === void 0 ? [] : [value];
|
|
1175
|
+
}
|
|
1176
|
+
if (Node8.isBreakStatement(stmt) || Node8.isContinueStatement(stmt)) {
|
|
1177
|
+
return [];
|
|
1178
|
+
}
|
|
1179
|
+
return [stmt];
|
|
1180
|
+
}
|
|
1181
|
+
function lowerCallbacksIn(parts, ctx) {
|
|
1182
|
+
const bodies = [];
|
|
1183
|
+
const visit = (node, root) => {
|
|
1184
|
+
if (node !== root && isDescentStop(node, ctx.func, ctx.barriers)) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
if (node !== root && (Node8.isArrowFunction(node) || Node8.isFunctionExpression(node)) && isInlineCallback(node, ctx.func, ctx.barriers)) {
|
|
1188
|
+
const body = node.getBody();
|
|
1189
|
+
if (body !== void 0 && Node8.isBlock(body)) {
|
|
1190
|
+
bodies.push(lowerList(body.getStatements(), ctx));
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
} else if (node !== root && startsItsOwnScope(node)) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
for (const child of node.getChildren()) {
|
|
1197
|
+
visit(child, root);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
for (const part of parts) {
|
|
1201
|
+
visit(part, part);
|
|
1202
|
+
}
|
|
1203
|
+
return bodies;
|
|
1204
|
+
}
|
|
1205
|
+
function lowerExpressionBodyCallbacks(expression, func, barriers = NO_BARRIERS) {
|
|
1206
|
+
return lowerCallbacksIn([expression], {
|
|
1207
|
+
func,
|
|
1208
|
+
barriers,
|
|
1209
|
+
rawToStructured: /* @__PURE__ */ new Map()
|
|
1210
|
+
});
|
|
1104
1211
|
}
|
|
1105
1212
|
function spliceBlocks(stmts) {
|
|
1106
1213
|
return stmts.flatMap(
|
|
1107
|
-
(s) =>
|
|
1214
|
+
(s) => Node8.isBlock(s) ? spliceBlocks(s.getStatements()) : [s]
|
|
1108
1215
|
);
|
|
1109
1216
|
}
|
|
1110
|
-
function buildStructured(stmt,
|
|
1111
|
-
if (
|
|
1217
|
+
function buildStructured(stmt, ctx) {
|
|
1218
|
+
if (Node8.isIfStatement(stmt)) {
|
|
1112
1219
|
const elseBranch = stmt.getElseStatement();
|
|
1113
1220
|
return {
|
|
1114
1221
|
kind: "if",
|
|
1115
1222
|
condition: conditionOf(stmt.getExpression()),
|
|
1116
|
-
thenBody: lowerList(
|
|
1117
|
-
|
|
1118
|
-
rawToStructured
|
|
1119
|
-
),
|
|
1120
|
-
elseBody: elseBranch === void 0 ? null : lowerList(statementsOf(elseBranch), rawToStructured),
|
|
1223
|
+
thenBody: lowerList(statementsOf(stmt.getThenStatement()), ctx),
|
|
1224
|
+
elseBody: elseBranch === void 0 ? null : lowerList(statementsOf(elseBranch), ctx),
|
|
1121
1225
|
exitKind: exitKindOf(stmt)
|
|
1122
1226
|
};
|
|
1123
1227
|
}
|
|
1124
|
-
if (
|
|
1228
|
+
if (Node8.isSwitchStatement(stmt)) {
|
|
1125
1229
|
return {
|
|
1126
1230
|
kind: "switch",
|
|
1127
|
-
groups: lowerSwitchGroups(stmt,
|
|
1231
|
+
groups: lowerSwitchGroups(stmt, ctx),
|
|
1128
1232
|
exitKind: exitKindOf(stmt)
|
|
1129
1233
|
};
|
|
1130
1234
|
}
|
|
@@ -1132,36 +1236,36 @@ function buildStructured(stmt, rawToStructured) {
|
|
|
1132
1236
|
return {
|
|
1133
1237
|
kind: "loop",
|
|
1134
1238
|
condition: { sourceText: loopHeaderText(stmt), expression: null },
|
|
1135
|
-
body: lowerList(statementsOf(getLoopBody(stmt)),
|
|
1239
|
+
body: lowerList(statementsOf(getLoopBody(stmt)), ctx),
|
|
1136
1240
|
exitKind: exitKindOf(stmt)
|
|
1137
1241
|
};
|
|
1138
1242
|
}
|
|
1139
|
-
if (
|
|
1243
|
+
if (Node8.isTryStatement(stmt)) {
|
|
1140
1244
|
const catchClause = stmt.getCatchClause();
|
|
1141
1245
|
const finallyBlock = stmt.getFinallyBlock();
|
|
1142
1246
|
return {
|
|
1143
1247
|
kind: "try",
|
|
1144
|
-
tryBody: lowerList(stmt.getTryBlock().getStatements(),
|
|
1145
|
-
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(),
|
|
1146
|
-
finallyBody: finallyBlock === void 0 ? null : lowerList(finallyBlock.getStatements(),
|
|
1248
|
+
tryBody: lowerList(stmt.getTryBlock().getStatements(), ctx),
|
|
1249
|
+
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(), ctx),
|
|
1250
|
+
finallyBody: finallyBlock === void 0 ? null : lowerList(finallyBlock.getStatements(), ctx),
|
|
1147
1251
|
exitKind: exitKindOf(stmt)
|
|
1148
1252
|
};
|
|
1149
1253
|
}
|
|
1150
|
-
if (
|
|
1254
|
+
if (Node8.isReturnStatement(stmt)) {
|
|
1151
1255
|
return { kind: "exit", exit: "return", exitKind: exitKindOf(stmt) };
|
|
1152
1256
|
}
|
|
1153
|
-
if (
|
|
1257
|
+
if (Node8.isThrowStatement(stmt)) {
|
|
1154
1258
|
return { kind: "exit", exit: "throw", exitKind: exitKindOf(stmt) };
|
|
1155
1259
|
}
|
|
1156
|
-
if (
|
|
1260
|
+
if (Node8.isBreakStatement(stmt)) {
|
|
1157
1261
|
return { kind: "exit", exit: "break", exitKind: exitKindOf(stmt) };
|
|
1158
1262
|
}
|
|
1159
|
-
if (
|
|
1263
|
+
if (Node8.isContinueStatement(stmt)) {
|
|
1160
1264
|
return { kind: "exit", exit: "continue", exitKind: exitKindOf(stmt) };
|
|
1161
1265
|
}
|
|
1162
1266
|
return { kind: "opaque", exitKind: exitKindOf(stmt) };
|
|
1163
1267
|
}
|
|
1164
|
-
function lowerSwitchGroups(stmt,
|
|
1268
|
+
function lowerSwitchGroups(stmt, ctx) {
|
|
1165
1269
|
const switchText = stmt.getExpression().getText();
|
|
1166
1270
|
const groups = [];
|
|
1167
1271
|
let pendingLabels = [];
|
|
@@ -1170,7 +1274,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1170
1274
|
if (sawDefault) {
|
|
1171
1275
|
throw new UnmodeledFlow("default clause is not last");
|
|
1172
1276
|
}
|
|
1173
|
-
if (
|
|
1277
|
+
if (Node8.isDefaultClause(clause)) {
|
|
1174
1278
|
sawDefault = true;
|
|
1175
1279
|
const stmts2 = clause.getStatements();
|
|
1176
1280
|
if (stmts2.length === 0) {
|
|
@@ -1178,11 +1282,11 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1178
1282
|
}
|
|
1179
1283
|
groups.push({
|
|
1180
1284
|
condition: null,
|
|
1181
|
-
...lowerGroupBody(stmts2,
|
|
1285
|
+
...lowerGroupBody(stmts2, ctx)
|
|
1182
1286
|
});
|
|
1183
1287
|
continue;
|
|
1184
1288
|
}
|
|
1185
|
-
if (!
|
|
1289
|
+
if (!Node8.isCaseClause(clause)) {
|
|
1186
1290
|
continue;
|
|
1187
1291
|
}
|
|
1188
1292
|
pendingLabels.push(clause.getExpression().getText());
|
|
@@ -1195,7 +1299,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1195
1299
|
const sourceText = labels.map((l) => `${switchText} === ${l}`).join(" || ");
|
|
1196
1300
|
groups.push({
|
|
1197
1301
|
condition: { sourceText, expression: null },
|
|
1198
|
-
...lowerGroupBody(stmts,
|
|
1302
|
+
...lowerGroupBody(stmts, ctx)
|
|
1199
1303
|
});
|
|
1200
1304
|
}
|
|
1201
1305
|
return groups;
|
|
@@ -1203,41 +1307,42 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1203
1307
|
function validateClauseBreaks(stmts) {
|
|
1204
1308
|
const last = stmts[stmts.length - 1];
|
|
1205
1309
|
for (const stmt of stmts) {
|
|
1206
|
-
if (stmt === last &&
|
|
1310
|
+
if (stmt === last && Node8.isBreakStatement(stmt)) {
|
|
1207
1311
|
continue;
|
|
1208
1312
|
}
|
|
1209
|
-
if (
|
|
1313
|
+
if (Node8.isSwitchStatement(stmt) || isLoop(stmt)) {
|
|
1210
1314
|
continue;
|
|
1211
1315
|
}
|
|
1212
1316
|
stmt.forEachDescendant((node, traversal) => {
|
|
1213
|
-
if (
|
|
1317
|
+
if (startsItsOwnScope(node) || Node8.isSwitchStatement(node) || isLoop(node)) {
|
|
1214
1318
|
traversal.skip();
|
|
1215
1319
|
return;
|
|
1216
1320
|
}
|
|
1217
|
-
if (
|
|
1321
|
+
if (Node8.isBreakStatement(node)) {
|
|
1218
1322
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
1219
1323
|
}
|
|
1220
1324
|
});
|
|
1221
|
-
if (
|
|
1325
|
+
if (Node8.isBreakStatement(stmt)) {
|
|
1222
1326
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
1223
1327
|
}
|
|
1224
1328
|
}
|
|
1225
1329
|
}
|
|
1226
|
-
function lowerGroupBody(rawStmts,
|
|
1330
|
+
function lowerGroupBody(rawStmts, ctx) {
|
|
1227
1331
|
const stmts = spliceBlocks(rawStmts);
|
|
1228
1332
|
validateClauseBreaks(stmts);
|
|
1229
1333
|
const last = stmts[stmts.length - 1];
|
|
1230
|
-
const hasTrailingBreak = last !== void 0 &&
|
|
1334
|
+
const hasTrailingBreak = last !== void 0 && Node8.isBreakStatement(last);
|
|
1231
1335
|
const kept = hasTrailingBreak ? stmts.slice(0, -1) : stmts;
|
|
1232
|
-
const body = lowerList(kept,
|
|
1336
|
+
const body = lowerList(kept, ctx);
|
|
1233
1337
|
if (hasTrailingBreak && last !== void 0) {
|
|
1234
|
-
lowerStatement(last,
|
|
1338
|
+
lowerStatement(last, ctx);
|
|
1235
1339
|
}
|
|
1236
1340
|
return { hasTrailingBreak, body };
|
|
1237
1341
|
}
|
|
1238
|
-
function lowerFunctionBody(body, terminalNodes) {
|
|
1342
|
+
function lowerFunctionBody(body, terminalNodes, func = body, barriers = NO_BARRIERS) {
|
|
1239
1343
|
const rawToStructured = /* @__PURE__ */ new Map();
|
|
1240
|
-
const
|
|
1344
|
+
const ctx = { func, barriers, rawToStructured };
|
|
1345
|
+
const statements = lowerList(body.getStatements(), ctx);
|
|
1241
1346
|
const terminalsByStmt = /* @__PURE__ */ new Map();
|
|
1242
1347
|
const terminalHomeRaw = /* @__PURE__ */ new Map();
|
|
1243
1348
|
for (const terminal of terminalNodes) {
|
|
@@ -1259,7 +1364,7 @@ function lowerFunctionBody(body, terminalNodes) {
|
|
|
1259
1364
|
function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
1260
1365
|
let current2 = terminal;
|
|
1261
1366
|
while (current2 !== void 0 && current2 !== body) {
|
|
1262
|
-
if (
|
|
1367
|
+
if (Node8.isStatement(current2) && rawToStructured.has(current2)) {
|
|
1263
1368
|
return current2;
|
|
1264
1369
|
}
|
|
1265
1370
|
current2 = current2.getParent();
|
|
@@ -1268,39 +1373,42 @@ function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
|
1268
1373
|
}
|
|
1269
1374
|
|
|
1270
1375
|
// src/paths/pathConditions.ts
|
|
1271
|
-
function containsUnmodeledFlow(body) {
|
|
1376
|
+
function containsUnmodeledFlow(body, func, barriers) {
|
|
1272
1377
|
let found = false;
|
|
1273
1378
|
body.forEachDescendant((node, traversal) => {
|
|
1274
|
-
if (
|
|
1379
|
+
if (isDescentStop(node, func, barriers)) {
|
|
1275
1380
|
traversal.skip();
|
|
1276
1381
|
return;
|
|
1277
1382
|
}
|
|
1278
|
-
if (
|
|
1383
|
+
if (Node9.isLabeledStatement(node)) {
|
|
1279
1384
|
found = true;
|
|
1280
1385
|
traversal.stop();
|
|
1281
1386
|
}
|
|
1282
1387
|
});
|
|
1283
1388
|
return found;
|
|
1284
1389
|
}
|
|
1285
|
-
function
|
|
1390
|
+
function loweredExpressionBody(body, terminalNodes, func, barriers) {
|
|
1391
|
+
const statement = {
|
|
1392
|
+
kind: "opaque",
|
|
1393
|
+
exitKind: null,
|
|
1394
|
+
callbacks: lowerExpressionBodyCallbacks(body, func, barriers)
|
|
1395
|
+
};
|
|
1396
|
+
return {
|
|
1397
|
+
statements: [statement],
|
|
1398
|
+
terminalsByStmt: /* @__PURE__ */ new Map([[statement, terminalNodes]]),
|
|
1399
|
+
terminalHomeRaw: /* @__PURE__ */ new Map()
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
function computePathConditions(func, terminalNodes, barriers = NO_BARRIERS) {
|
|
1286
1403
|
const body = func.getBody();
|
|
1287
1404
|
if (body === void 0) {
|
|
1288
1405
|
return { byTerminal: /* @__PURE__ */ new Map(), fallthrough: [] };
|
|
1289
1406
|
}
|
|
1290
|
-
if (
|
|
1291
|
-
const byTerminal = /* @__PURE__ */ new Map();
|
|
1292
|
-
for (const terminal of terminalNodes) {
|
|
1293
|
-
byTerminal.set(terminal, [
|
|
1294
|
-
collectAncestorConditionInfosBelow(terminal, func)
|
|
1295
|
-
]);
|
|
1296
|
-
}
|
|
1297
|
-
return { byTerminal, fallthrough: [] };
|
|
1298
|
-
}
|
|
1299
|
-
if (containsUnmodeledFlow(body)) {
|
|
1407
|
+
if (containsUnmodeledFlow(body, func, barriers)) {
|
|
1300
1408
|
return degradedResult(func, terminalNodes, "labeled statement");
|
|
1301
1409
|
}
|
|
1302
1410
|
try {
|
|
1303
|
-
const lowered = lowerFunctionBody(body, terminalNodes);
|
|
1411
|
+
const lowered = Node9.isBlock(body) ? lowerFunctionBody(body, terminalNodes, func, barriers) : loweredExpressionBody(body, terminalNodes, func, barriers);
|
|
1304
1412
|
const result = enumerateStructuredPaths({
|
|
1305
1413
|
statements: lowered.statements,
|
|
1306
1414
|
terminalsByStmt: lowered.terminalsByStmt
|
|
@@ -1367,7 +1475,7 @@ function lineAt(node, pos) {
|
|
|
1367
1475
|
}
|
|
1368
1476
|
|
|
1369
1477
|
// src/moduleExports.ts
|
|
1370
|
-
import { Node as
|
|
1478
|
+
import { Node as Node10 } from "ts-morph";
|
|
1371
1479
|
|
|
1372
1480
|
// src/bootstrap/lazyProjectInit.ts
|
|
1373
1481
|
import fs from "fs/promises";
|
|
@@ -1500,7 +1608,7 @@ var ModuleGraph = class {
|
|
|
1500
1608
|
return created;
|
|
1501
1609
|
}
|
|
1502
1610
|
assert(relation, tuple) {
|
|
1503
|
-
if (this.db.add(relation, tuple)) {
|
|
1611
|
+
if (this.db.add(relation, tuple) === "added") {
|
|
1504
1612
|
this.stale = true;
|
|
1505
1613
|
}
|
|
1506
1614
|
}
|
|
@@ -1717,8 +1825,8 @@ function loadImportGraphsDepthFirstFromPaths(project, rootPaths) {
|
|
|
1717
1825
|
stack.pop();
|
|
1718
1826
|
loadOrder.push(top.path);
|
|
1719
1827
|
let deepest = 0;
|
|
1720
|
-
for (const
|
|
1721
|
-
deepest = Math.max(deepest, chainDepth.get(
|
|
1828
|
+
for (const path12 of top.deps) {
|
|
1829
|
+
deepest = Math.max(deepest, chainDepth.get(path12) ?? 0);
|
|
1722
1830
|
}
|
|
1723
1831
|
chainDepth.set(top.path, deepest + 1);
|
|
1724
1832
|
}
|
|
@@ -1946,6 +2054,30 @@ async function readImportsConcurrently(paths) {
|
|
|
1946
2054
|
return results;
|
|
1947
2055
|
}
|
|
1948
2056
|
|
|
2057
|
+
// src/depTracking.ts
|
|
2058
|
+
function createDependencySink() {
|
|
2059
|
+
return { files: /* @__PURE__ */ new Set(), mountPrefixes: /* @__PURE__ */ new Map(), claims: [] };
|
|
2060
|
+
}
|
|
2061
|
+
var activeSink = null;
|
|
2062
|
+
function withDependencySink(sink, fn) {
|
|
2063
|
+
const previous = activeSink;
|
|
2064
|
+
activeSink = sink;
|
|
2065
|
+
try {
|
|
2066
|
+
return fn();
|
|
2067
|
+
} finally {
|
|
2068
|
+
activeSink = previous;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
function recordFileDependency(filePath) {
|
|
2072
|
+
activeSink?.files.add(filePath);
|
|
2073
|
+
}
|
|
2074
|
+
function recordMountPrefix(childId, prefix) {
|
|
2075
|
+
activeSink?.mountPrefixes.set(childId, prefix);
|
|
2076
|
+
}
|
|
2077
|
+
function recordUnitClaim(key, pack) {
|
|
2078
|
+
activeSink?.claims.push({ key, pack });
|
|
2079
|
+
}
|
|
2080
|
+
|
|
1949
2081
|
// src/perFileCache.ts
|
|
1950
2082
|
function createPerFileCache() {
|
|
1951
2083
|
const byParse = /* @__PURE__ */ new WeakMap();
|
|
@@ -1961,6 +2093,7 @@ function createPerFileCache() {
|
|
|
1961
2093
|
|
|
1962
2094
|
// src/moduleExports.ts
|
|
1963
2095
|
function exportedDeclarationsOf(sourceFile) {
|
|
2096
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
1964
2097
|
const cached = exportsByFile.get(sourceFile);
|
|
1965
2098
|
if (cached !== void 0) {
|
|
1966
2099
|
return cached;
|
|
@@ -1975,7 +2108,14 @@ function resolveAliasedSymbol(symbol) {
|
|
|
1975
2108
|
warmReExportChains(declaration.getSourceFile(), "every import");
|
|
1976
2109
|
}
|
|
1977
2110
|
try {
|
|
1978
|
-
|
|
2111
|
+
const aliased = symbol.getAliasedSymbol();
|
|
2112
|
+
for (const declaration of aliased?.getDeclarations() ?? []) {
|
|
2113
|
+
const file = declaration.getSourceFile();
|
|
2114
|
+
if (!file.isInNodeModules()) {
|
|
2115
|
+
recordFileDependency(file.getFilePath());
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
return aliased;
|
|
1979
2119
|
} catch (error) {
|
|
1980
2120
|
if (!(error instanceof RangeError)) {
|
|
1981
2121
|
throw error;
|
|
@@ -2031,11 +2171,11 @@ function walkAndWarm(root, reach) {
|
|
|
2031
2171
|
if (warmedFiles.get(target) !== void 0) {
|
|
2032
2172
|
continue;
|
|
2033
2173
|
}
|
|
2034
|
-
const
|
|
2035
|
-
if (visited.has(
|
|
2174
|
+
const path12 = target.getFilePath();
|
|
2175
|
+
if (visited.has(path12)) {
|
|
2036
2176
|
continue;
|
|
2037
2177
|
}
|
|
2038
|
-
visited.add(
|
|
2178
|
+
visited.add(path12);
|
|
2039
2179
|
stack.push(frameOf(target, reach));
|
|
2040
2180
|
continue;
|
|
2041
2181
|
}
|
|
@@ -2052,7 +2192,7 @@ function sitsOnWarmChains(file) {
|
|
|
2052
2192
|
return false;
|
|
2053
2193
|
}
|
|
2054
2194
|
const imported = importedFilePathsOf(project, file.getFilePath());
|
|
2055
|
-
return imported.length > 0 && imported.every((
|
|
2195
|
+
return imported.length > 0 && imported.every((path12) => warmed.has(path12));
|
|
2056
2196
|
}
|
|
2057
2197
|
function markWarmed(file) {
|
|
2058
2198
|
warmedFiles.set(file, true);
|
|
@@ -2090,7 +2230,7 @@ function reExportShapeOf(file, reach) {
|
|
|
2090
2230
|
for (const assignment of file.getExportAssignments()) {
|
|
2091
2231
|
exportNodes.push(assignment);
|
|
2092
2232
|
const expression = assignment.getExpression();
|
|
2093
|
-
if (
|
|
2233
|
+
if (Node10.isIdentifier(expression)) {
|
|
2094
2234
|
localNames.add(expression.getText());
|
|
2095
2235
|
}
|
|
2096
2236
|
}
|
|
@@ -2166,38 +2306,6 @@ function reportUnreadableExports(file) {
|
|
|
2166
2306
|
);
|
|
2167
2307
|
}
|
|
2168
2308
|
|
|
2169
|
-
// src/walk/descent.ts
|
|
2170
|
-
import { Node as Node10 } from "ts-morph";
|
|
2171
|
-
var NO_BARRIERS = /* @__PURE__ */ new Set();
|
|
2172
|
-
function isDescentStop(node, func, barriers = NO_BARRIERS) {
|
|
2173
|
-
if (node === func) {
|
|
2174
|
-
return false;
|
|
2175
|
-
}
|
|
2176
|
-
if (Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node)) {
|
|
2177
|
-
return true;
|
|
2178
|
-
}
|
|
2179
|
-
if (Node10.isArrowFunction(node) || Node10.isFunctionExpression(node)) {
|
|
2180
|
-
return barriers.has(node);
|
|
2181
|
-
}
|
|
2182
|
-
return false;
|
|
2183
|
-
}
|
|
2184
|
-
function isModuleScopeStop(node) {
|
|
2185
|
-
return Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node) || Node10.isArrowFunction(node) || Node10.isFunctionExpression(node) || Node10.isClassDeclaration(node) || Node10.isClassExpression(node);
|
|
2186
|
-
}
|
|
2187
|
-
function crossesNestedFunctionScope(node, func) {
|
|
2188
|
-
let current2 = node;
|
|
2189
|
-
while (current2 !== void 0 && current2 !== func) {
|
|
2190
|
-
if (startsItsOwnScope(current2)) {
|
|
2191
|
-
return true;
|
|
2192
|
-
}
|
|
2193
|
-
current2 = current2.getParent();
|
|
2194
|
-
}
|
|
2195
|
-
return false;
|
|
2196
|
-
}
|
|
2197
|
-
function startsItsOwnScope(node) {
|
|
2198
|
-
return Node10.isArrowFunction(node) || Node10.isFunctionExpression(node) || Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node) || Node10.isGetAccessorDeclaration(node) || Node10.isSetAccessorDeclaration(node) || Node10.isConstructorDeclaration(node);
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
2309
|
// src/resolve/invocationEffects.ts
|
|
2202
2310
|
function isImportedFrom(identifier, expectedModule) {
|
|
2203
2311
|
if (!Node11.isIdentifier(identifier)) {
|
|
@@ -2217,14 +2325,38 @@ function isImportedFrom(identifier, expectedModule) {
|
|
|
2217
2325
|
(decl) => decl.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2218
2326
|
);
|
|
2219
2327
|
}
|
|
2220
|
-
function methodDeclaredIn(callee, expectedModule) {
|
|
2328
|
+
function methodDeclaredIn(callee, expectedModule, resolve2) {
|
|
2221
2329
|
if (!Node11.isPropertyAccessExpression(callee)) {
|
|
2222
2330
|
return false;
|
|
2223
2331
|
}
|
|
2224
2332
|
const declarations = callee.getNameNode().getSymbol()?.getDeclarations();
|
|
2225
|
-
|
|
2333
|
+
if (declarations !== void 0 && declarations.some(
|
|
2226
2334
|
(declaration) => declaration.getSourceFile().getFilePath().includes(`/node_modules/${expectedModule}/`)
|
|
2227
|
-
)
|
|
2335
|
+
)) {
|
|
2336
|
+
return true;
|
|
2337
|
+
}
|
|
2338
|
+
if (resolve2 === void 0) {
|
|
2339
|
+
return false;
|
|
2340
|
+
}
|
|
2341
|
+
const written = resolve2(callee.getExpression());
|
|
2342
|
+
const made = maker(written);
|
|
2343
|
+
return made !== null && isImportedFrom(rootIdentifier(made), expectedModule);
|
|
2344
|
+
}
|
|
2345
|
+
function maker(written) {
|
|
2346
|
+
if (written === null) {
|
|
2347
|
+
return null;
|
|
2348
|
+
}
|
|
2349
|
+
if (Node11.isNewExpression(written) || Node11.isCallExpression(written)) {
|
|
2350
|
+
return written.getExpression();
|
|
2351
|
+
}
|
|
2352
|
+
return null;
|
|
2353
|
+
}
|
|
2354
|
+
function rootIdentifier(expression) {
|
|
2355
|
+
let root = expression;
|
|
2356
|
+
while (Node11.isPropertyAccessExpression(root)) {
|
|
2357
|
+
root = root.getExpression();
|
|
2358
|
+
}
|
|
2359
|
+
return root;
|
|
2228
2360
|
}
|
|
2229
2361
|
function importSpecifierMatches(decl, expectedModule) {
|
|
2230
2362
|
if (Node11.isImportSpecifier(decl)) {
|
|
@@ -2304,6 +2436,26 @@ function extractInvocationEffects(func, barriers = NO_BARRIERS) {
|
|
|
2304
2436
|
}
|
|
2305
2437
|
return;
|
|
2306
2438
|
}
|
|
2439
|
+
if (Node11.isReturnStatement(node)) {
|
|
2440
|
+
const returned = node.getExpression();
|
|
2441
|
+
const { call, async } = returned === void 0 ? { call: null, async: false } : unwrapCall(returned);
|
|
2442
|
+
if (call !== null) {
|
|
2443
|
+
const preconditions = collectPreconditions(node, func);
|
|
2444
|
+
results.push({
|
|
2445
|
+
effect: {
|
|
2446
|
+
type: "invocation",
|
|
2447
|
+
callee: call.getExpression().getText(),
|
|
2448
|
+
args: extractArgs(call),
|
|
2449
|
+
async,
|
|
2450
|
+
...preconditions.length > 0 ? { preconditions } : {}
|
|
2451
|
+
},
|
|
2452
|
+
line: startLineOf(node),
|
|
2453
|
+
neverTerminal: false,
|
|
2454
|
+
node: call
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2307
2459
|
if (Node11.isCallExpression(node)) {
|
|
2308
2460
|
const parent = node.getParent();
|
|
2309
2461
|
if (parent === void 0) {
|
|
@@ -4909,7 +5061,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4909
5061
|
];
|
|
4910
5062
|
const { byTerminal } = computePathConditions(
|
|
4911
5063
|
func,
|
|
4912
|
-
terminals.map(({ node }) => node)
|
|
5064
|
+
terminals.map(({ node }) => node),
|
|
5065
|
+
barriers
|
|
4913
5066
|
);
|
|
4914
5067
|
const wantsFallthrough = terminalPatterns.some(
|
|
4915
5068
|
(p) => p.match.type === "functionFallthrough"
|
|
@@ -4921,7 +5074,11 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4921
5074
|
if (!hasDefaultTerminal) {
|
|
4922
5075
|
const synthetic = makeFallthroughTerminal(func);
|
|
4923
5076
|
terminals.push(synthetic);
|
|
4924
|
-
const pathResult = computePathConditions(
|
|
5077
|
+
const pathResult = computePathConditions(
|
|
5078
|
+
func,
|
|
5079
|
+
[synthetic.node],
|
|
5080
|
+
barriers
|
|
5081
|
+
);
|
|
4925
5082
|
byTerminal.set(
|
|
4926
5083
|
synthetic.node,
|
|
4927
5084
|
pathResult.fallthrough.length > 0 ? pathResult.fallthrough : [[]]
|
|
@@ -4967,7 +5124,10 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4967
5124
|
const terminalLines = new Set(
|
|
4968
5125
|
distinctBranches.map((b) => b.terminal.location.start)
|
|
4969
5126
|
);
|
|
4970
|
-
|
|
5127
|
+
const terminalNodes = new Set(terminals.map(({ node }) => node));
|
|
5128
|
+
defaultBranch.effects = invocations.filter(
|
|
5129
|
+
(i) => i.node !== void 0 ? !terminalNodes.has(i.node) : i.neverTerminal || !terminalLines.has(i.line)
|
|
5130
|
+
).map((i) => i.effect);
|
|
4971
5131
|
}
|
|
4972
5132
|
}
|
|
4973
5133
|
if (recognized.length > 0) {
|
|
@@ -5012,9 +5172,9 @@ function createSourceFileLookup(project) {
|
|
|
5012
5172
|
if (sf === null) {
|
|
5013
5173
|
return null;
|
|
5014
5174
|
}
|
|
5015
|
-
const
|
|
5016
|
-
const index = functionsByFile.get(
|
|
5017
|
-
functionsByFile.set(
|
|
5175
|
+
const path12 = sf.getFilePath();
|
|
5176
|
+
const index = functionsByFile.get(path12) ?? indexFunctions(sf);
|
|
5177
|
+
functionsByFile.set(path12, index);
|
|
5018
5178
|
return index.get(rangeKey(location.range)) ?? null;
|
|
5019
5179
|
}
|
|
5020
5180
|
};
|
|
@@ -5052,7 +5212,7 @@ function indexFunctions(sf) {
|
|
|
5052
5212
|
import { createHash as createHash2 } from "crypto";
|
|
5053
5213
|
import fs2 from "fs/promises";
|
|
5054
5214
|
import path2 from "path";
|
|
5055
|
-
var SCHEMA_VERSION = "
|
|
5215
|
+
var SCHEMA_VERSION = "6";
|
|
5056
5216
|
var MAX_ENTRIES = 2;
|
|
5057
5217
|
var ENTRY_PREFIX = "key-";
|
|
5058
5218
|
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
@@ -5064,6 +5224,7 @@ function createCacheLayer(cacheDir) {
|
|
|
5064
5224
|
kind: "miss",
|
|
5065
5225
|
diagnostic: { kind: "miss", missReason: "no-manifest" }
|
|
5066
5226
|
}),
|
|
5227
|
+
plan: async () => null,
|
|
5067
5228
|
write: async () => {
|
|
5068
5229
|
}
|
|
5069
5230
|
};
|
|
@@ -5094,17 +5255,32 @@ function createCacheLayer(cacheDir) {
|
|
|
5094
5255
|
diagnostic: { kind: "hit" }
|
|
5095
5256
|
};
|
|
5096
5257
|
},
|
|
5097
|
-
async
|
|
5258
|
+
async plan(input) {
|
|
5259
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5260
|
+
const manifest = await readManifest(path2.join(entryDir, "manifest.json"));
|
|
5261
|
+
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
5262
|
+
return null;
|
|
5263
|
+
}
|
|
5264
|
+
const currentTsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5265
|
+
if (!fileStampEquals(manifest.tsconfigStamp, currentTsconfigStamp)) {
|
|
5266
|
+
return null;
|
|
5267
|
+
}
|
|
5268
|
+
await markUsed(entryDir);
|
|
5269
|
+
return buildPlan(manifest, await resolveFileStamps(input));
|
|
5270
|
+
},
|
|
5271
|
+
async write(input, summaries, attribution) {
|
|
5272
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5273
|
+
const previous = await readManifest(path2.join(entryDir, "manifest.json"));
|
|
5098
5274
|
const tsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5099
|
-
const files = await resolveFileStamps(input);
|
|
5275
|
+
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
5100
5276
|
const manifest = {
|
|
5101
5277
|
schemaVersion: SCHEMA_VERSION,
|
|
5102
5278
|
adapterPacksDigest: input.adapterPacksDigest,
|
|
5103
5279
|
tsconfigStamp,
|
|
5104
5280
|
files,
|
|
5105
|
-
summaries
|
|
5281
|
+
summaries,
|
|
5282
|
+
...attribution === void 0 ? {} : encodeAttribution(attribution)
|
|
5106
5283
|
};
|
|
5107
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
5108
5284
|
await fs2.mkdir(entryDir, { recursive: true });
|
|
5109
5285
|
await fs2.writeFile(
|
|
5110
5286
|
path2.join(entryDir, "manifest.json"),
|
|
@@ -5114,6 +5290,163 @@ function createCacheLayer(cacheDir) {
|
|
|
5114
5290
|
}
|
|
5115
5291
|
};
|
|
5116
5292
|
}
|
|
5293
|
+
async function buildPlan(manifest, currentStamps) {
|
|
5294
|
+
const stored = new Map(manifest.files.map((f) => [f.path, f]));
|
|
5295
|
+
const current2 = new Map(currentStamps.map((f) => [f.path, f]));
|
|
5296
|
+
const changed = /* @__PURE__ */ new Set();
|
|
5297
|
+
const removed = /* @__PURE__ */ new Set();
|
|
5298
|
+
for (const p of stored.keys()) {
|
|
5299
|
+
if (!current2.has(p)) {
|
|
5300
|
+
removed.add(p);
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
const toVerify = [];
|
|
5304
|
+
for (const [p, stamp] of current2) {
|
|
5305
|
+
const before = stored.get(p);
|
|
5306
|
+
if (before === void 0) {
|
|
5307
|
+
changed.add(p);
|
|
5308
|
+
} else if (!fileStampEquals(before, stamp)) {
|
|
5309
|
+
if (before.contentHash === void 0) {
|
|
5310
|
+
changed.add(p);
|
|
5311
|
+
} else {
|
|
5312
|
+
toVerify.push(p);
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
await Promise.all(
|
|
5317
|
+
toVerify.map(async (p) => {
|
|
5318
|
+
const hash = await hashFile(p);
|
|
5319
|
+
if (hash === null || hash !== stored.get(p)?.contentHash) {
|
|
5320
|
+
changed.add(p);
|
|
5321
|
+
}
|
|
5322
|
+
})
|
|
5323
|
+
);
|
|
5324
|
+
const roots = /* @__PURE__ */ new Map();
|
|
5325
|
+
const rootNames = manifest.roots ?? [];
|
|
5326
|
+
const depPaths = manifest.depPaths ?? [];
|
|
5327
|
+
let rootsDeclined = 0;
|
|
5328
|
+
rootNames.forEach((rootPath, i) => {
|
|
5329
|
+
const meta = manifest.rootMeta?.[i];
|
|
5330
|
+
if (meta === void 0) {
|
|
5331
|
+
return;
|
|
5332
|
+
}
|
|
5333
|
+
if (!meta.cacheable) {
|
|
5334
|
+
rootsDeclined += 1;
|
|
5335
|
+
}
|
|
5336
|
+
roots.set(rootPath, {
|
|
5337
|
+
path: rootPath,
|
|
5338
|
+
cacheable: meta.cacheable,
|
|
5339
|
+
deps: meta.deps.flatMap((d) => {
|
|
5340
|
+
const p = depPaths[d];
|
|
5341
|
+
return p === void 0 ? [] : [p];
|
|
5342
|
+
}),
|
|
5343
|
+
claims: meta.claims,
|
|
5344
|
+
mountPrefixes: meta.mountPrefixes,
|
|
5345
|
+
packs: meta.packs
|
|
5346
|
+
});
|
|
5347
|
+
});
|
|
5348
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
5349
|
+
for (const [rootPath, record] of roots) {
|
|
5350
|
+
if (!record.cacheable || !current2.has(rootPath)) {
|
|
5351
|
+
continue;
|
|
5352
|
+
}
|
|
5353
|
+
if (changed.has(rootPath)) {
|
|
5354
|
+
continue;
|
|
5355
|
+
}
|
|
5356
|
+
const depMoved = record.deps.some((d) => changed.has(d) || removed.has(d));
|
|
5357
|
+
if (!depMoved) {
|
|
5358
|
+
validRoots.add(rootPath);
|
|
5359
|
+
}
|
|
5360
|
+
}
|
|
5361
|
+
const owners = manifest.owners ?? [];
|
|
5362
|
+
return {
|
|
5363
|
+
changed,
|
|
5364
|
+
removed,
|
|
5365
|
+
roots,
|
|
5366
|
+
validRoots,
|
|
5367
|
+
rootsDeclined,
|
|
5368
|
+
reuse(valid) {
|
|
5369
|
+
const summaries = [];
|
|
5370
|
+
const reusedOwners = [];
|
|
5371
|
+
manifest.summaries.forEach((summary, i) => {
|
|
5372
|
+
const ownerPaths = (owners[i] ?? []).flatMap((o) => {
|
|
5373
|
+
const p = rootNames[o];
|
|
5374
|
+
return p === void 0 ? [] : [p];
|
|
5375
|
+
});
|
|
5376
|
+
if (ownerPaths.some((p) => valid.has(p))) {
|
|
5377
|
+
summaries.push(summary);
|
|
5378
|
+
reusedOwners.push(ownerPaths.filter((p) => valid.has(p)));
|
|
5379
|
+
}
|
|
5380
|
+
});
|
|
5381
|
+
return { summaries, owners: reusedOwners };
|
|
5382
|
+
},
|
|
5383
|
+
allSummaries() {
|
|
5384
|
+
return manifest.summaries;
|
|
5385
|
+
},
|
|
5386
|
+
attribution() {
|
|
5387
|
+
return {
|
|
5388
|
+
roots: [...roots.values()],
|
|
5389
|
+
owners: owners.map(
|
|
5390
|
+
(ownerIds) => ownerIds.flatMap((o) => {
|
|
5391
|
+
const p = rootNames[o];
|
|
5392
|
+
return p === void 0 ? [] : [p];
|
|
5393
|
+
})
|
|
5394
|
+
)
|
|
5395
|
+
};
|
|
5396
|
+
}
|
|
5397
|
+
};
|
|
5398
|
+
}
|
|
5399
|
+
function encodeAttribution(attribution) {
|
|
5400
|
+
const roots = attribution.roots.map((r) => r.path);
|
|
5401
|
+
const rootIndex = new Map(roots.map((p, i) => [p, i]));
|
|
5402
|
+
const depIndex = /* @__PURE__ */ new Map();
|
|
5403
|
+
const depPaths = [];
|
|
5404
|
+
const depIdOf = (p) => {
|
|
5405
|
+
const existing = depIndex.get(p);
|
|
5406
|
+
if (existing !== void 0) {
|
|
5407
|
+
return existing;
|
|
5408
|
+
}
|
|
5409
|
+
const id = depPaths.length;
|
|
5410
|
+
depPaths.push(p);
|
|
5411
|
+
depIndex.set(p, id);
|
|
5412
|
+
return id;
|
|
5413
|
+
};
|
|
5414
|
+
const rootMeta = attribution.roots.map((r) => ({
|
|
5415
|
+
cacheable: r.cacheable,
|
|
5416
|
+
deps: r.deps.map(depIdOf),
|
|
5417
|
+
claims: r.claims,
|
|
5418
|
+
mountPrefixes: r.mountPrefixes,
|
|
5419
|
+
packs: r.packs
|
|
5420
|
+
}));
|
|
5421
|
+
const owners = attribution.owners.map(
|
|
5422
|
+
(ownerPaths) => ownerPaths.flatMap((p) => {
|
|
5423
|
+
const i = rootIndex.get(p);
|
|
5424
|
+
return i === void 0 ? [] : [i];
|
|
5425
|
+
})
|
|
5426
|
+
);
|
|
5427
|
+
return { roots, rootMeta, depPaths, owners };
|
|
5428
|
+
}
|
|
5429
|
+
async function hashStamps(stamps, previous) {
|
|
5430
|
+
const before = new Map((previous?.files ?? []).map((f) => [f.path, f]));
|
|
5431
|
+
return Promise.all(
|
|
5432
|
+
stamps.map(async (stamp) => {
|
|
5433
|
+
const prior = before.get(stamp.path);
|
|
5434
|
+
if (prior !== void 0 && prior.contentHash !== void 0 && fileStampEquals(prior, stamp)) {
|
|
5435
|
+
return { ...stamp, contentHash: prior.contentHash };
|
|
5436
|
+
}
|
|
5437
|
+
const contentHash = await hashFile(stamp.path);
|
|
5438
|
+
return contentHash === null ? stamp : { ...stamp, contentHash };
|
|
5439
|
+
})
|
|
5440
|
+
);
|
|
5441
|
+
}
|
|
5442
|
+
async function hashFile(filePath) {
|
|
5443
|
+
try {
|
|
5444
|
+
const content = await fs2.readFile(filePath);
|
|
5445
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 16);
|
|
5446
|
+
} catch {
|
|
5447
|
+
return null;
|
|
5448
|
+
}
|
|
5449
|
+
}
|
|
5117
5450
|
async function describeAbsentEntry(cacheDir) {
|
|
5118
5451
|
try {
|
|
5119
5452
|
const entries = await fs2.readdir(cacheDir, { withFileTypes: true });
|
|
@@ -5127,7 +5460,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
5127
5460
|
SCHEMA_VERSION,
|
|
5128
5461
|
input.adapterPacksDigest,
|
|
5129
5462
|
input.tsconfigPath ?? ""
|
|
5130
|
-
].join("
|
|
5463
|
+
].join(" ");
|
|
5131
5464
|
const name = createHash2("sha256").update(key).digest("hex").slice(0, 16);
|
|
5132
5465
|
return path2.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
5133
5466
|
}
|
|
@@ -5368,7 +5701,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
5368
5701
|
}
|
|
5369
5702
|
const responses = [];
|
|
5370
5703
|
let method;
|
|
5371
|
-
let
|
|
5704
|
+
let path12;
|
|
5372
5705
|
for (const prop of endpointNode.getProperties()) {
|
|
5373
5706
|
if (!Node24.isPropertyAssignment(prop)) {
|
|
5374
5707
|
continue;
|
|
@@ -5383,7 +5716,7 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
5383
5716
|
if (propName === pattern.pathProperty) {
|
|
5384
5717
|
const val = prop.getInitializer();
|
|
5385
5718
|
if (val !== void 0 && Node24.isStringLiteral(val)) {
|
|
5386
|
-
|
|
5719
|
+
path12 = val.getLiteralValue();
|
|
5387
5720
|
}
|
|
5388
5721
|
}
|
|
5389
5722
|
if (propName === pattern.responseExtraction.property) {
|
|
@@ -5407,10 +5740,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
|
|
|
5407
5740
|
if (responses.length === 0) {
|
|
5408
5741
|
return null;
|
|
5409
5742
|
}
|
|
5410
|
-
const boundaryBinding = method !== void 0 ||
|
|
5743
|
+
const boundaryBinding = method !== void 0 || path12 !== void 0 ? restBinding({
|
|
5411
5744
|
transport: "http",
|
|
5412
5745
|
method: method ?? null,
|
|
5413
|
-
path:
|
|
5746
|
+
path: path12 ?? null,
|
|
5414
5747
|
recognition: framework
|
|
5415
5748
|
}) : null;
|
|
5416
5749
|
return {
|
|
@@ -6001,6 +6334,13 @@ function literalIndexOf(index) {
|
|
|
6001
6334
|
}
|
|
6002
6335
|
return null;
|
|
6003
6336
|
}
|
|
6337
|
+
function asFallbackExpression(expression) {
|
|
6338
|
+
if (!Node26.isBinaryExpression(expression)) {
|
|
6339
|
+
return null;
|
|
6340
|
+
}
|
|
6341
|
+
const operator = expression.getOperatorToken().getKind();
|
|
6342
|
+
return operator === SyntaxKind6.BarBarToken || operator === SyntaxKind6.QuestionQuestionToken ? expression : null;
|
|
6343
|
+
}
|
|
6004
6344
|
function unwrapExpression(expression) {
|
|
6005
6345
|
let current2 = expression;
|
|
6006
6346
|
for (; ; ) {
|
|
@@ -6112,6 +6452,12 @@ function emitValue(db, table, value) {
|
|
|
6112
6452
|
}
|
|
6113
6453
|
return id;
|
|
6114
6454
|
}
|
|
6455
|
+
const fallback = asFallbackExpression(expression);
|
|
6456
|
+
if (fallback !== null) {
|
|
6457
|
+
fact(db, "fallbackBranch", id, emitValue(db, table, fallback.getLeft()));
|
|
6458
|
+
fact(db, "fallbackBranch", id, emitValue(db, table, fallback.getRight()));
|
|
6459
|
+
return id;
|
|
6460
|
+
}
|
|
6115
6461
|
if (Node26.isCallExpression(expression) || Node26.isNewExpression(expression)) {
|
|
6116
6462
|
emitCallFacts(db, table, expression);
|
|
6117
6463
|
fact(db, "writtenValue", id);
|
|
@@ -6576,24 +6922,27 @@ function stampGraphqlClientRefs(summaries, sourceFiles, packs, resolution) {
|
|
|
6576
6922
|
const sole = soleGraphqlClientRef(
|
|
6577
6923
|
collectGraphqlClientRefs(sourceFiles, packs, resolution)
|
|
6578
6924
|
);
|
|
6579
|
-
if (sole === null && scopes.length === 0) {
|
|
6580
|
-
return;
|
|
6581
|
-
}
|
|
6582
6925
|
const workspace = sole !== null ? boundWorkspaceFor(sole, packs) : null;
|
|
6583
6926
|
const soleClient = sole !== null ? workspace !== null ? { ...sole, workspace } : sole : null;
|
|
6927
|
+
let registry = null;
|
|
6584
6928
|
for (const summary of summaries) {
|
|
6585
6929
|
if (!isGraphqlOperationBinding(summary.identity.boundaryBinding)) {
|
|
6586
6930
|
continue;
|
|
6587
6931
|
}
|
|
6932
|
+
const existing = readGraphqlMetadata(summary) ?? {};
|
|
6588
6933
|
const scoped = scopedWorkspaceFor(summary.location.file, scopes);
|
|
6589
6934
|
const client = scoped !== null ? { uri: null, uriRef: null, workspace: scoped } : soleClient;
|
|
6590
|
-
|
|
6935
|
+
const dangling = (existing.unresolvedFragments?.length ?? 0) > 0;
|
|
6936
|
+
if (client === null && !dangling) {
|
|
6591
6937
|
continue;
|
|
6592
6938
|
}
|
|
6593
|
-
|
|
6939
|
+
if (dangling && registry === null) {
|
|
6940
|
+
registry = fragmentRegistryStatus(sourceFiles, packs);
|
|
6941
|
+
}
|
|
6594
6942
|
summary.metadata = withGraphqlMetadata(summary.metadata, {
|
|
6595
6943
|
...existing,
|
|
6596
|
-
client
|
|
6944
|
+
...client !== null ? { client } : {},
|
|
6945
|
+
...dangling && registry !== null ? { fragmentRegistry: registry } : {}
|
|
6597
6946
|
});
|
|
6598
6947
|
}
|
|
6599
6948
|
}
|
|
@@ -6659,47 +7008,197 @@ function soleGraphqlClientRef(refs) {
|
|
|
6659
7008
|
}
|
|
6660
7009
|
return [...distinct.values()][0] ?? null;
|
|
6661
7010
|
}
|
|
6662
|
-
function
|
|
6663
|
-
const
|
|
6664
|
-
for (const
|
|
6665
|
-
const
|
|
6666
|
-
|
|
6667
|
-
|
|
7011
|
+
function fragmentRegistryStatus(sourceFiles, packs) {
|
|
7012
|
+
const statuses = [];
|
|
7013
|
+
for (const spec of packs.flatMap((pack) => pack.graphqlClients ?? [])) {
|
|
7014
|
+
const registrySpec = spec.fragmentRegistry;
|
|
7015
|
+
if (registrySpec === void 0) {
|
|
7016
|
+
continue;
|
|
7017
|
+
}
|
|
7018
|
+
for (const sourceFile of sourceFiles) {
|
|
7019
|
+
const local = localImportName(
|
|
7020
|
+
sourceFile,
|
|
7021
|
+
spec.importModule,
|
|
7022
|
+
spec.importName
|
|
7023
|
+
);
|
|
7024
|
+
if (local === null) {
|
|
6668
7025
|
continue;
|
|
6669
7026
|
}
|
|
6670
|
-
|
|
6671
|
-
if (
|
|
6672
|
-
|
|
7027
|
+
sourceFile.forEachDescendant((node) => {
|
|
7028
|
+
if (isConstructionNamed(node, local)) {
|
|
7029
|
+
statuses.push(constructionRegistryStatus(node, registrySpec));
|
|
6673
7030
|
}
|
|
6674
|
-
|
|
6675
|
-
names.set(local, spec.uriProperty);
|
|
6676
|
-
}
|
|
7031
|
+
});
|
|
6677
7032
|
}
|
|
6678
7033
|
}
|
|
6679
|
-
return
|
|
7034
|
+
return combineRegistryStatuses(statuses);
|
|
6680
7035
|
}
|
|
6681
|
-
function
|
|
6682
|
-
if (
|
|
6683
|
-
return
|
|
7036
|
+
function combineRegistryStatuses(statuses) {
|
|
7037
|
+
if (statuses.includes("configured")) {
|
|
7038
|
+
return "configured";
|
|
6684
7039
|
}
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
return null;
|
|
7040
|
+
if (statuses.length === 0 || statuses.includes("unknown")) {
|
|
7041
|
+
return "unknown";
|
|
6688
7042
|
}
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
7043
|
+
return "absent";
|
|
7044
|
+
}
|
|
7045
|
+
function constructionRegistryStatus(construction, spec) {
|
|
7046
|
+
const options = firstArgumentObjectLiteral(construction);
|
|
7047
|
+
if (options === null) {
|
|
7048
|
+
return "unknown";
|
|
6692
7049
|
}
|
|
6693
|
-
const
|
|
6694
|
-
if (
|
|
6695
|
-
return
|
|
7050
|
+
const cacheExpr = propertyValueOf2(options, spec.cacheProperty);
|
|
7051
|
+
if (cacheExpr === null) {
|
|
7052
|
+
return "unknown";
|
|
6696
7053
|
}
|
|
6697
|
-
const
|
|
6698
|
-
|
|
7054
|
+
const cacheConstruction = resolveToConstructionOf(
|
|
7055
|
+
cacheExpr,
|
|
7056
|
+
spec.cacheConstructor
|
|
7057
|
+
);
|
|
7058
|
+
if (cacheConstruction === null) {
|
|
7059
|
+
return "unknown";
|
|
7060
|
+
}
|
|
7061
|
+
if (!Node28.isNewExpression(cacheConstruction) && !Node28.isCallExpression(cacheConstruction)) {
|
|
7062
|
+
return "unknown";
|
|
7063
|
+
}
|
|
7064
|
+
const args = cacheConstruction.getArguments();
|
|
7065
|
+
if (args.length === 0) {
|
|
7066
|
+
return "absent";
|
|
7067
|
+
}
|
|
7068
|
+
const cacheOptions = firstArgumentObjectLiteral(cacheConstruction);
|
|
7069
|
+
if (cacheOptions === null) {
|
|
7070
|
+
return "unknown";
|
|
7071
|
+
}
|
|
7072
|
+
if (cacheOptions.getProperty(spec.registryProperty) !== void 0) {
|
|
7073
|
+
return "configured";
|
|
7074
|
+
}
|
|
7075
|
+
const hasSpread = cacheOptions.getProperties().some((property) => Node28.isSpreadAssignment(property));
|
|
7076
|
+
return hasSpread ? "unknown" : "absent";
|
|
7077
|
+
}
|
|
7078
|
+
function firstArgumentObjectLiteral(construction) {
|
|
7079
|
+
if (!Node28.isNewExpression(construction) && !Node28.isCallExpression(construction)) {
|
|
6699
7080
|
return null;
|
|
6700
7081
|
}
|
|
6701
|
-
const
|
|
6702
|
-
if (
|
|
7082
|
+
const arg = construction.getArguments()[0];
|
|
7083
|
+
if (arg === void 0 || !Node28.isObjectLiteralExpression(arg)) {
|
|
7084
|
+
return null;
|
|
7085
|
+
}
|
|
7086
|
+
return arg;
|
|
7087
|
+
}
|
|
7088
|
+
function propertyValueOf2(options, name) {
|
|
7089
|
+
const property = options.getProperty(name);
|
|
7090
|
+
if (property === void 0) {
|
|
7091
|
+
return null;
|
|
7092
|
+
}
|
|
7093
|
+
if (Node28.isPropertyAssignment(property)) {
|
|
7094
|
+
return property.getInitializer() ?? null;
|
|
7095
|
+
}
|
|
7096
|
+
if (Node28.isShorthandPropertyAssignment(property)) {
|
|
7097
|
+
const symbol = property.getProject().getTypeChecker().getShorthandAssignmentValueSymbol(property);
|
|
7098
|
+
return symbol?.getValueDeclaration() ?? null;
|
|
7099
|
+
}
|
|
7100
|
+
return null;
|
|
7101
|
+
}
|
|
7102
|
+
function resolveToConstructionOf(expression, cacheClass) {
|
|
7103
|
+
let current2 = expression;
|
|
7104
|
+
for (let hop = 0; hop < 4 && current2 !== void 0; hop += 1) {
|
|
7105
|
+
current2 = unwrapExpression2(current2);
|
|
7106
|
+
if (Node28.isVariableDeclaration(current2)) {
|
|
7107
|
+
current2 = current2.getInitializer();
|
|
7108
|
+
continue;
|
|
7109
|
+
}
|
|
7110
|
+
if (Node28.isNewExpression(current2) || Node28.isCallExpression(current2)) {
|
|
7111
|
+
const callee = current2.getExpression();
|
|
7112
|
+
if (callee === void 0 || !Node28.isIdentifier(callee)) {
|
|
7113
|
+
return null;
|
|
7114
|
+
}
|
|
7115
|
+
const local = localImportName(
|
|
7116
|
+
current2.getSourceFile(),
|
|
7117
|
+
cacheClass.importModule,
|
|
7118
|
+
cacheClass.importName
|
|
7119
|
+
);
|
|
7120
|
+
return local !== null && callee.getText() === local ? current2 : null;
|
|
7121
|
+
}
|
|
7122
|
+
if (!Node28.isIdentifier(current2)) {
|
|
7123
|
+
return null;
|
|
7124
|
+
}
|
|
7125
|
+
const declaration = current2.getSymbol()?.getValueDeclaration();
|
|
7126
|
+
if (declaration === void 0 || !Node28.isVariableDeclaration(declaration)) {
|
|
7127
|
+
return null;
|
|
7128
|
+
}
|
|
7129
|
+
current2 = declaration.getInitializer();
|
|
7130
|
+
}
|
|
7131
|
+
return null;
|
|
7132
|
+
}
|
|
7133
|
+
function unwrapExpression2(node) {
|
|
7134
|
+
let current2 = node;
|
|
7135
|
+
while (Node28.isParenthesizedExpression(current2) || Node28.isAsExpression(current2) || Node28.isNonNullExpression(current2)) {
|
|
7136
|
+
current2 = current2.getExpression();
|
|
7137
|
+
}
|
|
7138
|
+
return current2;
|
|
7139
|
+
}
|
|
7140
|
+
function isConstructionNamed(node, localName) {
|
|
7141
|
+
if (!Node28.isNewExpression(node) && !Node28.isCallExpression(node)) {
|
|
7142
|
+
return false;
|
|
7143
|
+
}
|
|
7144
|
+
const callee = node.getExpression();
|
|
7145
|
+
return callee !== void 0 && Node28.isIdentifier(callee) && callee.getText() === localName;
|
|
7146
|
+
}
|
|
7147
|
+
function localImportName(sourceFile, importModule, importName) {
|
|
7148
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
7149
|
+
const module = importDecl.getModuleSpecifierValue();
|
|
7150
|
+
if (module !== importModule && !module.startsWith(`${importModule}/`)) {
|
|
7151
|
+
continue;
|
|
7152
|
+
}
|
|
7153
|
+
for (const named2 of importDecl.getNamedImports()) {
|
|
7154
|
+
if (named2.getName() === importName) {
|
|
7155
|
+
return named2.getAliasNode()?.getText() ?? named2.getName();
|
|
7156
|
+
}
|
|
7157
|
+
}
|
|
7158
|
+
}
|
|
7159
|
+
return null;
|
|
7160
|
+
}
|
|
7161
|
+
function localNamesFor(sourceFile, specs) {
|
|
7162
|
+
const names = /* @__PURE__ */ new Map();
|
|
7163
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
7164
|
+
const module = importDecl.getModuleSpecifierValue();
|
|
7165
|
+
for (const spec of specs) {
|
|
7166
|
+
if (module !== spec.importModule) {
|
|
7167
|
+
continue;
|
|
7168
|
+
}
|
|
7169
|
+
for (const named2 of importDecl.getNamedImports()) {
|
|
7170
|
+
if (named2.getName() !== spec.importName) {
|
|
7171
|
+
continue;
|
|
7172
|
+
}
|
|
7173
|
+
const local = named2.getAliasNode()?.getText() ?? named2.getName();
|
|
7174
|
+
names.set(local, spec.uriProperty);
|
|
7175
|
+
}
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
return names;
|
|
7179
|
+
}
|
|
7180
|
+
function constructionRef(node, localNames, resolution) {
|
|
7181
|
+
if (!Node28.isNewExpression(node) && !Node28.isCallExpression(node)) {
|
|
7182
|
+
return null;
|
|
7183
|
+
}
|
|
7184
|
+
const callee = node.getExpression();
|
|
7185
|
+
if (callee === void 0 || !Node28.isIdentifier(callee)) {
|
|
7186
|
+
return null;
|
|
7187
|
+
}
|
|
7188
|
+
const uriProperty = localNames.get(callee.getText());
|
|
7189
|
+
if (uriProperty === void 0) {
|
|
7190
|
+
return null;
|
|
7191
|
+
}
|
|
7192
|
+
const optionsArg = node.getArguments()[0];
|
|
7193
|
+
if (optionsArg === void 0 || !Node28.isObjectLiteralExpression(optionsArg)) {
|
|
7194
|
+
return null;
|
|
7195
|
+
}
|
|
7196
|
+
const property = optionsArg.getProperty(uriProperty);
|
|
7197
|
+
if (property === void 0 || !Node28.isPropertyAssignment(property)) {
|
|
7198
|
+
return null;
|
|
7199
|
+
}
|
|
7200
|
+
const value = property.getInitializer();
|
|
7201
|
+
if (value === void 0) {
|
|
6703
7202
|
return null;
|
|
6704
7203
|
}
|
|
6705
7204
|
const literal = stringValueOf(value, resolution);
|
|
@@ -6986,7 +7485,7 @@ function calleeOf(decorator) {
|
|
|
6986
7485
|
|
|
6987
7486
|
// src/discovery/decoratedMethod.ts
|
|
6988
7487
|
function resolverTypeName(args) {
|
|
6989
|
-
return args.
|
|
7488
|
+
return args.typeMap[args.decoratorName] ?? args.classTypeName ?? null;
|
|
6990
7489
|
}
|
|
6991
7490
|
function resolveResolverClassTypeName(decoratorArg) {
|
|
6992
7491
|
if (Node32.isArrowFunction(decoratorArg)) {
|
|
@@ -7406,32 +7905,163 @@ function innerTemplateText(template) {
|
|
|
7406
7905
|
}
|
|
7407
7906
|
return raw;
|
|
7408
7907
|
}
|
|
7409
|
-
function
|
|
7410
|
-
|
|
7411
|
-
|
|
7908
|
+
function startAssembly(resolution) {
|
|
7909
|
+
return {
|
|
7910
|
+
resolution,
|
|
7911
|
+
seen: /* @__PURE__ */ new Set(),
|
|
7912
|
+
unresolvedInterpolations: [],
|
|
7913
|
+
unresolvedInsideSelection: false
|
|
7914
|
+
};
|
|
7915
|
+
}
|
|
7916
|
+
function assembledTemplateText(template, assembly) {
|
|
7917
|
+
if (Node35.isNoSubstitutionTemplateLiteral(template)) {
|
|
7918
|
+
return innerTemplateText(template);
|
|
7919
|
+
}
|
|
7920
|
+
if (!Node35.isTemplateExpression(template)) {
|
|
7921
|
+
return null;
|
|
7922
|
+
}
|
|
7923
|
+
let text = template.getHead().getLiteralText();
|
|
7924
|
+
for (const span of template.getTemplateSpans()) {
|
|
7925
|
+
const spliced = interpolatedDocumentText(span.getExpression(), assembly);
|
|
7926
|
+
if (spliced === null) {
|
|
7927
|
+
assembly.unresolvedInterpolations.push(
|
|
7928
|
+
singleLine(span.getExpression().getText())
|
|
7929
|
+
);
|
|
7930
|
+
if (openBraceDepth(text) > 0) {
|
|
7931
|
+
assembly.unresolvedInsideSelection = true;
|
|
7932
|
+
}
|
|
7933
|
+
} else {
|
|
7934
|
+
text += `
|
|
7935
|
+
${spliced}
|
|
7936
|
+
`;
|
|
7937
|
+
}
|
|
7938
|
+
text += span.getLiteral().getLiteralText();
|
|
7939
|
+
}
|
|
7940
|
+
return text;
|
|
7941
|
+
}
|
|
7942
|
+
function openBraceDepth(text) {
|
|
7943
|
+
let depth = 0;
|
|
7944
|
+
for (const char of text) {
|
|
7945
|
+
if (char === "{") {
|
|
7946
|
+
depth += 1;
|
|
7947
|
+
} else if (char === "}") {
|
|
7948
|
+
depth -= 1;
|
|
7949
|
+
}
|
|
7950
|
+
}
|
|
7951
|
+
return depth;
|
|
7952
|
+
}
|
|
7953
|
+
function interpolatedDocumentText(expr, assembly) {
|
|
7954
|
+
const stripped = stripDocumentNodeCasts(expr);
|
|
7955
|
+
const inline = documentTextFromExpression(stripped, assembly);
|
|
7412
7956
|
if (inline !== null) {
|
|
7413
|
-
return
|
|
7957
|
+
return inline;
|
|
7414
7958
|
}
|
|
7415
|
-
const
|
|
7416
|
-
if (
|
|
7417
|
-
return
|
|
7959
|
+
const named2 = resolveGqlTemplateText(stripped, assembly);
|
|
7960
|
+
if (named2 !== null) {
|
|
7961
|
+
return named2;
|
|
7418
7962
|
}
|
|
7419
7963
|
const objectDoc = resolveTypedDocumentSource(stripped);
|
|
7420
7964
|
if (objectDoc !== null) {
|
|
7421
|
-
return
|
|
7965
|
+
return objectDoc;
|
|
7422
7966
|
}
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7967
|
+
return resolveThroughFacts(stripped, assembly);
|
|
7968
|
+
}
|
|
7969
|
+
function resolveGraphqlDocument(arg, resolution) {
|
|
7970
|
+
const assembly = startAssembly(resolution);
|
|
7971
|
+
const stripped = stripDocumentNodeCasts(arg);
|
|
7972
|
+
const text = documentTextFromExpression(stripped, assembly) ?? resolveGqlTemplateText(stripped, assembly) ?? resolveTypedDocumentSource(stripped) ?? resolveThroughFacts(stripped, assembly);
|
|
7973
|
+
if (text !== null) {
|
|
7974
|
+
return assembledDocumentResolution(text, stripped, assembly);
|
|
7426
7975
|
}
|
|
7427
7976
|
return resolveTypedDocumentHeader(stripped);
|
|
7428
7977
|
}
|
|
7429
|
-
function
|
|
7978
|
+
function assembledDocumentResolution(text, arg, assembly) {
|
|
7979
|
+
const interpolations = assembly.unresolvedInterpolations;
|
|
7980
|
+
if (assembly.unresolvedInsideSelection) {
|
|
7981
|
+
const header = parseGraphqlOperation(text);
|
|
7982
|
+
return {
|
|
7983
|
+
...header !== null ? { operationType: header.operationType } : {},
|
|
7984
|
+
...header?.operationName !== void 0 ? { operationName: header.operationName } : {},
|
|
7985
|
+
unresolved: {
|
|
7986
|
+
reference: singleLine(arg.getText()),
|
|
7987
|
+
reason: `interpolated ${describeInterpolations(interpolations)} inside a selection set did not resolve to a GraphQL document, so what the operation selects is not statically written`
|
|
7988
|
+
}
|
|
7989
|
+
};
|
|
7990
|
+
}
|
|
7991
|
+
const dangling = danglingFragmentSpreads(text);
|
|
7992
|
+
if (dangling === null) {
|
|
7993
|
+
if (interpolations.length === 0) {
|
|
7994
|
+
return { document: text };
|
|
7995
|
+
}
|
|
7996
|
+
return {
|
|
7997
|
+
unresolved: {
|
|
7998
|
+
reference: singleLine(arg.getText()),
|
|
7999
|
+
reason: `the document did not parse after dropping interpolated ${describeInterpolations(interpolations)} that resolved to no GraphQL document`
|
|
8000
|
+
}
|
|
8001
|
+
};
|
|
8002
|
+
}
|
|
8003
|
+
if (dangling.length > 0) {
|
|
8004
|
+
return { document: text, unresolvedFragments: dangling };
|
|
8005
|
+
}
|
|
8006
|
+
if (interpolations.length > 0) {
|
|
8007
|
+
return {
|
|
8008
|
+
document: text,
|
|
8009
|
+
unresolved: {
|
|
8010
|
+
reference: singleLine(arg.getText()),
|
|
8011
|
+
reason: `interpolated ${describeInterpolations(interpolations)} did not resolve to a GraphQL document, so whatever it contributes is not part of the stored document`
|
|
8012
|
+
}
|
|
8013
|
+
};
|
|
8014
|
+
}
|
|
8015
|
+
return { document: text };
|
|
8016
|
+
}
|
|
8017
|
+
function describeInterpolations(interpolations) {
|
|
8018
|
+
const quoted = interpolations.map((text) => `\`${text}\``).join(", ");
|
|
8019
|
+
return interpolations.length === 1 ? `expression ${quoted}` : `expressions ${quoted}`;
|
|
8020
|
+
}
|
|
8021
|
+
function danglingFragmentSpreads(text) {
|
|
8022
|
+
let doc;
|
|
8023
|
+
try {
|
|
8024
|
+
doc = graphqlParse(text);
|
|
8025
|
+
} catch {
|
|
8026
|
+
return null;
|
|
8027
|
+
}
|
|
8028
|
+
const defined = /* @__PURE__ */ new Set();
|
|
8029
|
+
for (const def of doc.definitions) {
|
|
8030
|
+
if (def.kind === GraphqlKind.FRAGMENT_DEFINITION) {
|
|
8031
|
+
defined.add(def.name.value);
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
const dangling = /* @__PURE__ */ new Set();
|
|
8035
|
+
for (const def of doc.definitions) {
|
|
8036
|
+
if (def.kind === GraphqlKind.OPERATION_DEFINITION || def.kind === GraphqlKind.FRAGMENT_DEFINITION) {
|
|
8037
|
+
collectDanglingSpreads(def.selectionSet, defined, dangling);
|
|
8038
|
+
}
|
|
8039
|
+
}
|
|
8040
|
+
return [...dangling].sort();
|
|
8041
|
+
}
|
|
8042
|
+
function collectDanglingSpreads(selectionSet, defined, dangling) {
|
|
8043
|
+
for (const selection of selectionSet.selections) {
|
|
8044
|
+
if (selection.kind === GraphqlKind.FRAGMENT_SPREAD) {
|
|
8045
|
+
if (!defined.has(selection.name.value)) {
|
|
8046
|
+
dangling.add(selection.name.value);
|
|
8047
|
+
}
|
|
8048
|
+
continue;
|
|
8049
|
+
}
|
|
8050
|
+
if (selection.selectionSet !== void 0) {
|
|
8051
|
+
collectDanglingSpreads(selection.selectionSet, defined, dangling);
|
|
8052
|
+
}
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
function documentTextFromExpression(node, assembly) {
|
|
7430
8056
|
if (Node35.isTaggedTemplateExpression(node)) {
|
|
7431
8057
|
if (!isDocumentTag(node.getTag())) {
|
|
7432
8058
|
return null;
|
|
7433
8059
|
}
|
|
7434
|
-
|
|
8060
|
+
if (assembly.seen.has(node)) {
|
|
8061
|
+
return "";
|
|
8062
|
+
}
|
|
8063
|
+
assembly.seen.add(node);
|
|
8064
|
+
return assembledTemplateText(node.getTemplate(), assembly);
|
|
7435
8065
|
}
|
|
7436
8066
|
if (!Node35.isCallExpression(node)) {
|
|
7437
8067
|
return null;
|
|
@@ -7447,7 +8077,11 @@ function documentTextFromExpression(node) {
|
|
|
7447
8077
|
if (!Node35.isNoSubstitutionTemplateLiteral(template) && !Node35.isTemplateExpression(template)) {
|
|
7448
8078
|
return null;
|
|
7449
8079
|
}
|
|
7450
|
-
|
|
8080
|
+
if (assembly.seen.has(node)) {
|
|
8081
|
+
return "";
|
|
8082
|
+
}
|
|
8083
|
+
assembly.seen.add(node);
|
|
8084
|
+
return assembledTemplateText(template, assembly);
|
|
7451
8085
|
}
|
|
7452
8086
|
function isDocumentTag(tag) {
|
|
7453
8087
|
if (!Node35.isIdentifier(tag)) {
|
|
@@ -7467,15 +8101,15 @@ function isDocumentTag(tag) {
|
|
|
7467
8101
|
}
|
|
7468
8102
|
return false;
|
|
7469
8103
|
}
|
|
7470
|
-
function resolveThroughFacts(arg,
|
|
7471
|
-
if (resolution === void 0 || !Node35.isIdentifier(arg)) {
|
|
8104
|
+
function resolveThroughFacts(arg, assembly) {
|
|
8105
|
+
if (assembly.resolution === void 0 || !Node35.isIdentifier(arg)) {
|
|
7472
8106
|
return null;
|
|
7473
8107
|
}
|
|
7474
|
-
const written = resolution.resolveWrittenValue(arg);
|
|
8108
|
+
const written = assembly.resolution.resolveWrittenValue(arg);
|
|
7475
8109
|
if (written === null) {
|
|
7476
8110
|
return null;
|
|
7477
8111
|
}
|
|
7478
|
-
const text = documentTextFromExpression(written);
|
|
8112
|
+
const text = documentTextFromExpression(written, assembly);
|
|
7479
8113
|
if (text !== null) {
|
|
7480
8114
|
return text;
|
|
7481
8115
|
}
|
|
@@ -7488,7 +8122,13 @@ function operationInfoFromResolution(resolution, callOperationType) {
|
|
|
7488
8122
|
return null;
|
|
7489
8123
|
}
|
|
7490
8124
|
const operationType = operation.operationName !== void 0 ? operation.operationType : callOperationType;
|
|
7491
|
-
return {
|
|
8125
|
+
return {
|
|
8126
|
+
...operation,
|
|
8127
|
+
operationType,
|
|
8128
|
+
document: resolution.document,
|
|
8129
|
+
...resolution.unresolvedFragments !== void 0 ? { unresolvedFragments: resolution.unresolvedFragments } : {},
|
|
8130
|
+
...resolution.unresolved !== void 0 ? { unresolved: resolution.unresolved } : {}
|
|
8131
|
+
};
|
|
7492
8132
|
}
|
|
7493
8133
|
return {
|
|
7494
8134
|
operationType: resolution.operationType ?? callOperationType,
|
|
@@ -7530,8 +8170,8 @@ function importedVariableInitializers(identifier) {
|
|
|
7530
8170
|
}
|
|
7531
8171
|
return inits;
|
|
7532
8172
|
}
|
|
7533
|
-
function resolveGqlTemplateText(arg) {
|
|
7534
|
-
const direct = documentTextFromExpression(arg);
|
|
8173
|
+
function resolveGqlTemplateText(arg, assembly) {
|
|
8174
|
+
const direct = documentTextFromExpression(arg, assembly);
|
|
7535
8175
|
if (direct !== null) {
|
|
7536
8176
|
return direct;
|
|
7537
8177
|
}
|
|
@@ -7551,7 +8191,10 @@ function resolveGqlTemplateText(arg) {
|
|
|
7551
8191
|
}
|
|
7552
8192
|
}
|
|
7553
8193
|
for (const init of importedVariableInitializers(arg)) {
|
|
7554
|
-
const text = documentTextFromExpression(
|
|
8194
|
+
const text = documentTextFromExpression(
|
|
8195
|
+
stripDocumentNodeCasts(init),
|
|
8196
|
+
assembly
|
|
8197
|
+
);
|
|
7555
8198
|
if (text !== null) {
|
|
7556
8199
|
return text;
|
|
7557
8200
|
}
|
|
@@ -8139,14 +8782,14 @@ function unitForJsxRoute(node, match, routeNames, kind, resolution) {
|
|
|
8139
8782
|
}
|
|
8140
8783
|
return routeUnit(node, kind, match.method, resolved.path, target, resolution);
|
|
8141
8784
|
}
|
|
8142
|
-
function routeUnit(at, kind, method,
|
|
8143
|
-
const routeInfo = { method, path:
|
|
8785
|
+
function routeUnit(at, kind, method, path12, target, resolution) {
|
|
8786
|
+
const routeInfo = { method, path: path12 };
|
|
8144
8787
|
if (target.kind === "unreadable") {
|
|
8145
8788
|
return {
|
|
8146
8789
|
func: null,
|
|
8147
8790
|
announcedAt: at,
|
|
8148
8791
|
kind,
|
|
8149
|
-
name:
|
|
8792
|
+
name: path12,
|
|
8150
8793
|
nameKind: "label",
|
|
8151
8794
|
routeInfo
|
|
8152
8795
|
};
|
|
@@ -9034,9 +9677,9 @@ function withMountPrefix(routeInfo, subjectNode, mountPrefixes) {
|
|
|
9034
9677
|
const prefix = mountPrefixes.effectivePrefixFor(subjectNode);
|
|
9035
9678
|
return prefix === "" ? routeInfo : { ...routeInfo, path: joinMountedPath(prefix, routeInfo.path) };
|
|
9036
9679
|
}
|
|
9037
|
-
function joinMountedPath(prefix,
|
|
9680
|
+
function joinMountedPath(prefix, path12) {
|
|
9038
9681
|
const trimmed = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
9039
|
-
return trimmed === "" ?
|
|
9682
|
+
return trimmed === "" ? path12 : trimmed + path12;
|
|
9040
9683
|
}
|
|
9041
9684
|
function registrationSubjectsOf(sourceFile, importModule, importName) {
|
|
9042
9685
|
let importedLocalName = null;
|
|
@@ -9200,11 +9843,11 @@ function extractRouteInfoFromBinding(call, methodName, binding, resolution) {
|
|
|
9200
9843
|
return null;
|
|
9201
9844
|
}
|
|
9202
9845
|
const method2 = stringProperty(routeObject, binding.method.property);
|
|
9203
|
-
const
|
|
9204
|
-
if (method2 === null ||
|
|
9846
|
+
const path12 = stringProperty(routeObject, binding.path.property);
|
|
9847
|
+
if (method2 === null || path12 === null) {
|
|
9205
9848
|
return null;
|
|
9206
9849
|
}
|
|
9207
|
-
return { method: method2.toUpperCase(), path:
|
|
9850
|
+
return { method: method2.toUpperCase(), path: path12 };
|
|
9208
9851
|
}
|
|
9209
9852
|
if (binding.method.type !== "fromRegistration" || binding.path.type !== "fromRegistration") {
|
|
9210
9853
|
return null;
|
|
@@ -9311,7 +9954,7 @@ function bodyReferencesLoopVar(loop, name) {
|
|
|
9311
9954
|
}
|
|
9312
9955
|
function readRouteSpec(element, shape, resolution) {
|
|
9313
9956
|
let method = null;
|
|
9314
|
-
let
|
|
9957
|
+
let path12 = null;
|
|
9315
9958
|
let handler = null;
|
|
9316
9959
|
for (const prop of element.getProperties()) {
|
|
9317
9960
|
if (Node44.isMethodDeclaration(prop) && prop.getName() === shape.handlerKey) {
|
|
@@ -9329,16 +9972,16 @@ function readRouteSpec(element, shape, resolution) {
|
|
|
9329
9972
|
if (name === shape.methodKey) {
|
|
9330
9973
|
method = readStringLiteralValue(init);
|
|
9331
9974
|
} else if (name === shape.pathKey) {
|
|
9332
|
-
|
|
9975
|
+
path12 = readStringLiteralValue(init);
|
|
9333
9976
|
} else if (name === shape.handlerKey) {
|
|
9334
9977
|
const func = functionValueOf(init, resolution);
|
|
9335
9978
|
handler = func === null ? null : { func, name: handlerName(init) };
|
|
9336
9979
|
}
|
|
9337
9980
|
}
|
|
9338
|
-
if (method === null ||
|
|
9981
|
+
if (method === null || path12 === null || handler === null) {
|
|
9339
9982
|
return null;
|
|
9340
9983
|
}
|
|
9341
|
-
return { method, path:
|
|
9984
|
+
return { method, path: path12, handler: handler.func, handlerName: handler.name };
|
|
9342
9985
|
}
|
|
9343
9986
|
function readStringLiteralValue(node) {
|
|
9344
9987
|
if (Node44.isStringLiteral(node) || Node44.isNoSubstitutionTemplateLiteral(node)) {
|
|
@@ -9367,8 +10010,8 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
9367
10010
|
}
|
|
9368
10011
|
const args = node.getArguments();
|
|
9369
10012
|
for (const reg of match.registrations) {
|
|
9370
|
-
const
|
|
9371
|
-
if (
|
|
10013
|
+
const path12 = substitutePath(reg.pathTemplate, args);
|
|
10014
|
+
if (path12 === null) {
|
|
9372
10015
|
continue;
|
|
9373
10016
|
}
|
|
9374
10017
|
const handler = resolveHandler(reg.handlerArg, args, resolution);
|
|
@@ -9381,7 +10024,7 @@ function discoverRegistrationTemplates(sourceFile, match, kind, resolution) {
|
|
|
9381
10024
|
name: handler.name,
|
|
9382
10025
|
routeInfo: {
|
|
9383
10026
|
method: reg.method.toUpperCase(),
|
|
9384
|
-
path:
|
|
10027
|
+
path: path12
|
|
9385
10028
|
}
|
|
9386
10029
|
});
|
|
9387
10030
|
}
|
|
@@ -9550,7 +10193,10 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
|
|
|
9550
10193
|
resolverInfo: {
|
|
9551
10194
|
typeName,
|
|
9552
10195
|
fieldName,
|
|
9553
|
-
...schemaSdl !== null ? {
|
|
10196
|
+
...schemaSdl !== null ? {
|
|
10197
|
+
schemaSdl,
|
|
10198
|
+
schemaDocument: config.getSourceFile().getFilePath()
|
|
10199
|
+
} : {}
|
|
9554
10200
|
}
|
|
9555
10201
|
});
|
|
9556
10202
|
}
|
|
@@ -9747,7 +10393,15 @@ function discoverUnits(sourceFile, patterns, resolution, mountPrefixes) {
|
|
|
9747
10393
|
}
|
|
9748
10394
|
|
|
9749
10395
|
// src/discovery/mountPrefix.ts
|
|
9750
|
-
var NO_MOUNTS = {
|
|
10396
|
+
var NO_MOUNTS = {
|
|
10397
|
+
// Recorded even with no mounts anywhere: a mount added later in some
|
|
10398
|
+
// other file changes this router's prefix without touching its file.
|
|
10399
|
+
effectivePrefixFor: (routerNode) => {
|
|
10400
|
+
recordMountPrefix(nodeId(routerNode), "");
|
|
10401
|
+
return "";
|
|
10402
|
+
},
|
|
10403
|
+
prefixForId: () => ""
|
|
10404
|
+
};
|
|
9751
10405
|
function buildMountPrefixIndex(packsByFile, resolution) {
|
|
9752
10406
|
const subjectIdsByPack = /* @__PURE__ */ new Map();
|
|
9753
10407
|
const mountWorkByPack = /* @__PURE__ */ new Map();
|
|
@@ -9804,10 +10458,15 @@ function buildMountPrefixIndex(packsByFile, resolution) {
|
|
|
9804
10458
|
return NO_MOUNTS;
|
|
9805
10459
|
}
|
|
9806
10460
|
const memo = /* @__PURE__ */ new Map();
|
|
10461
|
+
const byId = (childId) => resolvePrefix(edgesByChild, memo, childId, /* @__PURE__ */ new Set()) ?? "";
|
|
9807
10462
|
return {
|
|
9808
10463
|
effectivePrefixFor(routerNode) {
|
|
9809
|
-
|
|
9810
|
-
|
|
10464
|
+
const childId = nodeId(routerNode);
|
|
10465
|
+
const prefix = byId(childId);
|
|
10466
|
+
recordMountPrefix(childId, prefix);
|
|
10467
|
+
return prefix;
|
|
10468
|
+
},
|
|
10469
|
+
prefixForId: byId
|
|
9811
10470
|
};
|
|
9812
10471
|
}
|
|
9813
10472
|
function recordEdge(edgesByChild, candidate) {
|
|
@@ -10051,10 +10710,12 @@ import {
|
|
|
10051
10710
|
deriveOnDemand,
|
|
10052
10711
|
evaluate as evaluate2,
|
|
10053
10712
|
lit as lit2,
|
|
10713
|
+
proofOf,
|
|
10054
10714
|
rule as rule2,
|
|
10055
10715
|
tupleKey,
|
|
10056
10716
|
tupleKeyParts,
|
|
10057
|
-
variable as v2
|
|
10717
|
+
variable as v2,
|
|
10718
|
+
witnesses
|
|
10058
10719
|
} from "@suss/datalog";
|
|
10059
10720
|
import {
|
|
10060
10721
|
ANSWER_RELATIONS,
|
|
@@ -10068,7 +10729,8 @@ var JS_RULES = [
|
|
|
10068
10729
|
rule2(
|
|
10069
10730
|
"stepsTo",
|
|
10070
10731
|
[v2("r"), v2("t"), VALUE_STEP],
|
|
10071
|
-
[lit2("bindCall", v2("r"), v2("t"))]
|
|
10732
|
+
[lit2("bindCall", v2("r"), v2("t"))],
|
|
10733
|
+
"bind"
|
|
10072
10734
|
)
|
|
10073
10735
|
];
|
|
10074
10736
|
var RESOLUTION_PROGRAM = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? {
|
|
@@ -10078,6 +10740,15 @@ var RESOLUTION_PROGRAM = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? {
|
|
|
10078
10740
|
[...SHARED_RULES, ...JS_RULES, ...RESOLUTION_QUESTIONS],
|
|
10079
10741
|
ANSWER_RELATIONS
|
|
10080
10742
|
);
|
|
10743
|
+
var WITNESS_RULES = [...SHARED_RULES, ...JS_RULES];
|
|
10744
|
+
var NOT_BASE_FACTS = /* @__PURE__ */ new Set([
|
|
10745
|
+
...[...SHARED_RULES, ...JS_RULES, ...RESOLUTION_QUESTIONS].map(
|
|
10746
|
+
(r) => r.head.relation
|
|
10747
|
+
),
|
|
10748
|
+
...RESOLUTION_PROGRAM.rules.map((r) => r.head.relation),
|
|
10749
|
+
"wanted",
|
|
10750
|
+
"wantedOrigin"
|
|
10751
|
+
]);
|
|
10081
10752
|
var QUERY_FACTS = RESOLUTION_PROGRAM.demandDriven.length === 0 ? [] : [...RESOLUTION_PROGRAM.demandDriven, "wanted", "wantedOrigin"];
|
|
10082
10753
|
var MAX_MODULE_HOPS = 6;
|
|
10083
10754
|
var ResolutionStore = class {
|
|
@@ -10086,6 +10757,8 @@ var ResolutionStore = class {
|
|
|
10086
10757
|
fullyExtracted = /* @__PURE__ */ new Set();
|
|
10087
10758
|
seededValues = /* @__PURE__ */ new Set();
|
|
10088
10759
|
importedNames = /* @__PURE__ */ new Map();
|
|
10760
|
+
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
10761
|
+
lastQueryWalked = [];
|
|
10089
10762
|
declarations = /* @__PURE__ */ new Map();
|
|
10090
10763
|
graph = new ModuleGraph();
|
|
10091
10764
|
stale = true;
|
|
@@ -10103,13 +10776,64 @@ var ResolutionStore = class {
|
|
|
10103
10776
|
* the walk never reaches on its own.
|
|
10104
10777
|
*/
|
|
10105
10778
|
resolveCallable(value, alsoFrom) {
|
|
10779
|
+
const sources = this.resolveCallableSources(value, alsoFrom);
|
|
10780
|
+
const only = sources[0];
|
|
10781
|
+
return sources.length === 1 && only !== void 0 ? only : null;
|
|
10782
|
+
}
|
|
10783
|
+
/**
|
|
10784
|
+
* Every function the value comes down to. One is the answer
|
|
10785
|
+
* `resolveCallable` gives; several is a value with more than one
|
|
10786
|
+
* possible source, which a caller says at the site rather than
|
|
10787
|
+
* folding into the same nothing as a chain that went nowhere.
|
|
10788
|
+
*/
|
|
10789
|
+
resolveCallableSources(value, alsoFrom) {
|
|
10106
10790
|
const target = factKeyOf(value);
|
|
10107
10791
|
return this.resolveByWaves(
|
|
10108
10792
|
target,
|
|
10109
10793
|
"wanted",
|
|
10110
|
-
() => this.
|
|
10794
|
+
() => this.lookupSources(target),
|
|
10111
10795
|
alsoFrom
|
|
10796
|
+
) ?? [];
|
|
10797
|
+
}
|
|
10798
|
+
/**
|
|
10799
|
+
* The witness proof behind `resolveCallable`'s answer. Resolves the
|
|
10800
|
+
* value first, which walks files and extracts facts in the usual
|
|
10801
|
+
* waves, then re-evaluates the rules over those base facts under the
|
|
10802
|
+
* witness algebra and rebuilds the proof of the answer. Null when
|
|
10803
|
+
* the value does not resolve at all.
|
|
10804
|
+
*/
|
|
10805
|
+
explainCallable(value, options = {}) {
|
|
10806
|
+
const resolved = this.resolveCallable(value, options.alsoFrom);
|
|
10807
|
+
if (resolved === null) {
|
|
10808
|
+
return null;
|
|
10809
|
+
}
|
|
10810
|
+
const proofDb = new Database2();
|
|
10811
|
+
let baseFacts = 0;
|
|
10812
|
+
for (const relation of this.db.relationNames()) {
|
|
10813
|
+
if (NOT_BASE_FACTS.has(relation)) {
|
|
10814
|
+
continue;
|
|
10815
|
+
}
|
|
10816
|
+
for (const tuple of this.db.facts(relation)) {
|
|
10817
|
+
proofDb.add(relation, tuple);
|
|
10818
|
+
baseFacts++;
|
|
10819
|
+
}
|
|
10820
|
+
}
|
|
10821
|
+
const started = performance.now();
|
|
10822
|
+
evaluate2(proofDb, WITNESS_RULES, witnesses);
|
|
10823
|
+
const evaluateMs = performance.now() - started;
|
|
10824
|
+
const derivedFacts = proofDb.relationNames().reduce((count, relation) => count + proofDb.size(relation), 0) - baseFacts;
|
|
10825
|
+
const proof = proofOf(
|
|
10826
|
+
proofDb,
|
|
10827
|
+
"resolves",
|
|
10828
|
+
[nodeId(factKeyOf(value)), nodeId(resolved)],
|
|
10829
|
+
options.maxDepth === void 0 ? {} : { maxDepth: options.maxDepth }
|
|
10112
10830
|
);
|
|
10831
|
+
return {
|
|
10832
|
+
target: resolved,
|
|
10833
|
+
proof,
|
|
10834
|
+
nodeFor: (atom) => this.table.byId.get(String(atom)),
|
|
10835
|
+
stats: { baseFacts, derivedFacts, evaluateMs }
|
|
10836
|
+
};
|
|
10113
10837
|
}
|
|
10114
10838
|
resolveObject(value) {
|
|
10115
10839
|
const target = factKeyOf(value);
|
|
@@ -10146,7 +10870,10 @@ var ResolutionStore = class {
|
|
|
10146
10870
|
const declaration = `${nodeId(refersTo)}|${modules.join(",")}`;
|
|
10147
10871
|
const cached = this.importedNames.get(declaration);
|
|
10148
10872
|
if (cached !== void 0) {
|
|
10149
|
-
|
|
10873
|
+
for (const walkedPath of cached.walked) {
|
|
10874
|
+
recordFileDependency(walkedPath);
|
|
10875
|
+
}
|
|
10876
|
+
return cached.names;
|
|
10150
10877
|
}
|
|
10151
10878
|
const target = factKeyOf(value);
|
|
10152
10879
|
const found = this.resolveByWaves(
|
|
@@ -10154,7 +10881,10 @@ var ResolutionStore = class {
|
|
|
10154
10881
|
"wantedOrigin",
|
|
10155
10882
|
() => this.lookupImportedNames(target, modules)
|
|
10156
10883
|
) ?? [];
|
|
10157
|
-
this.importedNames.set(declaration,
|
|
10884
|
+
this.importedNames.set(declaration, {
|
|
10885
|
+
names: found,
|
|
10886
|
+
walked: [...this.lastQueryWalked]
|
|
10887
|
+
});
|
|
10158
10888
|
return found;
|
|
10159
10889
|
}
|
|
10160
10890
|
/**
|
|
@@ -10188,6 +10918,7 @@ var ResolutionStore = class {
|
|
|
10188
10918
|
this.wantValue(question, value);
|
|
10189
10919
|
this.seedValue(value);
|
|
10190
10920
|
const walked = /* @__PURE__ */ new Set();
|
|
10921
|
+
this.lastQueryWalked = [];
|
|
10191
10922
|
let frontier = alsoFrom === void 0 ? [value.getSourceFile()] : [value.getSourceFile(), alsoFrom];
|
|
10192
10923
|
for (let hop = 0; hop <= MAX_MODULE_HOPS; hop++) {
|
|
10193
10924
|
const next = [];
|
|
@@ -10196,6 +10927,8 @@ var ResolutionStore = class {
|
|
|
10196
10927
|
continue;
|
|
10197
10928
|
}
|
|
10198
10929
|
walked.add(sourceFile.getFilePath());
|
|
10930
|
+
this.lastQueryWalked.push(sourceFile.getFilePath());
|
|
10931
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
10199
10932
|
this.extractFile(sourceFile);
|
|
10200
10933
|
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
10201
10934
|
}
|
|
@@ -10223,7 +10956,7 @@ var ResolutionStore = class {
|
|
|
10223
10956
|
this.stale = false;
|
|
10224
10957
|
}
|
|
10225
10958
|
wantValue(question, value) {
|
|
10226
|
-
if (this.db.add(question, [nodeId(value)])) {
|
|
10959
|
+
if (this.db.add(question, [nodeId(value)]) === "added") {
|
|
10227
10960
|
this.stale = true;
|
|
10228
10961
|
}
|
|
10229
10962
|
}
|
|
@@ -10287,10 +11020,12 @@ var ResolutionStore = class {
|
|
|
10287
11020
|
return this.graph.filesReachingAnyPackage(fileSets);
|
|
10288
11021
|
}
|
|
10289
11022
|
/**
|
|
10290
|
-
*
|
|
10291
|
-
*
|
|
11023
|
+
* Null keeps the wave walk widening; any candidate at all ends it,
|
|
11024
|
+
* since more files can only add candidates, never take one away. The
|
|
11025
|
+
* single-answer policy stays with the callers: picking one of two
|
|
11026
|
+
* would make the result depend on the order the facts came in.
|
|
10292
11027
|
*/
|
|
10293
|
-
|
|
11028
|
+
lookupSources(value) {
|
|
10294
11029
|
this.derive();
|
|
10295
11030
|
const candidates = /* @__PURE__ */ new Set();
|
|
10296
11031
|
for (const target of this.answersFor("wantedResolves", nodeId(value))) {
|
|
@@ -10302,10 +11037,7 @@ var ResolutionStore = class {
|
|
|
10302
11037
|
candidates.add(resolved);
|
|
10303
11038
|
}
|
|
10304
11039
|
}
|
|
10305
|
-
|
|
10306
|
-
return null;
|
|
10307
|
-
}
|
|
10308
|
-
return [...candidates][0];
|
|
11040
|
+
return candidates.size === 0 ? null : [...candidates];
|
|
10309
11041
|
}
|
|
10310
11042
|
derive() {
|
|
10311
11043
|
if (!this.stale) {
|
|
@@ -10495,6 +11227,27 @@ function moduleInitSummary(sourceFile, effects, options) {
|
|
|
10495
11227
|
return assembleSummary(raw, options);
|
|
10496
11228
|
}
|
|
10497
11229
|
|
|
11230
|
+
// src/referencedFiles.ts
|
|
11231
|
+
function createReferenceIndex(sourceFiles) {
|
|
11232
|
+
const direct = /* @__PURE__ */ new Map();
|
|
11233
|
+
for (const sourceFile of sourceFiles) {
|
|
11234
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
11235
|
+
for (const target of sourceFile.getReferencedSourceFiles()) {
|
|
11236
|
+
if (target.isInNodeModules() || target.isDeclarationFile()) {
|
|
11237
|
+
continue;
|
|
11238
|
+
}
|
|
11239
|
+
referenced.add(target.getFilePath());
|
|
11240
|
+
}
|
|
11241
|
+
direct.set(sourceFile.getFilePath(), referenced);
|
|
11242
|
+
}
|
|
11243
|
+
const none = /* @__PURE__ */ new Set();
|
|
11244
|
+
return {
|
|
11245
|
+
directOf(filePath) {
|
|
11246
|
+
return direct.get(filePath) ?? none;
|
|
11247
|
+
}
|
|
11248
|
+
};
|
|
11249
|
+
}
|
|
11250
|
+
|
|
10498
11251
|
// src/resolve/boundaryEffects.ts
|
|
10499
11252
|
import { evaluate as evaluate3, lit as lit3, rule as rule3, variable } from "@suss/datalog";
|
|
10500
11253
|
var EFFECT_RULES = [
|
|
@@ -10679,6 +11432,11 @@ function classifyStop(declarations) {
|
|
|
10679
11432
|
if (declarations.length === 0) {
|
|
10680
11433
|
return "noDeclaration";
|
|
10681
11434
|
}
|
|
11435
|
+
for (const declaration of declarations) {
|
|
11436
|
+
if (!isInExternalCode(declaration.getSourceFile())) {
|
|
11437
|
+
recordFileDependency(declaration.getSourceFile().getFilePath());
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
10682
11440
|
if (declarations.every(isExternalDeclaration)) {
|
|
10683
11441
|
return "outsideRun";
|
|
10684
11442
|
}
|
|
@@ -10690,6 +11448,7 @@ function classifyStop(declarations) {
|
|
|
10690
11448
|
var RECORDED = {
|
|
10691
11449
|
noBody: true,
|
|
10692
11450
|
unsettledValue: true,
|
|
11451
|
+
multipleSources: true,
|
|
10693
11452
|
outsideRun: false,
|
|
10694
11453
|
noDeclaration: false
|
|
10695
11454
|
};
|
|
@@ -10699,6 +11458,7 @@ function worthRecording(reason) {
|
|
|
10699
11458
|
var STOP_SENTENCE = {
|
|
10700
11459
|
noBody: (callee) => `The call to ${callee} lands on a declaration with no body, so whatever runs there is missing from this summary`,
|
|
10701
11460
|
unsettledValue: (callee) => `The call to ${callee} goes through a value this run could not settle, so whatever runs there is missing from this summary`,
|
|
11461
|
+
multipleSources: (callee) => `The call to ${callee} reaches a value with more than one possible source, so whatever runs there is missing from this summary`,
|
|
10702
11462
|
outsideRun: (callee) => `The call to ${callee} lands in a package whose source is not in this run, so whatever runs there is missing from this summary`,
|
|
10703
11463
|
noDeclaration: (callee) => `The call to ${callee} has no declaration this run could find, so whatever runs there is missing from this summary`
|
|
10704
11464
|
};
|
|
@@ -10752,24 +11512,6 @@ function resolveDecl(decl, calleeName) {
|
|
|
10752
11512
|
}
|
|
10753
11513
|
return null;
|
|
10754
11514
|
}
|
|
10755
|
-
if (Node50.isImportSpecifier(decl)) {
|
|
10756
|
-
const importDecl = decl.getImportDeclaration();
|
|
10757
|
-
const sf = importDecl.getModuleSpecifierSourceFile();
|
|
10758
|
-
if (sf === void 0 || isInExternalCode(sf)) {
|
|
10759
|
-
return null;
|
|
10760
|
-
}
|
|
10761
|
-
const exported = exportedDeclarationsOf(sf).get(decl.getName());
|
|
10762
|
-
if (exported === void 0) {
|
|
10763
|
-
return null;
|
|
10764
|
-
}
|
|
10765
|
-
for (const ed of exported) {
|
|
10766
|
-
const resolved = resolveDecl(ed, calleeName);
|
|
10767
|
-
if (resolved !== null) {
|
|
10768
|
-
return resolved;
|
|
10769
|
-
}
|
|
10770
|
-
}
|
|
10771
|
-
return null;
|
|
10772
|
-
}
|
|
10773
11515
|
return null;
|
|
10774
11516
|
}
|
|
10775
11517
|
function declName(decl) {
|
|
@@ -10797,20 +11539,27 @@ function resolveCallee(call, calleeName, scan) {
|
|
|
10797
11539
|
}
|
|
10798
11540
|
const callee = call.getExpression();
|
|
10799
11541
|
const symbol = callee.getSymbol();
|
|
10800
|
-
const declarations = symbol
|
|
11542
|
+
const declarations = declarationsBehind(symbol);
|
|
10801
11543
|
for (const decl of declarations) {
|
|
10802
11544
|
const resolved = resolveDecl(decl, calleeName);
|
|
10803
11545
|
if (resolved !== null) {
|
|
10804
11546
|
return { kind: "followed", candidate: resolved };
|
|
10805
11547
|
}
|
|
10806
11548
|
}
|
|
10807
|
-
const
|
|
10808
|
-
if (
|
|
10809
|
-
const
|
|
10810
|
-
const
|
|
11549
|
+
const resolveSources = scan.resolveCallableSources;
|
|
11550
|
+
if (resolveSources !== void 0 && Node50.isPropertyAccessExpression(callee) && declarations.some(isDeclaredShape)) {
|
|
11551
|
+
const sources = resolveSources(callee, scan.reachedFrom);
|
|
11552
|
+
const only = sources.length === 1 ? sources[0] : void 0;
|
|
11553
|
+
const resolved = only === void 0 ? null : resolveDecl(only, calleeName);
|
|
10811
11554
|
if (resolved !== null) {
|
|
10812
11555
|
return { kind: "followed", candidate: resolved };
|
|
10813
11556
|
}
|
|
11557
|
+
if (sources.length > 1) {
|
|
11558
|
+
return {
|
|
11559
|
+
kind: "stopped",
|
|
11560
|
+
stop: { callee: calleeName, reason: "multipleSources" }
|
|
11561
|
+
};
|
|
11562
|
+
}
|
|
10814
11563
|
}
|
|
10815
11564
|
return {
|
|
10816
11565
|
kind: "stopped",
|
|
@@ -10885,7 +11634,7 @@ var REACHABLE_RULES = [
|
|
|
10885
11634
|
)
|
|
10886
11635
|
];
|
|
10887
11636
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
10888
|
-
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS) {
|
|
11637
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = []) {
|
|
10889
11638
|
const lookup = createSourceFileLookup(project);
|
|
10890
11639
|
const db = facts?.db ?? new Database3();
|
|
10891
11640
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -10905,6 +11654,15 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10905
11654
|
db.add("entry", [key]);
|
|
10906
11655
|
}
|
|
10907
11656
|
}
|
|
11657
|
+
const knownKeys = /* @__PURE__ */ new Set();
|
|
11658
|
+
for (const summary of alreadySummarized) {
|
|
11659
|
+
const func = lookup.functionAt(summary.location);
|
|
11660
|
+
if (func !== null) {
|
|
11661
|
+
const key = nodeKey2(func);
|
|
11662
|
+
knownKeys.add(key);
|
|
11663
|
+
facts?.unitKeyBySummary.set(summary, key);
|
|
11664
|
+
}
|
|
11665
|
+
}
|
|
10908
11666
|
for (; ; ) {
|
|
10909
11667
|
evaluate4(db, REACHABLE_RULES);
|
|
10910
11668
|
const frontier = db.facts("reachable").map(([key]) => String(key)).filter((key) => !scanned.has(key));
|
|
@@ -10919,10 +11677,14 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10919
11677
|
}
|
|
10920
11678
|
const cameFrom = reachedFrom.get(key);
|
|
10921
11679
|
const scan = {
|
|
10922
|
-
...recognizers.
|
|
11680
|
+
...recognizers.resolveCallableSources === void 0 ? {} : { resolveCallableSources: recognizers.resolveCallableSources },
|
|
10923
11681
|
...cameFrom === void 0 ? {} : { reachedFrom: cameFrom }
|
|
10924
11682
|
};
|
|
10925
|
-
const { candidates, stops } =
|
|
11683
|
+
const { candidates, stops } = scanWithRecording(
|
|
11684
|
+
key,
|
|
11685
|
+
facts,
|
|
11686
|
+
() => collectReachable(source.func, scan)
|
|
11687
|
+
);
|
|
10926
11688
|
if (stops.length > 0) {
|
|
10927
11689
|
stopsByKey.set(key, stops);
|
|
10928
11690
|
}
|
|
@@ -10941,7 +11703,7 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10941
11703
|
const reached = [];
|
|
10942
11704
|
for (const [keyAtom] of db.facts("reachable")) {
|
|
10943
11705
|
const key = String(keyAtom);
|
|
10944
|
-
if (seedKeys.has(key)) {
|
|
11706
|
+
if (seedKeys.has(key) || knownKeys.has(key)) {
|
|
10945
11707
|
continue;
|
|
10946
11708
|
}
|
|
10947
11709
|
const candidate = functionByKey.get(key);
|
|
@@ -10955,7 +11717,11 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10955
11717
|
candidate.func.getSourceFile().getFilePath()
|
|
10956
11718
|
);
|
|
10957
11719
|
}
|
|
10958
|
-
const summary =
|
|
11720
|
+
const summary = scanWithRecording(
|
|
11721
|
+
key,
|
|
11722
|
+
facts,
|
|
11723
|
+
() => extractReachableSummary(candidate, options, recognizers)
|
|
11724
|
+
);
|
|
10959
11725
|
facts?.unitKeyBySummary.set(summary, key);
|
|
10960
11726
|
rememberSummary(summariesByKey, key, summary);
|
|
10961
11727
|
reached.push(summary);
|
|
@@ -10963,6 +11729,20 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10963
11729
|
recordStops(stopsByKey, summariesByKey, options);
|
|
10964
11730
|
return [...seeds, ...reached];
|
|
10965
11731
|
}
|
|
11732
|
+
function scanWithRecording(key, facts, fn) {
|
|
11733
|
+
const filesByKey = facts?.filesByKey;
|
|
11734
|
+
if (filesByKey === void 0) {
|
|
11735
|
+
return fn();
|
|
11736
|
+
}
|
|
11737
|
+
const sink = createDependencySink();
|
|
11738
|
+
const result = withDependencySink(sink, fn);
|
|
11739
|
+
const bucket = filesByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
11740
|
+
for (const filePath of sink.files) {
|
|
11741
|
+
bucket.add(filePath);
|
|
11742
|
+
}
|
|
11743
|
+
filesByKey.set(key, bucket);
|
|
11744
|
+
return result;
|
|
11745
|
+
}
|
|
10966
11746
|
function rememberSummary(summariesByKey, key, summary) {
|
|
10967
11747
|
const bucket = summariesByKey.get(key) ?? [];
|
|
10968
11748
|
bucket.push(summary);
|
|
@@ -11718,20 +12498,25 @@ import {
|
|
|
11718
12498
|
disambiguateSummaryIds,
|
|
11719
12499
|
summaryIdFromParts
|
|
11720
12500
|
} from "@suss/behavioral-ir";
|
|
12501
|
+
function workspaceRootFor(anchor) {
|
|
12502
|
+
return namedPackageDirAbove(anchor) ?? path7.resolve(anchor);
|
|
12503
|
+
}
|
|
11721
12504
|
function workspaceNameFor(root) {
|
|
11722
12505
|
if (root === void 0) {
|
|
11723
12506
|
return null;
|
|
11724
12507
|
}
|
|
11725
|
-
|
|
12508
|
+
const dir = namedPackageDirAbove(root);
|
|
12509
|
+
if (dir !== null) {
|
|
12510
|
+
return packageNameAt(dir);
|
|
12511
|
+
}
|
|
12512
|
+
const folder = path7.basename(path7.resolve(root));
|
|
12513
|
+
return folder.length > 0 ? folder : null;
|
|
12514
|
+
}
|
|
12515
|
+
function namedPackageDirAbove(start) {
|
|
12516
|
+
let at = path7.resolve(start);
|
|
11726
12517
|
for (let up = 0; up < 12; up += 1) {
|
|
11727
|
-
|
|
11728
|
-
|
|
11729
|
-
fs6.readFileSync(path7.join(at, "package.json"), "utf8")
|
|
11730
|
-
);
|
|
11731
|
-
if (typeof manifest.name === "string" && manifest.name.length > 0) {
|
|
11732
|
-
return manifest.name;
|
|
11733
|
-
}
|
|
11734
|
-
} catch {
|
|
12518
|
+
if (packageNameAt(at) !== null) {
|
|
12519
|
+
return at;
|
|
11735
12520
|
}
|
|
11736
12521
|
const parent = path7.dirname(at);
|
|
11737
12522
|
if (parent === at) {
|
|
@@ -11739,8 +12524,19 @@ function workspaceNameFor(root) {
|
|
|
11739
12524
|
}
|
|
11740
12525
|
at = parent;
|
|
11741
12526
|
}
|
|
11742
|
-
|
|
11743
|
-
|
|
12527
|
+
return null;
|
|
12528
|
+
}
|
|
12529
|
+
function packageNameAt(dir) {
|
|
12530
|
+
try {
|
|
12531
|
+
const manifest = JSON.parse(
|
|
12532
|
+
fs6.readFileSync(path7.join(dir, "package.json"), "utf8")
|
|
12533
|
+
);
|
|
12534
|
+
if (typeof manifest.name === "string" && manifest.name.length > 0) {
|
|
12535
|
+
return manifest.name;
|
|
12536
|
+
}
|
|
12537
|
+
} catch {
|
|
12538
|
+
}
|
|
12539
|
+
return null;
|
|
11744
12540
|
}
|
|
11745
12541
|
function nameSummaries(summaries, args) {
|
|
11746
12542
|
for (const summary of summaries) {
|
|
@@ -12224,6 +13020,36 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
12224
13020
|
function responseAccessorNames(pack, kind) {
|
|
12225
13021
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
12226
13022
|
}
|
|
13023
|
+
var ACCESSOR_FIELD_SEMANTICS = {
|
|
13024
|
+
bodyAccessors: "body",
|
|
13025
|
+
statusAccessors: "statusCode",
|
|
13026
|
+
successAccessors: "statusRange"
|
|
13027
|
+
};
|
|
13028
|
+
function responseAccessors(pack) {
|
|
13029
|
+
const out = {};
|
|
13030
|
+
for (const [field, kind] of Object.entries(ACCESSOR_FIELD_SEMANTICS)) {
|
|
13031
|
+
const names = responseAccessorNames(pack, kind);
|
|
13032
|
+
if (names !== void 0 && names.length > 0) {
|
|
13033
|
+
out[field] = names;
|
|
13034
|
+
}
|
|
13035
|
+
}
|
|
13036
|
+
return out;
|
|
13037
|
+
}
|
|
13038
|
+
var FUNCTION_FALLTHROUGH_TERMINAL = {
|
|
13039
|
+
kind: "return",
|
|
13040
|
+
match: { type: "functionFallthrough" },
|
|
13041
|
+
extraction: {}
|
|
13042
|
+
};
|
|
13043
|
+
function terminalsFor(unit, pack) {
|
|
13044
|
+
const declared = unit.terminals ?? pack.terminals;
|
|
13045
|
+
if (unit.callSite === void 0) {
|
|
13046
|
+
return declared;
|
|
13047
|
+
}
|
|
13048
|
+
if (declared.some((p) => p.match.type === "functionFallthrough")) {
|
|
13049
|
+
return declared;
|
|
13050
|
+
}
|
|
13051
|
+
return [...declared, FUNCTION_FALLTHROUGH_TERMINAL];
|
|
13052
|
+
}
|
|
12227
13053
|
function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers, barriers, resolveWrittenValue) {
|
|
12228
13054
|
const { func, kind, name } = unit;
|
|
12229
13055
|
if (func === null) {
|
|
@@ -12235,7 +13061,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12235
13061
|
);
|
|
12236
13062
|
const extracted = extractRawBranches(
|
|
12237
13063
|
func,
|
|
12238
|
-
unit
|
|
13064
|
+
terminalsFor(unit, pack),
|
|
12239
13065
|
invocationRecognizers,
|
|
12240
13066
|
accessRecognizers,
|
|
12241
13067
|
barriers,
|
|
@@ -12271,8 +13097,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12271
13097
|
}
|
|
12272
13098
|
}
|
|
12273
13099
|
}
|
|
12274
|
-
const
|
|
12275
|
-
const statusAccessors = unit.callSite !== void 0 ? responseAccessorNames(pack, "statusCode") : void 0;
|
|
13100
|
+
const accessors = unit.callSite !== void 0 ? responseAccessors(pack) : {};
|
|
12276
13101
|
return {
|
|
12277
13102
|
identity: {
|
|
12278
13103
|
name,
|
|
@@ -12296,8 +13121,8 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12296
13121
|
bodyContent: bodyContentOf(func),
|
|
12297
13122
|
dependencyCalls: depCalls,
|
|
12298
13123
|
declaredContract: null,
|
|
12299
|
-
...
|
|
12300
|
-
...
|
|
13124
|
+
...accessors,
|
|
13125
|
+
...unit.callSite !== void 0 && pack.failureDelivery !== void 0 ? { failureDelivery: pack.failureDelivery } : {}
|
|
12301
13126
|
};
|
|
12302
13127
|
}
|
|
12303
13128
|
function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
@@ -12310,11 +13135,11 @@ function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
|
12310
13135
|
return null;
|
|
12311
13136
|
}
|
|
12312
13137
|
const method = extractBindingMethod(binding, callSite, pack, resolution);
|
|
12313
|
-
const
|
|
13138
|
+
const path12 = extractBindingPath(binding, callSite, pack, resolution);
|
|
12314
13139
|
return restBinding2({
|
|
12315
13140
|
transport: pack.protocol,
|
|
12316
13141
|
method: method ?? null,
|
|
12317
|
-
path:
|
|
13142
|
+
path: path12 ?? null,
|
|
12318
13143
|
recognition: pack.name
|
|
12319
13144
|
});
|
|
12320
13145
|
}
|
|
@@ -12403,12 +13228,12 @@ function originEndOf(flattened) {
|
|
|
12403
13228
|
const slash = flattened.indexOf("/", opener[0].length);
|
|
12404
13229
|
return slash === -1 ? flattened.length : slash;
|
|
12405
13230
|
}
|
|
12406
|
-
function appendPathText(
|
|
13231
|
+
function appendPathText(path12, text) {
|
|
12407
13232
|
const idx = text.search(/[?#]/);
|
|
12408
13233
|
if (idx === -1) {
|
|
12409
|
-
return { path:
|
|
13234
|
+
return { path: path12 + text, stop: false };
|
|
12410
13235
|
}
|
|
12411
|
-
return { path:
|
|
13236
|
+
return { path: path12 + text.slice(0, idx), stop: true };
|
|
12412
13237
|
}
|
|
12413
13238
|
function parseAbsoluteUrl(text) {
|
|
12414
13239
|
try {
|
|
@@ -12432,8 +13257,8 @@ function pathnameOfAbsoluteLiteral(text) {
|
|
|
12432
13257
|
return stripQueryAndFragment(stripOriginManually(text));
|
|
12433
13258
|
}
|
|
12434
13259
|
function pathFromLiteralUrl(text) {
|
|
12435
|
-
const
|
|
12436
|
-
return
|
|
13260
|
+
const path12 = isAbsoluteUrlLiteral(text) ? pathnameOfAbsoluteLiteral(text) : stripQueryAndFragment(text);
|
|
13261
|
+
return path12 === "" ? void 0 : path12;
|
|
12437
13262
|
}
|
|
12438
13263
|
function pathFromTemplateUrl(arg) {
|
|
12439
13264
|
const headText = arg.getHead().getLiteralText();
|
|
@@ -12441,7 +13266,7 @@ function pathFromTemplateUrl(arg) {
|
|
|
12441
13266
|
const tails = spans.map((span) => span.getLiteral().getLiteralText());
|
|
12442
13267
|
const originEnd = originEndOf([headText, ...tails].join(SUBSTITUTION));
|
|
12443
13268
|
const head = appendPathText("", headText.slice(originEnd));
|
|
12444
|
-
let
|
|
13269
|
+
let path12 = head.path;
|
|
12445
13270
|
let stop = head.stop;
|
|
12446
13271
|
let at = headText.length;
|
|
12447
13272
|
for (let i = 0; i < spans.length && !stop; i++) {
|
|
@@ -12451,18 +13276,18 @@ function pathFromTemplateUrl(arg) {
|
|
|
12451
13276
|
continue;
|
|
12452
13277
|
}
|
|
12453
13278
|
if (at >= originEnd) {
|
|
12454
|
-
|
|
13279
|
+
path12 += `{${placeholderName(span.getExpression())}}`;
|
|
12455
13280
|
}
|
|
12456
13281
|
at += SUBSTITUTION.length;
|
|
12457
13282
|
const appended = appendPathText(
|
|
12458
|
-
|
|
13283
|
+
path12,
|
|
12459
13284
|
tailText.slice(Math.max(0, originEnd - at))
|
|
12460
13285
|
);
|
|
12461
|
-
|
|
13286
|
+
path12 = appended.path;
|
|
12462
13287
|
stop = appended.stop;
|
|
12463
13288
|
at += tailText.length;
|
|
12464
13289
|
}
|
|
12465
|
-
return
|
|
13290
|
+
return path12 === "" ? void 0 : path12;
|
|
12466
13291
|
}
|
|
12467
13292
|
function extractBindingPath(binding, callSite, pack, resolution) {
|
|
12468
13293
|
const p = binding.path;
|
|
@@ -12651,12 +13476,20 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12651
13476
|
if (claimant.pack === pack.name && claimant.file === sourceFile.getFilePath() && tally !== void 0) {
|
|
12652
13477
|
tally.selfCollisions += 1;
|
|
12653
13478
|
}
|
|
13479
|
+
if (claimant.file !== sourceFile.getFilePath()) {
|
|
13480
|
+
recordFileDependency(claimant.file);
|
|
13481
|
+
}
|
|
12654
13482
|
continue;
|
|
12655
13483
|
}
|
|
12656
13484
|
claimed.set(claimKey, {
|
|
12657
13485
|
pack: pack.name,
|
|
12658
13486
|
file: sourceFile.getFilePath()
|
|
12659
13487
|
});
|
|
13488
|
+
recordUnitClaim(claimKey, pack.name);
|
|
13489
|
+
const declaringFile = unit.func?.getSourceFile().getFilePath();
|
|
13490
|
+
if (declaringFile !== void 0 && declaringFile !== sourceFile.getFilePath()) {
|
|
13491
|
+
recordFileDependency(declaringFile);
|
|
13492
|
+
}
|
|
12660
13493
|
unitsWalkedHere += 1;
|
|
12661
13494
|
if (tally !== void 0) {
|
|
12662
13495
|
tally.unitsClaimed += 1;
|
|
@@ -12695,6 +13528,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12695
13528
|
}
|
|
12696
13529
|
if (unit.resolverInfo.schemaSdl !== void 0) {
|
|
12697
13530
|
raw.graphqlSchemaSdl = unit.resolverInfo.schemaSdl;
|
|
13531
|
+
if (unit.resolverInfo.schemaDocument !== void 0) {
|
|
13532
|
+
raw.sourceDocumentLabel = unit.resolverInfo.schemaDocument;
|
|
13533
|
+
}
|
|
12698
13534
|
if (unit.resolverInfo.typeName !== null) {
|
|
12699
13535
|
const contract = deriveGraphqlContract(
|
|
12700
13536
|
unit.resolverInfo.schemaSdl,
|
|
@@ -12730,6 +13566,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12730
13566
|
if (unit.operationInfo.document !== void 0) {
|
|
12731
13567
|
raw.graphqlDocument = unit.operationInfo.document;
|
|
12732
13568
|
}
|
|
13569
|
+
if (unit.operationInfo.unresolvedFragments !== void 0) {
|
|
13570
|
+
raw.graphqlUnresolvedFragments = unit.operationInfo.unresolvedFragments;
|
|
13571
|
+
}
|
|
12733
13572
|
if (unit.operationInfo.unresolved !== void 0) {
|
|
12734
13573
|
raw.graphqlUnresolvedDocument = unit.operationInfo.unresolved;
|
|
12735
13574
|
}
|
|
@@ -12883,6 +13722,37 @@ function fileImporting(project, modulePrefix) {
|
|
|
12883
13722
|
}
|
|
12884
13723
|
return void 0;
|
|
12885
13724
|
}
|
|
13725
|
+
function liftSchemasOntoDocuments(summaries) {
|
|
13726
|
+
const sdlByDocument = /* @__PURE__ */ new Map();
|
|
13727
|
+
for (const summary of summaries) {
|
|
13728
|
+
const label = readSourceDocumentMetadata(summary)?.label;
|
|
13729
|
+
const graphql = readGraphqlMetadata2(summary);
|
|
13730
|
+
if (label === void 0 || graphql?.schemaSdl === void 0) {
|
|
13731
|
+
continue;
|
|
13732
|
+
}
|
|
13733
|
+
sdlByDocument.set(label, graphql.schemaSdl);
|
|
13734
|
+
const { schemaSdl: _movedToTheDocument, ...rest } = graphql;
|
|
13735
|
+
summary.metadata = withGraphqlMetadata2(summary.metadata, rest);
|
|
13736
|
+
}
|
|
13737
|
+
for (const [label, schemaSdl] of sdlByDocument) {
|
|
13738
|
+
summaries.push(schemaDocumentSummary(label, schemaSdl));
|
|
13739
|
+
}
|
|
13740
|
+
}
|
|
13741
|
+
function schemaDocumentSummary(label, schemaSdl) {
|
|
13742
|
+
return {
|
|
13743
|
+
kind: "library",
|
|
13744
|
+
location: { file: label, range: { start: 0, end: 0 }, exportName: null },
|
|
13745
|
+
identity: { name: label, exportPath: null, boundaryBinding: null },
|
|
13746
|
+
inputs: [],
|
|
13747
|
+
transitions: [],
|
|
13748
|
+
gaps: [],
|
|
13749
|
+
confidence: { source: "declared", level: "high" },
|
|
13750
|
+
metadata: withGraphqlMetadata2(
|
|
13751
|
+
withSourceDocumentMetadata(void 0, { label }),
|
|
13752
|
+
{ schemaSdl }
|
|
13753
|
+
)
|
|
13754
|
+
};
|
|
13755
|
+
}
|
|
12886
13756
|
function libraryEnvReadMarker(pack, declared, importer) {
|
|
12887
13757
|
return {
|
|
12888
13758
|
kind: "library",
|
|
@@ -13000,8 +13870,8 @@ function synthesizeCallerSummaries(wrapper, _project, options) {
|
|
|
13000
13870
|
if (pathArg === void 0) {
|
|
13001
13871
|
continue;
|
|
13002
13872
|
}
|
|
13003
|
-
const
|
|
13004
|
-
if (
|
|
13873
|
+
const path12 = literalOrTemplate(pathArg);
|
|
13874
|
+
if (path12 === void 0) {
|
|
13005
13875
|
continue;
|
|
13006
13876
|
}
|
|
13007
13877
|
const callerFunc = enclosingFunction(callExpr);
|
|
@@ -13013,7 +13883,7 @@ function synthesizeCallerSummaries(wrapper, _project, options) {
|
|
|
13013
13883
|
continue;
|
|
13014
13884
|
}
|
|
13015
13885
|
seen.add(dedupKey);
|
|
13016
|
-
out.push(buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
13886
|
+
out.push(buildCallerSummary(wrapper, callerFunc, callExpr, path12, options));
|
|
13017
13887
|
}
|
|
13018
13888
|
return out;
|
|
13019
13889
|
}
|
|
@@ -13065,12 +13935,12 @@ function literalOrTemplate(arg) {
|
|
|
13065
13935
|
return arg.getLiteralValue();
|
|
13066
13936
|
}
|
|
13067
13937
|
if (Node54.isTemplateExpression(arg)) {
|
|
13068
|
-
let
|
|
13938
|
+
let path12 = arg.getHead().getLiteralText();
|
|
13069
13939
|
for (const span of arg.getTemplateSpans()) {
|
|
13070
|
-
|
|
13071
|
-
|
|
13940
|
+
path12 += `{${placeholderName(span.getExpression())}}`;
|
|
13941
|
+
path12 += span.getLiteral().getLiteralText();
|
|
13072
13942
|
}
|
|
13073
|
-
return
|
|
13943
|
+
return path12;
|
|
13074
13944
|
}
|
|
13075
13945
|
return void 0;
|
|
13076
13946
|
}
|
|
@@ -13087,7 +13957,7 @@ function callerName(func) {
|
|
|
13087
13957
|
}
|
|
13088
13958
|
return "anonymous";
|
|
13089
13959
|
}
|
|
13090
|
-
function buildCallerSummary(wrapper, callerFunc, callExpr,
|
|
13960
|
+
function buildCallerSummary(wrapper, callerFunc, callExpr, path12, options) {
|
|
13091
13961
|
const wrapperBinding = wrapper.summary.identity.boundaryBinding;
|
|
13092
13962
|
const wrapperRest = wrapperBinding?.semantics.name === "rest" ? wrapperBinding.semantics : null;
|
|
13093
13963
|
const syntheticPack = {
|
|
@@ -13119,7 +13989,7 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path11, options) {
|
|
|
13119
13989
|
raw.boundaryBinding = restBinding2({
|
|
13120
13990
|
transport: wrapperBinding?.transport ?? "http",
|
|
13121
13991
|
method: wrapperRest?.method ?? null,
|
|
13122
|
-
path:
|
|
13992
|
+
path: path12,
|
|
13123
13993
|
recognition: wrapperBinding?.recognition ?? "unknown"
|
|
13124
13994
|
});
|
|
13125
13995
|
const summary = assembleSummary3(raw, options);
|
|
@@ -13133,8 +14003,8 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path11, options) {
|
|
|
13133
14003
|
summary.confidence = { source: "inferred_static", level: "low" };
|
|
13134
14004
|
return summary;
|
|
13135
14005
|
}
|
|
13136
|
-
function named(summaries, workspace) {
|
|
13137
|
-
const projectRoot = commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
14006
|
+
function named(summaries, workspace, runRoot) {
|
|
14007
|
+
const projectRoot = runRoot ?? commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
13138
14008
|
nameSummaries(summaries, {
|
|
13139
14009
|
workspace: workspace ?? workspaceNameFor(projectRoot),
|
|
13140
14010
|
projectRoot
|
|
@@ -13192,6 +14062,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13192
14062
|
skipAddingFilesFromTsConfig: true
|
|
13193
14063
|
} : { skipAddingFilesFromTsConfig: true }
|
|
13194
14064
|
);
|
|
14065
|
+
const runRoot = config.projectRoot ?? (config.tsConfigFilePath !== void 0 ? workspaceRootFor(path9.dirname(config.tsConfigFilePath)) : void 0);
|
|
13195
14066
|
let lazyBootstrapped = false;
|
|
13196
14067
|
let projectFileSet;
|
|
13197
14068
|
const cacheDir = declineWhenRunFromSource(
|
|
@@ -13232,7 +14103,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13232
14103
|
)
|
|
13233
14104
|
);
|
|
13234
14105
|
}
|
|
13235
|
-
return named(summaries, config.workspace);
|
|
14106
|
+
return named(summaries, config.workspace, runRoot);
|
|
13236
14107
|
},
|
|
13237
14108
|
async extractAll() {
|
|
13238
14109
|
const timer = createTimer();
|
|
@@ -13265,7 +14136,25 @@ function createTypeScriptAdapter(config) {
|
|
|
13265
14136
|
if (config.onTiming !== void 0) {
|
|
13266
14137
|
config.onTiming(timer.report());
|
|
13267
14138
|
}
|
|
13268
|
-
return named(lookup.summaries, config.workspace);
|
|
14139
|
+
return named(lookup.summaries, config.workspace, runRoot);
|
|
14140
|
+
}
|
|
14141
|
+
const plan = lookup.diagnostic.missReason === "files-changed" ? await timer.timeAsync("cache.plan", () => cache.plan(cacheInput)) : null;
|
|
14142
|
+
if (plan !== null && plan.changed.size === 0 && plan.removed.size === 0) {
|
|
14143
|
+
try {
|
|
14144
|
+
await cache.write(
|
|
14145
|
+
cacheInput,
|
|
14146
|
+
plan.allSummaries(),
|
|
14147
|
+
plan.attribution()
|
|
14148
|
+
);
|
|
14149
|
+
} catch {
|
|
14150
|
+
}
|
|
14151
|
+
if (config.onCacheDiagnostic !== void 0) {
|
|
14152
|
+
config.onCacheDiagnostic({ kind: "hit" });
|
|
14153
|
+
}
|
|
14154
|
+
if (config.onTiming !== void 0) {
|
|
14155
|
+
config.onTiming(timer.report());
|
|
14156
|
+
}
|
|
14157
|
+
return named(plan.allSummaries(), config.workspace, runRoot);
|
|
13269
14158
|
}
|
|
13270
14159
|
let candidatePaths = null;
|
|
13271
14160
|
if (lazyEligible) {
|
|
@@ -13296,16 +14185,58 @@ function createTypeScriptAdapter(config) {
|
|
|
13296
14185
|
"mountPrefix",
|
|
13297
14186
|
() => buildMountPrefixIndex(packsByFile, resolution)
|
|
13298
14187
|
);
|
|
14188
|
+
const caching = cacheDir !== null;
|
|
14189
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
14190
|
+
if (plan !== null) {
|
|
14191
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
14192
|
+
for (const [sf, packs] of packsByFile) {
|
|
14193
|
+
packNamesByPath.set(
|
|
14194
|
+
sf.getFilePath(),
|
|
14195
|
+
packs.map((p) => p.name).sort().join(",")
|
|
14196
|
+
);
|
|
14197
|
+
}
|
|
14198
|
+
for (const rootPath of plan.validRoots) {
|
|
14199
|
+
const record = plan.roots.get(rootPath);
|
|
14200
|
+
if (record === void 0) {
|
|
14201
|
+
continue;
|
|
14202
|
+
}
|
|
14203
|
+
if (!mountAssumptionsAgree(record, mountPrefixes)) {
|
|
14204
|
+
continue;
|
|
14205
|
+
}
|
|
14206
|
+
const stored = [...record.packs].sort().join(",");
|
|
14207
|
+
if ((packNamesByPath.get(rootPath) ?? "") !== stored) {
|
|
14208
|
+
continue;
|
|
14209
|
+
}
|
|
14210
|
+
validRoots.add(rootPath);
|
|
14211
|
+
}
|
|
14212
|
+
}
|
|
14213
|
+
const reused = plan !== null && validRoots.size > 0 ? plan.reuse(validRoots) : null;
|
|
13299
14214
|
const claimedUnits = /* @__PURE__ */ new Map();
|
|
14215
|
+
if (reused !== null && plan !== null) {
|
|
14216
|
+
for (const rootPath of validRoots) {
|
|
14217
|
+
for (const claim of plan.roots.get(rootPath)?.claims ?? []) {
|
|
14218
|
+
claimedUnits.set(claim.key, { pack: claim.pack, file: rootPath });
|
|
14219
|
+
}
|
|
14220
|
+
}
|
|
14221
|
+
}
|
|
14222
|
+
const walkList = reused === null ? sourceFiles : sourceFiles.filter((sf) => !validRoots.has(sf.getFilePath()));
|
|
14223
|
+
const sinkByRoot = /* @__PURE__ */ new Map();
|
|
14224
|
+
const ownersBySummary = /* @__PURE__ */ new Map();
|
|
13300
14225
|
timer.time("extract per-file", () => {
|
|
13301
|
-
for (const sourceFile of
|
|
14226
|
+
for (const sourceFile of walkList) {
|
|
14227
|
+
const rootPath = sourceFile.getFilePath();
|
|
14228
|
+
const sink = createDependencySink();
|
|
14229
|
+
if (caching) {
|
|
14230
|
+
sinkByRoot.set(rootPath, sink);
|
|
14231
|
+
}
|
|
13302
14232
|
const applicablePacks = packsByFile.get(sourceFile);
|
|
13303
14233
|
if (applicablePacks === void 0) {
|
|
13304
14234
|
continue;
|
|
13305
14235
|
}
|
|
13306
14236
|
try {
|
|
13307
|
-
|
|
13308
|
-
|
|
14237
|
+
const walked = withDependencySink(
|
|
14238
|
+
sink,
|
|
14239
|
+
() => extractFromSourceFile(
|
|
13309
14240
|
sourceFile,
|
|
13310
14241
|
applicablePacks,
|
|
13311
14242
|
claimedUnits,
|
|
@@ -13315,6 +14246,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13315
14246
|
mountPrefixes
|
|
13316
14247
|
)
|
|
13317
14248
|
);
|
|
14249
|
+
for (const summary of walked) {
|
|
14250
|
+
ownersBySummary.set(summary, /* @__PURE__ */ new Set([rootPath]));
|
|
14251
|
+
}
|
|
14252
|
+
summaries.push(...walked);
|
|
13318
14253
|
} catch (error) {
|
|
13319
14254
|
if (!(error instanceof RangeError)) {
|
|
13320
14255
|
throw error;
|
|
@@ -13323,23 +14258,32 @@ function createTypeScriptAdapter(config) {
|
|
|
13323
14258
|
}
|
|
13324
14259
|
}
|
|
13325
14260
|
});
|
|
14261
|
+
const wrapperInput = reused === null ? summaries : [...summaries, ...reused.summaries];
|
|
13326
14262
|
const withWrappers = timer.time(
|
|
13327
14263
|
"expandWrapperCallers",
|
|
13328
|
-
() => expandWrapperCallers(
|
|
14264
|
+
() => expandWrapperCallers(wrapperInput, project, config.extractorOptions)
|
|
13329
14265
|
);
|
|
14266
|
+
const pipeline = reused === null ? withWrappers : [...summaries, ...withWrappers.slice(wrapperInput.length)];
|
|
13330
14267
|
const withSubUnits = timer.time(
|
|
13331
14268
|
"synthesizeSubUnits",
|
|
13332
14269
|
() => synthesizeSubUnits(
|
|
13333
|
-
|
|
14270
|
+
pipeline,
|
|
13334
14271
|
project,
|
|
13335
14272
|
config.frameworks,
|
|
13336
14273
|
config.extractorOptions,
|
|
13337
|
-
tallies
|
|
14274
|
+
tallies,
|
|
14275
|
+
(created, parent) => {
|
|
14276
|
+
const parentOwners = ownersBySummary.get(parent);
|
|
14277
|
+
if (parentOwners !== void 0) {
|
|
14278
|
+
ownersBySummary.set(created, new Set(parentOwners));
|
|
14279
|
+
}
|
|
14280
|
+
}
|
|
13338
14281
|
)
|
|
13339
14282
|
);
|
|
13340
14283
|
const closureFacts = {
|
|
13341
14284
|
db: new Database5(),
|
|
13342
|
-
unitKeyBySummary: /* @__PURE__ */ new Map()
|
|
14285
|
+
unitKeyBySummary: /* @__PURE__ */ new Map(),
|
|
14286
|
+
...caching ? { filesByKey: /* @__PURE__ */ new Map() } : {}
|
|
13343
14287
|
};
|
|
13344
14288
|
const withClosure = config.includeReachable !== false ? timer.time(
|
|
13345
14289
|
"expandReachableClosure",
|
|
@@ -13356,13 +14300,29 @@ function createTypeScriptAdapter(config) {
|
|
|
13356
14300
|
),
|
|
13357
14301
|
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13358
14302
|
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value),
|
|
13359
|
-
|
|
13360
|
-
}
|
|
14303
|
+
resolveCallableSources: (value, alsoFrom) => resolution.resolveCallableSources(value, alsoFrom)
|
|
14304
|
+
},
|
|
14305
|
+
// Reached units the cache already serves emit nothing,
|
|
14306
|
+
// the way a cold run's seeds do not.
|
|
14307
|
+
reused?.summaries ?? []
|
|
13361
14308
|
)
|
|
13362
14309
|
) : withSubUnits;
|
|
14310
|
+
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
14311
|
+
"cache.attributeClosure",
|
|
14312
|
+
() => attributeReachedSummaries(
|
|
14313
|
+
withSubUnits,
|
|
14314
|
+
withClosure.slice(withSubUnits.length),
|
|
14315
|
+
closureFacts,
|
|
14316
|
+
ownersBySummary
|
|
14317
|
+
)
|
|
14318
|
+
) : null;
|
|
14319
|
+
const merged = timer.time(
|
|
14320
|
+
"cache.merge",
|
|
14321
|
+
() => mergeWithReused(reused, withClosure, ownersBySummary)
|
|
14322
|
+
);
|
|
13363
14323
|
const enriched = timer.time(
|
|
13364
14324
|
"enrichRethrows",
|
|
13365
|
-
() => enrichRethrows(
|
|
14325
|
+
() => enrichRethrows(merged.summaries, project, closureFacts)
|
|
13366
14326
|
);
|
|
13367
14327
|
if (config.includeReachable !== false) {
|
|
13368
14328
|
timer.time(
|
|
@@ -13378,6 +14338,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13378
14338
|
"emitLibraryEnvReadMarkers",
|
|
13379
14339
|
() => emitLibraryEnvReadMarkers(enriched, project, config.frameworks)
|
|
13380
14340
|
);
|
|
14341
|
+
timer.time(
|
|
14342
|
+
"liftSchemasOntoDocuments",
|
|
14343
|
+
() => liftSchemasOntoDocuments(enriched)
|
|
14344
|
+
);
|
|
13381
14345
|
timer.time(
|
|
13382
14346
|
"stampGraphqlClientRefs",
|
|
13383
14347
|
() => stampGraphqlClientRefs(
|
|
@@ -13387,12 +14351,41 @@ function createTypeScriptAdapter(config) {
|
|
|
13387
14351
|
resolution
|
|
13388
14352
|
)
|
|
13389
14353
|
);
|
|
14354
|
+
if (config.onCacheDiagnostic !== void 0 && plan !== null) {
|
|
14355
|
+
config.onCacheDiagnostic({
|
|
14356
|
+
kind: "partial",
|
|
14357
|
+
partial: {
|
|
14358
|
+
filesChanged: plan.changed.size,
|
|
14359
|
+
filesRemoved: plan.removed.size,
|
|
14360
|
+
rootsReused: validRoots.size,
|
|
14361
|
+
rootsReextracted: walkList.length,
|
|
14362
|
+
rootsDeclined: plan.rootsDeclined,
|
|
14363
|
+
summariesReused: merged.reusedKept.length
|
|
14364
|
+
}
|
|
14365
|
+
});
|
|
14366
|
+
}
|
|
13390
14367
|
await timer.timeAsync("cache.write", async () => {
|
|
13391
|
-
if (enriched.length === 0) {
|
|
14368
|
+
if (!caching || enriched.length === 0) {
|
|
13392
14369
|
return;
|
|
13393
14370
|
}
|
|
13394
14371
|
try {
|
|
13395
|
-
|
|
14372
|
+
const attribution = buildCacheAttribution({
|
|
14373
|
+
project,
|
|
14374
|
+
plan,
|
|
14375
|
+
validRoots,
|
|
14376
|
+
sinkByRoot,
|
|
14377
|
+
ownersBySummary,
|
|
14378
|
+
closureOwnership,
|
|
14379
|
+
unitKeyBySummary: closureFacts.unitKeyBySummary,
|
|
14380
|
+
filesByKey: closureFacts.filesByKey,
|
|
14381
|
+
packsByFile,
|
|
14382
|
+
reusedKept: merged.reusedKept,
|
|
14383
|
+
reusedOwners: merged.reusedOwners,
|
|
14384
|
+
// Everything after the reused prefix, the passes' own
|
|
14385
|
+
// additions (markers, schema documents) included.
|
|
14386
|
+
fresh: enriched.slice(merged.reusedKept.length)
|
|
14387
|
+
});
|
|
14388
|
+
await cache.write(cacheInput, enriched, attribution);
|
|
13396
14389
|
} catch {
|
|
13397
14390
|
}
|
|
13398
14391
|
});
|
|
@@ -13405,7 +14398,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13405
14398
|
packs: config.frameworks,
|
|
13406
14399
|
tallies,
|
|
13407
14400
|
filesInProject: tsconfigFileList?.length ?? null,
|
|
13408
|
-
filesWalked:
|
|
14401
|
+
filesWalked: walkList.length,
|
|
13409
14402
|
summaries: enriched,
|
|
13410
14403
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
13411
14404
|
projectRoot: commonDirectoryOf(
|
|
@@ -13415,17 +14408,204 @@ function createTypeScriptAdapter(config) {
|
|
|
13415
14408
|
})
|
|
13416
14409
|
);
|
|
13417
14410
|
}
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
13421
|
-
)
|
|
13422
|
-
|
|
13423
|
-
});
|
|
13424
|
-
return enriched;
|
|
14411
|
+
return named(
|
|
14412
|
+
enriched,
|
|
14413
|
+
config.workspace,
|
|
14414
|
+
runRoot ?? commonDirectoryOf(sourceFiles.map((f) => f.getFilePath()))
|
|
14415
|
+
);
|
|
13425
14416
|
}
|
|
13426
14417
|
};
|
|
13427
14418
|
}
|
|
13428
|
-
function
|
|
14419
|
+
function mountAssumptionsAgree(record, index) {
|
|
14420
|
+
return Object.entries(record.mountPrefixes).every(
|
|
14421
|
+
([childId, prefix]) => (index.prefixForId?.(childId) ?? "") === prefix
|
|
14422
|
+
);
|
|
14423
|
+
}
|
|
14424
|
+
function attributeReachedSummaries(seeds, reached, facts, owners) {
|
|
14425
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
14426
|
+
for (const [from, to] of facts.db.facts("calls")) {
|
|
14427
|
+
const key = String(from);
|
|
14428
|
+
const bucket = adjacency.get(key) ?? [];
|
|
14429
|
+
bucket.push(String(to));
|
|
14430
|
+
adjacency.set(key, bucket);
|
|
14431
|
+
}
|
|
14432
|
+
const seedKeysByRoot = /* @__PURE__ */ new Map();
|
|
14433
|
+
for (const seed of seeds) {
|
|
14434
|
+
const key = facts.unitKeyBySummary.get(seed);
|
|
14435
|
+
if (key === void 0) {
|
|
14436
|
+
continue;
|
|
14437
|
+
}
|
|
14438
|
+
for (const root of owners.get(seed) ?? []) {
|
|
14439
|
+
const bucket = seedKeysByRoot.get(root) ?? [];
|
|
14440
|
+
bucket.push(key);
|
|
14441
|
+
seedKeysByRoot.set(root, bucket);
|
|
14442
|
+
}
|
|
14443
|
+
}
|
|
14444
|
+
const reachableByRoot = /* @__PURE__ */ new Map();
|
|
14445
|
+
const rootsByKey = /* @__PURE__ */ new Map();
|
|
14446
|
+
for (const [root, seedKeys] of seedKeysByRoot) {
|
|
14447
|
+
const seen = new Set(seedKeys);
|
|
14448
|
+
const queue = [...seedKeys];
|
|
14449
|
+
while (queue.length > 0) {
|
|
14450
|
+
const key = queue.pop();
|
|
14451
|
+
if (key === void 0) {
|
|
14452
|
+
continue;
|
|
14453
|
+
}
|
|
14454
|
+
for (const next of adjacency.get(key) ?? []) {
|
|
14455
|
+
if (!seen.has(next)) {
|
|
14456
|
+
seen.add(next);
|
|
14457
|
+
queue.push(next);
|
|
14458
|
+
}
|
|
14459
|
+
}
|
|
14460
|
+
const keyRoots = rootsByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
14461
|
+
keyRoots.add(root);
|
|
14462
|
+
rootsByKey.set(key, keyRoots);
|
|
14463
|
+
}
|
|
14464
|
+
reachableByRoot.set(root, seen);
|
|
14465
|
+
}
|
|
14466
|
+
for (const summary of reached) {
|
|
14467
|
+
const key = facts.unitKeyBySummary.get(summary);
|
|
14468
|
+
if (key === void 0) {
|
|
14469
|
+
continue;
|
|
14470
|
+
}
|
|
14471
|
+
const keyRoots = rootsByKey.get(key);
|
|
14472
|
+
if (keyRoots !== void 0 && keyRoots.size > 0) {
|
|
14473
|
+
owners.set(summary, new Set(keyRoots));
|
|
14474
|
+
}
|
|
14475
|
+
}
|
|
14476
|
+
return { reachableByRoot, rootsByKey };
|
|
14477
|
+
}
|
|
14478
|
+
function fileOfNodeKey(key) {
|
|
14479
|
+
const cut = key.lastIndexOf(":");
|
|
14480
|
+
return cut <= 0 ? null : key.slice(0, cut);
|
|
14481
|
+
}
|
|
14482
|
+
function summaryMergeKey(summary) {
|
|
14483
|
+
return JSON.stringify([
|
|
14484
|
+
summary.location.file,
|
|
14485
|
+
summary.location.range.start,
|
|
14486
|
+
summary.location.range.end,
|
|
14487
|
+
summary.kind,
|
|
14488
|
+
summary.identity.name,
|
|
14489
|
+
summary.identity.exportPath,
|
|
14490
|
+
summary.identity.boundaryBinding
|
|
14491
|
+
]);
|
|
14492
|
+
}
|
|
14493
|
+
function mergeWithReused(reused, fresh, ownersBySummary) {
|
|
14494
|
+
if (reused === null) {
|
|
14495
|
+
return { summaries: fresh, reusedKept: [], reusedOwners: [] };
|
|
14496
|
+
}
|
|
14497
|
+
const freshByKey = /* @__PURE__ */ new Map();
|
|
14498
|
+
for (const summary of fresh) {
|
|
14499
|
+
freshByKey.set(summaryMergeKey(summary), summary);
|
|
14500
|
+
}
|
|
14501
|
+
const reusedKept = [];
|
|
14502
|
+
const reusedOwners = [];
|
|
14503
|
+
reused.summaries.forEach((summary, i) => {
|
|
14504
|
+
const owners = reused.owners[i] ?? [];
|
|
14505
|
+
const supersededBy = freshByKey.get(summaryMergeKey(summary));
|
|
14506
|
+
if (supersededBy !== void 0) {
|
|
14507
|
+
const freshOwners = ownersBySummary.get(supersededBy) ?? /* @__PURE__ */ new Set();
|
|
14508
|
+
for (const owner of owners) {
|
|
14509
|
+
freshOwners.add(owner);
|
|
14510
|
+
}
|
|
14511
|
+
ownersBySummary.set(supersededBy, freshOwners);
|
|
14512
|
+
return;
|
|
14513
|
+
}
|
|
14514
|
+
reusedKept.push(summary);
|
|
14515
|
+
reusedOwners.push(owners);
|
|
14516
|
+
});
|
|
14517
|
+
return { summaries: [...reusedKept, ...fresh], reusedKept, reusedOwners };
|
|
14518
|
+
}
|
|
14519
|
+
function readsRunLevelJoins(summary) {
|
|
14520
|
+
if (readSourceDocumentMetadata(summary) !== void 0) {
|
|
14521
|
+
return true;
|
|
14522
|
+
}
|
|
14523
|
+
if (readGraphqlMetadata2(summary)?.client !== void 0) {
|
|
14524
|
+
return true;
|
|
14525
|
+
}
|
|
14526
|
+
const semantics = summary.identity.boundaryBinding?.semantics;
|
|
14527
|
+
return semantics !== void 0 && "operationType" in semantics;
|
|
14528
|
+
}
|
|
14529
|
+
function buildCacheAttribution(args) {
|
|
14530
|
+
const references = createReferenceIndex(
|
|
14531
|
+
args.project.getSourceFiles().filter((sf) => !sf.isDeclarationFile())
|
|
14532
|
+
);
|
|
14533
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
14534
|
+
for (const [sf, packs] of args.packsByFile) {
|
|
14535
|
+
packNamesByPath.set(
|
|
14536
|
+
sf.getFilePath(),
|
|
14537
|
+
packs.map((p) => p.name)
|
|
14538
|
+
);
|
|
14539
|
+
}
|
|
14540
|
+
const summariesByRoot = /* @__PURE__ */ new Map();
|
|
14541
|
+
for (const summary of args.fresh) {
|
|
14542
|
+
for (const root of args.ownersBySummary.get(summary) ?? []) {
|
|
14543
|
+
const bucket = summariesByRoot.get(root) ?? [];
|
|
14544
|
+
bucket.push(summary);
|
|
14545
|
+
summariesByRoot.set(root, bucket);
|
|
14546
|
+
}
|
|
14547
|
+
}
|
|
14548
|
+
const roots = [];
|
|
14549
|
+
for (const [rootPath, sink] of args.sinkByRoot) {
|
|
14550
|
+
const deps = new Set(sink.files);
|
|
14551
|
+
for (const dep of references.directOf(rootPath)) {
|
|
14552
|
+
deps.add(dep);
|
|
14553
|
+
}
|
|
14554
|
+
let cacheable = true;
|
|
14555
|
+
for (const summary of summariesByRoot.get(rootPath) ?? []) {
|
|
14556
|
+
deps.add(summary.location.file);
|
|
14557
|
+
if (readsRunLevelJoins(summary)) {
|
|
14558
|
+
cacheable = false;
|
|
14559
|
+
}
|
|
14560
|
+
}
|
|
14561
|
+
const reachable = args.closureOwnership?.reachableByRoot.get(rootPath) ?? [];
|
|
14562
|
+
for (const key of reachable) {
|
|
14563
|
+
const keyFile = fileOfNodeKey(key);
|
|
14564
|
+
if (keyFile !== null) {
|
|
14565
|
+
deps.add(keyFile);
|
|
14566
|
+
for (const hop of references.directOf(keyFile)) {
|
|
14567
|
+
deps.add(hop);
|
|
14568
|
+
}
|
|
14569
|
+
}
|
|
14570
|
+
for (const filePath of args.filesByKey?.get(key) ?? []) {
|
|
14571
|
+
deps.add(filePath);
|
|
14572
|
+
}
|
|
14573
|
+
}
|
|
14574
|
+
deps.delete(rootPath);
|
|
14575
|
+
roots.push({
|
|
14576
|
+
path: rootPath,
|
|
14577
|
+
cacheable,
|
|
14578
|
+
deps: [...deps].sort(),
|
|
14579
|
+
claims: sink.claims,
|
|
14580
|
+
mountPrefixes: Object.fromEntries(sink.mountPrefixes),
|
|
14581
|
+
packs: packNamesByPath.get(rootPath) ?? []
|
|
14582
|
+
});
|
|
14583
|
+
}
|
|
14584
|
+
if (args.plan !== null) {
|
|
14585
|
+
for (const rootPath of args.validRoots) {
|
|
14586
|
+
const record = args.plan.roots.get(rootPath);
|
|
14587
|
+
if (record !== void 0) {
|
|
14588
|
+
roots.push(record);
|
|
14589
|
+
}
|
|
14590
|
+
}
|
|
14591
|
+
}
|
|
14592
|
+
const reusedOwners = args.reusedKept.map((summary, i) => {
|
|
14593
|
+
const combined = new Set(args.reusedOwners[i] ?? []);
|
|
14594
|
+
const key = args.unitKeyBySummary.get(summary);
|
|
14595
|
+
if (key !== void 0) {
|
|
14596
|
+
for (const root of args.closureOwnership?.rootsByKey.get(key) ?? []) {
|
|
14597
|
+
combined.add(root);
|
|
14598
|
+
}
|
|
14599
|
+
}
|
|
14600
|
+
return [...combined];
|
|
14601
|
+
});
|
|
14602
|
+
const owners = [
|
|
14603
|
+
...reusedOwners,
|
|
14604
|
+
...args.fresh.map((s) => [...args.ownersBySummary.get(s) ?? []])
|
|
14605
|
+
];
|
|
14606
|
+
return { roots, owners };
|
|
14607
|
+
}
|
|
14608
|
+
function synthesizeSubUnits(summaries, project, frameworks, options, tallies, onCreated) {
|
|
13429
14609
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
13430
14610
|
for (const pack of frameworks) {
|
|
13431
14611
|
packByRecognition.set(pack.name, pack);
|
|
@@ -13468,6 +14648,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13468
14648
|
);
|
|
13469
14649
|
if (summary !== null) {
|
|
13470
14650
|
synthesized.push(summary);
|
|
14651
|
+
onCreated?.(summary, parent);
|
|
13471
14652
|
}
|
|
13472
14653
|
}
|
|
13473
14654
|
}
|
|
@@ -13476,14 +14657,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13476
14657
|
var DEFAULT_SUB_UNIT_TERMINALS = [
|
|
13477
14658
|
{ kind: "return", match: { type: "returnStatement" }, extraction: {} },
|
|
13478
14659
|
{ kind: "throw", match: { type: "throwExpression" }, extraction: {} },
|
|
13479
|
-
|
|
13480
|
-
// fall-through gives it a default transition. HTTP packs do not opt in:
|
|
13481
|
-
// a handler that sends no response should come out with none.
|
|
13482
|
-
{
|
|
13483
|
-
kind: "return",
|
|
13484
|
-
match: { type: "functionFallthrough" },
|
|
13485
|
-
extraction: {}
|
|
13486
|
-
}
|
|
14660
|
+
FUNCTION_FALLTHROUGH_TERMINAL
|
|
13487
14661
|
];
|
|
13488
14662
|
var DEFAULT_SUB_UNIT_INPUT_MAPPING = {
|
|
13489
14663
|
type: "positionalParams",
|
|
@@ -13673,7 +14847,7 @@ function readStringArg(arg) {
|
|
|
13673
14847
|
}
|
|
13674
14848
|
return candidate.value;
|
|
13675
14849
|
}
|
|
13676
|
-
function
|
|
14850
|
+
function rootIdentifier2(node) {
|
|
13677
14851
|
let current2 = node;
|
|
13678
14852
|
while (Node55.isPropertyAccessExpression(current2)) {
|
|
13679
14853
|
current2 = current2.getExpression();
|
|
@@ -13681,10 +14855,165 @@ function rootIdentifier(node) {
|
|
|
13681
14855
|
return Node55.isIdentifier(current2) ? current2 : null;
|
|
13682
14856
|
}
|
|
13683
14857
|
|
|
14858
|
+
// src/facts/why.ts
|
|
14859
|
+
import path11 from "path";
|
|
14860
|
+
import { Node as Node56, Project as Project3, SyntaxKind as SyntaxKind12 } from "ts-morph";
|
|
14861
|
+
import { explainResolutionProof, renderExplanation } from "@suss/resolution";
|
|
14862
|
+
var JS_PHRASES = {
|
|
14863
|
+
bind: ({ tuple, describe }) => ({
|
|
14864
|
+
reason: `${describe(tuple[0])} is a .bind of ${describe(tuple[1])}, which runs the same function`
|
|
14865
|
+
})
|
|
14866
|
+
};
|
|
14867
|
+
var WhySession = class {
|
|
14868
|
+
project;
|
|
14869
|
+
store;
|
|
14870
|
+
root;
|
|
14871
|
+
constructor(options) {
|
|
14872
|
+
this.root = path11.resolve(options.dir);
|
|
14873
|
+
const tsconfig = findNearestTsconfig(this.root);
|
|
14874
|
+
this.project = tsconfig === null ? createProjectWithoutTsconfig(this.root).project : new Project3({ tsConfigFilePath: tsconfig });
|
|
14875
|
+
this.store = new ResolutionStore();
|
|
14876
|
+
}
|
|
14877
|
+
/**
|
|
14878
|
+
* The smallest expression on `line` of `file` whose text is exactly
|
|
14879
|
+
* `text`, or null. Spelled from the person's side: the name as
|
|
14880
|
+
* written, not a node id.
|
|
14881
|
+
*/
|
|
14882
|
+
findExpression(file, line, text) {
|
|
14883
|
+
const sourceFile = this.sourceFileAt(file);
|
|
14884
|
+
if (sourceFile === null) {
|
|
14885
|
+
return null;
|
|
14886
|
+
}
|
|
14887
|
+
let found = null;
|
|
14888
|
+
sourceFile.forEachDescendant((node) => {
|
|
14889
|
+
if (Node56.isExpression(node) && node.getStartLineNumber() === line && node.getText() === text && (found === null || node.getWidth() <= found.getWidth())) {
|
|
14890
|
+
found = node;
|
|
14891
|
+
}
|
|
14892
|
+
});
|
|
14893
|
+
return found;
|
|
14894
|
+
}
|
|
14895
|
+
/**
|
|
14896
|
+
* The callee of the call written as `calleeText` between `startLine`
|
|
14897
|
+
* and `endLine` of `file`, or null. This is how a summary's recorded
|
|
14898
|
+
* callee gets back to its node: the summary keeps source text and a
|
|
14899
|
+
* range, not ids.
|
|
14900
|
+
*/
|
|
14901
|
+
findCallee(file, startLine, endLine, calleeText) {
|
|
14902
|
+
const sourceFile = this.sourceFileAt(file);
|
|
14903
|
+
if (sourceFile === null) {
|
|
14904
|
+
return null;
|
|
14905
|
+
}
|
|
14906
|
+
for (const call of sourceFile.getDescendantsOfKind(
|
|
14907
|
+
SyntaxKind12.CallExpression
|
|
14908
|
+
)) {
|
|
14909
|
+
const line = call.getStartLineNumber();
|
|
14910
|
+
if (line < startLine || line > endLine) {
|
|
14911
|
+
continue;
|
|
14912
|
+
}
|
|
14913
|
+
if (call.getExpression().getText() === calleeText) {
|
|
14914
|
+
return call.getExpression();
|
|
14915
|
+
}
|
|
14916
|
+
}
|
|
14917
|
+
return null;
|
|
14918
|
+
}
|
|
14919
|
+
/**
|
|
14920
|
+
* Why `value` resolves to what it does: the witness proof, flattened
|
|
14921
|
+
* to the chain and rendered. Null when the value does not resolve,
|
|
14922
|
+
* which the caller says in its own words.
|
|
14923
|
+
*/
|
|
14924
|
+
explain(value, options = {}) {
|
|
14925
|
+
const explained = this.store.explainCallable(value, options);
|
|
14926
|
+
if (explained === null) {
|
|
14927
|
+
return null;
|
|
14928
|
+
}
|
|
14929
|
+
const describe = (atom) => {
|
|
14930
|
+
const node = explained.nodeFor(atom);
|
|
14931
|
+
if (node === void 0) {
|
|
14932
|
+
return this.displayPath(String(atom));
|
|
14933
|
+
}
|
|
14934
|
+
const at = this.locate(node);
|
|
14935
|
+
return `${at.name} (${at.file}:${at.line})`;
|
|
14936
|
+
};
|
|
14937
|
+
const explanation = explainResolutionProof(explained.proof, {
|
|
14938
|
+
describe,
|
|
14939
|
+
phrases: JS_PHRASES
|
|
14940
|
+
});
|
|
14941
|
+
if (explanation === null) {
|
|
14942
|
+
return null;
|
|
14943
|
+
}
|
|
14944
|
+
return {
|
|
14945
|
+
explanation,
|
|
14946
|
+
chain: explanation.atoms.map((atom) => describe(atom)),
|
|
14947
|
+
lines: renderExplanation(explanation, describe),
|
|
14948
|
+
target: this.locate(explained.target),
|
|
14949
|
+
stats: explained.stats
|
|
14950
|
+
};
|
|
14951
|
+
}
|
|
14952
|
+
/** Where a found node is, in the terms an answer prints. */
|
|
14953
|
+
locate(node) {
|
|
14954
|
+
return {
|
|
14955
|
+
name: displayNameOf(node),
|
|
14956
|
+
file: this.displayPath(node.getSourceFile().getFilePath()),
|
|
14957
|
+
line: node.getStartLineNumber()
|
|
14958
|
+
};
|
|
14959
|
+
}
|
|
14960
|
+
sourceFileAt(file) {
|
|
14961
|
+
const absolute = path11.resolve(this.root, file);
|
|
14962
|
+
const loaded = this.project.getSourceFile(absolute);
|
|
14963
|
+
if (loaded !== void 0) {
|
|
14964
|
+
return loaded;
|
|
14965
|
+
}
|
|
14966
|
+
try {
|
|
14967
|
+
return this.project.addSourceFileAtPath(absolute);
|
|
14968
|
+
} catch {
|
|
14969
|
+
return null;
|
|
14970
|
+
}
|
|
14971
|
+
}
|
|
14972
|
+
/** A module key: a file path said relative to the root, or a package name. */
|
|
14973
|
+
displayPath(key) {
|
|
14974
|
+
if (key.startsWith(this.root)) {
|
|
14975
|
+
return path11.relative(this.root, key);
|
|
14976
|
+
}
|
|
14977
|
+
return key;
|
|
14978
|
+
}
|
|
14979
|
+
};
|
|
14980
|
+
function displayNameOf(node) {
|
|
14981
|
+
if (Node56.isIdentifier(node) || Node56.isPropertyAccessExpression(node)) {
|
|
14982
|
+
return node.getText();
|
|
14983
|
+
}
|
|
14984
|
+
if (Node56.isCallExpression(node) || Node56.isNewExpression(node)) {
|
|
14985
|
+
return `${node.getExpression()?.getText() ?? "call"}(...)`;
|
|
14986
|
+
}
|
|
14987
|
+
if (Node56.isFunctionDeclaration(node) || Node56.isClassDeclaration(node) || Node56.isMethodDeclaration(node) || Node56.isVariableDeclaration(node)) {
|
|
14988
|
+
const name = node.getName();
|
|
14989
|
+
if (name !== void 0) {
|
|
14990
|
+
return name;
|
|
14991
|
+
}
|
|
14992
|
+
}
|
|
14993
|
+
if (Node56.isArrowFunction(node) || Node56.isFunctionExpression(node)) {
|
|
14994
|
+
const parent = node.getParent();
|
|
14995
|
+
if (parent !== void 0 && Node56.isVariableDeclaration(parent)) {
|
|
14996
|
+
return parent.getName();
|
|
14997
|
+
}
|
|
14998
|
+
}
|
|
14999
|
+
const text = node.getText().split("\n")[0].trim();
|
|
15000
|
+
return text.length > 40 ? `${text.slice(0, 40)}...` : text;
|
|
15001
|
+
}
|
|
15002
|
+
|
|
13684
15003
|
// src/packHealth.ts
|
|
13685
15004
|
function stagesOf(funnel) {
|
|
13686
15005
|
const stages = [];
|
|
13687
15006
|
const gateSaysSomething = funnel.gates.length > 0 && funnel.unresolvedGates.length === 0;
|
|
15007
|
+
if (funnel.recognizes && !funnel.discovers && gateSaysSomething) {
|
|
15008
|
+
stages.push({
|
|
15009
|
+
from: {
|
|
15010
|
+
name: "unit bodies to look inside",
|
|
15011
|
+
count: funnel.unitsInGatedFiles
|
|
15012
|
+
},
|
|
15013
|
+
to: { name: "effects recognized", count: funnel.effectsRecognized },
|
|
15014
|
+
meaning: "its import gate found the library and it matched nothing in the bodies it saw"
|
|
15015
|
+
});
|
|
15016
|
+
}
|
|
13688
15017
|
if (funnel.discovers && gateSaysSomething) {
|
|
13689
15018
|
stages.push({
|
|
13690
15019
|
from: { name: "candidate files", count: funnel.candidateFiles },
|
|
@@ -13794,7 +15123,8 @@ function formatPackHealth(checks, audiences) {
|
|
|
13794
15123
|
}
|
|
13795
15124
|
|
|
13796
15125
|
// src/resolve/readName.ts
|
|
13797
|
-
import { Node as
|
|
15126
|
+
import { Node as Node57, SyntaxKind as SyntaxKind13 } from "ts-morph";
|
|
15127
|
+
import { patternHole, referenceName } from "@suss/behavioral-ir";
|
|
13798
15128
|
var MAX_HELPER_HOPS = 2;
|
|
13799
15129
|
var UNNAMED_HOLE = "param";
|
|
13800
15130
|
function readName(expr, options = {}) {
|
|
@@ -13808,6 +15138,14 @@ function readName(expr, options = {}) {
|
|
|
13808
15138
|
if (name !== null || options.unsettled !== "reference") {
|
|
13809
15139
|
return name;
|
|
13810
15140
|
}
|
|
15141
|
+
const reference = referenceIn(expr);
|
|
15142
|
+
return reference === null ? null : referenceName(reference);
|
|
15143
|
+
}
|
|
15144
|
+
function referenceIn(expr) {
|
|
15145
|
+
const fromParameter = parameterPath(expr);
|
|
15146
|
+
if (fromParameter !== null) {
|
|
15147
|
+
return fromParameter;
|
|
15148
|
+
}
|
|
13811
15149
|
const asked = holeName(expr, {
|
|
13812
15150
|
resolve: () => null,
|
|
13813
15151
|
bindings: /* @__PURE__ */ new Map(),
|
|
@@ -13815,7 +15153,25 @@ function readName(expr, options = {}) {
|
|
|
13815
15153
|
seen: /* @__PURE__ */ new Set(),
|
|
13816
15154
|
insideHole: true
|
|
13817
15155
|
});
|
|
13818
|
-
return asked === UNNAMED_HOLE ? null :
|
|
15156
|
+
return asked === UNNAMED_HOLE ? null : { root: asked, fields: [] };
|
|
15157
|
+
}
|
|
15158
|
+
function parameterPath(expr) {
|
|
15159
|
+
const fields = [];
|
|
15160
|
+
let step = expr;
|
|
15161
|
+
while (Node57.isPropertyAccessExpression(step)) {
|
|
15162
|
+
fields.unshift(step.getName());
|
|
15163
|
+
step = step.getExpression();
|
|
15164
|
+
}
|
|
15165
|
+
if (!Node57.isIdentifier(step) || !isParameter(step)) {
|
|
15166
|
+
return null;
|
|
15167
|
+
}
|
|
15168
|
+
return { root: step.getText(), fields };
|
|
15169
|
+
}
|
|
15170
|
+
function isParameter(identifier) {
|
|
15171
|
+
const declarations = identifier.getSymbol()?.getDeclarations() ?? [];
|
|
15172
|
+
return declarations.some(
|
|
15173
|
+
(declaration) => Node57.isParameterDeclaration(declaration)
|
|
15174
|
+
);
|
|
13819
15175
|
}
|
|
13820
15176
|
function read(expr, ctx) {
|
|
13821
15177
|
if (ctx.seen.has(expr)) {
|
|
@@ -13823,35 +15179,52 @@ function read(expr, ctx) {
|
|
|
13823
15179
|
}
|
|
13824
15180
|
const seen = new Set(ctx.seen).add(expr);
|
|
13825
15181
|
const inner = { ...ctx, seen };
|
|
13826
|
-
if (
|
|
15182
|
+
if (Node57.isStringLiteral(expr) || Node57.isNoSubstitutionTemplateLiteral(expr)) {
|
|
13827
15183
|
return expr.getLiteralValue();
|
|
13828
15184
|
}
|
|
13829
|
-
if (
|
|
15185
|
+
if (Node57.isNumericLiteral(expr)) {
|
|
13830
15186
|
return expr.getLiteralText();
|
|
13831
15187
|
}
|
|
13832
|
-
if (
|
|
15188
|
+
if (Node57.isTemplateExpression(expr)) {
|
|
13833
15189
|
return fromTemplate(expr, inner);
|
|
13834
15190
|
}
|
|
13835
|
-
if (
|
|
15191
|
+
if (Node57.isParenthesizedExpression(expr)) {
|
|
13836
15192
|
return read(expr.getExpression(), inner);
|
|
13837
15193
|
}
|
|
13838
|
-
if (
|
|
15194
|
+
if (Node57.isBinaryExpression(expr)) {
|
|
13839
15195
|
return fromBinary(expr, inner);
|
|
13840
15196
|
}
|
|
13841
|
-
if (
|
|
15197
|
+
if (Node57.isCallExpression(expr)) {
|
|
13842
15198
|
return fromCall(expr, inner);
|
|
13843
15199
|
}
|
|
13844
|
-
if (
|
|
15200
|
+
if (Node57.isIdentifier(expr)) {
|
|
13845
15201
|
const only = boundOnce(expr, ctx);
|
|
13846
15202
|
if (only !== null) {
|
|
13847
15203
|
return read(only.node, { ...inner, bindings: only.scope });
|
|
13848
15204
|
}
|
|
13849
15205
|
}
|
|
13850
15206
|
const written = ctx.resolve(expr);
|
|
13851
|
-
|
|
15207
|
+
if (written === null || written === expr) {
|
|
15208
|
+
return null;
|
|
15209
|
+
}
|
|
15210
|
+
if (ctx.insideHole && isFallbackBranch(written)) {
|
|
15211
|
+
return null;
|
|
15212
|
+
}
|
|
15213
|
+
return read(written, inner);
|
|
15214
|
+
}
|
|
15215
|
+
function isFallbackBranch(node) {
|
|
15216
|
+
let step = node.getParent();
|
|
15217
|
+
while (step !== void 0 && Node57.isParenthesizedExpression(step)) {
|
|
15218
|
+
step = step.getParent();
|
|
15219
|
+
}
|
|
15220
|
+
if (step === void 0 || !Node57.isBinaryExpression(step)) {
|
|
15221
|
+
return false;
|
|
15222
|
+
}
|
|
15223
|
+
const operator = step.getOperatorToken().getKind();
|
|
15224
|
+
return operator === SyntaxKind13.BarBarToken || operator === SyntaxKind13.QuestionQuestionToken;
|
|
13852
15225
|
}
|
|
13853
15226
|
function fromTemplate(expr, ctx) {
|
|
13854
|
-
if (!
|
|
15227
|
+
if (!Node57.isTemplateExpression(expr)) {
|
|
13855
15228
|
return null;
|
|
13856
15229
|
}
|
|
13857
15230
|
let name = expr.getHead().getLiteralText();
|
|
@@ -13862,28 +15235,28 @@ function fromTemplate(expr, ctx) {
|
|
|
13862
15235
|
return name;
|
|
13863
15236
|
}
|
|
13864
15237
|
function fromBinary(expr, ctx) {
|
|
13865
|
-
if (!
|
|
15238
|
+
if (!Node57.isBinaryExpression(expr)) {
|
|
13866
15239
|
return null;
|
|
13867
15240
|
}
|
|
13868
15241
|
const operator = expr.getOperatorToken().getKind();
|
|
13869
|
-
if (operator ===
|
|
15242
|
+
if (operator === SyntaxKind13.BarBarToken || operator === SyntaxKind13.QuestionQuestionToken) {
|
|
13870
15243
|
return ctx.insideHole ? null : read(expr.getRight(), ctx);
|
|
13871
15244
|
}
|
|
13872
|
-
if (operator !==
|
|
15245
|
+
if (operator !== SyntaxKind13.PlusToken) {
|
|
13873
15246
|
return null;
|
|
13874
15247
|
}
|
|
13875
15248
|
const parts = { ...ctx, insideHole: true };
|
|
13876
15249
|
return readOrHole(expr.getLeft(), parts) + readOrHole(expr.getRight(), parts);
|
|
13877
15250
|
}
|
|
13878
15251
|
function fromCall(expr, ctx) {
|
|
13879
|
-
if (!
|
|
15252
|
+
if (!Node57.isCallExpression(expr)) {
|
|
13880
15253
|
return null;
|
|
13881
15254
|
}
|
|
13882
15255
|
const callee = expr.getExpression();
|
|
13883
|
-
if (
|
|
15256
|
+
if (Node57.isPropertyAccessExpression(callee) && callee.getName() === "join") {
|
|
13884
15257
|
return fromJoin(callee.getExpression(), expr.getArguments(), ctx);
|
|
13885
15258
|
}
|
|
13886
|
-
if (
|
|
15259
|
+
if (Node57.isIdentifier(callee) && callee.getText() === "String") {
|
|
13887
15260
|
const only = expr.getArguments()[0];
|
|
13888
15261
|
return only === void 0 ? null : readOrHole(only, ctx);
|
|
13889
15262
|
}
|
|
@@ -13902,7 +15275,7 @@ function fromCall(expr, ctx) {
|
|
|
13902
15275
|
}
|
|
13903
15276
|
function fromJoin(subject, args, ctx) {
|
|
13904
15277
|
const separator = args[0];
|
|
13905
|
-
if (separator === void 0 || !
|
|
15278
|
+
if (separator === void 0 || !Node57.isStringLiteral(separator)) {
|
|
13906
15279
|
return null;
|
|
13907
15280
|
}
|
|
13908
15281
|
const parts = elementsOf(subject, ctx);
|
|
@@ -13918,17 +15291,17 @@ function fromJoin(subject, args, ctx) {
|
|
|
13918
15291
|
).join(separator.getLiteralValue());
|
|
13919
15292
|
}
|
|
13920
15293
|
function elementsOf(subject, ctx) {
|
|
13921
|
-
if (
|
|
15294
|
+
if (Node57.isArrayLiteralExpression(subject)) {
|
|
13922
15295
|
return subject.getElements().map((element) => here(element, ctx));
|
|
13923
15296
|
}
|
|
13924
|
-
if (
|
|
15297
|
+
if (Node57.isCallExpression(subject)) {
|
|
13925
15298
|
const callee = subject.getExpression();
|
|
13926
|
-
if (
|
|
15299
|
+
if (Node57.isPropertyAccessExpression(callee) && callee.getName() === "map") {
|
|
13927
15300
|
return elementsOf(callee.getExpression(), ctx);
|
|
13928
15301
|
}
|
|
13929
15302
|
return null;
|
|
13930
15303
|
}
|
|
13931
|
-
if (!
|
|
15304
|
+
if (!Node57.isIdentifier(subject)) {
|
|
13932
15305
|
return null;
|
|
13933
15306
|
}
|
|
13934
15307
|
const bound = ctx.bindings.get(subject.getText());
|
|
@@ -13936,7 +15309,7 @@ function elementsOf(subject, ctx) {
|
|
|
13936
15309
|
return null;
|
|
13937
15310
|
}
|
|
13938
15311
|
const only = bound.length === 1 ? bound[0] : void 0;
|
|
13939
|
-
return only !== void 0 &&
|
|
15312
|
+
return only !== void 0 && Node57.isArrayLiteralExpression(only.node) ? only.node.getElements().map((element) => here(element, ctx)) : bound;
|
|
13940
15313
|
}
|
|
13941
15314
|
function singleReturnBody(callee, ctx) {
|
|
13942
15315
|
const declaration = declarationOf2(callee, ctx);
|
|
@@ -13951,22 +15324,22 @@ function singleReturnBody(callee, ctx) {
|
|
|
13951
15324
|
if (body === void 0) {
|
|
13952
15325
|
return null;
|
|
13953
15326
|
}
|
|
13954
|
-
if (
|
|
15327
|
+
if (Node57.isExpression(body)) {
|
|
13955
15328
|
return { parameters, returned: body };
|
|
13956
15329
|
}
|
|
13957
|
-
if (!
|
|
15330
|
+
if (!Node57.isBlock(body)) {
|
|
13958
15331
|
return null;
|
|
13959
15332
|
}
|
|
13960
15333
|
const statements = body.getStatements();
|
|
13961
15334
|
const only = statements[0];
|
|
13962
|
-
if (statements.length !== 1 || only === void 0 || !
|
|
15335
|
+
if (statements.length !== 1 || only === void 0 || !Node57.isReturnStatement(only)) {
|
|
13963
15336
|
return null;
|
|
13964
15337
|
}
|
|
13965
15338
|
const returned = only.getExpression();
|
|
13966
15339
|
return returned === void 0 ? null : { parameters, returned };
|
|
13967
15340
|
}
|
|
13968
15341
|
function declarationOf2(callee, ctx) {
|
|
13969
|
-
const symbol =
|
|
15342
|
+
const symbol = Node57.isPropertyAccessExpression(callee) ? callee.getNameNode().getSymbol() : callee.getSymbol();
|
|
13970
15343
|
const declarations = symbol?.getAliasedSymbol()?.getDeclarations() ?? symbol?.getDeclarations() ?? [];
|
|
13971
15344
|
for (const declaration of declarations) {
|
|
13972
15345
|
const callable = asCallable(declaration);
|
|
@@ -13978,14 +15351,14 @@ function declarationOf2(callee, ctx) {
|
|
|
13978
15351
|
return written === null || written === callee ? null : declarationOf2(written, { ...ctx, resolve: () => null });
|
|
13979
15352
|
}
|
|
13980
15353
|
function asCallable(declaration) {
|
|
13981
|
-
if (
|
|
15354
|
+
if (Node57.isFunctionDeclaration(declaration) || Node57.isMethodDeclaration(declaration) || Node57.isArrowFunction(declaration) || Node57.isFunctionExpression(declaration)) {
|
|
13982
15355
|
return declaration;
|
|
13983
15356
|
}
|
|
13984
|
-
if (!
|
|
15357
|
+
if (!Node57.isVariableDeclaration(declaration)) {
|
|
13985
15358
|
return null;
|
|
13986
15359
|
}
|
|
13987
15360
|
const initializer = declaration.getInitializer();
|
|
13988
|
-
if (initializer !== void 0 && (
|
|
15361
|
+
if (initializer !== void 0 && (Node57.isArrowFunction(initializer) || Node57.isFunctionExpression(initializer))) {
|
|
13989
15362
|
return initializer;
|
|
13990
15363
|
}
|
|
13991
15364
|
return null;
|
|
@@ -14007,22 +15380,22 @@ function here(node, ctx) {
|
|
|
14007
15380
|
return { node, scope: ctx.bindings };
|
|
14008
15381
|
}
|
|
14009
15382
|
function boundOnce(expr, ctx) {
|
|
14010
|
-
const bound =
|
|
15383
|
+
const bound = Node57.isIdentifier(expr) ? ctx.bindings.get(expr.getText()) : void 0;
|
|
14011
15384
|
return bound !== void 0 && bound.length === 1 ? bound[0] : null;
|
|
14012
15385
|
}
|
|
14013
15386
|
function readOrHole(expr, ctx) {
|
|
14014
15387
|
const name = read(expr, ctx);
|
|
14015
|
-
return name ??
|
|
15388
|
+
return name ?? patternHole(holeName(expr, ctx));
|
|
14016
15389
|
}
|
|
14017
15390
|
function holeName(expr, ctx) {
|
|
14018
15391
|
const bound = boundOnce(expr, ctx);
|
|
14019
15392
|
if (bound !== null) {
|
|
14020
15393
|
return holeName(bound.node, { ...ctx, bindings: bound.scope });
|
|
14021
15394
|
}
|
|
14022
|
-
if (
|
|
15395
|
+
if (Node57.isIdentifier(expr)) {
|
|
14023
15396
|
return expr.getText();
|
|
14024
15397
|
}
|
|
14025
|
-
if (
|
|
15398
|
+
if (Node57.isPropertyAccessExpression(expr)) {
|
|
14026
15399
|
return expr.getName();
|
|
14027
15400
|
}
|
|
14028
15401
|
return UNNAMED_HOLE;
|
|
@@ -14030,6 +15403,7 @@ function holeName(expr, ctx) {
|
|
|
14030
15403
|
export {
|
|
14031
15404
|
ADAPTER_VERSION,
|
|
14032
15405
|
ResolutionStore,
|
|
15406
|
+
WhySession,
|
|
14033
15407
|
collectAncestorBranches,
|
|
14034
15408
|
collectClientFieldAccesses,
|
|
14035
15409
|
computeAdapterPacksDigest,
|
|
@@ -14055,5 +15429,6 @@ export {
|
|
|
14055
15429
|
readName,
|
|
14056
15430
|
resolveAliasedSymbol,
|
|
14057
15431
|
resolveSubject,
|
|
14058
|
-
rootIdentifier
|
|
15432
|
+
rootIdentifier2 as rootIdentifier,
|
|
15433
|
+
workspaceRootFor
|
|
14059
15434
|
};
|