unguard 0.10.1 → 0.10.3

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.
@@ -287,10 +287,36 @@ var noNullishCoalescing = {
287
287
  visit(node, ctx) {
288
288
  if (!ts6.isBinaryExpression(node)) return;
289
289
  if (node.operatorToken.kind !== ts6.SyntaxKind.QuestionQuestionToken) return;
290
+ if (isPossiblyMissingArrayBindingValue(node.left, ctx)) return;
290
291
  if (ctx.isNullable(node.left)) return;
291
292
  ctx.report(node);
292
293
  }
293
294
  };
295
+ function isPossiblyMissingArrayBindingValue(node, ctx) {
296
+ if (!ts6.isIdentifier(node)) return false;
297
+ const symbol = ctx.checker.getSymbolAtLocation(node);
298
+ if (!symbol) return false;
299
+ for (const declaration of symbol.declarations ?? []) {
300
+ if (!ts6.isBindingElement(declaration)) continue;
301
+ if (declaration.initializer || declaration.dotDotDotToken) continue;
302
+ if (!ts6.isArrayBindingPattern(declaration.parent)) continue;
303
+ const pattern = declaration.parent;
304
+ const index = pattern.elements.indexOf(declaration);
305
+ if (index < 0) continue;
306
+ if (!isTupleSlotDefinitelyPresent(ctx.checker.getTypeAtLocation(pattern), index, ctx.checker)) {
307
+ return true;
308
+ }
309
+ }
310
+ return false;
311
+ }
312
+ function isTupleSlotDefinitelyPresent(type, index, checker) {
313
+ if (type.isUnion()) {
314
+ return type.types.every((member) => isTupleSlotDefinitelyPresent(member, index, checker));
315
+ }
316
+ const apparent = checker.getApparentType(type);
317
+ if (!checker.isTupleType(apparent)) return false;
318
+ return index < apparent.target.minLength;
319
+ }
294
320
 
295
321
  // src/rules/ts/no-optional-call.ts
296
322
  import * as ts7 from "typescript";
@@ -636,6 +662,7 @@ var preferRequiredParamWithGuard = {
636
662
  };
637
663
 
638
664
  // src/rules/cross-file/duplicate-type-declaration.ts
665
+ import * as ts18 from "typescript";
639
666
  var duplicateTypeDeclaration = {
640
667
  id: "duplicate-type-declaration",
641
668
  severity: "warning",
@@ -645,6 +672,7 @@ var duplicateTypeDeclaration = {
645
672
  for (const group of project.types.getDuplicateGroups()) {
646
673
  const files = new Set(group.map((e) => e.file));
647
674
  if (files.size < 2) continue;
675
+ if (group.every((e) => isTrivialObjectShape(e.node))) continue;
648
676
  reportDuplicateGroup(
649
677
  group,
650
678
  this.id,
@@ -657,9 +685,14 @@ var duplicateTypeDeclaration = {
657
685
  return diagnostics;
658
686
  }
659
687
  };
688
+ function isTrivialObjectShape(node) {
689
+ if (ts18.isTypeLiteralNode(node)) return node.members.length <= 1;
690
+ if (ts18.isInterfaceDeclaration(node)) return node.members.length <= 1;
691
+ return false;
692
+ }
660
693
 
661
694
  // src/rules/cross-file/duplicate-function-declaration.ts
662
- import * as ts18 from "typescript";
695
+ import * as ts19 from "typescript";
663
696
  var duplicateFunctionDeclaration = {
664
697
  id: "duplicate-function-declaration",
665
698
  severity: "warning",
@@ -684,12 +717,13 @@ var duplicateFunctionDeclaration = {
684
717
  }
685
718
  };
686
719
  function getBodyBlock(node) {
687
- if (ts18.isFunctionDeclaration(node) || ts18.isFunctionExpression(node)) return node.body;
688
- if (ts18.isArrowFunction(node)) return ts18.isBlock(node.body) ? node.body : void 0;
689
- if (ts18.isMethodDeclaration(node)) return node.body;
720
+ if (ts19.isFunctionDeclaration(node) || ts19.isFunctionExpression(node)) return node.body;
721
+ if (ts19.isArrowFunction(node)) return ts19.isBlock(node.body) ? node.body : void 0;
722
+ if (ts19.isMethodDeclaration(node)) return node.body;
690
723
  return void 0;
691
724
  }
692
725
  function isSingleStatement(node) {
726
+ if (ts19.isArrowFunction(node) && !ts19.isBlock(node.body)) return true;
693
727
  const body = getBodyBlock(node);
694
728
  return body !== void 0 && body.statements.length <= 1;
695
729
  }
@@ -697,8 +731,8 @@ function isSetter(node) {
697
731
  const body = getBodyBlock(node);
698
732
  if (!body || body.statements.length !== 1) return false;
699
733
  const stmt = body.statements[0];
700
- if (stmt === void 0 || !ts18.isExpressionStatement(stmt)) return false;
701
- return ts18.isBinaryExpression(stmt.expression) && stmt.expression.operatorToken.kind === ts18.SyntaxKind.EqualsToken;
734
+ if (stmt === void 0 || !ts19.isExpressionStatement(stmt)) return false;
735
+ return ts19.isBinaryExpression(stmt.expression) && stmt.expression.operatorToken.kind === ts19.SyntaxKind.EqualsToken;
702
736
  }
703
737
 
704
738
  // src/rules/cross-file/optional-arg-always-used.ts
@@ -733,14 +767,14 @@ var optionalArgAlwaysUsed = {
733
767
  };
734
768
 
735
769
  // src/rules/ts/no-catch-return.ts
736
- import * as ts19 from "typescript";
770
+ import * as ts20 from "typescript";
737
771
  var noCatchReturn = {
738
772
  kind: "ts",
739
773
  id: "no-catch-return",
740
774
  severity: "warning",
741
775
  message: "Catch block silently returns a fallback value with no logging; rethrow, log the error, or let it propagate",
742
776
  visit(node, ctx) {
743
- if (!ts19.isCatchClause(node)) return;
777
+ if (!ts20.isCatchClause(node)) return;
744
778
  const block = node.block;
745
779
  if (hasReturn(block) && !hasThrow(block) && !hasLogging(block)) {
746
780
  ctx.report(node);
@@ -750,57 +784,57 @@ var noCatchReturn = {
750
784
  function walkBlock(block, predicate) {
751
785
  function visit(node) {
752
786
  if (predicate(node)) return true;
753
- if (ts19.isFunctionDeclaration(node) || ts19.isFunctionExpression(node) || ts19.isArrowFunction(node)) return false;
754
- return ts19.forEachChild(node, visit) ?? false;
787
+ if (ts20.isFunctionDeclaration(node) || ts20.isFunctionExpression(node) || ts20.isArrowFunction(node)) return false;
788
+ return ts20.forEachChild(node, visit) ?? false;
755
789
  }
756
- return ts19.forEachChild(block, visit) ?? false;
790
+ return ts20.forEachChild(block, visit) ?? false;
757
791
  }
758
792
  function hasReturn(block) {
759
- return walkBlock(block, (n) => ts19.isReturnStatement(n));
793
+ return walkBlock(block, (n) => ts20.isReturnStatement(n));
760
794
  }
761
795
  function hasThrow(block) {
762
- return walkBlock(block, (n) => ts19.isThrowStatement(n));
796
+ return walkBlock(block, (n) => ts20.isThrowStatement(n));
763
797
  }
764
798
  var LOG_OBJECTS = /* @__PURE__ */ new Set(["console", "logger", "log"]);
765
799
  function hasLogging(block) {
766
800
  return walkBlock(block, (n) => {
767
- if (!ts19.isCallExpression(n)) return false;
801
+ if (!ts20.isCallExpression(n)) return false;
768
802
  const callee = n.expression;
769
- if (!ts19.isPropertyAccessExpression(callee)) return false;
770
- if (!ts19.isIdentifier(callee.expression)) return false;
803
+ if (!ts20.isPropertyAccessExpression(callee)) return false;
804
+ if (!ts20.isIdentifier(callee.expression)) return false;
771
805
  return LOG_OBJECTS.has(callee.expression.text);
772
806
  });
773
807
  }
774
808
 
775
809
  // src/rules/ts/no-error-rewrap.ts
776
- import * as ts20 from "typescript";
810
+ import * as ts21 from "typescript";
777
811
  var noErrorRewrap = {
778
812
  kind: "ts",
779
813
  id: "no-error-rewrap",
780
814
  severity: "error",
781
815
  message: "Re-wrapped error loses the original stack trace and type; use { cause: originalError } to preserve the error chain",
782
816
  visit(node, ctx) {
783
- if (!ts20.isCatchClause(node)) return;
817
+ if (!ts21.isCatchClause(node)) return;
784
818
  if (!node.variableDeclaration) return;
785
819
  const param = node.variableDeclaration.name;
786
- if (!ts20.isIdentifier(param)) return;
820
+ if (!ts21.isIdentifier(param)) return;
787
821
  const catchName = param.text;
788
822
  findRewraps(node.block, catchName, ctx);
789
823
  }
790
824
  };
791
825
  function findRewraps(block, catchName, ctx) {
792
826
  function visit(node) {
793
- if (ts20.isFunctionDeclaration(node) || ts20.isFunctionExpression(node) || ts20.isArrowFunction(node)) return;
794
- if (ts20.isThrowStatement(node) && node.expression && ts20.isNewExpression(node.expression)) {
827
+ if (ts21.isFunctionDeclaration(node) || ts21.isFunctionExpression(node) || ts21.isArrowFunction(node)) return;
828
+ if (ts21.isThrowStatement(node) && node.expression && ts21.isNewExpression(node.expression)) {
795
829
  const args = node.expression.arguments;
796
830
  if (args && args.length > 0 && referencesName(args, catchName) && !hasCauseArg(args)) {
797
831
  ctx.report(node);
798
832
  }
799
833
  return;
800
834
  }
801
- ts20.forEachChild(node, visit);
835
+ ts21.forEachChild(node, visit);
802
836
  }
803
- ts20.forEachChild(block, visit);
837
+ ts21.forEachChild(block, visit);
804
838
  }
805
839
  function referencesName(args, name) {
806
840
  for (const arg of args) {
@@ -809,15 +843,15 @@ function referencesName(args, name) {
809
843
  return false;
810
844
  }
811
845
  function containsIdentifier(node, name) {
812
- if (ts20.isIdentifier(node) && node.text === name) return true;
813
- return ts20.forEachChild(node, (child) => containsIdentifier(child, name) || void 0) ?? false;
846
+ if (ts21.isIdentifier(node) && node.text === name) return true;
847
+ return ts21.forEachChild(node, (child) => containsIdentifier(child, name) || void 0) ?? false;
814
848
  }
815
849
  function hasCauseArg(args) {
816
850
  for (const arg of args) {
817
- if (ts20.isObjectLiteralExpression(arg)) {
851
+ if (ts21.isObjectLiteralExpression(arg)) {
818
852
  for (const prop of arg.properties) {
819
- if (ts20.isPropertyAssignment(prop) && ts20.isIdentifier(prop.name) && prop.name.text === "cause") return true;
820
- if (ts20.isShorthandPropertyAssignment(prop) && prop.name.text === "cause") return true;
853
+ if (ts21.isPropertyAssignment(prop) && ts21.isIdentifier(prop.name) && prop.name.text === "cause") return true;
854
+ if (ts21.isShorthandPropertyAssignment(prop) && prop.name.text === "cause") return true;
821
855
  }
822
856
  }
823
857
  }
@@ -825,7 +859,7 @@ function hasCauseArg(args) {
825
859
  }
826
860
 
827
861
  // src/rules/cross-file/explicit-null-arg.ts
828
- import * as ts21 from "typescript";
862
+ import * as ts22 from "typescript";
829
863
  var explicitNullArg = {
830
864
  id: "explicit-null-arg",
831
865
  severity: "warning",
@@ -845,7 +879,7 @@ var explicitNullArg = {
845
879
  const arg = site.node.arguments[i];
846
880
  if (arg === void 0) continue;
847
881
  if (isNullishLiteral(arg)) {
848
- const val = arg.kind === ts21.SyntaxKind.NullKeyword ? "null" : "undefined";
882
+ const val = arg.kind === ts22.SyntaxKind.NullKeyword ? "null" : "undefined";
849
883
  diagnostics.push({
850
884
  ruleId: this.id,
851
885
  severity: this.severity,
@@ -918,7 +952,7 @@ function resolveCandidates(fromFile, specifier) {
918
952
  }
919
953
 
920
954
  // src/rules/cross-file/duplicate-type-name.ts
921
- import * as ts22 from "typescript";
955
+ import * as ts23 from "typescript";
922
956
  var duplicateTypeName = {
923
957
  id: "duplicate-type-name",
924
958
  severity: "warning",
@@ -929,7 +963,7 @@ var duplicateTypeName = {
929
963
  const hashes = new Set(group.map((e) => e.hash));
930
964
  if (hashes.size === 1) continue;
931
965
  const hasInferredType = group.some(
932
- (e) => !ts22.isTypeLiteralNode(e.node) && !ts22.isInterfaceDeclaration(e.node)
966
+ (e) => !ts23.isTypeLiteralNode(e.node) && !ts23.isInterfaceDeclaration(e.node)
933
967
  );
934
968
  if (hasInferredType) continue;
935
969
  reportDuplicateGroup(
@@ -969,20 +1003,21 @@ var duplicateConstantDeclaration = {
969
1003
  };
970
1004
 
971
1005
  // src/rules/ts/no-dynamic-import.ts
972
- import * as ts23 from "typescript";
1006
+ import * as ts24 from "typescript";
973
1007
  var noDynamicImport = {
974
1008
  kind: "ts",
975
1009
  id: "no-dynamic-import",
976
1010
  severity: "error",
977
1011
  message: "Dynamic import() breaks static analysis and hides dependencies; use a static import instead",
978
1012
  visit(node, ctx) {
979
- if (!ts23.isCallExpression(node)) return;
980
- if (node.expression.kind !== ts23.SyntaxKind.ImportKeyword) return;
1013
+ if (!ts24.isCallExpression(node)) return;
1014
+ if (node.expression.kind !== ts24.SyntaxKind.ImportKeyword) return;
981
1015
  ctx.report(node);
982
1016
  }
983
1017
  };
984
1018
 
985
1019
  // src/rules/cross-file/near-duplicate-function.ts
1020
+ import * as ts25 from "typescript";
986
1021
  var nearDuplicateFunction = {
987
1022
  id: "near-duplicate-function",
988
1023
  severity: "warning",
@@ -992,6 +1027,7 @@ var nearDuplicateFunction = {
992
1027
  for (const group of project.functions.getNearDuplicateGroups()) {
993
1028
  const MIN_NORMALIZED_BODY = 32;
994
1029
  if (group.every((e) => e.normalizedBodyLength < MIN_NORMALIZED_BODY)) continue;
1030
+ if (group.every(isSimpleStructure)) continue;
995
1031
  reportDuplicateGroup(
996
1032
  group,
997
1033
  this.id,
@@ -1004,38 +1040,67 @@ var nearDuplicateFunction = {
1004
1040
  return diagnostics;
1005
1041
  }
1006
1042
  };
1043
+ function getFunctionBody(node) {
1044
+ if (ts25.isFunctionDeclaration(node) || ts25.isFunctionExpression(node)) return node.body;
1045
+ if (ts25.isArrowFunction(node)) return node.body;
1046
+ if (ts25.isMethodDeclaration(node)) return node.body;
1047
+ return void 0;
1048
+ }
1049
+ function getTopLevelStatementCount(body) {
1050
+ if (ts25.isBlock(body)) return body.statements.length;
1051
+ return 1;
1052
+ }
1053
+ function hasControlFlow(node) {
1054
+ let found = false;
1055
+ function visit(current) {
1056
+ if (found) return;
1057
+ if (ts25.isIfStatement(current) || ts25.isSwitchStatement(current) || ts25.isTryStatement(current) || ts25.isForStatement(current) || ts25.isForInStatement(current) || ts25.isForOfStatement(current) || ts25.isWhileStatement(current) || ts25.isDoStatement(current)) {
1058
+ found = true;
1059
+ return;
1060
+ }
1061
+ ts25.forEachChild(current, visit);
1062
+ }
1063
+ visit(node);
1064
+ return found;
1065
+ }
1066
+ function isSimpleStructure(entry) {
1067
+ const body = getFunctionBody(entry.node);
1068
+ if (!body) return false;
1069
+ if (hasControlFlow(body)) return false;
1070
+ return getTopLevelStatementCount(body) <= 2;
1071
+ }
1007
1072
 
1008
1073
  // src/rules/cross-file/trivial-wrapper.ts
1009
- import * as ts24 from "typescript";
1010
- function getFunctionBody(node) {
1011
- if (ts24.isFunctionDeclaration(node) || ts24.isFunctionExpression(node)) {
1074
+ import * as ts26 from "typescript";
1075
+ function getFunctionBody2(node) {
1076
+ if (ts26.isFunctionDeclaration(node) || ts26.isFunctionExpression(node)) {
1012
1077
  return node.body;
1013
1078
  }
1014
- if (ts24.isArrowFunction(node)) {
1079
+ if (ts26.isArrowFunction(node)) {
1015
1080
  return node.body;
1016
1081
  }
1017
- if (ts24.isMethodDeclaration(node)) {
1082
+ if (ts26.isMethodDeclaration(node)) {
1018
1083
  return node.body;
1019
1084
  }
1020
1085
  return void 0;
1021
1086
  }
1022
1087
  function getCalleeName(expr) {
1023
- if (ts24.isIdentifier(expr)) return expr.text;
1024
- if (ts24.isPropertyAccessExpression(expr)) return expr.name.text;
1088
+ if (ts26.isIdentifier(expr)) return expr.text;
1089
+ if (ts26.isPropertyAccessExpression(expr)) return expr.name.text;
1025
1090
  return void 0;
1026
1091
  }
1027
1092
  function getTrivialCallTarget(fn) {
1028
- const body = getFunctionBody(fn.node);
1093
+ const body = getFunctionBody2(fn.node);
1029
1094
  if (!body) return null;
1030
1095
  let callExpr;
1031
- if (ts24.isBlock(body)) {
1096
+ if (ts26.isBlock(body)) {
1032
1097
  if (body.statements.length !== 1) return null;
1033
1098
  const stmt = body.statements[0];
1034
- if (!stmt || !ts24.isReturnStatement(stmt) || !stmt.expression) return null;
1035
- if (!ts24.isCallExpression(stmt.expression)) return null;
1099
+ if (!stmt || !ts26.isReturnStatement(stmt) || !stmt.expression) return null;
1100
+ if (!ts26.isCallExpression(stmt.expression)) return null;
1036
1101
  callExpr = stmt.expression;
1037
1102
  } else {
1038
- if (!ts24.isCallExpression(body)) return null;
1103
+ if (!ts26.isCallExpression(body)) return null;
1039
1104
  callExpr = body;
1040
1105
  }
1041
1106
  const calleeName = getCalleeName(callExpr.expression);
@@ -1043,7 +1108,7 @@ function getTrivialCallTarget(fn) {
1043
1108
  const paramNames = fn.params.map((p) => p.name);
1044
1109
  const args = callExpr.arguments;
1045
1110
  for (const arg of args) {
1046
- if (!ts24.isIdentifier(arg)) return null;
1111
+ if (!ts26.isIdentifier(arg)) return null;
1047
1112
  if (!paramNames.includes(arg.text)) return null;
1048
1113
  }
1049
1114
  return { calleeName };
@@ -1340,32 +1405,32 @@ function isFailOn(value) {
1340
1405
  }
1341
1406
 
1342
1407
  // src/collect/index.ts
1343
- import * as ts27 from "typescript";
1408
+ import * as ts29 from "typescript";
1344
1409
  import { createHash as createHash2 } from "crypto";
1345
1410
 
1346
1411
  // src/utils/hash.ts
1347
1412
  import { createHash } from "crypto";
1348
- import * as ts25 from "typescript";
1413
+ import * as ts27 from "typescript";
1349
1414
  function hashTypeShape(node, sourceFile) {
1350
1415
  const normalized = normalizeTypeNode(node, sourceFile);
1351
1416
  return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
1352
1417
  }
1353
1418
  function normalizeTypeNode(node, sourceFile) {
1354
- if (ts25.isTypeLiteralNode(node)) {
1419
+ if (ts27.isTypeLiteralNode(node)) {
1355
1420
  const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(";");
1356
1421
  return `{${normalized}}`;
1357
1422
  }
1358
- if (ts25.isInterfaceDeclaration(node)) {
1423
+ if (ts27.isInterfaceDeclaration(node)) {
1359
1424
  const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(";");
1360
1425
  return `{${normalized}}`;
1361
1426
  }
1362
- if (ts25.isPropertySignature(node)) {
1427
+ if (ts27.isPropertySignature(node)) {
1363
1428
  const keyName = node.name.getText(sourceFile);
1364
1429
  const optional = node.questionToken ? "?" : "";
1365
1430
  const type = node.type ? normalizeTypeNode(node.type, sourceFile) : "any";
1366
1431
  return `${keyName}${optional}:${type}`;
1367
1432
  }
1368
- if (ts25.isTypeAliasDeclaration(node)) {
1433
+ if (ts27.isTypeAliasDeclaration(node)) {
1369
1434
  return normalizeTypeNode(node.type, sourceFile);
1370
1435
  }
1371
1436
  return node.getText(sourceFile).replace(/\s+/g, " ").trim();
@@ -1531,7 +1596,7 @@ var InlineParamTypeRegistry = class extends BaseRegistry {
1531
1596
  };
1532
1597
 
1533
1598
  // src/typecheck/walk.ts
1534
- import * as ts26 from "typescript";
1599
+ import * as ts28 from "typescript";
1535
1600
  function buildContext(rule, sourceFile, checker, source, filename, diagnostics) {
1536
1601
  return {
1537
1602
  filename,
@@ -1539,7 +1604,7 @@ function buildContext(rule, sourceFile, checker, source, filename, diagnostics)
1539
1604
  sourceFile,
1540
1605
  checker,
1541
1606
  report(node, message) {
1542
- const { line, character } = ts26.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile));
1607
+ const { line, character } = ts28.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile));
1543
1608
  diagnostics.push({
1544
1609
  ruleId: rule.id,
1545
1610
  severity: rule.severity,
@@ -1550,7 +1615,7 @@ function buildContext(rule, sourceFile, checker, source, filename, diagnostics)
1550
1615
  });
1551
1616
  },
1552
1617
  reportAtOffset(offset, message) {
1553
- const { line, character } = ts26.getLineAndCharacterOfPosition(sourceFile, offset);
1618
+ const { line, character } = ts28.getLineAndCharacterOfPosition(sourceFile, offset);
1554
1619
  diagnostics.push({
1555
1620
  ruleId: rule.id,
1556
1621
  severity: rule.severity,
@@ -1601,7 +1666,7 @@ function collectProject(program, tsRules, allowedFiles) {
1601
1666
  rule.visit(node, ctx);
1602
1667
  }
1603
1668
  }
1604
- ts27.forEachChild(node, visit2);
1669
+ ts29.forEachChild(node, visit2);
1605
1670
  };
1606
1671
  var visit = visit2;
1607
1672
  const file = sourceFile.fileName;
@@ -1615,7 +1680,7 @@ function collectProject(program, tsRules, allowedFiles) {
1615
1680
  rule,
1616
1681
  ctx: buildContext(rule, sourceFile, checker, source, file, diagnostics)
1617
1682
  }));
1618
- ts27.forEachChild(sourceFile, visit2);
1683
+ ts29.forEachChild(sourceFile, visit2);
1619
1684
  }
1620
1685
  const fileHashes = /* @__PURE__ */ new Map();
1621
1686
  for (const [file, { source }] of fileMap) {
@@ -1631,52 +1696,52 @@ function collectProject(program, tsRules, allowedFiles) {
1631
1696
  return { index: { types, functions, constants, callSites, imports, files: fileMap, fileHashes, statementSequences, inlineParamTypes }, diagnostics };
1632
1697
  }
1633
1698
  function hasNonPublicModifier(node) {
1634
- if (!ts27.canHaveModifiers(node)) return false;
1635
- const mods = ts27.getModifiers(node);
1699
+ if (!ts29.canHaveModifiers(node)) return false;
1700
+ const mods = ts29.getModifiers(node);
1636
1701
  if (mods === void 0) return false;
1637
1702
  return mods.some(
1638
- (m) => m.kind === ts27.SyntaxKind.PrivateKeyword || m.kind === ts27.SyntaxKind.ProtectedKeyword
1703
+ (m) => m.kind === ts29.SyntaxKind.PrivateKeyword || m.kind === ts29.SyntaxKind.ProtectedKeyword
1639
1704
  );
1640
1705
  }
1641
1706
  function isExported(node) {
1642
- if (!ts27.canHaveModifiers(node)) return false;
1643
- const mods = ts27.getModifiers(node);
1707
+ if (!ts29.canHaveModifiers(node)) return false;
1708
+ const mods = ts29.getModifiers(node);
1644
1709
  if (mods === void 0) return false;
1645
- return mods.some((m) => m.kind === ts27.SyntaxKind.ExportKeyword);
1710
+ return mods.some((m) => m.kind === ts29.SyntaxKind.ExportKeyword);
1646
1711
  }
1647
1712
  function collectTypes(node, file, sourceFile, registry) {
1648
- if (ts27.isTypeAliasDeclaration(node)) {
1649
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1713
+ if (ts29.isTypeAliasDeclaration(node)) {
1714
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1650
1715
  registry.add(node.name.text, file, line, node.type, sourceFile, isExported(node));
1651
1716
  }
1652
- if (ts27.isInterfaceDeclaration(node)) {
1653
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1717
+ if (ts29.isInterfaceDeclaration(node)) {
1718
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1654
1719
  registry.add(node.name.text, file, line, node, sourceFile, isExported(node));
1655
1720
  }
1656
1721
  }
1657
1722
  function isConstantValue(node) {
1658
- if (ts27.isStringLiteral(node)) return true;
1659
- if (ts27.isNumericLiteral(node)) return true;
1660
- if (ts27.isNoSubstitutionTemplateLiteral(node)) return true;
1661
- if (ts27.isPrefixUnaryExpression(node)) return isConstantValue(node.operand);
1662
- if (ts27.isBinaryExpression(node)) return isConstantValue(node.left) && isConstantValue(node.right);
1723
+ if (ts29.isStringLiteral(node)) return true;
1724
+ if (ts29.isNumericLiteral(node)) return true;
1725
+ if (ts29.isNoSubstitutionTemplateLiteral(node)) return true;
1726
+ if (ts29.isPrefixUnaryExpression(node)) return isConstantValue(node.operand);
1727
+ if (ts29.isBinaryExpression(node)) return isConstantValue(node.left) && isConstantValue(node.right);
1663
1728
  return false;
1664
1729
  }
1665
1730
  function collectConstants(node, file, sourceFile, registry) {
1666
- if (!ts27.isVariableStatement(node)) return;
1667
- if (!(node.declarationList.flags & ts27.NodeFlags.Const)) return;
1731
+ if (!ts29.isVariableStatement(node)) return;
1732
+ if (!(node.declarationList.flags & ts29.NodeFlags.Const)) return;
1668
1733
  const exported = isExported(node);
1669
1734
  for (const decl of node.declarationList.declarations) {
1670
- if (!decl.initializer || !ts27.isIdentifier(decl.name)) continue;
1735
+ if (!decl.initializer || !ts29.isIdentifier(decl.name)) continue;
1671
1736
  if (!isConstantValue(decl.initializer)) continue;
1672
1737
  const valueText = decl.initializer.getText(sourceFile).replace(/\s+/g, " ").trim();
1673
1738
  const valueHash = createHash2("sha256").update(valueText).digest("hex").slice(0, 16);
1674
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, decl.getStart(sourceFile)).line + 1;
1739
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, decl.getStart(sourceFile)).line + 1;
1675
1740
  registry.add({ name: decl.name.text, file, line, valueHash, valueText, exported });
1676
1741
  }
1677
1742
  }
1678
1743
  function buildFunctionEntry(body, parameters, sourceFile, file, lineNode, name, extra) {
1679
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, lineNode.getStart(sourceFile)).line + 1;
1744
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, lineNode.getStart(sourceFile)).line + 1;
1680
1745
  const params = extractParams(parameters, sourceFile);
1681
1746
  const paramNames = params.map((p) => p.name);
1682
1747
  const hash = hashFunctionBody(body, sourceFile);
@@ -1698,17 +1763,17 @@ function buildFunctionEntry(body, parameters, sourceFile, file, lineNode, name,
1698
1763
  };
1699
1764
  }
1700
1765
  function collectFunctions(node, file, sourceFile, checker, registry) {
1701
- if (ts27.isFunctionDeclaration(node) && node.name && node.body) {
1766
+ if (ts29.isFunctionDeclaration(node) && node.name && node.body) {
1702
1767
  registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, node.name.text, {
1703
1768
  exported: isExported(node),
1704
1769
  symbol: checker.getSymbolAtLocation(node.name),
1705
1770
  node
1706
1771
  }));
1707
1772
  }
1708
- if (ts27.isVariableStatement(node)) {
1773
+ if (ts29.isVariableStatement(node)) {
1709
1774
  const exported = isExported(node);
1710
1775
  for (const decl of node.declarationList.declarations) {
1711
- if (decl.initializer && ts27.isArrowFunction(decl.initializer) && ts27.isIdentifier(decl.name)) {
1776
+ if (decl.initializer && ts29.isArrowFunction(decl.initializer) && ts29.isIdentifier(decl.name)) {
1712
1777
  const arrow = decl.initializer;
1713
1778
  registry.add(buildFunctionEntry(arrow.body, arrow.parameters, sourceFile, file, decl, decl.name.text, {
1714
1779
  exported,
@@ -1716,7 +1781,7 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
1716
1781
  node: arrow
1717
1782
  }));
1718
1783
  }
1719
- if (decl.initializer && ts27.isFunctionExpression(decl.initializer) && ts27.isIdentifier(decl.name)) {
1784
+ if (decl.initializer && ts29.isFunctionExpression(decl.initializer) && ts29.isIdentifier(decl.name)) {
1720
1785
  const fn = decl.initializer;
1721
1786
  if (fn.body) {
1722
1787
  registry.add(buildFunctionEntry(fn.body, fn.parameters, sourceFile, file, decl, decl.name.text, {
@@ -1728,22 +1793,22 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
1728
1793
  }
1729
1794
  }
1730
1795
  }
1731
- if (ts27.isPropertyAssignment(node) && (ts27.isIdentifier(node.name) || ts27.isStringLiteral(node.name))) {
1796
+ if (ts29.isPropertyAssignment(node) && (ts29.isIdentifier(node.name) || ts29.isStringLiteral(node.name))) {
1732
1797
  const init = node.initializer;
1733
1798
  const propName = node.name.text;
1734
- if (ts27.isArrowFunction(init)) {
1799
+ if (ts29.isArrowFunction(init)) {
1735
1800
  registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));
1736
1801
  }
1737
- if (ts27.isFunctionExpression(init) && init.body) {
1802
+ if (ts29.isFunctionExpression(init) && init.body) {
1738
1803
  registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));
1739
1804
  }
1740
1805
  }
1741
- if (ts27.isArrowFunction(node) || ts27.isFunctionExpression(node)) {
1806
+ if (ts29.isArrowFunction(node) || ts29.isFunctionExpression(node)) {
1742
1807
  const parent = node.parent;
1743
- if (ts27.isVariableDeclaration(parent) && ts27.isIdentifier(parent.name)) {
1744
- } else if (ts27.isPropertyAssignment(parent)) {
1808
+ if (ts29.isVariableDeclaration(parent) && ts29.isIdentifier(parent.name)) {
1809
+ } else if (ts29.isPropertyAssignment(parent)) {
1745
1810
  } else {
1746
- const body = ts27.isArrowFunction(node) ? node.body : node.body;
1811
+ const body = ts29.isArrowFunction(node) ? node.body : node.body;
1747
1812
  if (body) {
1748
1813
  const MIN_ANON_BODY = 64;
1749
1814
  if (bodyTextLength(body, sourceFile) >= MIN_ANON_BODY) {
@@ -1753,14 +1818,14 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
1753
1818
  }
1754
1819
  }
1755
1820
  }
1756
- if (ts27.isMethodDeclaration(node) && node.body && ts27.isIdentifier(node.name)) {
1821
+ if (ts29.isMethodDeclaration(node) && node.body && ts29.isIdentifier(node.name)) {
1757
1822
  const parent = node.parent;
1758
- if (ts27.isClassDeclaration(parent)) {
1823
+ if (ts29.isClassDeclaration(parent)) {
1759
1824
  if (hasNonPublicModifier(node)) return;
1760
1825
  const className = parent.name ? parent.name.text : "<anonymous>";
1761
1826
  const name = `${className}.${node.name.text}`;
1762
1827
  const implementsInterface = parent.heritageClauses?.some(
1763
- (c) => c.token === ts27.SyntaxKind.ImplementsKeyword
1828
+ (c) => c.token === ts29.SyntaxKind.ImplementsKeyword
1764
1829
  ) ?? false;
1765
1830
  registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, name, {
1766
1831
  exported: isExported(parent),
@@ -1783,16 +1848,16 @@ function extractParams(parameters, sourceFile) {
1783
1848
  }
1784
1849
  function deriveAnonymousName(node, sourceFile) {
1785
1850
  const parent = node.parent;
1786
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1787
- if (ts27.isCallExpression(parent)) {
1851
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1852
+ if (ts29.isCallExpression(parent)) {
1788
1853
  const grandparent = parent.parent;
1789
- if (ts27.isPropertyAssignment(grandparent) && ts27.isIdentifier(grandparent.name)) {
1854
+ if (ts29.isPropertyAssignment(grandparent) && ts29.isIdentifier(grandparent.name)) {
1790
1855
  return grandparent.name.text;
1791
1856
  }
1792
1857
  let calleeName = null;
1793
- if (ts27.isIdentifier(parent.expression)) {
1858
+ if (ts29.isIdentifier(parent.expression)) {
1794
1859
  calleeName = parent.expression.text;
1795
- } else if (ts27.isPropertyAccessExpression(parent.expression)) {
1860
+ } else if (ts29.isPropertyAccessExpression(parent.expression)) {
1796
1861
  calleeName = parent.expression.name.text;
1797
1862
  }
1798
1863
  if (calleeName) {
@@ -1803,7 +1868,7 @@ function deriveAnonymousName(node, sourceFile) {
1803
1868
  return `<anonymous>:${line}`;
1804
1869
  }
1805
1870
  function collectImports(node, file, imports) {
1806
- if (ts27.isImportDeclaration(node) && ts27.isStringLiteral(node.moduleSpecifier)) {
1871
+ if (ts29.isImportDeclaration(node) && ts29.isStringLiteral(node.moduleSpecifier)) {
1807
1872
  const moduleSource = node.moduleSpecifier.text;
1808
1873
  const clause = node.importClause;
1809
1874
  if (!clause) return;
@@ -1815,7 +1880,7 @@ function collectImports(node, file, imports) {
1815
1880
  source: moduleSource
1816
1881
  });
1817
1882
  }
1818
- if (clause.namedBindings && ts27.isNamedImports(clause.namedBindings)) {
1883
+ if (clause.namedBindings && ts29.isNamedImports(clause.namedBindings)) {
1819
1884
  for (const el of clause.namedBindings.elements) {
1820
1885
  imports.push({
1821
1886
  file,
@@ -1826,9 +1891,9 @@ function collectImports(node, file, imports) {
1826
1891
  }
1827
1892
  }
1828
1893
  }
1829
- if (ts27.isExportDeclaration(node) && node.moduleSpecifier && ts27.isStringLiteral(node.moduleSpecifier)) {
1894
+ if (ts29.isExportDeclaration(node) && node.moduleSpecifier && ts29.isStringLiteral(node.moduleSpecifier)) {
1830
1895
  const moduleSource = node.moduleSpecifier.text;
1831
- if (node.exportClause && ts27.isNamedExports(node.exportClause)) {
1896
+ if (node.exportClause && ts29.isNamedExports(node.exportClause)) {
1832
1897
  for (const el of node.exportClause.elements) {
1833
1898
  imports.push({
1834
1899
  file,
@@ -1841,7 +1906,7 @@ function collectImports(node, file, imports) {
1841
1906
  }
1842
1907
  }
1843
1908
  function collectStatementSequences(node, file, sourceFile, registry) {
1844
- if (!ts27.isBlock(node)) return;
1909
+ if (!ts29.isBlock(node)) return;
1845
1910
  const stmts = node.statements;
1846
1911
  const n = stmts.length;
1847
1912
  if (n < 3) return;
@@ -1858,34 +1923,34 @@ function collectStatementSequences(node, file, sourceFile, registry) {
1858
1923
  const firstStmt = window[0];
1859
1924
  const lastStmt = window[window.length - 1];
1860
1925
  if (firstStmt === void 0 || lastStmt === void 0) continue;
1861
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, firstStmt.getStart(sourceFile)).line + 1;
1862
- const endLine = ts27.getLineAndCharacterOfPosition(sourceFile, lastStmt.getEnd()).line + 1;
1926
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, firstStmt.getStart(sourceFile)).line + 1;
1927
+ const endLine = ts29.getLineAndCharacterOfPosition(sourceFile, lastStmt.getEnd()).line + 1;
1863
1928
  registry.add({ file, line, endLine, hash, normalizedHash, statementCount: size, normalizedBodyLength: normalized.length });
1864
1929
  }
1865
1930
  }
1866
1931
  }
1867
1932
  function collectInlineParamTypes(node, file, sourceFile, registry) {
1868
- if (!ts27.isTypeLiteralNode(node)) return;
1933
+ if (!ts29.isTypeLiteralNode(node)) return;
1869
1934
  const parent = node.parent;
1870
- if (!parent || !ts27.isParameter(parent)) return;
1935
+ if (!parent || !ts29.isParameter(parent)) return;
1871
1936
  if (parent.type !== node) return;
1872
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1937
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1873
1938
  registry.add(file, line, node, sourceFile);
1874
1939
  }
1875
1940
  function collectCallSites(node, file, sourceFile, checker, sites) {
1876
- if (!ts27.isCallExpression(node)) return;
1941
+ if (!ts29.isCallExpression(node)) return;
1877
1942
  let calleeName = null;
1878
- if (ts27.isIdentifier(node.expression)) {
1943
+ if (ts29.isIdentifier(node.expression)) {
1879
1944
  calleeName = node.expression.text;
1880
- } else if (ts27.isPropertyAccessExpression(node.expression)) {
1945
+ } else if (ts29.isPropertyAccessExpression(node.expression)) {
1881
1946
  calleeName = node.expression.name.text;
1882
1947
  }
1883
1948
  if (calleeName) {
1884
- const line = ts27.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1949
+ const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
1885
1950
  let symbol;
1886
1951
  try {
1887
1952
  symbol = checker.getSymbolAtLocation(node.expression);
1888
- if (symbol && symbol.flags & ts27.SymbolFlags.Alias) {
1953
+ if (symbol && symbol.flags & ts29.SymbolFlags.Alias) {
1889
1954
  symbol = checker.getAliasedSymbol(symbol);
1890
1955
  }
1891
1956
  } catch {
@@ -1905,12 +1970,12 @@ function collectAllComments(sourceFile) {
1905
1970
  const source = sourceFile.getFullText();
1906
1971
  const seen = /* @__PURE__ */ new Set();
1907
1972
  function visit(node) {
1908
- const leading = ts27.getLeadingCommentRanges(source, node.getFullStart());
1973
+ const leading = ts29.getLeadingCommentRanges(source, node.getFullStart());
1909
1974
  if (leading) {
1910
1975
  for (const r of leading) {
1911
1976
  if (seen.has(r.pos)) continue;
1912
1977
  seen.add(r.pos);
1913
- const isLine = r.kind === ts27.SyntaxKind.SingleLineCommentTrivia;
1978
+ const isLine = r.kind === ts29.SyntaxKind.SingleLineCommentTrivia;
1914
1979
  comments.push({
1915
1980
  type: isLine ? "Line" : "Block",
1916
1981
  value: source.slice(r.pos + 2, isLine ? r.end : r.end - 2),
@@ -1919,12 +1984,12 @@ function collectAllComments(sourceFile) {
1919
1984
  });
1920
1985
  }
1921
1986
  }
1922
- const trailing = ts27.getTrailingCommentRanges(source, node.getEnd());
1987
+ const trailing = ts29.getTrailingCommentRanges(source, node.getEnd());
1923
1988
  if (trailing) {
1924
1989
  for (const r of trailing) {
1925
1990
  if (seen.has(r.pos)) continue;
1926
1991
  seen.add(r.pos);
1927
- const isLine = r.kind === ts27.SyntaxKind.SingleLineCommentTrivia;
1992
+ const isLine = r.kind === ts29.SyntaxKind.SingleLineCommentTrivia;
1928
1993
  comments.push({
1929
1994
  type: isLine ? "Line" : "Block",
1930
1995
  value: source.slice(r.pos + 2, isLine ? r.end : r.end - 2),
@@ -1933,34 +1998,34 @@ function collectAllComments(sourceFile) {
1933
1998
  });
1934
1999
  }
1935
2000
  }
1936
- ts27.forEachChild(node, visit);
2001
+ ts29.forEachChild(node, visit);
1937
2002
  }
1938
2003
  visit(sourceFile);
1939
2004
  return comments;
1940
2005
  }
1941
2006
 
1942
2007
  // src/typecheck/program.ts
1943
- import * as ts28 from "typescript";
2008
+ import * as ts30 from "typescript";
1944
2009
  import { dirname as dirname2 } from "path";
1945
2010
  function createProgramFromFiles(files) {
1946
2011
  let configPath;
1947
2012
  if (files.length > 0) {
1948
- configPath = ts28.findConfigFile(dirname2(files[0]), ts28.sys.fileExists, "tsconfig.json");
2013
+ configPath = ts30.findConfigFile(dirname2(files[0]), ts30.sys.fileExists, "tsconfig.json");
1949
2014
  }
1950
2015
  if (configPath) {
1951
- const configFile = ts28.readConfigFile(configPath, ts28.sys.readFile);
1952
- const parsed = ts28.parseJsonConfigFileContent(configFile.config, ts28.sys, dirname2(configPath));
1953
- return ts28.createProgram({
2016
+ const configFile = ts30.readConfigFile(configPath, ts30.sys.readFile);
2017
+ const parsed = ts30.parseJsonConfigFileContent(configFile.config, ts30.sys, dirname2(configPath));
2018
+ return ts30.createProgram({
1954
2019
  rootNames: files,
1955
2020
  options: { ...parsed.options, skipLibCheck: true }
1956
2021
  });
1957
2022
  }
1958
- return ts28.createProgram({
2023
+ return ts30.createProgram({
1959
2024
  rootNames: files,
1960
2025
  options: {
1961
- target: ts28.ScriptTarget.ESNext,
1962
- module: ts28.ModuleKind.ESNext,
1963
- moduleResolution: ts28.ModuleResolutionKind.Bundler,
2026
+ target: ts30.ScriptTarget.ESNext,
2027
+ module: ts30.ModuleKind.ESNext,
2028
+ moduleResolution: ts30.ModuleResolutionKind.Bundler,
1964
2029
  strict: true,
1965
2030
  skipLibCheck: true,
1966
2031
  noEmit: true
@@ -2200,4 +2265,4 @@ export {
2200
2265
  executeScan,
2201
2266
  scan
2202
2267
  };
2203
- //# sourceMappingURL=chunk-RV4V5VH5.js.map
2268
+ //# sourceMappingURL=chunk-7UXUNJSF.js.map