@suss/adapter-typescript 0.37.0 → 0.37.1

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.
Files changed (3) hide show
  1. package/dist/index.cjs +1800 -1508
  2. package/dist/index.js +730 -424
  3. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
  import path15 from "path";
3
3
  import {
4
4
  Node as Node82,
5
- Project as Project2
5
+ Project as Project2,
6
+ SyntaxKind as SyntaxKind31
6
7
  } from "ts-morph";
7
8
  import {
8
9
  BOUNDARY_ROLE,
@@ -37,7 +38,8 @@ import { force as force8, hostOf as hostOf2, literalOf as literalOf6, pathOf as
37
38
 
38
39
  // src/assembly.ts
39
40
  import {
40
- Node as Node67
41
+ Node as Node67,
42
+ SyntaxKind as SyntaxKind27
41
43
  } from "ts-morph";
42
44
  import { firesOn, runsBefore, splitAtHandOffs } from "@suss/extractor";
43
45
 
@@ -47,11 +49,11 @@ import {
47
49
  } from "ts-morph";
48
50
 
49
51
  // src/predicates.ts
50
- import { Node as Node45, SyntaxKind as SyntaxKind12 } from "ts-morph";
52
+ import { Node as Node45, SyntaxKind as SyntaxKind19 } from "ts-morph";
51
53
  import { replacePredicateRefs } from "@suss/behavioral-ir";
52
54
 
53
55
  // src/resolve/astResolve.ts
54
- import { Node as Node42, SyntaxKind as SyntaxKind11 } from "ts-morph";
56
+ import { Node as Node42, SyntaxKind as SyntaxKind18 } from "ts-morph";
55
57
 
56
58
  // src/walk/nodeKeys.ts
57
59
  import { declarationKey } from "@suss/behavioral-ir";
@@ -138,7 +140,7 @@ function passesValueThrough(node) {
138
140
  }
139
141
 
140
142
  // src/resolve/functionBehind.ts
141
- import { Node as Node41, SyntaxKind as SyntaxKind10 } from "ts-morph";
143
+ import { Node as Node41, SyntaxKind as SyntaxKind17 } from "ts-morph";
142
144
  import { normalizeCalleeText } from "@suss/behavioral-ir";
143
145
 
144
146
  // src/facts/store.ts
@@ -179,7 +181,8 @@ import path from "path";
179
181
 
180
182
  // src/discovery/shared.ts
181
183
  import {
182
- Node as Node2
184
+ Node as Node2,
185
+ SyntaxKind
183
186
  } from "ts-morph";
184
187
  function unitNode(unit) {
185
188
  return unit.func ?? unit.announcedAt ?? null;
@@ -218,8 +221,15 @@ function exportIdentityOf(unit) {
218
221
  return "";
219
222
  }
220
223
  function isFunctionRoot(node) {
221
- return Node2.isFunctionDeclaration(node) || Node2.isFunctionExpression(node) || Node2.isArrowFunction(node) || Node2.isMethodDeclaration(node) || Node2.isConstructorDeclaration(node);
222
- }
224
+ return FUNCTION_ROOT_KINDS.has(node.getKind());
225
+ }
226
+ var FUNCTION_ROOT_KINDS = /* @__PURE__ */ new Set([
227
+ SyntaxKind.FunctionDeclaration,
228
+ SyntaxKind.FunctionExpression,
229
+ SyntaxKind.ArrowFunction,
230
+ SyntaxKind.MethodDeclaration,
231
+ SyntaxKind.Constructor
232
+ ]);
223
233
  function declarationCarryingTheBody(declaration) {
224
234
  if (!Node2.isFunctionDeclaration(declaration) && !Node2.isMethodDeclaration(declaration) && !Node2.isConstructorDeclaration(declaration)) {
225
235
  return declaration;
@@ -300,6 +310,61 @@ function createPerFileCache() {
300
310
  };
301
311
  }
302
312
 
313
+ // src/walk/rawDescent.ts
314
+ import {
315
+ ts
316
+ } from "ts-morph";
317
+ function statementsOfKind(file, kind) {
318
+ const found = [];
319
+ for (const raw of file.compilerNode.statements) {
320
+ if (raw.kind === kind) {
321
+ found.push(wrapperOf(file, raw));
322
+ }
323
+ }
324
+ return found;
325
+ }
326
+ function forEachDescendantOfKinds(root, kinds, visit, skips = runsNothing) {
327
+ forEachDescendantWhere(root, (raw) => kinds.has(raw.kind), visit, skips);
328
+ }
329
+ function forEachDescendantWhere(root, accepts, visit, skips = runsNothing) {
330
+ const walk = (raw) => {
331
+ if (skips(raw)) {
332
+ return void 0;
333
+ }
334
+ if (accepts(raw) && visit(wrapperOf(root, raw)) === true) {
335
+ return void 0;
336
+ }
337
+ ts.forEachChild(raw, walk);
338
+ return void 0;
339
+ };
340
+ ts.forEachChild(root.compilerNode, walk);
341
+ }
342
+ function runsNothing(raw) {
343
+ return isTypeOnlySyntax(raw) || isAmbient(raw);
344
+ }
345
+ function skipsNothing() {
346
+ return false;
347
+ }
348
+ function isTypeOnlySyntax(raw) {
349
+ return raw.kind >= ts.SyntaxKind.FirstTypeNode && raw.kind <= ts.SyntaxKind.LastTypeNode || TYPE_DECLARATIONS.has(raw.kind);
350
+ }
351
+ var TYPE_DECLARATIONS = /* @__PURE__ */ new Set([
352
+ ts.SyntaxKind.TypeAliasDeclaration,
353
+ ts.SyntaxKind.InterfaceDeclaration,
354
+ ts.SyntaxKind.TypeParameter
355
+ ]);
356
+ function isAmbient(raw) {
357
+ if (!ts.canHaveModifiers(raw)) {
358
+ return false;
359
+ }
360
+ return ts.getModifiers(raw)?.some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword) ?? false;
361
+ }
362
+ function wrapperOf(anchor, raw) {
363
+ return anchor._getNodeFromCompilerNode(
364
+ raw
365
+ );
366
+ }
367
+
303
368
  // src/bootstrap/sourceFileLookup.ts
304
369
  function sourceFileFor(project, moduleKey) {
305
370
  if (!isPathKey(moduleKey)) {
@@ -403,17 +468,21 @@ function spanKey(span) {
403
468
  var functionIndexes = createPerFileCache();
404
469
  function indexFunctions(sf) {
405
470
  const index = /* @__PURE__ */ new Map();
406
- sf.forEachDescendant((node) => {
407
- if (!isFunctionRoot(node)) {
408
- return;
409
- }
410
- const bySpan = spanKey({ start: node.getStart(), end: node.getEnd() });
411
- index.set(bySpan, node);
412
- const key = rangeKey({ start: startLineOf(node), end: endLineOf(node) });
413
- if (!index.has(key)) {
414
- index.set(key, node);
415
- }
416
- });
471
+ forEachDescendantOfKinds(
472
+ sf,
473
+ FUNCTION_ROOT_KINDS,
474
+ (found) => {
475
+ const node = found;
476
+ const bySpan = spanKey({ start: node.getStart(), end: node.getEnd() });
477
+ index.set(bySpan, node);
478
+ const key = rangeKey({ start: startLineOf(node), end: endLineOf(node) });
479
+ if (!index.has(key)) {
480
+ index.set(key, node);
481
+ }
482
+ return false;
483
+ },
484
+ isTypeOnlySyntax
485
+ );
417
486
  return index;
418
487
  }
419
488
 
@@ -442,15 +511,15 @@ function recordUnitClaim(key, pack) {
442
511
  }
443
512
 
444
513
  // src/facts/containerWrites.ts
445
- import { Node as Node8, SyntaxKind as SyntaxKind4 } from "ts-morph";
514
+ import { Node as Node8, SyntaxKind as SyntaxKind8 } from "ts-morph";
446
515
 
447
516
  // src/facts/extract.ts
448
517
  import { posix } from "path";
449
518
  import {
450
519
  ModuleDeclarationKind,
451
520
  Node as Node6,
452
- SyntaxKind as SyntaxKind2,
453
- ts as ts2
521
+ SyntaxKind as SyntaxKind6,
522
+ ts as ts4
454
523
  } from "ts-morph";
455
524
  import {
456
525
  addEntryRows,
@@ -467,12 +536,12 @@ import {
467
536
  } from "@suss/resolution";
468
537
 
469
538
  // src/moduleExports.ts
470
- import { Node as Node3 } from "ts-morph";
539
+ import { Node as Node3, SyntaxKind as SyntaxKind4 } from "ts-morph";
471
540
 
472
541
  // src/bootstrap/lazyProjectInit.ts
473
542
  import fs2 from "fs/promises";
474
543
  import path3 from "path";
475
- import { ts } from "ts-morph";
544
+ import { ts as ts2 } from "ts-morph";
476
545
 
477
546
  // src/facts/generatedModules.ts
478
547
  import fs from "fs";
@@ -558,6 +627,7 @@ function generatedModulesOf(packs) {
558
627
  }
559
628
 
560
629
  // src/facts/moduleGraph.ts
630
+ import { SyntaxKind as SyntaxKind2 } from "ts-morph";
561
631
  import { Database, evaluate, lit, rule, variable as v } from "@suss/datalog";
562
632
  var NO_GENERATOR = new GeneratedModules([]);
563
633
  var REACH_RULES = [
@@ -762,10 +832,16 @@ var ModuleGraph = class {
762
832
  };
763
833
  function readModuleSpecifiers(sourceFile) {
764
834
  const specifiers = [];
765
- for (const importDecl of sourceFile.getImportDeclarations()) {
835
+ for (const importDecl of statementsOfKind(
836
+ sourceFile,
837
+ SyntaxKind2.ImportDeclaration
838
+ )) {
766
839
  specifiers.push(importDecl.getModuleSpecifierValue());
767
840
  }
768
- for (const exportDecl of sourceFile.getExportDeclarations()) {
841
+ for (const exportDecl of statementsOfKind(
842
+ sourceFile,
843
+ SyntaxKind2.ExportDeclaration
844
+ )) {
769
845
  const specifier = exportDecl.getModuleSpecifierValue();
770
846
  if (specifier !== void 0) {
771
847
  specifiers.push(specifier);
@@ -785,13 +861,19 @@ function resolveModuleSpecifiers(sourceFile) {
785
861
  }
786
862
  function resolveModuleSpecifiersOf(sourceFile) {
787
863
  const resolved = [];
788
- for (const importDecl of sourceFile.getImportDeclarations()) {
864
+ for (const importDecl of statementsOfKind(
865
+ sourceFile,
866
+ SyntaxKind2.ImportDeclaration
867
+ )) {
789
868
  const target = importDecl.getModuleSpecifierSourceFile();
790
869
  if (target !== void 0) {
791
870
  resolved.push(target);
792
871
  }
793
872
  }
794
- for (const exportDecl of sourceFile.getExportDeclarations()) {
873
+ for (const exportDecl of statementsOfKind(
874
+ sourceFile,
875
+ SyntaxKind2.ExportDeclaration
876
+ )) {
795
877
  const target = exportDecl.getModuleSpecifierSourceFile();
796
878
  if (target !== void 0) {
797
879
  resolved.push(target);
@@ -809,6 +891,7 @@ function namesAnyPackage(specifiers, names) {
809
891
  }
810
892
 
811
893
  // src/bootstrap/preFilter.ts
894
+ import { SyntaxKind as SyntaxKind3 } from "ts-morph";
812
895
  function computePackApplicability(sourceFiles, packs, resolution) {
813
896
  const ungatedPacks = [];
814
897
  const gatedPacks = [];
@@ -828,7 +911,9 @@ function computePackApplicability(sourceFiles, packs, resolution) {
828
911
  for (const sf of sourceFiles) {
829
912
  importsByFile.set(
830
913
  sf,
831
- sf.getImportDeclarations().map((d) => d.getModuleSpecifierValue())
914
+ statementsOfKind(sf, SyntaxKind3.ImportDeclaration).map(
915
+ (d) => d.getModuleSpecifierValue()
916
+ )
832
917
  );
833
918
  }
834
919
  }
@@ -1088,7 +1173,7 @@ function resolutionCacheFor(project, options) {
1088
1173
  if (existing !== void 0) {
1089
1174
  return existing;
1090
1175
  }
1091
- const fresh = ts.createModuleResolutionCache(
1176
+ const fresh = ts2.createModuleResolutionCache(
1092
1177
  project.getFileSystem().getCurrentDirectory(),
1093
1178
  (name) => name,
1094
1179
  options
@@ -1122,11 +1207,11 @@ function readSpecifierPaths(project, filePath, options, host) {
1122
1207
  if (text3 === null) {
1123
1208
  return [];
1124
1209
  }
1125
- const scanned = ts.preProcessFile(text3, true, true);
1210
+ const scanned = ts2.preProcessFile(text3, true, true);
1126
1211
  const cache = resolutionCacheFor(project, options);
1127
1212
  const paths = [];
1128
1213
  for (const imported of scanned.importedFiles) {
1129
- const resolved = ts.resolveModuleName(
1214
+ const resolved = ts2.resolveModuleName(
1130
1215
  imported.fileName,
1131
1216
  filePath,
1132
1217
  options,
@@ -1152,13 +1237,13 @@ function readFileText(project, filePath) {
1152
1237
  }
1153
1238
  function parseTsconfig(tsConfigFilePath, seen = /* @__PURE__ */ new Set()) {
1154
1239
  seen.add(tsConfigFilePath);
1155
- const configFile = ts.readConfigFile(tsConfigFilePath, ts.sys.readFile);
1240
+ const configFile = ts2.readConfigFile(tsConfigFilePath, ts2.sys.readFile);
1156
1241
  if (configFile.error !== void 0) {
1157
1242
  return { fileNames: [], options: {} };
1158
1243
  }
1159
- const parsed = ts.parseJsonConfigFileContent(
1244
+ const parsed = ts2.parseJsonConfigFileContent(
1160
1245
  configFile.config,
1161
- ts.sys,
1246
+ ts2.sys,
1162
1247
  path3.dirname(tsConfigFilePath),
1163
1248
  /*existingOptions*/
1164
1249
  void 0,
@@ -1167,7 +1252,7 @@ function parseTsconfig(tsConfigFilePath, seen = /* @__PURE__ */ new Set()) {
1167
1252
  if (parsed.fileNames.length > 0) {
1168
1253
  return { fileNames: parsed.fileNames, options: parsed.options };
1169
1254
  }
1170
- const referenced = (parsed.projectReferences ?? []).map((reference) => ts.resolveProjectReferencePath(reference)).filter((referencePath) => !seen.has(referencePath)).map((referencePath) => parseTsconfig(referencePath, seen));
1255
+ const referenced = (parsed.projectReferences ?? []).map((reference) => ts2.resolveProjectReferencePath(reference)).filter((referencePath) => !seen.has(referencePath)).map((referencePath) => parseTsconfig(referencePath, seen));
1171
1256
  const fileNames = [
1172
1257
  ...new Set(referenced.flatMap((reference) => reference.fileNames))
1173
1258
  ];
@@ -1241,17 +1326,17 @@ function addImportersOfMatches(fileImports, matched, options) {
1241
1326
  }
1242
1327
  function internalSpecifierResolver(files, options) {
1243
1328
  const fileSet = new Set(files);
1244
- const cache = ts.createModuleResolutionCache(
1245
- ts.sys.getCurrentDirectory(),
1329
+ const cache = ts2.createModuleResolutionCache(
1330
+ ts2.sys.getCurrentDirectory(),
1246
1331
  (name) => name,
1247
1332
  options
1248
1333
  );
1249
1334
  return (fromFile, spec) => {
1250
- const resolved = ts.resolveModuleName(
1335
+ const resolved = ts2.resolveModuleName(
1251
1336
  spec,
1252
1337
  fromFile,
1253
1338
  options,
1254
- ts.sys,
1339
+ ts2.sys,
1255
1340
  cache
1256
1341
  ).resolvedModule?.resolvedFileName;
1257
1342
  if (resolved === void 0) {
@@ -1260,7 +1345,7 @@ function internalSpecifierResolver(files, options) {
1260
1345
  if (fileSet.has(resolved)) {
1261
1346
  return resolved;
1262
1347
  }
1263
- const real = ts.sys.realpath?.(resolved) ?? resolved;
1348
+ const real = ts2.sys.realpath?.(resolved) ?? resolved;
1264
1349
  return fileSet.has(real) ? real : null;
1265
1350
  };
1266
1351
  }
@@ -1295,7 +1380,7 @@ async function readImportsConcurrently(paths, marks) {
1295
1380
  const p = paths[i];
1296
1381
  try {
1297
1382
  const text3 = await fs2.readFile(p, "utf-8");
1298
- const pre = ts.preProcessFile(text3, true, false);
1383
+ const pre = ts2.preProcessFile(text3, true, false);
1299
1384
  results[i] = {
1300
1385
  path: p,
1301
1386
  importedModules: pre.importedFiles.map((f) => f.fileName),
@@ -1418,7 +1503,7 @@ function reExportShapeOf(file, reach) {
1418
1503
  const targets = [];
1419
1504
  const exportNodes = [];
1420
1505
  const localNames = /* @__PURE__ */ new Set();
1421
- for (const decl of file.getExportDeclarations()) {
1506
+ for (const decl of statementsOfKind(file, SyntaxKind4.ExportDeclaration)) {
1422
1507
  const target = decl.getModuleSpecifierSourceFile();
1423
1508
  if (target !== void 0) {
1424
1509
  targets.push(target);
@@ -1430,7 +1515,10 @@ function reExportShapeOf(file, reach) {
1430
1515
  }
1431
1516
  }
1432
1517
  }
1433
- for (const assignment of file.getExportAssignments()) {
1518
+ for (const assignment of statementsOfKind(
1519
+ file,
1520
+ SyntaxKind4.ExportAssignment
1521
+ )) {
1434
1522
  exportNodes.push(assignment);
1435
1523
  const expression = assignment.getExpression();
1436
1524
  if (Node3.isIdentifier(expression)) {
@@ -1438,7 +1526,7 @@ function reExportShapeOf(file, reach) {
1438
1526
  }
1439
1527
  }
1440
1528
  const importNodes = [];
1441
- for (const decl of file.getImportDeclarations()) {
1529
+ for (const decl of statementsOfKind(file, SyntaxKind4.ImportDeclaration)) {
1442
1530
  const all = importBindingsOf(decl);
1443
1531
  const bindings = reach === "every import" ? all : all.filter((binding) => localNames.has(binding.name));
1444
1532
  if (bindings.length === 0) {
@@ -1528,7 +1616,7 @@ function keyNameOf(name) {
1528
1616
  }
1529
1617
 
1530
1618
  // src/facts/assignments.ts
1531
- import { Node as Node5, SyntaxKind, VariableDeclarationKind } from "ts-morph";
1619
+ import { Node as Node5, SyntaxKind as SyntaxKind5, ts as ts3, VariableDeclarationKind } from "ts-morph";
1532
1620
  import { valueLeftByWrites } from "@suss/resolution";
1533
1621
  var byFile = createPerFileCache();
1534
1622
  var byDeclaration = /* @__PURE__ */ new WeakMap();
@@ -1576,7 +1664,7 @@ function describeWrites(values) {
1576
1664
  }));
1577
1665
  }
1578
1666
  function isNotYetPlaceholder(value) {
1579
- return value.getKind() === SyntaxKind.NullKeyword || Node5.isIdentifier(value) && value.getText() === "undefined";
1667
+ return value.getKind() === SyntaxKind5.NullKeyword || Node5.isIdentifier(value) && value.getText() === "undefined";
1580
1668
  }
1581
1669
  function isConstruction(value) {
1582
1670
  return Node5.isCallExpression(value) || Node5.isNewExpression(value) || Node5.isObjectLiteralExpression(value) || Node5.isArrayLiteralExpression(value);
@@ -1711,11 +1799,8 @@ function assignmentsInFile(sourceFile) {
1711
1799
  }
1712
1800
  const found = /* @__PURE__ */ new Map();
1713
1801
  byFile.set(sourceFile, found);
1714
- sourceFile.forEachDescendant((node) => {
1802
+ forEachDescendantWhere(sourceFile, mayWrite, (node) => {
1715
1803
  const written = writeAt(node);
1716
- if (written === null) {
1717
- return;
1718
- }
1719
1804
  for (const declaration of declarationsOf(written.target)) {
1720
1805
  const writes = found.get(declaration);
1721
1806
  if (writes === void 0) {
@@ -1724,34 +1809,33 @@ function assignmentsInFile(sourceFile) {
1724
1809
  writes.push(written.write);
1725
1810
  }
1726
1811
  }
1812
+ return false;
1727
1813
  });
1728
1814
  return found;
1729
1815
  }
1816
+ function mayWrite(raw) {
1817
+ if (ts3.isBinaryExpression(raw)) {
1818
+ return isAssignmentOperator(raw.operatorToken.kind) && (ts3.isIdentifier(raw.left) || ts3.isPropertyAccessExpression(raw.left));
1819
+ }
1820
+ if (ts3.isPrefixUnaryExpression(raw) || ts3.isPostfixUnaryExpression(raw)) {
1821
+ return (raw.operator === SyntaxKind5.PlusPlusToken || raw.operator === SyntaxKind5.MinusMinusToken) && ts3.isIdentifier(raw.operand);
1822
+ }
1823
+ return false;
1824
+ }
1730
1825
  function isAssignmentOperator(kind) {
1731
- return kind >= SyntaxKind.FirstAssignment && kind <= SyntaxKind.LastAssignment;
1826
+ return kind >= SyntaxKind5.FirstAssignment && kind <= SyntaxKind5.LastAssignment;
1732
1827
  }
1733
1828
  function writesItsWholeValue(kind) {
1734
- return kind === SyntaxKind.EqualsToken || kind === SyntaxKind.QuestionQuestionEqualsToken || kind === SyntaxKind.BarBarEqualsToken;
1829
+ return kind === SyntaxKind5.EqualsToken || kind === SyntaxKind5.QuestionQuestionEqualsToken || kind === SyntaxKind5.BarBarEqualsToken;
1735
1830
  }
1736
1831
  function writeAt(node) {
1737
1832
  if (Node5.isBinaryExpression(node)) {
1738
1833
  const operator = node.getOperatorToken().getKind();
1739
- const target = node.getLeft();
1740
- if (!isAssignmentOperator(operator) || !(Node5.isIdentifier(target) || Node5.isPropertyAccessExpression(target))) {
1741
- return null;
1742
- }
1743
1834
  const value = writesItsWholeValue(operator) ? node.getRight() : null;
1744
- return { target, write: { value, node } };
1745
- }
1746
- if (Node5.isPrefixUnaryExpression(node) || Node5.isPostfixUnaryExpression(node)) {
1747
- const operator = node.getOperatorToken();
1748
- if (operator !== SyntaxKind.PlusPlusToken && operator !== SyntaxKind.MinusMinusToken) {
1749
- return null;
1750
- }
1751
- const target = node.getOperand();
1752
- return Node5.isIdentifier(target) ? { target, write: { value: null, node } } : null;
1835
+ return { target: node.getLeft(), write: { value, node } };
1753
1836
  }
1754
- return null;
1837
+ const update = node;
1838
+ return { target: update.getOperand(), write: { value: null, node } };
1755
1839
  }
1756
1840
  function declarationsOf(name) {
1757
1841
  const nameNode = Node5.isPropertyAccessExpression(name) ? name.getNameNode() : name;
@@ -1793,35 +1877,39 @@ function statementOf(node) {
1793
1877
  function isReadBefore(declaration, position) {
1794
1878
  const name = declaration.getName();
1795
1879
  const sourceFile = declaration.getSourceFile();
1796
- let read2 = false;
1797
- sourceFile.forEachDescendant((node, traversal) => {
1798
- if (read2) {
1799
- traversal.stop();
1800
- return;
1801
- }
1802
- if (node.getStart() >= position) {
1803
- traversal.skip();
1804
- return;
1805
- }
1806
- if (startsItsOwnBody(node)) {
1807
- traversal.skip();
1808
- return;
1809
- }
1810
- if (!Node5.isIdentifier(node) || node.getText() !== name) {
1811
- return;
1880
+ const file = sourceFile.compilerNode;
1881
+ const readsHere = (raw) => {
1882
+ if (!ts3.isIdentifier(raw) || raw.getText(file) !== name) {
1883
+ return false;
1812
1884
  }
1885
+ const node = wrapperOf(sourceFile, raw);
1813
1886
  if (node === declaration.getNameNode() || isWriteTarget(node)) {
1814
- return;
1815
- }
1816
- if (declarationsOf(node).includes(declaration)) {
1817
- read2 = true;
1887
+ return false;
1818
1888
  }
1819
- });
1820
- return read2;
1821
- }
1822
- function startsItsOwnBody(node) {
1823
- return Node5.isFunctionDeclaration(node) || Node5.isFunctionExpression(node) || Node5.isArrowFunction(node) || Node5.isMethodDeclaration(node) || Node5.isClassDeclaration(node);
1889
+ return declarationsOf(node).includes(declaration);
1890
+ };
1891
+ return someBefore(file, position, readsHere);
1824
1892
  }
1893
+ function someBefore(root, position, test) {
1894
+ const file = root.getSourceFile();
1895
+ const visit = (raw) => {
1896
+ if (raw.getStart(file) >= position || OWN_BODY_KINDS.has(raw.kind)) {
1897
+ return void 0;
1898
+ }
1899
+ if (test(raw)) {
1900
+ return true;
1901
+ }
1902
+ return ts3.forEachChild(raw, visit);
1903
+ };
1904
+ return ts3.forEachChild(root, visit) === true;
1905
+ }
1906
+ var OWN_BODY_KINDS = /* @__PURE__ */ new Set([
1907
+ SyntaxKind5.FunctionDeclaration,
1908
+ SyntaxKind5.FunctionExpression,
1909
+ SyntaxKind5.ArrowFunction,
1910
+ SyntaxKind5.MethodDeclaration,
1911
+ SyntaxKind5.ClassDeclaration
1912
+ ]);
1825
1913
  function isWriteTarget(name) {
1826
1914
  const parent = name.getParent();
1827
1915
  if (parent === void 0) {
@@ -1911,21 +1999,12 @@ function runsAsItsOwnBody(node) {
1911
1999
  return Node5.isFunctionDeclaration(node) || Node5.isFunctionExpression(node) || Node5.isArrowFunction(node) || Node5.isMethodDeclaration(node) || Node5.isConstructorDeclaration(node) || Node5.isGetAccessorDeclaration(node) || Node5.isSetAccessorDeclaration(node);
1912
2000
  }
1913
2001
  function isPropertyReadBefore(statements, name, property, position) {
1914
- let read2 = false;
1915
- statements.forEachDescendant((node, traversal) => {
1916
- if (read2) {
1917
- traversal.stop();
1918
- return;
1919
- }
1920
- if (node.getStart() >= position || startsItsOwnBody(node)) {
1921
- traversal.skip();
1922
- return;
1923
- }
1924
- if (Node5.isPropertyAccessExpression(node) && node.getName() === property && node.getExpression().getText() === name && !isWriteTarget(node)) {
1925
- read2 = true;
1926
- }
1927
- });
1928
- return read2;
2002
+ const file = statements.getSourceFile().compilerNode;
2003
+ return someBefore(
2004
+ statements.compilerNode,
2005
+ position,
2006
+ (raw) => ts3.isPropertyAccessExpression(raw) && raw.name.getText(file) === property && raw.expression.getText(file) === name && !isWriteTarget(wrapperOf(statements, raw))
2007
+ );
1929
2008
  }
1930
2009
 
1931
2010
  // src/facts/languageWords.ts
@@ -1974,8 +2053,15 @@ function createNodeTable(environmentObjects = [], runtime = NO_RUNTIME_SPELLINGS
1974
2053
  };
1975
2054
  }
1976
2055
  function nodeId(node) {
1977
- return `${node.getSourceFile().getFilePath()}:${node.getStart()}-${node.getEnd()}`;
2056
+ const known = idByNode.get(node.compilerNode);
2057
+ if (known !== void 0) {
2058
+ return known;
2059
+ }
2060
+ const id = `${node.getSourceFile().getFilePath()}:${node.getStart()}-${node.getEnd()}`;
2061
+ idByNode.set(node.compilerNode, id);
2062
+ return id;
1978
2063
  }
2064
+ var idByNode = /* @__PURE__ */ new WeakMap();
1979
2065
  function moduleKeyOf(declaration) {
1980
2066
  const resolved = declaration.getModuleSpecifierSourceFile();
1981
2067
  if (resolved !== void 0) {
@@ -1989,7 +2075,7 @@ function moduleKeyOf(declaration) {
1989
2075
  }
1990
2076
  function compilerResolvedPathOf(declaration, specifier) {
1991
2077
  const project = declaration.getProject();
1992
- const result = ts2.resolveModuleName(
2078
+ const result = ts4.resolveModuleName(
1993
2079
  specifier,
1994
2080
  declaration.getSourceFile().getFilePath(),
1995
2081
  project.getCompilerOptions(),
@@ -2031,7 +2117,7 @@ function moduleKeysOf(moduleKey, specifier) {
2031
2117
  }
2032
2118
  function dynamicImportKeysOf(expression) {
2033
2119
  const call = unwrapExpression(expression);
2034
- if (!Node6.isCallExpression(call) || call.getExpression().getKind() !== SyntaxKind2.ImportKeyword) {
2120
+ if (!Node6.isCallExpression(call) || call.getExpression().getKind() !== SyntaxKind6.ImportKeyword) {
2035
2121
  return null;
2036
2122
  }
2037
2123
  const [argument] = call.getArguments();
@@ -2296,7 +2382,33 @@ function spellingsHandedOn(paths, sourceFile) {
2296
2382
  if (!paths.some((path18) => text3.includes(path18))) {
2297
2383
  return [];
2298
2384
  }
2299
- return sourceFile.getDescendantsOfKind(SyntaxKind2.PropertyAccessExpression).filter((node) => spellsOneOf(paths, node) && flowsOnward(node));
2385
+ const file = sourceFile.compilerNode;
2386
+ const found = [];
2387
+ forEachDescendantWhere(
2388
+ sourceFile,
2389
+ (raw) => ts4.isPropertyAccessExpression(raw) && paths.includes(compilerDottedPathOf(raw, file) ?? ""),
2390
+ (node) => {
2391
+ if (flowsOnward(node)) {
2392
+ found.push(node);
2393
+ }
2394
+ return false;
2395
+ }
2396
+ );
2397
+ return found;
2398
+ }
2399
+ function compilerDottedPathOf(raw, file) {
2400
+ if (ts4.isIdentifier(raw)) {
2401
+ return raw.getText(file);
2402
+ }
2403
+ if (ts4.isMetaProperty(raw)) {
2404
+ const keyword = ts4.tokenToString(raw.keywordToken);
2405
+ return `${keyword}.${raw.name.getText(file)}`;
2406
+ }
2407
+ if (!ts4.isPropertyAccessExpression(raw)) {
2408
+ return null;
2409
+ }
2410
+ const object = compilerDottedPathOf(raw.expression, file);
2411
+ return object === null ? null : `${object}.${raw.name.getText(file)}`;
2300
2412
  }
2301
2413
  function flowsOnward(node) {
2302
2414
  const parent = node.getParent();
@@ -2313,7 +2425,7 @@ function dottedPathOf(expression) {
2313
2425
  return expression.getText();
2314
2426
  }
2315
2427
  if (Node6.isMetaProperty(expression)) {
2316
- const keyword = ts2.tokenToString(expression.getKeywordToken());
2428
+ const keyword = ts4.tokenToString(expression.getKeywordToken());
2317
2429
  return `${keyword}.${expression.getName()}`;
2318
2430
  }
2319
2431
  if (!Node6.isPropertyAccessExpression(expression)) {
@@ -2327,7 +2439,7 @@ function asFallbackExpression(expression) {
2327
2439
  return null;
2328
2440
  }
2329
2441
  const operator = expression.getOperatorToken().getKind();
2330
- return operator === SyntaxKind2.BarBarToken || operator === SyntaxKind2.QuestionQuestionToken ? expression : null;
2442
+ return operator === SyntaxKind6.BarBarToken || operator === SyntaxKind6.QuestionQuestionToken ? expression : null;
2331
2443
  }
2332
2444
  function unwrapExpression(expression) {
2333
2445
  let current2 = expression;
@@ -2349,7 +2461,7 @@ function unwrapExpression(expression) {
2349
2461
  }
2350
2462
  function emitValue(db, table, value) {
2351
2463
  const expression = unwrapExpression(value);
2352
- if (expression.getKind() === SyntaxKind2.ThisKeyword) {
2464
+ if (expression.getKind() === SyntaxKind6.ThisKeyword) {
2353
2465
  const receiver = receiverKeyOf(db, table, expression);
2354
2466
  if (receiver !== null) {
2355
2467
  return receiver;
@@ -2503,7 +2615,7 @@ function memberReadName(read2) {
2503
2615
  }
2504
2616
  function readsOffClassItself(receiver) {
2505
2617
  const written = unwrapExpression(receiver);
2506
- if (written.getKind() === SyntaxKind2.ThisKeyword) {
2618
+ if (written.getKind() === SyntaxKind6.ThisKeyword) {
2507
2619
  return thisIsTheClass(written);
2508
2620
  }
2509
2621
  return isClassReference(written, /* @__PURE__ */ new Set());
@@ -2648,7 +2760,7 @@ function emitReferenceFacts(db, table, reference) {
2648
2760
  }
2649
2761
  if (Node6.isImportClause(declaration)) {
2650
2762
  const importDecl = declaration.getParentIfKind(
2651
- SyntaxKind2.ImportDeclaration
2763
+ SyntaxKind6.ImportDeclaration
2652
2764
  );
2653
2765
  if (importDecl !== void 0) {
2654
2766
  emitImportFacts(
@@ -2664,7 +2776,7 @@ function emitReferenceFacts(db, table, reference) {
2664
2776
  }
2665
2777
  if (Node6.isNamespaceImport(declaration)) {
2666
2778
  const importDecl = declaration.getFirstAncestorByKind(
2667
- SyntaxKind2.ImportDeclaration
2779
+ SyntaxKind6.ImportDeclaration
2668
2780
  );
2669
2781
  if (importDecl !== void 0) {
2670
2782
  emitImportFacts(
@@ -2978,11 +3090,11 @@ function emitConstructorFacts(db, table, declaration, classId) {
2978
3090
  return;
2979
3091
  }
2980
3092
  const writes = propertyWritesOf(implementation, body);
2981
- body.forEachDescendant((descendant, traversal) => {
2982
- if (recordBodyCalls(db, table, classId, descendant, writes)) {
2983
- traversal.skip();
2984
- }
2985
- });
3093
+ forEachDescendantOfKinds(
3094
+ body,
3095
+ BODY_FACT_KINDS,
3096
+ (descendant) => recordBodyCalls(db, table, classId, descendant, writes)
3097
+ );
2986
3098
  emitNamedStores(db, table, writes);
2987
3099
  }
2988
3100
  function emitParameters(db, table, ownerId, parameters) {
@@ -3034,11 +3146,11 @@ function emitFunctionFacts(db, table, fn) {
3034
3146
  returns.stated = true;
3035
3147
  recordBodyNode(db, table, fnId, body, returns, writes);
3036
3148
  }
3037
- body.forEachDescendant((descendant, traversal) => {
3038
- if (recordBodyNode(db, table, fnId, descendant, returns, writes)) {
3039
- traversal.skip();
3040
- }
3041
- });
3149
+ forEachDescendantOfKinds(
3150
+ body,
3151
+ BODY_FACT_KINDS,
3152
+ (descendant) => recordBodyNode(db, table, fnId, descendant, returns, writes)
3153
+ );
3042
3154
  emitNamedStores(db, table, writes);
3043
3155
  }
3044
3156
  if (!returns.stated) {
@@ -3096,6 +3208,18 @@ function recordBodyNode(db, table, fnId, node, returns, writes) {
3096
3208
  }
3097
3209
  return recordBodyCalls(db, table, fnId, node, writes);
3098
3210
  }
3211
+ var BODY_FACT_KINDS = /* @__PURE__ */ new Set([
3212
+ ...FUNCTION_ROOT_KINDS,
3213
+ SyntaxKind6.ReturnStatement,
3214
+ SyntaxKind6.ElementAccessExpression,
3215
+ SyntaxKind6.BinaryExpression,
3216
+ SyntaxKind6.CallExpression,
3217
+ SyntaxKind6.NewExpression,
3218
+ SyntaxKind6.AwaitExpression,
3219
+ SyntaxKind6.ParenthesizedExpression,
3220
+ SyntaxKind6.AsExpression,
3221
+ SyntaxKind6.SatisfiesExpression
3222
+ ]);
3099
3223
  function recordBodyCalls(db, table, fnId, node, writes) {
3100
3224
  if (isFunctionRoot(node)) {
3101
3225
  emitValue(db, table, node);
@@ -3122,7 +3246,7 @@ function recordBodyCalls(db, table, fnId, node, writes) {
3122
3246
  return false;
3123
3247
  }
3124
3248
  function emitExitCodeWrite(db, table, node) {
3125
- if (table.exitCodeWrites.length === 0 || !Node6.isBinaryExpression(node) || node.getOperatorToken().getKind() !== SyntaxKind2.EqualsToken || !spellsOneOf(table.exitCodeWrites, node.getLeft())) {
3249
+ if (table.exitCodeWrites.length === 0 || !Node6.isBinaryExpression(node) || node.getOperatorToken().getKind() !== SyntaxKind6.EqualsToken || !spellsOneOf(table.exitCodeWrites, node.getLeft())) {
3126
3250
  return;
3127
3251
  }
3128
3252
  fact(db, "exitCodeWrite", emitValue(db, table, node.getRight()));
@@ -3146,12 +3270,12 @@ function emitTopLevelStatements(db, table, sourceFile) {
3146
3270
  continue;
3147
3271
  }
3148
3272
  if (TOP_LEVEL_BLOCKS.has(statement.getKind())) {
3149
- statement.forEachDescendant((node, traversal) => {
3273
+ forEachDescendantOfKinds(statement, TOP_LEVEL_WRITE_KINDS, (node) => {
3150
3274
  if (isFunctionRoot(node) || Node6.isClassDeclaration(node)) {
3151
- traversal.skip();
3152
- return;
3275
+ return true;
3153
3276
  }
3154
3277
  notePropertyWrite(writes, node);
3278
+ return false;
3155
3279
  });
3156
3280
  }
3157
3281
  }
@@ -3162,16 +3286,21 @@ function statementExpressionOf(statement) {
3162
3286
  return Node6.isVoidExpression(expression) ? unwrapExpression(expression.getExpression()) : expression;
3163
3287
  }
3164
3288
  var TOP_LEVEL_BLOCKS = /* @__PURE__ */ new Set([
3165
- SyntaxKind2.Block,
3166
- SyntaxKind2.IfStatement,
3167
- SyntaxKind2.TryStatement,
3168
- SyntaxKind2.SwitchStatement,
3169
- SyntaxKind2.LabeledStatement,
3170
- SyntaxKind2.ForStatement,
3171
- SyntaxKind2.ForOfStatement,
3172
- SyntaxKind2.ForInStatement,
3173
- SyntaxKind2.WhileStatement,
3174
- SyntaxKind2.DoStatement
3289
+ SyntaxKind6.Block,
3290
+ SyntaxKind6.IfStatement,
3291
+ SyntaxKind6.TryStatement,
3292
+ SyntaxKind6.SwitchStatement,
3293
+ SyntaxKind6.LabeledStatement,
3294
+ SyntaxKind6.ForStatement,
3295
+ SyntaxKind6.ForOfStatement,
3296
+ SyntaxKind6.ForInStatement,
3297
+ SyntaxKind6.WhileStatement,
3298
+ SyntaxKind6.DoStatement
3299
+ ]);
3300
+ var TOP_LEVEL_WRITE_KINDS = /* @__PURE__ */ new Set([
3301
+ ...FUNCTION_ROOT_KINDS,
3302
+ SyntaxKind6.BinaryExpression,
3303
+ SyntaxKind6.ClassDeclaration
3175
3304
  ]);
3176
3305
  function descendantIsReturned(fn) {
3177
3306
  const consumer = climbSyntax(fn).getParent();
@@ -3180,8 +3309,8 @@ function descendantIsReturned(fn) {
3180
3309
  function importedModuleKeys(sourceFile) {
3181
3310
  const keys = [];
3182
3311
  for (const declaration of [
3183
- ...sourceFile.getImportDeclarations(),
3184
- ...sourceFile.getExportDeclarations()
3312
+ ...statementsOfKind(sourceFile, SyntaxKind6.ImportDeclaration),
3313
+ ...statementsOfKind(sourceFile, SyntaxKind6.ExportDeclaration)
3185
3314
  ]) {
3186
3315
  const moduleKey = moduleKeyOf(declaration);
3187
3316
  if (moduleKey !== null) {
@@ -3192,7 +3321,10 @@ function importedModuleKeys(sourceFile) {
3192
3321
  }
3193
3322
  function extractReExportFacts(db, sourceFile) {
3194
3323
  const filePath = sourceFile.getFilePath();
3195
- for (const exportDecl of sourceFile.getExportDeclarations()) {
3324
+ for (const exportDecl of statementsOfKind(
3325
+ sourceFile,
3326
+ SyntaxKind6.ExportDeclaration
3327
+ )) {
3196
3328
  const moduleKey = moduleKeyOf(exportDecl);
3197
3329
  if (moduleKey === null) {
3198
3330
  continue;
@@ -3249,7 +3381,7 @@ function collectDirectExports(statements, found) {
3249
3381
  continue;
3250
3382
  }
3251
3383
  for (const element of nameNode.getDescendantsOfKind(
3252
- SyntaxKind2.BindingElement
3384
+ SyntaxKind6.BindingElement
3253
3385
  )) {
3254
3386
  const bound = element.getNameNode();
3255
3387
  if (Node6.isIdentifier(bound)) {
@@ -3268,7 +3400,10 @@ function collectDirectExports(statements, found) {
3268
3400
  }
3269
3401
  }
3270
3402
  function emitLocalExportLists(db, table, sourceFile, filePath) {
3271
- for (const exportDecl of sourceFile.getExportDeclarations()) {
3403
+ for (const exportDecl of statementsOfKind(
3404
+ sourceFile,
3405
+ SyntaxKind6.ExportDeclaration
3406
+ )) {
3272
3407
  if (exportDecl.getModuleSpecifier() !== void 0) {
3273
3408
  continue;
3274
3409
  }
@@ -3279,7 +3414,10 @@ function emitLocalExportLists(db, table, sourceFile, filePath) {
3279
3414
  }
3280
3415
  }
3281
3416
  }
3282
- for (const assignment of sourceFile.getExportAssignments()) {
3417
+ for (const assignment of statementsOfKind(
3418
+ sourceFile,
3419
+ SyntaxKind6.ExportAssignment
3420
+ )) {
3283
3421
  if (assignment.isExportEquals()) {
3284
3422
  continue;
3285
3423
  }
@@ -3303,7 +3441,7 @@ function emitExportedDeclaration(db, table, filePath, alias, declaration) {
3303
3441
  const specifier = importSpecifierOf(declaration);
3304
3442
  if (specifier !== null) {
3305
3443
  const importDecl = declaration.getFirstAncestorByKind(
3306
- SyntaxKind2.ImportDeclaration
3444
+ SyntaxKind6.ImportDeclaration
3307
3445
  );
3308
3446
  const moduleKey = importDecl === void 0 ? null : moduleKeyOf(importDecl);
3309
3447
  if (moduleKey !== null) {
@@ -3358,7 +3496,7 @@ function emitExportedValue(db, table, filePath, name, spelling) {
3358
3496
  }
3359
3497
 
3360
3498
  // src/facts/localUses.ts
3361
- import { Node as Node7, SyntaxKind as SyntaxKind3 } from "ts-morph";
3499
+ import { Node as Node7, SyntaxKind as SyntaxKind7 } from "ts-morph";
3362
3500
  import { UNPLACED_STORE_NAME } from "@suss/resolution";
3363
3501
  function fact2(db, relation, ...tuple) {
3364
3502
  db.add(relation, tuple);
@@ -3420,25 +3558,25 @@ function emitUse(db, table, operand2) {
3420
3558
  return key;
3421
3559
  }
3422
3560
  var CONSUMERS = {
3423
- [SyntaxKind3.PropertyAccessExpression]: emitPartRead,
3424
- [SyntaxKind3.ElementAccessExpression]: emitPartRead,
3425
- [SyntaxKind3.CallExpression]: emitWhole,
3426
- [SyntaxKind3.NewExpression]: emitWhole,
3427
- [SyntaxKind3.ArrayLiteralExpression]: emitWhole,
3428
- [SyntaxKind3.PropertyAssignment]: emitHolder,
3429
- [SyntaxKind3.ShorthandPropertyAssignment]: emitHolder,
3430
- [SyntaxKind3.ReturnStatement]: emitEnclosingFunction,
3431
- [SyntaxKind3.ArrowFunction]: emitEnclosingFunction,
3432
- [SyntaxKind3.Parameter]: emitEnclosingFunction,
3433
- [SyntaxKind3.YieldExpression]: emitYield,
3434
- [SyntaxKind3.VariableDeclaration]: emitNameWrite,
3435
- [SyntaxKind3.BinaryExpression]: emitBinary,
3436
- [SyntaxKind3.ConditionalExpression]: emitConditionalBranch,
3437
- [SyntaxKind3.SpreadElement]: emitGivenTo,
3438
- [SyntaxKind3.SpreadAssignment]: emitGivenTo,
3439
- [SyntaxKind3.JsxSpreadAttribute]: emitGivenToElement,
3440
- [SyntaxKind3.JsxExpression]: emitGivenToElement,
3441
- [SyntaxKind3.PropertyDeclaration]: emitFieldInitializer
3561
+ [SyntaxKind7.PropertyAccessExpression]: emitPartRead,
3562
+ [SyntaxKind7.ElementAccessExpression]: emitPartRead,
3563
+ [SyntaxKind7.CallExpression]: emitWhole,
3564
+ [SyntaxKind7.NewExpression]: emitWhole,
3565
+ [SyntaxKind7.ArrayLiteralExpression]: emitWhole,
3566
+ [SyntaxKind7.PropertyAssignment]: emitHolder,
3567
+ [SyntaxKind7.ShorthandPropertyAssignment]: emitHolder,
3568
+ [SyntaxKind7.ReturnStatement]: emitEnclosingFunction,
3569
+ [SyntaxKind7.ArrowFunction]: emitEnclosingFunction,
3570
+ [SyntaxKind7.Parameter]: emitEnclosingFunction,
3571
+ [SyntaxKind7.YieldExpression]: emitYield,
3572
+ [SyntaxKind7.VariableDeclaration]: emitNameWrite,
3573
+ [SyntaxKind7.BinaryExpression]: emitBinary,
3574
+ [SyntaxKind7.ConditionalExpression]: emitConditionalBranch,
3575
+ [SyntaxKind7.SpreadElement]: emitGivenTo,
3576
+ [SyntaxKind7.SpreadAssignment]: emitGivenTo,
3577
+ [SyntaxKind7.JsxSpreadAttribute]: emitGivenToElement,
3578
+ [SyntaxKind7.JsxExpression]: emitGivenToElement,
3579
+ [SyntaxKind7.PropertyDeclaration]: emitFieldInitializer
3442
3580
  };
3443
3581
  function emitGivenTo(db, _table, _operand, key, parent) {
3444
3582
  const container = parent.getParent();
@@ -3526,16 +3664,16 @@ function emitNameWrite(db, _table, _operand, key, parent) {
3526
3664
  fact2(db, "mayHold", nodeId(name), key);
3527
3665
  }
3528
3666
  var WHOLE_VALUE_WRITES = /* @__PURE__ */ new Set([
3529
- SyntaxKind3.EqualsToken,
3530
- SyntaxKind3.BarBarEqualsToken,
3531
- SyntaxKind3.QuestionQuestionEqualsToken
3667
+ SyntaxKind7.EqualsToken,
3668
+ SyntaxKind7.BarBarEqualsToken,
3669
+ SyntaxKind7.QuestionQuestionEqualsToken
3532
3670
  ]);
3533
3671
  function emitBinary(db, table, operand2, key, parent) {
3534
3672
  if (!Node7.isBinaryExpression(parent)) {
3535
3673
  return;
3536
3674
  }
3537
3675
  const operator = parent.getOperatorToken().getKind();
3538
- if (operator === SyntaxKind3.AmpersandAmpersandToken && parent.getRight() === operand2) {
3676
+ if (operator === SyntaxKind7.AmpersandAmpersandToken && parent.getRight() === operand2) {
3539
3677
  fact2(db, "conditionalBranch", nodeId(parent), key);
3540
3678
  return;
3541
3679
  }
@@ -3611,7 +3749,7 @@ function valueWrittenThrough(name) {
3611
3749
  const parent = name.getParent();
3612
3750
  if (Node8.isElementAccessExpression(parent) && parent.getExpression() === name) {
3613
3751
  const assignment = parent.getParent();
3614
- return Node8.isBinaryExpression(assignment) && assignment.getLeft() === parent && assignment.getOperatorToken().getKind() === SyntaxKind4.EqualsToken ? assignment.getRight() : null;
3752
+ return Node8.isBinaryExpression(assignment) && assignment.getLeft() === parent && assignment.getOperatorToken().getKind() === SyntaxKind8.EqualsToken ? assignment.getRight() : null;
3615
3753
  }
3616
3754
  if (Node8.isPropertyAccessExpression(parent) && parent.getExpression() === name && parent.getName() === MAP_ENTRY_WRITE) {
3617
3755
  const call = parent.getParent();
@@ -5246,12 +5384,12 @@ function forgetProgramMemos(project) {
5246
5384
  }
5247
5385
 
5248
5386
  // src/values/lowering.ts
5249
- import { Node as Node11, SyntaxKind as SyntaxKind6 } from "ts-morph";
5387
+ import { Node as Node11, SyntaxKind as SyntaxKind10 } from "ts-morph";
5250
5388
 
5251
5389
  // src/resolve/unfollowedCall.ts
5252
5390
  import {
5253
5391
  Node as Node10,
5254
- SyntaxKind as SyntaxKind5
5392
+ SyntaxKind as SyntaxKind9
5255
5393
  } from "ts-morph";
5256
5394
  import {
5257
5395
  unfollowedCallGap,
@@ -5274,14 +5412,14 @@ function isExternalDeclaration(declaration) {
5274
5412
  return true;
5275
5413
  }
5276
5414
  if (Node10.isImportSpecifier(declaration) || Node10.isImportClause(declaration) || Node10.isNamespaceImport(declaration)) {
5277
- const target = declaration.getFirstAncestorByKind(SyntaxKind5.ImportDeclaration)?.getModuleSpecifierSourceFile();
5415
+ const target = declaration.getFirstAncestorByKind(SyntaxKind9.ImportDeclaration)?.getModuleSpecifierSourceFile();
5278
5416
  return target === void 0 || isInExternalCode(target);
5279
5417
  }
5280
5418
  return declaresAnotherModule(declaration);
5281
5419
  }
5282
5420
  function declaresAnotherModule(declaration) {
5283
5421
  const module = declaration.getFirstAncestorByKind(
5284
- SyntaxKind5.ModuleDeclaration
5422
+ SyntaxKind9.ModuleDeclaration
5285
5423
  );
5286
5424
  return module !== void 0 && Node10.isStringLiteral(module.getNameNode());
5287
5425
  }
@@ -5534,7 +5672,7 @@ function expressionOf(node, originOf2) {
5534
5672
  }
5535
5673
  if (Node11.isPrefixUnaryExpression(node)) {
5536
5674
  const operator = node.getOperatorToken();
5537
- return operator === SyntaxKind6.ExclamationToken ? { kind: "operator", operator: "!", operands: [node.getOperand()] } : { kind: "opaque" };
5675
+ return operator === SyntaxKind10.ExclamationToken ? { kind: "operator", operator: "!", operands: [node.getOperand()] } : { kind: "opaque" };
5538
5676
  }
5539
5677
  if (Node11.isConditionalExpression(node)) {
5540
5678
  return {
@@ -6295,7 +6433,7 @@ function settledChannel(argument, resolution) {
6295
6433
  }
6296
6434
 
6297
6435
  // src/discovery/importedCalls.ts
6298
- import { Node as Node14 } from "ts-morph";
6436
+ import { Node as Node14, ts as ts5 } from "ts-morph";
6299
6437
  function callsResolvingTo(sourceFile, resolution, spec) {
6300
6438
  return [
6301
6439
  ...callsByOriginName(
@@ -6307,26 +6445,30 @@ function callsResolvingTo(sourceFile, resolution, spec) {
6307
6445
  ];
6308
6446
  }
6309
6447
  function callsByOriginName(sourceFile, resolution, module, names) {
6448
+ return callsNamed(importedCallOrigins(sourceFile, resolution, module), names);
6449
+ }
6450
+ function importedCallOrigins(sourceFile, resolution, module) {
6310
6451
  const candidates = [];
6311
- sourceFile.forEachDescendant((node) => {
6312
- if (!Node14.isCallExpression(node) && !Node14.isNewExpression(node)) {
6313
- return;
6314
- }
6315
- const callee = node.getExpression();
6316
- if (Node14.isIdentifier(callee) && !declaredLocally(callee)) {
6317
- candidates.push(node);
6452
+ forEachDescendantWhere(sourceFile, callsANamedCallee, (node) => {
6453
+ const call = node;
6454
+ if (!declaredLocally(call.getExpression())) {
6455
+ candidates.push(call);
6318
6456
  }
6457
+ return false;
6319
6458
  });
6320
- const matched = /* @__PURE__ */ new Map();
6321
6459
  if (candidates.length === 0) {
6322
- return matched;
6460
+ return { candidates, origins: /* @__PURE__ */ new Map() };
6323
6461
  }
6324
6462
  const origins = resolution.importOriginsOfMany(
6325
6463
  candidates.map((call) => call.getExpression()),
6326
6464
  [module]
6327
6465
  );
6328
- for (const call of candidates) {
6329
- const origin = (origins.get(call.getExpression()) ?? []).find(
6466
+ return { candidates, origins };
6467
+ }
6468
+ function callsNamed(found, names) {
6469
+ const matched = /* @__PURE__ */ new Map();
6470
+ for (const call of found.candidates) {
6471
+ const origin = (found.origins.get(call.getExpression()) ?? []).find(
6330
6472
  (one) => one.path.length === 1 && names.has(one.path[0] ?? "")
6331
6473
  );
6332
6474
  const name = origin?.path[0];
@@ -6336,6 +6478,9 @@ function callsByOriginName(sourceFile, resolution, module, names) {
6336
6478
  }
6337
6479
  return matched;
6338
6480
  }
6481
+ function callsANamedCallee(raw) {
6482
+ return (ts5.isCallExpression(raw) || ts5.isNewExpression(raw)) && ts5.isIdentifier(raw.expression);
6483
+ }
6339
6484
  function declaredLocally(callee) {
6340
6485
  const declarations = callee.getSymbol()?.getDeclarations() ?? [];
6341
6486
  return declarations.length > 0 && declarations.every(
@@ -6384,7 +6529,7 @@ function unitFor(call, func, match, kind, store, binding) {
6384
6529
  }
6385
6530
 
6386
6531
  // src/discovery/clientCall.ts
6387
- import { Node as Node15, SyntaxKind as SyntaxKind7 } from "ts-morph";
6532
+ import { Node as Node15, SyntaxKind as SyntaxKind12 } from "ts-morph";
6388
6533
  import { hasNameHole } from "@suss/behavioral-ir";
6389
6534
 
6390
6535
  // src/resolve/routePath.ts
@@ -6424,6 +6569,9 @@ function propertyValueAt(arg, property, resolution, site) {
6424
6569
 
6425
6570
  // src/discovery/importScan.ts
6426
6571
  import path4 from "path";
6572
+ import {
6573
+ SyntaxKind as SyntaxKind11
6574
+ } from "ts-morph";
6427
6575
  import { commonDirectoryOf } from "@suss/extractor";
6428
6576
  function specifierMatches(specifier, moduleName, subpaths) {
6429
6577
  if (specifier === moduleName) {
@@ -6468,7 +6616,10 @@ function importedRootsOf(sourceFile, modules, options = {}) {
6468
6616
  return roots;
6469
6617
  }
6470
6618
  function moduleImportedWholeAs(sourceFile, local) {
6471
- for (const decl of sourceFile.getImportDeclarations()) {
6619
+ for (const decl of statementsOfKind(
6620
+ sourceFile,
6621
+ SyntaxKind11.ImportDeclaration
6622
+ )) {
6472
6623
  const bound = decl.getNamespaceImport()?.getText() ?? decl.getDefaultImport()?.getText();
6473
6624
  if (bound !== local) {
6474
6625
  continue;
@@ -6479,7 +6630,10 @@ function moduleImportedWholeAs(sourceFile, local) {
6479
6630
  return null;
6480
6631
  }
6481
6632
  function specifierImportedAs(sourceFile, local) {
6482
- for (const decl of sourceFile.getImportDeclarations()) {
6633
+ for (const decl of statementsOfKind(
6634
+ sourceFile,
6635
+ SyntaxKind11.ImportDeclaration
6636
+ )) {
6483
6637
  const bound = [
6484
6638
  decl.getDefaultImport()?.getText(),
6485
6639
  decl.getNamespaceImport()?.getText(),
@@ -6510,9 +6664,11 @@ function importDeclarationsOf(sourceFile, modules, options = {}) {
6510
6664
  function matchingImportDeclarations(sourceFile, importModule, resolution, subpaths = false) {
6511
6665
  const target = isPathShapedSpecifier(importModule) ? resolvedModuleFile(sourceFile.getProject(), importModule, resolution) : null;
6512
6666
  if (target !== null) {
6513
- return sourceFile.getImportDeclarations().filter((decl) => decl.getModuleSpecifierSourceFile() === target);
6667
+ return statementsOfKind(sourceFile, SyntaxKind11.ImportDeclaration).filter(
6668
+ (decl) => decl.getModuleSpecifierSourceFile() === target
6669
+ );
6514
6670
  }
6515
- return sourceFile.getImportDeclarations().filter(
6671
+ return statementsOfKind(sourceFile, SyntaxKind11.ImportDeclaration).filter(
6516
6672
  (decl) => specifierMatches(decl.getModuleSpecifierValue(), importModule, subpaths)
6517
6673
  );
6518
6674
  }
@@ -6588,14 +6744,18 @@ function importedReferenceSpellings(sourceFile, importModule, importName) {
6588
6744
  }
6589
6745
 
6590
6746
  // src/discovery/clientCall.ts
6747
+ var CALL_KIND = /* @__PURE__ */ new Set([SyntaxKind12.CallExpression]);
6748
+ var BINDING_KINDS = /* @__PURE__ */ new Set([
6749
+ SyntaxKind12.VariableDeclaration,
6750
+ SyntaxKind12.Parameter
6751
+ ]);
6591
6752
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
6592
6753
  function discoverClientCalls(sourceFile, match, kind, resolution, binding) {
6593
6754
  const results = [];
6594
6755
  const calls = [];
6595
- sourceFile.forEachDescendant((node) => {
6596
- if (Node15.isCallExpression(node)) {
6597
- calls.push(node);
6598
- }
6756
+ forEachDescendantOfKinds(sourceFile, CALL_KIND, (node) => {
6757
+ calls.push(node);
6758
+ return false;
6599
6759
  });
6600
6760
  const matched = match.importModule === "global" ? globalCallsAmong(calls, match) : clientCallsAmong(calls, match, sourceFile, resolution);
6601
6761
  for (const call of calls) {
@@ -6709,7 +6869,7 @@ function clientsBuiltAtTopLevel(sourceFile, match, resolution) {
6709
6869
  );
6710
6870
  }
6711
6871
  function sitesToReadUnder(call, binding, resolution) {
6712
- const cls = call.getFirstAncestorByKind(SyntaxKind7.ClassDeclaration);
6872
+ const cls = call.getFirstAncestorByKind(SyntaxKind12.ClassDeclaration);
6713
6873
  if (binding === void 0 || resolution === void 0 || cls === void 0) {
6714
6874
  return [void 0];
6715
6875
  }
@@ -6797,7 +6957,7 @@ function clientReceiverCheckFor(sourceFile, match, resolution) {
6797
6957
  );
6798
6958
  const constructedHere = /* @__PURE__ */ new Set();
6799
6959
  const initializedBy = /* @__PURE__ */ new Map();
6800
- sourceFile.forEachDescendant((node) => {
6960
+ const visit = (node) => {
6801
6961
  if (Node15.isVariableDeclaration(node)) {
6802
6962
  const init = node.getInitializer();
6803
6963
  if (init !== void 0 && (Node15.isCallExpression(init) || Node15.isNewExpression(init))) {
@@ -6806,7 +6966,7 @@ function clientReceiverCheckFor(sourceFile, match, resolution) {
6806
6966
  if (localName !== null && typedAsClient(node.getTypeNode(), localName)) {
6807
6967
  constructedHere.add(node.getName());
6808
6968
  }
6809
- return;
6969
+ return false;
6810
6970
  }
6811
6971
  if (Node15.isParameterDeclaration(node) && localName !== null && typedAsClient(node.getTypeNode(), localName)) {
6812
6972
  const written = node.getNameNode();
@@ -6814,7 +6974,9 @@ function clientReceiverCheckFor(sourceFile, match, resolution) {
6814
6974
  constructedHere.add(written.getText());
6815
6975
  }
6816
6976
  }
6817
- });
6977
+ return false;
6978
+ };
6979
+ forEachDescendantOfKinds(sourceFile, BINDING_KINDS, visit, skipsNothing);
6818
6980
  const creating = creationCallsAmong(
6819
6981
  [...initializedBy.keys()],
6820
6982
  match,
@@ -7011,7 +7173,7 @@ function callableOf(member) {
7011
7173
  }
7012
7174
 
7013
7175
  // src/discovery/decoratorComposition.ts
7014
- import { Node as Node17, SyntaxKind as SyntaxKind8 } from "ts-morph";
7176
+ import { Node as Node17, SyntaxKind as SyntaxKind13 } from "ts-morph";
7015
7177
  function classDecoratorStandingFor(cls, names, modules, resolution) {
7016
7178
  for (const candidate of names) {
7017
7179
  const decorator = cls.getDecorator(candidate);
@@ -7049,7 +7211,7 @@ function frameworkArgs(decorator, standsFor, modules, resolution) {
7049
7211
  if (wrapper === null) {
7050
7212
  return atClass;
7051
7213
  }
7052
- for (const call of wrapper.getDescendantsOfKind(SyntaxKind8.CallExpression)) {
7214
+ for (const call of wrapper.getDescendantsOfKind(SyntaxKind13.CallExpression)) {
7053
7215
  const names = resolution.importedNamesOf(call.getExpression(), modules);
7054
7216
  if (!names.includes(standsFor)) {
7055
7217
  continue;
@@ -7060,7 +7222,7 @@ function frameworkArgs(decorator, standsFor, modules, resolution) {
7060
7222
  return atClass;
7061
7223
  }
7062
7224
  function statesAValue(arg, wrapper) {
7063
- const identifiers = Node17.isIdentifier(arg) ? [arg] : arg.getDescendantsOfKind(SyntaxKind8.Identifier);
7225
+ const identifiers = Node17.isIdentifier(arg) ? [arg] : arg.getDescendantsOfKind(SyntaxKind13.Identifier);
7064
7226
  return !identifiers.some(
7065
7227
  (identifier) => identifier.getSymbol()?.getDeclarations().some(
7066
7228
  (declaration) => Node17.isParameterDeclaration(declaration) && isWithin(declaration, wrapper)
@@ -7798,7 +7960,8 @@ import picomatch from "picomatch";
7798
7960
 
7799
7961
  // src/discovery/namedExport.ts
7800
7962
  import {
7801
- Node as Node27
7963
+ Node as Node27,
7964
+ SyntaxKind as SyntaxKind15
7802
7965
  } from "ts-morph";
7803
7966
 
7804
7967
  // src/discovery/wrappedExport.ts
@@ -7808,7 +7971,7 @@ import { Node as Node26 } from "ts-morph";
7808
7971
  import { Node as Node23 } from "ts-morph";
7809
7972
 
7810
7973
  // src/walk/descent.ts
7811
- import { Node as Node22 } from "ts-morph";
7974
+ import { Node as Node22, SyntaxKind as SyntaxKind14 } from "ts-morph";
7812
7975
  var NO_BARRIERS = /* @__PURE__ */ new Set();
7813
7976
  function isDescentStop(node, func, barriers = NO_BARRIERS) {
7814
7977
  if (node === func) {
@@ -7822,24 +7985,16 @@ function isDescentStop(node, func, barriers = NO_BARRIERS) {
7822
7985
  }
7823
7986
  return false;
7824
7987
  }
7825
- function forEachInUnitBody(root, visit) {
7826
- root.forEachDescendant(visit);
7988
+ function forEachInUnitBodyOfKinds(root, kinds, visit) {
7989
+ forEachInUnitBodyWhere(root, (raw) => kinds.has(raw.kind), visit);
7990
+ }
7991
+ function forEachInUnitBodyWhere(root, accepts, visit) {
7992
+ forEachDescendantWhere(root, accepts, visit);
7827
7993
  for (const initializer of fieldInitializersRunBy(root)) {
7828
- let skipped = false;
7829
- visit(initializer, {
7830
- stop: () => {
7831
- skipped = true;
7832
- },
7833
- skip: () => {
7834
- skipped = true;
7835
- },
7836
- up: () => {
7837
- skipped = true;
7838
- }
7839
- });
7840
- if (!skipped) {
7841
- initializer.forEachDescendant(visit);
7994
+ if (accepts(initializer.compilerNode) && visit(initializer)) {
7995
+ continue;
7842
7996
  }
7997
+ forEachDescendantWhere(initializer, accepts, visit);
7843
7998
  }
7844
7999
  }
7845
8000
  function fieldInitializersRunBy(root) {
@@ -7868,6 +8023,19 @@ function isInlineCallback(node, func, barriers = NO_BARRIERS) {
7868
8023
  }
7869
8024
  return !barriers.has(node);
7870
8025
  }
8026
+ var DESCENT_STOP_KINDS = /* @__PURE__ */ new Set([
8027
+ SyntaxKind14.FunctionDeclaration,
8028
+ SyntaxKind14.MethodDeclaration,
8029
+ SyntaxKind14.Constructor,
8030
+ SyntaxKind14.ArrowFunction,
8031
+ SyntaxKind14.FunctionExpression,
8032
+ SyntaxKind14.ClassDeclaration,
8033
+ SyntaxKind14.ClassExpression,
8034
+ SyntaxKind14.Decorator
8035
+ ]);
8036
+ function withDescentStops(...kinds) {
8037
+ return /* @__PURE__ */ new Set([...DESCENT_STOP_KINDS, ...kinds]);
8038
+ }
7871
8039
  function isModuleScopeStop(node) {
7872
8040
  if (isImmediatelyInvoked(node)) {
7873
8041
  return false;
@@ -7896,11 +8064,17 @@ function crossesNestedFunctionScope(node, func) {
7896
8064
  return false;
7897
8065
  }
7898
8066
  function startsItsOwnScope(node) {
7899
- return Node22.isArrowFunction(node) || Node22.isFunctionExpression(node) || Node22.isFunctionDeclaration(node) || Node22.isMethodDeclaration(node) || Node22.isGetAccessorDeclaration(node) || Node22.isSetAccessorDeclaration(node) || Node22.isConstructorDeclaration(node);
7900
- }
7901
- function containsNoCode(node) {
7902
- return Node22.isTypeNode(node) && !Node22.isExpressionWithTypeArguments(node);
7903
- }
8067
+ return OWN_SCOPE_KINDS.has(node.getKind());
8068
+ }
8069
+ var OWN_SCOPE_KINDS = /* @__PURE__ */ new Set([
8070
+ SyntaxKind14.ArrowFunction,
8071
+ SyntaxKind14.FunctionExpression,
8072
+ SyntaxKind14.FunctionDeclaration,
8073
+ SyntaxKind14.MethodDeclaration,
8074
+ SyntaxKind14.GetAccessor,
8075
+ SyntaxKind14.SetAccessor,
8076
+ SyntaxKind14.Constructor
8077
+ ]);
7904
8078
 
7905
8079
  // src/parameterReads.ts
7906
8080
  function pathAbove(reference) {
@@ -9101,7 +9275,10 @@ function discoverNamedExports(sourceFile, match, kind, resolution, options = {})
9101
9275
  return results;
9102
9276
  }
9103
9277
  function defaultExportUnits(sourceFile, kind, resolution, options) {
9104
- for (const assignment of sourceFile.getExportAssignments()) {
9278
+ for (const assignment of statementsOfKind(
9279
+ sourceFile,
9280
+ SyntaxKind15.ExportAssignment
9281
+ )) {
9105
9282
  if (assignment.isExportEquals()) {
9106
9283
  continue;
9107
9284
  }
@@ -10022,7 +10199,7 @@ function sameDeclaration(a, b) {
10022
10199
  }
10023
10200
 
10024
10201
  // src/discovery/factorySurface.ts
10025
- import { Node as Node32, SyntaxKind as SyntaxKind9 } from "ts-morph";
10202
+ import { Node as Node32, SyntaxKind as SyntaxKind16 } from "ts-morph";
10026
10203
  var MAX_BUILDER_HOPS = 2;
10027
10204
  function surfaceMethods(decl, resolution) {
10028
10205
  if (Node32.isClassDeclaration(decl)) {
@@ -10037,7 +10214,7 @@ function surfaceClassMethods(cls) {
10037
10214
  const out = [];
10038
10215
  const seen = /* @__PURE__ */ new Set();
10039
10216
  for (const method of cls.getInstanceMethods()) {
10040
- if (method.hasModifier(SyntaxKind9.PrivateKeyword)) {
10217
+ if (method.hasModifier(SyntaxKind16.PrivateKeyword)) {
10041
10218
  continue;
10042
10219
  }
10043
10220
  const name = method.getName();
@@ -10048,7 +10225,7 @@ function surfaceClassMethods(cls) {
10048
10225
  out.push({ func: method, name });
10049
10226
  }
10050
10227
  for (const method of cls.getStaticMethods()) {
10051
- if (method.hasModifier(SyntaxKind9.PrivateKeyword)) {
10228
+ if (method.hasModifier(SyntaxKind16.PrivateKeyword)) {
10052
10229
  continue;
10053
10230
  }
10054
10231
  const name = method.getName();
@@ -11882,7 +12059,7 @@ function constructorCalledAt(construction) {
11882
12059
  }
11883
12060
  function baseConstructorCalledAt(superKeyword) {
11884
12061
  const owner = superKeyword.getFirstAncestorByKind(
11885
- SyntaxKind10.ClassDeclaration
12062
+ SyntaxKind17.ClassDeclaration
11886
12063
  );
11887
12064
  const base = owner?.getBaseClass();
11888
12065
  return base === void 0 ? null : constructorOf(base);
@@ -12088,7 +12265,7 @@ function shapeFromDeclaration(decl, extractShape2, ctx) {
12088
12265
  return enterShape(init, extractShape2, ctx);
12089
12266
  }
12090
12267
  if (Node42.isBindingElement(decl)) {
12091
- const varDecl = decl.getFirstAncestorByKind(SyntaxKind11.VariableDeclaration);
12268
+ const varDecl = decl.getFirstAncestorByKind(SyntaxKind18.VariableDeclaration);
12092
12269
  if (!varDecl) {
12093
12270
  return null;
12094
12271
  }
@@ -12174,7 +12351,7 @@ function isInformativeInitializer(node) {
12174
12351
  return isInformativeInitializer(unwrapped2.getOperand());
12175
12352
  }
12176
12353
  const kind = unwrapped2.getKind();
12177
- return kind === SyntaxKind11.TrueKeyword || kind === SyntaxKind11.FalseKeyword || kind === SyntaxKind11.NullKeyword;
12354
+ return kind === SyntaxKind18.TrueKeyword || kind === SyntaxKind18.FalseKeyword || kind === SyntaxKind18.NullKeyword;
12178
12355
  }
12179
12356
  function resolveCallableBody(callee) {
12180
12357
  if (!Node42.isIdentifier(callee)) {
@@ -12523,7 +12700,7 @@ function parseConditionExpression(expr, depth = 0) {
12523
12700
  }
12524
12701
  }
12525
12702
  if (Node45.isPrefixUnaryExpression(expr)) {
12526
- if (expr.getOperatorToken() !== SyntaxKind12.ExclamationToken) {
12703
+ if (expr.getOperatorToken() !== SyntaxKind19.ExclamationToken) {
12527
12704
  return null;
12528
12705
  }
12529
12706
  const operand2 = expr.getOperand();
@@ -12551,7 +12728,7 @@ function parseConditionExpression(expr, depth = 0) {
12551
12728
  const right = expr.getRight();
12552
12729
  const opToken = expr.getOperatorToken();
12553
12730
  const opText = opToken.getText();
12554
- if (opToken.getKind() === SyntaxKind12.AmpersandAmpersandToken) {
12731
+ if (opToken.getKind() === SyntaxKind19.AmpersandAmpersandToken) {
12555
12732
  const leftPred = parseConditionExpression(left, depth);
12556
12733
  const rightPred = parseConditionExpression(right, depth);
12557
12734
  return {
@@ -12563,7 +12740,7 @@ function parseConditionExpression(expr, depth = 0) {
12563
12740
  ]
12564
12741
  };
12565
12742
  }
12566
- if (opToken.getKind() === SyntaxKind12.BarBarToken) {
12743
+ if (opToken.getKind() === SyntaxKind19.BarBarToken) {
12567
12744
  const leftPred = parseConditionExpression(left, depth);
12568
12745
  const rightPred = parseConditionExpression(right, depth);
12569
12746
  return {
@@ -12575,11 +12752,11 @@ function parseConditionExpression(expr, depth = 0) {
12575
12752
  ]
12576
12753
  };
12577
12754
  }
12578
- if (opToken.getKind() === SyntaxKind12.InstanceOfKeyword) {
12755
+ if (opToken.getKind() === SyntaxKind19.InstanceOfKeyword) {
12579
12756
  const subject = resolveSubject(left);
12580
12757
  return { type: "typeCheck", subject, expectedType: right.getText() };
12581
12758
  }
12582
- if (opToken.getKind() === SyntaxKind12.InKeyword) {
12759
+ if (opToken.getKind() === SyntaxKind19.InKeyword) {
12583
12760
  if (Node45.isStringLiteral(left)) {
12584
12761
  const subject = resolveSubject(right);
12585
12762
  return {
@@ -12896,7 +13073,7 @@ function collectFallthroughCaseLabels(caseClause) {
12896
13073
  }
12897
13074
 
12898
13075
  // src/paths/pathConditions.ts
12899
- import { Node as Node48 } from "ts-morph";
13076
+ import { Node as Node48, SyntaxKind as SyntaxKind21 } from "ts-morph";
12900
13077
  import {
12901
13078
  enumerateStructuredPaths,
12902
13079
  PathBudgetExceeded,
@@ -12906,7 +13083,9 @@ import {
12906
13083
 
12907
13084
  // src/paths/lowering.ts
12908
13085
  import {
12909
- Node as Node47
13086
+ Node as Node47,
13087
+ SyntaxKind as SyntaxKind20,
13088
+ ts as ts6
12910
13089
  } from "ts-morph";
12911
13090
  import {
12912
13091
  UnmodeledFlow
@@ -12915,24 +13094,25 @@ var NO_ENDINGS = /* @__PURE__ */ new Set();
12915
13094
  function exitKindOf(stmt, endings) {
12916
13095
  let sawReturn = false;
12917
13096
  let sawThrow = false;
12918
- const visit = (node) => {
12919
- if (node !== stmt && startsItsOwnScope(node)) {
12920
- return;
13097
+ const ending = new Set([...endings].map((node) => node.compilerNode));
13098
+ const root = stmt.compilerNode;
13099
+ const visit = (raw) => {
13100
+ if (raw !== root && OWN_SCOPE_KINDS.has(raw.kind)) {
13101
+ return void 0;
12921
13102
  }
12922
- if (containsNoCode(node)) {
12923
- return;
13103
+ if (runsNothing(raw)) {
13104
+ return void 0;
12924
13105
  }
12925
- if (Node47.isReturnStatement(node) || endings.has(node)) {
13106
+ if (raw.kind === SyntaxKind20.ReturnStatement || ending.has(raw)) {
12926
13107
  sawReturn = true;
12927
13108
  }
12928
- if (Node47.isThrowStatement(node)) {
13109
+ if (raw.kind === SyntaxKind20.ThrowStatement) {
12929
13110
  sawThrow = true;
12930
13111
  }
12931
- for (const child of node.getChildren()) {
12932
- visit(child);
12933
- }
13112
+ ts6.forEachChild(raw, visit);
13113
+ return void 0;
12934
13114
  };
12935
- visit(stmt);
13115
+ visit(root);
12936
13116
  if (sawThrow) {
12937
13117
  return "throw";
12938
13118
  }
@@ -12947,7 +13127,20 @@ var statementsOf = (stmt) => {
12947
13127
  }
12948
13128
  return [stmt];
12949
13129
  };
12950
- var isLoop = (stmt) => Node47.isForOfStatement(stmt) || Node47.isForInStatement(stmt) || Node47.isForStatement(stmt) || Node47.isWhileStatement(stmt) || Node47.isDoStatement(stmt);
13130
+ var LOOP_KINDS = /* @__PURE__ */ new Set([
13131
+ SyntaxKind20.ForOfStatement,
13132
+ SyntaxKind20.ForInStatement,
13133
+ SyntaxKind20.ForStatement,
13134
+ SyntaxKind20.WhileStatement,
13135
+ SyntaxKind20.DoStatement
13136
+ ]);
13137
+ var isLoop = (stmt) => LOOP_KINDS.has(stmt.getKind());
13138
+ var CLAUSE_BREAK_KINDS = /* @__PURE__ */ new Set([
13139
+ ...OWN_SCOPE_KINDS,
13140
+ ...LOOP_KINDS,
13141
+ SyntaxKind20.SwitchStatement,
13142
+ SyntaxKind20.BreakStatement
13143
+ ]);
12951
13144
  function getLoopBody(stmt) {
12952
13145
  if (Node47.isForOfStatement(stmt) || Node47.isForInStatement(stmt) || Node47.isForStatement(stmt) || Node47.isWhileStatement(stmt) || Node47.isDoStatement(stmt)) {
12953
13146
  return stmt.getStatement();
@@ -13006,28 +13199,33 @@ function ownExpressionsOf(stmt) {
13006
13199
  }
13007
13200
  function lowerCallbacksIn(parts, ctx) {
13008
13201
  const bodies = [];
13009
- const visit = (node, root) => {
13010
- if (node !== root && isDescentStop(node, ctx.func, ctx.barriers)) {
13011
- return;
13012
- }
13013
- if (node !== root && (Node47.isArrowFunction(node) || Node47.isFunctionExpression(node)) && isInlineCallback(node, ctx.func, ctx.barriers)) {
13014
- const body = node.getBody();
13015
- if (body !== void 0 && Node47.isBlock(body)) {
13016
- bodies.push(lowerList(body.getStatements(), ctx));
13017
- return;
13018
- }
13019
- } else if (node !== root && startsItsOwnScope(node)) {
13020
- return;
13202
+ const entersScope = (node) => {
13203
+ if (isDescentStop(node, ctx.func, ctx.barriers)) {
13204
+ return false;
13021
13205
  }
13022
- if (containsNoCode(node)) {
13023
- return;
13206
+ if (!(Node47.isArrowFunction(node) || Node47.isFunctionExpression(node)) || !isInlineCallback(node, ctx.func, ctx.barriers)) {
13207
+ return !startsItsOwnScope(node);
13024
13208
  }
13025
- for (const child of node.getChildren()) {
13026
- visit(child, root);
13209
+ const body = node.getBody();
13210
+ if (body !== void 0 && Node47.isBlock(body)) {
13211
+ bodies.push(lowerList(body.getStatements(), ctx));
13212
+ return false;
13027
13213
  }
13214
+ return true;
13028
13215
  };
13029
13216
  for (const part of parts) {
13030
- visit(part, part);
13217
+ const root = part.compilerNode;
13218
+ const visit = (raw) => {
13219
+ if (raw !== root && OWN_SCOPE_KINDS.has(raw.kind) && !entersScope(wrapperOf(part, raw))) {
13220
+ return void 0;
13221
+ }
13222
+ if (runsNothing(raw)) {
13223
+ return void 0;
13224
+ }
13225
+ ts6.forEachChild(raw, visit);
13226
+ return void 0;
13227
+ };
13228
+ visit(root);
13031
13229
  }
13032
13230
  return bodies;
13033
13231
  }
@@ -13149,14 +13347,11 @@ function validateClauseBreaks(stmts) {
13149
13347
  if (Node47.isSwitchStatement(stmt) || isLoop(stmt)) {
13150
13348
  continue;
13151
13349
  }
13152
- stmt.forEachDescendant((node, traversal) => {
13153
- if (startsItsOwnScope(node) || Node47.isSwitchStatement(node) || isLoop(node)) {
13154
- traversal.skip();
13155
- return;
13156
- }
13350
+ forEachDescendantOfKinds(stmt, CLAUSE_BREAK_KINDS, (node) => {
13157
13351
  if (Node47.isBreakStatement(node)) {
13158
13352
  throw new UnmodeledFlow("non-trailing break in switch clause");
13159
13353
  }
13354
+ return true;
13160
13355
  });
13161
13356
  if (Node47.isBreakStatement(stmt)) {
13162
13357
  throw new UnmodeledFlow("non-trailing break in switch clause");
@@ -13211,18 +13406,20 @@ function enclosingLoweredStatement(terminal, body, rawToStructured) {
13211
13406
  // src/paths/pathConditions.ts
13212
13407
  function containsUnmodeledFlow(body, func, barriers) {
13213
13408
  let found = false;
13214
- body.forEachDescendant((node, traversal) => {
13215
- if (isDescentStop(node, func, barriers)) {
13216
- traversal.skip();
13217
- return;
13218
- }
13219
- if (Node48.isLabeledStatement(node)) {
13220
- found = true;
13221
- traversal.stop();
13409
+ forEachDescendantWhere(
13410
+ body,
13411
+ (raw) => !found && LABELS_AND_STOPS.has(raw.kind),
13412
+ (node) => {
13413
+ if (isDescentStop(node, func, barriers)) {
13414
+ return true;
13415
+ }
13416
+ found = Node48.isLabeledStatement(node);
13417
+ return found;
13222
13418
  }
13223
- });
13419
+ );
13224
13420
  return found;
13225
13421
  }
13422
+ var LABELS_AND_STOPS = withDescentStops(SyntaxKind21.LabeledStatement);
13226
13423
  function loweredExpressionBody(body, terminalNodes, func, barriers) {
13227
13424
  const statement = {
13228
13425
  kind: "opaque",
@@ -13385,6 +13582,8 @@ function literalAt(node, resolution) {
13385
13582
  // src/resolve/invocationEffects.ts
13386
13583
  import {
13387
13584
  Node as Node54,
13585
+ SyntaxKind as SyntaxKind23,
13586
+ ts as ts8,
13388
13587
  VariableDeclarationKind as VariableDeclarationKind2
13389
13588
  } from "ts-morph";
13390
13589
  import {
@@ -13402,27 +13601,43 @@ import { Node as Node51 } from "ts-morph";
13402
13601
  import { Node as Node50 } from "ts-morph";
13403
13602
 
13404
13603
  // src/shapes/typeText.ts
13405
- import { ts as ts3 } from "ts-morph";
13406
- var PRINTER = ts3.createPrinter({
13604
+ import { ts as ts7 } from "ts-morph";
13605
+ var PRINTER = ts7.createPrinter({
13407
13606
  removeComments: true,
13408
- newLine: ts3.NewLineKind.LineFeed
13607
+ newLine: ts7.NewLineKind.LineFeed
13409
13608
  });
13410
- var NO_FILE = ts3.createSourceFile("", "", ts3.ScriptTarget.Latest);
13609
+ var NO_FILE = ts7.createSourceFile("", "", ts7.ScriptTarget.Latest);
13411
13610
  function defaultFlags(enclosing) {
13412
- const flags = ts3.TypeFormatFlags.UseTypeOfFunction | ts3.TypeFormatFlags.NoTruncation | ts3.TypeFormatFlags.UseFullyQualifiedType | ts3.TypeFormatFlags.WriteTypeArgumentsOfSignature;
13413
- if (enclosing?.getKind() === ts3.SyntaxKind.TypeAliasDeclaration) {
13414
- return flags | ts3.TypeFormatFlags.InTypeAlias;
13611
+ const flags = ts7.TypeFormatFlags.UseTypeOfFunction | ts7.TypeFormatFlags.NoTruncation | ts7.TypeFormatFlags.UseFullyQualifiedType | ts7.TypeFormatFlags.WriteTypeArgumentsOfSignature;
13612
+ if (enclosing?.getKind() === ts7.SyntaxKind.TypeAliasDeclaration) {
13613
+ return flags | ts7.TypeFormatFlags.InTypeAlias;
13415
13614
  }
13416
13615
  return flags;
13417
13616
  }
13418
13617
  function stableTypeText(type, reader, enclosing, flags) {
13419
- const checker = reader.getProject().getTypeChecker().compilerObject;
13420
13618
  const format = flags ?? defaultFlags(enclosing);
13619
+ const place = enclosing?.compilerNode ?? NOWHERE;
13620
+ const atPlace = printedAt.get(place) ?? /* @__PURE__ */ new WeakMap();
13621
+ printedAt.set(place, atPlace);
13622
+ const byFormat = atPlace.get(type.compilerType) ?? /* @__PURE__ */ new Map();
13623
+ atPlace.set(type.compilerType, byFormat);
13624
+ const kept = byFormat.get(format);
13625
+ if (kept !== void 0) {
13626
+ return kept;
13627
+ }
13628
+ const text3 = printedType(type, reader, enclosing, format);
13629
+ byFormat.set(format, text3);
13630
+ return text3;
13631
+ }
13632
+ var NOWHERE = {};
13633
+ var printedAt = /* @__PURE__ */ new WeakMap();
13634
+ function printedType(type, reader, enclosing, format) {
13635
+ const checker = reader.getProject().getTypeChecker().compilerObject;
13421
13636
  const enclosingNode = enclosing?.compilerNode;
13422
13637
  const typeNode = checker.typeToTypeNode(
13423
13638
  type.compilerType,
13424
13639
  enclosingNode,
13425
- format & ts3.TypeFormatFlags.NodeBuilderFlagsMask | ts3.NodeBuilderFlags.IgnoreErrors
13640
+ format & ts7.TypeFormatFlags.NodeBuilderFlagsMask | ts7.NodeBuilderFlags.IgnoreErrors
13426
13641
  );
13427
13642
  if (typeNode === void 0) {
13428
13643
  return withoutImportQualifiers(
@@ -13436,23 +13651,23 @@ function stableTypeText(type, reader, enclosing, flags) {
13436
13651
  var IMPORT_QUALIFIER = /import\("[^"]*"\)\./g;
13437
13652
  var withoutImportQualifiers = (text3) => text3.replace(IMPORT_QUALIFIER, "");
13438
13653
  function printed(node, file) {
13439
- return PRINTER.printNode(ts3.EmitHint.Unspecified, node, file).replace(
13654
+ return PRINTER.printNode(ts7.EmitHint.Unspecified, node, file).replace(
13440
13655
  /\n/g,
13441
13656
  ""
13442
13657
  );
13443
13658
  }
13444
13659
  function containsUnion(node) {
13445
- if (ts3.isUnionTypeNode(node)) {
13660
+ if (ts7.isUnionTypeNode(node)) {
13446
13661
  return true;
13447
13662
  }
13448
- return ts3.forEachChild(node, (child) => containsUnion(child) || void 0) === true;
13663
+ return ts7.forEachChild(node, (child) => containsUnion(child) || void 0) === true;
13449
13664
  }
13450
13665
  function withUnionMembersOrdered(root, file) {
13451
- const result = ts3.transform(root, [
13666
+ const result = ts7.transform(root, [
13452
13667
  (context) => {
13453
13668
  const visit = (node) => {
13454
- const visited = ts3.visitEachChild(node, visit, context);
13455
- if (!ts3.isUnionTypeNode(visited)) {
13669
+ const visited = ts7.visitEachChild(node, visit, context);
13670
+ if (!ts7.isUnionTypeNode(visited)) {
13456
13671
  return visited;
13457
13672
  }
13458
13673
  return context.factory.updateUnionTypeNode(
@@ -13650,7 +13865,7 @@ function rootIdentifier(node) {
13650
13865
  }
13651
13866
 
13652
13867
  // src/resolve/readName.ts
13653
- import { Node as Node52, SyntaxKind as SyntaxKind13 } from "ts-morph";
13868
+ import { Node as Node52, SyntaxKind as SyntaxKind22 } from "ts-morph";
13654
13869
  import { patternHole, referenceName } from "@suss/behavioral-ir";
13655
13870
  var MAX_HELPER_HOPS = 2;
13656
13871
  var UNNAMED_HOLE = "param";
@@ -13748,7 +13963,7 @@ function isFallbackBranch(node) {
13748
13963
  return false;
13749
13964
  }
13750
13965
  const operator = step.getOperatorToken().getKind();
13751
- return operator === SyntaxKind13.BarBarToken || operator === SyntaxKind13.QuestionQuestionToken;
13966
+ return operator === SyntaxKind22.BarBarToken || operator === SyntaxKind22.QuestionQuestionToken;
13752
13967
  }
13753
13968
  function fromTemplate(expr, ctx) {
13754
13969
  if (!Node52.isTemplateExpression(expr)) {
@@ -13766,10 +13981,10 @@ function fromBinary(expr, ctx) {
13766
13981
  return null;
13767
13982
  }
13768
13983
  const operator = expr.getOperatorToken().getKind();
13769
- if (operator === SyntaxKind13.BarBarToken || operator === SyntaxKind13.QuestionQuestionToken) {
13984
+ if (operator === SyntaxKind22.BarBarToken || operator === SyntaxKind22.QuestionQuestionToken) {
13770
13985
  return ctx.insideHole ? null : read(expr.getRight(), ctx);
13771
13986
  }
13772
- if (operator !== SyntaxKind13.PlusToken) {
13987
+ if (operator !== SyntaxKind22.PlusToken) {
13773
13988
  return null;
13774
13989
  }
13775
13990
  const parts = { ...ctx, insideHole: true };
@@ -14483,16 +14698,32 @@ function extractInvocationEffectsAtModuleScope(sourceFile) {
14483
14698
  (call) => !invokesFunctionInPlace(call.node)
14484
14699
  );
14485
14700
  }
14701
+ var CALLS_AND_STOPS = withDescentStops(SyntaxKind23.CallExpression);
14702
+ var ACCESSES_CONSTRUCTIONS_AND_STOPS = withDescentStops(
14703
+ SyntaxKind23.PropertyAccessExpression,
14704
+ SyntaxKind23.CallExpression,
14705
+ SyntaxKind23.TaggedTemplateExpression,
14706
+ SyntaxKind23.NewExpression
14707
+ );
14708
+ var INVOCATIONS_AND_STOPS = withDescentStops(
14709
+ SyntaxKind23.CallExpression,
14710
+ SyntaxKind23.NewExpression
14711
+ );
14712
+ var ACCESSES_AND_STOPS = withDescentStops(
14713
+ SyntaxKind23.PropertyAccessExpression,
14714
+ SyntaxKind23.CallExpression,
14715
+ SyntaxKind23.TaggedTemplateExpression
14716
+ );
14486
14717
  function invocationsUnder(root, isStop) {
14487
14718
  const calls = [];
14488
- forEachInUnitBody(root, (node, traversal) => {
14719
+ forEachInUnitBodyOfKinds(root, INVOCATIONS_AND_STOPS, (node) => {
14489
14720
  if (isStop(node)) {
14490
- traversal.skip();
14491
- return;
14721
+ return true;
14492
14722
  }
14493
14723
  if (Node54.isCallExpression(node) || runsProjectConstructor(node)) {
14494
14724
  calls.push(node);
14495
14725
  }
14726
+ return false;
14496
14727
  });
14497
14728
  calls.sort((a, b) => a.getEnd() - b.getEnd());
14498
14729
  return calls.map((call) => invocationAt(call, root));
@@ -14530,14 +14761,14 @@ function runInvocationRecognizers(func, recognizers, barriers = NO_BARRIERS, res
14530
14761
  const sites = [];
14531
14762
  const sourceFile = func.getSourceFile();
14532
14763
  const calls = [];
14533
- forEachInUnitBody(func, (node, traversal) => {
14764
+ forEachInUnitBodyOfKinds(func, CALLS_AND_STOPS, (node) => {
14534
14765
  if (isDescentStop(node, func, barriers)) {
14535
- traversal.skip();
14536
- return;
14766
+ return true;
14537
14767
  }
14538
14768
  if (Node54.isCallExpression(node)) {
14539
14769
  calls.push(node);
14540
14770
  }
14771
+ return false;
14541
14772
  });
14542
14773
  const walk = walkArguments(calls, resolution);
14543
14774
  for (const node of calls) {
@@ -14697,10 +14928,11 @@ function dispatchAccessRecognizers(root, recognizers, isStop, resolution, origin
14697
14928
  function accessedIn(root, isStop) {
14698
14929
  const sites = [];
14699
14930
  const calls = [];
14700
- forEachInUnitBody(root, (node, traversal) => {
14931
+ const own = root.compilerNode;
14932
+ const accepts = (raw) => ACCESSES_CONSTRUCTIONS_AND_STOPS.has(raw.kind) || ts8.isParameter(raw.parent) && raw.parent.initializer === raw && raw.parent.parent === own;
14933
+ forEachInUnitBodyWhere(root, accepts, (node) => {
14701
14934
  if (isStop(node) || isOwnParameterDefault(node, root)) {
14702
- traversal.skip();
14703
- return;
14935
+ return true;
14704
14936
  }
14705
14937
  if (isAccessed(node)) {
14706
14938
  sites.push({ node, at: node });
@@ -14708,17 +14940,18 @@ function accessedIn(root, isStop) {
14708
14940
  if (Node54.isCallExpression(node) || Node54.isNewExpression(node)) {
14709
14941
  calls.push(node);
14710
14942
  }
14943
+ return false;
14711
14944
  });
14712
14945
  for (const call of calls) {
14713
14946
  for (const initializer of defaultsRunBy(call)) {
14714
- forEachInUnitBody(initializer, (node, traversal) => {
14947
+ forEachInUnitBodyOfKinds(initializer, ACCESSES_AND_STOPS, (node) => {
14715
14948
  if (isStop(node)) {
14716
- traversal.skip();
14717
- return;
14949
+ return true;
14718
14950
  }
14719
14951
  if (isAccessed(node)) {
14720
14952
  sites.push({ node, at: call });
14721
14953
  }
14954
+ return false;
14722
14955
  });
14723
14956
  if (isAccessed(initializer)) {
14724
14957
  sites.push({ node: initializer, at: call });
@@ -15455,7 +15688,7 @@ function rootOf(ref) {
15455
15688
  }
15456
15689
 
15457
15690
  // src/terminals/index.ts
15458
- import { Node as Node66 } from "ts-morph";
15691
+ import { Node as Node66, SyntaxKind as SyntaxKind26 } from "ts-morph";
15459
15692
 
15460
15693
  // src/terminals/continuation.ts
15461
15694
  import { Node as Node57 } from "ts-morph";
@@ -15493,7 +15726,7 @@ import { constantOf as constantOf5 } from "@suss/values";
15493
15726
  // src/shapes/shapes.ts
15494
15727
  import {
15495
15728
  Node as Node59,
15496
- SyntaxKind as SyntaxKind14
15729
+ SyntaxKind as SyntaxKind24
15497
15730
  } from "ts-morph";
15498
15731
 
15499
15732
  // src/shapes/typeShapes.ts
@@ -15505,6 +15738,8 @@ var current = null;
15505
15738
  var definitionsInProgress = () => current;
15506
15739
  function createDefinitionTable() {
15507
15740
  const shapes = /* @__PURE__ */ new Map();
15741
+ const deferred = [];
15742
+ let settling = false;
15508
15743
  return {
15509
15744
  has: (key) => shapes.has(key),
15510
15745
  reserve: (key) => {
@@ -15513,6 +15748,22 @@ function createDefinitionTable() {
15513
15748
  define: (key, shape) => {
15514
15749
  shapes.set(key, shape);
15515
15750
  },
15751
+ defer: (key, expand) => {
15752
+ deferred.push({ key, expand });
15753
+ },
15754
+ settle: () => {
15755
+ if (settling) {
15756
+ return;
15757
+ }
15758
+ settling = true;
15759
+ try {
15760
+ for (let next = deferred.shift(); next; next = deferred.shift()) {
15761
+ shapes.set(next.key, next.expand());
15762
+ }
15763
+ } finally {
15764
+ settling = false;
15765
+ }
15766
+ },
15516
15767
  // Sorted because the walk meets types in the checker's union order,
15517
15768
  // which changes between runs.
15518
15769
  collected: () => {
@@ -15882,16 +16133,16 @@ function namedOnce(type, ctx) {
15882
16133
  const filed = { ...named2, def: key };
15883
16134
  if (!table.has(key)) {
15884
16135
  table.reserve(key);
15885
- const expanded = objectToShape(type, {
15886
- enclosing: ctx.enclosing,
15887
- depth: 0,
15888
- seen: /* @__PURE__ */ new Set()
15889
- });
15890
- if (expanded === null) {
15891
- return null;
15892
- }
15893
- table.define(key, expanded);
16136
+ table.defer(
16137
+ key,
16138
+ () => objectToShape(type, {
16139
+ enclosing: ctx.enclosing,
16140
+ depth: 0,
16141
+ seen: /* @__PURE__ */ new Set()
16142
+ })
16143
+ );
15894
16144
  }
16145
+ table.settle();
15895
16146
  return filed;
15896
16147
  }
15897
16148
  function definitionKeyFor(type, name, reader) {
@@ -16055,13 +16306,13 @@ function extractShapeInner(node) {
16055
16306
  }
16056
16307
  if (Node59.isPrefixUnaryExpression(unwrapped2)) {
16057
16308
  const op = unwrapped2.getOperatorToken();
16058
- if (op === SyntaxKind14.MinusToken || op === SyntaxKind14.PlusToken) {
16309
+ if (op === SyntaxKind24.MinusToken || op === SyntaxKind24.PlusToken) {
16059
16310
  const inner = unwrapped2.getOperand();
16060
16311
  if (Node59.isNumericLiteral(inner)) {
16061
16312
  const v2 = inner.getLiteralValue();
16062
- const signed = op === SyntaxKind14.MinusToken ? -v2 : v2;
16313
+ const signed = op === SyntaxKind24.MinusToken ? -v2 : v2;
16063
16314
  const rawBody = inner.getText();
16064
- const raw = op === SyntaxKind14.MinusToken ? `-${rawBody}` : rawBody;
16315
+ const raw = op === SyntaxKind24.MinusToken ? `-${rawBody}` : rawBody;
16065
16316
  return numericLiteralShape(signed, raw);
16066
16317
  }
16067
16318
  }
@@ -16070,13 +16321,13 @@ function extractShapeInner(node) {
16070
16321
  return { type: "ref", name: "bigint" };
16071
16322
  }
16072
16323
  const kind = unwrapped2.getKind();
16073
- if (kind === SyntaxKind14.TrueKeyword) {
16324
+ if (kind === SyntaxKind24.TrueKeyword) {
16074
16325
  return { type: "literal", value: true };
16075
16326
  }
16076
- if (kind === SyntaxKind14.FalseKeyword) {
16327
+ if (kind === SyntaxKind24.FalseKeyword) {
16077
16328
  return { type: "literal", value: false };
16078
16329
  }
16079
- if (kind === SyntaxKind14.NullKeyword) {
16330
+ if (kind === SyntaxKind24.NullKeyword) {
16080
16331
  return { type: "null" };
16081
16332
  }
16082
16333
  if (Node59.isIdentifier(unwrapped2) && unwrapped2.getText() === "undefined") {
@@ -16664,7 +16915,7 @@ import {
16664
16915
  } from "ts-morph";
16665
16916
 
16666
16917
  // src/terminals/helperResolution.ts
16667
- import { Node as Node62, SyntaxKind as SyntaxKind15 } from "ts-morph";
16918
+ import { Node as Node62, SyntaxKind as SyntaxKind25 } from "ts-morph";
16668
16919
  function resolveHelperReturn(call, resolveCallee2) {
16669
16920
  const callee = call.getExpression();
16670
16921
  if (!Node62.isIdentifier(callee)) {
@@ -16877,7 +17128,7 @@ function returnedObjects(fn) {
16877
17128
  }
16878
17129
  const found = [];
16879
17130
  for (const statement of body.getDescendantsOfKind(
16880
- SyntaxKind15.ReturnStatement
17131
+ SyntaxKind25.ReturnStatement
16881
17132
  )) {
16882
17133
  if (enclosingFunctionOf2(statement) !== body) {
16883
17134
  continue;
@@ -17437,12 +17688,23 @@ function classifyThrownExpression(thrown, constructorPattern) {
17437
17688
 
17438
17689
  // src/terminals/index.ts
17439
17690
  var NESTED_ESCAPING_MATCH_TYPES = /* @__PURE__ */ new Set(["parameterMethodCall"]);
17691
+ var TERMINAL_KINDS = /* @__PURE__ */ new Set([
17692
+ SyntaxKind26.ObjectLiteralExpression,
17693
+ SyntaxKind26.ReturnStatement,
17694
+ SyntaxKind26.ThrowStatement,
17695
+ SyntaxKind26.CallExpression,
17696
+ SyntaxKind26.NewExpression,
17697
+ SyntaxKind26.ArrowFunction,
17698
+ SyntaxKind26.FunctionExpression,
17699
+ SyntaxKind26.FunctionDeclaration,
17700
+ SyntaxKind26.MethodDeclaration,
17701
+ SyntaxKind26.Constructor
17702
+ ]);
17440
17703
  function findTerminals(func, patterns, barriers = NO_BARRIERS, resolution, originatesFrom, resolveCallee2) {
17441
17704
  const results = [];
17442
- func.forEachDescendant((node, traversal) => {
17705
+ forEachDescendantOfKinds(func, TERMINAL_KINDS, (node) => {
17443
17706
  if (isDescentStop(node, func, barriers)) {
17444
- traversal.skip();
17445
- return;
17707
+ return true;
17446
17708
  }
17447
17709
  const nested = crossesNestedFunctionScope(node, func);
17448
17710
  for (const pattern of patterns) {
@@ -17510,6 +17772,7 @@ function findTerminals(func, patterns, barriers = NO_BARRIERS, resolution, origi
17510
17772
  break;
17511
17773
  }
17512
17774
  }
17775
+ return false;
17513
17776
  });
17514
17777
  if (results.length === 0 && Node66.isArrowFunction(func)) {
17515
17778
  const body = func.getBody();
@@ -17635,27 +17898,27 @@ function countUnmatchedReturns(func, terminals, barriers = NO_BARRIERS) {
17635
17898
  return claimed.has(body) ? 0 : 1;
17636
17899
  }
17637
17900
  let unmatched = 0;
17638
- body.forEachDescendant((node, traversal) => {
17901
+ forEachDescendantOfKinds(body, RETURNS_AND_SCOPES, (node) => {
17639
17902
  if (isDescentStop(node, func, barriers)) {
17640
- traversal.skip();
17641
- return;
17903
+ return true;
17642
17904
  }
17643
17905
  if (startsItsOwnScope(node)) {
17644
- traversal.skip();
17645
- return;
17646
- }
17647
- if (!Node67.isReturnStatement(node)) {
17648
- return;
17906
+ return true;
17649
17907
  }
17650
17908
  if (node.getExpression() === void 0) {
17651
- return;
17909
+ return false;
17652
17910
  }
17653
17911
  if (!claimed.has(node)) {
17654
17912
  unmatched++;
17655
17913
  }
17914
+ return false;
17656
17915
  });
17657
17916
  return unmatched;
17658
17917
  }
17918
+ var RETURNS_AND_SCOPES = /* @__PURE__ */ new Set([
17919
+ ...OWN_SCOPE_KINDS,
17920
+ SyntaxKind27.ReturnStatement
17921
+ ]);
17659
17922
  function extractRawBranches(func, terminalPatterns, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf, resolveCallee2, collectCallAccounting = false, keepsArms, handOff) {
17660
17923
  const terminals = findTerminals(
17661
17924
  func,
@@ -17847,14 +18110,14 @@ function accountFor(site, terminalNodes, branches) {
17847
18110
  }
17848
18111
 
17849
18112
  // src/bootstrap/automaticTypes.ts
17850
- import { ts as ts4 } from "ts-morph";
18113
+ import { ts as ts9 } from "ts-morph";
17851
18114
  function pinAutomaticTypes(project) {
17852
18115
  const options = project.getCompilerOptions();
17853
18116
  if (options.types !== void 0) {
17854
18117
  return;
17855
18118
  }
17856
18119
  project.compilerOptions.set({
17857
- types: ts4.getAutomaticTypeDirectiveNames(options, ts4.sys)
18120
+ types: ts9.getAutomaticTypeDirectiveNames(options, ts9.sys)
17858
18121
  });
17859
18122
  }
17860
18123
 
@@ -18297,7 +18560,7 @@ function readContractForClientCall(callExpression, methodName, pattern, framewor
18297
18560
 
18298
18561
  // src/diagnostics.ts
18299
18562
  import path10 from "path";
18300
- import { ts as ts5 } from "ts-morph";
18563
+ import { ts as ts10 } from "ts-morph";
18301
18564
  import {
18302
18565
  createPackTallies,
18303
18566
  emptyTally,
@@ -18305,23 +18568,23 @@ import {
18305
18568
  summaryCountsByPack
18306
18569
  } from "@suss/extractor";
18307
18570
  var DEFAULT_RESOLUTION = {
18308
- moduleResolution: ts5.ModuleResolutionKind.Bundler,
18309
- target: ts5.ScriptTarget.ESNext,
18310
- module: ts5.ModuleKind.ESNext
18571
+ moduleResolution: ts10.ModuleResolutionKind.Bundler,
18572
+ target: ts10.ScriptTarget.ESNext,
18573
+ module: ts10.ModuleKind.ESNext
18311
18574
  };
18312
18575
  function resolutionContext(args) {
18313
18576
  if (args.tsConfigFilePath !== void 0) {
18314
- const configFile = ts5.readConfigFile(
18577
+ const configFile = ts10.readConfigFile(
18315
18578
  args.tsConfigFilePath,
18316
- ts5.sys.readFile
18579
+ ts10.sys.readFile
18317
18580
  );
18318
18581
  if (configFile.error !== void 0) {
18319
18582
  return null;
18320
18583
  }
18321
18584
  const dir = path10.dirname(args.tsConfigFilePath);
18322
- const parsed = ts5.parseJsonConfigFileContent(
18585
+ const parsed = ts10.parseJsonConfigFileContent(
18323
18586
  configFile.config,
18324
- ts5.sys,
18587
+ ts10.sys,
18325
18588
  dir,
18326
18589
  /*existingOptions*/
18327
18590
  void 0,
@@ -18350,11 +18613,11 @@ function unresolvedGatesFor(gates, args) {
18350
18613
  }
18351
18614
  const unresolved = [];
18352
18615
  for (const gate of gates) {
18353
- const resolved = ts5.resolveModuleName(
18616
+ const resolved = ts10.resolveModuleName(
18354
18617
  gate,
18355
18618
  context.containingFile,
18356
18619
  context.options,
18357
- ts5.sys
18620
+ ts10.sys
18358
18621
  );
18359
18622
  if (resolved.resolvedModule === void 0) {
18360
18623
  unresolved.push(gate);
@@ -18706,14 +18969,14 @@ function graphqlClientConstructions(sourceFiles, specs, resolution) {
18706
18969
  const store = resolution ?? new ResolutionStore();
18707
18970
  const found = [];
18708
18971
  for (const sourceFile of sourceFiles) {
18972
+ const byModule = /* @__PURE__ */ new Map();
18709
18973
  for (const spec of specs) {
18710
- const constructions = callsByOriginName(
18711
- sourceFile,
18712
- store,
18713
- spec.importModule,
18974
+ const origins = byModule.get(spec.importModule) ?? importedCallOrigins(sourceFile, store, spec.importModule);
18975
+ byModule.set(spec.importModule, origins);
18976
+ for (const node of callsNamed(
18977
+ origins,
18714
18978
  /* @__PURE__ */ new Set([spec.importName])
18715
- );
18716
- for (const node of constructions.keys()) {
18979
+ ).keys()) {
18717
18980
  found.push({ node, spec });
18718
18981
  }
18719
18982
  }
@@ -19851,7 +20114,17 @@ function scopeOf(args, wraps, resolution) {
19851
20114
  }
19852
20115
 
19853
20116
  // src/discoveryContext.ts
19854
- import { Node as Node75 } from "ts-morph";
20117
+ import { Node as Node75, SyntaxKind as SyntaxKind28 } from "ts-morph";
20118
+ var NESTED_FUNCTION_KINDS = /* @__PURE__ */ new Set([
20119
+ SyntaxKind28.FunctionDeclaration,
20120
+ SyntaxKind28.FunctionExpression,
20121
+ SyntaxKind28.ArrowFunction,
20122
+ SyntaxKind28.MethodDeclaration
20123
+ ]);
20124
+ var RETURNS_AND_FUNCTIONS = /* @__PURE__ */ new Set([
20125
+ ...NESTED_FUNCTION_KINDS,
20126
+ SyntaxKind28.ReturnStatement
20127
+ ]);
19855
20128
  function createTsDiscoveryContext(resolution) {
19856
20129
  const store = resolution ?? new ResolutionStore();
19857
20130
  return {
@@ -19936,22 +20209,20 @@ function hasJsxReturn(func) {
19936
20209
  return false;
19937
20210
  }
19938
20211
  let found = false;
19939
- body.forEachDescendant((node, traversal) => {
19940
- if (found) {
19941
- traversal.stop();
19942
- return;
19943
- }
19944
- if (node !== func && (Node75.isFunctionDeclaration(node) || Node75.isFunctionExpression(node) || Node75.isArrowFunction(node) || Node75.isMethodDeclaration(node))) {
19945
- traversal.skip();
19946
- return;
19947
- }
19948
- if (Node75.isReturnStatement(node)) {
19949
- const expr = node.getExpression();
19950
- if (expr !== void 0 && isJsxOrFragment(expr)) {
19951
- found = true;
20212
+ forEachDescendantWhere(
20213
+ body,
20214
+ (raw) => !found && RETURNS_AND_FUNCTIONS.has(raw.kind),
20215
+ (node) => {
20216
+ if (node !== func && NESTED_FUNCTION_KINDS.has(node.getKind())) {
20217
+ return true;
20218
+ }
20219
+ if (Node75.isReturnStatement(node)) {
20220
+ const expr = node.getExpression();
20221
+ found = expr !== void 0 && isJsxOrFragment(expr);
19952
20222
  }
20223
+ return found;
19953
20224
  }
19954
- });
20225
+ );
19955
20226
  return found;
19956
20227
  }
19957
20228
  function isJsxOrFragment(node) {
@@ -20505,7 +20776,8 @@ function placeOfKey(key) {
20505
20776
 
20506
20777
  // src/resolve/reachableClosure.ts
20507
20778
  import {
20508
- Node as Node79
20779
+ Node as Node79,
20780
+ SyntaxKind as SyntaxKind29
20509
20781
  } from "ts-morph";
20510
20782
  import {
20511
20783
  functionCallBinding,
@@ -20912,6 +21184,21 @@ function resolveJsxReference(node, scan) {
20912
21184
  )
20913
21185
  };
20914
21186
  }
21187
+ var BODY_SCAN_KINDS = /* @__PURE__ */ new Set([
21188
+ SyntaxKind29.CallExpression,
21189
+ SyntaxKind29.NewExpression,
21190
+ SyntaxKind29.JsxOpeningElement,
21191
+ SyntaxKind29.JsxSelfClosingElement
21192
+ ]);
21193
+ var MODULE_SCAN_KINDS = /* @__PURE__ */ new Set([
21194
+ ...BODY_SCAN_KINDS,
21195
+ SyntaxKind29.FunctionDeclaration,
21196
+ SyntaxKind29.MethodDeclaration,
21197
+ SyntaxKind29.ArrowFunction,
21198
+ SyntaxKind29.FunctionExpression,
21199
+ SyntaxKind29.ClassDeclaration,
21200
+ SyntaxKind29.ClassExpression
21201
+ ]);
20915
21202
  function collectReachable(root, scan) {
20916
21203
  const atModuleScope = Node79.isSourceFile(root);
20917
21204
  const inFunc = atModuleScope ? { ...scan } : { ...scan, scanning: root };
@@ -20978,31 +21265,32 @@ function collectReachable(root, scan) {
20978
21265
  });
20979
21266
  };
20980
21267
  const found = [];
20981
- forEachInUnitBody(root, (node, traversal) => {
21268
+ const kinds = atModuleScope ? MODULE_SCAN_KINDS : BODY_SCAN_KINDS;
21269
+ forEachInUnitBodyOfKinds(root, kinds, (node) => {
20982
21270
  if (atModuleScope && isModuleScopeStop(node)) {
20983
- traversal.skip();
20984
- return;
21271
+ return true;
20985
21272
  }
20986
21273
  const jsx = resolveJsxReference(node, inFunc);
20987
21274
  if (jsx !== null) {
20988
21275
  found.push({ node, outcome: jsx.outcome });
20989
- return;
21276
+ return false;
20990
21277
  }
20991
21278
  if (Node79.isNewExpression(node)) {
20992
21279
  const outcome2 = resolveConstruction(node, inFunc);
20993
21280
  if (outcome2 !== null) {
20994
21281
  found.push({ node, calleeText: constructionCallee(node), outcome: outcome2 });
20995
21282
  }
20996
- return;
21283
+ return false;
20997
21284
  }
20998
21285
  if (!Node79.isCallExpression(node)) {
20999
- return;
21286
+ return false;
21000
21287
  }
21001
21288
  const calleeText = normalizeCalleeText2(node.getExpression().getText());
21002
21289
  const outcome = resolveCallee(node, calleeText, inFunc);
21003
21290
  if (outcome !== null) {
21004
21291
  found.push({ node, calleeText, outcome });
21005
21292
  }
21293
+ return false;
21006
21294
  });
21007
21295
  const settle = settleThroughStore(
21008
21296
  found.map((one) => one.outcome),
@@ -21775,7 +22063,8 @@ function resolveCalleeSummary(call, index) {
21775
22063
 
21776
22064
  // src/subUnitContext.ts
21777
22065
  import {
21778
- Node as Node81
22066
+ Node as Node81,
22067
+ SyntaxKind as SyntaxKind30
21779
22068
  } from "ts-morph";
21780
22069
  function createTsSubUnitContext() {
21781
22070
  return {
@@ -21787,24 +22076,19 @@ function createTsSubUnitContext() {
21787
22076
  readArrayLiteralText
21788
22077
  };
21789
22078
  }
21790
- function skipNestedFunctions(parent) {
21791
- return (node, traversal) => {
21792
- if (isDescentStop(node, parent)) {
21793
- traversal.skip();
21794
- return true;
21795
- }
21796
- return false;
21797
- };
21798
- }
22079
+ var JSX_ELEMENTS_AND_STOPS = withDescentStops(
22080
+ SyntaxKind30.JsxOpeningElement,
22081
+ SyntaxKind30.JsxSelfClosingElement
22082
+ );
22083
+ var CALLS_AND_STOPS2 = withDescentStops(SyntaxKind30.CallExpression);
21799
22084
  function findJsxAttributes(parent) {
21800
22085
  const out = [];
21801
- const skip = skipNestedFunctions(parent);
21802
- parent.forEachDescendant((node, traversal) => {
21803
- if (skip(node, traversal)) {
21804
- return;
22086
+ forEachDescendantOfKinds(parent, JSX_ELEMENTS_AND_STOPS, (node) => {
22087
+ if (isDescentStop(node, parent)) {
22088
+ return true;
21805
22089
  }
21806
22090
  if (!Node81.isJsxOpeningElement(node) && !Node81.isJsxSelfClosingElement(node)) {
21807
- return;
22091
+ return false;
21808
22092
  }
21809
22093
  const tag = node.getTagNameNode().getText();
21810
22094
  for (const attr of node.getAttributes()) {
@@ -21827,23 +22111,24 @@ function findJsxAttributes(parent) {
21827
22111
  valueExpression
21828
22112
  });
21829
22113
  }
22114
+ return false;
21830
22115
  });
21831
22116
  return out;
21832
22117
  }
21833
22118
  function findCallExpressionsByName(parent, name) {
21834
22119
  const out = [];
21835
- const skip = skipNestedFunctions(parent);
21836
- parent.forEachDescendant((node, traversal) => {
21837
- if (skip(node, traversal)) {
21838
- return;
22120
+ forEachDescendantOfKinds(parent, CALLS_AND_STOPS2, (node) => {
22121
+ if (isDescentStop(node, parent)) {
22122
+ return true;
21839
22123
  }
21840
22124
  if (!Node81.isCallExpression(node)) {
21841
- return;
22125
+ return false;
21842
22126
  }
21843
22127
  const callee = node.getExpression();
21844
22128
  if (Node81.isIdentifier(callee) && callee.getText() === name) {
21845
22129
  out.push(node);
21846
22130
  }
22131
+ return false;
21847
22132
  });
21848
22133
  return out;
21849
22134
  }
@@ -22494,17 +22779,16 @@ function extractParameters(func, inputMapping) {
22494
22779
  }
22495
22780
  function extractDependencyCalls(func, barriers = NO_BARRIERS) {
22496
22781
  const results = [];
22497
- func.forEachDescendant((node, traversal) => {
22782
+ forEachDescendantOfKinds(func, DECLARATIONS_AND_STOPS, (node) => {
22498
22783
  if (isDescentStop(node, func, barriers)) {
22499
- traversal.skip();
22500
- return;
22784
+ return true;
22501
22785
  }
22502
22786
  if (!Node82.isVariableDeclaration(node)) {
22503
- return;
22787
+ return false;
22504
22788
  }
22505
22789
  const init = node.getInitializer();
22506
22790
  if (init === void 0) {
22507
- return;
22791
+ return false;
22508
22792
  }
22509
22793
  let isAsync = false;
22510
22794
  let callExpr = init;
@@ -22513,7 +22797,7 @@ function extractDependencyCalls(func, barriers = NO_BARRIERS) {
22513
22797
  callExpr = init.getExpression();
22514
22798
  }
22515
22799
  if (!Node82.isCallExpression(callExpr)) {
22516
- return;
22800
+ return false;
22517
22801
  }
22518
22802
  const calleeName = callExpr.getExpression().getText();
22519
22803
  const nameNode = node.getNameNode();
@@ -22531,9 +22815,11 @@ function extractDependencyCalls(func, barriers = NO_BARRIERS) {
22531
22815
  end: endLineOf(locationNode)
22532
22816
  }
22533
22817
  });
22818
+ return false;
22534
22819
  });
22535
22820
  return results;
22536
22821
  }
22822
+ var DECLARATIONS_AND_STOPS = withDescentStops(SyntaxKind31.VariableDeclaration);
22537
22823
  function resolveResponseProperties(branches, calleeText, semantics) {
22538
22824
  return branches.map((branch) => ({
22539
22825
  ...branch,
@@ -23480,7 +23766,10 @@ function fileImporting(project, modulePrefix) {
23480
23766
  if (sourceFile.isInNodeModules() || sourceFile.isDeclarationFile()) {
23481
23767
  continue;
23482
23768
  }
23483
- for (const imp of sourceFile.getImportDeclarations()) {
23769
+ for (const imp of statementsOfKind(
23770
+ sourceFile,
23771
+ SyntaxKind31.ImportDeclaration
23772
+ )) {
23484
23773
  if (imp.getModuleSpecifierValue().startsWith(modulePrefix)) {
23485
23774
  return sourceFile.getFilePath();
23486
23775
  }
@@ -23530,10 +23819,16 @@ function internalImportsOf(project, file) {
23530
23819
  targets.add(target.getFilePath());
23531
23820
  }
23532
23821
  };
23533
- for (const imp of sourceFile.getImportDeclarations()) {
23822
+ for (const imp of statementsOfKind(
23823
+ sourceFile,
23824
+ SyntaxKind31.ImportDeclaration
23825
+ )) {
23534
23826
  record2(imp.getModuleSpecifierSourceFile());
23535
23827
  }
23536
- for (const exp of sourceFile.getExportDeclarations()) {
23828
+ for (const exp of statementsOfKind(
23829
+ sourceFile,
23830
+ SyntaxKind31.ExportDeclaration
23831
+ )) {
23537
23832
  record2(exp.getModuleSpecifierSourceFile());
23538
23833
  }
23539
23834
  return [...targets].sort();
@@ -24751,7 +25046,7 @@ function buildSubUnitSummary(subUnit, parent, parentFunc, recognizers, everyUnit
24751
25046
 
24752
25047
  // src/facts/why.ts
24753
25048
  import path16 from "path";
24754
- import { Node as Node83, Project as Project3, SyntaxKind as SyntaxKind16 } from "ts-morph";
25049
+ import { Node as Node83, Project as Project3, SyntaxKind as SyntaxKind32 } from "ts-morph";
24755
25050
  import { explainResolutionProof, renderExplanation } from "@suss/resolution";
24756
25051
  var TypeScriptWhySession = class {
24757
25052
  project;
@@ -24793,7 +25088,7 @@ var TypeScriptWhySession = class {
24793
25088
  return null;
24794
25089
  }
24795
25090
  for (const call of sourceFile.getDescendantsOfKind(
24796
- SyntaxKind16.CallExpression
25091
+ SyntaxKind32.CallExpression
24797
25092
  )) {
24798
25093
  const line = call.getStartLineNumber();
24799
25094
  if (line < startLine || line > endLine) {
@@ -24929,7 +25224,7 @@ function stubEvidence(options) {
24929
25224
  }
24930
25225
 
24931
25226
  // src/walk/defaulted.ts
24932
- import { Node as Node84, SyntaxKind as SyntaxKind17 } from "ts-morph";
25227
+ import { Node as Node84, SyntaxKind as SyntaxKind33, ts as ts11 } from "ts-morph";
24933
25228
  function isDefaultedAt(node) {
24934
25229
  if (!Node84.isBindingElement(node)) {
24935
25230
  const read2 = climbSyntax(node);
@@ -25219,7 +25514,7 @@ function comparedValue(operand2, other, loose) {
25219
25514
  return missing ? operand2 : null;
25220
25515
  }
25221
25516
  function negatedOperand(node) {
25222
- if (Node84.isPrefixUnaryExpression(node) && node.getOperatorToken() === SyntaxKind17.ExclamationToken) {
25517
+ if (Node84.isPrefixUnaryExpression(node) && node.getOperatorToken() === SyntaxKind33.ExclamationToken) {
25223
25518
  return node.getOperand();
25224
25519
  }
25225
25520
  return null;
@@ -25261,9 +25556,20 @@ function declarationInitializedBy(node) {
25261
25556
  return null;
25262
25557
  }
25263
25558
  function usesOf(local) {
25264
- return local.scope.getDescendantsOfKind(SyntaxKind17.Identifier).filter(
25265
- (identifier) => identifier !== local.name && refersTo(identifier, local)
25266
- );
25559
+ const name = local.name.getText();
25560
+ const file = local.scope.getSourceFile();
25561
+ const uses = [];
25562
+ const visit = (node) => {
25563
+ if (ts11.isIdentifier(node) && node.text === name) {
25564
+ const found = file.getDescendantAtPos(node.getStart(file.compilerNode));
25565
+ if (found !== void 0 && Node84.isIdentifier(found) && found !== local.name && refersTo(found, local)) {
25566
+ uses.push(found);
25567
+ }
25568
+ }
25569
+ ts11.forEachChild(node, visit);
25570
+ };
25571
+ ts11.forEachChild(local.scope.compilerNode, visit);
25572
+ return uses;
25267
25573
  }
25268
25574
  export {
25269
25575
  ADAPTER_VERSION,