@suss/adapter-typescript 0.9.0 → 0.10.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 +952 -162
- package/dist/index.d.cts +44 -10
- package/dist/index.d.ts +44 -10
- package/dist/index.js +945 -151
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1076,24 +1076,64 @@ function collectFallthroughCaseLabels(caseClause) {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
1078
|
// src/paths/pathConditions.ts
|
|
1079
|
-
var
|
|
1079
|
+
var import_ts_morph9 = require("ts-morph");
|
|
1080
1080
|
var import_extractor2 = require("@suss/extractor");
|
|
1081
1081
|
|
|
1082
|
-
// src/
|
|
1082
|
+
// src/walk/descent.ts
|
|
1083
1083
|
var import_ts_morph7 = require("ts-morph");
|
|
1084
|
+
var NO_BARRIERS = /* @__PURE__ */ new Set();
|
|
1085
|
+
function isDescentStop(node, func, barriers = NO_BARRIERS) {
|
|
1086
|
+
if (node === func) {
|
|
1087
|
+
return false;
|
|
1088
|
+
}
|
|
1089
|
+
if (import_ts_morph7.Node.isFunctionDeclaration(node) || import_ts_morph7.Node.isMethodDeclaration(node)) {
|
|
1090
|
+
return true;
|
|
1091
|
+
}
|
|
1092
|
+
if (import_ts_morph7.Node.isArrowFunction(node) || import_ts_morph7.Node.isFunctionExpression(node)) {
|
|
1093
|
+
return barriers.has(node);
|
|
1094
|
+
}
|
|
1095
|
+
return false;
|
|
1096
|
+
}
|
|
1097
|
+
function isInlineCallback(node, func, barriers = NO_BARRIERS) {
|
|
1098
|
+
if (node === func) {
|
|
1099
|
+
return false;
|
|
1100
|
+
}
|
|
1101
|
+
if (!(import_ts_morph7.Node.isArrowFunction(node) || import_ts_morph7.Node.isFunctionExpression(node))) {
|
|
1102
|
+
return false;
|
|
1103
|
+
}
|
|
1104
|
+
return !barriers.has(node);
|
|
1105
|
+
}
|
|
1106
|
+
function isModuleScopeStop(node) {
|
|
1107
|
+
return import_ts_morph7.Node.isFunctionDeclaration(node) || import_ts_morph7.Node.isMethodDeclaration(node) || import_ts_morph7.Node.isArrowFunction(node) || import_ts_morph7.Node.isFunctionExpression(node) || import_ts_morph7.Node.isClassDeclaration(node) || import_ts_morph7.Node.isClassExpression(node);
|
|
1108
|
+
}
|
|
1109
|
+
function crossesNestedFunctionScope(node, func) {
|
|
1110
|
+
let current2 = node;
|
|
1111
|
+
while (current2 !== void 0 && current2 !== func) {
|
|
1112
|
+
if (startsItsOwnScope(current2)) {
|
|
1113
|
+
return true;
|
|
1114
|
+
}
|
|
1115
|
+
current2 = current2.getParent();
|
|
1116
|
+
}
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
function startsItsOwnScope(node) {
|
|
1120
|
+
return import_ts_morph7.Node.isArrowFunction(node) || import_ts_morph7.Node.isFunctionExpression(node) || import_ts_morph7.Node.isFunctionDeclaration(node) || import_ts_morph7.Node.isMethodDeclaration(node) || import_ts_morph7.Node.isGetAccessorDeclaration(node) || import_ts_morph7.Node.isSetAccessorDeclaration(node) || import_ts_morph7.Node.isConstructorDeclaration(node);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/paths/lowering.ts
|
|
1124
|
+
var import_ts_morph8 = require("ts-morph");
|
|
1084
1125
|
var import_extractor = require("@suss/extractor");
|
|
1085
|
-
var isFunctionBoundary = (node) => import_ts_morph7.Node.isFunctionDeclaration(node) || import_ts_morph7.Node.isFunctionExpression(node) || import_ts_morph7.Node.isArrowFunction(node) || import_ts_morph7.Node.isMethodDeclaration(node);
|
|
1086
1126
|
function exitKindOf(stmt) {
|
|
1087
1127
|
let sawReturn = false;
|
|
1088
1128
|
let sawThrow = false;
|
|
1089
1129
|
const visit = (node) => {
|
|
1090
|
-
if (node !== stmt &&
|
|
1130
|
+
if (node !== stmt && startsItsOwnScope(node)) {
|
|
1091
1131
|
return;
|
|
1092
1132
|
}
|
|
1093
|
-
if (
|
|
1133
|
+
if (import_ts_morph8.Node.isReturnStatement(node)) {
|
|
1094
1134
|
sawReturn = true;
|
|
1095
1135
|
}
|
|
1096
|
-
if (
|
|
1136
|
+
if (import_ts_morph8.Node.isThrowStatement(node)) {
|
|
1097
1137
|
sawThrow = true;
|
|
1098
1138
|
}
|
|
1099
1139
|
for (const child of node.getChildren()) {
|
|
@@ -1110,14 +1150,14 @@ var statementsOf = (stmt) => {
|
|
|
1110
1150
|
if (stmt === void 0) {
|
|
1111
1151
|
return [];
|
|
1112
1152
|
}
|
|
1113
|
-
if (
|
|
1153
|
+
if (import_ts_morph8.Node.isBlock(stmt)) {
|
|
1114
1154
|
return stmt.getStatements();
|
|
1115
1155
|
}
|
|
1116
1156
|
return [stmt];
|
|
1117
1157
|
};
|
|
1118
|
-
var isLoop = (stmt) =>
|
|
1158
|
+
var isLoop = (stmt) => import_ts_morph8.Node.isForOfStatement(stmt) || import_ts_morph8.Node.isForInStatement(stmt) || import_ts_morph8.Node.isForStatement(stmt) || import_ts_morph8.Node.isWhileStatement(stmt) || import_ts_morph8.Node.isDoStatement(stmt);
|
|
1119
1159
|
function getLoopBody(stmt) {
|
|
1120
|
-
if (
|
|
1160
|
+
if (import_ts_morph8.Node.isForOfStatement(stmt) || import_ts_morph8.Node.isForInStatement(stmt) || import_ts_morph8.Node.isForStatement(stmt) || import_ts_morph8.Node.isWhileStatement(stmt) || import_ts_morph8.Node.isDoStatement(stmt)) {
|
|
1121
1161
|
return stmt.getStatement();
|
|
1122
1162
|
}
|
|
1123
1163
|
return void 0;
|
|
@@ -1132,37 +1172,97 @@ var conditionOf = (expr) => ({
|
|
|
1132
1172
|
sourceText: expr.getText(),
|
|
1133
1173
|
expression: expr
|
|
1134
1174
|
});
|
|
1135
|
-
function lowerStatement(stmt,
|
|
1136
|
-
const structured =
|
|
1137
|
-
|
|
1175
|
+
function lowerStatement(stmt, ctx) {
|
|
1176
|
+
const structured = {
|
|
1177
|
+
...buildStructured(stmt, ctx),
|
|
1178
|
+
callbacks: lowerCallbacksIn(ownExpressionsOf(stmt), ctx)
|
|
1179
|
+
};
|
|
1180
|
+
ctx.rawToStructured.set(stmt, structured);
|
|
1138
1181
|
return structured;
|
|
1139
1182
|
}
|
|
1140
|
-
function lowerList(stmts,
|
|
1141
|
-
return spliceBlocks(stmts).map((s) => lowerStatement(s,
|
|
1183
|
+
function lowerList(stmts, ctx) {
|
|
1184
|
+
return spliceBlocks(stmts).map((s) => lowerStatement(s, ctx));
|
|
1185
|
+
}
|
|
1186
|
+
function ownExpressionsOf(stmt) {
|
|
1187
|
+
if (import_ts_morph8.Node.isIfStatement(stmt) || import_ts_morph8.Node.isSwitchStatement(stmt)) {
|
|
1188
|
+
return [stmt.getExpression()];
|
|
1189
|
+
}
|
|
1190
|
+
if (import_ts_morph8.Node.isWhileStatement(stmt) || import_ts_morph8.Node.isDoStatement(stmt)) {
|
|
1191
|
+
return [stmt.getExpression()];
|
|
1192
|
+
}
|
|
1193
|
+
if (import_ts_morph8.Node.isForOfStatement(stmt) || import_ts_morph8.Node.isForInStatement(stmt)) {
|
|
1194
|
+
return [stmt.getInitializer(), stmt.getExpression()];
|
|
1195
|
+
}
|
|
1196
|
+
if (import_ts_morph8.Node.isForStatement(stmt)) {
|
|
1197
|
+
return [
|
|
1198
|
+
stmt.getInitializer(),
|
|
1199
|
+
stmt.getCondition(),
|
|
1200
|
+
stmt.getIncrementor()
|
|
1201
|
+
].filter((n) => n !== void 0);
|
|
1202
|
+
}
|
|
1203
|
+
if (import_ts_morph8.Node.isTryStatement(stmt)) {
|
|
1204
|
+
return [];
|
|
1205
|
+
}
|
|
1206
|
+
if (import_ts_morph8.Node.isReturnStatement(stmt) || import_ts_morph8.Node.isThrowStatement(stmt)) {
|
|
1207
|
+
const value = stmt.getExpression();
|
|
1208
|
+
return value === void 0 ? [] : [value];
|
|
1209
|
+
}
|
|
1210
|
+
if (import_ts_morph8.Node.isBreakStatement(stmt) || import_ts_morph8.Node.isContinueStatement(stmt)) {
|
|
1211
|
+
return [];
|
|
1212
|
+
}
|
|
1213
|
+
return [stmt];
|
|
1214
|
+
}
|
|
1215
|
+
function lowerCallbacksIn(parts, ctx) {
|
|
1216
|
+
const bodies = [];
|
|
1217
|
+
const visit = (node, root) => {
|
|
1218
|
+
if (node !== root && isDescentStop(node, ctx.func, ctx.barriers)) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
if (node !== root && (import_ts_morph8.Node.isArrowFunction(node) || import_ts_morph8.Node.isFunctionExpression(node)) && isInlineCallback(node, ctx.func, ctx.barriers)) {
|
|
1222
|
+
const body = node.getBody();
|
|
1223
|
+
if (body !== void 0 && import_ts_morph8.Node.isBlock(body)) {
|
|
1224
|
+
bodies.push(lowerList(body.getStatements(), ctx));
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
} else if (node !== root && startsItsOwnScope(node)) {
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
for (const child of node.getChildren()) {
|
|
1231
|
+
visit(child, root);
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
for (const part of parts) {
|
|
1235
|
+
visit(part, part);
|
|
1236
|
+
}
|
|
1237
|
+
return bodies;
|
|
1238
|
+
}
|
|
1239
|
+
function lowerExpressionBodyCallbacks(expression, func, barriers = NO_BARRIERS) {
|
|
1240
|
+
return lowerCallbacksIn([expression], {
|
|
1241
|
+
func,
|
|
1242
|
+
barriers,
|
|
1243
|
+
rawToStructured: /* @__PURE__ */ new Map()
|
|
1244
|
+
});
|
|
1142
1245
|
}
|
|
1143
1246
|
function spliceBlocks(stmts) {
|
|
1144
1247
|
return stmts.flatMap(
|
|
1145
|
-
(s) =>
|
|
1248
|
+
(s) => import_ts_morph8.Node.isBlock(s) ? spliceBlocks(s.getStatements()) : [s]
|
|
1146
1249
|
);
|
|
1147
1250
|
}
|
|
1148
|
-
function buildStructured(stmt,
|
|
1149
|
-
if (
|
|
1251
|
+
function buildStructured(stmt, ctx) {
|
|
1252
|
+
if (import_ts_morph8.Node.isIfStatement(stmt)) {
|
|
1150
1253
|
const elseBranch = stmt.getElseStatement();
|
|
1151
1254
|
return {
|
|
1152
1255
|
kind: "if",
|
|
1153
1256
|
condition: conditionOf(stmt.getExpression()),
|
|
1154
|
-
thenBody: lowerList(
|
|
1155
|
-
|
|
1156
|
-
rawToStructured
|
|
1157
|
-
),
|
|
1158
|
-
elseBody: elseBranch === void 0 ? null : lowerList(statementsOf(elseBranch), rawToStructured),
|
|
1257
|
+
thenBody: lowerList(statementsOf(stmt.getThenStatement()), ctx),
|
|
1258
|
+
elseBody: elseBranch === void 0 ? null : lowerList(statementsOf(elseBranch), ctx),
|
|
1159
1259
|
exitKind: exitKindOf(stmt)
|
|
1160
1260
|
};
|
|
1161
1261
|
}
|
|
1162
|
-
if (
|
|
1262
|
+
if (import_ts_morph8.Node.isSwitchStatement(stmt)) {
|
|
1163
1263
|
return {
|
|
1164
1264
|
kind: "switch",
|
|
1165
|
-
groups: lowerSwitchGroups(stmt,
|
|
1265
|
+
groups: lowerSwitchGroups(stmt, ctx),
|
|
1166
1266
|
exitKind: exitKindOf(stmt)
|
|
1167
1267
|
};
|
|
1168
1268
|
}
|
|
@@ -1170,36 +1270,36 @@ function buildStructured(stmt, rawToStructured) {
|
|
|
1170
1270
|
return {
|
|
1171
1271
|
kind: "loop",
|
|
1172
1272
|
condition: { sourceText: loopHeaderText(stmt), expression: null },
|
|
1173
|
-
body: lowerList(statementsOf(getLoopBody(stmt)),
|
|
1273
|
+
body: lowerList(statementsOf(getLoopBody(stmt)), ctx),
|
|
1174
1274
|
exitKind: exitKindOf(stmt)
|
|
1175
1275
|
};
|
|
1176
1276
|
}
|
|
1177
|
-
if (
|
|
1277
|
+
if (import_ts_morph8.Node.isTryStatement(stmt)) {
|
|
1178
1278
|
const catchClause = stmt.getCatchClause();
|
|
1179
1279
|
const finallyBlock = stmt.getFinallyBlock();
|
|
1180
1280
|
return {
|
|
1181
1281
|
kind: "try",
|
|
1182
|
-
tryBody: lowerList(stmt.getTryBlock().getStatements(),
|
|
1183
|
-
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(),
|
|
1184
|
-
finallyBody: finallyBlock === void 0 ? null : lowerList(finallyBlock.getStatements(),
|
|
1282
|
+
tryBody: lowerList(stmt.getTryBlock().getStatements(), ctx),
|
|
1283
|
+
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(), ctx),
|
|
1284
|
+
finallyBody: finallyBlock === void 0 ? null : lowerList(finallyBlock.getStatements(), ctx),
|
|
1185
1285
|
exitKind: exitKindOf(stmt)
|
|
1186
1286
|
};
|
|
1187
1287
|
}
|
|
1188
|
-
if (
|
|
1288
|
+
if (import_ts_morph8.Node.isReturnStatement(stmt)) {
|
|
1189
1289
|
return { kind: "exit", exit: "return", exitKind: exitKindOf(stmt) };
|
|
1190
1290
|
}
|
|
1191
|
-
if (
|
|
1291
|
+
if (import_ts_morph8.Node.isThrowStatement(stmt)) {
|
|
1192
1292
|
return { kind: "exit", exit: "throw", exitKind: exitKindOf(stmt) };
|
|
1193
1293
|
}
|
|
1194
|
-
if (
|
|
1294
|
+
if (import_ts_morph8.Node.isBreakStatement(stmt)) {
|
|
1195
1295
|
return { kind: "exit", exit: "break", exitKind: exitKindOf(stmt) };
|
|
1196
1296
|
}
|
|
1197
|
-
if (
|
|
1297
|
+
if (import_ts_morph8.Node.isContinueStatement(stmt)) {
|
|
1198
1298
|
return { kind: "exit", exit: "continue", exitKind: exitKindOf(stmt) };
|
|
1199
1299
|
}
|
|
1200
1300
|
return { kind: "opaque", exitKind: exitKindOf(stmt) };
|
|
1201
1301
|
}
|
|
1202
|
-
function lowerSwitchGroups(stmt,
|
|
1302
|
+
function lowerSwitchGroups(stmt, ctx) {
|
|
1203
1303
|
const switchText = stmt.getExpression().getText();
|
|
1204
1304
|
const groups = [];
|
|
1205
1305
|
let pendingLabels = [];
|
|
@@ -1208,7 +1308,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1208
1308
|
if (sawDefault) {
|
|
1209
1309
|
throw new import_extractor.UnmodeledFlow("default clause is not last");
|
|
1210
1310
|
}
|
|
1211
|
-
if (
|
|
1311
|
+
if (import_ts_morph8.Node.isDefaultClause(clause)) {
|
|
1212
1312
|
sawDefault = true;
|
|
1213
1313
|
const stmts2 = clause.getStatements();
|
|
1214
1314
|
if (stmts2.length === 0) {
|
|
@@ -1216,11 +1316,11 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1216
1316
|
}
|
|
1217
1317
|
groups.push({
|
|
1218
1318
|
condition: null,
|
|
1219
|
-
...lowerGroupBody(stmts2,
|
|
1319
|
+
...lowerGroupBody(stmts2, ctx)
|
|
1220
1320
|
});
|
|
1221
1321
|
continue;
|
|
1222
1322
|
}
|
|
1223
|
-
if (!
|
|
1323
|
+
if (!import_ts_morph8.Node.isCaseClause(clause)) {
|
|
1224
1324
|
continue;
|
|
1225
1325
|
}
|
|
1226
1326
|
pendingLabels.push(clause.getExpression().getText());
|
|
@@ -1233,7 +1333,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1233
1333
|
const sourceText = labels.map((l) => `${switchText} === ${l}`).join(" || ");
|
|
1234
1334
|
groups.push({
|
|
1235
1335
|
condition: { sourceText, expression: null },
|
|
1236
|
-
...lowerGroupBody(stmts,
|
|
1336
|
+
...lowerGroupBody(stmts, ctx)
|
|
1237
1337
|
});
|
|
1238
1338
|
}
|
|
1239
1339
|
return groups;
|
|
@@ -1241,41 +1341,42 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1241
1341
|
function validateClauseBreaks(stmts) {
|
|
1242
1342
|
const last = stmts[stmts.length - 1];
|
|
1243
1343
|
for (const stmt of stmts) {
|
|
1244
|
-
if (stmt === last &&
|
|
1344
|
+
if (stmt === last && import_ts_morph8.Node.isBreakStatement(stmt)) {
|
|
1245
1345
|
continue;
|
|
1246
1346
|
}
|
|
1247
|
-
if (
|
|
1347
|
+
if (import_ts_morph8.Node.isSwitchStatement(stmt) || isLoop(stmt)) {
|
|
1248
1348
|
continue;
|
|
1249
1349
|
}
|
|
1250
1350
|
stmt.forEachDescendant((node, traversal) => {
|
|
1251
|
-
if (
|
|
1351
|
+
if (startsItsOwnScope(node) || import_ts_morph8.Node.isSwitchStatement(node) || isLoop(node)) {
|
|
1252
1352
|
traversal.skip();
|
|
1253
1353
|
return;
|
|
1254
1354
|
}
|
|
1255
|
-
if (
|
|
1355
|
+
if (import_ts_morph8.Node.isBreakStatement(node)) {
|
|
1256
1356
|
throw new import_extractor.UnmodeledFlow("non-trailing break in switch clause");
|
|
1257
1357
|
}
|
|
1258
1358
|
});
|
|
1259
|
-
if (
|
|
1359
|
+
if (import_ts_morph8.Node.isBreakStatement(stmt)) {
|
|
1260
1360
|
throw new import_extractor.UnmodeledFlow("non-trailing break in switch clause");
|
|
1261
1361
|
}
|
|
1262
1362
|
}
|
|
1263
1363
|
}
|
|
1264
|
-
function lowerGroupBody(rawStmts,
|
|
1364
|
+
function lowerGroupBody(rawStmts, ctx) {
|
|
1265
1365
|
const stmts = spliceBlocks(rawStmts);
|
|
1266
1366
|
validateClauseBreaks(stmts);
|
|
1267
1367
|
const last = stmts[stmts.length - 1];
|
|
1268
|
-
const hasTrailingBreak = last !== void 0 &&
|
|
1368
|
+
const hasTrailingBreak = last !== void 0 && import_ts_morph8.Node.isBreakStatement(last);
|
|
1269
1369
|
const kept = hasTrailingBreak ? stmts.slice(0, -1) : stmts;
|
|
1270
|
-
const body = lowerList(kept,
|
|
1370
|
+
const body = lowerList(kept, ctx);
|
|
1271
1371
|
if (hasTrailingBreak && last !== void 0) {
|
|
1272
|
-
lowerStatement(last,
|
|
1372
|
+
lowerStatement(last, ctx);
|
|
1273
1373
|
}
|
|
1274
1374
|
return { hasTrailingBreak, body };
|
|
1275
1375
|
}
|
|
1276
|
-
function lowerFunctionBody(body, terminalNodes) {
|
|
1376
|
+
function lowerFunctionBody(body, terminalNodes, func = body, barriers = NO_BARRIERS) {
|
|
1277
1377
|
const rawToStructured = /* @__PURE__ */ new Map();
|
|
1278
|
-
const
|
|
1378
|
+
const ctx = { func, barriers, rawToStructured };
|
|
1379
|
+
const statements = lowerList(body.getStatements(), ctx);
|
|
1279
1380
|
const terminalsByStmt = /* @__PURE__ */ new Map();
|
|
1280
1381
|
const terminalHomeRaw = /* @__PURE__ */ new Map();
|
|
1281
1382
|
for (const terminal of terminalNodes) {
|
|
@@ -1297,7 +1398,7 @@ function lowerFunctionBody(body, terminalNodes) {
|
|
|
1297
1398
|
function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
1298
1399
|
let current2 = terminal;
|
|
1299
1400
|
while (current2 !== void 0 && current2 !== body) {
|
|
1300
|
-
if (
|
|
1401
|
+
if (import_ts_morph8.Node.isStatement(current2) && rawToStructured.has(current2)) {
|
|
1301
1402
|
return current2;
|
|
1302
1403
|
}
|
|
1303
1404
|
current2 = current2.getParent();
|
|
@@ -1306,39 +1407,42 @@ function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
|
1306
1407
|
}
|
|
1307
1408
|
|
|
1308
1409
|
// src/paths/pathConditions.ts
|
|
1309
|
-
function containsUnmodeledFlow(body) {
|
|
1410
|
+
function containsUnmodeledFlow(body, func, barriers) {
|
|
1310
1411
|
let found = false;
|
|
1311
1412
|
body.forEachDescendant((node, traversal) => {
|
|
1312
|
-
if (
|
|
1413
|
+
if (isDescentStop(node, func, barriers)) {
|
|
1313
1414
|
traversal.skip();
|
|
1314
1415
|
return;
|
|
1315
1416
|
}
|
|
1316
|
-
if (
|
|
1417
|
+
if (import_ts_morph9.Node.isLabeledStatement(node)) {
|
|
1317
1418
|
found = true;
|
|
1318
1419
|
traversal.stop();
|
|
1319
1420
|
}
|
|
1320
1421
|
});
|
|
1321
1422
|
return found;
|
|
1322
1423
|
}
|
|
1323
|
-
function
|
|
1424
|
+
function loweredExpressionBody(body, terminalNodes, func, barriers) {
|
|
1425
|
+
const statement = {
|
|
1426
|
+
kind: "opaque",
|
|
1427
|
+
exitKind: null,
|
|
1428
|
+
callbacks: lowerExpressionBodyCallbacks(body, func, barriers)
|
|
1429
|
+
};
|
|
1430
|
+
return {
|
|
1431
|
+
statements: [statement],
|
|
1432
|
+
terminalsByStmt: /* @__PURE__ */ new Map([[statement, terminalNodes]]),
|
|
1433
|
+
terminalHomeRaw: /* @__PURE__ */ new Map()
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function computePathConditions(func, terminalNodes, barriers = NO_BARRIERS) {
|
|
1324
1437
|
const body = func.getBody();
|
|
1325
1438
|
if (body === void 0) {
|
|
1326
1439
|
return { byTerminal: /* @__PURE__ */ new Map(), fallthrough: [] };
|
|
1327
1440
|
}
|
|
1328
|
-
if (
|
|
1329
|
-
const byTerminal = /* @__PURE__ */ new Map();
|
|
1330
|
-
for (const terminal of terminalNodes) {
|
|
1331
|
-
byTerminal.set(terminal, [
|
|
1332
|
-
collectAncestorConditionInfosBelow(terminal, func)
|
|
1333
|
-
]);
|
|
1334
|
-
}
|
|
1335
|
-
return { byTerminal, fallthrough: [] };
|
|
1336
|
-
}
|
|
1337
|
-
if (containsUnmodeledFlow(body)) {
|
|
1441
|
+
if (containsUnmodeledFlow(body, func, barriers)) {
|
|
1338
1442
|
return degradedResult(func, terminalNodes, "labeled statement");
|
|
1339
1443
|
}
|
|
1340
1444
|
try {
|
|
1341
|
-
const lowered = lowerFunctionBody(body, terminalNodes);
|
|
1445
|
+
const lowered = import_ts_morph9.Node.isBlock(body) ? lowerFunctionBody(body, terminalNodes, func, barriers) : loweredExpressionBody(body, terminalNodes, func, barriers);
|
|
1342
1446
|
const result = (0, import_extractor2.enumerateStructuredPaths)({
|
|
1343
1447
|
statements: lowered.statements,
|
|
1344
1448
|
terminalsByStmt: lowered.terminalsByStmt
|
|
@@ -1405,12 +1509,12 @@ function lineAt(node, pos) {
|
|
|
1405
1509
|
}
|
|
1406
1510
|
|
|
1407
1511
|
// src/moduleExports.ts
|
|
1408
|
-
var
|
|
1512
|
+
var import_ts_morph11 = require("ts-morph");
|
|
1409
1513
|
|
|
1410
1514
|
// src/bootstrap/lazyProjectInit.ts
|
|
1411
1515
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
1412
1516
|
var import_node_path = __toESM(require("path"), 1);
|
|
1413
|
-
var
|
|
1517
|
+
var import_ts_morph10 = require("ts-morph");
|
|
1414
1518
|
|
|
1415
1519
|
// src/facts/moduleGraph.ts
|
|
1416
1520
|
var import_datalog = require("@suss/datalog");
|
|
@@ -1828,10 +1932,10 @@ function readSpecifierPaths(project, filePath, options, host) {
|
|
|
1828
1932
|
if (text === null) {
|
|
1829
1933
|
return [];
|
|
1830
1934
|
}
|
|
1831
|
-
const scanned =
|
|
1935
|
+
const scanned = import_ts_morph10.ts.preProcessFile(text, true, true);
|
|
1832
1936
|
const paths = [];
|
|
1833
1937
|
for (const imported of scanned.importedFiles) {
|
|
1834
|
-
const resolved =
|
|
1938
|
+
const resolved = import_ts_morph10.ts.resolveModuleName(
|
|
1835
1939
|
imported.fileName,
|
|
1836
1940
|
filePath,
|
|
1837
1941
|
options,
|
|
@@ -1855,13 +1959,13 @@ function readFileText(project, filePath) {
|
|
|
1855
1959
|
}
|
|
1856
1960
|
}
|
|
1857
1961
|
function parseTsconfig(tsConfigFilePath) {
|
|
1858
|
-
const configFile =
|
|
1962
|
+
const configFile = import_ts_morph10.ts.readConfigFile(tsConfigFilePath, import_ts_morph10.ts.sys.readFile);
|
|
1859
1963
|
if (configFile.error !== void 0) {
|
|
1860
1964
|
return { fileNames: [], options: {} };
|
|
1861
1965
|
}
|
|
1862
|
-
const parsed =
|
|
1966
|
+
const parsed = import_ts_morph10.ts.parseJsonConfigFileContent(
|
|
1863
1967
|
configFile.config,
|
|
1864
|
-
|
|
1968
|
+
import_ts_morph10.ts.sys,
|
|
1865
1969
|
import_node_path.default.dirname(tsConfigFilePath),
|
|
1866
1970
|
/*existingOptions*/
|
|
1867
1971
|
void 0,
|
|
@@ -1921,17 +2025,17 @@ function addImportersOfMatches(fileImports, matched, options) {
|
|
|
1921
2025
|
}
|
|
1922
2026
|
function internalSpecifierResolver(files, options) {
|
|
1923
2027
|
const fileSet = new Set(files);
|
|
1924
|
-
const cache =
|
|
1925
|
-
|
|
2028
|
+
const cache = import_ts_morph10.ts.createModuleResolutionCache(
|
|
2029
|
+
import_ts_morph10.ts.sys.getCurrentDirectory(),
|
|
1926
2030
|
(name) => name,
|
|
1927
2031
|
options
|
|
1928
2032
|
);
|
|
1929
2033
|
return (fromFile, spec) => {
|
|
1930
|
-
const resolved =
|
|
2034
|
+
const resolved = import_ts_morph10.ts.resolveModuleName(
|
|
1931
2035
|
spec,
|
|
1932
2036
|
fromFile,
|
|
1933
2037
|
options,
|
|
1934
|
-
|
|
2038
|
+
import_ts_morph10.ts.sys,
|
|
1935
2039
|
cache
|
|
1936
2040
|
).resolvedModule?.resolvedFileName;
|
|
1937
2041
|
if (resolved === void 0) {
|
|
@@ -1940,7 +2044,7 @@ function internalSpecifierResolver(files, options) {
|
|
|
1940
2044
|
if (fileSet.has(resolved)) {
|
|
1941
2045
|
return resolved;
|
|
1942
2046
|
}
|
|
1943
|
-
const real =
|
|
2047
|
+
const real = import_ts_morph10.ts.sys.realpath?.(resolved) ?? resolved;
|
|
1944
2048
|
return fileSet.has(real) ? real : null;
|
|
1945
2049
|
};
|
|
1946
2050
|
}
|
|
@@ -1966,7 +2070,7 @@ async function readImportsConcurrently(paths) {
|
|
|
1966
2070
|
const p = paths[i];
|
|
1967
2071
|
try {
|
|
1968
2072
|
const text = await import_promises.default.readFile(p, "utf-8");
|
|
1969
|
-
const pre =
|
|
2073
|
+
const pre = import_ts_morph10.ts.preProcessFile(text, true, false);
|
|
1970
2074
|
results[i] = {
|
|
1971
2075
|
path: p,
|
|
1972
2076
|
importedModules: pre.importedFiles.map((f) => f.fileName)
|
|
@@ -1984,6 +2088,30 @@ async function readImportsConcurrently(paths) {
|
|
|
1984
2088
|
return results;
|
|
1985
2089
|
}
|
|
1986
2090
|
|
|
2091
|
+
// src/depTracking.ts
|
|
2092
|
+
function createDependencySink() {
|
|
2093
|
+
return { files: /* @__PURE__ */ new Set(), mountPrefixes: /* @__PURE__ */ new Map(), claims: [] };
|
|
2094
|
+
}
|
|
2095
|
+
var activeSink = null;
|
|
2096
|
+
function withDependencySink(sink, fn) {
|
|
2097
|
+
const previous = activeSink;
|
|
2098
|
+
activeSink = sink;
|
|
2099
|
+
try {
|
|
2100
|
+
return fn();
|
|
2101
|
+
} finally {
|
|
2102
|
+
activeSink = previous;
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
function recordFileDependency(filePath) {
|
|
2106
|
+
activeSink?.files.add(filePath);
|
|
2107
|
+
}
|
|
2108
|
+
function recordMountPrefix(childId, prefix) {
|
|
2109
|
+
activeSink?.mountPrefixes.set(childId, prefix);
|
|
2110
|
+
}
|
|
2111
|
+
function recordUnitClaim(key, pack) {
|
|
2112
|
+
activeSink?.claims.push({ key, pack });
|
|
2113
|
+
}
|
|
2114
|
+
|
|
1987
2115
|
// src/perFileCache.ts
|
|
1988
2116
|
function createPerFileCache() {
|
|
1989
2117
|
const byParse = /* @__PURE__ */ new WeakMap();
|
|
@@ -1999,6 +2127,7 @@ function createPerFileCache() {
|
|
|
1999
2127
|
|
|
2000
2128
|
// src/moduleExports.ts
|
|
2001
2129
|
function exportedDeclarationsOf(sourceFile) {
|
|
2130
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
2002
2131
|
const cached = exportsByFile.get(sourceFile);
|
|
2003
2132
|
if (cached !== void 0) {
|
|
2004
2133
|
return cached;
|
|
@@ -2013,7 +2142,14 @@ function resolveAliasedSymbol(symbol) {
|
|
|
2013
2142
|
warmReExportChains(declaration.getSourceFile(), "every import");
|
|
2014
2143
|
}
|
|
2015
2144
|
try {
|
|
2016
|
-
|
|
2145
|
+
const aliased = symbol.getAliasedSymbol();
|
|
2146
|
+
for (const declaration of aliased?.getDeclarations() ?? []) {
|
|
2147
|
+
const file = declaration.getSourceFile();
|
|
2148
|
+
if (!file.isInNodeModules()) {
|
|
2149
|
+
recordFileDependency(file.getFilePath());
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return aliased;
|
|
2017
2153
|
} catch (error) {
|
|
2018
2154
|
if (!(error instanceof RangeError)) {
|
|
2019
2155
|
throw error;
|
|
@@ -2128,7 +2264,7 @@ function reExportShapeOf(file, reach) {
|
|
|
2128
2264
|
for (const assignment of file.getExportAssignments()) {
|
|
2129
2265
|
exportNodes.push(assignment);
|
|
2130
2266
|
const expression = assignment.getExpression();
|
|
2131
|
-
if (
|
|
2267
|
+
if (import_ts_morph11.Node.isIdentifier(expression)) {
|
|
2132
2268
|
localNames.add(expression.getText());
|
|
2133
2269
|
}
|
|
2134
2270
|
}
|
|
@@ -2204,38 +2340,6 @@ function reportUnreadableExports(file) {
|
|
|
2204
2340
|
);
|
|
2205
2341
|
}
|
|
2206
2342
|
|
|
2207
|
-
// src/walk/descent.ts
|
|
2208
|
-
var import_ts_morph11 = require("ts-morph");
|
|
2209
|
-
var NO_BARRIERS = /* @__PURE__ */ new Set();
|
|
2210
|
-
function isDescentStop(node, func, barriers = NO_BARRIERS) {
|
|
2211
|
-
if (node === func) {
|
|
2212
|
-
return false;
|
|
2213
|
-
}
|
|
2214
|
-
if (import_ts_morph11.Node.isFunctionDeclaration(node) || import_ts_morph11.Node.isMethodDeclaration(node)) {
|
|
2215
|
-
return true;
|
|
2216
|
-
}
|
|
2217
|
-
if (import_ts_morph11.Node.isArrowFunction(node) || import_ts_morph11.Node.isFunctionExpression(node)) {
|
|
2218
|
-
return barriers.has(node);
|
|
2219
|
-
}
|
|
2220
|
-
return false;
|
|
2221
|
-
}
|
|
2222
|
-
function isModuleScopeStop(node) {
|
|
2223
|
-
return import_ts_morph11.Node.isFunctionDeclaration(node) || import_ts_morph11.Node.isMethodDeclaration(node) || import_ts_morph11.Node.isArrowFunction(node) || import_ts_morph11.Node.isFunctionExpression(node) || import_ts_morph11.Node.isClassDeclaration(node) || import_ts_morph11.Node.isClassExpression(node);
|
|
2224
|
-
}
|
|
2225
|
-
function crossesNestedFunctionScope(node, func) {
|
|
2226
|
-
let current2 = node;
|
|
2227
|
-
while (current2 !== void 0 && current2 !== func) {
|
|
2228
|
-
if (startsItsOwnScope(current2)) {
|
|
2229
|
-
return true;
|
|
2230
|
-
}
|
|
2231
|
-
current2 = current2.getParent();
|
|
2232
|
-
}
|
|
2233
|
-
return false;
|
|
2234
|
-
}
|
|
2235
|
-
function startsItsOwnScope(node) {
|
|
2236
|
-
return import_ts_morph11.Node.isArrowFunction(node) || import_ts_morph11.Node.isFunctionExpression(node) || import_ts_morph11.Node.isFunctionDeclaration(node) || import_ts_morph11.Node.isMethodDeclaration(node) || import_ts_morph11.Node.isGetAccessorDeclaration(node) || import_ts_morph11.Node.isSetAccessorDeclaration(node) || import_ts_morph11.Node.isConstructorDeclaration(node);
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
2343
|
// src/resolve/invocationEffects.ts
|
|
2240
2344
|
function isImportedFrom(identifier, expectedModule) {
|
|
2241
2345
|
if (!import_ts_morph12.Node.isIdentifier(identifier)) {
|
|
@@ -4940,7 +5044,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4940
5044
|
];
|
|
4941
5045
|
const { byTerminal } = computePathConditions(
|
|
4942
5046
|
func,
|
|
4943
|
-
terminals.map(({ node }) => node)
|
|
5047
|
+
terminals.map(({ node }) => node),
|
|
5048
|
+
barriers
|
|
4944
5049
|
);
|
|
4945
5050
|
const wantsFallthrough = terminalPatterns.some(
|
|
4946
5051
|
(p) => p.match.type === "functionFallthrough"
|
|
@@ -4952,7 +5057,11 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4952
5057
|
if (!hasDefaultTerminal) {
|
|
4953
5058
|
const synthetic = makeFallthroughTerminal(func);
|
|
4954
5059
|
terminals.push(synthetic);
|
|
4955
|
-
const pathResult = computePathConditions(
|
|
5060
|
+
const pathResult = computePathConditions(
|
|
5061
|
+
func,
|
|
5062
|
+
[synthetic.node],
|
|
5063
|
+
barriers
|
|
5064
|
+
);
|
|
4956
5065
|
byTerminal.set(
|
|
4957
5066
|
synthetic.node,
|
|
4958
5067
|
pathResult.fallthrough.length > 0 ? pathResult.fallthrough : [[]]
|
|
@@ -5083,7 +5192,7 @@ function indexFunctions(sf) {
|
|
|
5083
5192
|
var import_node_crypto2 = require("crypto");
|
|
5084
5193
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
5085
5194
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
5086
|
-
var SCHEMA_VERSION = "
|
|
5195
|
+
var SCHEMA_VERSION = "6";
|
|
5087
5196
|
var MAX_ENTRIES = 2;
|
|
5088
5197
|
var ENTRY_PREFIX = "key-";
|
|
5089
5198
|
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
@@ -5095,6 +5204,7 @@ function createCacheLayer(cacheDir) {
|
|
|
5095
5204
|
kind: "miss",
|
|
5096
5205
|
diagnostic: { kind: "miss", missReason: "no-manifest" }
|
|
5097
5206
|
}),
|
|
5207
|
+
plan: async () => null,
|
|
5098
5208
|
write: async () => {
|
|
5099
5209
|
}
|
|
5100
5210
|
};
|
|
@@ -5122,20 +5232,36 @@ function createCacheLayer(cacheDir) {
|
|
|
5122
5232
|
return {
|
|
5123
5233
|
kind: "hit",
|
|
5124
5234
|
summaries: manifest.summaries,
|
|
5235
|
+
...manifest.projectRoot === void 0 ? {} : { projectRoot: manifest.projectRoot },
|
|
5125
5236
|
diagnostic: { kind: "hit" }
|
|
5126
5237
|
};
|
|
5127
5238
|
},
|
|
5128
|
-
async
|
|
5239
|
+
async plan(input) {
|
|
5240
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5241
|
+
const manifest = await readManifest(import_node_path2.default.join(entryDir, "manifest.json"));
|
|
5242
|
+
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
5243
|
+
return null;
|
|
5244
|
+
}
|
|
5245
|
+
const currentTsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5246
|
+
if (!fileStampEquals(manifest.tsconfigStamp, currentTsconfigStamp)) {
|
|
5247
|
+
return null;
|
|
5248
|
+
}
|
|
5249
|
+
await markUsed(entryDir);
|
|
5250
|
+
return buildPlan(manifest, await resolveFileStamps(input));
|
|
5251
|
+
},
|
|
5252
|
+
async write(input, summaries, attribution) {
|
|
5253
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5254
|
+
const previous = await readManifest(import_node_path2.default.join(entryDir, "manifest.json"));
|
|
5129
5255
|
const tsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5130
|
-
const files = await resolveFileStamps(input);
|
|
5256
|
+
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
5131
5257
|
const manifest = {
|
|
5132
5258
|
schemaVersion: SCHEMA_VERSION,
|
|
5133
5259
|
adapterPacksDigest: input.adapterPacksDigest,
|
|
5134
5260
|
tsconfigStamp,
|
|
5135
5261
|
files,
|
|
5136
|
-
summaries
|
|
5262
|
+
summaries,
|
|
5263
|
+
...attribution === void 0 ? {} : encodeAttribution(attribution)
|
|
5137
5264
|
};
|
|
5138
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
5139
5265
|
await import_promises2.default.mkdir(entryDir, { recursive: true });
|
|
5140
5266
|
await import_promises2.default.writeFile(
|
|
5141
5267
|
import_node_path2.default.join(entryDir, "manifest.json"),
|
|
@@ -5145,6 +5271,171 @@ function createCacheLayer(cacheDir) {
|
|
|
5145
5271
|
}
|
|
5146
5272
|
};
|
|
5147
5273
|
}
|
|
5274
|
+
async function buildPlan(manifest, currentStamps) {
|
|
5275
|
+
const stored = new Map(manifest.files.map((f) => [f.path, f]));
|
|
5276
|
+
const current2 = new Map(currentStamps.map((f) => [f.path, f]));
|
|
5277
|
+
const changed = /* @__PURE__ */ new Set();
|
|
5278
|
+
const removed = /* @__PURE__ */ new Set();
|
|
5279
|
+
for (const p of stored.keys()) {
|
|
5280
|
+
if (!current2.has(p)) {
|
|
5281
|
+
removed.add(p);
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
const toVerify = [];
|
|
5285
|
+
for (const [p, stamp] of current2) {
|
|
5286
|
+
const before = stored.get(p);
|
|
5287
|
+
if (before === void 0) {
|
|
5288
|
+
changed.add(p);
|
|
5289
|
+
} else if (!fileStampEquals(before, stamp)) {
|
|
5290
|
+
if (before.contentHash === void 0) {
|
|
5291
|
+
changed.add(p);
|
|
5292
|
+
} else {
|
|
5293
|
+
toVerify.push(p);
|
|
5294
|
+
}
|
|
5295
|
+
}
|
|
5296
|
+
}
|
|
5297
|
+
await Promise.all(
|
|
5298
|
+
toVerify.map(async (p) => {
|
|
5299
|
+
const hash = await hashFile(p);
|
|
5300
|
+
if (hash === null || hash !== stored.get(p)?.contentHash) {
|
|
5301
|
+
changed.add(p);
|
|
5302
|
+
}
|
|
5303
|
+
})
|
|
5304
|
+
);
|
|
5305
|
+
const roots = /* @__PURE__ */ new Map();
|
|
5306
|
+
const rootNames = manifest.roots ?? [];
|
|
5307
|
+
const depPaths = manifest.depPaths ?? [];
|
|
5308
|
+
let rootsDeclined = 0;
|
|
5309
|
+
rootNames.forEach((rootPath, i) => {
|
|
5310
|
+
const meta = manifest.rootMeta?.[i];
|
|
5311
|
+
if (meta === void 0) {
|
|
5312
|
+
return;
|
|
5313
|
+
}
|
|
5314
|
+
if (!meta.cacheable) {
|
|
5315
|
+
rootsDeclined += 1;
|
|
5316
|
+
}
|
|
5317
|
+
roots.set(rootPath, {
|
|
5318
|
+
path: rootPath,
|
|
5319
|
+
cacheable: meta.cacheable,
|
|
5320
|
+
deps: meta.deps.flatMap((d) => {
|
|
5321
|
+
const p = depPaths[d];
|
|
5322
|
+
return p === void 0 ? [] : [p];
|
|
5323
|
+
}),
|
|
5324
|
+
claims: meta.claims,
|
|
5325
|
+
mountPrefixes: meta.mountPrefixes,
|
|
5326
|
+
packs: meta.packs
|
|
5327
|
+
});
|
|
5328
|
+
});
|
|
5329
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
5330
|
+
for (const [rootPath, record] of roots) {
|
|
5331
|
+
if (!record.cacheable || !current2.has(rootPath)) {
|
|
5332
|
+
continue;
|
|
5333
|
+
}
|
|
5334
|
+
if (changed.has(rootPath)) {
|
|
5335
|
+
continue;
|
|
5336
|
+
}
|
|
5337
|
+
const depMoved = record.deps.some((d) => changed.has(d) || removed.has(d));
|
|
5338
|
+
if (!depMoved) {
|
|
5339
|
+
validRoots.add(rootPath);
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5342
|
+
const owners = manifest.owners ?? [];
|
|
5343
|
+
return {
|
|
5344
|
+
changed,
|
|
5345
|
+
removed,
|
|
5346
|
+
roots,
|
|
5347
|
+
validRoots,
|
|
5348
|
+
rootsDeclined,
|
|
5349
|
+
storedProjectRoot: manifest.projectRoot ?? null,
|
|
5350
|
+
reuse(valid) {
|
|
5351
|
+
const summaries = [];
|
|
5352
|
+
const reusedOwners = [];
|
|
5353
|
+
manifest.summaries.forEach((summary, i) => {
|
|
5354
|
+
const ownerPaths = (owners[i] ?? []).flatMap((o) => {
|
|
5355
|
+
const p = rootNames[o];
|
|
5356
|
+
return p === void 0 ? [] : [p];
|
|
5357
|
+
});
|
|
5358
|
+
if (ownerPaths.some((p) => valid.has(p))) {
|
|
5359
|
+
summaries.push(summary);
|
|
5360
|
+
reusedOwners.push(ownerPaths.filter((p) => valid.has(p)));
|
|
5361
|
+
}
|
|
5362
|
+
});
|
|
5363
|
+
return { summaries, owners: reusedOwners };
|
|
5364
|
+
},
|
|
5365
|
+
allSummaries() {
|
|
5366
|
+
return manifest.summaries;
|
|
5367
|
+
},
|
|
5368
|
+
attribution() {
|
|
5369
|
+
return {
|
|
5370
|
+
roots: [...roots.values()],
|
|
5371
|
+
owners: owners.map(
|
|
5372
|
+
(ownerIds) => ownerIds.flatMap((o) => {
|
|
5373
|
+
const p = rootNames[o];
|
|
5374
|
+
return p === void 0 ? [] : [p];
|
|
5375
|
+
})
|
|
5376
|
+
),
|
|
5377
|
+
...manifest.projectRoot === void 0 ? {} : { projectRoot: manifest.projectRoot }
|
|
5378
|
+
};
|
|
5379
|
+
}
|
|
5380
|
+
};
|
|
5381
|
+
}
|
|
5382
|
+
function encodeAttribution(attribution) {
|
|
5383
|
+
const roots = attribution.roots.map((r) => r.path);
|
|
5384
|
+
const rootIndex = new Map(roots.map((p, i) => [p, i]));
|
|
5385
|
+
const depIndex = /* @__PURE__ */ new Map();
|
|
5386
|
+
const depPaths = [];
|
|
5387
|
+
const depIdOf = (p) => {
|
|
5388
|
+
const existing = depIndex.get(p);
|
|
5389
|
+
if (existing !== void 0) {
|
|
5390
|
+
return existing;
|
|
5391
|
+
}
|
|
5392
|
+
const id = depPaths.length;
|
|
5393
|
+
depPaths.push(p);
|
|
5394
|
+
depIndex.set(p, id);
|
|
5395
|
+
return id;
|
|
5396
|
+
};
|
|
5397
|
+
const rootMeta = attribution.roots.map((r) => ({
|
|
5398
|
+
cacheable: r.cacheable,
|
|
5399
|
+
deps: r.deps.map(depIdOf),
|
|
5400
|
+
claims: r.claims,
|
|
5401
|
+
mountPrefixes: r.mountPrefixes,
|
|
5402
|
+
packs: r.packs
|
|
5403
|
+
}));
|
|
5404
|
+
const owners = attribution.owners.map(
|
|
5405
|
+
(ownerPaths) => ownerPaths.flatMap((p) => {
|
|
5406
|
+
const i = rootIndex.get(p);
|
|
5407
|
+
return i === void 0 ? [] : [i];
|
|
5408
|
+
})
|
|
5409
|
+
);
|
|
5410
|
+
return {
|
|
5411
|
+
roots,
|
|
5412
|
+
rootMeta,
|
|
5413
|
+
depPaths,
|
|
5414
|
+
owners,
|
|
5415
|
+
...attribution.projectRoot === void 0 ? {} : { projectRoot: attribution.projectRoot }
|
|
5416
|
+
};
|
|
5417
|
+
}
|
|
5418
|
+
async function hashStamps(stamps, previous) {
|
|
5419
|
+
const before = new Map((previous?.files ?? []).map((f) => [f.path, f]));
|
|
5420
|
+
return Promise.all(
|
|
5421
|
+
stamps.map(async (stamp) => {
|
|
5422
|
+
const prior = before.get(stamp.path);
|
|
5423
|
+
if (prior !== void 0 && prior.contentHash !== void 0 && fileStampEquals(prior, stamp)) {
|
|
5424
|
+
return { ...stamp, contentHash: prior.contentHash };
|
|
5425
|
+
}
|
|
5426
|
+
const contentHash = await hashFile(stamp.path);
|
|
5427
|
+
return contentHash === null ? stamp : { ...stamp, contentHash };
|
|
5428
|
+
})
|
|
5429
|
+
);
|
|
5430
|
+
}
|
|
5431
|
+
async function hashFile(filePath) {
|
|
5432
|
+
try {
|
|
5433
|
+
const content = await import_promises2.default.readFile(filePath);
|
|
5434
|
+
return (0, import_node_crypto2.createHash)("sha256").update(content).digest("hex").slice(0, 16);
|
|
5435
|
+
} catch {
|
|
5436
|
+
return null;
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5148
5439
|
async function describeAbsentEntry(cacheDir) {
|
|
5149
5440
|
try {
|
|
5150
5441
|
const entries = await import_promises2.default.readdir(cacheDir, { withFileTypes: true });
|
|
@@ -5158,7 +5449,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
5158
5449
|
SCHEMA_VERSION,
|
|
5159
5450
|
input.adapterPacksDigest,
|
|
5160
5451
|
input.tsconfigPath ?? ""
|
|
5161
|
-
].join("
|
|
5452
|
+
].join(" ");
|
|
5162
5453
|
const name = (0, import_node_crypto2.createHash)("sha256").update(key).digest("hex").slice(0, 16);
|
|
5163
5454
|
return import_node_path2.default.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
5164
5455
|
}
|
|
@@ -7010,7 +7301,7 @@ function calleeOf(decorator) {
|
|
|
7010
7301
|
|
|
7011
7302
|
// src/discovery/decoratedMethod.ts
|
|
7012
7303
|
function resolverTypeName(args) {
|
|
7013
|
-
return args.
|
|
7304
|
+
return args.typeMap[args.decoratorName] ?? args.classTypeName ?? null;
|
|
7014
7305
|
}
|
|
7015
7306
|
function resolveResolverClassTypeName(decoratorArg) {
|
|
7016
7307
|
if (import_ts_morph34.Node.isArrowFunction(decoratorArg)) {
|
|
@@ -9568,7 +9859,10 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
|
|
|
9568
9859
|
resolverInfo: {
|
|
9569
9860
|
typeName,
|
|
9570
9861
|
fieldName,
|
|
9571
|
-
...schemaSdl !== null ? {
|
|
9862
|
+
...schemaSdl !== null ? {
|
|
9863
|
+
schemaSdl,
|
|
9864
|
+
schemaDocument: config.getSourceFile().getFilePath()
|
|
9865
|
+
} : {}
|
|
9572
9866
|
}
|
|
9573
9867
|
});
|
|
9574
9868
|
}
|
|
@@ -9765,7 +10059,15 @@ function discoverUnits(sourceFile, patterns, resolution, mountPrefixes) {
|
|
|
9765
10059
|
}
|
|
9766
10060
|
|
|
9767
10061
|
// src/discovery/mountPrefix.ts
|
|
9768
|
-
var NO_MOUNTS = {
|
|
10062
|
+
var NO_MOUNTS = {
|
|
10063
|
+
// Recorded even with no mounts anywhere: a mount added later in some
|
|
10064
|
+
// other file changes this router's prefix without touching its file.
|
|
10065
|
+
effectivePrefixFor: (routerNode) => {
|
|
10066
|
+
recordMountPrefix(nodeId(routerNode), "");
|
|
10067
|
+
return "";
|
|
10068
|
+
},
|
|
10069
|
+
prefixForId: () => ""
|
|
10070
|
+
};
|
|
9769
10071
|
function buildMountPrefixIndex(packsByFile, resolution) {
|
|
9770
10072
|
const subjectIdsByPack = /* @__PURE__ */ new Map();
|
|
9771
10073
|
const mountWorkByPack = /* @__PURE__ */ new Map();
|
|
@@ -9822,10 +10124,15 @@ function buildMountPrefixIndex(packsByFile, resolution) {
|
|
|
9822
10124
|
return NO_MOUNTS;
|
|
9823
10125
|
}
|
|
9824
10126
|
const memo = /* @__PURE__ */ new Map();
|
|
10127
|
+
const byId = (childId) => resolvePrefix(edgesByChild, memo, childId, /* @__PURE__ */ new Set()) ?? "";
|
|
9825
10128
|
return {
|
|
9826
10129
|
effectivePrefixFor(routerNode) {
|
|
9827
|
-
|
|
9828
|
-
|
|
10130
|
+
const childId = nodeId(routerNode);
|
|
10131
|
+
const prefix = byId(childId);
|
|
10132
|
+
recordMountPrefix(childId, prefix);
|
|
10133
|
+
return prefix;
|
|
10134
|
+
},
|
|
10135
|
+
prefixForId: byId
|
|
9829
10136
|
};
|
|
9830
10137
|
}
|
|
9831
10138
|
function recordEdge(edgesByChild, candidate) {
|
|
@@ -10089,6 +10396,8 @@ var ResolutionStore = class {
|
|
|
10089
10396
|
fullyExtracted = /* @__PURE__ */ new Set();
|
|
10090
10397
|
seededValues = /* @__PURE__ */ new Set();
|
|
10091
10398
|
importedNames = /* @__PURE__ */ new Map();
|
|
10399
|
+
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
10400
|
+
lastQueryWalked = [];
|
|
10092
10401
|
declarations = /* @__PURE__ */ new Map();
|
|
10093
10402
|
graph = new ModuleGraph();
|
|
10094
10403
|
stale = true;
|
|
@@ -10149,7 +10458,10 @@ var ResolutionStore = class {
|
|
|
10149
10458
|
const declaration = `${nodeId(refersTo)}|${modules.join(",")}`;
|
|
10150
10459
|
const cached = this.importedNames.get(declaration);
|
|
10151
10460
|
if (cached !== void 0) {
|
|
10152
|
-
|
|
10461
|
+
for (const walkedPath of cached.walked) {
|
|
10462
|
+
recordFileDependency(walkedPath);
|
|
10463
|
+
}
|
|
10464
|
+
return cached.names;
|
|
10153
10465
|
}
|
|
10154
10466
|
const target = factKeyOf(value);
|
|
10155
10467
|
const found = this.resolveByWaves(
|
|
@@ -10157,7 +10469,10 @@ var ResolutionStore = class {
|
|
|
10157
10469
|
"wantedOrigin",
|
|
10158
10470
|
() => this.lookupImportedNames(target, modules)
|
|
10159
10471
|
) ?? [];
|
|
10160
|
-
this.importedNames.set(declaration,
|
|
10472
|
+
this.importedNames.set(declaration, {
|
|
10473
|
+
names: found,
|
|
10474
|
+
walked: [...this.lastQueryWalked]
|
|
10475
|
+
});
|
|
10161
10476
|
return found;
|
|
10162
10477
|
}
|
|
10163
10478
|
/**
|
|
@@ -10191,6 +10506,7 @@ var ResolutionStore = class {
|
|
|
10191
10506
|
this.wantValue(question, value);
|
|
10192
10507
|
this.seedValue(value);
|
|
10193
10508
|
const walked = /* @__PURE__ */ new Set();
|
|
10509
|
+
this.lastQueryWalked = [];
|
|
10194
10510
|
let frontier = alsoFrom === void 0 ? [value.getSourceFile()] : [value.getSourceFile(), alsoFrom];
|
|
10195
10511
|
for (let hop = 0; hop <= MAX_MODULE_HOPS; hop++) {
|
|
10196
10512
|
const next = [];
|
|
@@ -10199,6 +10515,8 @@ var ResolutionStore = class {
|
|
|
10199
10515
|
continue;
|
|
10200
10516
|
}
|
|
10201
10517
|
walked.add(sourceFile.getFilePath());
|
|
10518
|
+
this.lastQueryWalked.push(sourceFile.getFilePath());
|
|
10519
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
10202
10520
|
this.extractFile(sourceFile);
|
|
10203
10521
|
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
10204
10522
|
}
|
|
@@ -10495,6 +10813,27 @@ function moduleInitSummary(sourceFile, effects, options) {
|
|
|
10495
10813
|
return (0, import_extractor3.assembleSummary)(raw, options);
|
|
10496
10814
|
}
|
|
10497
10815
|
|
|
10816
|
+
// src/referencedFiles.ts
|
|
10817
|
+
function createReferenceIndex(sourceFiles) {
|
|
10818
|
+
const direct = /* @__PURE__ */ new Map();
|
|
10819
|
+
for (const sourceFile of sourceFiles) {
|
|
10820
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
10821
|
+
for (const target of sourceFile.getReferencedSourceFiles()) {
|
|
10822
|
+
if (target.isInNodeModules() || target.isDeclarationFile()) {
|
|
10823
|
+
continue;
|
|
10824
|
+
}
|
|
10825
|
+
referenced.add(target.getFilePath());
|
|
10826
|
+
}
|
|
10827
|
+
direct.set(sourceFile.getFilePath(), referenced);
|
|
10828
|
+
}
|
|
10829
|
+
const none = /* @__PURE__ */ new Set();
|
|
10830
|
+
return {
|
|
10831
|
+
directOf(filePath) {
|
|
10832
|
+
return direct.get(filePath) ?? none;
|
|
10833
|
+
}
|
|
10834
|
+
};
|
|
10835
|
+
}
|
|
10836
|
+
|
|
10498
10837
|
// src/resolve/boundaryEffects.ts
|
|
10499
10838
|
var import_datalog3 = require("@suss/datalog");
|
|
10500
10839
|
var EFFECT_RULES = [
|
|
@@ -10676,6 +11015,11 @@ function classifyStop(declarations) {
|
|
|
10676
11015
|
if (declarations.length === 0) {
|
|
10677
11016
|
return "noDeclaration";
|
|
10678
11017
|
}
|
|
11018
|
+
for (const declaration of declarations) {
|
|
11019
|
+
if (!isInExternalCode(declaration.getSourceFile())) {
|
|
11020
|
+
recordFileDependency(declaration.getSourceFile().getFilePath());
|
|
11021
|
+
}
|
|
11022
|
+
}
|
|
10679
11023
|
if (declarations.every(isExternalDeclaration)) {
|
|
10680
11024
|
return "outsideRun";
|
|
10681
11025
|
}
|
|
@@ -10882,7 +11226,7 @@ var REACHABLE_RULES = [
|
|
|
10882
11226
|
)
|
|
10883
11227
|
];
|
|
10884
11228
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
10885
|
-
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS) {
|
|
11229
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = []) {
|
|
10886
11230
|
const lookup = createSourceFileLookup(project);
|
|
10887
11231
|
const db = facts?.db ?? new import_datalog4.Database();
|
|
10888
11232
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -10902,6 +11246,15 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10902
11246
|
db.add("entry", [key]);
|
|
10903
11247
|
}
|
|
10904
11248
|
}
|
|
11249
|
+
const knownKeys = /* @__PURE__ */ new Set();
|
|
11250
|
+
for (const summary of alreadySummarized) {
|
|
11251
|
+
const func = lookup.functionAt(summary.location);
|
|
11252
|
+
if (func !== null) {
|
|
11253
|
+
const key = nodeKey2(func);
|
|
11254
|
+
knownKeys.add(key);
|
|
11255
|
+
facts?.unitKeyBySummary.set(summary, key);
|
|
11256
|
+
}
|
|
11257
|
+
}
|
|
10905
11258
|
for (; ; ) {
|
|
10906
11259
|
(0, import_datalog4.evaluate)(db, REACHABLE_RULES);
|
|
10907
11260
|
const frontier = db.facts("reachable").map(([key]) => String(key)).filter((key) => !scanned.has(key));
|
|
@@ -10919,7 +11272,11 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10919
11272
|
...recognizers.resolveCallable === void 0 ? {} : { resolveCallable: recognizers.resolveCallable },
|
|
10920
11273
|
...cameFrom === void 0 ? {} : { reachedFrom: cameFrom }
|
|
10921
11274
|
};
|
|
10922
|
-
const { candidates, stops } =
|
|
11275
|
+
const { candidates, stops } = scanWithRecording(
|
|
11276
|
+
key,
|
|
11277
|
+
facts,
|
|
11278
|
+
() => collectReachable(source.func, scan)
|
|
11279
|
+
);
|
|
10923
11280
|
if (stops.length > 0) {
|
|
10924
11281
|
stopsByKey.set(key, stops);
|
|
10925
11282
|
}
|
|
@@ -10938,7 +11295,7 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10938
11295
|
const reached = [];
|
|
10939
11296
|
for (const [keyAtom] of db.facts("reachable")) {
|
|
10940
11297
|
const key = String(keyAtom);
|
|
10941
|
-
if (seedKeys.has(key)) {
|
|
11298
|
+
if (seedKeys.has(key) || knownKeys.has(key)) {
|
|
10942
11299
|
continue;
|
|
10943
11300
|
}
|
|
10944
11301
|
const candidate = functionByKey.get(key);
|
|
@@ -10952,7 +11309,11 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10952
11309
|
candidate.func.getSourceFile().getFilePath()
|
|
10953
11310
|
);
|
|
10954
11311
|
}
|
|
10955
|
-
const summary =
|
|
11312
|
+
const summary = scanWithRecording(
|
|
11313
|
+
key,
|
|
11314
|
+
facts,
|
|
11315
|
+
() => extractReachableSummary(candidate, options, recognizers)
|
|
11316
|
+
);
|
|
10956
11317
|
facts?.unitKeyBySummary.set(summary, key);
|
|
10957
11318
|
rememberSummary(summariesByKey, key, summary);
|
|
10958
11319
|
reached.push(summary);
|
|
@@ -10960,6 +11321,20 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10960
11321
|
recordStops(stopsByKey, summariesByKey, options);
|
|
10961
11322
|
return [...seeds, ...reached];
|
|
10962
11323
|
}
|
|
11324
|
+
function scanWithRecording(key, facts, fn) {
|
|
11325
|
+
const filesByKey = facts?.filesByKey;
|
|
11326
|
+
if (filesByKey === void 0) {
|
|
11327
|
+
return fn();
|
|
11328
|
+
}
|
|
11329
|
+
const sink = createDependencySink();
|
|
11330
|
+
const result = withDependencySink(sink, fn);
|
|
11331
|
+
const bucket = filesByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
11332
|
+
for (const filePath of sink.files) {
|
|
11333
|
+
bucket.add(filePath);
|
|
11334
|
+
}
|
|
11335
|
+
filesByKey.set(key, bucket);
|
|
11336
|
+
return result;
|
|
11337
|
+
}
|
|
10963
11338
|
function rememberSummary(summariesByKey, key, summary) {
|
|
10964
11339
|
const bucket = summariesByKey.get(key) ?? [];
|
|
10965
11340
|
bucket.push(summary);
|
|
@@ -12215,6 +12590,36 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
12215
12590
|
function responseAccessorNames(pack, kind) {
|
|
12216
12591
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
12217
12592
|
}
|
|
12593
|
+
var ACCESSOR_FIELD_SEMANTICS = {
|
|
12594
|
+
bodyAccessors: "body",
|
|
12595
|
+
statusAccessors: "statusCode",
|
|
12596
|
+
successAccessors: "statusRange"
|
|
12597
|
+
};
|
|
12598
|
+
function responseAccessors(pack) {
|
|
12599
|
+
const out = {};
|
|
12600
|
+
for (const [field, kind] of Object.entries(ACCESSOR_FIELD_SEMANTICS)) {
|
|
12601
|
+
const names = responseAccessorNames(pack, kind);
|
|
12602
|
+
if (names !== void 0 && names.length > 0) {
|
|
12603
|
+
out[field] = names;
|
|
12604
|
+
}
|
|
12605
|
+
}
|
|
12606
|
+
return out;
|
|
12607
|
+
}
|
|
12608
|
+
var FUNCTION_FALLTHROUGH_TERMINAL = {
|
|
12609
|
+
kind: "return",
|
|
12610
|
+
match: { type: "functionFallthrough" },
|
|
12611
|
+
extraction: {}
|
|
12612
|
+
};
|
|
12613
|
+
function terminalsFor(unit, pack) {
|
|
12614
|
+
const declared = unit.terminals ?? pack.terminals;
|
|
12615
|
+
if (unit.callSite === void 0) {
|
|
12616
|
+
return declared;
|
|
12617
|
+
}
|
|
12618
|
+
if (declared.some((p) => p.match.type === "functionFallthrough")) {
|
|
12619
|
+
return declared;
|
|
12620
|
+
}
|
|
12621
|
+
return [...declared, FUNCTION_FALLTHROUGH_TERMINAL];
|
|
12622
|
+
}
|
|
12218
12623
|
function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers, barriers, resolveWrittenValue) {
|
|
12219
12624
|
const { func, kind, name } = unit;
|
|
12220
12625
|
if (func === null) {
|
|
@@ -12226,7 +12631,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12226
12631
|
);
|
|
12227
12632
|
const extracted = extractRawBranches(
|
|
12228
12633
|
func,
|
|
12229
|
-
unit
|
|
12634
|
+
terminalsFor(unit, pack),
|
|
12230
12635
|
invocationRecognizers,
|
|
12231
12636
|
accessRecognizers,
|
|
12232
12637
|
barriers,
|
|
@@ -12262,8 +12667,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12262
12667
|
}
|
|
12263
12668
|
}
|
|
12264
12669
|
}
|
|
12265
|
-
const
|
|
12266
|
-
const statusAccessors = unit.callSite !== void 0 ? responseAccessorNames(pack, "statusCode") : void 0;
|
|
12670
|
+
const accessors = unit.callSite !== void 0 ? responseAccessors(pack) : {};
|
|
12267
12671
|
return {
|
|
12268
12672
|
identity: {
|
|
12269
12673
|
name,
|
|
@@ -12287,8 +12691,8 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12287
12691
|
bodyContent: bodyContentOf(func),
|
|
12288
12692
|
dependencyCalls: depCalls,
|
|
12289
12693
|
declaredContract: null,
|
|
12290
|
-
...
|
|
12291
|
-
...
|
|
12694
|
+
...accessors,
|
|
12695
|
+
...unit.callSite !== void 0 && pack.failureDelivery !== void 0 ? { failureDelivery: pack.failureDelivery } : {}
|
|
12292
12696
|
};
|
|
12293
12697
|
}
|
|
12294
12698
|
function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
@@ -12642,12 +13046,20 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12642
13046
|
if (claimant.pack === pack.name && claimant.file === sourceFile.getFilePath() && tally !== void 0) {
|
|
12643
13047
|
tally.selfCollisions += 1;
|
|
12644
13048
|
}
|
|
13049
|
+
if (claimant.file !== sourceFile.getFilePath()) {
|
|
13050
|
+
recordFileDependency(claimant.file);
|
|
13051
|
+
}
|
|
12645
13052
|
continue;
|
|
12646
13053
|
}
|
|
12647
13054
|
claimed.set(claimKey, {
|
|
12648
13055
|
pack: pack.name,
|
|
12649
13056
|
file: sourceFile.getFilePath()
|
|
12650
13057
|
});
|
|
13058
|
+
recordUnitClaim(claimKey, pack.name);
|
|
13059
|
+
const declaringFile = unit.func?.getSourceFile().getFilePath();
|
|
13060
|
+
if (declaringFile !== void 0 && declaringFile !== sourceFile.getFilePath()) {
|
|
13061
|
+
recordFileDependency(declaringFile);
|
|
13062
|
+
}
|
|
12651
13063
|
unitsWalkedHere += 1;
|
|
12652
13064
|
if (tally !== void 0) {
|
|
12653
13065
|
tally.unitsClaimed += 1;
|
|
@@ -12686,6 +13098,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12686
13098
|
}
|
|
12687
13099
|
if (unit.resolverInfo.schemaSdl !== void 0) {
|
|
12688
13100
|
raw.graphqlSchemaSdl = unit.resolverInfo.schemaSdl;
|
|
13101
|
+
if (unit.resolverInfo.schemaDocument !== void 0) {
|
|
13102
|
+
raw.sourceDocumentLabel = unit.resolverInfo.schemaDocument;
|
|
13103
|
+
}
|
|
12689
13104
|
if (unit.resolverInfo.typeName !== null) {
|
|
12690
13105
|
const contract = deriveGraphqlContract(
|
|
12691
13106
|
unit.resolverInfo.schemaSdl,
|
|
@@ -12874,6 +13289,37 @@ function fileImporting(project, modulePrefix) {
|
|
|
12874
13289
|
}
|
|
12875
13290
|
return void 0;
|
|
12876
13291
|
}
|
|
13292
|
+
function liftSchemasOntoDocuments(summaries) {
|
|
13293
|
+
const sdlByDocument = /* @__PURE__ */ new Map();
|
|
13294
|
+
for (const summary of summaries) {
|
|
13295
|
+
const label = (0, import_behavioral_ir6.readSourceDocumentMetadata)(summary)?.label;
|
|
13296
|
+
const graphql = (0, import_behavioral_ir6.readGraphqlMetadata)(summary);
|
|
13297
|
+
if (label === void 0 || graphql?.schemaSdl === void 0) {
|
|
13298
|
+
continue;
|
|
13299
|
+
}
|
|
13300
|
+
sdlByDocument.set(label, graphql.schemaSdl);
|
|
13301
|
+
const { schemaSdl: _movedToTheDocument, ...rest } = graphql;
|
|
13302
|
+
summary.metadata = (0, import_behavioral_ir6.withGraphqlMetadata)(summary.metadata, rest);
|
|
13303
|
+
}
|
|
13304
|
+
for (const [label, schemaSdl] of sdlByDocument) {
|
|
13305
|
+
summaries.push(schemaDocumentSummary(label, schemaSdl));
|
|
13306
|
+
}
|
|
13307
|
+
}
|
|
13308
|
+
function schemaDocumentSummary(label, schemaSdl) {
|
|
13309
|
+
return {
|
|
13310
|
+
kind: "library",
|
|
13311
|
+
location: { file: label, range: { start: 0, end: 0 }, exportName: null },
|
|
13312
|
+
identity: { name: label, exportPath: null, boundaryBinding: null },
|
|
13313
|
+
inputs: [],
|
|
13314
|
+
transitions: [],
|
|
13315
|
+
gaps: [],
|
|
13316
|
+
confidence: { source: "declared", level: "high" },
|
|
13317
|
+
metadata: (0, import_behavioral_ir6.withGraphqlMetadata)(
|
|
13318
|
+
(0, import_behavioral_ir6.withSourceDocumentMetadata)(void 0, { label }),
|
|
13319
|
+
{ schemaSdl }
|
|
13320
|
+
)
|
|
13321
|
+
};
|
|
13322
|
+
}
|
|
12877
13323
|
function libraryEnvReadMarker(pack, declared, importer) {
|
|
12878
13324
|
return {
|
|
12879
13325
|
kind: "library",
|
|
@@ -13124,8 +13570,8 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path11, options) {
|
|
|
13124
13570
|
summary.confidence = { source: "inferred_static", level: "low" };
|
|
13125
13571
|
return summary;
|
|
13126
13572
|
}
|
|
13127
|
-
function named(summaries, workspace) {
|
|
13128
|
-
const projectRoot = commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
13573
|
+
function named(summaries, workspace, storedProjectRoot) {
|
|
13574
|
+
const projectRoot = storedProjectRoot ?? commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
13129
13575
|
nameSummaries(summaries, {
|
|
13130
13576
|
workspace: workspace ?? workspaceNameFor(projectRoot),
|
|
13131
13577
|
projectRoot
|
|
@@ -13256,7 +13702,29 @@ function createTypeScriptAdapter(config) {
|
|
|
13256
13702
|
if (config.onTiming !== void 0) {
|
|
13257
13703
|
config.onTiming(timer.report());
|
|
13258
13704
|
}
|
|
13259
|
-
return named(lookup.summaries, config.workspace);
|
|
13705
|
+
return named(lookup.summaries, config.workspace, lookup.projectRoot);
|
|
13706
|
+
}
|
|
13707
|
+
const plan = lookup.diagnostic.missReason === "files-changed" ? await timer.timeAsync("cache.plan", () => cache.plan(cacheInput)) : null;
|
|
13708
|
+
if (plan !== null && plan.changed.size === 0 && plan.removed.size === 0) {
|
|
13709
|
+
try {
|
|
13710
|
+
await cache.write(
|
|
13711
|
+
cacheInput,
|
|
13712
|
+
plan.allSummaries(),
|
|
13713
|
+
plan.attribution()
|
|
13714
|
+
);
|
|
13715
|
+
} catch {
|
|
13716
|
+
}
|
|
13717
|
+
if (config.onCacheDiagnostic !== void 0) {
|
|
13718
|
+
config.onCacheDiagnostic({ kind: "hit" });
|
|
13719
|
+
}
|
|
13720
|
+
if (config.onTiming !== void 0) {
|
|
13721
|
+
config.onTiming(timer.report());
|
|
13722
|
+
}
|
|
13723
|
+
return named(
|
|
13724
|
+
plan.allSummaries(),
|
|
13725
|
+
config.workspace,
|
|
13726
|
+
plan.storedProjectRoot ?? void 0
|
|
13727
|
+
);
|
|
13260
13728
|
}
|
|
13261
13729
|
let candidatePaths = null;
|
|
13262
13730
|
if (lazyEligible) {
|
|
@@ -13287,16 +13755,58 @@ function createTypeScriptAdapter(config) {
|
|
|
13287
13755
|
"mountPrefix",
|
|
13288
13756
|
() => buildMountPrefixIndex(packsByFile, resolution)
|
|
13289
13757
|
);
|
|
13758
|
+
const caching = cacheDir !== null;
|
|
13759
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
13760
|
+
if (plan !== null) {
|
|
13761
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
13762
|
+
for (const [sf, packs] of packsByFile) {
|
|
13763
|
+
packNamesByPath.set(
|
|
13764
|
+
sf.getFilePath(),
|
|
13765
|
+
packs.map((p) => p.name).sort().join(",")
|
|
13766
|
+
);
|
|
13767
|
+
}
|
|
13768
|
+
for (const rootPath of plan.validRoots) {
|
|
13769
|
+
const record = plan.roots.get(rootPath);
|
|
13770
|
+
if (record === void 0) {
|
|
13771
|
+
continue;
|
|
13772
|
+
}
|
|
13773
|
+
if (!mountAssumptionsAgree(record, mountPrefixes)) {
|
|
13774
|
+
continue;
|
|
13775
|
+
}
|
|
13776
|
+
const stored = [...record.packs].sort().join(",");
|
|
13777
|
+
if ((packNamesByPath.get(rootPath) ?? "") !== stored) {
|
|
13778
|
+
continue;
|
|
13779
|
+
}
|
|
13780
|
+
validRoots.add(rootPath);
|
|
13781
|
+
}
|
|
13782
|
+
}
|
|
13783
|
+
const reused = plan !== null && validRoots.size > 0 ? plan.reuse(validRoots) : null;
|
|
13290
13784
|
const claimedUnits = /* @__PURE__ */ new Map();
|
|
13785
|
+
if (reused !== null && plan !== null) {
|
|
13786
|
+
for (const rootPath of validRoots) {
|
|
13787
|
+
for (const claim of plan.roots.get(rootPath)?.claims ?? []) {
|
|
13788
|
+
claimedUnits.set(claim.key, { pack: claim.pack, file: rootPath });
|
|
13789
|
+
}
|
|
13790
|
+
}
|
|
13791
|
+
}
|
|
13792
|
+
const walkList = reused === null ? sourceFiles : sourceFiles.filter((sf) => !validRoots.has(sf.getFilePath()));
|
|
13793
|
+
const sinkByRoot = /* @__PURE__ */ new Map();
|
|
13794
|
+
const ownersBySummary = /* @__PURE__ */ new Map();
|
|
13291
13795
|
timer.time("extract per-file", () => {
|
|
13292
|
-
for (const sourceFile of
|
|
13796
|
+
for (const sourceFile of walkList) {
|
|
13797
|
+
const rootPath = sourceFile.getFilePath();
|
|
13798
|
+
const sink = createDependencySink();
|
|
13799
|
+
if (caching) {
|
|
13800
|
+
sinkByRoot.set(rootPath, sink);
|
|
13801
|
+
}
|
|
13293
13802
|
const applicablePacks = packsByFile.get(sourceFile);
|
|
13294
13803
|
if (applicablePacks === void 0) {
|
|
13295
13804
|
continue;
|
|
13296
13805
|
}
|
|
13297
13806
|
try {
|
|
13298
|
-
|
|
13299
|
-
|
|
13807
|
+
const walked = withDependencySink(
|
|
13808
|
+
sink,
|
|
13809
|
+
() => extractFromSourceFile(
|
|
13300
13810
|
sourceFile,
|
|
13301
13811
|
applicablePacks,
|
|
13302
13812
|
claimedUnits,
|
|
@@ -13306,6 +13816,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13306
13816
|
mountPrefixes
|
|
13307
13817
|
)
|
|
13308
13818
|
);
|
|
13819
|
+
for (const summary of walked) {
|
|
13820
|
+
ownersBySummary.set(summary, /* @__PURE__ */ new Set([rootPath]));
|
|
13821
|
+
}
|
|
13822
|
+
summaries.push(...walked);
|
|
13309
13823
|
} catch (error) {
|
|
13310
13824
|
if (!(error instanceof RangeError)) {
|
|
13311
13825
|
throw error;
|
|
@@ -13314,23 +13828,32 @@ function createTypeScriptAdapter(config) {
|
|
|
13314
13828
|
}
|
|
13315
13829
|
}
|
|
13316
13830
|
});
|
|
13831
|
+
const wrapperInput = reused === null ? summaries : [...summaries, ...reused.summaries];
|
|
13317
13832
|
const withWrappers = timer.time(
|
|
13318
13833
|
"expandWrapperCallers",
|
|
13319
|
-
() => expandWrapperCallers(
|
|
13834
|
+
() => expandWrapperCallers(wrapperInput, project, config.extractorOptions)
|
|
13320
13835
|
);
|
|
13836
|
+
const pipeline = reused === null ? withWrappers : [...summaries, ...withWrappers.slice(wrapperInput.length)];
|
|
13321
13837
|
const withSubUnits = timer.time(
|
|
13322
13838
|
"synthesizeSubUnits",
|
|
13323
13839
|
() => synthesizeSubUnits(
|
|
13324
|
-
|
|
13840
|
+
pipeline,
|
|
13325
13841
|
project,
|
|
13326
13842
|
config.frameworks,
|
|
13327
13843
|
config.extractorOptions,
|
|
13328
|
-
tallies
|
|
13844
|
+
tallies,
|
|
13845
|
+
(created, parent) => {
|
|
13846
|
+
const parentOwners = ownersBySummary.get(parent);
|
|
13847
|
+
if (parentOwners !== void 0) {
|
|
13848
|
+
ownersBySummary.set(created, new Set(parentOwners));
|
|
13849
|
+
}
|
|
13850
|
+
}
|
|
13329
13851
|
)
|
|
13330
13852
|
);
|
|
13331
13853
|
const closureFacts = {
|
|
13332
13854
|
db: new import_datalog6.Database(),
|
|
13333
|
-
unitKeyBySummary: /* @__PURE__ */ new Map()
|
|
13855
|
+
unitKeyBySummary: /* @__PURE__ */ new Map(),
|
|
13856
|
+
...caching ? { filesByKey: /* @__PURE__ */ new Map() } : {}
|
|
13334
13857
|
};
|
|
13335
13858
|
const withClosure = config.includeReachable !== false ? timer.time(
|
|
13336
13859
|
"expandReachableClosure",
|
|
@@ -13348,12 +13871,28 @@ function createTypeScriptAdapter(config) {
|
|
|
13348
13871
|
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13349
13872
|
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value),
|
|
13350
13873
|
resolveCallable: (value, alsoFrom) => resolution.resolveCallable(value, alsoFrom)
|
|
13351
|
-
}
|
|
13874
|
+
},
|
|
13875
|
+
// Reached units the cache already serves emit nothing,
|
|
13876
|
+
// the way a cold run's seeds do not.
|
|
13877
|
+
reused?.summaries ?? []
|
|
13352
13878
|
)
|
|
13353
13879
|
) : withSubUnits;
|
|
13880
|
+
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
13881
|
+
"cache.attributeClosure",
|
|
13882
|
+
() => attributeReachedSummaries(
|
|
13883
|
+
withSubUnits,
|
|
13884
|
+
withClosure.slice(withSubUnits.length),
|
|
13885
|
+
closureFacts,
|
|
13886
|
+
ownersBySummary
|
|
13887
|
+
)
|
|
13888
|
+
) : null;
|
|
13889
|
+
const merged = timer.time(
|
|
13890
|
+
"cache.merge",
|
|
13891
|
+
() => mergeWithReused(reused, withClosure, ownersBySummary)
|
|
13892
|
+
);
|
|
13354
13893
|
const enriched = timer.time(
|
|
13355
13894
|
"enrichRethrows",
|
|
13356
|
-
() => enrichRethrows(
|
|
13895
|
+
() => enrichRethrows(merged.summaries, project, closureFacts)
|
|
13357
13896
|
);
|
|
13358
13897
|
if (config.includeReachable !== false) {
|
|
13359
13898
|
timer.time(
|
|
@@ -13369,6 +13908,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13369
13908
|
"emitLibraryEnvReadMarkers",
|
|
13370
13909
|
() => emitLibraryEnvReadMarkers(enriched, project, config.frameworks)
|
|
13371
13910
|
);
|
|
13911
|
+
timer.time(
|
|
13912
|
+
"liftSchemasOntoDocuments",
|
|
13913
|
+
() => liftSchemasOntoDocuments(enriched)
|
|
13914
|
+
);
|
|
13372
13915
|
timer.time(
|
|
13373
13916
|
"stampGraphqlClientRefs",
|
|
13374
13917
|
() => stampGraphqlClientRefs(
|
|
@@ -13378,12 +13921,45 @@ function createTypeScriptAdapter(config) {
|
|
|
13378
13921
|
resolution
|
|
13379
13922
|
)
|
|
13380
13923
|
);
|
|
13924
|
+
if (config.onCacheDiagnostic !== void 0 && plan !== null) {
|
|
13925
|
+
config.onCacheDiagnostic({
|
|
13926
|
+
kind: "partial",
|
|
13927
|
+
partial: {
|
|
13928
|
+
filesChanged: plan.changed.size,
|
|
13929
|
+
filesRemoved: plan.removed.size,
|
|
13930
|
+
rootsReused: validRoots.size,
|
|
13931
|
+
rootsReextracted: walkList.length,
|
|
13932
|
+
rootsDeclined: plan.rootsDeclined,
|
|
13933
|
+
summariesReused: merged.reusedKept.length
|
|
13934
|
+
}
|
|
13935
|
+
});
|
|
13936
|
+
}
|
|
13937
|
+
const runProjectRoot = commonDirectoryOf(
|
|
13938
|
+
sourceFiles.map((f) => f.getFilePath())
|
|
13939
|
+
);
|
|
13381
13940
|
await timer.timeAsync("cache.write", async () => {
|
|
13382
|
-
if (enriched.length === 0) {
|
|
13941
|
+
if (!caching || enriched.length === 0) {
|
|
13383
13942
|
return;
|
|
13384
13943
|
}
|
|
13385
13944
|
try {
|
|
13386
|
-
|
|
13945
|
+
const attribution = buildCacheAttribution({
|
|
13946
|
+
project,
|
|
13947
|
+
plan,
|
|
13948
|
+
validRoots,
|
|
13949
|
+
sinkByRoot,
|
|
13950
|
+
ownersBySummary,
|
|
13951
|
+
closureOwnership,
|
|
13952
|
+
unitKeyBySummary: closureFacts.unitKeyBySummary,
|
|
13953
|
+
filesByKey: closureFacts.filesByKey,
|
|
13954
|
+
packsByFile,
|
|
13955
|
+
reusedKept: merged.reusedKept,
|
|
13956
|
+
reusedOwners: merged.reusedOwners,
|
|
13957
|
+
// Everything after the reused prefix, the passes' own
|
|
13958
|
+
// additions (markers, schema documents) included.
|
|
13959
|
+
fresh: enriched.slice(merged.reusedKept.length),
|
|
13960
|
+
projectRoot: runProjectRoot
|
|
13961
|
+
});
|
|
13962
|
+
await cache.write(cacheInput, enriched, attribution);
|
|
13387
13963
|
} catch {
|
|
13388
13964
|
}
|
|
13389
13965
|
});
|
|
@@ -13396,7 +13972,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13396
13972
|
packs: config.frameworks,
|
|
13397
13973
|
tallies,
|
|
13398
13974
|
filesInProject: tsconfigFileList?.length ?? null,
|
|
13399
|
-
filesWalked:
|
|
13975
|
+
filesWalked: walkList.length,
|
|
13400
13976
|
summaries: enriched,
|
|
13401
13977
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
13402
13978
|
projectRoot: commonDirectoryOf(
|
|
@@ -13416,7 +13992,200 @@ function createTypeScriptAdapter(config) {
|
|
|
13416
13992
|
}
|
|
13417
13993
|
};
|
|
13418
13994
|
}
|
|
13419
|
-
function
|
|
13995
|
+
function mountAssumptionsAgree(record, index) {
|
|
13996
|
+
return Object.entries(record.mountPrefixes).every(
|
|
13997
|
+
([childId, prefix]) => (index.prefixForId?.(childId) ?? "") === prefix
|
|
13998
|
+
);
|
|
13999
|
+
}
|
|
14000
|
+
function attributeReachedSummaries(seeds, reached, facts, owners) {
|
|
14001
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
14002
|
+
for (const [from, to] of facts.db.facts("calls")) {
|
|
14003
|
+
const key = String(from);
|
|
14004
|
+
const bucket = adjacency.get(key) ?? [];
|
|
14005
|
+
bucket.push(String(to));
|
|
14006
|
+
adjacency.set(key, bucket);
|
|
14007
|
+
}
|
|
14008
|
+
const seedKeysByRoot = /* @__PURE__ */ new Map();
|
|
14009
|
+
for (const seed of seeds) {
|
|
14010
|
+
const key = facts.unitKeyBySummary.get(seed);
|
|
14011
|
+
if (key === void 0) {
|
|
14012
|
+
continue;
|
|
14013
|
+
}
|
|
14014
|
+
for (const root of owners.get(seed) ?? []) {
|
|
14015
|
+
const bucket = seedKeysByRoot.get(root) ?? [];
|
|
14016
|
+
bucket.push(key);
|
|
14017
|
+
seedKeysByRoot.set(root, bucket);
|
|
14018
|
+
}
|
|
14019
|
+
}
|
|
14020
|
+
const reachableByRoot = /* @__PURE__ */ new Map();
|
|
14021
|
+
const rootsByKey = /* @__PURE__ */ new Map();
|
|
14022
|
+
for (const [root, seedKeys] of seedKeysByRoot) {
|
|
14023
|
+
const seen = new Set(seedKeys);
|
|
14024
|
+
const queue = [...seedKeys];
|
|
14025
|
+
while (queue.length > 0) {
|
|
14026
|
+
const key = queue.pop();
|
|
14027
|
+
if (key === void 0) {
|
|
14028
|
+
continue;
|
|
14029
|
+
}
|
|
14030
|
+
for (const next of adjacency.get(key) ?? []) {
|
|
14031
|
+
if (!seen.has(next)) {
|
|
14032
|
+
seen.add(next);
|
|
14033
|
+
queue.push(next);
|
|
14034
|
+
}
|
|
14035
|
+
}
|
|
14036
|
+
const keyRoots = rootsByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
14037
|
+
keyRoots.add(root);
|
|
14038
|
+
rootsByKey.set(key, keyRoots);
|
|
14039
|
+
}
|
|
14040
|
+
reachableByRoot.set(root, seen);
|
|
14041
|
+
}
|
|
14042
|
+
for (const summary of reached) {
|
|
14043
|
+
const key = facts.unitKeyBySummary.get(summary);
|
|
14044
|
+
if (key === void 0) {
|
|
14045
|
+
continue;
|
|
14046
|
+
}
|
|
14047
|
+
const keyRoots = rootsByKey.get(key);
|
|
14048
|
+
if (keyRoots !== void 0 && keyRoots.size > 0) {
|
|
14049
|
+
owners.set(summary, new Set(keyRoots));
|
|
14050
|
+
}
|
|
14051
|
+
}
|
|
14052
|
+
return { reachableByRoot, rootsByKey };
|
|
14053
|
+
}
|
|
14054
|
+
function fileOfNodeKey(key) {
|
|
14055
|
+
const cut = key.lastIndexOf(":");
|
|
14056
|
+
return cut <= 0 ? null : key.slice(0, cut);
|
|
14057
|
+
}
|
|
14058
|
+
function summaryMergeKey(summary) {
|
|
14059
|
+
return JSON.stringify([
|
|
14060
|
+
summary.location.file,
|
|
14061
|
+
summary.location.range.start,
|
|
14062
|
+
summary.location.range.end,
|
|
14063
|
+
summary.kind,
|
|
14064
|
+
summary.identity.name,
|
|
14065
|
+
summary.identity.exportPath,
|
|
14066
|
+
summary.identity.boundaryBinding
|
|
14067
|
+
]);
|
|
14068
|
+
}
|
|
14069
|
+
function mergeWithReused(reused, fresh, ownersBySummary) {
|
|
14070
|
+
if (reused === null) {
|
|
14071
|
+
return { summaries: fresh, reusedKept: [], reusedOwners: [] };
|
|
14072
|
+
}
|
|
14073
|
+
const freshByKey = /* @__PURE__ */ new Map();
|
|
14074
|
+
for (const summary of fresh) {
|
|
14075
|
+
freshByKey.set(summaryMergeKey(summary), summary);
|
|
14076
|
+
}
|
|
14077
|
+
const reusedKept = [];
|
|
14078
|
+
const reusedOwners = [];
|
|
14079
|
+
reused.summaries.forEach((summary, i) => {
|
|
14080
|
+
const owners = reused.owners[i] ?? [];
|
|
14081
|
+
const supersededBy = freshByKey.get(summaryMergeKey(summary));
|
|
14082
|
+
if (supersededBy !== void 0) {
|
|
14083
|
+
const freshOwners = ownersBySummary.get(supersededBy) ?? /* @__PURE__ */ new Set();
|
|
14084
|
+
for (const owner of owners) {
|
|
14085
|
+
freshOwners.add(owner);
|
|
14086
|
+
}
|
|
14087
|
+
ownersBySummary.set(supersededBy, freshOwners);
|
|
14088
|
+
return;
|
|
14089
|
+
}
|
|
14090
|
+
reusedKept.push(summary);
|
|
14091
|
+
reusedOwners.push(owners);
|
|
14092
|
+
});
|
|
14093
|
+
return { summaries: [...reusedKept, ...fresh], reusedKept, reusedOwners };
|
|
14094
|
+
}
|
|
14095
|
+
function readsRunLevelJoins(summary) {
|
|
14096
|
+
if ((0, import_behavioral_ir6.readSourceDocumentMetadata)(summary) !== void 0) {
|
|
14097
|
+
return true;
|
|
14098
|
+
}
|
|
14099
|
+
if ((0, import_behavioral_ir6.readGraphqlMetadata)(summary)?.client !== void 0) {
|
|
14100
|
+
return true;
|
|
14101
|
+
}
|
|
14102
|
+
const semantics = summary.identity.boundaryBinding?.semantics;
|
|
14103
|
+
return semantics !== void 0 && "operationType" in semantics;
|
|
14104
|
+
}
|
|
14105
|
+
function buildCacheAttribution(args) {
|
|
14106
|
+
const references = createReferenceIndex(
|
|
14107
|
+
args.project.getSourceFiles().filter((sf) => !sf.isDeclarationFile())
|
|
14108
|
+
);
|
|
14109
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
14110
|
+
for (const [sf, packs] of args.packsByFile) {
|
|
14111
|
+
packNamesByPath.set(
|
|
14112
|
+
sf.getFilePath(),
|
|
14113
|
+
packs.map((p) => p.name)
|
|
14114
|
+
);
|
|
14115
|
+
}
|
|
14116
|
+
const summariesByRoot = /* @__PURE__ */ new Map();
|
|
14117
|
+
for (const summary of args.fresh) {
|
|
14118
|
+
for (const root of args.ownersBySummary.get(summary) ?? []) {
|
|
14119
|
+
const bucket = summariesByRoot.get(root) ?? [];
|
|
14120
|
+
bucket.push(summary);
|
|
14121
|
+
summariesByRoot.set(root, bucket);
|
|
14122
|
+
}
|
|
14123
|
+
}
|
|
14124
|
+
const roots = [];
|
|
14125
|
+
for (const [rootPath, sink] of args.sinkByRoot) {
|
|
14126
|
+
const deps = new Set(sink.files);
|
|
14127
|
+
for (const dep of references.directOf(rootPath)) {
|
|
14128
|
+
deps.add(dep);
|
|
14129
|
+
}
|
|
14130
|
+
let cacheable = true;
|
|
14131
|
+
for (const summary of summariesByRoot.get(rootPath) ?? []) {
|
|
14132
|
+
deps.add(summary.location.file);
|
|
14133
|
+
if (readsRunLevelJoins(summary)) {
|
|
14134
|
+
cacheable = false;
|
|
14135
|
+
}
|
|
14136
|
+
}
|
|
14137
|
+
const reachable = args.closureOwnership?.reachableByRoot.get(rootPath) ?? [];
|
|
14138
|
+
for (const key of reachable) {
|
|
14139
|
+
const keyFile = fileOfNodeKey(key);
|
|
14140
|
+
if (keyFile !== null) {
|
|
14141
|
+
deps.add(keyFile);
|
|
14142
|
+
for (const hop of references.directOf(keyFile)) {
|
|
14143
|
+
deps.add(hop);
|
|
14144
|
+
}
|
|
14145
|
+
}
|
|
14146
|
+
for (const filePath of args.filesByKey?.get(key) ?? []) {
|
|
14147
|
+
deps.add(filePath);
|
|
14148
|
+
}
|
|
14149
|
+
}
|
|
14150
|
+
deps.delete(rootPath);
|
|
14151
|
+
roots.push({
|
|
14152
|
+
path: rootPath,
|
|
14153
|
+
cacheable,
|
|
14154
|
+
deps: [...deps].sort(),
|
|
14155
|
+
claims: sink.claims,
|
|
14156
|
+
mountPrefixes: Object.fromEntries(sink.mountPrefixes),
|
|
14157
|
+
packs: packNamesByPath.get(rootPath) ?? []
|
|
14158
|
+
});
|
|
14159
|
+
}
|
|
14160
|
+
if (args.plan !== null) {
|
|
14161
|
+
for (const rootPath of args.validRoots) {
|
|
14162
|
+
const record = args.plan.roots.get(rootPath);
|
|
14163
|
+
if (record !== void 0) {
|
|
14164
|
+
roots.push(record);
|
|
14165
|
+
}
|
|
14166
|
+
}
|
|
14167
|
+
}
|
|
14168
|
+
const reusedOwners = args.reusedKept.map((summary, i) => {
|
|
14169
|
+
const combined = new Set(args.reusedOwners[i] ?? []);
|
|
14170
|
+
const key = args.unitKeyBySummary.get(summary);
|
|
14171
|
+
if (key !== void 0) {
|
|
14172
|
+
for (const root of args.closureOwnership?.rootsByKey.get(key) ?? []) {
|
|
14173
|
+
combined.add(root);
|
|
14174
|
+
}
|
|
14175
|
+
}
|
|
14176
|
+
return [...combined];
|
|
14177
|
+
});
|
|
14178
|
+
const owners = [
|
|
14179
|
+
...reusedOwners,
|
|
14180
|
+
...args.fresh.map((s) => [...args.ownersBySummary.get(s) ?? []])
|
|
14181
|
+
];
|
|
14182
|
+
return {
|
|
14183
|
+
roots,
|
|
14184
|
+
owners,
|
|
14185
|
+
...args.projectRoot === void 0 ? {} : { projectRoot: args.projectRoot }
|
|
14186
|
+
};
|
|
14187
|
+
}
|
|
14188
|
+
function synthesizeSubUnits(summaries, project, frameworks, options, tallies, onCreated) {
|
|
13420
14189
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
13421
14190
|
for (const pack of frameworks) {
|
|
13422
14191
|
packByRecognition.set(pack.name, pack);
|
|
@@ -13459,6 +14228,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13459
14228
|
);
|
|
13460
14229
|
if (summary !== null) {
|
|
13461
14230
|
synthesized.push(summary);
|
|
14231
|
+
onCreated?.(summary, parent);
|
|
13462
14232
|
}
|
|
13463
14233
|
}
|
|
13464
14234
|
}
|
|
@@ -13467,14 +14237,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13467
14237
|
var DEFAULT_SUB_UNIT_TERMINALS = [
|
|
13468
14238
|
{ kind: "return", match: { type: "returnStatement" }, extraction: {} },
|
|
13469
14239
|
{ kind: "throw", match: { type: "throwExpression" }, extraction: {} },
|
|
13470
|
-
|
|
13471
|
-
// fall-through gives it a default transition. HTTP packs do not opt in:
|
|
13472
|
-
// a handler that sends no response should come out with none.
|
|
13473
|
-
{
|
|
13474
|
-
kind: "return",
|
|
13475
|
-
match: { type: "functionFallthrough" },
|
|
13476
|
-
extraction: {}
|
|
13477
|
-
}
|
|
14240
|
+
FUNCTION_FALLTHROUGH_TERMINAL
|
|
13478
14241
|
];
|
|
13479
14242
|
var DEFAULT_SUB_UNIT_INPUT_MAPPING = {
|
|
13480
14243
|
type: "positionalParams",
|
|
@@ -13781,6 +14544,7 @@ function formatPackHealth(checks, audiences) {
|
|
|
13781
14544
|
|
|
13782
14545
|
// src/resolve/readName.ts
|
|
13783
14546
|
var import_ts_morph59 = require("ts-morph");
|
|
14547
|
+
var import_behavioral_ir7 = require("@suss/behavioral-ir");
|
|
13784
14548
|
var MAX_HELPER_HOPS = 2;
|
|
13785
14549
|
var UNNAMED_HOLE = "param";
|
|
13786
14550
|
function readName(expr, options = {}) {
|
|
@@ -13794,6 +14558,14 @@ function readName(expr, options = {}) {
|
|
|
13794
14558
|
if (name !== null || options.unsettled !== "reference") {
|
|
13795
14559
|
return name;
|
|
13796
14560
|
}
|
|
14561
|
+
const reference = referenceIn(expr);
|
|
14562
|
+
return reference === null ? null : (0, import_behavioral_ir7.referenceName)(reference);
|
|
14563
|
+
}
|
|
14564
|
+
function referenceIn(expr) {
|
|
14565
|
+
const fromParameter = parameterPath(expr);
|
|
14566
|
+
if (fromParameter !== null) {
|
|
14567
|
+
return fromParameter;
|
|
14568
|
+
}
|
|
13797
14569
|
const asked = holeName(expr, {
|
|
13798
14570
|
resolve: () => null,
|
|
13799
14571
|
bindings: /* @__PURE__ */ new Map(),
|
|
@@ -13801,7 +14573,25 @@ function readName(expr, options = {}) {
|
|
|
13801
14573
|
seen: /* @__PURE__ */ new Set(),
|
|
13802
14574
|
insideHole: true
|
|
13803
14575
|
});
|
|
13804
|
-
return asked === UNNAMED_HOLE ? null :
|
|
14576
|
+
return asked === UNNAMED_HOLE ? null : { root: asked, fields: [] };
|
|
14577
|
+
}
|
|
14578
|
+
function parameterPath(expr) {
|
|
14579
|
+
const fields = [];
|
|
14580
|
+
let step = expr;
|
|
14581
|
+
while (import_ts_morph59.Node.isPropertyAccessExpression(step)) {
|
|
14582
|
+
fields.unshift(step.getName());
|
|
14583
|
+
step = step.getExpression();
|
|
14584
|
+
}
|
|
14585
|
+
if (!import_ts_morph59.Node.isIdentifier(step) || !isParameter(step)) {
|
|
14586
|
+
return null;
|
|
14587
|
+
}
|
|
14588
|
+
return { root: step.getText(), fields };
|
|
14589
|
+
}
|
|
14590
|
+
function isParameter(identifier) {
|
|
14591
|
+
const declarations = identifier.getSymbol()?.getDeclarations() ?? [];
|
|
14592
|
+
return declarations.some(
|
|
14593
|
+
(declaration) => import_ts_morph59.Node.isParameterDeclaration(declaration)
|
|
14594
|
+
);
|
|
13805
14595
|
}
|
|
13806
14596
|
function read(expr, ctx) {
|
|
13807
14597
|
if (ctx.seen.has(expr)) {
|
|
@@ -13998,7 +14788,7 @@ function boundOnce(expr, ctx) {
|
|
|
13998
14788
|
}
|
|
13999
14789
|
function readOrHole(expr, ctx) {
|
|
14000
14790
|
const name = read(expr, ctx);
|
|
14001
|
-
return name ??
|
|
14791
|
+
return name ?? (0, import_behavioral_ir7.patternHole)(holeName(expr, ctx));
|
|
14002
14792
|
}
|
|
14003
14793
|
function holeName(expr, ctx) {
|
|
14004
14794
|
const bound = boundOnce(expr, ctx);
|