@suss/adapter-typescript 0.8.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 +1258 -350
- package/dist/index.d.cts +44 -10
- package/dist/index.d.ts +44 -10
- package/dist/index.js +1252 -335
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// src/adapter.ts
|
|
2
2
|
import path9 from "path";
|
|
3
3
|
import {
|
|
4
|
-
Node as
|
|
5
|
-
Project
|
|
4
|
+
Node as Node54,
|
|
5
|
+
Project,
|
|
6
|
+
SyntaxKind as SyntaxKind11
|
|
6
7
|
} from "ts-morph";
|
|
7
8
|
import {
|
|
8
9
|
functionCallBinding as functionCallBinding2,
|
|
@@ -10,7 +11,11 @@ import {
|
|
|
10
11
|
graphqlResolverBinding,
|
|
11
12
|
messageBusBinding,
|
|
12
13
|
packageExportBinding,
|
|
13
|
-
|
|
14
|
+
readGraphqlMetadata as readGraphqlMetadata2,
|
|
15
|
+
readSourceDocumentMetadata,
|
|
16
|
+
restBinding as restBinding2,
|
|
17
|
+
withGraphqlMetadata as withGraphqlMetadata2,
|
|
18
|
+
withSourceDocumentMetadata
|
|
14
19
|
} from "@suss/behavioral-ir";
|
|
15
20
|
import { Database as Database5 } from "@suss/datalog";
|
|
16
21
|
import {
|
|
@@ -1029,32 +1034,72 @@ function collectFallthroughCaseLabels(caseClause) {
|
|
|
1029
1034
|
}
|
|
1030
1035
|
|
|
1031
1036
|
// src/paths/pathConditions.ts
|
|
1032
|
-
import { Node as
|
|
1037
|
+
import { Node as Node9 } from "ts-morph";
|
|
1033
1038
|
import {
|
|
1034
1039
|
enumerateStructuredPaths,
|
|
1035
1040
|
PathBudgetExceeded,
|
|
1036
1041
|
UnmodeledFlow as UnmodeledFlow2
|
|
1037
1042
|
} from "@suss/extractor";
|
|
1038
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
|
+
|
|
1039
1085
|
// src/paths/lowering.ts
|
|
1040
1086
|
import {
|
|
1041
|
-
Node as
|
|
1087
|
+
Node as Node8
|
|
1042
1088
|
} from "ts-morph";
|
|
1043
1089
|
import {
|
|
1044
1090
|
UnmodeledFlow
|
|
1045
1091
|
} from "@suss/extractor";
|
|
1046
|
-
var isFunctionBoundary = (node) => Node7.isFunctionDeclaration(node) || Node7.isFunctionExpression(node) || Node7.isArrowFunction(node) || Node7.isMethodDeclaration(node);
|
|
1047
1092
|
function exitKindOf(stmt) {
|
|
1048
1093
|
let sawReturn = false;
|
|
1049
1094
|
let sawThrow = false;
|
|
1050
1095
|
const visit = (node) => {
|
|
1051
|
-
if (node !== stmt &&
|
|
1096
|
+
if (node !== stmt && startsItsOwnScope(node)) {
|
|
1052
1097
|
return;
|
|
1053
1098
|
}
|
|
1054
|
-
if (
|
|
1099
|
+
if (Node8.isReturnStatement(node)) {
|
|
1055
1100
|
sawReturn = true;
|
|
1056
1101
|
}
|
|
1057
|
-
if (
|
|
1102
|
+
if (Node8.isThrowStatement(node)) {
|
|
1058
1103
|
sawThrow = true;
|
|
1059
1104
|
}
|
|
1060
1105
|
for (const child of node.getChildren()) {
|
|
@@ -1071,14 +1116,14 @@ var statementsOf = (stmt) => {
|
|
|
1071
1116
|
if (stmt === void 0) {
|
|
1072
1117
|
return [];
|
|
1073
1118
|
}
|
|
1074
|
-
if (
|
|
1119
|
+
if (Node8.isBlock(stmt)) {
|
|
1075
1120
|
return stmt.getStatements();
|
|
1076
1121
|
}
|
|
1077
1122
|
return [stmt];
|
|
1078
1123
|
};
|
|
1079
|
-
var isLoop = (stmt) =>
|
|
1124
|
+
var isLoop = (stmt) => Node8.isForOfStatement(stmt) || Node8.isForInStatement(stmt) || Node8.isForStatement(stmt) || Node8.isWhileStatement(stmt) || Node8.isDoStatement(stmt);
|
|
1080
1125
|
function getLoopBody(stmt) {
|
|
1081
|
-
if (
|
|
1126
|
+
if (Node8.isForOfStatement(stmt) || Node8.isForInStatement(stmt) || Node8.isForStatement(stmt) || Node8.isWhileStatement(stmt) || Node8.isDoStatement(stmt)) {
|
|
1082
1127
|
return stmt.getStatement();
|
|
1083
1128
|
}
|
|
1084
1129
|
return void 0;
|
|
@@ -1093,37 +1138,97 @@ var conditionOf = (expr) => ({
|
|
|
1093
1138
|
sourceText: expr.getText(),
|
|
1094
1139
|
expression: expr
|
|
1095
1140
|
});
|
|
1096
|
-
function lowerStatement(stmt,
|
|
1097
|
-
const structured =
|
|
1098
|
-
|
|
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);
|
|
1099
1147
|
return structured;
|
|
1100
1148
|
}
|
|
1101
|
-
function lowerList(stmts,
|
|
1102
|
-
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
|
+
});
|
|
1103
1211
|
}
|
|
1104
1212
|
function spliceBlocks(stmts) {
|
|
1105
1213
|
return stmts.flatMap(
|
|
1106
|
-
(s) =>
|
|
1214
|
+
(s) => Node8.isBlock(s) ? spliceBlocks(s.getStatements()) : [s]
|
|
1107
1215
|
);
|
|
1108
1216
|
}
|
|
1109
|
-
function buildStructured(stmt,
|
|
1110
|
-
if (
|
|
1217
|
+
function buildStructured(stmt, ctx) {
|
|
1218
|
+
if (Node8.isIfStatement(stmt)) {
|
|
1111
1219
|
const elseBranch = stmt.getElseStatement();
|
|
1112
1220
|
return {
|
|
1113
1221
|
kind: "if",
|
|
1114
1222
|
condition: conditionOf(stmt.getExpression()),
|
|
1115
|
-
thenBody: lowerList(
|
|
1116
|
-
|
|
1117
|
-
rawToStructured
|
|
1118
|
-
),
|
|
1119
|
-
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),
|
|
1120
1225
|
exitKind: exitKindOf(stmt)
|
|
1121
1226
|
};
|
|
1122
1227
|
}
|
|
1123
|
-
if (
|
|
1228
|
+
if (Node8.isSwitchStatement(stmt)) {
|
|
1124
1229
|
return {
|
|
1125
1230
|
kind: "switch",
|
|
1126
|
-
groups: lowerSwitchGroups(stmt,
|
|
1231
|
+
groups: lowerSwitchGroups(stmt, ctx),
|
|
1127
1232
|
exitKind: exitKindOf(stmt)
|
|
1128
1233
|
};
|
|
1129
1234
|
}
|
|
@@ -1131,36 +1236,36 @@ function buildStructured(stmt, rawToStructured) {
|
|
|
1131
1236
|
return {
|
|
1132
1237
|
kind: "loop",
|
|
1133
1238
|
condition: { sourceText: loopHeaderText(stmt), expression: null },
|
|
1134
|
-
body: lowerList(statementsOf(getLoopBody(stmt)),
|
|
1239
|
+
body: lowerList(statementsOf(getLoopBody(stmt)), ctx),
|
|
1135
1240
|
exitKind: exitKindOf(stmt)
|
|
1136
1241
|
};
|
|
1137
1242
|
}
|
|
1138
|
-
if (
|
|
1243
|
+
if (Node8.isTryStatement(stmt)) {
|
|
1139
1244
|
const catchClause = stmt.getCatchClause();
|
|
1140
1245
|
const finallyBlock = stmt.getFinallyBlock();
|
|
1141
1246
|
return {
|
|
1142
1247
|
kind: "try",
|
|
1143
|
-
tryBody: lowerList(stmt.getTryBlock().getStatements(),
|
|
1144
|
-
catchBody: catchClause === void 0 ? null : lowerList(catchClause.getBlock().getStatements(),
|
|
1145
|
-
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),
|
|
1146
1251
|
exitKind: exitKindOf(stmt)
|
|
1147
1252
|
};
|
|
1148
1253
|
}
|
|
1149
|
-
if (
|
|
1254
|
+
if (Node8.isReturnStatement(stmt)) {
|
|
1150
1255
|
return { kind: "exit", exit: "return", exitKind: exitKindOf(stmt) };
|
|
1151
1256
|
}
|
|
1152
|
-
if (
|
|
1257
|
+
if (Node8.isThrowStatement(stmt)) {
|
|
1153
1258
|
return { kind: "exit", exit: "throw", exitKind: exitKindOf(stmt) };
|
|
1154
1259
|
}
|
|
1155
|
-
if (
|
|
1260
|
+
if (Node8.isBreakStatement(stmt)) {
|
|
1156
1261
|
return { kind: "exit", exit: "break", exitKind: exitKindOf(stmt) };
|
|
1157
1262
|
}
|
|
1158
|
-
if (
|
|
1263
|
+
if (Node8.isContinueStatement(stmt)) {
|
|
1159
1264
|
return { kind: "exit", exit: "continue", exitKind: exitKindOf(stmt) };
|
|
1160
1265
|
}
|
|
1161
1266
|
return { kind: "opaque", exitKind: exitKindOf(stmt) };
|
|
1162
1267
|
}
|
|
1163
|
-
function lowerSwitchGroups(stmt,
|
|
1268
|
+
function lowerSwitchGroups(stmt, ctx) {
|
|
1164
1269
|
const switchText = stmt.getExpression().getText();
|
|
1165
1270
|
const groups = [];
|
|
1166
1271
|
let pendingLabels = [];
|
|
@@ -1169,7 +1274,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1169
1274
|
if (sawDefault) {
|
|
1170
1275
|
throw new UnmodeledFlow("default clause is not last");
|
|
1171
1276
|
}
|
|
1172
|
-
if (
|
|
1277
|
+
if (Node8.isDefaultClause(clause)) {
|
|
1173
1278
|
sawDefault = true;
|
|
1174
1279
|
const stmts2 = clause.getStatements();
|
|
1175
1280
|
if (stmts2.length === 0) {
|
|
@@ -1177,11 +1282,11 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1177
1282
|
}
|
|
1178
1283
|
groups.push({
|
|
1179
1284
|
condition: null,
|
|
1180
|
-
...lowerGroupBody(stmts2,
|
|
1285
|
+
...lowerGroupBody(stmts2, ctx)
|
|
1181
1286
|
});
|
|
1182
1287
|
continue;
|
|
1183
1288
|
}
|
|
1184
|
-
if (!
|
|
1289
|
+
if (!Node8.isCaseClause(clause)) {
|
|
1185
1290
|
continue;
|
|
1186
1291
|
}
|
|
1187
1292
|
pendingLabels.push(clause.getExpression().getText());
|
|
@@ -1194,7 +1299,7 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1194
1299
|
const sourceText = labels.map((l) => `${switchText} === ${l}`).join(" || ");
|
|
1195
1300
|
groups.push({
|
|
1196
1301
|
condition: { sourceText, expression: null },
|
|
1197
|
-
...lowerGroupBody(stmts,
|
|
1302
|
+
...lowerGroupBody(stmts, ctx)
|
|
1198
1303
|
});
|
|
1199
1304
|
}
|
|
1200
1305
|
return groups;
|
|
@@ -1202,41 +1307,42 @@ function lowerSwitchGroups(stmt, rawToStructured) {
|
|
|
1202
1307
|
function validateClauseBreaks(stmts) {
|
|
1203
1308
|
const last = stmts[stmts.length - 1];
|
|
1204
1309
|
for (const stmt of stmts) {
|
|
1205
|
-
if (stmt === last &&
|
|
1310
|
+
if (stmt === last && Node8.isBreakStatement(stmt)) {
|
|
1206
1311
|
continue;
|
|
1207
1312
|
}
|
|
1208
|
-
if (
|
|
1313
|
+
if (Node8.isSwitchStatement(stmt) || isLoop(stmt)) {
|
|
1209
1314
|
continue;
|
|
1210
1315
|
}
|
|
1211
1316
|
stmt.forEachDescendant((node, traversal) => {
|
|
1212
|
-
if (
|
|
1317
|
+
if (startsItsOwnScope(node) || Node8.isSwitchStatement(node) || isLoop(node)) {
|
|
1213
1318
|
traversal.skip();
|
|
1214
1319
|
return;
|
|
1215
1320
|
}
|
|
1216
|
-
if (
|
|
1321
|
+
if (Node8.isBreakStatement(node)) {
|
|
1217
1322
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
1218
1323
|
}
|
|
1219
1324
|
});
|
|
1220
|
-
if (
|
|
1325
|
+
if (Node8.isBreakStatement(stmt)) {
|
|
1221
1326
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
1222
1327
|
}
|
|
1223
1328
|
}
|
|
1224
1329
|
}
|
|
1225
|
-
function lowerGroupBody(rawStmts,
|
|
1330
|
+
function lowerGroupBody(rawStmts, ctx) {
|
|
1226
1331
|
const stmts = spliceBlocks(rawStmts);
|
|
1227
1332
|
validateClauseBreaks(stmts);
|
|
1228
1333
|
const last = stmts[stmts.length - 1];
|
|
1229
|
-
const hasTrailingBreak = last !== void 0 &&
|
|
1334
|
+
const hasTrailingBreak = last !== void 0 && Node8.isBreakStatement(last);
|
|
1230
1335
|
const kept = hasTrailingBreak ? stmts.slice(0, -1) : stmts;
|
|
1231
|
-
const body = lowerList(kept,
|
|
1336
|
+
const body = lowerList(kept, ctx);
|
|
1232
1337
|
if (hasTrailingBreak && last !== void 0) {
|
|
1233
|
-
lowerStatement(last,
|
|
1338
|
+
lowerStatement(last, ctx);
|
|
1234
1339
|
}
|
|
1235
1340
|
return { hasTrailingBreak, body };
|
|
1236
1341
|
}
|
|
1237
|
-
function lowerFunctionBody(body, terminalNodes) {
|
|
1342
|
+
function lowerFunctionBody(body, terminalNodes, func = body, barriers = NO_BARRIERS) {
|
|
1238
1343
|
const rawToStructured = /* @__PURE__ */ new Map();
|
|
1239
|
-
const
|
|
1344
|
+
const ctx = { func, barriers, rawToStructured };
|
|
1345
|
+
const statements = lowerList(body.getStatements(), ctx);
|
|
1240
1346
|
const terminalsByStmt = /* @__PURE__ */ new Map();
|
|
1241
1347
|
const terminalHomeRaw = /* @__PURE__ */ new Map();
|
|
1242
1348
|
for (const terminal of terminalNodes) {
|
|
@@ -1258,7 +1364,7 @@ function lowerFunctionBody(body, terminalNodes) {
|
|
|
1258
1364
|
function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
1259
1365
|
let current2 = terminal;
|
|
1260
1366
|
while (current2 !== void 0 && current2 !== body) {
|
|
1261
|
-
if (
|
|
1367
|
+
if (Node8.isStatement(current2) && rawToStructured.has(current2)) {
|
|
1262
1368
|
return current2;
|
|
1263
1369
|
}
|
|
1264
1370
|
current2 = current2.getParent();
|
|
@@ -1267,39 +1373,42 @@ function enclosingLoweredStatement(terminal, body, rawToStructured) {
|
|
|
1267
1373
|
}
|
|
1268
1374
|
|
|
1269
1375
|
// src/paths/pathConditions.ts
|
|
1270
|
-
function containsUnmodeledFlow(body) {
|
|
1376
|
+
function containsUnmodeledFlow(body, func, barriers) {
|
|
1271
1377
|
let found = false;
|
|
1272
1378
|
body.forEachDescendant((node, traversal) => {
|
|
1273
|
-
if (
|
|
1379
|
+
if (isDescentStop(node, func, barriers)) {
|
|
1274
1380
|
traversal.skip();
|
|
1275
1381
|
return;
|
|
1276
1382
|
}
|
|
1277
|
-
if (
|
|
1383
|
+
if (Node9.isLabeledStatement(node)) {
|
|
1278
1384
|
found = true;
|
|
1279
1385
|
traversal.stop();
|
|
1280
1386
|
}
|
|
1281
1387
|
});
|
|
1282
1388
|
return found;
|
|
1283
1389
|
}
|
|
1284
|
-
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) {
|
|
1285
1403
|
const body = func.getBody();
|
|
1286
1404
|
if (body === void 0) {
|
|
1287
1405
|
return { byTerminal: /* @__PURE__ */ new Map(), fallthrough: [] };
|
|
1288
1406
|
}
|
|
1289
|
-
if (
|
|
1290
|
-
const byTerminal = /* @__PURE__ */ new Map();
|
|
1291
|
-
for (const terminal of terminalNodes) {
|
|
1292
|
-
byTerminal.set(terminal, [
|
|
1293
|
-
collectAncestorConditionInfosBelow(terminal, func)
|
|
1294
|
-
]);
|
|
1295
|
-
}
|
|
1296
|
-
return { byTerminal, fallthrough: [] };
|
|
1297
|
-
}
|
|
1298
|
-
if (containsUnmodeledFlow(body)) {
|
|
1407
|
+
if (containsUnmodeledFlow(body, func, barriers)) {
|
|
1299
1408
|
return degradedResult(func, terminalNodes, "labeled statement");
|
|
1300
1409
|
}
|
|
1301
1410
|
try {
|
|
1302
|
-
const lowered = lowerFunctionBody(body, terminalNodes);
|
|
1411
|
+
const lowered = Node9.isBlock(body) ? lowerFunctionBody(body, terminalNodes, func, barriers) : loweredExpressionBody(body, terminalNodes, func, barriers);
|
|
1303
1412
|
const result = enumerateStructuredPaths({
|
|
1304
1413
|
statements: lowered.statements,
|
|
1305
1414
|
terminalsByStmt: lowered.terminalsByStmt
|
|
@@ -1366,7 +1475,7 @@ function lineAt(node, pos) {
|
|
|
1366
1475
|
}
|
|
1367
1476
|
|
|
1368
1477
|
// src/moduleExports.ts
|
|
1369
|
-
import { Node as
|
|
1478
|
+
import { Node as Node10 } from "ts-morph";
|
|
1370
1479
|
|
|
1371
1480
|
// src/bootstrap/lazyProjectInit.ts
|
|
1372
1481
|
import fs from "fs/promises";
|
|
@@ -1945,6 +2054,30 @@ async function readImportsConcurrently(paths) {
|
|
|
1945
2054
|
return results;
|
|
1946
2055
|
}
|
|
1947
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
|
+
|
|
1948
2081
|
// src/perFileCache.ts
|
|
1949
2082
|
function createPerFileCache() {
|
|
1950
2083
|
const byParse = /* @__PURE__ */ new WeakMap();
|
|
@@ -1960,6 +2093,7 @@ function createPerFileCache() {
|
|
|
1960
2093
|
|
|
1961
2094
|
// src/moduleExports.ts
|
|
1962
2095
|
function exportedDeclarationsOf(sourceFile) {
|
|
2096
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
1963
2097
|
const cached = exportsByFile.get(sourceFile);
|
|
1964
2098
|
if (cached !== void 0) {
|
|
1965
2099
|
return cached;
|
|
@@ -1974,7 +2108,14 @@ function resolveAliasedSymbol(symbol) {
|
|
|
1974
2108
|
warmReExportChains(declaration.getSourceFile(), "every import");
|
|
1975
2109
|
}
|
|
1976
2110
|
try {
|
|
1977
|
-
|
|
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;
|
|
1978
2119
|
} catch (error) {
|
|
1979
2120
|
if (!(error instanceof RangeError)) {
|
|
1980
2121
|
throw error;
|
|
@@ -2089,7 +2230,7 @@ function reExportShapeOf(file, reach) {
|
|
|
2089
2230
|
for (const assignment of file.getExportAssignments()) {
|
|
2090
2231
|
exportNodes.push(assignment);
|
|
2091
2232
|
const expression = assignment.getExpression();
|
|
2092
|
-
if (
|
|
2233
|
+
if (Node10.isIdentifier(expression)) {
|
|
2093
2234
|
localNames.add(expression.getText());
|
|
2094
2235
|
}
|
|
2095
2236
|
}
|
|
@@ -2165,38 +2306,6 @@ function reportUnreadableExports(file) {
|
|
|
2165
2306
|
);
|
|
2166
2307
|
}
|
|
2167
2308
|
|
|
2168
|
-
// src/walk/descent.ts
|
|
2169
|
-
import { Node as Node10 } from "ts-morph";
|
|
2170
|
-
var NO_BARRIERS = /* @__PURE__ */ new Set();
|
|
2171
|
-
function isDescentStop(node, func, barriers = NO_BARRIERS) {
|
|
2172
|
-
if (node === func) {
|
|
2173
|
-
return false;
|
|
2174
|
-
}
|
|
2175
|
-
if (Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node)) {
|
|
2176
|
-
return true;
|
|
2177
|
-
}
|
|
2178
|
-
if (Node10.isArrowFunction(node) || Node10.isFunctionExpression(node)) {
|
|
2179
|
-
return barriers.has(node);
|
|
2180
|
-
}
|
|
2181
|
-
return false;
|
|
2182
|
-
}
|
|
2183
|
-
function isModuleScopeStop(node) {
|
|
2184
|
-
return Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node) || Node10.isArrowFunction(node) || Node10.isFunctionExpression(node) || Node10.isClassDeclaration(node) || Node10.isClassExpression(node);
|
|
2185
|
-
}
|
|
2186
|
-
function crossesNestedFunctionScope(node, func) {
|
|
2187
|
-
let current2 = node;
|
|
2188
|
-
while (current2 !== void 0 && current2 !== func) {
|
|
2189
|
-
if (startsItsOwnScope(current2)) {
|
|
2190
|
-
return true;
|
|
2191
|
-
}
|
|
2192
|
-
current2 = current2.getParent();
|
|
2193
|
-
}
|
|
2194
|
-
return false;
|
|
2195
|
-
}
|
|
2196
|
-
function startsItsOwnScope(node) {
|
|
2197
|
-
return Node10.isArrowFunction(node) || Node10.isFunctionExpression(node) || Node10.isFunctionDeclaration(node) || Node10.isMethodDeclaration(node) || Node10.isGetAccessorDeclaration(node) || Node10.isSetAccessorDeclaration(node) || Node10.isConstructorDeclaration(node);
|
|
2198
|
-
}
|
|
2199
|
-
|
|
2200
2309
|
// src/resolve/invocationEffects.ts
|
|
2201
2310
|
function isImportedFrom(identifier, expectedModule) {
|
|
2202
2311
|
if (!Node11.isIdentifier(identifier)) {
|
|
@@ -4908,7 +5017,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4908
5017
|
];
|
|
4909
5018
|
const { byTerminal } = computePathConditions(
|
|
4910
5019
|
func,
|
|
4911
|
-
terminals.map(({ node }) => node)
|
|
5020
|
+
terminals.map(({ node }) => node),
|
|
5021
|
+
barriers
|
|
4912
5022
|
);
|
|
4913
5023
|
const wantsFallthrough = terminalPatterns.some(
|
|
4914
5024
|
(p) => p.match.type === "functionFallthrough"
|
|
@@ -4920,7 +5030,11 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
4920
5030
|
if (!hasDefaultTerminal) {
|
|
4921
5031
|
const synthetic = makeFallthroughTerminal(func);
|
|
4922
5032
|
terminals.push(synthetic);
|
|
4923
|
-
const pathResult = computePathConditions(
|
|
5033
|
+
const pathResult = computePathConditions(
|
|
5034
|
+
func,
|
|
5035
|
+
[synthetic.node],
|
|
5036
|
+
barriers
|
|
5037
|
+
);
|
|
4924
5038
|
byTerminal.set(
|
|
4925
5039
|
synthetic.node,
|
|
4926
5040
|
pathResult.fallthrough.length > 0 ? pathResult.fallthrough : [[]]
|
|
@@ -5051,7 +5165,7 @@ function indexFunctions(sf) {
|
|
|
5051
5165
|
import { createHash as createHash2 } from "crypto";
|
|
5052
5166
|
import fs2 from "fs/promises";
|
|
5053
5167
|
import path2 from "path";
|
|
5054
|
-
var SCHEMA_VERSION = "
|
|
5168
|
+
var SCHEMA_VERSION = "6";
|
|
5055
5169
|
var MAX_ENTRIES = 2;
|
|
5056
5170
|
var ENTRY_PREFIX = "key-";
|
|
5057
5171
|
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
@@ -5063,6 +5177,7 @@ function createCacheLayer(cacheDir) {
|
|
|
5063
5177
|
kind: "miss",
|
|
5064
5178
|
diagnostic: { kind: "miss", missReason: "no-manifest" }
|
|
5065
5179
|
}),
|
|
5180
|
+
plan: async () => null,
|
|
5066
5181
|
write: async () => {
|
|
5067
5182
|
}
|
|
5068
5183
|
};
|
|
@@ -5090,20 +5205,36 @@ function createCacheLayer(cacheDir) {
|
|
|
5090
5205
|
return {
|
|
5091
5206
|
kind: "hit",
|
|
5092
5207
|
summaries: manifest.summaries,
|
|
5208
|
+
...manifest.projectRoot === void 0 ? {} : { projectRoot: manifest.projectRoot },
|
|
5093
5209
|
diagnostic: { kind: "hit" }
|
|
5094
5210
|
};
|
|
5095
5211
|
},
|
|
5096
|
-
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"));
|
|
5097
5228
|
const tsconfigStamp = await stampTsconfig(input.tsconfigPath);
|
|
5098
|
-
const files = await resolveFileStamps(input);
|
|
5229
|
+
const files = await hashStamps(await resolveFileStamps(input), previous);
|
|
5099
5230
|
const manifest = {
|
|
5100
5231
|
schemaVersion: SCHEMA_VERSION,
|
|
5101
5232
|
adapterPacksDigest: input.adapterPacksDigest,
|
|
5102
5233
|
tsconfigStamp,
|
|
5103
5234
|
files,
|
|
5104
|
-
summaries
|
|
5235
|
+
summaries,
|
|
5236
|
+
...attribution === void 0 ? {} : encodeAttribution(attribution)
|
|
5105
5237
|
};
|
|
5106
|
-
const entryDir = entryDirFor(cacheDir, input);
|
|
5107
5238
|
await fs2.mkdir(entryDir, { recursive: true });
|
|
5108
5239
|
await fs2.writeFile(
|
|
5109
5240
|
path2.join(entryDir, "manifest.json"),
|
|
@@ -5113,6 +5244,171 @@ function createCacheLayer(cacheDir) {
|
|
|
5113
5244
|
}
|
|
5114
5245
|
};
|
|
5115
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
|
+
}
|
|
5116
5412
|
async function describeAbsentEntry(cacheDir) {
|
|
5117
5413
|
try {
|
|
5118
5414
|
const entries = await fs2.readdir(cacheDir, { withFileTypes: true });
|
|
@@ -5126,7 +5422,7 @@ function entryDirFor(cacheDir, input) {
|
|
|
5126
5422
|
SCHEMA_VERSION,
|
|
5127
5423
|
input.adapterPacksDigest,
|
|
5128
5424
|
input.tsconfigPath ?? ""
|
|
5129
|
-
].join("
|
|
5425
|
+
].join(" ");
|
|
5130
5426
|
const name = createHash2("sha256").update(key).digest("hex").slice(0, 16);
|
|
5131
5427
|
return path2.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
5132
5428
|
}
|
|
@@ -6985,7 +7281,7 @@ function calleeOf(decorator) {
|
|
|
6985
7281
|
|
|
6986
7282
|
// src/discovery/decoratedMethod.ts
|
|
6987
7283
|
function resolverTypeName(args) {
|
|
6988
|
-
return args.
|
|
7284
|
+
return args.typeMap[args.decoratorName] ?? args.classTypeName ?? null;
|
|
6989
7285
|
}
|
|
6990
7286
|
function resolveResolverClassTypeName(decoratorArg) {
|
|
6991
7287
|
if (Node32.isArrowFunction(decoratorArg)) {
|
|
@@ -9549,7 +9845,10 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
|
|
|
9549
9845
|
resolverInfo: {
|
|
9550
9846
|
typeName,
|
|
9551
9847
|
fieldName,
|
|
9552
|
-
...schemaSdl !== null ? {
|
|
9848
|
+
...schemaSdl !== null ? {
|
|
9849
|
+
schemaSdl,
|
|
9850
|
+
schemaDocument: config.getSourceFile().getFilePath()
|
|
9851
|
+
} : {}
|
|
9553
9852
|
}
|
|
9554
9853
|
});
|
|
9555
9854
|
}
|
|
@@ -9746,7 +10045,15 @@ function discoverUnits(sourceFile, patterns, resolution, mountPrefixes) {
|
|
|
9746
10045
|
}
|
|
9747
10046
|
|
|
9748
10047
|
// src/discovery/mountPrefix.ts
|
|
9749
|
-
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
|
+
};
|
|
9750
10057
|
function buildMountPrefixIndex(packsByFile, resolution) {
|
|
9751
10058
|
const subjectIdsByPack = /* @__PURE__ */ new Map();
|
|
9752
10059
|
const mountWorkByPack = /* @__PURE__ */ new Map();
|
|
@@ -9803,10 +10110,15 @@ function buildMountPrefixIndex(packsByFile, resolution) {
|
|
|
9803
10110
|
return NO_MOUNTS;
|
|
9804
10111
|
}
|
|
9805
10112
|
const memo = /* @__PURE__ */ new Map();
|
|
10113
|
+
const byId = (childId) => resolvePrefix(edgesByChild, memo, childId, /* @__PURE__ */ new Set()) ?? "";
|
|
9806
10114
|
return {
|
|
9807
10115
|
effectivePrefixFor(routerNode) {
|
|
9808
|
-
|
|
9809
|
-
|
|
10116
|
+
const childId = nodeId(routerNode);
|
|
10117
|
+
const prefix = byId(childId);
|
|
10118
|
+
recordMountPrefix(childId, prefix);
|
|
10119
|
+
return prefix;
|
|
10120
|
+
},
|
|
10121
|
+
prefixForId: byId
|
|
9810
10122
|
};
|
|
9811
10123
|
}
|
|
9812
10124
|
function recordEdge(edgesByChild, candidate) {
|
|
@@ -10058,14 +10370,16 @@ import {
|
|
|
10058
10370
|
import {
|
|
10059
10371
|
ANSWER_RELATIONS,
|
|
10060
10372
|
RESOLUTION_QUESTIONS,
|
|
10061
|
-
RESOLUTION_RULES as SHARED_RULES
|
|
10373
|
+
RESOLUTION_RULES as SHARED_RULES,
|
|
10374
|
+
VALUE_STEP
|
|
10062
10375
|
} from "@suss/resolution";
|
|
10063
10376
|
var JS_RULES = [
|
|
10064
|
-
// f.bind(...)
|
|
10377
|
+
// f.bind(...) leads wherever f leads. Stated as a step, so the
|
|
10378
|
+
// questions other than `comesTo` follow it too.
|
|
10065
10379
|
rule2(
|
|
10066
|
-
"
|
|
10067
|
-
[v2("r"), v2("
|
|
10068
|
-
[lit2("bindCall", v2("r"), v2("t"))
|
|
10380
|
+
"stepsTo",
|
|
10381
|
+
[v2("r"), v2("t"), VALUE_STEP],
|
|
10382
|
+
[lit2("bindCall", v2("r"), v2("t"))]
|
|
10069
10383
|
)
|
|
10070
10384
|
];
|
|
10071
10385
|
var RESOLUTION_PROGRAM = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? {
|
|
@@ -10083,6 +10397,8 @@ var ResolutionStore = class {
|
|
|
10083
10397
|
fullyExtracted = /* @__PURE__ */ new Set();
|
|
10084
10398
|
seededValues = /* @__PURE__ */ new Set();
|
|
10085
10399
|
importedNames = /* @__PURE__ */ new Map();
|
|
10400
|
+
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
10401
|
+
lastQueryWalked = [];
|
|
10086
10402
|
declarations = /* @__PURE__ */ new Map();
|
|
10087
10403
|
graph = new ModuleGraph();
|
|
10088
10404
|
stale = true;
|
|
@@ -10143,7 +10459,10 @@ var ResolutionStore = class {
|
|
|
10143
10459
|
const declaration = `${nodeId(refersTo)}|${modules.join(",")}`;
|
|
10144
10460
|
const cached = this.importedNames.get(declaration);
|
|
10145
10461
|
if (cached !== void 0) {
|
|
10146
|
-
|
|
10462
|
+
for (const walkedPath of cached.walked) {
|
|
10463
|
+
recordFileDependency(walkedPath);
|
|
10464
|
+
}
|
|
10465
|
+
return cached.names;
|
|
10147
10466
|
}
|
|
10148
10467
|
const target = factKeyOf(value);
|
|
10149
10468
|
const found = this.resolveByWaves(
|
|
@@ -10151,7 +10470,10 @@ var ResolutionStore = class {
|
|
|
10151
10470
|
"wantedOrigin",
|
|
10152
10471
|
() => this.lookupImportedNames(target, modules)
|
|
10153
10472
|
) ?? [];
|
|
10154
|
-
this.importedNames.set(declaration,
|
|
10473
|
+
this.importedNames.set(declaration, {
|
|
10474
|
+
names: found,
|
|
10475
|
+
walked: [...this.lastQueryWalked]
|
|
10476
|
+
});
|
|
10155
10477
|
return found;
|
|
10156
10478
|
}
|
|
10157
10479
|
/**
|
|
@@ -10185,6 +10507,7 @@ var ResolutionStore = class {
|
|
|
10185
10507
|
this.wantValue(question, value);
|
|
10186
10508
|
this.seedValue(value);
|
|
10187
10509
|
const walked = /* @__PURE__ */ new Set();
|
|
10510
|
+
this.lastQueryWalked = [];
|
|
10188
10511
|
let frontier = alsoFrom === void 0 ? [value.getSourceFile()] : [value.getSourceFile(), alsoFrom];
|
|
10189
10512
|
for (let hop = 0; hop <= MAX_MODULE_HOPS; hop++) {
|
|
10190
10513
|
const next = [];
|
|
@@ -10193,6 +10516,8 @@ var ResolutionStore = class {
|
|
|
10193
10516
|
continue;
|
|
10194
10517
|
}
|
|
10195
10518
|
walked.add(sourceFile.getFilePath());
|
|
10519
|
+
this.lastQueryWalked.push(sourceFile.getFilePath());
|
|
10520
|
+
recordFileDependency(sourceFile.getFilePath());
|
|
10196
10521
|
this.extractFile(sourceFile);
|
|
10197
10522
|
next.push(...this.graph.importedFilesOf(sourceFile));
|
|
10198
10523
|
}
|
|
@@ -10492,6 +10817,27 @@ function moduleInitSummary(sourceFile, effects, options) {
|
|
|
10492
10817
|
return assembleSummary(raw, options);
|
|
10493
10818
|
}
|
|
10494
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
|
+
|
|
10495
10841
|
// src/resolve/boundaryEffects.ts
|
|
10496
10842
|
import { evaluate as evaluate3, lit as lit3, rule as rule3, variable } from "@suss/datalog";
|
|
10497
10843
|
var EFFECT_RULES = [
|
|
@@ -10537,7 +10883,10 @@ function bindingLabel(binding) {
|
|
|
10537
10883
|
if (semantics.name === "graphql-operation") {
|
|
10538
10884
|
return `${semantics.operationType} ${semantics.operationName ?? ""}`.trim();
|
|
10539
10885
|
}
|
|
10540
|
-
|
|
10886
|
+
if ("exportName" in semantics || "module" in semantics) {
|
|
10887
|
+
return semantics.exportName ?? semantics.module ?? binding.recognition;
|
|
10888
|
+
}
|
|
10889
|
+
return binding.recognition;
|
|
10541
10890
|
}
|
|
10542
10891
|
function effectFact(effect) {
|
|
10543
10892
|
if (effect.type === "invocation") {
|
|
@@ -10609,10 +10958,108 @@ function deriveBoundaryEffects(summaries, facts) {
|
|
|
10609
10958
|
}
|
|
10610
10959
|
|
|
10611
10960
|
// src/resolve/reachableClosure.ts
|
|
10612
|
-
import { Node as
|
|
10961
|
+
import { Node as Node50 } from "ts-morph";
|
|
10613
10962
|
import { functionCallBinding } from "@suss/behavioral-ir";
|
|
10614
10963
|
import { Database as Database3, evaluate as evaluate4, lit as lit4, rule as rule4, variable as variable2 } from "@suss/datalog";
|
|
10615
10964
|
import { assembleSummary as assembleSummary2 } from "@suss/extractor";
|
|
10965
|
+
|
|
10966
|
+
// src/resolve/unfollowedCall.ts
|
|
10967
|
+
import {
|
|
10968
|
+
Node as Node49,
|
|
10969
|
+
SyntaxKind as SyntaxKind10
|
|
10970
|
+
} from "ts-morph";
|
|
10971
|
+
function isInExternalCode(sourceFile) {
|
|
10972
|
+
if (sourceFile.isDeclarationFile()) {
|
|
10973
|
+
return true;
|
|
10974
|
+
}
|
|
10975
|
+
return sourceFile.getFilePath().includes("/node_modules/");
|
|
10976
|
+
}
|
|
10977
|
+
function hasBody(fn) {
|
|
10978
|
+
if (Node49.isFunctionDeclaration(fn) || Node49.isMethodDeclaration(fn) || Node49.isFunctionExpression(fn)) {
|
|
10979
|
+
return fn.getBody?.() !== void 0;
|
|
10980
|
+
}
|
|
10981
|
+
return true;
|
|
10982
|
+
}
|
|
10983
|
+
function isDeclaredShape(declaration) {
|
|
10984
|
+
return (Node49.isMethodSignature(declaration) || Node49.isPropertySignature(declaration)) && !isInExternalCode(declaration.getSourceFile());
|
|
10985
|
+
}
|
|
10986
|
+
function isExternalDeclaration(declaration) {
|
|
10987
|
+
if (isInExternalCode(declaration.getSourceFile())) {
|
|
10988
|
+
return true;
|
|
10989
|
+
}
|
|
10990
|
+
if (Node49.isImportSpecifier(declaration) || Node49.isImportClause(declaration) || Node49.isNamespaceImport(declaration)) {
|
|
10991
|
+
const target = declaration.getFirstAncestorByKind(SyntaxKind10.ImportDeclaration)?.getModuleSpecifierSourceFile();
|
|
10992
|
+
return target === void 0 || isInExternalCode(target);
|
|
10993
|
+
}
|
|
10994
|
+
return declaresAnotherModule(declaration);
|
|
10995
|
+
}
|
|
10996
|
+
function declaresAnotherModule(declaration) {
|
|
10997
|
+
const module = declaration.getFirstAncestorByKind(
|
|
10998
|
+
SyntaxKind10.ModuleDeclaration
|
|
10999
|
+
);
|
|
11000
|
+
return module !== void 0 && Node49.isStringLiteral(module.getNameNode());
|
|
11001
|
+
}
|
|
11002
|
+
function statesShapeOnly(declaration) {
|
|
11003
|
+
if (isExternalDeclaration(declaration)) {
|
|
11004
|
+
return false;
|
|
11005
|
+
}
|
|
11006
|
+
if (Node49.isMethodSignature(declaration) || Node49.isPropertySignature(declaration)) {
|
|
11007
|
+
return true;
|
|
11008
|
+
}
|
|
11009
|
+
if (Node49.isFunctionDeclaration(declaration) || Node49.isMethodDeclaration(declaration)) {
|
|
11010
|
+
return declaration.getBody() === void 0;
|
|
11011
|
+
}
|
|
11012
|
+
return false;
|
|
11013
|
+
}
|
|
11014
|
+
function declarationsBehind(symbol) {
|
|
11015
|
+
if (symbol === void 0) {
|
|
11016
|
+
return [];
|
|
11017
|
+
}
|
|
11018
|
+
const behind = symbol.getAliasedSymbol()?.getDeclarations() ?? [];
|
|
11019
|
+
return behind.length > 0 ? behind : symbol.getDeclarations();
|
|
11020
|
+
}
|
|
11021
|
+
function classifyStop(declarations) {
|
|
11022
|
+
if (declarations.length === 0) {
|
|
11023
|
+
return "noDeclaration";
|
|
11024
|
+
}
|
|
11025
|
+
for (const declaration of declarations) {
|
|
11026
|
+
if (!isInExternalCode(declaration.getSourceFile())) {
|
|
11027
|
+
recordFileDependency(declaration.getSourceFile().getFilePath());
|
|
11028
|
+
}
|
|
11029
|
+
}
|
|
11030
|
+
if (declarations.every(isExternalDeclaration)) {
|
|
11031
|
+
return "outsideRun";
|
|
11032
|
+
}
|
|
11033
|
+
if (declarations.some(statesShapeOnly)) {
|
|
11034
|
+
return "noBody";
|
|
11035
|
+
}
|
|
11036
|
+
return "unsettledValue";
|
|
11037
|
+
}
|
|
11038
|
+
var RECORDED = {
|
|
11039
|
+
noBody: true,
|
|
11040
|
+
unsettledValue: true,
|
|
11041
|
+
outsideRun: false,
|
|
11042
|
+
noDeclaration: false
|
|
11043
|
+
};
|
|
11044
|
+
function worthRecording(reason) {
|
|
11045
|
+
return RECORDED[reason];
|
|
11046
|
+
}
|
|
11047
|
+
var STOP_SENTENCE = {
|
|
11048
|
+
noBody: (callee) => `The call to ${callee} lands on a declaration with no body, so whatever runs there is missing from this summary`,
|
|
11049
|
+
unsettledValue: (callee) => `The call to ${callee} goes through a value this run could not settle, so whatever runs there is missing from this summary`,
|
|
11050
|
+
outsideRun: (callee) => `The call to ${callee} lands in a package whose source is not in this run, so whatever runs there is missing from this summary`,
|
|
11051
|
+
noDeclaration: (callee) => `The call to ${callee} has no declaration this run could find, so whatever runs there is missing from this summary`
|
|
11052
|
+
};
|
|
11053
|
+
function unfollowedCallGap(stop) {
|
|
11054
|
+
return {
|
|
11055
|
+
type: "unfollowedCall",
|
|
11056
|
+
conditions: [],
|
|
11057
|
+
consequence: "unknown",
|
|
11058
|
+
description: STOP_SENTENCE[stop.reason](stop.callee)
|
|
11059
|
+
};
|
|
11060
|
+
}
|
|
11061
|
+
|
|
11062
|
+
// src/resolve/reachableClosure.ts
|
|
10616
11063
|
var reachablePack = {
|
|
10617
11064
|
name: "reachable",
|
|
10618
11065
|
languages: ["typescript"],
|
|
@@ -10635,23 +11082,6 @@ function nodeKey2(func) {
|
|
|
10635
11082
|
const sf = func.getSourceFile();
|
|
10636
11083
|
return `${sf.getFilePath()}:${func.getStart()}-${func.getEnd()}`;
|
|
10637
11084
|
}
|
|
10638
|
-
function isInExternalCode(sourceFile) {
|
|
10639
|
-
if (sourceFile.isDeclarationFile()) {
|
|
10640
|
-
return true;
|
|
10641
|
-
}
|
|
10642
|
-
const filePath = sourceFile.getFilePath();
|
|
10643
|
-
if (filePath.includes("/node_modules/")) {
|
|
10644
|
-
return true;
|
|
10645
|
-
}
|
|
10646
|
-
return false;
|
|
10647
|
-
}
|
|
10648
|
-
function hasBody(fn) {
|
|
10649
|
-
if (Node49.isFunctionDeclaration(fn) || Node49.isMethodDeclaration(fn) || Node49.isFunctionExpression(fn)) {
|
|
10650
|
-
const body = fn.getBody?.();
|
|
10651
|
-
return body !== void 0;
|
|
10652
|
-
}
|
|
10653
|
-
return true;
|
|
10654
|
-
}
|
|
10655
11085
|
function resolveDecl(decl, calleeName) {
|
|
10656
11086
|
if (isInExternalCode(decl.getSourceFile())) {
|
|
10657
11087
|
return null;
|
|
@@ -10663,14 +11093,14 @@ function resolveDecl(decl, calleeName) {
|
|
|
10663
11093
|
}
|
|
10664
11094
|
return { func: fn, name: declName(decl) ?? calleeName };
|
|
10665
11095
|
}
|
|
10666
|
-
if (
|
|
11096
|
+
if (Node50.isVariableDeclaration(decl)) {
|
|
10667
11097
|
const init = decl.getInitializer();
|
|
10668
|
-
if (init !== void 0 && (
|
|
11098
|
+
if (init !== void 0 && (Node50.isArrowFunction(init) || Node50.isFunctionExpression(init))) {
|
|
10669
11099
|
return { func: init, name: decl.getName() };
|
|
10670
11100
|
}
|
|
10671
11101
|
return null;
|
|
10672
11102
|
}
|
|
10673
|
-
if (
|
|
11103
|
+
if (Node50.isImportSpecifier(decl)) {
|
|
10674
11104
|
const importDecl = decl.getImportDeclaration();
|
|
10675
11105
|
const sf = importDecl.getModuleSpecifierSourceFile();
|
|
10676
11106
|
if (sf === void 0 || isInExternalCode(sf)) {
|
|
@@ -10691,78 +11121,85 @@ function resolveDecl(decl, calleeName) {
|
|
|
10691
11121
|
return null;
|
|
10692
11122
|
}
|
|
10693
11123
|
function declName(decl) {
|
|
10694
|
-
if (
|
|
11124
|
+
if (Node50.isFunctionDeclaration(decl) || Node50.isMethodDeclaration(decl)) {
|
|
10695
11125
|
const n = decl.getName?.();
|
|
10696
11126
|
if (typeof n === "string" && n.length > 0) {
|
|
10697
11127
|
return n;
|
|
10698
11128
|
}
|
|
10699
11129
|
}
|
|
10700
|
-
if (
|
|
11130
|
+
if (Node50.isFunctionExpression(decl)) {
|
|
10701
11131
|
const n = decl.getName();
|
|
10702
11132
|
if (typeof n === "string" && n.length > 0) {
|
|
10703
11133
|
return n;
|
|
10704
11134
|
}
|
|
10705
11135
|
}
|
|
10706
11136
|
const parent = decl.getParent();
|
|
10707
|
-
if (parent !== void 0 &&
|
|
11137
|
+
if (parent !== void 0 && Node50.isVariableDeclaration(parent)) {
|
|
10708
11138
|
return parent.getName();
|
|
10709
11139
|
}
|
|
10710
11140
|
return null;
|
|
10711
11141
|
}
|
|
10712
11142
|
function resolveCallee(call, calleeName, scan) {
|
|
10713
|
-
if (!
|
|
11143
|
+
if (!Node50.isCallExpression(call)) {
|
|
10714
11144
|
return null;
|
|
10715
11145
|
}
|
|
10716
11146
|
const callee = call.getExpression();
|
|
10717
|
-
const
|
|
11147
|
+
const symbol = callee.getSymbol();
|
|
11148
|
+
const declarations = symbol?.getDeclarations() ?? [];
|
|
10718
11149
|
for (const decl of declarations) {
|
|
10719
11150
|
const resolved = resolveDecl(decl, calleeName);
|
|
10720
11151
|
if (resolved !== null) {
|
|
10721
|
-
return resolved;
|
|
11152
|
+
return { kind: "followed", candidate: resolved };
|
|
10722
11153
|
}
|
|
10723
11154
|
}
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
return value === null ? null : resolveDecl(value, calleeName);
|
|
10732
|
-
}
|
|
10733
|
-
function readsAField(callee) {
|
|
10734
|
-
if (!Node49.isPropertyAccessExpression(callee)) {
|
|
10735
|
-
return false;
|
|
10736
|
-
}
|
|
10737
|
-
let receiver = callee.getExpression();
|
|
10738
|
-
while (Node49.isPropertyAccessExpression(receiver)) {
|
|
10739
|
-
receiver = receiver.getExpression();
|
|
11155
|
+
const resolveCallable = scan.resolveCallable;
|
|
11156
|
+
if (resolveCallable !== void 0 && Node50.isPropertyAccessExpression(callee) && declarations.some(isDeclaredShape)) {
|
|
11157
|
+
const value = resolveCallable(callee, scan.reachedFrom);
|
|
11158
|
+
const resolved = value === null ? null : resolveDecl(value, calleeName);
|
|
11159
|
+
if (resolved !== null) {
|
|
11160
|
+
return { kind: "followed", candidate: resolved };
|
|
11161
|
+
}
|
|
10740
11162
|
}
|
|
10741
|
-
return
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
11163
|
+
return {
|
|
11164
|
+
kind: "stopped",
|
|
11165
|
+
stop: {
|
|
11166
|
+
callee: calleeName,
|
|
11167
|
+
reason: classifyStop(declarationsBehind(symbol))
|
|
11168
|
+
}
|
|
11169
|
+
};
|
|
10745
11170
|
}
|
|
10746
11171
|
function collectReachable(func, scan) {
|
|
10747
|
-
const
|
|
11172
|
+
const candidates = [];
|
|
11173
|
+
const stops = [];
|
|
10748
11174
|
const seen = /* @__PURE__ */ new Set();
|
|
10749
11175
|
func.forEachDescendant((node) => {
|
|
10750
|
-
if (!
|
|
11176
|
+
if (!Node50.isCallExpression(node)) {
|
|
10751
11177
|
return;
|
|
10752
11178
|
}
|
|
10753
|
-
const calleeText = node.getExpression().getText();
|
|
10754
|
-
const
|
|
10755
|
-
if (
|
|
11179
|
+
const calleeText = normalizeCallee(node.getExpression().getText());
|
|
11180
|
+
const outcome = resolveCallee(node, calleeText, scan);
|
|
11181
|
+
if (outcome === null) {
|
|
10756
11182
|
return;
|
|
10757
11183
|
}
|
|
10758
|
-
|
|
11184
|
+
if (outcome.kind === "stopped") {
|
|
11185
|
+
const stopKey = `${outcome.stop.reason}:${outcome.stop.callee}`;
|
|
11186
|
+
if (!seen.has(stopKey) && worthRecording(outcome.stop.reason)) {
|
|
11187
|
+
seen.add(stopKey);
|
|
11188
|
+
stops.push(outcome.stop);
|
|
11189
|
+
}
|
|
11190
|
+
return;
|
|
11191
|
+
}
|
|
11192
|
+
const key = nodeKey2(outcome.candidate.func);
|
|
10759
11193
|
if (seen.has(key)) {
|
|
10760
11194
|
return;
|
|
10761
11195
|
}
|
|
10762
11196
|
seen.add(key);
|
|
10763
|
-
|
|
11197
|
+
candidates.push(outcome.candidate);
|
|
10764
11198
|
});
|
|
10765
|
-
return
|
|
11199
|
+
return { candidates, stops };
|
|
11200
|
+
}
|
|
11201
|
+
function normalizeCallee(text) {
|
|
11202
|
+
return text.replace(/\s+/g, " ").trim();
|
|
10766
11203
|
}
|
|
10767
11204
|
function extractReachableSummary(candidate, options, recognizers) {
|
|
10768
11205
|
const unit = {
|
|
@@ -10796,12 +11233,14 @@ var REACHABLE_RULES = [
|
|
|
10796
11233
|
)
|
|
10797
11234
|
];
|
|
10798
11235
|
var NO_RECOGNIZERS = { invocation: [], access: [] };
|
|
10799
|
-
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS) {
|
|
11236
|
+
function expandReachableClosure(seeds, project, options, projectFileSet, facts, recognizers = NO_RECOGNIZERS, alreadySummarized = []) {
|
|
10800
11237
|
const lookup = createSourceFileLookup(project);
|
|
10801
11238
|
const db = facts?.db ?? new Database3();
|
|
10802
11239
|
const functionByKey = /* @__PURE__ */ new Map();
|
|
10803
11240
|
const seedKeys = /* @__PURE__ */ new Set();
|
|
10804
11241
|
const scanned = /* @__PURE__ */ new Set();
|
|
11242
|
+
const stopsByKey = /* @__PURE__ */ new Map();
|
|
11243
|
+
const summariesByKey = /* @__PURE__ */ new Map();
|
|
10805
11244
|
const reachedFrom = /* @__PURE__ */ new Map();
|
|
10806
11245
|
for (const seed of seeds) {
|
|
10807
11246
|
const func = lookup.functionAt(seed.location);
|
|
@@ -10810,9 +11249,19 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10810
11249
|
seedKeys.add(key);
|
|
10811
11250
|
functionByKey.set(key, { func, name: seed.identity.name });
|
|
10812
11251
|
facts?.unitKeyBySummary.set(seed, key);
|
|
11252
|
+
rememberSummary(summariesByKey, key, seed);
|
|
10813
11253
|
db.add("entry", [key]);
|
|
10814
11254
|
}
|
|
10815
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
|
+
}
|
|
10816
11265
|
for (; ; ) {
|
|
10817
11266
|
evaluate4(db, REACHABLE_RULES);
|
|
10818
11267
|
const frontier = db.facts("reachable").map(([key]) => String(key)).filter((key) => !scanned.has(key));
|
|
@@ -10830,7 +11279,15 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10830
11279
|
...recognizers.resolveCallable === void 0 ? {} : { resolveCallable: recognizers.resolveCallable },
|
|
10831
11280
|
...cameFrom === void 0 ? {} : { reachedFrom: cameFrom }
|
|
10832
11281
|
};
|
|
10833
|
-
|
|
11282
|
+
const { candidates, stops } = scanWithRecording(
|
|
11283
|
+
key,
|
|
11284
|
+
facts,
|
|
11285
|
+
() => collectReachable(source.func, scan)
|
|
11286
|
+
);
|
|
11287
|
+
if (stops.length > 0) {
|
|
11288
|
+
stopsByKey.set(key, stops);
|
|
11289
|
+
}
|
|
11290
|
+
for (const candidate of candidates) {
|
|
10834
11291
|
const calleeKey = nodeKey2(candidate.func);
|
|
10835
11292
|
if (!functionByKey.has(calleeKey)) {
|
|
10836
11293
|
functionByKey.set(calleeKey, candidate);
|
|
@@ -10845,7 +11302,7 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10845
11302
|
const reached = [];
|
|
10846
11303
|
for (const [keyAtom] of db.facts("reachable")) {
|
|
10847
11304
|
const key = String(keyAtom);
|
|
10848
|
-
if (seedKeys.has(key)) {
|
|
11305
|
+
if (seedKeys.has(key) || knownKeys.has(key)) {
|
|
10849
11306
|
continue;
|
|
10850
11307
|
}
|
|
10851
11308
|
const candidate = functionByKey.get(key);
|
|
@@ -10859,15 +11316,50 @@ function expandReachableClosure(seeds, project, options, projectFileSet, facts,
|
|
|
10859
11316
|
candidate.func.getSourceFile().getFilePath()
|
|
10860
11317
|
);
|
|
10861
11318
|
}
|
|
10862
|
-
const summary =
|
|
11319
|
+
const summary = scanWithRecording(
|
|
11320
|
+
key,
|
|
11321
|
+
facts,
|
|
11322
|
+
() => extractReachableSummary(candidate, options, recognizers)
|
|
11323
|
+
);
|
|
10863
11324
|
facts?.unitKeyBySummary.set(summary, key);
|
|
11325
|
+
rememberSummary(summariesByKey, key, summary);
|
|
10864
11326
|
reached.push(summary);
|
|
10865
11327
|
}
|
|
11328
|
+
recordStops(stopsByKey, summariesByKey, options);
|
|
10866
11329
|
return [...seeds, ...reached];
|
|
10867
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
|
+
}
|
|
11345
|
+
function rememberSummary(summariesByKey, key, summary) {
|
|
11346
|
+
const bucket = summariesByKey.get(key) ?? [];
|
|
11347
|
+
bucket.push(summary);
|
|
11348
|
+
summariesByKey.set(key, bucket);
|
|
11349
|
+
}
|
|
11350
|
+
function recordStops(stopsByKey, summariesByKey, options) {
|
|
11351
|
+
if (options?.gapHandling === "silent") {
|
|
11352
|
+
return;
|
|
11353
|
+
}
|
|
11354
|
+
for (const [key, stops] of stopsByKey) {
|
|
11355
|
+
for (const summary of summariesByKey.get(key) ?? []) {
|
|
11356
|
+
summary.gaps.push(...stops.map(unfollowedCallGap));
|
|
11357
|
+
}
|
|
11358
|
+
}
|
|
11359
|
+
}
|
|
10868
11360
|
|
|
10869
11361
|
// src/resolve/rethrowEnrichment.ts
|
|
10870
|
-
import { Node as
|
|
11362
|
+
import { Node as Node51 } from "ts-morph";
|
|
10871
11363
|
import { Database as Database4, evaluate as evaluate5, lit as lit5, rule as rule5, variable as variable3 } from "@suss/datalog";
|
|
10872
11364
|
var RETHROW_RULES = [
|
|
10873
11365
|
rule5(
|
|
@@ -11007,7 +11499,7 @@ function findBareRethrow(func, location) {
|
|
|
11007
11499
|
traversal.stop();
|
|
11008
11500
|
return;
|
|
11009
11501
|
}
|
|
11010
|
-
if (!
|
|
11502
|
+
if (!Node51.isThrowStatement(node)) {
|
|
11011
11503
|
return;
|
|
11012
11504
|
}
|
|
11013
11505
|
if (startLineOf(node) !== location.start) {
|
|
@@ -11017,7 +11509,7 @@ function findBareRethrow(func, location) {
|
|
|
11017
11509
|
return;
|
|
11018
11510
|
}
|
|
11019
11511
|
const thrown = node.getExpression();
|
|
11020
|
-
if (thrown !== void 0 &&
|
|
11512
|
+
if (thrown !== void 0 && Node51.isIdentifier(thrown)) {
|
|
11021
11513
|
found = node;
|
|
11022
11514
|
}
|
|
11023
11515
|
});
|
|
@@ -11027,13 +11519,13 @@ function enclosingTry(throwStmt) {
|
|
|
11027
11519
|
let current2 = throwStmt.getParent();
|
|
11028
11520
|
let sawCatchClause = false;
|
|
11029
11521
|
while (current2 !== void 0) {
|
|
11030
|
-
if (
|
|
11522
|
+
if (Node51.isCatchClause(current2)) {
|
|
11031
11523
|
sawCatchClause = true;
|
|
11032
11524
|
}
|
|
11033
|
-
if (
|
|
11525
|
+
if (Node51.isTryStatement(current2)) {
|
|
11034
11526
|
return sawCatchClause ? current2 : null;
|
|
11035
11527
|
}
|
|
11036
|
-
if (
|
|
11528
|
+
if (Node51.isFunctionDeclaration(current2) || Node51.isFunctionExpression(current2) || Node51.isArrowFunction(current2) || Node51.isMethodDeclaration(current2)) {
|
|
11037
11529
|
return null;
|
|
11038
11530
|
}
|
|
11039
11531
|
current2 = current2.getParent();
|
|
@@ -11041,14 +11533,14 @@ function enclosingTry(throwStmt) {
|
|
|
11041
11533
|
return null;
|
|
11042
11534
|
}
|
|
11043
11535
|
function collectTryBodyCallees(tryStmt, index, keyFor) {
|
|
11044
|
-
if (!
|
|
11536
|
+
if (!Node51.isTryStatement(tryStmt)) {
|
|
11045
11537
|
return [];
|
|
11046
11538
|
}
|
|
11047
11539
|
const tryBlock = tryStmt.getTryBlock();
|
|
11048
11540
|
const callees = [];
|
|
11049
11541
|
const seen = /* @__PURE__ */ new Set();
|
|
11050
11542
|
tryBlock.forEachDescendant((node) => {
|
|
11051
|
-
if (!
|
|
11543
|
+
if (!Node51.isCallExpression(node)) {
|
|
11052
11544
|
return;
|
|
11053
11545
|
}
|
|
11054
11546
|
const calleeSummary = resolveCalleeSummary(node, index);
|
|
@@ -11065,7 +11557,7 @@ function collectTryBodyCallees(tryStmt, index, keyFor) {
|
|
|
11065
11557
|
return callees;
|
|
11066
11558
|
}
|
|
11067
11559
|
function resolveCalleeSummary(call, index) {
|
|
11068
|
-
if (!
|
|
11560
|
+
if (!Node51.isCallExpression(call)) {
|
|
11069
11561
|
return null;
|
|
11070
11562
|
}
|
|
11071
11563
|
const callee = call.getExpression();
|
|
@@ -11091,12 +11583,12 @@ function resolveCalleeSummary(call, index) {
|
|
|
11091
11583
|
return null;
|
|
11092
11584
|
}
|
|
11093
11585
|
function functionFromDecl(decl) {
|
|
11094
|
-
if (
|
|
11586
|
+
if (Node51.isFunctionDeclaration(decl) || Node51.isFunctionExpression(decl) || Node51.isArrowFunction(decl) || Node51.isMethodDeclaration(decl)) {
|
|
11095
11587
|
return decl;
|
|
11096
11588
|
}
|
|
11097
|
-
if (
|
|
11589
|
+
if (Node51.isVariableDeclaration(decl)) {
|
|
11098
11590
|
const init = decl.getInitializer();
|
|
11099
|
-
if (init !== void 0 && (
|
|
11591
|
+
if (init !== void 0 && (Node51.isArrowFunction(init) || Node51.isFunctionExpression(init))) {
|
|
11100
11592
|
return init;
|
|
11101
11593
|
}
|
|
11102
11594
|
}
|
|
@@ -11105,23 +11597,23 @@ function functionFromDecl(decl) {
|
|
|
11105
11597
|
|
|
11106
11598
|
// src/shapes/fieldAccesses.ts
|
|
11107
11599
|
import {
|
|
11108
|
-
Node as
|
|
11600
|
+
Node as Node52
|
|
11109
11601
|
} from "ts-morph";
|
|
11110
11602
|
function findResponseAccessor(callExpr) {
|
|
11111
11603
|
let current2 = callExpr;
|
|
11112
11604
|
const parent1 = current2.getParent();
|
|
11113
|
-
if (parent1 !== void 0 &&
|
|
11605
|
+
if (parent1 !== void 0 && Node52.isAwaitExpression(parent1)) {
|
|
11114
11606
|
current2 = parent1;
|
|
11115
11607
|
}
|
|
11116
11608
|
const parent2 = current2.getParent();
|
|
11117
|
-
if (parent2 === void 0 || !
|
|
11609
|
+
if (parent2 === void 0 || !Node52.isVariableDeclaration(parent2)) {
|
|
11118
11610
|
return null;
|
|
11119
11611
|
}
|
|
11120
11612
|
const nameNode = parent2.getNameNode();
|
|
11121
|
-
if (
|
|
11613
|
+
if (Node52.isIdentifier(nameNode)) {
|
|
11122
11614
|
return { kind: "identifier", name: nameNode.getText() };
|
|
11123
11615
|
}
|
|
11124
|
-
if (
|
|
11616
|
+
if (Node52.isObjectBindingPattern(nameNode)) {
|
|
11125
11617
|
const bindings = /* @__PURE__ */ new Map();
|
|
11126
11618
|
for (const element of nameNode.getElements()) {
|
|
11127
11619
|
if (element.getDotDotDotToken() !== void 0) {
|
|
@@ -11142,11 +11634,11 @@ function findResponseAccessor(callExpr) {
|
|
|
11142
11634
|
function buildThenChainAccessor(callExpr, func) {
|
|
11143
11635
|
const bindings = /* @__PURE__ */ new Map();
|
|
11144
11636
|
func.forEachDescendant((node) => {
|
|
11145
|
-
if (!
|
|
11637
|
+
if (!Node52.isParameterDeclaration(node)) {
|
|
11146
11638
|
return;
|
|
11147
11639
|
}
|
|
11148
11640
|
const nameNode = node.getNameNode();
|
|
11149
|
-
if (!
|
|
11641
|
+
if (!Node52.isIdentifier(nameNode)) {
|
|
11150
11642
|
return;
|
|
11151
11643
|
}
|
|
11152
11644
|
const prefix = prefixOfThenParam(node, callExpr, 0);
|
|
@@ -11178,7 +11670,7 @@ function prefixOfExpr(expr, responseCall, depth) {
|
|
|
11178
11670
|
if (node === responseCall) {
|
|
11179
11671
|
return [];
|
|
11180
11672
|
}
|
|
11181
|
-
if (
|
|
11673
|
+
if (Node52.isCallExpression(node)) {
|
|
11182
11674
|
const hop = thenLikeCall(node);
|
|
11183
11675
|
if (hop !== null) {
|
|
11184
11676
|
if (hop.method === "catch") {
|
|
@@ -11210,14 +11702,14 @@ function prefixOfMemberExpr(expr, responseCall, depth) {
|
|
|
11210
11702
|
return null;
|
|
11211
11703
|
}
|
|
11212
11704
|
const decl = chain.root.getSymbol()?.getDeclarations()?.[0];
|
|
11213
|
-
if (decl === void 0 || !
|
|
11705
|
+
if (decl === void 0 || !Node52.isParameterDeclaration(decl)) {
|
|
11214
11706
|
return null;
|
|
11215
11707
|
}
|
|
11216
11708
|
const base = prefixOfThenParam(decl, responseCall, depth + 1);
|
|
11217
11709
|
return base === null ? null : [...base, ...chain.segments];
|
|
11218
11710
|
}
|
|
11219
11711
|
function firstCallbackParamName(callback) {
|
|
11220
|
-
if (callback === void 0 || !(
|
|
11712
|
+
if (callback === void 0 || !(Node52.isArrowFunction(callback) || Node52.isFunctionExpression(callback))) {
|
|
11221
11713
|
return null;
|
|
11222
11714
|
}
|
|
11223
11715
|
const param = callback.getParameters()[0];
|
|
@@ -11225,11 +11717,11 @@ function firstCallbackParamName(callback) {
|
|
|
11225
11717
|
return null;
|
|
11226
11718
|
}
|
|
11227
11719
|
const nameNode = param.getNameNode();
|
|
11228
|
-
return
|
|
11720
|
+
return Node52.isIdentifier(nameNode) ? nameNode.getText() : null;
|
|
11229
11721
|
}
|
|
11230
11722
|
function unwrap2(expr) {
|
|
11231
11723
|
let node = expr;
|
|
11232
|
-
while (
|
|
11724
|
+
while (Node52.isAwaitExpression(node) || Node52.isParenthesizedExpression(node) || Node52.isAsExpression(node)) {
|
|
11233
11725
|
node = node.getExpression();
|
|
11234
11726
|
}
|
|
11235
11727
|
return node;
|
|
@@ -11239,15 +11731,15 @@ function chainRootedAt(expr, rootName) {
|
|
|
11239
11731
|
if (chain === null) {
|
|
11240
11732
|
return null;
|
|
11241
11733
|
}
|
|
11242
|
-
return
|
|
11734
|
+
return Node52.isIdentifier(chain.root) && chain.root.getText() === rootName ? chain.segments : null;
|
|
11243
11735
|
}
|
|
11244
11736
|
function memberChain(expr) {
|
|
11245
|
-
let node =
|
|
11246
|
-
if (
|
|
11737
|
+
let node = Node52.isExpression(expr) ? unwrap2(expr) : expr;
|
|
11738
|
+
if (Node52.isCallExpression(node)) {
|
|
11247
11739
|
node = node.getExpression();
|
|
11248
11740
|
}
|
|
11249
11741
|
const segments = [];
|
|
11250
|
-
while (
|
|
11742
|
+
while (Node52.isPropertyAccessExpression(node)) {
|
|
11251
11743
|
segments.unshift(node.getName());
|
|
11252
11744
|
node = node.getExpression();
|
|
11253
11745
|
}
|
|
@@ -11266,16 +11758,16 @@ function collectPropertyAccesses(subtree, accessor) {
|
|
|
11266
11758
|
if (accessor.kind === "identifier") {
|
|
11267
11759
|
const varName = accessor.name;
|
|
11268
11760
|
subtree.forEachDescendant((node) => {
|
|
11269
|
-
if (!
|
|
11761
|
+
if (!Node52.isPropertyAccessExpression(node)) {
|
|
11270
11762
|
return;
|
|
11271
11763
|
}
|
|
11272
11764
|
const chain = [];
|
|
11273
11765
|
let current2 = node;
|
|
11274
|
-
while (
|
|
11766
|
+
while (Node52.isPropertyAccessExpression(current2)) {
|
|
11275
11767
|
chain.unshift(current2.getName());
|
|
11276
11768
|
current2 = current2.getExpression();
|
|
11277
11769
|
}
|
|
11278
|
-
if (
|
|
11770
|
+
if (Node52.isIdentifier(current2) && current2.getText() === varName) {
|
|
11279
11771
|
pushChain(chain);
|
|
11280
11772
|
}
|
|
11281
11773
|
});
|
|
@@ -11286,7 +11778,7 @@ function collectPropertyAccesses(subtree, accessor) {
|
|
|
11286
11778
|
return source === void 0 ? void 0 : [source];
|
|
11287
11779
|
} : (name) => accessor.bindings.get(name);
|
|
11288
11780
|
subtree.forEachDescendant((node) => {
|
|
11289
|
-
if (!
|
|
11781
|
+
if (!Node52.isIdentifier(node)) {
|
|
11290
11782
|
return;
|
|
11291
11783
|
}
|
|
11292
11784
|
const prefix = prefixOf(node.getText());
|
|
@@ -11298,13 +11790,13 @@ function collectPropertyAccesses(subtree, accessor) {
|
|
|
11298
11790
|
}
|
|
11299
11791
|
let chainTop = node;
|
|
11300
11792
|
let parent = chainTop.getParent();
|
|
11301
|
-
while (parent !== void 0 &&
|
|
11793
|
+
while (parent !== void 0 && Node52.isPropertyAccessExpression(parent) && parent.getExpression() === chainTop) {
|
|
11302
11794
|
chainTop = parent;
|
|
11303
11795
|
parent = chainTop.getParent();
|
|
11304
11796
|
}
|
|
11305
11797
|
const segments = [];
|
|
11306
11798
|
let current2 = chainTop;
|
|
11307
|
-
while (
|
|
11799
|
+
while (Node52.isPropertyAccessExpression(current2)) {
|
|
11308
11800
|
segments.push(current2.getName());
|
|
11309
11801
|
current2 = current2.getExpression();
|
|
11310
11802
|
}
|
|
@@ -11318,15 +11810,15 @@ function isBindingDeclarationSite(node) {
|
|
|
11318
11810
|
return true;
|
|
11319
11811
|
}
|
|
11320
11812
|
const parent = node.getParent();
|
|
11321
|
-
return parent !== void 0 &&
|
|
11813
|
+
return parent !== void 0 && Node52.isParameterDeclaration(parent) && parent.getNameNode() === node;
|
|
11322
11814
|
}
|
|
11323
11815
|
function isInsideObjectBindingPattern(node) {
|
|
11324
11816
|
let current2 = node.getParent();
|
|
11325
11817
|
while (current2 !== void 0) {
|
|
11326
|
-
if (
|
|
11818
|
+
if (Node52.isObjectBindingPattern(current2)) {
|
|
11327
11819
|
return true;
|
|
11328
11820
|
}
|
|
11329
|
-
if (
|
|
11821
|
+
if (Node52.isFunctionLikeDeclaration(current2) || Node52.isVariableStatement(current2)) {
|
|
11330
11822
|
break;
|
|
11331
11823
|
}
|
|
11332
11824
|
current2 = current2.getParent();
|
|
@@ -11389,7 +11881,7 @@ function findBranchSubtree(func, byLineRange, terminalStartLine, terminalEndLine
|
|
|
11389
11881
|
if (parent === void 0) {
|
|
11390
11882
|
break;
|
|
11391
11883
|
}
|
|
11392
|
-
if (
|
|
11884
|
+
if (Node52.isIfStatement(parent)) {
|
|
11393
11885
|
const ifStmt = parent;
|
|
11394
11886
|
const thenBlock = ifStmt.getThenStatement();
|
|
11395
11887
|
const elseBlock = ifStmt.getElseStatement();
|
|
@@ -11452,7 +11944,7 @@ function buildNonBodyPropertySet(semantics) {
|
|
|
11452
11944
|
|
|
11453
11945
|
// src/subUnitContext.ts
|
|
11454
11946
|
import {
|
|
11455
|
-
Node as
|
|
11947
|
+
Node as Node53
|
|
11456
11948
|
} from "ts-morph";
|
|
11457
11949
|
function createTsSubUnitContext() {
|
|
11458
11950
|
return {
|
|
@@ -11466,7 +11958,7 @@ function createTsSubUnitContext() {
|
|
|
11466
11958
|
}
|
|
11467
11959
|
function skipNestedFunctions(parent) {
|
|
11468
11960
|
return (node, traversal) => {
|
|
11469
|
-
if (node !== parent && (
|
|
11961
|
+
if (node !== parent && (Node53.isFunctionDeclaration(node) || Node53.isFunctionExpression(node) || Node53.isArrowFunction(node) || Node53.isMethodDeclaration(node))) {
|
|
11470
11962
|
traversal.skip();
|
|
11471
11963
|
return true;
|
|
11472
11964
|
}
|
|
@@ -11480,18 +11972,18 @@ function findJsxAttributes(parent) {
|
|
|
11480
11972
|
if (skip(node, traversal)) {
|
|
11481
11973
|
return;
|
|
11482
11974
|
}
|
|
11483
|
-
if (!
|
|
11975
|
+
if (!Node53.isJsxOpeningElement(node) && !Node53.isJsxSelfClosingElement(node)) {
|
|
11484
11976
|
return;
|
|
11485
11977
|
}
|
|
11486
11978
|
const tag = node.getTagNameNode().getText();
|
|
11487
11979
|
for (const attr of node.getAttributes()) {
|
|
11488
|
-
if (!
|
|
11980
|
+
if (!Node53.isJsxAttribute(attr)) {
|
|
11489
11981
|
continue;
|
|
11490
11982
|
}
|
|
11491
11983
|
const initializer = attr.getInitializer();
|
|
11492
11984
|
let valueExpression = null;
|
|
11493
11985
|
if (initializer !== void 0) {
|
|
11494
|
-
if (
|
|
11986
|
+
if (Node53.isJsxExpression(initializer)) {
|
|
11495
11987
|
const inner = initializer.getExpression();
|
|
11496
11988
|
valueExpression = inner ?? null;
|
|
11497
11989
|
} else {
|
|
@@ -11514,11 +12006,11 @@ function findCallExpressionsByName(parent, name) {
|
|
|
11514
12006
|
if (skip(node, traversal)) {
|
|
11515
12007
|
return;
|
|
11516
12008
|
}
|
|
11517
|
-
if (!
|
|
12009
|
+
if (!Node53.isCallExpression(node)) {
|
|
11518
12010
|
return;
|
|
11519
12011
|
}
|
|
11520
12012
|
const callee = node.getExpression();
|
|
11521
|
-
if (
|
|
12013
|
+
if (Node53.isIdentifier(callee) && callee.getText() === name) {
|
|
11522
12014
|
out.push(node);
|
|
11523
12015
|
}
|
|
11524
12016
|
});
|
|
@@ -11529,10 +12021,10 @@ function resolveAttributeValueFunction(attr, parent) {
|
|
|
11529
12021
|
if (expr === null) {
|
|
11530
12022
|
return null;
|
|
11531
12023
|
}
|
|
11532
|
-
if (
|
|
12024
|
+
if (Node53.isArrowFunction(expr) || Node53.isFunctionExpression(expr)) {
|
|
11533
12025
|
return { func: expr, localName: null };
|
|
11534
12026
|
}
|
|
11535
|
-
if (
|
|
12027
|
+
if (Node53.isIdentifier(expr)) {
|
|
11536
12028
|
const symbol = expr.getSymbol();
|
|
11537
12029
|
if (symbol === void 0) {
|
|
11538
12030
|
return null;
|
|
@@ -11551,15 +12043,15 @@ function resolveAttributeValueFunction(attr, parent) {
|
|
|
11551
12043
|
return null;
|
|
11552
12044
|
}
|
|
11553
12045
|
function tryExtractFunction(decl) {
|
|
11554
|
-
if (
|
|
12046
|
+
if (Node53.isFunctionDeclaration(decl)) {
|
|
11555
12047
|
return decl;
|
|
11556
12048
|
}
|
|
11557
|
-
if (
|
|
12049
|
+
if (Node53.isVariableDeclaration(decl)) {
|
|
11558
12050
|
const init = decl.getInitializer();
|
|
11559
12051
|
if (init === void 0) {
|
|
11560
12052
|
return null;
|
|
11561
12053
|
}
|
|
11562
|
-
if (
|
|
12054
|
+
if (Node53.isArrowFunction(init) || Node53.isFunctionExpression(init)) {
|
|
11563
12055
|
return init;
|
|
11564
12056
|
}
|
|
11565
12057
|
}
|
|
@@ -11580,7 +12072,7 @@ function getCallArgumentFunction(call, position) {
|
|
|
11580
12072
|
if (arg === void 0) {
|
|
11581
12073
|
return null;
|
|
11582
12074
|
}
|
|
11583
|
-
if (
|
|
12075
|
+
if (Node53.isArrowFunction(arg) || Node53.isFunctionExpression(arg)) {
|
|
11584
12076
|
return arg;
|
|
11585
12077
|
}
|
|
11586
12078
|
return null;
|
|
@@ -11592,7 +12084,7 @@ function readArrayLiteralText(node) {
|
|
|
11592
12084
|
if (node === null) {
|
|
11593
12085
|
return null;
|
|
11594
12086
|
}
|
|
11595
|
-
if (
|
|
12087
|
+
if (Node53.isArrayLiteralExpression(node)) {
|
|
11596
12088
|
return node.getElements().map((e) => e.getText());
|
|
11597
12089
|
}
|
|
11598
12090
|
return [node.getText()];
|
|
@@ -11817,13 +12309,13 @@ var raise = (msg) => {
|
|
|
11817
12309
|
throw new Error(msg);
|
|
11818
12310
|
};
|
|
11819
12311
|
function bindingPatternNames(nameNode) {
|
|
11820
|
-
if (
|
|
12312
|
+
if (Node54.isObjectBindingPattern(nameNode)) {
|
|
11821
12313
|
return nameNode.getElements().map((e) => e.getName());
|
|
11822
12314
|
}
|
|
11823
|
-
if (
|
|
12315
|
+
if (Node54.isArrayBindingPattern(nameNode)) {
|
|
11824
12316
|
const names = [];
|
|
11825
12317
|
for (const element of nameNode.getElements()) {
|
|
11826
|
-
if (
|
|
12318
|
+
if (Node54.isOmittedExpression(element)) {
|
|
11827
12319
|
continue;
|
|
11828
12320
|
}
|
|
11829
12321
|
names.push(element.getName());
|
|
@@ -11834,7 +12326,7 @@ function bindingPatternNames(nameNode) {
|
|
|
11834
12326
|
}
|
|
11835
12327
|
function componentPropsParameters(param, mapping) {
|
|
11836
12328
|
const nameNode = param.getNameNode();
|
|
11837
|
-
if (!
|
|
12329
|
+
if (!Node54.isObjectBindingPattern(nameNode)) {
|
|
11838
12330
|
const type = param.getType();
|
|
11839
12331
|
return [
|
|
11840
12332
|
{
|
|
@@ -11960,11 +12452,11 @@ function extractParameters(func, inputMapping) {
|
|
|
11960
12452
|
function extractDependencyCalls(func) {
|
|
11961
12453
|
const results = [];
|
|
11962
12454
|
func.forEachDescendant((node, traversal) => {
|
|
11963
|
-
if (node !== func && (
|
|
12455
|
+
if (node !== func && (Node54.isFunctionDeclaration(node) || Node54.isFunctionExpression(node) || Node54.isArrowFunction(node) || Node54.isMethodDeclaration(node))) {
|
|
11964
12456
|
traversal.skip();
|
|
11965
12457
|
return;
|
|
11966
12458
|
}
|
|
11967
|
-
if (!
|
|
12459
|
+
if (!Node54.isVariableDeclaration(node)) {
|
|
11968
12460
|
return;
|
|
11969
12461
|
}
|
|
11970
12462
|
const init = node.getInitializer();
|
|
@@ -11973,19 +12465,19 @@ function extractDependencyCalls(func) {
|
|
|
11973
12465
|
}
|
|
11974
12466
|
let isAsync = false;
|
|
11975
12467
|
let callExpr = init;
|
|
11976
|
-
if (
|
|
12468
|
+
if (Node54.isAwaitExpression(init)) {
|
|
11977
12469
|
isAsync = true;
|
|
11978
12470
|
callExpr = init.getExpression();
|
|
11979
12471
|
}
|
|
11980
|
-
if (!
|
|
12472
|
+
if (!Node54.isCallExpression(callExpr)) {
|
|
11981
12473
|
return;
|
|
11982
12474
|
}
|
|
11983
12475
|
const calleeName = callExpr.getExpression().getText();
|
|
11984
12476
|
const nameNode = node.getNameNode();
|
|
11985
|
-
const assignedTo =
|
|
12477
|
+
const assignedTo = Node54.isIdentifier(nameNode) ? nameNode.getText() : null;
|
|
11986
12478
|
const declList = node.getParent();
|
|
11987
12479
|
const varStmt = declList?.getParent();
|
|
11988
|
-
const locationNode = varStmt !== void 0 &&
|
|
12480
|
+
const locationNode = varStmt !== void 0 && Node54.isVariableStatement(varStmt) ? varStmt : node;
|
|
11989
12481
|
results.push({
|
|
11990
12482
|
name: calleeName,
|
|
11991
12483
|
assignedTo,
|
|
@@ -12111,6 +12603,36 @@ function extractCodeStructure(unit, pack, invocationRecognizers = [], accessReco
|
|
|
12111
12603
|
function responseAccessorNames(pack, kind) {
|
|
12112
12604
|
return pack.responseSemantics?.filter((m) => m.semantics.type === kind).map((m) => m.name);
|
|
12113
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
|
+
}
|
|
12114
12636
|
function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers, barriers, resolveWrittenValue) {
|
|
12115
12637
|
const { func, kind, name } = unit;
|
|
12116
12638
|
if (func === null) {
|
|
@@ -12122,7 +12644,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12122
12644
|
);
|
|
12123
12645
|
const extracted = extractRawBranches(
|
|
12124
12646
|
func,
|
|
12125
|
-
unit
|
|
12647
|
+
terminalsFor(unit, pack),
|
|
12126
12648
|
invocationRecognizers,
|
|
12127
12649
|
accessRecognizers,
|
|
12128
12650
|
barriers,
|
|
@@ -12158,8 +12680,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12158
12680
|
}
|
|
12159
12681
|
}
|
|
12160
12682
|
}
|
|
12161
|
-
const
|
|
12162
|
-
const statusAccessors = unit.callSite !== void 0 ? responseAccessorNames(pack, "statusCode") : void 0;
|
|
12683
|
+
const accessors = unit.callSite !== void 0 ? responseAccessors(pack) : {};
|
|
12163
12684
|
return {
|
|
12164
12685
|
identity: {
|
|
12165
12686
|
name,
|
|
@@ -12183,8 +12704,8 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
|
|
|
12183
12704
|
bodyContent: bodyContentOf(func),
|
|
12184
12705
|
dependencyCalls: depCalls,
|
|
12185
12706
|
declaredContract: null,
|
|
12186
|
-
...
|
|
12187
|
-
...
|
|
12707
|
+
...accessors,
|
|
12708
|
+
...unit.callSite !== void 0 && pack.failureDelivery !== void 0 ? { failureDelivery: pack.failureDelivery } : {}
|
|
12188
12709
|
};
|
|
12189
12710
|
}
|
|
12190
12711
|
function extractConsumerBinding(unit, pattern, pack, resolution) {
|
|
@@ -12241,9 +12762,9 @@ function extractBindingMethod(binding, callSite, pack, resolution) {
|
|
|
12241
12762
|
if (m.type === "fromArgumentProperty") {
|
|
12242
12763
|
const args = callSite.callExpression.getArguments();
|
|
12243
12764
|
const arg = args[m.position];
|
|
12244
|
-
if (arg !== void 0 &&
|
|
12765
|
+
if (arg !== void 0 && Node54.isObjectLiteralExpression(arg)) {
|
|
12245
12766
|
const prop = arg.getProperty(m.property);
|
|
12246
|
-
if (prop !== void 0 &&
|
|
12767
|
+
if (prop !== void 0 && Node54.isPropertyAssignment(prop)) {
|
|
12247
12768
|
const init = prop.getInitializer();
|
|
12248
12769
|
if (init !== void 0) {
|
|
12249
12770
|
const value = stringValueOf(init, resolution);
|
|
@@ -12372,22 +12893,22 @@ function extractBindingPath(binding, callSite, pack, resolution) {
|
|
|
12372
12893
|
return void 0;
|
|
12373
12894
|
}
|
|
12374
12895
|
function pathFromUrlNode(node) {
|
|
12375
|
-
if (
|
|
12896
|
+
if (Node54.isStringLiteral(node)) {
|
|
12376
12897
|
return pathFromLiteralUrl(node.getLiteralValue());
|
|
12377
12898
|
}
|
|
12378
|
-
if (
|
|
12899
|
+
if (Node54.isNoSubstitutionTemplateLiteral(node)) {
|
|
12379
12900
|
return pathFromLiteralUrl(node.getLiteralValue());
|
|
12380
12901
|
}
|
|
12381
|
-
if (
|
|
12902
|
+
if (Node54.isTemplateExpression(node)) {
|
|
12382
12903
|
return pathFromTemplateUrl(node);
|
|
12383
12904
|
}
|
|
12384
12905
|
return void 0;
|
|
12385
12906
|
}
|
|
12386
12907
|
function placeholderName(expr) {
|
|
12387
|
-
if (
|
|
12908
|
+
if (Node54.isIdentifier(expr)) {
|
|
12388
12909
|
return expr.getText();
|
|
12389
12910
|
}
|
|
12390
|
-
if (
|
|
12911
|
+
if (Node54.isPropertyAccessExpression(expr)) {
|
|
12391
12912
|
return expr.getName();
|
|
12392
12913
|
}
|
|
12393
12914
|
return "param";
|
|
@@ -12538,12 +13059,20 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12538
13059
|
if (claimant.pack === pack.name && claimant.file === sourceFile.getFilePath() && tally !== void 0) {
|
|
12539
13060
|
tally.selfCollisions += 1;
|
|
12540
13061
|
}
|
|
13062
|
+
if (claimant.file !== sourceFile.getFilePath()) {
|
|
13063
|
+
recordFileDependency(claimant.file);
|
|
13064
|
+
}
|
|
12541
13065
|
continue;
|
|
12542
13066
|
}
|
|
12543
13067
|
claimed.set(claimKey, {
|
|
12544
13068
|
pack: pack.name,
|
|
12545
13069
|
file: sourceFile.getFilePath()
|
|
12546
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
|
+
}
|
|
12547
13076
|
unitsWalkedHere += 1;
|
|
12548
13077
|
if (tally !== void 0) {
|
|
12549
13078
|
tally.unitsClaimed += 1;
|
|
@@ -12582,6 +13111,9 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
|
|
|
12582
13111
|
}
|
|
12583
13112
|
if (unit.resolverInfo.schemaSdl !== void 0) {
|
|
12584
13113
|
raw.graphqlSchemaSdl = unit.resolverInfo.schemaSdl;
|
|
13114
|
+
if (unit.resolverInfo.schemaDocument !== void 0) {
|
|
13115
|
+
raw.sourceDocumentLabel = unit.resolverInfo.schemaDocument;
|
|
13116
|
+
}
|
|
12585
13117
|
if (unit.resolverInfo.typeName !== null) {
|
|
12586
13118
|
const contract = deriveGraphqlContract(
|
|
12587
13119
|
unit.resolverInfo.schemaSdl,
|
|
@@ -12770,6 +13302,37 @@ function fileImporting(project, modulePrefix) {
|
|
|
12770
13302
|
}
|
|
12771
13303
|
return void 0;
|
|
12772
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
|
+
}
|
|
12773
13336
|
function libraryEnvReadMarker(pack, declared, importer) {
|
|
12774
13337
|
return {
|
|
12775
13338
|
kind: "library",
|
|
@@ -12822,7 +13385,7 @@ function expandWrapperCallers(summaries, project, options) {
|
|
|
12822
13385
|
continue;
|
|
12823
13386
|
}
|
|
12824
13387
|
const binding = s.identity.boundaryBinding;
|
|
12825
|
-
if (binding === null || binding.semantics.name !== "rest" || binding.semantics.method === null
|
|
13388
|
+
if (binding === null || binding.semantics.name !== "rest" || binding.semantics.method === null) {
|
|
12826
13389
|
continue;
|
|
12827
13390
|
}
|
|
12828
13391
|
lookup ??= createSourceFileLookup(project);
|
|
@@ -12850,11 +13413,21 @@ function findWrapperPathParam(summary, lookup) {
|
|
|
12850
13413
|
if (func === null) {
|
|
12851
13414
|
return null;
|
|
12852
13415
|
}
|
|
12853
|
-
const
|
|
12854
|
-
if (
|
|
13416
|
+
const names = func.getParameters().map((p) => p.getName());
|
|
13417
|
+
if (names.length === 0) {
|
|
12855
13418
|
return null;
|
|
12856
13419
|
}
|
|
12857
|
-
|
|
13420
|
+
for (const call of func.getDescendantsOfKind(SyntaxKind11.CallExpression)) {
|
|
13421
|
+
const first = call.getArguments()[0];
|
|
13422
|
+
if (first === void 0 || !Node54.isIdentifier(first)) {
|
|
13423
|
+
continue;
|
|
13424
|
+
}
|
|
13425
|
+
const at = names.indexOf(first.getText());
|
|
13426
|
+
if (at !== -1) {
|
|
13427
|
+
return { func, pathParamPosition: at };
|
|
13428
|
+
}
|
|
13429
|
+
}
|
|
13430
|
+
return null;
|
|
12858
13431
|
}
|
|
12859
13432
|
function synthesizeCallerSummaries(wrapper, _project, options) {
|
|
12860
13433
|
const nameNode = wrapperNameNode(wrapper.func);
|
|
@@ -12895,16 +13468,16 @@ function synthesizeCallerSummaries(wrapper, _project, options) {
|
|
|
12895
13468
|
return out;
|
|
12896
13469
|
}
|
|
12897
13470
|
function wrapperNameNode(func) {
|
|
12898
|
-
if (
|
|
13471
|
+
if (Node54.isFunctionDeclaration(func) || Node54.isMethodDeclaration(func)) {
|
|
12899
13472
|
const name = func.getNameNode();
|
|
12900
|
-
if (name !== void 0 &&
|
|
13473
|
+
if (name !== void 0 && Node54.isIdentifier(name)) {
|
|
12901
13474
|
return name;
|
|
12902
13475
|
}
|
|
12903
13476
|
}
|
|
12904
13477
|
const parent = func.getParent();
|
|
12905
|
-
if (parent !== void 0 &&
|
|
13478
|
+
if (parent !== void 0 && Node54.isVariableDeclaration(parent)) {
|
|
12906
13479
|
const nameNode = parent.getNameNode();
|
|
12907
|
-
if (
|
|
13480
|
+
if (Node54.isIdentifier(nameNode)) {
|
|
12908
13481
|
return nameNode;
|
|
12909
13482
|
}
|
|
12910
13483
|
}
|
|
@@ -12913,10 +13486,10 @@ function wrapperNameNode(func) {
|
|
|
12913
13486
|
function enclosingCall(node) {
|
|
12914
13487
|
let current2 = node.getParent();
|
|
12915
13488
|
while (current2 !== void 0) {
|
|
12916
|
-
if (
|
|
13489
|
+
if (Node54.isCallExpression(current2)) {
|
|
12917
13490
|
return current2;
|
|
12918
13491
|
}
|
|
12919
|
-
if (
|
|
13492
|
+
if (Node54.isPropertyAccessExpression(current2)) {
|
|
12920
13493
|
current2 = current2.getParent();
|
|
12921
13494
|
continue;
|
|
12922
13495
|
}
|
|
@@ -12927,7 +13500,7 @@ function enclosingCall(node) {
|
|
|
12927
13500
|
function enclosingFunction(node) {
|
|
12928
13501
|
let current2 = node.getParent();
|
|
12929
13502
|
while (current2 !== void 0) {
|
|
12930
|
-
if (
|
|
13503
|
+
if (Node54.isFunctionDeclaration(current2) || Node54.isFunctionExpression(current2) || Node54.isArrowFunction(current2) || Node54.isMethodDeclaration(current2)) {
|
|
12931
13504
|
return current2;
|
|
12932
13505
|
}
|
|
12933
13506
|
current2 = current2.getParent();
|
|
@@ -12935,13 +13508,13 @@ function enclosingFunction(node) {
|
|
|
12935
13508
|
return null;
|
|
12936
13509
|
}
|
|
12937
13510
|
function literalOrTemplate(arg) {
|
|
12938
|
-
if (
|
|
13511
|
+
if (Node54.isStringLiteral(arg)) {
|
|
12939
13512
|
return arg.getLiteralValue();
|
|
12940
13513
|
}
|
|
12941
|
-
if (
|
|
13514
|
+
if (Node54.isNoSubstitutionTemplateLiteral(arg)) {
|
|
12942
13515
|
return arg.getLiteralValue();
|
|
12943
13516
|
}
|
|
12944
|
-
if (
|
|
13517
|
+
if (Node54.isTemplateExpression(arg)) {
|
|
12945
13518
|
let path11 = arg.getHead().getLiteralText();
|
|
12946
13519
|
for (const span of arg.getTemplateSpans()) {
|
|
12947
13520
|
path11 += `{${placeholderName(span.getExpression())}}`;
|
|
@@ -12952,13 +13525,13 @@ function literalOrTemplate(arg) {
|
|
|
12952
13525
|
return void 0;
|
|
12953
13526
|
}
|
|
12954
13527
|
function callerName(func) {
|
|
12955
|
-
if (
|
|
13528
|
+
if (Node54.isFunctionDeclaration(func) || Node54.isMethodDeclaration(func)) {
|
|
12956
13529
|
return func.getName() ?? "anonymous";
|
|
12957
13530
|
}
|
|
12958
13531
|
const parent = func.getParent();
|
|
12959
|
-
if (parent !== void 0 &&
|
|
13532
|
+
if (parent !== void 0 && Node54.isVariableDeclaration(parent)) {
|
|
12960
13533
|
const nameNode = parent.getNameNode();
|
|
12961
|
-
if (
|
|
13534
|
+
if (Node54.isIdentifier(nameNode)) {
|
|
12962
13535
|
return nameNode.getText();
|
|
12963
13536
|
}
|
|
12964
13537
|
}
|
|
@@ -13010,8 +13583,8 @@ function buildCallerSummary(wrapper, callerFunc, callExpr, path11, options) {
|
|
|
13010
13583
|
summary.confidence = { source: "inferred_static", level: "low" };
|
|
13011
13584
|
return summary;
|
|
13012
13585
|
}
|
|
13013
|
-
function named(summaries, workspace) {
|
|
13014
|
-
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));
|
|
13015
13588
|
nameSummaries(summaries, {
|
|
13016
13589
|
workspace: workspace ?? workspaceNameFor(projectRoot),
|
|
13017
13590
|
projectRoot
|
|
@@ -13142,7 +13715,29 @@ function createTypeScriptAdapter(config) {
|
|
|
13142
13715
|
if (config.onTiming !== void 0) {
|
|
13143
13716
|
config.onTiming(timer.report());
|
|
13144
13717
|
}
|
|
13145
|
-
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
|
+
);
|
|
13146
13741
|
}
|
|
13147
13742
|
let candidatePaths = null;
|
|
13148
13743
|
if (lazyEligible) {
|
|
@@ -13173,16 +13768,58 @@ function createTypeScriptAdapter(config) {
|
|
|
13173
13768
|
"mountPrefix",
|
|
13174
13769
|
() => buildMountPrefixIndex(packsByFile, resolution)
|
|
13175
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;
|
|
13176
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();
|
|
13177
13808
|
timer.time("extract per-file", () => {
|
|
13178
|
-
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
|
+
}
|
|
13179
13815
|
const applicablePacks = packsByFile.get(sourceFile);
|
|
13180
13816
|
if (applicablePacks === void 0) {
|
|
13181
13817
|
continue;
|
|
13182
13818
|
}
|
|
13183
13819
|
try {
|
|
13184
|
-
|
|
13185
|
-
|
|
13820
|
+
const walked = withDependencySink(
|
|
13821
|
+
sink,
|
|
13822
|
+
() => extractFromSourceFile(
|
|
13186
13823
|
sourceFile,
|
|
13187
13824
|
applicablePacks,
|
|
13188
13825
|
claimedUnits,
|
|
@@ -13192,6 +13829,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13192
13829
|
mountPrefixes
|
|
13193
13830
|
)
|
|
13194
13831
|
);
|
|
13832
|
+
for (const summary of walked) {
|
|
13833
|
+
ownersBySummary.set(summary, /* @__PURE__ */ new Set([rootPath]));
|
|
13834
|
+
}
|
|
13835
|
+
summaries.push(...walked);
|
|
13195
13836
|
} catch (error) {
|
|
13196
13837
|
if (!(error instanceof RangeError)) {
|
|
13197
13838
|
throw error;
|
|
@@ -13200,23 +13841,32 @@ function createTypeScriptAdapter(config) {
|
|
|
13200
13841
|
}
|
|
13201
13842
|
}
|
|
13202
13843
|
});
|
|
13844
|
+
const wrapperInput = reused === null ? summaries : [...summaries, ...reused.summaries];
|
|
13203
13845
|
const withWrappers = timer.time(
|
|
13204
13846
|
"expandWrapperCallers",
|
|
13205
|
-
() => expandWrapperCallers(
|
|
13847
|
+
() => expandWrapperCallers(wrapperInput, project, config.extractorOptions)
|
|
13206
13848
|
);
|
|
13849
|
+
const pipeline = reused === null ? withWrappers : [...summaries, ...withWrappers.slice(wrapperInput.length)];
|
|
13207
13850
|
const withSubUnits = timer.time(
|
|
13208
13851
|
"synthesizeSubUnits",
|
|
13209
13852
|
() => synthesizeSubUnits(
|
|
13210
|
-
|
|
13853
|
+
pipeline,
|
|
13211
13854
|
project,
|
|
13212
13855
|
config.frameworks,
|
|
13213
13856
|
config.extractorOptions,
|
|
13214
|
-
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
|
+
}
|
|
13215
13864
|
)
|
|
13216
13865
|
);
|
|
13217
13866
|
const closureFacts = {
|
|
13218
13867
|
db: new Database5(),
|
|
13219
|
-
unitKeyBySummary: /* @__PURE__ */ new Map()
|
|
13868
|
+
unitKeyBySummary: /* @__PURE__ */ new Map(),
|
|
13869
|
+
...caching ? { filesByKey: /* @__PURE__ */ new Map() } : {}
|
|
13220
13870
|
};
|
|
13221
13871
|
const withClosure = config.includeReachable !== false ? timer.time(
|
|
13222
13872
|
"expandReachableClosure",
|
|
@@ -13234,12 +13884,28 @@ function createTypeScriptAdapter(config) {
|
|
|
13234
13884
|
access: collectAccessRecognizers(config.frameworks, tallies),
|
|
13235
13885
|
resolveWrittenValue: (value) => resolution.resolveWrittenValue(value),
|
|
13236
13886
|
resolveCallable: (value, alsoFrom) => resolution.resolveCallable(value, alsoFrom)
|
|
13237
|
-
}
|
|
13887
|
+
},
|
|
13888
|
+
// Reached units the cache already serves emit nothing,
|
|
13889
|
+
// the way a cold run's seeds do not.
|
|
13890
|
+
reused?.summaries ?? []
|
|
13238
13891
|
)
|
|
13239
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
|
+
);
|
|
13240
13906
|
const enriched = timer.time(
|
|
13241
13907
|
"enrichRethrows",
|
|
13242
|
-
() => enrichRethrows(
|
|
13908
|
+
() => enrichRethrows(merged.summaries, project, closureFacts)
|
|
13243
13909
|
);
|
|
13244
13910
|
if (config.includeReachable !== false) {
|
|
13245
13911
|
timer.time(
|
|
@@ -13255,6 +13921,10 @@ function createTypeScriptAdapter(config) {
|
|
|
13255
13921
|
"emitLibraryEnvReadMarkers",
|
|
13256
13922
|
() => emitLibraryEnvReadMarkers(enriched, project, config.frameworks)
|
|
13257
13923
|
);
|
|
13924
|
+
timer.time(
|
|
13925
|
+
"liftSchemasOntoDocuments",
|
|
13926
|
+
() => liftSchemasOntoDocuments(enriched)
|
|
13927
|
+
);
|
|
13258
13928
|
timer.time(
|
|
13259
13929
|
"stampGraphqlClientRefs",
|
|
13260
13930
|
() => stampGraphqlClientRefs(
|
|
@@ -13264,12 +13934,45 @@ function createTypeScriptAdapter(config) {
|
|
|
13264
13934
|
resolution
|
|
13265
13935
|
)
|
|
13266
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
|
+
);
|
|
13267
13953
|
await timer.timeAsync("cache.write", async () => {
|
|
13268
|
-
if (enriched.length === 0) {
|
|
13954
|
+
if (!caching || enriched.length === 0) {
|
|
13269
13955
|
return;
|
|
13270
13956
|
}
|
|
13271
13957
|
try {
|
|
13272
|
-
|
|
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);
|
|
13273
13976
|
} catch {
|
|
13274
13977
|
}
|
|
13275
13978
|
});
|
|
@@ -13282,7 +13985,7 @@ function createTypeScriptAdapter(config) {
|
|
|
13282
13985
|
packs: config.frameworks,
|
|
13283
13986
|
tallies,
|
|
13284
13987
|
filesInProject: tsconfigFileList?.length ?? null,
|
|
13285
|
-
filesWalked:
|
|
13988
|
+
filesWalked: walkList.length,
|
|
13286
13989
|
summaries: enriched,
|
|
13287
13990
|
tsConfigFilePath: config.tsConfigFilePath,
|
|
13288
13991
|
projectRoot: commonDirectoryOf(
|
|
@@ -13302,7 +14005,200 @@ function createTypeScriptAdapter(config) {
|
|
|
13302
14005
|
}
|
|
13303
14006
|
};
|
|
13304
14007
|
}
|
|
13305
|
-
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) {
|
|
13306
14202
|
const packByRecognition = /* @__PURE__ */ new Map();
|
|
13307
14203
|
for (const pack of frameworks) {
|
|
13308
14204
|
packByRecognition.set(pack.name, pack);
|
|
@@ -13345,6 +14241,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13345
14241
|
);
|
|
13346
14242
|
if (summary !== null) {
|
|
13347
14243
|
synthesized.push(summary);
|
|
14244
|
+
onCreated?.(summary, parent);
|
|
13348
14245
|
}
|
|
13349
14246
|
}
|
|
13350
14247
|
}
|
|
@@ -13353,14 +14250,7 @@ function synthesizeSubUnits(summaries, project, frameworks, options, tallies) {
|
|
|
13353
14250
|
var DEFAULT_SUB_UNIT_TERMINALS = [
|
|
13354
14251
|
{ kind: "return", match: { type: "returnStatement" }, extraction: {} },
|
|
13355
14252
|
{ kind: "throw", match: { type: "throwExpression" }, extraction: {} },
|
|
13356
|
-
|
|
13357
|
-
// fall-through gives it a default transition. HTTP packs do not opt in:
|
|
13358
|
-
// a handler that sends no response should come out with none.
|
|
13359
|
-
{
|
|
13360
|
-
kind: "return",
|
|
13361
|
-
match: { type: "functionFallthrough" },
|
|
13362
|
-
extraction: {}
|
|
13363
|
-
}
|
|
14253
|
+
FUNCTION_FALLTHROUGH_TERMINAL
|
|
13364
14254
|
];
|
|
13365
14255
|
var DEFAULT_SUB_UNIT_INPUT_MAPPING = {
|
|
13366
14256
|
type: "positionalParams",
|
|
@@ -13504,10 +14394,10 @@ function findNearestTsconfig(startDir) {
|
|
|
13504
14394
|
}
|
|
13505
14395
|
|
|
13506
14396
|
// src/configuredCall.ts
|
|
13507
|
-
import { Node as
|
|
14397
|
+
import { Node as Node55 } from "ts-morph";
|
|
13508
14398
|
function readConfiguredCall(call, ctx, spec) {
|
|
13509
14399
|
const callee = call.getExpression();
|
|
13510
|
-
if (!
|
|
14400
|
+
if (!Node55.isPropertyAccessExpression(callee)) {
|
|
13511
14401
|
return null;
|
|
13512
14402
|
}
|
|
13513
14403
|
if (callee.getName() !== spec.method) {
|
|
@@ -13552,10 +14442,10 @@ function readStringArg(arg) {
|
|
|
13552
14442
|
}
|
|
13553
14443
|
function rootIdentifier(node) {
|
|
13554
14444
|
let current2 = node;
|
|
13555
|
-
while (
|
|
14445
|
+
while (Node55.isPropertyAccessExpression(current2)) {
|
|
13556
14446
|
current2 = current2.getExpression();
|
|
13557
14447
|
}
|
|
13558
|
-
return
|
|
14448
|
+
return Node55.isIdentifier(current2) ? current2 : null;
|
|
13559
14449
|
}
|
|
13560
14450
|
|
|
13561
14451
|
// src/packHealth.ts
|
|
@@ -13671,7 +14561,8 @@ function formatPackHealth(checks, audiences) {
|
|
|
13671
14561
|
}
|
|
13672
14562
|
|
|
13673
14563
|
// src/resolve/readName.ts
|
|
13674
|
-
import { Node as
|
|
14564
|
+
import { Node as Node56, SyntaxKind as SyntaxKind12 } from "ts-morph";
|
|
14565
|
+
import { patternHole, referenceName } from "@suss/behavioral-ir";
|
|
13675
14566
|
var MAX_HELPER_HOPS = 2;
|
|
13676
14567
|
var UNNAMED_HOLE = "param";
|
|
13677
14568
|
function readName(expr, options = {}) {
|
|
@@ -13685,6 +14576,14 @@ function readName(expr, options = {}) {
|
|
|
13685
14576
|
if (name !== null || options.unsettled !== "reference") {
|
|
13686
14577
|
return name;
|
|
13687
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
|
+
}
|
|
13688
14587
|
const asked = holeName(expr, {
|
|
13689
14588
|
resolve: () => null,
|
|
13690
14589
|
bindings: /* @__PURE__ */ new Map(),
|
|
@@ -13692,7 +14591,25 @@ function readName(expr, options = {}) {
|
|
|
13692
14591
|
seen: /* @__PURE__ */ new Set(),
|
|
13693
14592
|
insideHole: true
|
|
13694
14593
|
});
|
|
13695
|
-
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
|
+
);
|
|
13696
14613
|
}
|
|
13697
14614
|
function read(expr, ctx) {
|
|
13698
14615
|
if (ctx.seen.has(expr)) {
|
|
@@ -13700,25 +14617,25 @@ function read(expr, ctx) {
|
|
|
13700
14617
|
}
|
|
13701
14618
|
const seen = new Set(ctx.seen).add(expr);
|
|
13702
14619
|
const inner = { ...ctx, seen };
|
|
13703
|
-
if (
|
|
14620
|
+
if (Node56.isStringLiteral(expr) || Node56.isNoSubstitutionTemplateLiteral(expr)) {
|
|
13704
14621
|
return expr.getLiteralValue();
|
|
13705
14622
|
}
|
|
13706
|
-
if (
|
|
14623
|
+
if (Node56.isNumericLiteral(expr)) {
|
|
13707
14624
|
return expr.getLiteralText();
|
|
13708
14625
|
}
|
|
13709
|
-
if (
|
|
14626
|
+
if (Node56.isTemplateExpression(expr)) {
|
|
13710
14627
|
return fromTemplate(expr, inner);
|
|
13711
14628
|
}
|
|
13712
|
-
if (
|
|
14629
|
+
if (Node56.isParenthesizedExpression(expr)) {
|
|
13713
14630
|
return read(expr.getExpression(), inner);
|
|
13714
14631
|
}
|
|
13715
|
-
if (
|
|
14632
|
+
if (Node56.isBinaryExpression(expr)) {
|
|
13716
14633
|
return fromBinary(expr, inner);
|
|
13717
14634
|
}
|
|
13718
|
-
if (
|
|
14635
|
+
if (Node56.isCallExpression(expr)) {
|
|
13719
14636
|
return fromCall(expr, inner);
|
|
13720
14637
|
}
|
|
13721
|
-
if (
|
|
14638
|
+
if (Node56.isIdentifier(expr)) {
|
|
13722
14639
|
const only = boundOnce(expr, ctx);
|
|
13723
14640
|
if (only !== null) {
|
|
13724
14641
|
return read(only.node, { ...inner, bindings: only.scope });
|
|
@@ -13728,7 +14645,7 @@ function read(expr, ctx) {
|
|
|
13728
14645
|
return written === null || written === expr ? null : read(written, inner);
|
|
13729
14646
|
}
|
|
13730
14647
|
function fromTemplate(expr, ctx) {
|
|
13731
|
-
if (!
|
|
14648
|
+
if (!Node56.isTemplateExpression(expr)) {
|
|
13732
14649
|
return null;
|
|
13733
14650
|
}
|
|
13734
14651
|
let name = expr.getHead().getLiteralText();
|
|
@@ -13739,28 +14656,28 @@ function fromTemplate(expr, ctx) {
|
|
|
13739
14656
|
return name;
|
|
13740
14657
|
}
|
|
13741
14658
|
function fromBinary(expr, ctx) {
|
|
13742
|
-
if (!
|
|
14659
|
+
if (!Node56.isBinaryExpression(expr)) {
|
|
13743
14660
|
return null;
|
|
13744
14661
|
}
|
|
13745
14662
|
const operator = expr.getOperatorToken().getKind();
|
|
13746
|
-
if (operator ===
|
|
14663
|
+
if (operator === SyntaxKind12.BarBarToken || operator === SyntaxKind12.QuestionQuestionToken) {
|
|
13747
14664
|
return ctx.insideHole ? null : read(expr.getRight(), ctx);
|
|
13748
14665
|
}
|
|
13749
|
-
if (operator !==
|
|
14666
|
+
if (operator !== SyntaxKind12.PlusToken) {
|
|
13750
14667
|
return null;
|
|
13751
14668
|
}
|
|
13752
14669
|
const parts = { ...ctx, insideHole: true };
|
|
13753
14670
|
return readOrHole(expr.getLeft(), parts) + readOrHole(expr.getRight(), parts);
|
|
13754
14671
|
}
|
|
13755
14672
|
function fromCall(expr, ctx) {
|
|
13756
|
-
if (!
|
|
14673
|
+
if (!Node56.isCallExpression(expr)) {
|
|
13757
14674
|
return null;
|
|
13758
14675
|
}
|
|
13759
14676
|
const callee = expr.getExpression();
|
|
13760
|
-
if (
|
|
14677
|
+
if (Node56.isPropertyAccessExpression(callee) && callee.getName() === "join") {
|
|
13761
14678
|
return fromJoin(callee.getExpression(), expr.getArguments(), ctx);
|
|
13762
14679
|
}
|
|
13763
|
-
if (
|
|
14680
|
+
if (Node56.isIdentifier(callee) && callee.getText() === "String") {
|
|
13764
14681
|
const only = expr.getArguments()[0];
|
|
13765
14682
|
return only === void 0 ? null : readOrHole(only, ctx);
|
|
13766
14683
|
}
|
|
@@ -13779,7 +14696,7 @@ function fromCall(expr, ctx) {
|
|
|
13779
14696
|
}
|
|
13780
14697
|
function fromJoin(subject, args, ctx) {
|
|
13781
14698
|
const separator = args[0];
|
|
13782
|
-
if (separator === void 0 || !
|
|
14699
|
+
if (separator === void 0 || !Node56.isStringLiteral(separator)) {
|
|
13783
14700
|
return null;
|
|
13784
14701
|
}
|
|
13785
14702
|
const parts = elementsOf(subject, ctx);
|
|
@@ -13795,17 +14712,17 @@ function fromJoin(subject, args, ctx) {
|
|
|
13795
14712
|
).join(separator.getLiteralValue());
|
|
13796
14713
|
}
|
|
13797
14714
|
function elementsOf(subject, ctx) {
|
|
13798
|
-
if (
|
|
14715
|
+
if (Node56.isArrayLiteralExpression(subject)) {
|
|
13799
14716
|
return subject.getElements().map((element) => here(element, ctx));
|
|
13800
14717
|
}
|
|
13801
|
-
if (
|
|
14718
|
+
if (Node56.isCallExpression(subject)) {
|
|
13802
14719
|
const callee = subject.getExpression();
|
|
13803
|
-
if (
|
|
14720
|
+
if (Node56.isPropertyAccessExpression(callee) && callee.getName() === "map") {
|
|
13804
14721
|
return elementsOf(callee.getExpression(), ctx);
|
|
13805
14722
|
}
|
|
13806
14723
|
return null;
|
|
13807
14724
|
}
|
|
13808
|
-
if (!
|
|
14725
|
+
if (!Node56.isIdentifier(subject)) {
|
|
13809
14726
|
return null;
|
|
13810
14727
|
}
|
|
13811
14728
|
const bound = ctx.bindings.get(subject.getText());
|
|
@@ -13813,7 +14730,7 @@ function elementsOf(subject, ctx) {
|
|
|
13813
14730
|
return null;
|
|
13814
14731
|
}
|
|
13815
14732
|
const only = bound.length === 1 ? bound[0] : void 0;
|
|
13816
|
-
return only !== void 0 &&
|
|
14733
|
+
return only !== void 0 && Node56.isArrayLiteralExpression(only.node) ? only.node.getElements().map((element) => here(element, ctx)) : bound;
|
|
13817
14734
|
}
|
|
13818
14735
|
function singleReturnBody(callee, ctx) {
|
|
13819
14736
|
const declaration = declarationOf2(callee, ctx);
|
|
@@ -13828,22 +14745,22 @@ function singleReturnBody(callee, ctx) {
|
|
|
13828
14745
|
if (body === void 0) {
|
|
13829
14746
|
return null;
|
|
13830
14747
|
}
|
|
13831
|
-
if (
|
|
14748
|
+
if (Node56.isExpression(body)) {
|
|
13832
14749
|
return { parameters, returned: body };
|
|
13833
14750
|
}
|
|
13834
|
-
if (!
|
|
14751
|
+
if (!Node56.isBlock(body)) {
|
|
13835
14752
|
return null;
|
|
13836
14753
|
}
|
|
13837
14754
|
const statements = body.getStatements();
|
|
13838
14755
|
const only = statements[0];
|
|
13839
|
-
if (statements.length !== 1 || only === void 0 || !
|
|
14756
|
+
if (statements.length !== 1 || only === void 0 || !Node56.isReturnStatement(only)) {
|
|
13840
14757
|
return null;
|
|
13841
14758
|
}
|
|
13842
14759
|
const returned = only.getExpression();
|
|
13843
14760
|
return returned === void 0 ? null : { parameters, returned };
|
|
13844
14761
|
}
|
|
13845
14762
|
function declarationOf2(callee, ctx) {
|
|
13846
|
-
const symbol =
|
|
14763
|
+
const symbol = Node56.isPropertyAccessExpression(callee) ? callee.getNameNode().getSymbol() : callee.getSymbol();
|
|
13847
14764
|
const declarations = symbol?.getAliasedSymbol()?.getDeclarations() ?? symbol?.getDeclarations() ?? [];
|
|
13848
14765
|
for (const declaration of declarations) {
|
|
13849
14766
|
const callable = asCallable(declaration);
|
|
@@ -13855,14 +14772,14 @@ function declarationOf2(callee, ctx) {
|
|
|
13855
14772
|
return written === null || written === callee ? null : declarationOf2(written, { ...ctx, resolve: () => null });
|
|
13856
14773
|
}
|
|
13857
14774
|
function asCallable(declaration) {
|
|
13858
|
-
if (
|
|
14775
|
+
if (Node56.isFunctionDeclaration(declaration) || Node56.isMethodDeclaration(declaration) || Node56.isArrowFunction(declaration) || Node56.isFunctionExpression(declaration)) {
|
|
13859
14776
|
return declaration;
|
|
13860
14777
|
}
|
|
13861
|
-
if (!
|
|
14778
|
+
if (!Node56.isVariableDeclaration(declaration)) {
|
|
13862
14779
|
return null;
|
|
13863
14780
|
}
|
|
13864
14781
|
const initializer = declaration.getInitializer();
|
|
13865
|
-
if (initializer !== void 0 && (
|
|
14782
|
+
if (initializer !== void 0 && (Node56.isArrowFunction(initializer) || Node56.isFunctionExpression(initializer))) {
|
|
13866
14783
|
return initializer;
|
|
13867
14784
|
}
|
|
13868
14785
|
return null;
|
|
@@ -13884,22 +14801,22 @@ function here(node, ctx) {
|
|
|
13884
14801
|
return { node, scope: ctx.bindings };
|
|
13885
14802
|
}
|
|
13886
14803
|
function boundOnce(expr, ctx) {
|
|
13887
|
-
const bound =
|
|
14804
|
+
const bound = Node56.isIdentifier(expr) ? ctx.bindings.get(expr.getText()) : void 0;
|
|
13888
14805
|
return bound !== void 0 && bound.length === 1 ? bound[0] : null;
|
|
13889
14806
|
}
|
|
13890
14807
|
function readOrHole(expr, ctx) {
|
|
13891
14808
|
const name = read(expr, ctx);
|
|
13892
|
-
return name ??
|
|
14809
|
+
return name ?? patternHole(holeName(expr, ctx));
|
|
13893
14810
|
}
|
|
13894
14811
|
function holeName(expr, ctx) {
|
|
13895
14812
|
const bound = boundOnce(expr, ctx);
|
|
13896
14813
|
if (bound !== null) {
|
|
13897
14814
|
return holeName(bound.node, { ...ctx, bindings: bound.scope });
|
|
13898
14815
|
}
|
|
13899
|
-
if (
|
|
14816
|
+
if (Node56.isIdentifier(expr)) {
|
|
13900
14817
|
return expr.getText();
|
|
13901
14818
|
}
|
|
13902
|
-
if (
|
|
14819
|
+
if (Node56.isPropertyAccessExpression(expr)) {
|
|
13903
14820
|
return expr.getName();
|
|
13904
14821
|
}
|
|
13905
14822
|
return UNNAMED_HOLE;
|