@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.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";
|
|
@@ -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;
|
|
@@ -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)) {
|
|
@@ -4909,7 +5017,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4909
5017
|
];
|
|
4910
5018
|
const { byTerminal } = computePathConditions(
|
|
4911
5019
|
func,
|
|
4912
|
-
terminals.map(({ node }) => node)
|
|
5020
|
+
terminals.map(({ node }) => node),
|
|
5021
|
+
barriers
|
|
4913
5022
|
);
|
|
4914
5023
|
const wantsFallthrough = terminalPatterns.some(
|
|
4915
5024
|
(p) => p.match.type === "functionFallthrough"
|
|
@@ -4921,7 +5030,11 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4921
5030
|
if (!hasDefaultTerminal) {
|
|
4922
5031
|
const synthetic = makeFallthroughTerminal(func);
|
|
4923
5032
|
terminals.push(synthetic);
|
|
4924
|
-
const pathResult = computePathConditions(
|
|
5033
|
+
const pathResult = computePathConditions(
|
|
5034
|
+
func,
|
|
5035
|
+
[synthetic.node],
|
|
5036
|
+
barriers
|
|
5037
|
+
);
|
|
4925
5038
|
byTerminal.set(
|
|
4926
5039
|
synthetic.node,
|
|
4927
5040
|
pathResult.fallthrough.length > 0 ? pathResult.fallthrough : [[]]
|
|
@@ -5052,7 +5165,7 @@ function indexFunctions(sf) {
|
|
|
5052
5165
|
import { createHash as createHash2 } from "crypto";
|
|
5053
5166
|
import fs2 from "fs/promises";
|
|
5054
5167
|
import path2 from "path";
|
|
5055
|
-
var SCHEMA_VERSION = "
|
|
5168
|
+
var SCHEMA_VERSION = "6";
|
|
5056
5169
|
var MAX_ENTRIES = 2;
|
|
5057
5170
|
var ENTRY_PREFIX = "key-";
|
|
5058
5171
|
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
@@ -5064,6 +5177,7 @@ function createCacheLayer(cacheDir) {
|
|
|
5064
5177
|
kind: "miss",
|
|
5065
5178
|
diagnostic: { kind: "miss", missReason: "no-manifest" }
|
|
5066
5179
|
}),
|
|
5180
|
+
plan: async () => null,
|
|
5067
5181
|
write: async () => {
|
|
5068
5182
|
}
|
|
5069
5183
|
};
|
|
@@ -5091,20 +5205,36 @@ function createCacheLayer(cacheDir) {
|
|
|
5091
5205
|
return {
|
|
5092
5206
|
kind: "hit",
|
|
5093
5207
|
summaries: manifest.summaries,
|
|
5208
|
+
...manifest.projectRoot === void 0 ? {} : { projectRoot: manifest.projectRoot },
|
|
5094
5209
|
diagnostic: { kind: "hit" }
|
|
5095
5210
|
};
|
|
5096
5211
|
},
|
|
5097
|
-
async
|
|
5212
|
+
async plan(input) {
|
|
5213
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5214
|
+
const manifest = await readManifest(path2.join(entryDir, "manifest.json"));
|
|
5215
|
+
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
5216
|
+
return null;
|
|
5217
|
+
}
|
|
5218
|
+
const currentTsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5219
|
+
if (!fileStampEquals(manifest.tsconfigStamp, currentTsconfigStamp)) {
|
|
5220
|
+
return null;
|
|
5221
|
+
}
|
|
5222
|
+
await markUsed(entryDir);
|
|
5223
|
+
return buildPlan(manifest, await resolveFileStamps(input));
|
|
5224
|
+
},
|
|
5225
|
+
async write(input, summaries, attribution) {
|
|
5226
|
+
const entryDir = entryDirFor(cacheDir, input);
|
|
5227
|
+
const previous = await readManifest(path2.join(entryDir, "manifest.json"));
|
|
5098
5228
|
const tsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5099
|
-
const files = await resolveFileStamps(input);
|
|
5229
|
+
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
5100
5230
|
const manifest = {
|
|
5101
5231
|
schemaVersion: SCHEMA_VERSION,
|
|
5102
5232
|
adapterPacksDigest: input.adapterPacksDigest,
|
|
5103
5233
|
tsconfigStamp,
|
|
5104
5234
|
files,
|
|
5105
|
-
summaries
|
|
5235
|
+
summaries,
|
|
5236
|
+
...attribution === void 0 ? {} : encodeAttribution(attribution)
|
|
5106
5237
|
};
|
|
5107
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
5108
5238
|
await fs2.mkdir(entryDir, { recursive: true });
|
|
5109
5239
|
await fs2.writeFile(
|
|
5110
5240
|
path2.join(entryDir, "manifest.json"),
|
|
@@ -5114,6 +5244,171 @@ function createCacheLayer(cacheDir) {
|
|
|
5114
5244
|
}
|
|
5115
5245
|
};
|
|
5116
5246
|
}
|
|
5247
|
+
async function buildPlan(manifest, currentStamps) {
|
|
5248
|
+
const stored = new Map(manifest.files.map((f) => [f.path, f]));
|
|
5249
|
+
const current2 = new Map(currentStamps.map((f) => [f.path, f]));
|
|
5250
|
+
const changed = /* @__PURE__ */ new Set();
|
|
5251
|
+
const removed = /* @__PURE__ */ new Set();
|
|
5252
|
+
for (const p of stored.keys()) {
|
|
5253
|
+
if (!current2.has(p)) {
|
|
5254
|
+
removed.add(p);
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
const toVerify = [];
|
|
5258
|
+
for (const [p, stamp] of current2) {
|
|
5259
|
+
const before = stored.get(p);
|
|
5260
|
+
if (before === void 0) {
|
|
5261
|
+
changed.add(p);
|
|
5262
|
+
} else if (!fileStampEquals(before, stamp)) {
|
|
5263
|
+
if (before.contentHash === void 0) {
|
|
5264
|
+
changed.add(p);
|
|
5265
|
+
} else {
|
|
5266
|
+
toVerify.push(p);
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
await Promise.all(
|
|
5271
|
+
toVerify.map(async (p) => {
|
|
5272
|
+
const hash = await hashFile(p);
|
|
5273
|
+
if (hash === null || hash !== stored.get(p)?.contentHash) {
|
|
5274
|
+
changed.add(p);
|
|
5275
|
+
}
|
|
5276
|
+
})
|
|
5277
|
+
);
|
|
5278
|
+
const roots = /* @__PURE__ */ new Map();
|
|
5279
|
+
const rootNames = manifest.roots ?? [];
|
|
5280
|
+
const depPaths = manifest.depPaths ?? [];
|
|
5281
|
+
let rootsDeclined = 0;
|
|
5282
|
+
rootNames.forEach((rootPath, i) => {
|
|
5283
|
+
const meta = manifest.rootMeta?.[i];
|
|
5284
|
+
if (meta === void 0) {
|
|
5285
|
+
return;
|
|
5286
|
+
}
|
|
5287
|
+
if (!meta.cacheable) {
|
|
5288
|
+
rootsDeclined += 1;
|
|
5289
|
+
}
|
|
5290
|
+
roots.set(rootPath, {
|
|
5291
|
+
path: rootPath,
|
|
5292
|
+
cacheable: meta.cacheable,
|
|
5293
|
+
deps: meta.deps.flatMap((d) => {
|
|
5294
|
+
const p = depPaths[d];
|
|
5295
|
+
return p === void 0 ? [] : [p];
|
|
5296
|
+
}),
|
|
5297
|
+
claims: meta.claims,
|
|
5298
|
+
mountPrefixes: meta.mountPrefixes,
|
|
5299
|
+
packs: meta.packs
|
|
5300
|
+
});
|
|
5301
|
+
});
|
|
5302
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
5303
|
+
for (const [rootPath, record] of roots) {
|
|
5304
|
+
if (!record.cacheable || !current2.has(rootPath)) {
|
|
5305
|
+
continue;
|
|
5306
|
+
}
|
|
5307
|
+
if (changed.has(rootPath)) {
|
|
5308
|
+
continue;
|
|
5309
|
+
}
|
|
5310
|
+
const depMoved = record.deps.some((d) => changed.has(d) || removed.has(d));
|
|
5311
|
+
if (!depMoved) {
|
|
5312
|
+
validRoots.add(rootPath);
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
const owners = manifest.owners ?? [];
|
|
5316
|
+
return {
|
|
5317
|
+
changed,
|
|
5318
|
+
removed,
|
|
5319
|
+
roots,
|
|
5320
|
+
validRoots,
|
|
5321
|
+
rootsDeclined,
|
|
5322
|
+
storedProjectRoot: manifest.projectRoot ?? null,
|
|
5323
|
+
reuse(valid) {
|
|
5324
|
+
const summaries = [];
|
|
5325
|
+
const reusedOwners = [];
|
|
5326
|
+
manifest.summaries.forEach((summary, i) => {
|
|
5327
|
+
const ownerPaths = (owners[i] ?? []).flatMap((o) => {
|
|
5328
|
+
const p = rootNames[o];
|
|
5329
|
+
return p === void 0 ? [] : [p];
|
|
5330
|
+
});
|
|
5331
|
+
if (ownerPaths.some((p) => valid.has(p))) {
|
|
5332
|
+
summaries.push(summary);
|
|
5333
|
+
reusedOwners.push(ownerPaths.filter((p) => valid.has(p)));
|
|
5334
|
+
}
|
|
5335
|
+
});
|
|
5336
|
+
return { summaries, owners: reusedOwners };
|
|
5337
|
+
},
|
|
5338
|
+
allSummaries() {
|
|
5339
|
+
return manifest.summaries;
|
|
5340
|
+
},
|
|
5341
|
+
attribution() {
|
|
5342
|
+
return {
|
|
5343
|
+
roots: [...roots.values()],
|
|
5344
|
+
owners: owners.map(
|
|
5345
|
+
(ownerIds) => ownerIds.flatMap((o) => {
|
|
5346
|
+
const p = rootNames[o];
|
|
5347
|
+
return p === void 0 ? [] : [p];
|
|
5348
|
+
})
|
|
5349
|
+
),
|
|
5350
|
+
...manifest.projectRoot === void 0 ? {} : { projectRoot: manifest.projectRoot }
|
|
5351
|
+
};
|
|
5352
|
+
}
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
5355
|
+
function encodeAttribution(attribution) {
|
|
5356
|
+
const roots = attribution.roots.map((r) => r.path);
|
|
5357
|
+
const rootIndex = new Map(roots.map((p, i) => [p, i]));
|
|
5358
|
+
const depIndex = /* @__PURE__ */ new Map();
|
|
5359
|
+
const depPaths = [];
|
|
5360
|
+
const depIdOf = (p) => {
|
|
5361
|
+
const existing = depIndex.get(p);
|
|
5362
|
+
if (existing !== void 0) {
|
|
5363
|
+
return existing;
|
|
5364
|
+
}
|
|
5365
|
+
const id = depPaths.length;
|
|
5366
|
+
depPaths.push(p);
|
|
5367
|
+
depIndex.set(p, id);
|
|
5368
|
+
return id;
|
|
5369
|
+
};
|
|
5370
|
+
const rootMeta = attribution.roots.map((r) => ({
|
|
5371
|
+
cacheable: r.cacheable,
|
|
5372
|
+
deps: r.deps.map(depIdOf),
|
|
5373
|
+
claims: r.claims,
|
|
5374
|
+
mountPrefixes: r.mountPrefixes,
|
|
5375
|
+
packs: r.packs
|
|
5376
|
+
}));
|
|
5377
|
+
const owners = attribution.owners.map(
|
|
5378
|
+
(ownerPaths) => ownerPaths.flatMap((p) => {
|
|
5379
|
+
const i = rootIndex.get(p);
|
|
5380
|
+
return i === void 0 ? [] : [i];
|
|
5381
|
+
})
|
|
5382
|
+
);
|
|
5383
|
+
return {
|
|
5384
|
+
roots,
|
|
5385
|
+
rootMeta,
|
|
5386
|
+
depPaths,
|
|
5387
|
+
owners,
|
|
5388
|
+
...attribution.projectRoot === void 0 ? {} : { projectRoot: attribution.projectRoot }
|
|
5389
|
+
};
|
|
5390
|
+
}
|
|
5391
|
+
async function hashStamps(stamps, previous) {
|
|
5392
|
+
const before = new Map((previous?.files ?? []).map((f) => [f.path, f]));
|
|
5393
|
+
return Promise.all(
|
|
5394
|
+
stamps.map(async (stamp) => {
|
|
5395
|
+
const prior = before.get(stamp.path);
|
|
5396
|
+
if (prior !== void 0 && prior.contentHash !== void 0 && fileStampEquals(prior, stamp)) {
|
|
5397
|
+
return { ...stamp, contentHash: prior.contentHash };
|
|
5398
|
+
}
|
|
5399
|
+
const contentHash = await hashFile(stamp.path);
|
|
5400
|
+
return contentHash === null ? stamp : { ...stamp, contentHash };
|
|
5401
|
+
})
|
|
5402
|
+
);
|
|
5403
|
+
}
|
|
5404
|
+
async function hashFile(filePath) {
|
|
5405
|
+
try {
|
|
5406
|
+
const content = await fs2.readFile(filePath);
|
|
5407
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 16);
|
|
5408
|
+
} catch {
|
|
5409
|
+
return null;
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5117
5412
|
async function describeAbsentEntry(cacheDir) {
|
|
5118
5413
|
try {
|
|
5119
5414
|
const entries = await fs2.readdir(cacheDir, { withFileTypes: true });
|
|
@@ -5127,7 +5422,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
5127
5422
|
SCHEMA_VERSION,
|
|
5128
5423
|
input.adapterPacksDigest,
|
|
5129
5424
|
input.tsconfigPath ?? ""
|
|
5130
|
-
].join("
|
|
5425
|
+
].join(" ");
|
|
5131
5426
|
const name = createHash2("sha256").update(key).digest("hex").slice(0, 16);
|
|
5132
5427
|
return path2.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
5133
5428
|
}
|
|
@@ -6986,7 +7281,7 @@ function calleeOf(decorator) {
|
|
|
6986
7281
|
|
|
6987
7282
|
// src/discovery/decoratedMethod.ts
|
|
6988
7283
|
function resolverTypeName(args) {
|
|
6989
|
-
return args.
|
|
7284
|
+
return args.typeMap[args.decoratorName] ?? args.classTypeName ?? null;
|
|
6990
7285
|
}
|
|
6991
7286
|
function resolveResolverClassTypeName(decoratorArg) {
|
|
6992
7287
|
if (Node32.isArrowFunction(decoratorArg)) {
|
|
@@ -9550,7 +9845,10 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
|
|
|
9550
9845
|
resolverInfo: {
|
|
9551
9846
|
typeName,
|
|
9552
9847
|
fieldName,
|
|
9553
|
-
...schemaSdl !== null ? {
|
|
9848
|
+
...schemaSdl !== null ? {
|
|
9849
|
+
schemaSdl,
|
|
9850
|
+
schemaDocument: config.getSourceFile().getFilePath()
|
|
9851
|
+
} : {}
|
|
9554
9852
|
}
|
|
9555
9853
|
});
|
|
9556
9854
|
}
|
|
@@ -9747,7 +10045,15 @@ function discoverUnits(sourceFile, patterns, resolution, mountPrefixes) {
|
|
|
9747
10045
|
}
|
|
9748
10046
|
|
|
9749
10047
|
// src/discovery/mountPrefix.ts
|
|
9750
|
-
var NO_MOUNTS = {
|
|
10048
|
+
var NO_MOUNTS = {
|
|
10049
|
+
// Recorded even with no mounts anywhere: a mount added later in some
|
|
10050
|
+
// other file changes this router's prefix without touching its file.
|
|
10051
|
+
effectivePrefixFor: (routerNode) => {
|
|
10052
|
+
recordMountPrefix(nodeId(routerNode), "");
|
|
10053
|
+
return "";
|
|
10054
|
+
},
|
|
10055
|
+
prefixForId: () => ""
|
|
10056
|
+
};
|
|
9751
10057
|
function buildMountPrefixIndex(packsByFile, resolution) {
|
|
9752
10058
|
const subjectIdsByPack = /* @__PURE__ */ new Map();
|
|
9753
10059
|
const mountWorkByPack = /* @__PURE__ */ new Map();
|
|
@@ -9804,10 +10110,15 @@ function buildMountPrefixIndex(packsByFile, resolution) {
|
|
|
9804
10110
|
return NO_MOUNTS;
|
|
9805
10111
|
}
|
|
9806
10112
|
const memo = /* @__PURE__ */ new Map();
|
|
10113
|
+
const byId = (childId) => resolvePrefix(edgesByChild, memo, childId, /* @__PURE__ */ new Set()) ?? "";
|
|
9807
10114
|
return {
|
|
9808
10115
|
effectivePrefixFor(routerNode) {
|
|
9809
|
-
|
|
9810
|
-
|
|
10116
|
+
const childId = nodeId(routerNode);
|
|
10117
|
+
const prefix = byId(childId);
|
|
10118
|
+
recordMountPrefix(childId, prefix);
|
|
10119
|
+
return prefix;
|
|
10120
|
+
},
|
|
10121
|
+
prefixForId: byId
|
|
9811
10122
|
};
|
|
9812
10123
|
}
|
|
9813
10124
|
function recordEdge(edgesByChild, candidate) {
|
|
@@ -10086,6 +10397,8 @@ var ResolutionStore = class {
|
|
|
10086
10397
|
fullyExtracted = /* @__PURE__ */ new Set();
|
|
10087
10398
|
seededValues = /* @__PURE__ */ new Set();
|
|
10088
10399
|
importedNames = /* @__PURE__ */ new Map();
|
|
10400
|
+
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
10401
|
+
lastQueryWalked = [];
|
|
10089
10402
|
declarations = /* @__PURE__ */ new Map();
|
|
10090
10403
|
graph = new ModuleGraph();
|
|
10091
10404
|
stale = true;
|
|
@@ -10146,7 +10459,10 @@ var ResolutionStore = class {
|
|
|
10146
10459
|
const declaration = `${nodeId(refersTo)}|${modules.join(",")}`;
|
|
10147
10460
|
const cached = this.importedNames.get(declaration);
|
|
10148
10461
|
if (cached !== void 0) {
|
|
10149
|
-
|
|
10462
|
+
for (const walkedPath of cached.walked) {
|
|
10463
|
+
recordFileDependency(walkedPath);
|
|
10464
|
+
}
|
|
10465
|
+
return cached.names;
|
|
10150
10466
|
}
|
|
10151
10467
|
const target = factKeyOf(value);
|
|
10152
10468
|
const found = this.resolveByWaves(
|
|
@@ -10154,7 +10470,10 @@ var ResolutionStore = class {
|
|
|
10154
10470
|
"wantedOrigin",
|
|
10155
10471
|
() => this.lookupImportedNames(target, modules)
|
|
10156
10472
|
) ?? [];
|
|
10157
|
-
this.importedNames.set(declaration,
|
|
10473
|
+
this.importedNames.set(declaration, {
|
|
10474
|
+
names: found,
|
|
10475
|
+
walked: [...this.lastQueryWalked]
|
|
10476
|
+
});
|
|
10158
10477
|
return found;
|
|
10159
10478
|
}
|
|
10160
10479
|
/**
|
|
@@ -10188,6 +10507,7 @@ var ResolutionStore = class {
|
|
|
10188
10507
|
this.wantValue(question, value);
|
|
10189
10508
|
this.seedValue(value);
|
|
10190
10509
|
const walked = /* @__PURE__ */ new Set();
|
|
10510
|
+
this.lastQueryWalked = [];
|
|
10191
10511
|
let frontier = alsoFrom === void 0 ? [value.getSourceFile()] : [value.getSourceFile(), alsoFrom];
|
|
10192
10512
|
for (let hop = 0; hop <= MAX_MODULE_HOPS; hop++) {
|
|
10193
10513
|
const next = [];
|
|
@@ -10196,6 +10516,8 @@ var ResolutionStore = class {
|
|
|
10196
10516
|
continue;
|
|
10197
10517
|
}
|
|
10198
10518
|
walked.add(sourceFile.getFilePath());
|
|
10519
|
+
this.lastQueryWalked.push(sourceFile.getFilePath());
|
|
10520
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
10199
10521
|
this.extractFile(sourceFile);
|
|
10200
10522
|
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
10201
10523
|
}
|
|
@@ -10495,6 +10817,27 @@ function moduleInitSummary(sourceFile, effects, options) {
|
|
|
10495
10817
|
return assembleSummary(raw, options);
|
|
10496
10818
|
}
|
|
10497
10819
|
|
|
10820
|
+
// src/referencedFiles.ts
|
|
10821
|
+
function createReferenceIndex(sourceFiles) {
|
|
10822
|
+
const direct = /* @__PURE__ */ new Map();
|
|
10823
|
+
for (const sourceFile of sourceFiles) {
|
|
10824
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
10825
|
+
for (const target of sourceFile.getReferencedSourceFiles()) {
|
|
10826
|
+
if (target.isInNodeModules() || target.isDeclarationFile()) {
|
|
10827
|
+
continue;
|
|
10828
|
+
}
|
|
10829
|
+
referenced.add(target.getFilePath());
|
|
10830
|
+
}
|
|
10831
|
+
direct.set(sourceFile.getFilePath(), referenced);
|
|
10832
|
+
}
|
|
10833
|
+
const none = /* @__PURE__ */ new Set();
|
|
10834
|
+
return {
|
|
10835
|
+
directOf(filePath) {
|
|
10836
|
+
return direct.get(filePath) ?? none;
|
|
10837
|
+
}
|
|
10838
|
+
};
|
|
10839
|
+
}
|
|
10840
|
+
|
|
10498
10841
|
// src/resolve/boundaryEffects.ts
|
|
10499
10842
|
import { evaluate as evaluate3, lit as lit3, rule as rule3, variable } from "@suss/datalog";
|
|
10500
10843
|
var EFFECT_RULES = [
|
|
@@ -10679,6 +11022,11 @@ function classifyStop(declarations) {
|
|
|
10679
11022
|
if (declarations.length === 0) {
|
|
10680
11023
|
return "noDeclaration";
|
|
10681
11024
|
}
|
|
11025
|
+
for (const declaration of declarations) {
|
|
11026
|
+
if (!isInExternalCode(declaration.getSourceFile())) {
|
|
11027
|
+
recordFileDependency(declaration.getSourceFile().getFilePath());
|
|
11028
|
+
}
|
|
11029
|
+
}
|
|
10682
11030
|
if (declarations.every(isExternalDeclaration)) {
|
|
10683
11031
|
return "outsideRun";
|
|
10684
11032
|
}
|
|
@@ -10885,7 +11233,7 @@ var REACHABLE_RULES = [
|
|
|
10885
11233
|
)
|
|
10886
11234
|
];
|
|
10887
11235
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
10888
|
-
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS) {
|
|
11236
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = []) {
|
|
10889
11237
|
const lookup = createSourceFileLookup(project);
|
|
10890
11238
|
const db = facts?.db ?? new Database3();
|
|
10891
11239
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
@@ -10905,6 +11253,15 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10905
11253
|
db.add("entry", [key]);
|
|
10906
11254
|
}
|
|
10907
11255
|
}
|
|
11256
|
+
const knownKeys = /* @__PURE__ */ new Set();
|
|
11257
|
+
for (const summary of alreadySummarized) {
|
|
11258
|
+
const func = lookup.functionAt(summary.location);
|
|
11259
|
+
if (func !== null) {
|
|
11260
|
+
const key = nodeKey2(func);
|
|
11261
|
+
knownKeys.add(key);
|
|
11262
|
+
facts?.unitKeyBySummary.set(summary, key);
|
|
11263
|
+
}
|
|
11264
|
+
}
|
|
10908
11265
|
for (; ; ) {
|
|
10909
11266
|
evaluate4(db, REACHABLE_RULES);
|
|
10910
11267
|
const frontier = db.facts("reachable").map(([key]) => String(key)).filter((key) => !scanned.has(key));
|
|
@@ -10922,7 +11279,11 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10922
11279
|
...recognizers.resolveCallable === void 0 ? {} : { resolveCallable: recognizers.resolveCallable },
|
|
10923
11280
|
...cameFrom === void 0 ? {} : { reachedFrom: cameFrom }
|
|
10924
11281
|
};
|
|
10925
|
-
const { candidates, stops } =
|
|
11282
|
+
const { candidates, stops } = scanWithRecording(
|
|
11283
|
+
key,
|
|
11284
|
+
facts,
|
|
11285
|
+
() => collectReachable(source.func, scan)
|
|
11286
|
+
);
|
|
10926
11287
|
if (stops.length > 0) {
|
|
10927
11288
|
stopsByKey.set(key, stops);
|
|
10928
11289
|
}
|
|
@@ -10941,7 +11302,7 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10941
11302
|
const reached = [];
|
|
10942
11303
|
for (const [keyAtom] of db.facts("reachable")) {
|
|
10943
11304
|
const key = String(keyAtom);
|
|
10944
|
-
if (seedKeys.has(key)) {
|
|
11305
|
+
if (seedKeys.has(key) || knownKeys.has(key)) {
|
|
10945
11306
|
continue;
|
|
10946
11307
|
}
|
|
10947
11308
|
const candidate = functionByKey.get(key);
|
|
@@ -10955,7 +11316,11 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10955
11316
|
candidate.func.getSourceFile().getFilePath()
|
|
10956
11317
|
);
|
|
10957
11318
|
}
|
|
10958
|
-
const summary =
|
|
11319
|
+
const summary = scanWithRecording(
|
|
11320
|
+
key,
|
|
11321
|
+
facts,
|
|
11322
|
+
() => extractReachableSummary(candidate, options, recognizers)
|
|
11323
|
+
);
|
|
10959
11324
|
facts?.unitKeyBySummary.set(summary, key);
|
|
10960
11325
|
rememberSummary(summariesByKey, key, summary);
|
|
10961
11326
|
reached.push(summary);
|
|
@@ -10963,6 +11328,20 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10963
11328
|
recordStops(stopsByKey, summariesByKey, options);
|
|
10964
11329
|
return [...seeds, ...reached];
|
|
10965
11330
|
}
|
|
11331
|
+
function scanWithRecording(key, facts, fn) {
|
|
11332
|
+
const filesByKey = facts?.filesByKey;
|
|
11333
|
+
if (filesByKey === void 0) {
|
|
11334
|
+
return fn();
|
|
11335
|
+
}
|
|
11336
|
+
const sink = createDependencySink();
|
|
11337
|
+
const result = withDependencySink(sink, fn);
|
|
11338
|
+
const bucket = filesByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
11339
|
+
for (const filePath of sink.files) {
|
|
11340
|
+
bucket.add(filePath);
|
|
11341
|
+
}
|
|
11342
|
+
filesByKey.set(key, bucket);
|
|
11343
|
+
return result;
|
|
11344
|
+
}
|
|
10966
11345
|
function rememberSummary(summariesByKey, key, summary) {
|
|
10967
11346
|
const bucket = summariesByKey.get(key) ?? [];
|
|
10968
11347
|
bucket.push(summary);
|
|
@@ -12224,6 +12603,36 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
12224
12603
|
function responseAccessorNames(pack, kind) {
|
|
12225
12604
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
12226
12605
|
}
|
|
12606
|
+
var ACCESSOR_FIELD_SEMANTICS = {
|
|
12607
|
+
bodyAccessors: "body",
|
|
12608
|
+
statusAccessors: "statusCode",
|
|
12609
|
+
successAccessors: "statusRange"
|
|
12610
|
+
};
|
|
12611
|
+
function responseAccessors(pack) {
|
|
12612
|
+
const out = {};
|
|
12613
|
+
for (const [field, kind] of Object.entries(ACCESSOR_FIELD_SEMANTICS)) {
|
|
12614
|
+
const names = responseAccessorNames(pack, kind);
|
|
12615
|
+
if (names !== void 0 && names.length > 0) {
|
|
12616
|
+
out[field] = names;
|
|
12617
|
+
}
|
|
12618
|
+
}
|
|
12619
|
+
return out;
|
|
12620
|
+
}
|
|
12621
|
+
var FUNCTION_FALLTHROUGH_TERMINAL = {
|
|
12622
|
+
kind: "return",
|
|
12623
|
+
match: { type: "functionFallthrough" },
|
|
12624
|
+
extraction: {}
|
|
12625
|
+
};
|
|
12626
|
+
function terminalsFor(unit, pack) {
|
|
12627
|
+
const declared = unit.terminals ?? pack.terminals;
|
|
12628
|
+
if (unit.callSite === void 0) {
|
|
12629
|
+
return declared;
|
|
12630
|
+
}
|
|
12631
|
+
if (declared.some((p) => p.match.type === "functionFallthrough")) {
|
|
12632
|
+
return declared;
|
|
12633
|
+
}
|
|
12634
|
+
return [...declared, FUNCTION_FALLTHROUGH_TERMINAL];
|
|
12635
|
+
}
|
|
12227
12636
|
function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers, barriers, resolveWrittenValue) {
|
|
12228
12637
|
const { func, kind, name } = unit;
|
|
12229
12638
|
if (func === null) {
|
|
@@ -12235,7 +12644,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12235
12644
|
);
|
|
12236
12645
|
const extracted = extractRawBranches(
|
|
12237
12646
|
func,
|
|
12238
|
-
unit
|
|
12647
|
+
terminalsFor(unit, pack),
|
|
12239
12648
|
invocationRecognizers,
|
|
12240
12649
|
accessRecognizers,
|
|
12241
12650
|
barriers,
|
|
@@ -12271,8 +12680,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12271
12680
|
}
|
|
12272
12681
|
}
|
|
12273
12682
|
}
|
|
12274
|
-
const
|
|
12275
|
-
const statusAccessors = unit.callSite !== void 0 ? responseAccessorNames(pack, "statusCode") : void 0;
|
|
12683
|
+
const accessors = unit.callSite !== void 0 ? responseAccessors(pack) : {};
|
|
12276
12684
|
return {
|
|
12277
12685
|
identity: {
|
|
12278
12686
|
name,
|
|
@@ -12296,8 +12704,8 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12296
12704
|
bodyContent: bodyContentOf(func),
|
|
12297
12705
|
dependencyCalls: depCalls,
|
|
12298
12706
|
declaredContract: null,
|
|
12299
|
-
...
|
|
12300
|
-
...
|
|
12707
|
+
...accessors,
|
|
12708
|
+
...unit.callSite !== void 0 && pack.failureDelivery !== void 0 ? { failureDelivery: pack.failureDelivery } : {}
|
|
12301
12709
|
};
|
|
12302
12710
|
}
|
|
12303
12711
|
function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
@@ -12651,12 +13059,20 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12651
13059
|
if (claimant.pack === pack.name && claimant.file === sourceFile.getFilePath() && tally !== void 0) {
|
|
12652
13060
|
tally.selfCollisions += 1;
|
|
12653
13061
|
}
|
|
13062
|
+
if (claimant.file !== sourceFile.getFilePath()) {
|
|
13063
|
+
recordFileDependency(claimant.file);
|
|
13064
|
+
}
|
|
12654
13065
|
continue;
|
|
12655
13066
|
}
|
|
12656
13067
|
claimed.set(claimKey, {
|
|
12657
13068
|
pack: pack.name,
|
|
12658
13069
|
file: sourceFile.getFilePath()
|
|
12659
13070
|
});
|
|
13071
|
+
recordUnitClaim(claimKey, pack.name);
|
|
13072
|
+
const declaringFile = unit.func?.getSourceFile().getFilePath();
|
|
13073
|
+
if (declaringFile !== void 0 && declaringFile !== sourceFile.getFilePath()) {
|
|
13074
|
+
recordFileDependency(declaringFile);
|
|
13075
|
+
}
|
|
12660
13076
|
unitsWalkedHere += 1;
|
|
12661
13077
|
if (tally !== void 0) {
|
|
12662
13078
|
tally.unitsClaimed += 1;
|
|
@@ -12695,6 +13111,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12695
13111
|
}
|
|
12696
13112
|
if (unit.resolverInfo.schemaSdl !== void 0) {
|
|
12697
13113
|
raw.graphqlSchemaSdl = unit.resolverInfo.schemaSdl;
|
|
13114
|
+
if (unit.resolverInfo.schemaDocument !== void 0) {
|
|
13115
|
+
raw.sourceDocumentLabel = unit.resolverInfo.schemaDocument;
|
|
13116
|
+
}
|
|
12698
13117
|
if (unit.resolverInfo.typeName !== null) {
|
|
12699
13118
|
const contract = deriveGraphqlContract(
|
|
12700
13119
|
unit.resolverInfo.schemaSdl,
|
|
@@ -12883,6 +13302,37 @@ function fileImporting(project, modulePrefix) {
|
|
|
12883
13302
|
}
|
|
12884
13303
|
return void 0;
|
|
12885
13304
|
}
|
|
13305
|
+
function liftSchemasOntoDocuments(summaries) {
|
|
13306
|
+
const sdlByDocument = /* @__PURE__ */ new Map();
|
|
13307
|
+
for (const summary of summaries) {
|
|
13308
|
+
const label = readSourceDocumentMetadata(summary)?.label;
|
|
13309
|
+
const graphql = readGraphqlMetadata2(summary);
|
|
13310
|
+
if (label === void 0 || graphql?.schemaSdl === void 0) {
|
|
13311
|
+
continue;
|
|
13312
|
+
}
|
|
13313
|
+
sdlByDocument.set(label, graphql.schemaSdl);
|
|
13314
|
+
const { schemaSdl: _movedToTheDocument, ...rest } = graphql;
|
|
13315
|
+
summary.metadata = withGraphqlMetadata2(summary.metadata, rest);
|
|
13316
|
+
}
|
|
13317
|
+
for (const [label, schemaSdl] of sdlByDocument) {
|
|
13318
|
+
summaries.push(schemaDocumentSummary(label, schemaSdl));
|
|
13319
|
+
}
|
|
13320
|
+
}
|
|
13321
|
+
function schemaDocumentSummary(label, schemaSdl) {
|
|
13322
|
+
return {
|
|
13323
|
+
kind: "library",
|
|
13324
|
+
location: { file: label, range: { start: 0, end: 0 }, exportName: null },
|
|
13325
|
+
identity: { name: label, exportPath: null, boundaryBinding: null },
|
|
13326
|
+
inputs: [],
|
|
13327
|
+
transitions: [],
|
|
13328
|
+
gaps: [],
|
|
13329
|
+
confidence: { source: "declared", level: "high" },
|
|
13330
|
+
metadata: withGraphqlMetadata2(
|
|
13331
|
+
withSourceDocumentMetadata(void 0, { label }),
|
|
13332
|
+
{ schemaSdl }
|
|
13333
|
+
)
|
|
13334
|
+
};
|
|
13335
|
+
}
|
|
12886
13336
|
function libraryEnvReadMarker(pack, declared, importer) {
|
|
12887
13337
|
return {
|
|
12888
13338
|
kind: "library",
|
|
@@ -13133,8 +13583,8 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path11, options) {
|
|
|
13133
13583
|
summary.confidence = { source: "inferred_static", level: "low" };
|
|
13134
13584
|
return summary;
|
|
13135
13585
|
}
|
|
13136
|
-
function named(summaries, workspace) {
|
|
13137
|
-
const projectRoot = commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
13586
|
+
function named(summaries, workspace, storedProjectRoot) {
|
|
13587
|
+
const projectRoot = storedProjectRoot ?? commonDirectoryOf(summaries.map((s) => s.location.file));
|
|
13138
13588
|
nameSummaries(summaries, {
|
|
13139
13589
|
workspace: workspace ?? workspaceNameFor(projectRoot),
|
|
13140
13590
|
projectRoot
|
|
@@ -13265,7 +13715,29 @@ function createTypeScriptAdapter(config) {
|
|
|
13265
13715
|
if (config.onTiming !== void 0) {
|
|
13266
13716
|
config.onTiming(timer.report());
|
|
13267
13717
|
}
|
|
13268
|
-
return named(lookup.summaries, config.workspace);
|
|
13718
|
+
return named(lookup.summaries, config.workspace, lookup.projectRoot);
|
|
13719
|
+
}
|
|
13720
|
+
const plan = lookup.diagnostic.missReason === "files-changed" ? await timer.timeAsync("cache.plan", () => cache.plan(cacheInput)) : null;
|
|
13721
|
+
if (plan !== null && plan.changed.size === 0 && plan.removed.size === 0) {
|
|
13722
|
+
try {
|
|
13723
|
+
await cache.write(
|
|
13724
|
+
cacheInput,
|
|
13725
|
+
plan.allSummaries(),
|
|
13726
|
+
plan.attribution()
|
|
13727
|
+
);
|
|
13728
|
+
} catch {
|
|
13729
|
+
}
|
|
13730
|
+
if (config.onCacheDiagnostic !== void 0) {
|
|
13731
|
+
config.onCacheDiagnostic({ kind: "hit" });
|
|
13732
|
+
}
|
|
13733
|
+
if (config.onTiming !== void 0) {
|
|
13734
|
+
config.onTiming(timer.report());
|
|
13735
|
+
}
|
|
13736
|
+
return named(
|
|
13737
|
+
plan.allSummaries(),
|
|
13738
|
+
config.workspace,
|
|
13739
|
+
plan.storedProjectRoot ?? void 0
|
|
13740
|
+
);
|
|
13269
13741
|
}
|
|
13270
13742
|
let candidatePaths = null;
|
|
13271
13743
|
if (lazyEligible) {
|
|
@@ -13296,16 +13768,58 @@ function createTypeScriptAdapter(config) {
|
|
|
13296
13768
|
"mountPrefix",
|
|
13297
13769
|
() => buildMountPrefixIndex(packsByFile, resolution)
|
|
13298
13770
|
);
|
|
13771
|
+
const caching = cacheDir !== null;
|
|
13772
|
+
const validRoots = /* @__PURE__ */ new Set();
|
|
13773
|
+
if (plan !== null) {
|
|
13774
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
13775
|
+
for (const [sf, packs] of packsByFile) {
|
|
13776
|
+
packNamesByPath.set(
|
|
13777
|
+
sf.getFilePath(),
|
|
13778
|
+
packs.map((p) => p.name).sort().join(",")
|
|
13779
|
+
);
|
|
13780
|
+
}
|
|
13781
|
+
for (const rootPath of plan.validRoots) {
|
|
13782
|
+
const record = plan.roots.get(rootPath);
|
|
13783
|
+
if (record === void 0) {
|
|
13784
|
+
continue;
|
|
13785
|
+
}
|
|
13786
|
+
if (!mountAssumptionsAgree(record, mountPrefixes)) {
|
|
13787
|
+
continue;
|
|
13788
|
+
}
|
|
13789
|
+
const stored = [...record.packs].sort().join(",");
|
|
13790
|
+
if ((packNamesByPath.get(rootPath) ?? "") !== stored) {
|
|
13791
|
+
continue;
|
|
13792
|
+
}
|
|
13793
|
+
validRoots.add(rootPath);
|
|
13794
|
+
}
|
|
13795
|
+
}
|
|
13796
|
+
const reused = plan !== null && validRoots.size > 0 ? plan.reuse(validRoots) : null;
|
|
13299
13797
|
const claimedUnits = /* @__PURE__ */ new Map();
|
|
13798
|
+
if (reused !== null && plan !== null) {
|
|
13799
|
+
for (const rootPath of validRoots) {
|
|
13800
|
+
for (const claim of plan.roots.get(rootPath)?.claims ?? []) {
|
|
13801
|
+
claimedUnits.set(claim.key, { pack: claim.pack, file: rootPath });
|
|
13802
|
+
}
|
|
13803
|
+
}
|
|
13804
|
+
}
|
|
13805
|
+
const walkList = reused === null ? sourceFiles : sourceFiles.filter((sf) => !validRoots.has(sf.getFilePath()));
|
|
13806
|
+
const sinkByRoot = /* @__PURE__ */ new Map();
|
|
13807
|
+
const ownersBySummary = /* @__PURE__ */ new Map();
|
|
13300
13808
|
timer.time("extract per-file", () => {
|
|
13301
|
-
for (const sourceFile of
|
|
13809
|
+
for (const sourceFile of walkList) {
|
|
13810
|
+
const rootPath = sourceFile.getFilePath();
|
|
13811
|
+
const sink = createDependencySink();
|
|
13812
|
+
if (caching) {
|
|
13813
|
+
sinkByRoot.set(rootPath, sink);
|
|
13814
|
+
}
|
|
13302
13815
|
const applicablePacks = packsByFile.get(sourceFile);
|
|
13303
13816
|
if (applicablePacks === void 0) {
|
|
13304
13817
|
continue;
|
|
13305
13818
|
}
|
|
13306
13819
|
try {
|
|
13307
|
-
|
|
13308
|
-
|
|
13820
|
+
const walked = withDependencySink(
|
|
13821
|
+
sink,
|
|
13822
|
+
() => extractFromSourceFile(
|
|
13309
13823
|
sourceFile,
|
|
13310
13824
|
applicablePacks,
|
|
13311
13825
|
claimedUnits,
|
|
@@ -13315,6 +13829,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13315
13829
|
mountPrefixes
|
|
13316
13830
|
)
|
|
13317
13831
|
);
|
|
13832
|
+
for (const summary of walked) {
|
|
13833
|
+
ownersBySummary.set(summary, /* @__PURE__ */ new Set([rootPath]));
|
|
13834
|
+
}
|
|
13835
|
+
summaries.push(...walked);
|
|
13318
13836
|
} catch (error) {
|
|
13319
13837
|
if (!(error instanceof RangeError)) {
|
|
13320
13838
|
throw error;
|
|
@@ -13323,23 +13841,32 @@ function createTypeScriptAdapter(config) {
|
|
|
13323
13841
|
}
|
|
13324
13842
|
}
|
|
13325
13843
|
});
|
|
13844
|
+
const wrapperInput = reused === null ? summaries : [...summaries, ...reused.summaries];
|
|
13326
13845
|
const withWrappers = timer.time(
|
|
13327
13846
|
"expandWrapperCallers",
|
|
13328
|
-
() => expandWrapperCallers(
|
|
13847
|
+
() => expandWrapperCallers(wrapperInput, project, config.extractorOptions)
|
|
13329
13848
|
);
|
|
13849
|
+
const pipeline = reused === null ? withWrappers : [...summaries, ...withWrappers.slice(wrapperInput.length)];
|
|
13330
13850
|
const withSubUnits = timer.time(
|
|
13331
13851
|
"synthesizeSubUnits",
|
|
13332
13852
|
() => synthesizeSubUnits(
|
|
13333
|
-
|
|
13853
|
+
pipeline,
|
|
13334
13854
|
project,
|
|
13335
13855
|
config.frameworks,
|
|
13336
13856
|
config.extractorOptions,
|
|
13337
|
-
tallies
|
|
13857
|
+
tallies,
|
|
13858
|
+
(created, parent) => {
|
|
13859
|
+
const parentOwners = ownersBySummary.get(parent);
|
|
13860
|
+
if (parentOwners !== void 0) {
|
|
13861
|
+
ownersBySummary.set(created, new Set(parentOwners));
|
|
13862
|
+
}
|
|
13863
|
+
}
|
|
13338
13864
|
)
|
|
13339
13865
|
);
|
|
13340
13866
|
const closureFacts = {
|
|
13341
13867
|
db: new Database5(),
|
|
13342
|
-
unitKeyBySummary: /* @__PURE__ */ new Map()
|
|
13868
|
+
unitKeyBySummary: /* @__PURE__ */ new Map(),
|
|
13869
|
+
...caching ? { filesByKey: /* @__PURE__ */ new Map() } : {}
|
|
13343
13870
|
};
|
|
13344
13871
|
const withClosure = config.includeReachable !== false ? timer.time(
|
|
13345
13872
|
"expandReachableClosure",
|
|
@@ -13357,12 +13884,28 @@ function createTypeScriptAdapter(config) {
|
|
|
13357
13884
|
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13358
13885
|
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value),
|
|
13359
13886
|
resolveCallable: (value, alsoFrom) => resolution.resolveCallable(value, alsoFrom)
|
|
13360
|
-
}
|
|
13887
|
+
},
|
|
13888
|
+
// Reached units the cache already serves emit nothing,
|
|
13889
|
+
// the way a cold run's seeds do not.
|
|
13890
|
+
reused?.summaries ?? []
|
|
13361
13891
|
)
|
|
13362
13892
|
) : withSubUnits;
|
|
13893
|
+
const closureOwnership = caching && config.includeReachable !== false ? timer.time(
|
|
13894
|
+
"cache.attributeClosure",
|
|
13895
|
+
() => attributeReachedSummaries(
|
|
13896
|
+
withSubUnits,
|
|
13897
|
+
withClosure.slice(withSubUnits.length),
|
|
13898
|
+
closureFacts,
|
|
13899
|
+
ownersBySummary
|
|
13900
|
+
)
|
|
13901
|
+
) : null;
|
|
13902
|
+
const merged = timer.time(
|
|
13903
|
+
"cache.merge",
|
|
13904
|
+
() => mergeWithReused(reused, withClosure, ownersBySummary)
|
|
13905
|
+
);
|
|
13363
13906
|
const enriched = timer.time(
|
|
13364
13907
|
"enrichRethrows",
|
|
13365
|
-
() => enrichRethrows(
|
|
13908
|
+
() => enrichRethrows(merged.summaries, project, closureFacts)
|
|
13366
13909
|
);
|
|
13367
13910
|
if (config.includeReachable !== false) {
|
|
13368
13911
|
timer.time(
|
|
@@ -13378,6 +13921,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13378
13921
|
"emitLibraryEnvReadMarkers",
|
|
13379
13922
|
() => emitLibraryEnvReadMarkers(enriched, project, config.frameworks)
|
|
13380
13923
|
);
|
|
13924
|
+
timer.time(
|
|
13925
|
+
"liftSchemasOntoDocuments",
|
|
13926
|
+
() => liftSchemasOntoDocuments(enriched)
|
|
13927
|
+
);
|
|
13381
13928
|
timer.time(
|
|
13382
13929
|
"stampGraphqlClientRefs",
|
|
13383
13930
|
() => stampGraphqlClientRefs(
|
|
@@ -13387,12 +13934,45 @@ function createTypeScriptAdapter(config) {
|
|
|
13387
13934
|
resolution
|
|
13388
13935
|
)
|
|
13389
13936
|
);
|
|
13937
|
+
if (config.onCacheDiagnostic !== void 0 && plan !== null) {
|
|
13938
|
+
config.onCacheDiagnostic({
|
|
13939
|
+
kind: "partial",
|
|
13940
|
+
partial: {
|
|
13941
|
+
filesChanged: plan.changed.size,
|
|
13942
|
+
filesRemoved: plan.removed.size,
|
|
13943
|
+
rootsReused: validRoots.size,
|
|
13944
|
+
rootsReextracted: walkList.length,
|
|
13945
|
+
rootsDeclined: plan.rootsDeclined,
|
|
13946
|
+
summariesReused: merged.reusedKept.length
|
|
13947
|
+
}
|
|
13948
|
+
});
|
|
13949
|
+
}
|
|
13950
|
+
const runProjectRoot = commonDirectoryOf(
|
|
13951
|
+
sourceFiles.map((f) => f.getFilePath())
|
|
13952
|
+
);
|
|
13390
13953
|
await timer.timeAsync("cache.write", async () => {
|
|
13391
|
-
if (enriched.length === 0) {
|
|
13954
|
+
if (!caching || enriched.length === 0) {
|
|
13392
13955
|
return;
|
|
13393
13956
|
}
|
|
13394
13957
|
try {
|
|
13395
|
-
|
|
13958
|
+
const attribution = buildCacheAttribution({
|
|
13959
|
+
project,
|
|
13960
|
+
plan,
|
|
13961
|
+
validRoots,
|
|
13962
|
+
sinkByRoot,
|
|
13963
|
+
ownersBySummary,
|
|
13964
|
+
closureOwnership,
|
|
13965
|
+
unitKeyBySummary: closureFacts.unitKeyBySummary,
|
|
13966
|
+
filesByKey: closureFacts.filesByKey,
|
|
13967
|
+
packsByFile,
|
|
13968
|
+
reusedKept: merged.reusedKept,
|
|
13969
|
+
reusedOwners: merged.reusedOwners,
|
|
13970
|
+
// Everything after the reused prefix, the passes' own
|
|
13971
|
+
// additions (markers, schema documents) included.
|
|
13972
|
+
fresh: enriched.slice(merged.reusedKept.length),
|
|
13973
|
+
projectRoot: runProjectRoot
|
|
13974
|
+
});
|
|
13975
|
+
await cache.write(cacheInput, enriched, attribution);
|
|
13396
13976
|
} catch {
|
|
13397
13977
|
}
|
|
13398
13978
|
});
|
|
@@ -13405,7 +13985,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13405
13985
|
packs: config.frameworks,
|
|
13406
13986
|
tallies,
|
|
13407
13987
|
filesInProject: tsconfigFileList?.length ?? null,
|
|
13408
|
-
filesWalked:
|
|
13988
|
+
filesWalked: walkList.length,
|
|
13409
13989
|
summaries: enriched,
|
|
13410
13990
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
13411
13991
|
projectRoot: commonDirectoryOf(
|
|
@@ -13425,7 +14005,200 @@ function createTypeScriptAdapter(config) {
|
|
|
13425
14005
|
}
|
|
13426
14006
|
};
|
|
13427
14007
|
}
|
|
13428
|
-
function
|
|
14008
|
+
function mountAssumptionsAgree(record, index) {
|
|
14009
|
+
return Object.entries(record.mountPrefixes).every(
|
|
14010
|
+
([childId, prefix]) => (index.prefixForId?.(childId) ?? "") === prefix
|
|
14011
|
+
);
|
|
14012
|
+
}
|
|
14013
|
+
function attributeReachedSummaries(seeds, reached, facts, owners) {
|
|
14014
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
14015
|
+
for (const [from, to] of facts.db.facts("calls")) {
|
|
14016
|
+
const key = String(from);
|
|
14017
|
+
const bucket = adjacency.get(key) ?? [];
|
|
14018
|
+
bucket.push(String(to));
|
|
14019
|
+
adjacency.set(key, bucket);
|
|
14020
|
+
}
|
|
14021
|
+
const seedKeysByRoot = /* @__PURE__ */ new Map();
|
|
14022
|
+
for (const seed of seeds) {
|
|
14023
|
+
const key = facts.unitKeyBySummary.get(seed);
|
|
14024
|
+
if (key === void 0) {
|
|
14025
|
+
continue;
|
|
14026
|
+
}
|
|
14027
|
+
for (const root of owners.get(seed) ?? []) {
|
|
14028
|
+
const bucket = seedKeysByRoot.get(root) ?? [];
|
|
14029
|
+
bucket.push(key);
|
|
14030
|
+
seedKeysByRoot.set(root, bucket);
|
|
14031
|
+
}
|
|
14032
|
+
}
|
|
14033
|
+
const reachableByRoot = /* @__PURE__ */ new Map();
|
|
14034
|
+
const rootsByKey = /* @__PURE__ */ new Map();
|
|
14035
|
+
for (const [root, seedKeys] of seedKeysByRoot) {
|
|
14036
|
+
const seen = new Set(seedKeys);
|
|
14037
|
+
const queue = [...seedKeys];
|
|
14038
|
+
while (queue.length > 0) {
|
|
14039
|
+
const key = queue.pop();
|
|
14040
|
+
if (key === void 0) {
|
|
14041
|
+
continue;
|
|
14042
|
+
}
|
|
14043
|
+
for (const next of adjacency.get(key) ?? []) {
|
|
14044
|
+
if (!seen.has(next)) {
|
|
14045
|
+
seen.add(next);
|
|
14046
|
+
queue.push(next);
|
|
14047
|
+
}
|
|
14048
|
+
}
|
|
14049
|
+
const keyRoots = rootsByKey.get(key) ?? /* @__PURE__ */ new Set();
|
|
14050
|
+
keyRoots.add(root);
|
|
14051
|
+
rootsByKey.set(key, keyRoots);
|
|
14052
|
+
}
|
|
14053
|
+
reachableByRoot.set(root, seen);
|
|
14054
|
+
}
|
|
14055
|
+
for (const summary of reached) {
|
|
14056
|
+
const key = facts.unitKeyBySummary.get(summary);
|
|
14057
|
+
if (key === void 0) {
|
|
14058
|
+
continue;
|
|
14059
|
+
}
|
|
14060
|
+
const keyRoots = rootsByKey.get(key);
|
|
14061
|
+
if (keyRoots !== void 0 && keyRoots.size > 0) {
|
|
14062
|
+
owners.set(summary, new Set(keyRoots));
|
|
14063
|
+
}
|
|
14064
|
+
}
|
|
14065
|
+
return { reachableByRoot, rootsByKey };
|
|
14066
|
+
}
|
|
14067
|
+
function fileOfNodeKey(key) {
|
|
14068
|
+
const cut = key.lastIndexOf(":");
|
|
14069
|
+
return cut <= 0 ? null : key.slice(0, cut);
|
|
14070
|
+
}
|
|
14071
|
+
function summaryMergeKey(summary) {
|
|
14072
|
+
return JSON.stringify([
|
|
14073
|
+
summary.location.file,
|
|
14074
|
+
summary.location.range.start,
|
|
14075
|
+
summary.location.range.end,
|
|
14076
|
+
summary.kind,
|
|
14077
|
+
summary.identity.name,
|
|
14078
|
+
summary.identity.exportPath,
|
|
14079
|
+
summary.identity.boundaryBinding
|
|
14080
|
+
]);
|
|
14081
|
+
}
|
|
14082
|
+
function mergeWithReused(reused, fresh, ownersBySummary) {
|
|
14083
|
+
if (reused === null) {
|
|
14084
|
+
return { summaries: fresh, reusedKept: [], reusedOwners: [] };
|
|
14085
|
+
}
|
|
14086
|
+
const freshByKey = /* @__PURE__ */ new Map();
|
|
14087
|
+
for (const summary of fresh) {
|
|
14088
|
+
freshByKey.set(summaryMergeKey(summary), summary);
|
|
14089
|
+
}
|
|
14090
|
+
const reusedKept = [];
|
|
14091
|
+
const reusedOwners = [];
|
|
14092
|
+
reused.summaries.forEach((summary, i) => {
|
|
14093
|
+
const owners = reused.owners[i] ?? [];
|
|
14094
|
+
const supersededBy = freshByKey.get(summaryMergeKey(summary));
|
|
14095
|
+
if (supersededBy !== void 0) {
|
|
14096
|
+
const freshOwners = ownersBySummary.get(supersededBy) ?? /* @__PURE__ */ new Set();
|
|
14097
|
+
for (const owner of owners) {
|
|
14098
|
+
freshOwners.add(owner);
|
|
14099
|
+
}
|
|
14100
|
+
ownersBySummary.set(supersededBy, freshOwners);
|
|
14101
|
+
return;
|
|
14102
|
+
}
|
|
14103
|
+
reusedKept.push(summary);
|
|
14104
|
+
reusedOwners.push(owners);
|
|
14105
|
+
});
|
|
14106
|
+
return { summaries: [...reusedKept, ...fresh], reusedKept, reusedOwners };
|
|
14107
|
+
}
|
|
14108
|
+
function readsRunLevelJoins(summary) {
|
|
14109
|
+
if (readSourceDocumentMetadata(summary) !== void 0) {
|
|
14110
|
+
return true;
|
|
14111
|
+
}
|
|
14112
|
+
if (readGraphqlMetadata2(summary)?.client !== void 0) {
|
|
14113
|
+
return true;
|
|
14114
|
+
}
|
|
14115
|
+
const semantics = summary.identity.boundaryBinding?.semantics;
|
|
14116
|
+
return semantics !== void 0 && "operationType" in semantics;
|
|
14117
|
+
}
|
|
14118
|
+
function buildCacheAttribution(args) {
|
|
14119
|
+
const references = createReferenceIndex(
|
|
14120
|
+
args.project.getSourceFiles().filter((sf) => !sf.isDeclarationFile())
|
|
14121
|
+
);
|
|
14122
|
+
const packNamesByPath = /* @__PURE__ */ new Map();
|
|
14123
|
+
for (const [sf, packs] of args.packsByFile) {
|
|
14124
|
+
packNamesByPath.set(
|
|
14125
|
+
sf.getFilePath(),
|
|
14126
|
+
packs.map((p) => p.name)
|
|
14127
|
+
);
|
|
14128
|
+
}
|
|
14129
|
+
const summariesByRoot = /* @__PURE__ */ new Map();
|
|
14130
|
+
for (const summary of args.fresh) {
|
|
14131
|
+
for (const root of args.ownersBySummary.get(summary) ?? []) {
|
|
14132
|
+
const bucket = summariesByRoot.get(root) ?? [];
|
|
14133
|
+
bucket.push(summary);
|
|
14134
|
+
summariesByRoot.set(root, bucket);
|
|
14135
|
+
}
|
|
14136
|
+
}
|
|
14137
|
+
const roots = [];
|
|
14138
|
+
for (const [rootPath, sink] of args.sinkByRoot) {
|
|
14139
|
+
const deps = new Set(sink.files);
|
|
14140
|
+
for (const dep of references.directOf(rootPath)) {
|
|
14141
|
+
deps.add(dep);
|
|
14142
|
+
}
|
|
14143
|
+
let cacheable = true;
|
|
14144
|
+
for (const summary of summariesByRoot.get(rootPath) ?? []) {
|
|
14145
|
+
deps.add(summary.location.file);
|
|
14146
|
+
if (readsRunLevelJoins(summary)) {
|
|
14147
|
+
cacheable = false;
|
|
14148
|
+
}
|
|
14149
|
+
}
|
|
14150
|
+
const reachable = args.closureOwnership?.reachableByRoot.get(rootPath) ?? [];
|
|
14151
|
+
for (const key of reachable) {
|
|
14152
|
+
const keyFile = fileOfNodeKey(key);
|
|
14153
|
+
if (keyFile !== null) {
|
|
14154
|
+
deps.add(keyFile);
|
|
14155
|
+
for (const hop of references.directOf(keyFile)) {
|
|
14156
|
+
deps.add(hop);
|
|
14157
|
+
}
|
|
14158
|
+
}
|
|
14159
|
+
for (const filePath of args.filesByKey?.get(key) ?? []) {
|
|
14160
|
+
deps.add(filePath);
|
|
14161
|
+
}
|
|
14162
|
+
}
|
|
14163
|
+
deps.delete(rootPath);
|
|
14164
|
+
roots.push({
|
|
14165
|
+
path: rootPath,
|
|
14166
|
+
cacheable,
|
|
14167
|
+
deps: [...deps].sort(),
|
|
14168
|
+
claims: sink.claims,
|
|
14169
|
+
mountPrefixes: Object.fromEntries(sink.mountPrefixes),
|
|
14170
|
+
packs: packNamesByPath.get(rootPath) ?? []
|
|
14171
|
+
});
|
|
14172
|
+
}
|
|
14173
|
+
if (args.plan !== null) {
|
|
14174
|
+
for (const rootPath of args.validRoots) {
|
|
14175
|
+
const record = args.plan.roots.get(rootPath);
|
|
14176
|
+
if (record !== void 0) {
|
|
14177
|
+
roots.push(record);
|
|
14178
|
+
}
|
|
14179
|
+
}
|
|
14180
|
+
}
|
|
14181
|
+
const reusedOwners = args.reusedKept.map((summary, i) => {
|
|
14182
|
+
const combined = new Set(args.reusedOwners[i] ?? []);
|
|
14183
|
+
const key = args.unitKeyBySummary.get(summary);
|
|
14184
|
+
if (key !== void 0) {
|
|
14185
|
+
for (const root of args.closureOwnership?.rootsByKey.get(key) ?? []) {
|
|
14186
|
+
combined.add(root);
|
|
14187
|
+
}
|
|
14188
|
+
}
|
|
14189
|
+
return [...combined];
|
|
14190
|
+
});
|
|
14191
|
+
const owners = [
|
|
14192
|
+
...reusedOwners,
|
|
14193
|
+
...args.fresh.map((s) => [...args.ownersBySummary.get(s) ?? []])
|
|
14194
|
+
];
|
|
14195
|
+
return {
|
|
14196
|
+
roots,
|
|
14197
|
+
owners,
|
|
14198
|
+
...args.projectRoot === void 0 ? {} : { projectRoot: args.projectRoot }
|
|
14199
|
+
};
|
|
14200
|
+
}
|
|
14201
|
+
function synthesizeSubUnits(summaries, project, frameworks, options, tallies, onCreated) {
|
|
13429
14202
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
13430
14203
|
for (const pack of frameworks) {
|
|
13431
14204
|
packByRecognition.set(pack.name, pack);
|
|
@@ -13468,6 +14241,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13468
14241
|
);
|
|
13469
14242
|
if (summary !== null) {
|
|
13470
14243
|
synthesized.push(summary);
|
|
14244
|
+
onCreated?.(summary, parent);
|
|
13471
14245
|
}
|
|
13472
14246
|
}
|
|
13473
14247
|
}
|
|
@@ -13476,14 +14250,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13476
14250
|
var DEFAULT_SUB_UNIT_TERMINALS = [
|
|
13477
14251
|
{ kind: "return", match: { type: "returnStatement" }, extraction: {} },
|
|
13478
14252
|
{ 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
|
-
}
|
|
14253
|
+
FUNCTION_FALLTHROUGH_TERMINAL
|
|
13487
14254
|
];
|
|
13488
14255
|
var DEFAULT_SUB_UNIT_INPUT_MAPPING = {
|
|
13489
14256
|
type: "positionalParams",
|
|
@@ -13795,6 +14562,7 @@ function formatPackHealth(checks, audiences) {
|
|
|
13795
14562
|
|
|
13796
14563
|
// src/resolve/readName.ts
|
|
13797
14564
|
import { Node as Node56, SyntaxKind as SyntaxKind12 } from "ts-morph";
|
|
14565
|
+
import { patternHole, referenceName } from "@suss/behavioral-ir";
|
|
13798
14566
|
var MAX_HELPER_HOPS = 2;
|
|
13799
14567
|
var UNNAMED_HOLE = "param";
|
|
13800
14568
|
function readName(expr, options = {}) {
|
|
@@ -13808,6 +14576,14 @@ function readName(expr, options = {}) {
|
|
|
13808
14576
|
if (name !== null || options.unsettled !== "reference") {
|
|
13809
14577
|
return name;
|
|
13810
14578
|
}
|
|
14579
|
+
const reference = referenceIn(expr);
|
|
14580
|
+
return reference === null ? null : referenceName(reference);
|
|
14581
|
+
}
|
|
14582
|
+
function referenceIn(expr) {
|
|
14583
|
+
const fromParameter = parameterPath(expr);
|
|
14584
|
+
if (fromParameter !== null) {
|
|
14585
|
+
return fromParameter;
|
|
14586
|
+
}
|
|
13811
14587
|
const asked = holeName(expr, {
|
|
13812
14588
|
resolve: () => null,
|
|
13813
14589
|
bindings: /* @__PURE__ */ new Map(),
|
|
@@ -13815,7 +14591,25 @@ function readName(expr, options = {}) {
|
|
|
13815
14591
|
seen: /* @__PURE__ */ new Set(),
|
|
13816
14592
|
insideHole: true
|
|
13817
14593
|
});
|
|
13818
|
-
return asked === UNNAMED_HOLE ? null :
|
|
14594
|
+
return asked === UNNAMED_HOLE ? null : { root: asked, fields: [] };
|
|
14595
|
+
}
|
|
14596
|
+
function parameterPath(expr) {
|
|
14597
|
+
const fields = [];
|
|
14598
|
+
let step = expr;
|
|
14599
|
+
while (Node56.isPropertyAccessExpression(step)) {
|
|
14600
|
+
fields.unshift(step.getName());
|
|
14601
|
+
step = step.getExpression();
|
|
14602
|
+
}
|
|
14603
|
+
if (!Node56.isIdentifier(step) || !isParameter(step)) {
|
|
14604
|
+
return null;
|
|
14605
|
+
}
|
|
14606
|
+
return { root: step.getText(), fields };
|
|
14607
|
+
}
|
|
14608
|
+
function isParameter(identifier) {
|
|
14609
|
+
const declarations = identifier.getSymbol()?.getDeclarations() ?? [];
|
|
14610
|
+
return declarations.some(
|
|
14611
|
+
(declaration) => Node56.isParameterDeclaration(declaration)
|
|
14612
|
+
);
|
|
13819
14613
|
}
|
|
13820
14614
|
function read(expr, ctx) {
|
|
13821
14615
|
if (ctx.seen.has(expr)) {
|
|
@@ -14012,7 +14806,7 @@ function boundOnce(expr, ctx) {
|
|
|
14012
14806
|
}
|
|
14013
14807
|
function readOrHole(expr, ctx) {
|
|
14014
14808
|
const name = read(expr, ctx);
|
|
14015
|
-
return name ??
|
|
14809
|
+
return name ?? patternHole(holeName(expr, ctx));
|
|
14016
14810
|
}
|
|
14017
14811
|
function holeName(expr, ctx) {
|
|
14018
14812
|
const bound = boundOnce(expr, ctx);
|