dslop 1.6.1 → 1.7.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 (4) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +132 -32
  3. package/dist/index.cjs +774 -1736
  4. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -29710,11 +29710,11 @@ var require_visitors = __commonJS({
29710
29710
  }
29711
29711
  visitor._verified = true;
29712
29712
  }
29713
- function validateVisitorMethods(path5, val) {
29713
+ function validateVisitorMethods(path6, val) {
29714
29714
  const fns = [].concat(val);
29715
29715
  for (const fn of fns) {
29716
29716
  if (typeof fn !== "function") {
29717
- throw new TypeError(`Non-function found defined in ${path5} with type ${typeof fn}`);
29717
+ throw new TypeError(`Non-function found defined in ${path6} with type ${typeof fn}`);
29718
29718
  }
29719
29719
  }
29720
29720
  }
@@ -29759,8 +29759,8 @@ var require_visitors = __commonJS({
29759
29759
  fns = fns.map(function(fn) {
29760
29760
  let newFn = fn;
29761
29761
  if (state) {
29762
- newFn = function(path5) {
29763
- fn.call(state, path5, state);
29762
+ newFn = function(path6) {
29763
+ fn.call(state, path6, state);
29764
29764
  };
29765
29765
  }
29766
29766
  if (wrapper) {
@@ -29793,8 +29793,8 @@ var require_visitors = __commonJS({
29793
29793
  function wrapCheck(nodeType, fn) {
29794
29794
  const fnKey = `is${nodeType}`;
29795
29795
  const validator = virtualTypesValidators[fnKey];
29796
- const newFn = function(path5) {
29797
- if (validator.call(path5)) {
29796
+ const newFn = function(path6) {
29797
+ if (validator.call(path6)) {
29798
29798
  return fn.apply(this, arguments);
29799
29799
  }
29800
29800
  };
@@ -29821,24 +29821,24 @@ var require_visitors = __commonJS({
29821
29821
  }
29822
29822
  }
29823
29823
  var _environmentVisitor = {
29824
- FunctionParent(path5) {
29825
- if (path5.isArrowFunctionExpression()) return;
29826
- path5.skip();
29827
- if (path5.isMethod()) {
29828
- if (!path5.requeueComputedKeyAndDecorators) {
29829
- _context.requeueComputedKeyAndDecorators.call(path5);
29824
+ FunctionParent(path6) {
29825
+ if (path6.isArrowFunctionExpression()) return;
29826
+ path6.skip();
29827
+ if (path6.isMethod()) {
29828
+ if (!path6.requeueComputedKeyAndDecorators) {
29829
+ _context.requeueComputedKeyAndDecorators.call(path6);
29830
29830
  } else {
29831
- path5.requeueComputedKeyAndDecorators();
29831
+ path6.requeueComputedKeyAndDecorators();
29832
29832
  }
29833
29833
  }
29834
29834
  },
29835
- Property(path5) {
29836
- if (path5.isObjectProperty()) return;
29837
- path5.skip();
29838
- if (!path5.requeueComputedKeyAndDecorators) {
29839
- _context.requeueComputedKeyAndDecorators.call(path5);
29835
+ Property(path6) {
29836
+ if (path6.isObjectProperty()) return;
29837
+ path6.skip();
29838
+ if (!path6.requeueComputedKeyAndDecorators) {
29839
+ _context.requeueComputedKeyAndDecorators.call(path6);
29840
29840
  } else {
29841
- path5.requeueComputedKeyAndDecorators();
29841
+ path6.requeueComputedKeyAndDecorators();
29842
29842
  }
29843
29843
  }
29844
29844
  };
@@ -29872,14 +29872,14 @@ var require_renamer = __commonJS({
29872
29872
  node.name = state.newName;
29873
29873
  }
29874
29874
  },
29875
- Scope(path5, state) {
29876
- if (!path5.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) {
29877
- path5.skip();
29878
- if (path5.isMethod()) {
29879
- if (!path5.requeueComputedKeyAndDecorators) {
29880
- _context.requeueComputedKeyAndDecorators.call(path5);
29875
+ Scope(path6, state) {
29876
+ if (!path6.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) {
29877
+ path6.skip();
29878
+ if (path6.isMethod()) {
29879
+ if (!path6.requeueComputedKeyAndDecorators) {
29880
+ _context.requeueComputedKeyAndDecorators.call(path6);
29881
29881
  } else {
29882
- path5.requeueComputedKeyAndDecorators();
29882
+ path6.requeueComputedKeyAndDecorators();
29883
29883
  }
29884
29884
  }
29885
29885
  }
@@ -29899,9 +29899,9 @@ var require_renamer = __commonJS({
29899
29899
  }
29900
29900
  }
29901
29901
  },
29902
- "AssignmentExpression|Declaration|VariableDeclarator"(path5, state) {
29903
- if (path5.isVariableDeclaration()) return;
29904
- const ids = path5.isAssignmentExpression() ? getAssignmentIdentifiers(path5.node) : path5.getOuterBindingIdentifiers();
29902
+ "AssignmentExpression|Declaration|VariableDeclarator"(path6, state) {
29903
+ if (path6.isVariableDeclaration()) return;
29904
+ const ids = path6.isAssignmentExpression() ? getAssignmentIdentifiers(path6.node) : path6.getOuterBindingIdentifiers();
29905
29905
  for (const name in ids) {
29906
29906
  if (name === state.oldName) ids[name].name = state.newName;
29907
29907
  }
@@ -29931,11 +29931,11 @@ var require_renamer = __commonJS({
29931
29931
  }
29932
29932
  maybeExportDeclar.splitExportDeclaration();
29933
29933
  }
29934
- maybeConvertFromClassFunctionDeclaration(path5) {
29935
- return path5;
29934
+ maybeConvertFromClassFunctionDeclaration(path6) {
29935
+ return path6;
29936
29936
  }
29937
- maybeConvertFromClassFunctionExpression(path5) {
29938
- return path5;
29937
+ maybeConvertFromClassFunctionExpression(path6) {
29938
+ return path6;
29939
29939
  }
29940
29940
  rename() {
29941
29941
  const {
@@ -29945,9 +29945,9 @@ var require_renamer = __commonJS({
29945
29945
  } = this;
29946
29946
  const {
29947
29947
  scope,
29948
- path: path5
29948
+ path: path6
29949
29949
  } = binding;
29950
- const parentDeclar = path5.find((path6) => path6.isDeclaration() || path6.isFunctionExpression() || path6.isClassExpression());
29950
+ const parentDeclar = path6.find((path7) => path7.isDeclaration() || path7.isFunctionExpression() || path7.isClassExpression());
29951
29951
  if (parentDeclar) {
29952
29952
  const bindingIds = parentDeclar.getOuterBindingIdentifiers();
29953
29953
  if (bindingIds[oldName] === binding.identifier) {
@@ -29973,8 +29973,8 @@ var require_renamer = __commonJS({
29973
29973
  this.binding.identifier.name = newName;
29974
29974
  }
29975
29975
  if (parentDeclar) {
29976
- this.maybeConvertFromClassFunctionDeclaration(path5);
29977
- this.maybeConvertFromClassFunctionExpression(path5);
29976
+ this.maybeConvertFromClassFunctionDeclaration(path6);
29977
+ this.maybeConvertFromClassFunctionExpression(path6);
29978
29978
  }
29979
29979
  }
29980
29980
  };
@@ -29997,17 +29997,17 @@ var require_traverseForScope = __commonJS({
29997
29997
  var {
29998
29998
  VISITOR_KEYS
29999
29999
  } = _t;
30000
- function traverseForScope(path5, visitors, state) {
30000
+ function traverseForScope(path6, visitors, state) {
30001
30001
  const exploded = (0, _visitors.explode)(visitors);
30002
30002
  if (exploded.enter || exploded.exit) {
30003
30003
  throw new Error("Should not be used with enter/exit visitors.");
30004
30004
  }
30005
- _traverse2(path5.parentPath, path5.parent, path5.node, path5.container, path5.key, path5.listKey, path5.hub, path5);
30005
+ _traverse2(path6.parentPath, path6.parent, path6.node, path6.container, path6.key, path6.listKey, path6.hub, path6);
30006
30006
  function _traverse2(parentPath, parent, node, container, key, listKey, hub, inPath) {
30007
30007
  if (!node) {
30008
30008
  return;
30009
30009
  }
30010
- const path6 = inPath || _index.NodePath.get({
30010
+ const path7 = inPath || _index.NodePath.get({
30011
30011
  hub,
30012
30012
  parentPath,
30013
30013
  parent,
@@ -30015,21 +30015,21 @@ var require_traverseForScope = __commonJS({
30015
30015
  listKey,
30016
30016
  key
30017
30017
  });
30018
- _context.setScope.call(path6);
30018
+ _context.setScope.call(path7);
30019
30019
  const visitor = exploded[node.type];
30020
30020
  if (visitor) {
30021
30021
  if (visitor.enter) {
30022
30022
  for (const visit of visitor.enter) {
30023
- visit.call(state, path6, state);
30023
+ visit.call(state, path7, state);
30024
30024
  }
30025
30025
  }
30026
30026
  if (visitor.exit) {
30027
30027
  for (const visit of visitor.exit) {
30028
- visit.call(state, path6, state);
30028
+ visit.call(state, path7, state);
30029
30029
  }
30030
30030
  }
30031
30031
  }
30032
- if (path6.shouldSkip) {
30032
+ if (path7.shouldSkip) {
30033
30033
  return;
30034
30034
  }
30035
30035
  const keys = VISITOR_KEYS[node.type];
@@ -30042,10 +30042,10 @@ var require_traverseForScope = __commonJS({
30042
30042
  if (Array.isArray(prop)) {
30043
30043
  for (let i = 0; i < prop.length; i++) {
30044
30044
  const value = prop[i];
30045
- _traverse2(path6, node, value, prop, i, key2);
30045
+ _traverse2(path7, node, value, prop, i, key2);
30046
30046
  }
30047
30047
  } else {
30048
- _traverse2(path6, node, prop, node, key2, null);
30048
+ _traverse2(path7, node, prop, node, key2, null);
30049
30049
  }
30050
30050
  }
30051
30051
  }
@@ -30065,7 +30065,7 @@ var require_binding = __commonJS({
30065
30065
  constructor({
30066
30066
  identifier,
30067
30067
  scope,
30068
- path: path5,
30068
+ path: path6,
30069
30069
  kind
30070
30070
  }) {
30071
30071
  this.identifier = void 0;
@@ -30079,10 +30079,10 @@ var require_binding = __commonJS({
30079
30079
  this.references = 0;
30080
30080
  this.identifier = identifier;
30081
30081
  this.scope = scope;
30082
- this.path = path5;
30082
+ this.path = path6;
30083
30083
  this.kind = kind;
30084
- if ((kind === "var" || kind === "hoisted") && isInitInLoop(path5)) {
30085
- this.reassign(path5);
30084
+ if ((kind === "var" || kind === "hoisted") && isInitInLoop(path6)) {
30085
+ this.reassign(path6);
30086
30086
  }
30087
30087
  this.clearValue();
30088
30088
  }
@@ -30100,20 +30100,20 @@ var require_binding = __commonJS({
30100
30100
  this.hasValue = false;
30101
30101
  this.value = null;
30102
30102
  }
30103
- reassign(path5) {
30103
+ reassign(path6) {
30104
30104
  this.constant = false;
30105
- if (this.constantViolations.includes(path5)) {
30105
+ if (this.constantViolations.includes(path6)) {
30106
30106
  return;
30107
30107
  }
30108
- this.constantViolations.push(path5);
30108
+ this.constantViolations.push(path6);
30109
30109
  }
30110
- reference(path5) {
30111
- if (this.referencePaths.includes(path5)) {
30110
+ reference(path6) {
30111
+ if (this.referencePaths.includes(path6)) {
30112
30112
  return;
30113
30113
  }
30114
30114
  this.referenced = true;
30115
30115
  this.references++;
30116
- this.referencePaths.push(path5);
30116
+ this.referencePaths.push(path6);
30117
30117
  }
30118
30118
  dereference() {
30119
30119
  this.references--;
@@ -30121,12 +30121,12 @@ var require_binding = __commonJS({
30121
30121
  }
30122
30122
  };
30123
30123
  exports2.default = Binding;
30124
- function isInitInLoop(path5) {
30125
- const isFunctionDeclarationOrHasInit = !path5.isVariableDeclarator() || path5.node.init;
30124
+ function isInitInLoop(path6) {
30125
+ const isFunctionDeclarationOrHasInit = !path6.isVariableDeclarator() || path6.node.init;
30126
30126
  for (let {
30127
30127
  parentPath,
30128
30128
  key
30129
- } = path5; parentPath; {
30129
+ } = path6; parentPath; {
30130
30130
  parentPath,
30131
30131
  key
30132
30132
  } = parentPath) {
@@ -30165,11 +30165,11 @@ var require_cache = __commonJS({
30165
30165
  function clearScope() {
30166
30166
  exports2.scope = scope = /* @__PURE__ */ new WeakMap();
30167
30167
  }
30168
- function getCachedPaths(path5) {
30168
+ function getCachedPaths(path6) {
30169
30169
  const {
30170
30170
  parent,
30171
30171
  parentPath
30172
- } = path5;
30172
+ } = path6;
30173
30173
  return pathsCache.get(parent);
30174
30174
  }
30175
30175
  function getOrCreateCachedPaths(node, parentPath) {
@@ -30450,131 +30450,131 @@ var require_scope = __commonJS({
30450
30450
  scope.bindings = /* @__PURE__ */ Object.create(null);
30451
30451
  scope.globals = /* @__PURE__ */ Object.create(null);
30452
30452
  }
30453
- function isAnonymousFunctionExpression(path5) {
30454
- return path5.isFunctionExpression() && !path5.node.id || path5.isArrowFunctionExpression();
30453
+ function isAnonymousFunctionExpression(path6) {
30454
+ return path6.isFunctionExpression() && !path6.node.id || path6.isArrowFunctionExpression();
30455
30455
  }
30456
30456
  {
30457
30457
  NOT_LOCAL_BINDING = /* @__PURE__ */ Symbol.for("should not be considered a local binding");
30458
30458
  }
30459
30459
  var NOT_LOCAL_BINDING;
30460
30460
  var collectorVisitor = {
30461
- ForStatement(path5) {
30462
- const declar = path5.get("init");
30461
+ ForStatement(path6) {
30462
+ const declar = path6.get("init");
30463
30463
  if (declar.isVar()) {
30464
30464
  const {
30465
30465
  scope
30466
- } = path5;
30466
+ } = path6;
30467
30467
  const parentScope = scope.getFunctionParent() || scope.getProgramParent();
30468
30468
  parentScope.registerBinding("var", declar);
30469
30469
  }
30470
30470
  },
30471
- Declaration(path5) {
30472
- if (path5.isBlockScoped()) return;
30473
- if (path5.isImportDeclaration()) return;
30474
- if (path5.isExportDeclaration()) return;
30475
- const parent = path5.scope.getFunctionParent() || path5.scope.getProgramParent();
30476
- parent.registerDeclaration(path5);
30471
+ Declaration(path6) {
30472
+ if (path6.isBlockScoped()) return;
30473
+ if (path6.isImportDeclaration()) return;
30474
+ if (path6.isExportDeclaration()) return;
30475
+ const parent = path6.scope.getFunctionParent() || path6.scope.getProgramParent();
30476
+ parent.registerDeclaration(path6);
30477
30477
  },
30478
- ImportDeclaration(path5) {
30479
- const parent = path5.scope.getBlockParent();
30480
- parent.registerDeclaration(path5);
30478
+ ImportDeclaration(path6) {
30479
+ const parent = path6.scope.getBlockParent();
30480
+ parent.registerDeclaration(path6);
30481
30481
  },
30482
- TSImportEqualsDeclaration(path5) {
30483
- const parent = path5.scope.getBlockParent();
30484
- parent.registerDeclaration(path5);
30482
+ TSImportEqualsDeclaration(path6) {
30483
+ const parent = path6.scope.getBlockParent();
30484
+ parent.registerDeclaration(path6);
30485
30485
  },
30486
- ReferencedIdentifier(path5, state) {
30487
- if (t2.isTSQualifiedName(path5.parent) && path5.parent.right === path5.node) {
30486
+ ReferencedIdentifier(path6, state) {
30487
+ if (t2.isTSQualifiedName(path6.parent) && path6.parent.right === path6.node) {
30488
30488
  return;
30489
30489
  }
30490
- if (path5.parentPath.isTSImportEqualsDeclaration()) return;
30491
- state.references.push(path5);
30490
+ if (path6.parentPath.isTSImportEqualsDeclaration()) return;
30491
+ state.references.push(path6);
30492
30492
  },
30493
- ForXStatement(path5, state) {
30494
- const left = path5.get("left");
30493
+ ForXStatement(path6, state) {
30494
+ const left = path6.get("left");
30495
30495
  if (left.isPattern() || left.isIdentifier()) {
30496
- state.constantViolations.push(path5);
30496
+ state.constantViolations.push(path6);
30497
30497
  } else if (left.isVar()) {
30498
30498
  const {
30499
30499
  scope
30500
- } = path5;
30500
+ } = path6;
30501
30501
  const parentScope = scope.getFunctionParent() || scope.getProgramParent();
30502
30502
  parentScope.registerBinding("var", left);
30503
30503
  }
30504
30504
  },
30505
30505
  ExportDeclaration: {
30506
- exit(path5) {
30506
+ exit(path6) {
30507
30507
  const {
30508
30508
  node,
30509
30509
  scope
30510
- } = path5;
30510
+ } = path6;
30511
30511
  if (isExportAllDeclaration(node)) return;
30512
30512
  const declar = node.declaration;
30513
30513
  if (isClassDeclaration2(declar) || isFunctionDeclaration2(declar)) {
30514
30514
  const id = declar.id;
30515
30515
  if (!id) return;
30516
30516
  const binding = scope.getBinding(id.name);
30517
- binding == null || binding.reference(path5);
30517
+ binding == null || binding.reference(path6);
30518
30518
  } else if (isVariableDeclaration2(declar)) {
30519
30519
  for (const decl of declar.declarations) {
30520
30520
  for (const name of Object.keys(getBindingIdentifiers(decl))) {
30521
30521
  const binding = scope.getBinding(name);
30522
- binding == null || binding.reference(path5);
30522
+ binding == null || binding.reference(path6);
30523
30523
  }
30524
30524
  }
30525
30525
  }
30526
30526
  }
30527
30527
  },
30528
- LabeledStatement(path5) {
30529
- path5.scope.getBlockParent().registerDeclaration(path5);
30528
+ LabeledStatement(path6) {
30529
+ path6.scope.getBlockParent().registerDeclaration(path6);
30530
30530
  },
30531
- AssignmentExpression(path5, state) {
30532
- state.assignments.push(path5);
30531
+ AssignmentExpression(path6, state) {
30532
+ state.assignments.push(path6);
30533
30533
  },
30534
- UpdateExpression(path5, state) {
30535
- state.constantViolations.push(path5);
30534
+ UpdateExpression(path6, state) {
30535
+ state.constantViolations.push(path6);
30536
30536
  },
30537
- UnaryExpression(path5, state) {
30538
- if (path5.node.operator === "delete") {
30539
- state.constantViolations.push(path5);
30537
+ UnaryExpression(path6, state) {
30538
+ if (path6.node.operator === "delete") {
30539
+ state.constantViolations.push(path6);
30540
30540
  }
30541
30541
  },
30542
- BlockScoped(path5) {
30543
- let scope = path5.scope;
30544
- if (scope.path === path5) scope = scope.parent;
30542
+ BlockScoped(path6) {
30543
+ let scope = path6.scope;
30544
+ if (scope.path === path6) scope = scope.parent;
30545
30545
  const parent = scope.getBlockParent();
30546
- parent.registerDeclaration(path5);
30547
- if (path5.isClassDeclaration() && path5.node.id) {
30548
- const id = path5.node.id;
30546
+ parent.registerDeclaration(path6);
30547
+ if (path6.isClassDeclaration() && path6.node.id) {
30548
+ const id = path6.node.id;
30549
30549
  const name = id.name;
30550
- path5.scope.bindings[name] = path5.scope.parent.getBinding(name);
30550
+ path6.scope.bindings[name] = path6.scope.parent.getBinding(name);
30551
30551
  }
30552
30552
  },
30553
- CatchClause(path5) {
30554
- path5.scope.registerBinding("let", path5);
30553
+ CatchClause(path6) {
30554
+ path6.scope.registerBinding("let", path6);
30555
30555
  },
30556
- Function(path5) {
30557
- const params = path5.get("params");
30556
+ Function(path6) {
30557
+ const params = path6.get("params");
30558
30558
  for (const param of params) {
30559
- path5.scope.registerBinding("param", param);
30559
+ path6.scope.registerBinding("param", param);
30560
30560
  }
30561
- if (path5.isFunctionExpression() && path5.node.id && !path5.node.id[NOT_LOCAL_BINDING]) {
30562
- path5.scope.registerBinding("local", path5.get("id"), path5);
30561
+ if (path6.isFunctionExpression() && path6.node.id && !path6.node.id[NOT_LOCAL_BINDING]) {
30562
+ path6.scope.registerBinding("local", path6.get("id"), path6);
30563
30563
  }
30564
30564
  },
30565
- ClassExpression(path5) {
30566
- if (path5.node.id && !path5.node.id[NOT_LOCAL_BINDING]) {
30567
- path5.scope.registerBinding("local", path5.get("id"), path5);
30565
+ ClassExpression(path6) {
30566
+ if (path6.node.id && !path6.node.id[NOT_LOCAL_BINDING]) {
30567
+ path6.scope.registerBinding("local", path6.get("id"), path6);
30568
30568
  }
30569
30569
  },
30570
- TSTypeAnnotation(path5) {
30571
- path5.skip();
30570
+ TSTypeAnnotation(path6) {
30571
+ path6.skip();
30572
30572
  }
30573
30573
  };
30574
30574
  var scopeVisitor;
30575
30575
  var uid = 0;
30576
30576
  var Scope = class _Scope {
30577
- constructor(path5) {
30577
+ constructor(path6) {
30578
30578
  this.uid = void 0;
30579
30579
  this.path = void 0;
30580
30580
  this.block = void 0;
@@ -30588,15 +30588,15 @@ var require_scope = __commonJS({
30588
30588
  this.crawling = void 0;
30589
30589
  const {
30590
30590
  node
30591
- } = path5;
30591
+ } = path6;
30592
30592
  const cached = _cache.scope.get(node);
30593
- if ((cached == null ? void 0 : cached.path) === path5) {
30593
+ if ((cached == null ? void 0 : cached.path) === path6) {
30594
30594
  return cached;
30595
30595
  }
30596
30596
  _cache.scope.set(node, this);
30597
30597
  this.uid = uid++;
30598
30598
  this.block = node;
30599
- this.path = path5;
30599
+ this.path = path6;
30600
30600
  this.labels = /* @__PURE__ */ new Map();
30601
30601
  this.inited = false;
30602
30602
  {
@@ -30618,14 +30618,14 @@ var require_scope = __commonJS({
30618
30618
  }
30619
30619
  get parent() {
30620
30620
  var _parent;
30621
- let parent, path5 = this.path;
30621
+ let parent, path6 = this.path;
30622
30622
  do {
30623
30623
  var _path;
30624
- const shouldSkip = path5.key === "key" || path5.listKey === "decorators";
30625
- path5 = path5.parentPath;
30626
- if (shouldSkip && path5.isMethod()) path5 = path5.parentPath;
30627
- if ((_path = path5) != null && _path.isScope()) parent = path5;
30628
- } while (path5 && !parent);
30624
+ const shouldSkip = path6.key === "key" || path6.listKey === "decorators";
30625
+ path6 = path6.parentPath;
30626
+ if (shouldSkip && path6.isMethod()) path6 = path6.parentPath;
30627
+ if ((_path = path6) != null && _path.isScope()) parent = path6;
30628
+ } while (path6 && !parent);
30629
30629
  return (_parent = parent) == null ? void 0 : _parent.scope;
30630
30630
  }
30631
30631
  get references() {
@@ -30742,62 +30742,62 @@ var require_scope = __commonJS({
30742
30742
  getLabel(name) {
30743
30743
  return this.labels.get(name);
30744
30744
  }
30745
- registerLabel(path5) {
30746
- this.labels.set(path5.node.label.name, path5);
30745
+ registerLabel(path6) {
30746
+ this.labels.set(path6.node.label.name, path6);
30747
30747
  }
30748
- registerDeclaration(path5) {
30749
- if (path5.isLabeledStatement()) {
30750
- this.registerLabel(path5);
30751
- } else if (path5.isFunctionDeclaration()) {
30752
- this.registerBinding("hoisted", path5.get("id"), path5);
30753
- } else if (path5.isVariableDeclaration()) {
30754
- const declarations = path5.get("declarations");
30748
+ registerDeclaration(path6) {
30749
+ if (path6.isLabeledStatement()) {
30750
+ this.registerLabel(path6);
30751
+ } else if (path6.isFunctionDeclaration()) {
30752
+ this.registerBinding("hoisted", path6.get("id"), path6);
30753
+ } else if (path6.isVariableDeclaration()) {
30754
+ const declarations = path6.get("declarations");
30755
30755
  const {
30756
30756
  kind
30757
- } = path5.node;
30757
+ } = path6.node;
30758
30758
  for (const declar of declarations) {
30759
30759
  this.registerBinding(kind === "using" || kind === "await using" ? "const" : kind, declar);
30760
30760
  }
30761
- } else if (path5.isClassDeclaration()) {
30762
- if (path5.node.declare) return;
30763
- this.registerBinding("let", path5);
30764
- } else if (path5.isImportDeclaration()) {
30765
- const isTypeDeclaration = path5.node.importKind === "type" || path5.node.importKind === "typeof";
30766
- const specifiers = path5.get("specifiers");
30761
+ } else if (path6.isClassDeclaration()) {
30762
+ if (path6.node.declare) return;
30763
+ this.registerBinding("let", path6);
30764
+ } else if (path6.isImportDeclaration()) {
30765
+ const isTypeDeclaration = path6.node.importKind === "type" || path6.node.importKind === "typeof";
30766
+ const specifiers = path6.get("specifiers");
30767
30767
  for (const specifier of specifiers) {
30768
30768
  const isTypeSpecifier = isTypeDeclaration || specifier.isImportSpecifier() && (specifier.node.importKind === "type" || specifier.node.importKind === "typeof");
30769
30769
  this.registerBinding(isTypeSpecifier ? "unknown" : "module", specifier);
30770
30770
  }
30771
- } else if (path5.isExportDeclaration()) {
30772
- const declar = path5.get("declaration");
30771
+ } else if (path6.isExportDeclaration()) {
30772
+ const declar = path6.get("declaration");
30773
30773
  if (declar.isClassDeclaration() || declar.isFunctionDeclaration() || declar.isVariableDeclaration()) {
30774
30774
  this.registerDeclaration(declar);
30775
30775
  }
30776
30776
  } else {
30777
- this.registerBinding("unknown", path5);
30777
+ this.registerBinding("unknown", path6);
30778
30778
  }
30779
30779
  }
30780
30780
  buildUndefinedNode() {
30781
30781
  return buildUndefinedNode();
30782
30782
  }
30783
- registerConstantViolation(path5) {
30784
- const ids = path5.getAssignmentIdentifiers();
30783
+ registerConstantViolation(path6) {
30784
+ const ids = path6.getAssignmentIdentifiers();
30785
30785
  for (const name of Object.keys(ids)) {
30786
30786
  var _this$getBinding;
30787
- (_this$getBinding = this.getBinding(name)) == null || _this$getBinding.reassign(path5);
30787
+ (_this$getBinding = this.getBinding(name)) == null || _this$getBinding.reassign(path6);
30788
30788
  }
30789
30789
  }
30790
- registerBinding(kind, path5, bindingPath = path5) {
30790
+ registerBinding(kind, path6, bindingPath = path6) {
30791
30791
  if (!kind) throw new ReferenceError("no `kind`");
30792
- if (path5.isVariableDeclaration()) {
30793
- const declarators = path5.get("declarations");
30792
+ if (path6.isVariableDeclaration()) {
30793
+ const declarators = path6.get("declarations");
30794
30794
  for (const declar of declarators) {
30795
30795
  this.registerBinding(kind, declar);
30796
30796
  }
30797
30797
  return;
30798
30798
  }
30799
30799
  const parent = this.getProgramParent();
30800
- const ids = path5.getOuterBindingIdentifiers(true);
30800
+ const ids = path6.getOuterBindingIdentifiers(true);
30801
30801
  for (const name of Object.keys(ids)) {
30802
30802
  {
30803
30803
  parent.references[name] = true;
@@ -30945,7 +30945,7 @@ var require_scope = __commonJS({
30945
30945
  }
30946
30946
  }
30947
30947
  crawl() {
30948
- const path5 = this.path;
30948
+ const path6 = this.path;
30949
30949
  ;
30950
30950
  resetScope(this);
30951
30951
  this.data = /* @__PURE__ */ Object.create(null);
@@ -30964,29 +30964,29 @@ var require_scope = __commonJS({
30964
30964
  };
30965
30965
  this.crawling = true;
30966
30966
  scopeVisitor || (scopeVisitor = _index.default.visitors.merge([{
30967
- Scope(path6) {
30968
- resetScope(path6.scope);
30967
+ Scope(path7) {
30968
+ resetScope(path7.scope);
30969
30969
  }
30970
30970
  }, collectorVisitor]));
30971
- if (path5.type !== "Program") {
30972
- const typeVisitors = scopeVisitor[path5.type];
30971
+ if (path6.type !== "Program") {
30972
+ const typeVisitors = scopeVisitor[path6.type];
30973
30973
  if (typeVisitors) {
30974
30974
  for (const visit of typeVisitors.enter) {
30975
- visit.call(state, path5, state);
30975
+ visit.call(state, path6, state);
30976
30976
  }
30977
30977
  }
30978
30978
  }
30979
30979
  {
30980
- path5.traverse(scopeVisitor, state);
30980
+ path6.traverse(scopeVisitor, state);
30981
30981
  }
30982
30982
  this.crawling = false;
30983
- for (const path6 of state.assignments) {
30984
- const ids = path6.getAssignmentIdentifiers();
30983
+ for (const path7 of state.assignments) {
30984
+ const ids = path7.getAssignmentIdentifiers();
30985
30985
  for (const name of Object.keys(ids)) {
30986
- if (path6.scope.getBinding(name)) continue;
30986
+ if (path7.scope.getBinding(name)) continue;
30987
30987
  programParent.addGlobal(ids[name]);
30988
30988
  }
30989
- path6.scope.registerConstantViolation(path6);
30989
+ path7.scope.registerConstantViolation(path7);
30990
30990
  }
30991
30991
  for (const ref of state.references) {
30992
30992
  const binding = ref.scope.getBinding(ref.node.name);
@@ -30996,19 +30996,19 @@ var require_scope = __commonJS({
30996
30996
  programParent.addGlobal(ref.node);
30997
30997
  }
30998
30998
  }
30999
- for (const path6 of state.constantViolations) {
31000
- path6.scope.registerConstantViolation(path6);
30999
+ for (const path7 of state.constantViolations) {
31000
+ path7.scope.registerConstantViolation(path7);
31001
31001
  }
31002
31002
  }
31003
31003
  push(opts) {
31004
- let path5 = this.path;
31005
- if (path5.isPattern()) {
31006
- path5 = this.getPatternParent().path;
31007
- } else if (!path5.isBlockStatement() && !path5.isProgram()) {
31008
- path5 = this.getBlockParent().path;
31004
+ let path6 = this.path;
31005
+ if (path6.isPattern()) {
31006
+ path6 = this.getPatternParent().path;
31007
+ } else if (!path6.isBlockStatement() && !path6.isProgram()) {
31008
+ path6 = this.getBlockParent().path;
31009
31009
  }
31010
- if (path5.isSwitchStatement()) {
31011
- path5 = (this.getFunctionParent() || this.getProgramParent()).path;
31010
+ if (path6.isSwitchStatement()) {
31011
+ path6 = (this.getFunctionParent() || this.getProgramParent()).path;
31012
31012
  }
31013
31013
  const {
31014
31014
  init,
@@ -31016,29 +31016,29 @@ var require_scope = __commonJS({
31016
31016
  kind = "var",
31017
31017
  id
31018
31018
  } = opts;
31019
- if (!init && !unique && (kind === "var" || kind === "let") && isAnonymousFunctionExpression(path5) && isCallExpression2(path5.parent, {
31020
- callee: path5.node
31021
- }) && path5.parent.arguments.length <= path5.node.params.length && isIdentifier2(id)) {
31022
- path5.pushContainer("params", id);
31023
- path5.scope.registerBinding("param", path5.get("params")[path5.node.params.length - 1]);
31019
+ if (!init && !unique && (kind === "var" || kind === "let") && isAnonymousFunctionExpression(path6) && isCallExpression2(path6.parent, {
31020
+ callee: path6.node
31021
+ }) && path6.parent.arguments.length <= path6.node.params.length && isIdentifier2(id)) {
31022
+ path6.pushContainer("params", id);
31023
+ path6.scope.registerBinding("param", path6.get("params")[path6.node.params.length - 1]);
31024
31024
  return;
31025
31025
  }
31026
- if (path5.isLoop() || path5.isCatchClause() || path5.isFunction()) {
31027
- path5.ensureBlock();
31028
- path5 = path5.get("body");
31026
+ if (path6.isLoop() || path6.isCatchClause() || path6.isFunction()) {
31027
+ path6.ensureBlock();
31028
+ path6 = path6.get("body");
31029
31029
  }
31030
31030
  const blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist;
31031
31031
  const dataKey = `declaration:${kind}:${blockHoist}`;
31032
- let declarPath = !unique && path5.getData(dataKey);
31032
+ let declarPath = !unique && path6.getData(dataKey);
31033
31033
  if (!declarPath) {
31034
31034
  const declar = variableDeclaration(kind, []);
31035
31035
  declar._blockHoist = blockHoist;
31036
- [declarPath] = path5.unshiftContainer("body", [declar]);
31037
- if (!unique) path5.setData(dataKey, declarPath);
31036
+ [declarPath] = path6.unshiftContainer("body", [declar]);
31037
+ if (!unique) path6.setData(dataKey, declarPath);
31038
31038
  }
31039
31039
  const declarator = variableDeclarator(id, init);
31040
31040
  const len = declarPath.node.declarations.push(declarator);
31041
- path5.scope.registerBinding(kind, declarPath.get("declarations")[len - 1]);
31041
+ path6.scope.registerBinding(kind, declarPath.get("declarations")[len - 1]);
31042
31042
  }
31043
31043
  getProgramParent() {
31044
31044
  let scope = this;
@@ -31185,15 +31185,15 @@ var require_scope = __commonJS({
31185
31185
  const binding = this.bindings[name];
31186
31186
  if (!binding) continue;
31187
31187
  const {
31188
- path: path5
31188
+ path: path6
31189
31189
  } = binding;
31190
- if (!path5.isVariableDeclarator()) continue;
31190
+ if (!path6.isVariableDeclarator()) continue;
31191
31191
  const {
31192
31192
  parent,
31193
31193
  parentPath
31194
- } = path5;
31194
+ } = path6;
31195
31195
  if (parent.kind !== "var" || seen.has(parent)) continue;
31196
- seen.add(path5.parent);
31196
+ seen.add(path6.parent);
31197
31197
  let firstId;
31198
31198
  const init = [];
31199
31199
  for (const decl of parent.declarations) {
@@ -31800,16 +31800,16 @@ var require_resolve_uri_umd = __commonJS({
31800
31800
  }
31801
31801
  function parseFileUrl(input) {
31802
31802
  const match2 = fileRegex.exec(input);
31803
- const path5 = match2[2];
31804
- return makeUrl("file:", "", match2[1] || "", "", isAbsolutePath(path5) ? path5 : "/" + path5, match2[3] || "", match2[4] || "");
31803
+ const path6 = match2[2];
31804
+ return makeUrl("file:", "", match2[1] || "", "", isAbsolutePath(path6) ? path6 : "/" + path6, match2[3] || "", match2[4] || "");
31805
31805
  }
31806
- function makeUrl(scheme, user, host, port, path5, query, hash) {
31806
+ function makeUrl(scheme, user, host, port, path6, query, hash) {
31807
31807
  return {
31808
31808
  scheme,
31809
31809
  user,
31810
31810
  host,
31811
31811
  port,
31812
- path: path5,
31812
+ path: path6,
31813
31813
  query,
31814
31814
  hash,
31815
31815
  type: 7
@@ -31839,11 +31839,11 @@ var require_resolve_uri_umd = __commonJS({
31839
31839
  url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
31840
31840
  return url;
31841
31841
  }
31842
- function stripPathFilename(path5) {
31843
- if (path5.endsWith("/.."))
31844
- return path5;
31845
- const index = path5.lastIndexOf("/");
31846
- return path5.slice(0, index + 1);
31842
+ function stripPathFilename(path6) {
31843
+ if (path6.endsWith("/.."))
31844
+ return path6;
31845
+ const index = path6.lastIndexOf("/");
31846
+ return path6.slice(0, index + 1);
31847
31847
  }
31848
31848
  function mergePaths(url, base) {
31849
31849
  normalizePath(base, base.type);
@@ -31881,14 +31881,14 @@ var require_resolve_uri_umd = __commonJS({
31881
31881
  pieces[pointer++] = piece;
31882
31882
  positive++;
31883
31883
  }
31884
- let path5 = "";
31884
+ let path6 = "";
31885
31885
  for (let i = 1; i < pointer; i++) {
31886
- path5 += "/" + pieces[i];
31886
+ path6 += "/" + pieces[i];
31887
31887
  }
31888
- if (!path5 || addTrailingSlash && !path5.endsWith("/..")) {
31889
- path5 += "/";
31888
+ if (!path6 || addTrailingSlash && !path6.endsWith("/..")) {
31889
+ path6 += "/";
31890
31890
  }
31891
- url.path = path5;
31891
+ url.path = path6;
31892
31892
  }
31893
31893
  function resolve(input, base) {
31894
31894
  if (!input && !base)
@@ -31929,13 +31929,13 @@ var require_resolve_uri_umd = __commonJS({
31929
31929
  case 3:
31930
31930
  return queryHash;
31931
31931
  case 4: {
31932
- const path5 = url.path.slice(1);
31933
- if (!path5)
31932
+ const path6 = url.path.slice(1);
31933
+ if (!path6)
31934
31934
  return queryHash || ".";
31935
- if (isRelative(base || input) && !isRelative(path5)) {
31936
- return "./" + path5 + queryHash;
31935
+ if (isRelative(base || input) && !isRelative(path6)) {
31936
+ return "./" + path6 + queryHash;
31937
31937
  }
31938
- return path5 + queryHash;
31938
+ return path6 + queryHash;
31939
31939
  }
31940
31940
  case 5:
31941
31941
  return url.path + queryHash;
@@ -32034,10 +32034,10 @@ var require_trace_mapping_umd = __commonJS({
32034
32034
  module3.exports = __toCommonJS(trace_mapping_exports);
32035
32035
  var import_sourcemap_codec = __toESM2(require_sourcemap_codec());
32036
32036
  var import_resolve_uri = __toESM2(require_resolve_uri());
32037
- function stripFilename(path5) {
32038
- if (!path5) return "";
32039
- const index = path5.lastIndexOf("/");
32040
- return path5.slice(0, index + 1);
32037
+ function stripFilename(path6) {
32038
+ if (!path6) return "";
32039
+ const index = path6.lastIndexOf("/");
32040
+ return path6.slice(0, index + 1);
32041
32041
  }
32042
32042
  function resolver(mapUrl, sourceRoot) {
32043
32043
  const from = stripFilename(mapUrl);
@@ -38533,56 +38533,56 @@ var require_ancestry = __commonJS({
38533
38533
  VISITOR_KEYS
38534
38534
  } = _t;
38535
38535
  function findParent(callback) {
38536
- let path5 = this;
38537
- while (path5 = path5.parentPath) {
38538
- if (callback(path5)) return path5;
38536
+ let path6 = this;
38537
+ while (path6 = path6.parentPath) {
38538
+ if (callback(path6)) return path6;
38539
38539
  }
38540
38540
  return null;
38541
38541
  }
38542
38542
  function find(callback) {
38543
- let path5 = this;
38543
+ let path6 = this;
38544
38544
  do {
38545
- if (callback(path5)) return path5;
38546
- } while (path5 = path5.parentPath);
38545
+ if (callback(path6)) return path6;
38546
+ } while (path6 = path6.parentPath);
38547
38547
  return null;
38548
38548
  }
38549
38549
  function getFunctionParent() {
38550
38550
  return this.findParent((p) => p.isFunction());
38551
38551
  }
38552
38552
  function getStatementParent() {
38553
- let path5 = this;
38553
+ let path6 = this;
38554
38554
  do {
38555
- if (!path5.parentPath || Array.isArray(path5.container) && path5.isStatement()) {
38555
+ if (!path6.parentPath || Array.isArray(path6.container) && path6.isStatement()) {
38556
38556
  break;
38557
38557
  } else {
38558
- path5 = path5.parentPath;
38558
+ path6 = path6.parentPath;
38559
38559
  }
38560
- } while (path5);
38561
- if (path5 && (path5.isProgram() || path5.isFile())) {
38560
+ } while (path6);
38561
+ if (path6 && (path6.isProgram() || path6.isFile())) {
38562
38562
  throw new Error("File/Program node, we can't possibly find a statement parent to this");
38563
38563
  }
38564
- return path5;
38564
+ return path6;
38565
38565
  }
38566
38566
  function getEarliestCommonAncestorFrom(paths) {
38567
38567
  return this.getDeepestCommonAncestorFrom(paths, function(deepest, i, ancestries) {
38568
38568
  let earliest;
38569
38569
  const keys = VISITOR_KEYS[deepest.type];
38570
38570
  for (const ancestry of ancestries) {
38571
- const path5 = ancestry[i + 1];
38571
+ const path6 = ancestry[i + 1];
38572
38572
  if (!earliest) {
38573
- earliest = path5;
38573
+ earliest = path6;
38574
38574
  continue;
38575
38575
  }
38576
- if (path5.listKey && earliest.listKey === path5.listKey) {
38577
- if (path5.key < earliest.key) {
38578
- earliest = path5;
38576
+ if (path6.listKey && earliest.listKey === path6.listKey) {
38577
+ if (path6.key < earliest.key) {
38578
+ earliest = path6;
38579
38579
  continue;
38580
38580
  }
38581
38581
  }
38582
38582
  const earliestKeyIndex = keys.indexOf(earliest.parentKey);
38583
- const currentKeyIndex = keys.indexOf(path5.parentKey);
38583
+ const currentKeyIndex = keys.indexOf(path6.parentKey);
38584
38584
  if (earliestKeyIndex > currentKeyIndex) {
38585
- earliest = path5;
38585
+ earliest = path6;
38586
38586
  }
38587
38587
  }
38588
38588
  return earliest;
@@ -38597,11 +38597,11 @@ var require_ancestry = __commonJS({
38597
38597
  }
38598
38598
  let minDepth = Infinity;
38599
38599
  let lastCommonIndex, lastCommon;
38600
- const ancestries = paths.map((path5) => {
38600
+ const ancestries = paths.map((path6) => {
38601
38601
  const ancestry = [];
38602
38602
  do {
38603
- ancestry.unshift(path5);
38604
- } while ((path5 = path5.parentPath) && path5 !== this);
38603
+ ancestry.unshift(path6);
38604
+ } while ((path6 = path6.parentPath) && path6 !== this);
38605
38605
  if (ancestry.length < minDepth) {
38606
38606
  minDepth = ancestry.length;
38607
38607
  }
@@ -38629,11 +38629,11 @@ var require_ancestry = __commonJS({
38629
38629
  }
38630
38630
  }
38631
38631
  function getAncestry() {
38632
- let path5 = this;
38632
+ let path6 = this;
38633
38633
  const paths = [];
38634
38634
  do {
38635
- paths.push(path5);
38636
- } while (path5 = path5.parentPath);
38635
+ paths.push(path6);
38636
+ } while (path6 = path6.parentPath);
38637
38637
  return paths;
38638
38638
  }
38639
38639
  function isAncestor(maybeDescendant) {
@@ -38643,10 +38643,10 @@ var require_ancestry = __commonJS({
38643
38643
  return !!this.findParent((parent) => parent === maybeAncestor);
38644
38644
  }
38645
38645
  function inType(...candidateTypes) {
38646
- let path5 = this;
38647
- while (path5) {
38648
- if (candidateTypes.includes(path5.node.type)) return true;
38649
- path5 = path5.parentPath;
38646
+ let path6 = this;
38647
+ while (path6) {
38648
+ if (candidateTypes.includes(path6.node.type)) return true;
38649
+ path6 = path6.parentPath;
38650
38650
  }
38651
38651
  return false;
38652
38652
  }
@@ -38719,14 +38719,14 @@ var require_inferer_reference = __commonJS({
38719
38719
  } else if (node.name === "arguments") {
38720
38720
  }
38721
38721
  }
38722
- function getTypeAnnotationBindingConstantViolations(binding, path5, name) {
38722
+ function getTypeAnnotationBindingConstantViolations(binding, path6, name) {
38723
38723
  const types2 = [];
38724
38724
  const functionConstantViolations = [];
38725
- let constantViolations = getConstantViolationsBefore(binding, path5, functionConstantViolations);
38726
- const testType = getConditionalAnnotation(binding, path5, name);
38725
+ let constantViolations = getConstantViolationsBefore(binding, path6, functionConstantViolations);
38726
+ const testType = getConditionalAnnotation(binding, path6, name);
38727
38727
  if (testType) {
38728
38728
  const testConstantViolations = getConstantViolationsBefore(binding, testType.ifStatement);
38729
- constantViolations = constantViolations.filter((path6) => !testConstantViolations.includes(path6));
38729
+ constantViolations = constantViolations.filter((path7) => !testConstantViolations.includes(path7));
38730
38730
  types2.push(testType.typeAnnotation);
38731
38731
  }
38732
38732
  if (constantViolations.length) {
@@ -38740,20 +38740,20 @@ var require_inferer_reference = __commonJS({
38740
38740
  }
38741
38741
  return (0, _util.createUnionType)(types2);
38742
38742
  }
38743
- function getConstantViolationsBefore(binding, path5, functions) {
38743
+ function getConstantViolationsBefore(binding, path6, functions) {
38744
38744
  const violations = binding.constantViolations.slice();
38745
38745
  violations.unshift(binding.path);
38746
38746
  return violations.filter((violation) => {
38747
38747
  violation = violation.resolve();
38748
- const status = violation._guessExecutionStatusRelativeTo(path5);
38748
+ const status = violation._guessExecutionStatusRelativeTo(path6);
38749
38749
  if (functions && status === "unknown") functions.push(violation);
38750
38750
  return status === "before";
38751
38751
  });
38752
38752
  }
38753
- function inferAnnotationFromBinaryExpression(name, path5) {
38754
- const operator = path5.node.operator;
38755
- const right = path5.get("right").resolve();
38756
- const left = path5.get("left").resolve();
38753
+ function inferAnnotationFromBinaryExpression(name, path6) {
38754
+ const operator = path6.node.operator;
38755
+ const right = path6.get("right").resolve();
38756
+ const left = path6.get("left").resolve();
38757
38757
  let target;
38758
38758
  if (left.isIdentifier({
38759
38759
  name
@@ -38797,11 +38797,11 @@ var require_inferer_reference = __commonJS({
38797
38797
  if (typeof typeValue !== "string") return;
38798
38798
  return createTypeAnnotationBasedOnTypeof(typeValue);
38799
38799
  }
38800
- function getParentConditionalPath(binding, path5, name) {
38800
+ function getParentConditionalPath(binding, path6, name) {
38801
38801
  let parentPath;
38802
- while (parentPath = path5.parentPath) {
38802
+ while (parentPath = path6.parentPath) {
38803
38803
  if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) {
38804
- if (path5.key === "test") {
38804
+ if (path6.key === "test") {
38805
38805
  return;
38806
38806
  }
38807
38807
  return parentPath;
@@ -38809,24 +38809,24 @@ var require_inferer_reference = __commonJS({
38809
38809
  if (parentPath.isFunction()) {
38810
38810
  if (name == null || parentPath.parentPath.scope.getBinding(name) !== binding) return;
38811
38811
  }
38812
- path5 = parentPath;
38812
+ path6 = parentPath;
38813
38813
  }
38814
38814
  }
38815
- function getConditionalAnnotation(binding, path5, name) {
38816
- const ifStatement = getParentConditionalPath(binding, path5, name);
38815
+ function getConditionalAnnotation(binding, path6, name) {
38816
+ const ifStatement = getParentConditionalPath(binding, path6, name);
38817
38817
  if (!ifStatement) return;
38818
38818
  const test = ifStatement.get("test");
38819
38819
  const paths = [test];
38820
38820
  const types2 = [];
38821
38821
  for (let i = 0; i < paths.length; i++) {
38822
- const path6 = paths[i];
38823
- if (path6.isLogicalExpression()) {
38824
- if (path6.node.operator === "&&") {
38825
- paths.push(path6.get("left"));
38826
- paths.push(path6.get("right"));
38827
- }
38828
- } else if (path6.isBinaryExpression()) {
38829
- const type = inferAnnotationFromBinaryExpression(name, path6);
38822
+ const path7 = paths[i];
38823
+ if (path7.isLogicalExpression()) {
38824
+ if (path7.node.operator === "&&") {
38825
+ paths.push(path7.get("left"));
38826
+ paths.push(path7.get("right"));
38827
+ }
38828
+ } else if (path7.isBinaryExpression()) {
38829
+ const type = inferAnnotationFromBinaryExpression(name, path7);
38830
38830
  if (type) types2.push(type);
38831
38831
  }
38832
38832
  }
@@ -39644,12 +39644,12 @@ var require_hoister = __commonJS({
39644
39644
  variableDeclarator
39645
39645
  } = _t2;
39646
39646
  var referenceVisitor = {
39647
- ReferencedIdentifier(path5, state) {
39648
- if (path5.isJSXIdentifier() && react.isCompatTag(path5.node.name) && !path5.parentPath.isJSXMemberExpression()) {
39647
+ ReferencedIdentifier(path6, state) {
39648
+ if (path6.isJSXIdentifier() && react.isCompatTag(path6.node.name) && !path6.parentPath.isJSXMemberExpression()) {
39649
39649
  return;
39650
39650
  }
39651
- if (path5.node.name === "this") {
39652
- let scope = path5.scope;
39651
+ if (path6.node.name === "this") {
39652
+ let scope = path6.scope;
39653
39653
  do {
39654
39654
  if (scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) {
39655
39655
  break;
@@ -39657,21 +39657,21 @@ var require_hoister = __commonJS({
39657
39657
  } while (scope = scope.parent);
39658
39658
  if (scope) state.breakOnScopePaths.push(scope.path);
39659
39659
  }
39660
- const binding = path5.scope.getBinding(path5.node.name);
39660
+ const binding = path6.scope.getBinding(path6.node.name);
39661
39661
  if (!binding) return;
39662
39662
  for (const violation of binding.constantViolations) {
39663
39663
  if (violation.scope !== binding.path.scope) {
39664
39664
  state.mutableBinding = true;
39665
- path5.stop();
39665
+ path6.stop();
39666
39666
  return;
39667
39667
  }
39668
39668
  }
39669
- if (binding !== state.scope.getBinding(path5.node.name)) return;
39670
- state.bindings[path5.node.name] = binding;
39669
+ if (binding !== state.scope.getBinding(path6.node.name)) return;
39670
+ state.bindings[path6.node.name] = binding;
39671
39671
  }
39672
39672
  };
39673
39673
  var PathHoister = class {
39674
- constructor(path5, scope) {
39674
+ constructor(path6, scope) {
39675
39675
  this.breakOnScopePaths = void 0;
39676
39676
  this.bindings = void 0;
39677
39677
  this.mutableBinding = void 0;
@@ -39684,7 +39684,7 @@ var require_hoister = __commonJS({
39684
39684
  this.mutableBinding = false;
39685
39685
  this.scopes = [];
39686
39686
  this.scope = scope;
39687
- this.path = path5;
39687
+ this.path = path6;
39688
39688
  this.attachAfter = false;
39689
39689
  }
39690
39690
  isCompatibleScope(scope) {
@@ -39710,11 +39710,11 @@ var require_hoister = __commonJS({
39710
39710
  } while (scope = scope.parent);
39711
39711
  }
39712
39712
  getAttachmentPath() {
39713
- let path5 = this._getAttachmentPath();
39714
- if (!path5) return;
39715
- let targetScope = path5.scope;
39716
- if (targetScope.path === path5) {
39717
- targetScope = path5.scope.parent;
39713
+ let path6 = this._getAttachmentPath();
39714
+ if (!path6) return;
39715
+ let targetScope = path6.scope;
39716
+ if (targetScope.path === path6) {
39717
+ targetScope = path6.scope.parent;
39718
39718
  }
39719
39719
  if (targetScope.path.isProgram() || targetScope.path.isFunction()) {
39720
39720
  for (const name of Object.keys(this.bindings)) {
@@ -39724,18 +39724,18 @@ var require_hoister = __commonJS({
39724
39724
  continue;
39725
39725
  }
39726
39726
  const bindingParentPath = this.getAttachmentParentForPath(binding.path);
39727
- if (bindingParentPath.key >= path5.key) {
39727
+ if (bindingParentPath.key >= path6.key) {
39728
39728
  this.attachAfter = true;
39729
- path5 = binding.path;
39729
+ path6 = binding.path;
39730
39730
  for (const violationPath of binding.constantViolations) {
39731
- if (this.getAttachmentParentForPath(violationPath).key > path5.key) {
39732
- path5 = violationPath;
39731
+ if (this.getAttachmentParentForPath(violationPath).key > path6.key) {
39732
+ path6 = violationPath;
39733
39733
  }
39734
39734
  }
39735
39735
  }
39736
39736
  }
39737
39737
  }
39738
- return path5;
39738
+ return path6;
39739
39739
  }
39740
39740
  _getAttachmentPath() {
39741
39741
  const scopes = this.scopes;
@@ -39760,13 +39760,13 @@ var require_hoister = __commonJS({
39760
39760
  const scope = this.scopes.pop();
39761
39761
  if (scope) return this.getAttachmentParentForPath(scope.path);
39762
39762
  }
39763
- getAttachmentParentForPath(path5) {
39763
+ getAttachmentParentForPath(path6) {
39764
39764
  do {
39765
- if (!path5.parentPath || Array.isArray(path5.container) && path5.isStatement()) {
39766
- return path5;
39765
+ if (!path6.parentPath || Array.isArray(path6.container) && path6.isStatement()) {
39766
+ return path6;
39767
39767
  }
39768
- } while (path5 = path5.parentPath);
39769
- return path5;
39768
+ } while (path6 = path6.parentPath);
39769
+ return path6;
39770
39770
  }
39771
39771
  hasOwnParamBindings(scope) {
39772
39772
  for (const name of Object.keys(this.bindings)) {
@@ -39868,18 +39868,18 @@ var require_modification = __commonJS({
39868
39868
  for (let i = 0; i < nodes.length; i++) {
39869
39869
  var _this$context;
39870
39870
  const to = from + i;
39871
- const path5 = this.getSibling(to);
39872
- paths.push(path5);
39871
+ const path6 = this.getSibling(to);
39872
+ paths.push(path6);
39873
39873
  if ((_this$context = this.context) != null && _this$context.queue) {
39874
- _context.pushContext.call(path5, this.context);
39874
+ _context.pushContext.call(path6, this.context);
39875
39875
  }
39876
39876
  }
39877
39877
  const contexts = _context._getQueueContexts.call(this);
39878
- for (const path5 of paths) {
39879
- _context.setScope.call(path5);
39880
- path5.debug("Inserted.");
39878
+ for (const path6 of paths) {
39879
+ _context.setScope.call(path6);
39880
+ path6.debug("Inserted.");
39881
39881
  for (const context of contexts) {
39882
- context.maybeQueue(path5, true);
39882
+ context.maybeQueue(path6, true);
39883
39883
  }
39884
39884
  }
39885
39885
  return paths;
@@ -39891,8 +39891,8 @@ var require_modification = __commonJS({
39891
39891
  return _containerInsert.call(this, this.key + 1, nodes);
39892
39892
  }
39893
39893
  var last = (arr) => arr[arr.length - 1];
39894
- function isHiddenInSequenceExpression(path5) {
39895
- return isSequenceExpression(path5.parent) && (last(path5.parent.expressions) !== path5.node || isHiddenInSequenceExpression(path5.parentPath));
39894
+ function isHiddenInSequenceExpression(path6) {
39895
+ return isSequenceExpression(path6.parent) && (last(path6.parent.expressions) !== path6.node || isHiddenInSequenceExpression(path6.parentPath));
39896
39896
  }
39897
39897
  function isAlmostConstantAssignment(node, scope) {
39898
39898
  if (!isAssignmentExpression2(node) || !isIdentifier2(node.left)) {
@@ -39966,9 +39966,9 @@ var require_modification = __commonJS({
39966
39966
  if (!this.parent) return;
39967
39967
  const paths = (0, _cache.getCachedPaths)(this);
39968
39968
  if (!paths) return;
39969
- for (const [, path5] of paths) {
39970
- if (typeof path5.key === "number" && path5.container === this.container && path5.key >= fromIndex) {
39971
- path5.key += incrementBy;
39969
+ for (const [, path6] of paths) {
39970
+ if (typeof path6.key === "number" && path6.container === this.container && path6.key >= fromIndex) {
39971
+ path6.key += incrementBy;
39972
39972
  }
39973
39973
  }
39974
39974
  }
@@ -40002,27 +40002,27 @@ var require_modification = __commonJS({
40002
40002
  _removal._assertUnremoved.call(this);
40003
40003
  const verifiedNodes = _verifyNodeList.call(this, nodes);
40004
40004
  const container = this.node[listKey];
40005
- const path5 = _index.default.get({
40005
+ const path6 = _index.default.get({
40006
40006
  parentPath: this,
40007
40007
  parent: this.node,
40008
40008
  container,
40009
40009
  listKey,
40010
40010
  key: 0
40011
40011
  }).setContext(this.context);
40012
- return _containerInsertBefore.call(path5, verifiedNodes);
40012
+ return _containerInsertBefore.call(path6, verifiedNodes);
40013
40013
  }
40014
40014
  function pushContainer(listKey, nodes) {
40015
40015
  _removal._assertUnremoved.call(this);
40016
40016
  const verifiedNodes = _verifyNodeList.call(this, nodes);
40017
40017
  const container = this.node[listKey];
40018
- const path5 = _index.default.get({
40018
+ const path6 = _index.default.get({
40019
40019
  parentPath: this,
40020
40020
  parent: this.node,
40021
40021
  container,
40022
40022
  listKey,
40023
40023
  key: container.length
40024
40024
  }).setContext(this.context);
40025
- return path5.replaceWithMultiple(verifiedNodes);
40025
+ return path6.replaceWithMultiple(verifiedNodes);
40026
40026
  }
40027
40027
  {
40028
40028
  exports2.hoist = function hoist(scope = this.scope) {
@@ -40202,9 +40202,9 @@ var require_replacement = __commonJS({
40202
40202
  id
40203
40203
  }));
40204
40204
  const completionRecords = callee.getCompletionRecords();
40205
- for (const path5 of completionRecords) {
40206
- if (!path5.isExpressionStatement()) continue;
40207
- const loop = path5.findParent((path6) => path6.isLoop());
40205
+ for (const path6 of completionRecords) {
40206
+ if (!path6.isExpressionStatement()) continue;
40207
+ const loop = path6.findParent((path7) => path7.isLoop());
40208
40208
  if (loop) {
40209
40209
  let uid = loop.getData("expressionReplacementReturnUid");
40210
40210
  if (!uid) {
@@ -40214,9 +40214,9 @@ var require_replacement = __commonJS({
40214
40214
  } else {
40215
40215
  uid = identifier(uid.name);
40216
40216
  }
40217
- path5.get("expression").replaceWith(assignmentExpression("=", cloneNode(uid), path5.node.expression));
40217
+ path6.get("expression").replaceWith(assignmentExpression("=", cloneNode(uid), path6.node.expression));
40218
40218
  } else {
40219
- path5.replaceWith(returnStatement(path5.node.expression));
40219
+ path6.replaceWith(returnStatement(path6.node.expression));
40220
40220
  }
40221
40221
  }
40222
40222
  callee.arrowFunctionToExpression();
@@ -40325,16 +40325,16 @@ var require_evaluation = __commonJS({
40325
40325
  const res = this.evaluate();
40326
40326
  if (res.confident) return !!res.value;
40327
40327
  }
40328
- function deopt(path5, state) {
40328
+ function deopt(path6, state) {
40329
40329
  if (!state.confident) return;
40330
- state.deoptPath = path5;
40330
+ state.deoptPath = path6;
40331
40331
  state.confident = false;
40332
40332
  }
40333
40333
  var Globals = /* @__PURE__ */ new Map([["undefined", void 0], ["Infinity", Infinity], ["NaN", NaN]]);
40334
- function evaluateCached(path5, state) {
40334
+ function evaluateCached(path6, state) {
40335
40335
  const {
40336
40336
  node
40337
- } = path5;
40337
+ } = path6;
40338
40338
  const {
40339
40339
  seen
40340
40340
  } = state;
@@ -40343,7 +40343,7 @@ var require_evaluation = __commonJS({
40343
40343
  if (existing.resolved) {
40344
40344
  return existing.value;
40345
40345
  } else {
40346
- deopt(path5, state);
40346
+ deopt(path6, state);
40347
40347
  return;
40348
40348
  }
40349
40349
  } else {
@@ -40351,7 +40351,7 @@ var require_evaluation = __commonJS({
40351
40351
  resolved: false
40352
40352
  };
40353
40353
  seen.set(node, item);
40354
- const val = _evaluate(path5, state);
40354
+ const val = _evaluate(path6, state);
40355
40355
  if (state.confident) {
40356
40356
  item.resolved = true;
40357
40357
  item.value = val;
@@ -40359,55 +40359,55 @@ var require_evaluation = __commonJS({
40359
40359
  return val;
40360
40360
  }
40361
40361
  }
40362
- function _evaluate(path5, state) {
40362
+ function _evaluate(path6, state) {
40363
40363
  if (!state.confident) return;
40364
- if (path5.isSequenceExpression()) {
40365
- const exprs = path5.get("expressions");
40364
+ if (path6.isSequenceExpression()) {
40365
+ const exprs = path6.get("expressions");
40366
40366
  return evaluateCached(exprs[exprs.length - 1], state);
40367
40367
  }
40368
- if (path5.isStringLiteral() || path5.isNumericLiteral() || path5.isBooleanLiteral()) {
40369
- return path5.node.value;
40368
+ if (path6.isStringLiteral() || path6.isNumericLiteral() || path6.isBooleanLiteral()) {
40369
+ return path6.node.value;
40370
40370
  }
40371
- if (path5.isNullLiteral()) {
40371
+ if (path6.isNullLiteral()) {
40372
40372
  return null;
40373
40373
  }
40374
- if (path5.isTemplateLiteral()) {
40375
- return evaluateQuasis(path5, path5.node.quasis, state);
40374
+ if (path6.isTemplateLiteral()) {
40375
+ return evaluateQuasis(path6, path6.node.quasis, state);
40376
40376
  }
40377
- if (path5.isTaggedTemplateExpression() && path5.get("tag").isMemberExpression()) {
40378
- const object = path5.get("tag.object");
40377
+ if (path6.isTaggedTemplateExpression() && path6.get("tag").isMemberExpression()) {
40378
+ const object = path6.get("tag.object");
40379
40379
  const {
40380
40380
  node: {
40381
40381
  name
40382
40382
  }
40383
40383
  } = object;
40384
- const property = path5.get("tag.property");
40385
- if (object.isIdentifier() && name === "String" && !path5.scope.getBinding(name) && property.isIdentifier() && property.node.name === "raw") {
40386
- return evaluateQuasis(path5, path5.node.quasi.quasis, state, true);
40384
+ const property = path6.get("tag.property");
40385
+ if (object.isIdentifier() && name === "String" && !path6.scope.getBinding(name) && property.isIdentifier() && property.node.name === "raw") {
40386
+ return evaluateQuasis(path6, path6.node.quasi.quasis, state, true);
40387
40387
  }
40388
40388
  }
40389
- if (path5.isConditionalExpression()) {
40390
- const testResult = evaluateCached(path5.get("test"), state);
40389
+ if (path6.isConditionalExpression()) {
40390
+ const testResult = evaluateCached(path6.get("test"), state);
40391
40391
  if (!state.confident) return;
40392
40392
  if (testResult) {
40393
- return evaluateCached(path5.get("consequent"), state);
40393
+ return evaluateCached(path6.get("consequent"), state);
40394
40394
  } else {
40395
- return evaluateCached(path5.get("alternate"), state);
40395
+ return evaluateCached(path6.get("alternate"), state);
40396
40396
  }
40397
40397
  }
40398
- if (path5.isExpressionWrapper()) {
40399
- return evaluateCached(path5.get("expression"), state);
40398
+ if (path6.isExpressionWrapper()) {
40399
+ return evaluateCached(path6.get("expression"), state);
40400
40400
  }
40401
- if (path5.isMemberExpression() && !path5.parentPath.isCallExpression({
40402
- callee: path5.node
40401
+ if (path6.isMemberExpression() && !path6.parentPath.isCallExpression({
40402
+ callee: path6.node
40403
40403
  })) {
40404
- const property = path5.get("property");
40405
- const object = path5.get("object");
40404
+ const property = path6.get("property");
40405
+ const object = path6.get("object");
40406
40406
  if (object.isLiteral()) {
40407
40407
  const value = object.node.value;
40408
40408
  const type = typeof value;
40409
40409
  let key = null;
40410
- if (path5.node.computed) {
40410
+ if (path6.node.computed) {
40411
40411
  key = evaluateCached(property, state);
40412
40412
  if (!state.confident) return;
40413
40413
  } else if (property.isIdentifier()) {
@@ -40418,10 +40418,10 @@ var require_evaluation = __commonJS({
40418
40418
  }
40419
40419
  }
40420
40420
  }
40421
- if (path5.isReferencedIdentifier()) {
40422
- const binding = path5.scope.getBinding(path5.node.name);
40421
+ if (path6.isReferencedIdentifier()) {
40422
+ const binding = path6.scope.getBinding(path6.node.name);
40423
40423
  if (binding) {
40424
- if (binding.constantViolations.length > 0 || path5.node.start < binding.path.node.end) {
40424
+ if (binding.constantViolations.length > 0 || path6.node.start < binding.path.node.end) {
40425
40425
  deopt(binding.path, state);
40426
40426
  return;
40427
40427
  }
@@ -40430,7 +40430,7 @@ var require_evaluation = __commonJS({
40430
40430
  let hasUnsafeBlock = !bindingPathScope.path.parentPath.isBlockStatement();
40431
40431
  for (let scope = bindingPathScope.parent; scope; scope = scope.parent) {
40432
40432
  var _scope$path$parentPat;
40433
- if (scope === path5.scope) {
40433
+ if (scope === path6.scope) {
40434
40434
  if (hasUnsafeBlock) {
40435
40435
  deopt(binding.path, state);
40436
40436
  return;
@@ -40446,7 +40446,7 @@ var require_evaluation = __commonJS({
40446
40446
  return binding.value;
40447
40447
  }
40448
40448
  }
40449
- const name = path5.node.name;
40449
+ const name = path6.node.name;
40450
40450
  if (Globals.has(name)) {
40451
40451
  if (!binding) {
40452
40452
  return Globals.get(name);
@@ -40454,9 +40454,9 @@ var require_evaluation = __commonJS({
40454
40454
  deopt(binding.path, state);
40455
40455
  return;
40456
40456
  }
40457
- const resolved = path5.resolve();
40458
- if (resolved === path5) {
40459
- deopt(path5, state);
40457
+ const resolved = path6.resolve();
40458
+ if (resolved === path6) {
40459
+ deopt(path6, state);
40460
40460
  return;
40461
40461
  }
40462
40462
  const value = evaluateCached(resolved, state);
@@ -40466,19 +40466,19 @@ var require_evaluation = __commonJS({
40466
40466
  }
40467
40467
  return value;
40468
40468
  }
40469
- if (path5.isUnaryExpression({
40469
+ if (path6.isUnaryExpression({
40470
40470
  prefix: true
40471
40471
  })) {
40472
- if (path5.node.operator === "void") {
40472
+ if (path6.node.operator === "void") {
40473
40473
  return void 0;
40474
40474
  }
40475
- const argument = path5.get("argument");
40476
- if (path5.node.operator === "typeof" && (argument.isFunction() || argument.isClass())) {
40475
+ const argument = path6.get("argument");
40476
+ if (path6.node.operator === "typeof" && (argument.isFunction() || argument.isClass())) {
40477
40477
  return "function";
40478
40478
  }
40479
40479
  const arg = evaluateCached(argument, state);
40480
40480
  if (!state.confident) return;
40481
- switch (path5.node.operator) {
40481
+ switch (path6.node.operator) {
40482
40482
  case "!":
40483
40483
  return !arg;
40484
40484
  case "+":
@@ -40491,9 +40491,9 @@ var require_evaluation = __commonJS({
40491
40491
  return typeof arg;
40492
40492
  }
40493
40493
  }
40494
- if (path5.isArrayExpression()) {
40494
+ if (path6.isArrayExpression()) {
40495
40495
  const arr = [];
40496
- const elems = path5.get("elements");
40496
+ const elems = path6.get("elements");
40497
40497
  for (const elem of elems) {
40498
40498
  const elemValue = elem.evaluate();
40499
40499
  if (elemValue.confident) {
@@ -40505,9 +40505,9 @@ var require_evaluation = __commonJS({
40505
40505
  }
40506
40506
  return arr;
40507
40507
  }
40508
- if (path5.isObjectExpression()) {
40508
+ if (path6.isObjectExpression()) {
40509
40509
  const obj = {};
40510
- const props = path5.get("properties");
40510
+ const props = path6.get("properties");
40511
40511
  for (const prop of props) {
40512
40512
  if (prop.isObjectMethod() || prop.isSpreadElement()) {
40513
40513
  deopt(prop, state);
@@ -40538,14 +40538,14 @@ var require_evaluation = __commonJS({
40538
40538
  }
40539
40539
  return obj;
40540
40540
  }
40541
- if (path5.isLogicalExpression()) {
40541
+ if (path6.isLogicalExpression()) {
40542
40542
  const wasConfident = state.confident;
40543
- const left = evaluateCached(path5.get("left"), state);
40543
+ const left = evaluateCached(path6.get("left"), state);
40544
40544
  const leftConfident = state.confident;
40545
40545
  state.confident = wasConfident;
40546
- const right = evaluateCached(path5.get("right"), state);
40546
+ const right = evaluateCached(path6.get("right"), state);
40547
40547
  const rightConfident = state.confident;
40548
- switch (path5.node.operator) {
40548
+ switch (path6.node.operator) {
40549
40549
  case "||":
40550
40550
  state.confident = leftConfident && (!!left || rightConfident);
40551
40551
  if (!state.confident) return;
@@ -40560,12 +40560,12 @@ var require_evaluation = __commonJS({
40560
40560
  return left != null ? left : right;
40561
40561
  }
40562
40562
  }
40563
- if (path5.isBinaryExpression()) {
40564
- const left = evaluateCached(path5.get("left"), state);
40563
+ if (path6.isBinaryExpression()) {
40564
+ const left = evaluateCached(path6.get("left"), state);
40565
40565
  if (!state.confident) return;
40566
- const right = evaluateCached(path5.get("right"), state);
40566
+ const right = evaluateCached(path6.get("right"), state);
40567
40567
  if (!state.confident) return;
40568
- switch (path5.node.operator) {
40568
+ switch (path6.node.operator) {
40569
40569
  case "-":
40570
40570
  return left - right;
40571
40571
  case "+":
@@ -40608,11 +40608,11 @@ var require_evaluation = __commonJS({
40608
40608
  return left >>> right;
40609
40609
  }
40610
40610
  }
40611
- if (path5.isCallExpression()) {
40612
- const callee = path5.get("callee");
40611
+ if (path6.isCallExpression()) {
40612
+ const callee = path6.get("callee");
40613
40613
  let context;
40614
40614
  let func;
40615
- if (callee.isIdentifier() && !path5.scope.getBinding(callee.node.name) && (isValidObjectCallee(callee.node.name) || isValidIdentifierCallee(callee.node.name))) {
40615
+ if (callee.isIdentifier() && !path6.scope.getBinding(callee.node.name) && (isValidObjectCallee(callee.node.name) || isValidIdentifierCallee(callee.node.name))) {
40616
40616
  func = global[callee.node.name];
40617
40617
  }
40618
40618
  if (callee.isMemberExpression()) {
@@ -40634,17 +40634,17 @@ var require_evaluation = __commonJS({
40634
40634
  }
40635
40635
  }
40636
40636
  if (func) {
40637
- const args = path5.get("arguments").map((arg) => evaluateCached(arg, state));
40637
+ const args = path6.get("arguments").map((arg) => evaluateCached(arg, state));
40638
40638
  if (!state.confident) return;
40639
40639
  return func.apply(context, args);
40640
40640
  }
40641
40641
  }
40642
- deopt(path5, state);
40642
+ deopt(path6, state);
40643
40643
  }
40644
- function evaluateQuasis(path5, quasis, state, raw = false) {
40644
+ function evaluateQuasis(path6, quasis, state, raw = false) {
40645
40645
  let str = "";
40646
40646
  let i = 0;
40647
- const exprs = path5.isTemplateLiteral() ? path5.get("expressions") : path5.get("quasi.expressions");
40647
+ const exprs = path6.isTemplateLiteral() ? path6.get("expressions") : path6.get("quasi.expressions");
40648
40648
  for (const elem of quasis) {
40649
40649
  if (!state.confident) break;
40650
40650
  str += raw ? elem.value.raw : elem.value.cooked;
@@ -41440,8 +41440,8 @@ var require_conversion = __commonJS({
41440
41440
  }
41441
41441
  hoistFunctionEnvironment(this);
41442
41442
  }
41443
- function setType(path5, type) {
41444
- path5.node.type = type;
41443
+ function setType(path6, type) {
41444
+ path6.node.type = type;
41445
41445
  }
41446
41446
  function arrowFunctionToExpression({
41447
41447
  allowInsertArrow = true,
@@ -41856,14 +41856,14 @@ var require_conversion = __commonJS({
41856
41856
  return this;
41857
41857
  }
41858
41858
  var refersOuterBindingVisitor = {
41859
- "ReferencedIdentifier|BindingIdentifier"(path5, state) {
41860
- if (path5.node.name !== state.name) return;
41859
+ "ReferencedIdentifier|BindingIdentifier"(path6, state) {
41860
+ if (path6.node.name !== state.name) return;
41861
41861
  state.needsRename = true;
41862
- path5.stop();
41862
+ path6.stop();
41863
41863
  },
41864
- Scope(path5, state) {
41865
- if (path5.scope.hasOwnBinding(state.name)) {
41866
- path5.skip();
41864
+ Scope(path6, state) {
41865
+ if (path6.scope.hasOwnBinding(state.name)) {
41866
+ path6.skip();
41867
41867
  }
41868
41868
  }
41869
41869
  };
@@ -42020,21 +42020,21 @@ var require_introspection = __commonJS({
42020
42020
  return false;
42021
42021
  }
42022
42022
  function isCompletionRecord(allowInsideFunction) {
42023
- let path5 = this;
42023
+ let path6 = this;
42024
42024
  let first = true;
42025
42025
  do {
42026
42026
  const {
42027
42027
  type,
42028
42028
  container
42029
- } = path5;
42030
- if (!first && (path5.isFunction() || type === "StaticBlock")) {
42029
+ } = path6;
42030
+ if (!first && (path6.isFunction() || type === "StaticBlock")) {
42031
42031
  return !!allowInsideFunction;
42032
42032
  }
42033
42033
  first = false;
42034
- if (Array.isArray(container) && path5.key !== container.length - 1) {
42034
+ if (Array.isArray(container) && path6.key !== container.length - 1) {
42035
42035
  return false;
42036
42036
  }
42037
- } while ((path5 = path5.parentPath) && !path5.isProgram() && !path5.isDoExpression());
42037
+ } while ((path6 = path6.parentPath) && !path6.isProgram() && !path6.isDoExpression());
42038
42038
  return true;
42039
42039
  }
42040
42040
  function isStatementOrBlock() {
@@ -42056,21 +42056,21 @@ var require_introspection = __commonJS({
42056
42056
  }
42057
42057
  const binding = this.scope.getBinding(this.node.name);
42058
42058
  if (!binding || binding.kind !== "module") return false;
42059
- const path5 = binding.path;
42060
- const parent = path5.parentPath;
42059
+ const path6 = binding.path;
42060
+ const parent = path6.parentPath;
42061
42061
  if (!parent.isImportDeclaration()) return false;
42062
42062
  if (parent.node.source.value === moduleSource) {
42063
42063
  if (!importName) return true;
42064
42064
  } else {
42065
42065
  return false;
42066
42066
  }
42067
- if (path5.isImportDefaultSpecifier() && importName === "default") {
42067
+ if (path6.isImportDefaultSpecifier() && importName === "default") {
42068
42068
  return true;
42069
42069
  }
42070
- if (path5.isImportNamespaceSpecifier() && importName === "*") {
42070
+ if (path6.isImportNamespaceSpecifier() && importName === "*") {
42071
42071
  return true;
42072
42072
  }
42073
- if (path5.isImportSpecifier() && isIdentifier2(path5.node.imported, {
42073
+ if (path6.isImportSpecifier() && isIdentifier2(path6.node.imported, {
42074
42074
  name: importName
42075
42075
  })) {
42076
42076
  return true;
@@ -42088,8 +42088,8 @@ var require_introspection = __commonJS({
42088
42088
  function willIMaybeExecuteBefore(target) {
42089
42089
  return this._guessExecutionStatusRelativeTo(target) !== "after";
42090
42090
  }
42091
- function getOuterFunction(path5) {
42092
- return path5.isProgram() ? path5 : (path5.parentPath.scope.getFunctionParent() || path5.parentPath.scope.getProgramParent()).path;
42091
+ function getOuterFunction(path6) {
42092
+ return path6.isProgram() ? path6 : (path6.parentPath.scope.getFunctionParent() || path6.parentPath.scope.getProgramParent()).path;
42093
42093
  }
42094
42094
  function isExecutionUncertain(type, key) {
42095
42095
  switch (type) {
@@ -42121,8 +42121,8 @@ var require_introspection = __commonJS({
42121
42121
  }
42122
42122
  function isExecutionUncertainInList(paths, maxIndex) {
42123
42123
  for (let i = 0; i < maxIndex; i++) {
42124
- const path5 = paths[i];
42125
- if (isExecutionUncertain(path5.parent.type, path5.parentKey)) {
42124
+ const path6 = paths[i];
42125
+ if (isExecutionUncertain(path6.parent.type, path6.parentKey)) {
42126
42126
  return true;
42127
42127
  }
42128
42128
  }
@@ -42152,10 +42152,10 @@ var require_introspection = __commonJS({
42152
42152
  this: 0
42153
42153
  };
42154
42154
  while (!commonPath && commonIndex.this < paths.this.length) {
42155
- const path5 = paths.this[commonIndex.this];
42156
- commonIndex.target = paths.target.indexOf(path5);
42155
+ const path6 = paths.this[commonIndex.this];
42156
+ commonIndex.target = paths.target.indexOf(path6);
42157
42157
  if (commonIndex.target >= 0) {
42158
- commonPath = path5;
42158
+ commonPath = path6;
42159
42159
  } else {
42160
42160
  commonIndex.this++;
42161
42161
  }
@@ -42193,13 +42193,13 @@ var require_introspection = __commonJS({
42193
42193
  if (!binding.references) return "before";
42194
42194
  const referencePaths = binding.referencePaths;
42195
42195
  let allStatus;
42196
- for (const path5 of referencePaths) {
42197
- const childOfFunction = !!path5.find((path6) => path6.node === target.node);
42196
+ for (const path6 of referencePaths) {
42197
+ const childOfFunction = !!path6.find((path7) => path7.node === target.node);
42198
42198
  if (childOfFunction) continue;
42199
- if (path5.key !== "callee" || !path5.parentPath.isCallExpression()) {
42199
+ if (path6.key !== "callee" || !path6.parentPath.isCallExpression()) {
42200
42200
  return "unknown";
42201
42201
  }
42202
- const status = _guessExecutionStatusRelativeToCached(base, path5, cache);
42202
+ const status = _guessExecutionStatusRelativeToCached(base, path6, cache);
42203
42203
  if (allStatus && allStatus !== status) {
42204
42204
  return "unknown";
42205
42205
  } else {
@@ -42317,19 +42317,19 @@ var require_introspection = __commonJS({
42317
42317
  }
42318
42318
  function isInStrictMode() {
42319
42319
  const start = this.isProgram() ? this : this.parentPath;
42320
- const strictParent = start.find((path5) => {
42321
- if (path5.isProgram({
42320
+ const strictParent = start.find((path6) => {
42321
+ if (path6.isProgram({
42322
42322
  sourceType: "module"
42323
42323
  })) return true;
42324
- if (path5.isClass()) return true;
42325
- if (path5.isArrowFunctionExpression() && !path5.get("body").isBlockStatement()) {
42324
+ if (path6.isClass()) return true;
42325
+ if (path6.isArrowFunctionExpression() && !path6.get("body").isBlockStatement()) {
42326
42326
  return false;
42327
42327
  }
42328
42328
  let body;
42329
- if (path5.isFunction()) {
42330
- body = path5.node.body;
42331
- } else if (path5.isProgram()) {
42332
- body = path5.node;
42329
+ if (path6.isFunction()) {
42330
+ body = path6.node.body;
42331
+ } else if (path6.isProgram()) {
42332
+ body = path6.node;
42333
42333
  } else {
42334
42334
  return false;
42335
42335
  }
@@ -42378,16 +42378,16 @@ var require_family = __commonJS({
42378
42378
  } = _t;
42379
42379
  var NORMAL_COMPLETION = 0;
42380
42380
  var BREAK_COMPLETION = 1;
42381
- function NormalCompletion(path5) {
42381
+ function NormalCompletion(path6) {
42382
42382
  return {
42383
42383
  type: NORMAL_COMPLETION,
42384
- path: path5
42384
+ path: path6
42385
42385
  };
42386
42386
  }
42387
- function BreakCompletion(path5) {
42387
+ function BreakCompletion(path6) {
42388
42388
  return {
42389
42389
  type: BREAK_COMPLETION,
42390
- path: path5
42390
+ path: path6
42391
42391
  };
42392
42392
  }
42393
42393
  function getOpposite() {
@@ -42398,9 +42398,9 @@ var require_family = __commonJS({
42398
42398
  }
42399
42399
  return null;
42400
42400
  }
42401
- function addCompletionRecords(path5, records, context) {
42402
- if (path5) {
42403
- records.push(..._getCompletionRecords(path5, context));
42401
+ function addCompletionRecords(path6, records, context) {
42402
+ if (path6) {
42403
+ records.push(..._getCompletionRecords(path6, context));
42404
42404
  }
42405
42405
  return records;
42406
42406
  }
@@ -42450,16 +42450,16 @@ var require_family = __commonJS({
42450
42450
  if (context.canHaveBreak) {
42451
42451
  let lastNormalCompletions = [];
42452
42452
  for (let i = 0; i < paths.length; i++) {
42453
- const path5 = paths[i];
42453
+ const path6 = paths[i];
42454
42454
  const newContext = Object.assign({}, context, {
42455
42455
  inCaseClause: false
42456
42456
  });
42457
- if (path5.isBlockStatement() && (context.inCaseClause || context.shouldPopulateBreak)) {
42457
+ if (path6.isBlockStatement() && (context.inCaseClause || context.shouldPopulateBreak)) {
42458
42458
  newContext.shouldPopulateBreak = true;
42459
42459
  } else {
42460
42460
  newContext.shouldPopulateBreak = false;
42461
42461
  }
42462
- const statementCompletions = _getCompletionRecords(path5, newContext);
42462
+ const statementCompletions = _getCompletionRecords(path6, newContext);
42463
42463
  if (statementCompletions.length > 0 && statementCompletions.every((c) => c.type === BREAK_COMPLETION)) {
42464
42464
  if (lastNormalCompletions.length > 0 && statementCompletions.every((c) => c.path.isBreakStatement({
42465
42465
  label: null
@@ -42509,35 +42509,35 @@ var require_family = __commonJS({
42509
42509
  }
42510
42510
  return completions;
42511
42511
  }
42512
- function _getCompletionRecords(path5, context) {
42512
+ function _getCompletionRecords(path6, context) {
42513
42513
  let records = [];
42514
- if (path5.isIfStatement()) {
42515
- records = addCompletionRecords(path5.get("consequent"), records, context);
42516
- records = addCompletionRecords(path5.get("alternate"), records, context);
42517
- } else if (path5.isDoExpression() || path5.isFor() || path5.isWhile() || path5.isLabeledStatement()) {
42518
- return addCompletionRecords(path5.get("body"), records, context);
42519
- } else if (path5.isProgram() || path5.isBlockStatement()) {
42520
- return getStatementListCompletion(path5.get("body"), context);
42521
- } else if (path5.isFunction()) {
42522
- return _getCompletionRecords(path5.get("body"), context);
42523
- } else if (path5.isTryStatement()) {
42524
- records = addCompletionRecords(path5.get("block"), records, context);
42525
- records = addCompletionRecords(path5.get("handler"), records, context);
42526
- } else if (path5.isCatchClause()) {
42527
- return addCompletionRecords(path5.get("body"), records, context);
42528
- } else if (path5.isSwitchStatement()) {
42529
- return completionRecordForSwitch(path5.get("cases"), records, context);
42530
- } else if (path5.isSwitchCase()) {
42531
- return getStatementListCompletion(path5.get("consequent"), {
42514
+ if (path6.isIfStatement()) {
42515
+ records = addCompletionRecords(path6.get("consequent"), records, context);
42516
+ records = addCompletionRecords(path6.get("alternate"), records, context);
42517
+ } else if (path6.isDoExpression() || path6.isFor() || path6.isWhile() || path6.isLabeledStatement()) {
42518
+ return addCompletionRecords(path6.get("body"), records, context);
42519
+ } else if (path6.isProgram() || path6.isBlockStatement()) {
42520
+ return getStatementListCompletion(path6.get("body"), context);
42521
+ } else if (path6.isFunction()) {
42522
+ return _getCompletionRecords(path6.get("body"), context);
42523
+ } else if (path6.isTryStatement()) {
42524
+ records = addCompletionRecords(path6.get("block"), records, context);
42525
+ records = addCompletionRecords(path6.get("handler"), records, context);
42526
+ } else if (path6.isCatchClause()) {
42527
+ return addCompletionRecords(path6.get("body"), records, context);
42528
+ } else if (path6.isSwitchStatement()) {
42529
+ return completionRecordForSwitch(path6.get("cases"), records, context);
42530
+ } else if (path6.isSwitchCase()) {
42531
+ return getStatementListCompletion(path6.get("consequent"), {
42532
42532
  canHaveBreak: true,
42533
42533
  shouldPopulateBreak: false,
42534
42534
  inCaseClause: true,
42535
42535
  shouldPreserveBreak: context.shouldPreserveBreak
42536
42536
  });
42537
- } else if (path5.isBreakStatement()) {
42538
- records.push(BreakCompletion(path5));
42537
+ } else if (path6.isBreakStatement()) {
42538
+ records.push(BreakCompletion(path6));
42539
42539
  } else {
42540
- records.push(NormalCompletion(path5));
42540
+ records.push(NormalCompletion(path6));
42541
42541
  }
42542
42542
  return records;
42543
42543
  }
@@ -42617,19 +42617,19 @@ var require_family = __commonJS({
42617
42617
  }
42618
42618
  }
42619
42619
  function _getPattern(parts, context) {
42620
- let path5 = this;
42620
+ let path6 = this;
42621
42621
  for (const part of parts) {
42622
42622
  if (part === ".") {
42623
- path5 = path5.parentPath;
42623
+ path6 = path6.parentPath;
42624
42624
  } else {
42625
- if (Array.isArray(path5)) {
42626
- path5 = path5[part];
42625
+ if (Array.isArray(path6)) {
42626
+ path6 = path6[part];
42627
42627
  } else {
42628
- path5 = path5.get(part, context);
42628
+ path6 = path6.get(part, context);
42629
42629
  }
42630
42630
  }
42631
42631
  }
42632
- return path5;
42632
+ return path6;
42633
42633
  }
42634
42634
  function getAssignmentIdentifiers() {
42635
42635
  return _getAssignmentIdentifiers(this.node);
@@ -42641,8 +42641,8 @@ var require_family = __commonJS({
42641
42641
  return _getOuterBindingIdentifiers(this.node, duplicates);
42642
42642
  }
42643
42643
  function getBindingIdentifierPaths(duplicates = false, outerOnly = false) {
42644
- const path5 = this;
42645
- const search = [path5];
42644
+ const path6 = this;
42645
+ const search = [path6];
42646
42646
  const ids = /* @__PURE__ */ Object.create(null);
42647
42647
  while (search.length) {
42648
42648
  const id = search.shift();
@@ -42841,13 +42841,13 @@ var require_path = __commonJS({
42841
42841
  }
42842
42842
  const targetNode = container[key];
42843
42843
  const paths = cache.getOrCreateCachedPaths(parent, parentPath);
42844
- let path5 = paths.get(targetNode);
42845
- if (!path5) {
42846
- path5 = new NodePath(hub, parent);
42847
- if (targetNode) paths.set(targetNode, path5);
42844
+ let path6 = paths.get(targetNode);
42845
+ if (!path6) {
42846
+ path6 = new NodePath(hub, parent);
42847
+ if (targetNode) paths.set(targetNode, path6);
42848
42848
  }
42849
- _context.setup.call(path5, parentPath, container, listKey, key);
42850
- return path5;
42849
+ _context.setup.call(path6, parentPath, container, listKey, key);
42850
+ return path6;
42851
42851
  }
42852
42852
  getScope(scope) {
42853
42853
  return this.isScope() ? new _index2.default(this) : scope;
@@ -42881,12 +42881,12 @@ var require_path = __commonJS({
42881
42881
  }
42882
42882
  getPathLocation() {
42883
42883
  const parts = [];
42884
- let path5 = this;
42884
+ let path6 = this;
42885
42885
  do {
42886
- let key = path5.key;
42887
- if (path5.inList) key = `${path5.listKey}[${key}]`;
42886
+ let key = path6.key;
42887
+ if (path6.inList) key = `${path6.listKey}[${key}]`;
42888
42888
  parts.unshift(key);
42889
- } while (path5 = path5.parentPath);
42889
+ } while (path6 = path6.parentPath);
42890
42890
  return parts.join(".");
42891
42891
  }
42892
42892
  debug(message) {
@@ -43092,12 +43092,12 @@ var require_context = __commonJS({
43092
43092
  listKey
43093
43093
  });
43094
43094
  }
43095
- maybeQueue(path5, notPriority) {
43095
+ maybeQueue(path6, notPriority) {
43096
43096
  if (this.queue) {
43097
43097
  if (notPriority) {
43098
- this.queue.push(path5);
43098
+ this.queue.push(path6);
43099
43099
  } else {
43100
- this.priorityQueue.push(path5);
43100
+ this.priorityQueue.push(path6);
43101
43101
  }
43102
43102
  }
43103
43103
  }
@@ -43126,20 +43126,20 @@ var require_context = __commonJS({
43126
43126
  let stop = false;
43127
43127
  let visitIndex = 0;
43128
43128
  for (; visitIndex < queue.length; ) {
43129
- const path5 = queue[visitIndex];
43129
+ const path6 = queue[visitIndex];
43130
43130
  visitIndex++;
43131
- _context.resync.call(path5);
43131
+ _context.resync.call(path6);
43132
43132
  ;
43133
- if (path5.contexts.length === 0 || path5.contexts[path5.contexts.length - 1] !== this) {
43134
- _context.pushContext.call(path5, this);
43133
+ if (path6.contexts.length === 0 || path6.contexts[path6.contexts.length - 1] !== this) {
43134
+ _context.pushContext.call(path6, this);
43135
43135
  }
43136
- if (path5.key === null) continue;
43136
+ if (path6.key === null) continue;
43137
43137
  const {
43138
43138
  node
43139
- } = path5;
43139
+ } = path6;
43140
43140
  if (visited.has(node)) continue;
43141
43141
  if (node) visited.add(node);
43142
- if (path5.visit()) {
43142
+ if (path6.visit()) {
43143
43143
  stop = true;
43144
43144
  break;
43145
43145
  }
@@ -43186,14 +43186,14 @@ var require_traverse_node = __commonJS({
43186
43186
  var {
43187
43187
  VISITOR_KEYS
43188
43188
  } = _t;
43189
- function traverseNode(node, opts, scope, state, path5, skipKeys, visitSelf) {
43189
+ function traverseNode(node, opts, scope, state, path6, skipKeys, visitSelf) {
43190
43190
  ;
43191
43191
  const keys = VISITOR_KEYS[node.type];
43192
43192
  if (!keys) return false;
43193
- const context = new _context.default(scope, opts, state, path5);
43193
+ const context = new _context.default(scope, opts, state, path6);
43194
43194
  if (visitSelf) {
43195
- if (skipKeys != null && skipKeys[path5.parentKey]) return false;
43196
- return context.visitQueue([path5]);
43195
+ if (skipKeys != null && skipKeys[path6.parentKey]) return false;
43196
+ return context.visitQueue([path6]);
43197
43197
  }
43198
43198
  for (const key of keys) {
43199
43199
  if (skipKeys != null && skipKeys[key]) continue;
@@ -43276,11 +43276,11 @@ var require_context2 = __commonJS({
43276
43276
  {
43277
43277
  exports2.isBlacklisted = isDenylisted;
43278
43278
  }
43279
- function restoreContext(path5, context) {
43280
- if (path5.context !== context) {
43281
- path5.context = context;
43282
- path5.state = context.state;
43283
- path5.opts = context.opts;
43279
+ function restoreContext(path6, context) {
43280
+ if (path6.context !== context) {
43281
+ path6.context = context;
43282
+ path6.state = context.state;
43283
+ path6.opts = context.opts;
43284
43284
  }
43285
43285
  }
43286
43286
  function visit() {
@@ -43321,16 +43321,16 @@ var require_context2 = __commonJS({
43321
43321
  function setScope() {
43322
43322
  var _this$opts2, _this$scope;
43323
43323
  if ((_this$opts2 = this.opts) != null && _this$opts2.noScope) return;
43324
- let path5 = this.parentPath;
43325
- if ((this.key === "key" || this.listKey === "decorators") && path5.isMethod() || this.key === "discriminant" && path5.isSwitchStatement()) {
43326
- path5 = path5.parentPath;
43324
+ let path6 = this.parentPath;
43325
+ if ((this.key === "key" || this.listKey === "decorators") && path6.isMethod() || this.key === "discriminant" && path6.isSwitchStatement()) {
43326
+ path6 = path6.parentPath;
43327
43327
  }
43328
43328
  let target;
43329
- while (path5 && !target) {
43329
+ while (path6 && !target) {
43330
43330
  var _path$opts;
43331
- if ((_path$opts = path5.opts) != null && _path$opts.noScope) return;
43332
- target = path5.scope;
43333
- path5 = path5.parentPath;
43331
+ if ((_path$opts = path6.opts) != null && _path$opts.noScope) return;
43332
+ target = path6.scope;
43333
+ path6 = path6.parentPath;
43334
43334
  }
43335
43335
  this.scope = this.getScope(target);
43336
43336
  (_this$scope = this.scope) == null || _this$scope.init();
@@ -43439,12 +43439,12 @@ var require_context2 = __commonJS({
43439
43439
  }
43440
43440
  }
43441
43441
  function _getQueueContexts() {
43442
- let path5 = this;
43442
+ let path6 = this;
43443
43443
  let contexts = this.contexts;
43444
43444
  while (!contexts.length) {
43445
- path5 = path5.parentPath;
43446
- if (!path5) break;
43447
- contexts = path5.contexts;
43445
+ path6 = path6.parentPath;
43446
+ if (!path6) break;
43447
+ contexts = path6.contexts;
43448
43448
  }
43449
43449
  return contexts;
43450
43450
  }
@@ -43539,8 +43539,8 @@ var require_lib8 = __commonJS({
43539
43539
  traverseFast(node, enter);
43540
43540
  return;
43541
43541
  };
43542
- traverse2.node = function(node, opts, scope, state, path5, skipKeys) {
43543
- (0, _traverseNode.traverseNode)(node, opts, scope, state, path5, skipKeys);
43542
+ traverse2.node = function(node, opts, scope, state, path6, skipKeys) {
43543
+ (0, _traverseNode.traverseNode)(node, opts, scope, state, path6, skipKeys);
43544
43544
  };
43545
43545
  traverse2.clearNode = function(node, opts) {
43546
43546
  removeProperties(node, opts);
@@ -43567,799 +43567,15 @@ var require_lib8 = __commonJS({
43567
43567
 
43568
43568
  // index.ts
43569
43569
  var import_node_child_process = require("node:child_process");
43570
- var import_node_path4 = __toESM(require("node:path"), 1);
43570
+ var import_node_path5 = __toESM(require("node:path"), 1);
43571
43571
  var import_node_util = require("node:util");
43572
43572
 
43573
- // src/constants.ts
43574
- var DEFAULT_MIN_LINES = 4;
43575
- var DEFAULT_SIMILARITY = 0.7;
43576
- var DEFAULT_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
43577
- var DEFAULT_IGNORE_PATTERNS = [
43578
- "node_modules",
43579
- "dist",
43580
- ".git",
43581
- "build",
43582
- ".next",
43583
- "coverage",
43584
- ".turbo",
43585
- ".cache",
43586
- // Generated/data files that often have intentional repetition
43587
- "drizzle/migrations",
43588
- "migrations",
43589
- "assets/data",
43590
- "__generated__",
43591
- ".generated",
43592
- "generated"
43593
- ];
43594
- var MAX_BLOCK_SIZE = 100;
43595
- var BLOCK_SIZE_MULTIPLIER = 1.5;
43596
- var MIN_MEANINGFUL_LINE_RATIO = 0.6;
43597
- var SLIDING_WINDOW_STEP_DIVISOR = 2;
43598
- var SKIP_LINE_PREFIXES = [
43599
- "//",
43600
- // Single-line comments
43601
- "/*",
43602
- // Multi-line comment start
43603
- "*",
43604
- // Multi-line comment continuation
43605
- "import ",
43606
- // Import statements
43607
- "export {"
43608
- // Re-exports
43609
- ];
43610
- var SIZE_BUCKET_DIVISOR = 5;
43611
- var MAX_SIMILARITY_SAMPLES = 5;
43612
- var MIN_OCCURRENCES = 2;
43613
- var GROUP_OVERLAP_THRESHOLD = 0.5;
43614
- var STRING_PLACEHOLDER = "<STRING>";
43615
- var TEMPLATE_PLACEHOLDER = "<TEMPLATE>";
43616
- var NUMBER_PLACEHOLDER = "<NUMBER>";
43617
- var COLOR_PLACEHOLDER = "<COLOR>";
43618
- var MAX_PATH_DISPLAY_LENGTH = 60;
43619
- var CODE_PREVIEW_CONTEXT_LINES = 3;
43620
- var MAX_MATCHES_IN_SUMMARY = 5;
43621
- var MAX_GROUPS_DETAILED = 20;
43622
- var SECTION_SEPARATOR = "\u2500".repeat(80);
43623
- var COLORS = {
43624
- reset: "\x1B[0m",
43625
- bold: "\x1B[1m",
43626
- dim: "\x1B[2m",
43627
- red: "\x1B[31m",
43628
- green: "\x1B[32m",
43629
- yellow: "\x1B[33m",
43630
- blue: "\x1B[34m",
43631
- magenta: "\x1B[35m",
43632
- cyan: "\x1B[36m",
43633
- white: "\x1B[37m",
43634
- gray: "\x1B[90m"
43635
- };
43636
- var MAX_FILE_SIZE = 1024 * 1024;
43637
- var MAX_BLOCKS_FOR_SIMILARITY = 1e4;
43638
-
43639
- // src/normalizer.ts
43640
- function normalizeCode(code) {
43641
- let normalized = code;
43642
- normalized = normalized.replace(/"(?:[^"\\]|\\.)*"/g, `"${STRING_PLACEHOLDER}"`);
43643
- normalized = normalized.replace(/'(?:[^'\\]|\\.)*'/g, `'${STRING_PLACEHOLDER}'`);
43644
- normalized = normalized.replace(/`(?:[^`\\]|\\.)*`/g, `\`${TEMPLATE_PLACEHOLDER}\``);
43645
- normalized = normalized.replace(/\b\d+\.?\d*\b/g, NUMBER_PLACEHOLDER);
43646
- normalized = normalized.replace(/#[0-9a-fA-F]{3,8}\b/g, COLOR_PLACEHOLDER);
43647
- normalized = normalized.replace(/[ \t]+/g, " ");
43648
- normalized = normalized.split("\n").map((line) => line.trimEnd()).join("\n");
43649
- normalized = normalized.replace(/\n\s*\n/g, "\n");
43650
- return normalized;
43651
- }
43652
-
43653
- // src/declarations.ts
43654
- function simpleHash(str) {
43655
- let hash = 0;
43656
- for (let i = 0; i < str.length; i++) {
43657
- const char = str.charCodeAt(i);
43658
- hash = (hash << 5) - hash + char;
43659
- hash = hash & hash;
43660
- }
43661
- return hash.toString(36);
43662
- }
43663
- var DECLARATION_PATTERNS = [
43664
- // Type aliases: type X = ... or export type X = ...
43665
- { type: "type", regex: /^(export\s+)?type\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*=/m, nameGroup: 2 },
43666
- // Interfaces: interface X { or export interface X {
43667
- { type: "interface", regex: /^(export\s+)?interface\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*(?:extends\s+[^{]+)?\{/m, nameGroup: 2 },
43668
- // Classes: class X { or export class X {
43669
- { type: "class", regex: /^(export\s+)?(?:abstract\s+)?class\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*(?:extends\s+\w+)?\s*(?:implements\s+[^{]+)?\{/m, nameGroup: 2 },
43670
- // Enums: enum X { or export enum X {
43671
- { type: "enum", regex: /^(export\s+)?(?:const\s+)?enum\s+([A-Z]\w*)\s*\{/m, nameGroup: 2 },
43672
- // Named functions: function x( or export function x( or export async function x(
43673
- { type: "function", regex: /^(export\s+)?(?:async\s+)?function\s+([a-zA-Z]\w*)\s*(?:<[^>]*>)?\s*\(/m, nameGroup: 2 },
43674
- // Arrow functions: const x = ( or export const x = async (
43675
- { type: "function", regex: /^(export\s+)?const\s+([a-zA-Z]\w*)\s*(?::\s*[^=]+)?\s*=\s*(?:async\s*)?\(/m, nameGroup: 2 },
43676
- // Arrow functions with generics: const x = <T>(
43677
- { type: "function", regex: /^(export\s+)?const\s+([a-zA-Z]\w*)\s*=\s*<[^>]+>\s*\(/m, nameGroup: 2 },
43678
- // Constants (non-function): export const X = "..." or const X = {...}
43679
- { type: "const", regex: /^(export\s+)?const\s+([A-Z][A-Z_0-9]*)\s*(?::\s*[^=]+)?\s*=/m, nameGroup: 2 }
43680
- ];
43681
- function findMatchingBrace(content, startIndex) {
43682
- let depth = 0;
43683
- let inString = false;
43684
- let stringChar = "";
43685
- let inTemplate = false;
43686
- for (let i = startIndex; i < content.length; i++) {
43687
- const char = content[i];
43688
- const prevChar = content[i - 1];
43689
- if (inString) {
43690
- if (char === stringChar && prevChar !== "\\") {
43691
- inString = false;
43692
- }
43693
- continue;
43694
- }
43695
- if (inTemplate) {
43696
- if (char === "`" && prevChar !== "\\") {
43697
- inTemplate = false;
43698
- }
43699
- continue;
43700
- }
43701
- if (char === '"' || char === "'") {
43702
- inString = true;
43703
- stringChar = char;
43704
- continue;
43705
- }
43706
- if (char === "`") {
43707
- inTemplate = true;
43708
- continue;
43709
- }
43710
- if (char === "{") depth++;
43711
- if (char === "}") {
43712
- depth--;
43713
- if (depth === 0) return i;
43714
- }
43715
- }
43716
- return -1;
43717
- }
43718
- function findStatementEnd(content, startIndex) {
43719
- let depth = 0;
43720
- let inString = false;
43721
- let stringChar = "";
43722
- for (let i = startIndex; i < content.length; i++) {
43723
- const char = content[i];
43724
- const prevChar = content[i - 1];
43725
- if (inString) {
43726
- if (char === stringChar && prevChar !== "\\") {
43727
- inString = false;
43728
- }
43729
- continue;
43730
- }
43731
- if (char === '"' || char === "'") {
43732
- inString = true;
43733
- stringChar = char;
43734
- continue;
43735
- }
43736
- if (char === "(" || char === "{" || char === "[") depth++;
43737
- if (char === ")" || char === "}" || char === "]") depth--;
43738
- if (depth === 0 && (char === ";" || char === "\n")) {
43739
- const remaining = content.slice(i + 1).trimStart();
43740
- if (!remaining.startsWith("|") && !remaining.startsWith("&")) {
43741
- return i;
43742
- }
43743
- }
43744
- }
43745
- return content.length - 1;
43746
- }
43747
- var QUICK_CHECK = /^(export\s+)?(type|interface|class|enum|const|function|async\s+function)\s+/;
43748
- function extractDeclarations(content, filePath) {
43749
- const declarations = [];
43750
- const lines = content.split("\n");
43751
- let lineStart = 0;
43752
- for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
43753
- const line = lines[lineIndex];
43754
- if (!line) continue;
43755
- const trimmed = line.trimStart();
43756
- if (!QUICK_CHECK.test(trimmed)) {
43757
- lineStart += line.length + 1;
43758
- continue;
43759
- }
43760
- const remainingContent = content.slice(lineStart);
43761
- for (const pattern of DECLARATION_PATTERNS) {
43762
- const match2 = remainingContent.match(pattern.regex);
43763
- if (match2 && match2.index === 0) {
43764
- const name = match2[pattern.nameGroup];
43765
- if (!name) continue;
43766
- const exported = !!match2[1];
43767
- let endIndex;
43768
- if (pattern.type === "interface" || pattern.type === "class" || pattern.type === "enum") {
43769
- const braceStart = remainingContent.indexOf("{");
43770
- if (braceStart === -1) continue;
43771
- endIndex = findMatchingBrace(remainingContent, braceStart);
43772
- if (endIndex === -1) endIndex = remainingContent.indexOf("\n", braceStart + 1);
43773
- } else if (pattern.type === "type") {
43774
- endIndex = findStatementEnd(remainingContent, match2[0].length);
43775
- } else {
43776
- const hasArrow = remainingContent.slice(match2[0].length, match2[0].length + 100).includes("=>");
43777
- if (hasArrow) {
43778
- const arrowIndex = remainingContent.indexOf("=>", match2[0].length);
43779
- const afterArrow = remainingContent.slice(arrowIndex + 2).trimStart();
43780
- if (afterArrow.startsWith("{")) {
43781
- const braceStart = arrowIndex + 2 + (remainingContent.slice(arrowIndex + 2).length - afterArrow.length);
43782
- endIndex = findMatchingBrace(remainingContent, braceStart);
43783
- } else {
43784
- endIndex = findStatementEnd(remainingContent, arrowIndex + 2);
43785
- }
43786
- } else {
43787
- const braceIndex = remainingContent.indexOf("{", match2[0].length);
43788
- const newlineIndex = remainingContent.indexOf("\n", match2[0].length);
43789
- if (braceIndex !== -1 && (newlineIndex === -1 || braceIndex < newlineIndex)) {
43790
- endIndex = findMatchingBrace(remainingContent, braceIndex);
43791
- } else {
43792
- endIndex = findStatementEnd(remainingContent, match2[0].length);
43793
- }
43794
- }
43795
- }
43796
- if (endIndex === -1) endIndex = remainingContent.indexOf("\n\n");
43797
- if (endIndex === -1) endIndex = Math.min(remainingContent.length - 1, 500);
43798
- const declarationContent = remainingContent.slice(0, endIndex + 1).trim();
43799
- const endLineIndex = lineIndex + declarationContent.split("\n").length - 1;
43800
- const normalized = normalizeCode(declarationContent);
43801
- declarations.push({
43802
- type: pattern.type,
43803
- name,
43804
- content: declarationContent,
43805
- normalized,
43806
- hash: simpleHash(normalized),
43807
- filePath,
43808
- startLine: lineIndex + 1,
43809
- endLine: endLineIndex + 1,
43810
- exported
43811
- });
43812
- break;
43813
- }
43814
- }
43815
- lineStart += line.length + 1;
43816
- }
43817
- return declarations;
43818
- }
43819
- function calculateNameSimilarity(a, b) {
43820
- if (a === b) return 1;
43821
- const aLower = a.toLowerCase();
43822
- const bLower = b.toLowerCase();
43823
- if (aLower === bLower) return 0.95;
43824
- if (aLower.includes(bLower) || bLower.includes(aLower)) return 0.8;
43825
- const aWords = splitCamelCase(a);
43826
- const bWords = splitCamelCase(b);
43827
- const aSet = new Set(aWords.map((w) => w.toLowerCase()));
43828
- const bSet = new Set(bWords.map((w) => w.toLowerCase()));
43829
- let intersection = 0;
43830
- for (const word of aSet) {
43831
- if (bSet.has(word)) intersection++;
43832
- }
43833
- const union = aSet.size + bSet.size - intersection;
43834
- const wordSimilarity = union > 0 ? intersection / union : 0;
43835
- if (wordSimilarity > 0.5) return wordSimilarity * 0.9;
43836
- const distance = levenshteinDistance(aLower, bLower);
43837
- const maxLen = Math.max(aLower.length, bLower.length);
43838
- return Math.max(0, 1 - distance / maxLen) * 0.7;
43839
- }
43840
- function splitCamelCase(str) {
43841
- return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[_-]/g, " ").split(/\s+/).filter((w) => w.length > 0);
43842
- }
43843
- function levenshteinDistance(a, b) {
43844
- if (a.length === 0) return b.length;
43845
- if (b.length === 0) return a.length;
43846
- const matrix = Array.from(
43847
- { length: b.length + 1 },
43848
- (_, i) => Array.from({ length: a.length + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
43849
- );
43850
- for (let i = 1; i <= b.length; i++) {
43851
- for (let j = 1; j <= a.length; j++) {
43852
- const prevRow = matrix[i - 1];
43853
- const currRow = matrix[i];
43854
- if (!prevRow || !currRow) continue;
43855
- if (b[i - 1] === a[j - 1]) {
43856
- currRow[j] = prevRow[j - 1] ?? 0;
43857
- } else {
43858
- currRow[j] = Math.min(
43859
- (prevRow[j - 1] ?? 0) + 1,
43860
- (currRow[j - 1] ?? 0) + 1,
43861
- (prevRow[j] ?? 0) + 1
43862
- );
43863
- }
43864
- }
43865
- }
43866
- return matrix[b.length]?.[a.length] ?? Math.max(a.length, b.length);
43867
- }
43868
-
43869
- // src/detector.ts
43870
- function calculateSimilarityFast(a, b) {
43871
- if (a === b) return 1;
43872
- if (a.length === 0 || b.length === 0) return 0;
43873
- const linesA = a.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
43874
- const linesB = b.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
43875
- if (linesA.length === 0 || linesB.length === 0) return 0;
43876
- const lenRatio = Math.min(linesA.length, linesB.length) / Math.max(linesA.length, linesB.length);
43877
- if (lenRatio < 0.5) return lenRatio * 0.5;
43878
- const setA = new Set(linesA);
43879
- const setB = new Set(linesB);
43880
- let intersection = 0;
43881
- for (const line of setA) {
43882
- if (setB.has(line)) {
43883
- intersection++;
43884
- }
43885
- }
43886
- const union = setA.size + setB.size - intersection;
43887
- return union > 0 ? intersection / union : 0;
43888
- }
43889
- function getFingerprint(normalized) {
43890
- const lines = normalized.split("\n");
43891
- if (lines.length < 3) return normalized.slice(0, 100);
43892
- const first = lines.slice(0, 2).join("");
43893
- const mid = lines[Math.floor(lines.length / 2)] ?? "";
43894
- const last = lines.slice(-2).join("");
43895
- return (first + mid + last).slice(0, 200);
43896
- }
43897
- var UnionFind = class {
43898
- parent = /* @__PURE__ */ new Map();
43899
- rank = /* @__PURE__ */ new Map();
43900
- find(x) {
43901
- if (!this.parent.has(x)) {
43902
- this.parent.set(x, x);
43903
- this.rank.set(x, 0);
43904
- }
43905
- const parentVal = this.parent.get(x);
43906
- if (parentVal !== void 0 && parentVal !== x) {
43907
- const root = this.find(parentVal);
43908
- this.parent.set(x, root);
43909
- return root;
43910
- }
43911
- return this.parent.get(x) ?? x;
43912
- }
43913
- union(x, y) {
43914
- const rootX = this.find(x);
43915
- const rootY = this.find(y);
43916
- if (rootX === rootY) return;
43917
- const rankX = this.rank.get(rootX) ?? 0;
43918
- const rankY = this.rank.get(rootY) ?? 0;
43919
- if (rankX < rankY) {
43920
- this.parent.set(rootX, rootY);
43921
- } else if (rankX > rankY) {
43922
- this.parent.set(rootY, rootX);
43923
- } else {
43924
- this.parent.set(rootY, rootX);
43925
- this.rank.set(rootX, rankX + 1);
43926
- }
43927
- }
43928
- };
43929
- function findDuplicates(blocks, minSimilarity, basePath) {
43930
- const hashGroups = /* @__PURE__ */ new Map();
43931
- for (const block of blocks) {
43932
- const existing = hashGroups.get(block.hash) ?? [];
43933
- existing.push(block);
43934
- hashGroups.set(block.hash, existing);
43935
- }
43936
- const exactDuplicates = [];
43937
- let groupId = 0;
43938
- for (const [, groupBlocks] of hashGroups) {
43939
- const uniqueLocations = filterOverlappingBlocks(groupBlocks);
43940
- if (uniqueLocations.length >= MIN_OCCURRENCES) {
43941
- exactDuplicates.push({
43942
- id: groupId++,
43943
- similarity: 1,
43944
- lineCount: uniqueLocations[0]?.lineCount ?? 0,
43945
- occurrences: uniqueLocations.length,
43946
- matches: uniqueLocations.map((b) => ({
43947
- filePath: b.filePath,
43948
- startLine: b.startLine,
43949
- endLine: b.endLine,
43950
- content: b.content
43951
- })),
43952
- pattern: uniqueLocations[0]?.normalized ?? ""
43953
- });
43954
- }
43955
- }
43956
- const similarDuplicates = [];
43957
- const uniqueHashCount = hashGroups.size;
43958
- if (minSimilarity < 1 && uniqueHashCount <= MAX_BLOCKS_FOR_SIMILARITY) {
43959
- const uniqueBlocks = [];
43960
- const seenHashes = /* @__PURE__ */ new Set();
43961
- for (const block of blocks) {
43962
- if (!seenHashes.has(block.hash)) {
43963
- seenHashes.add(block.hash);
43964
- uniqueBlocks.push(block);
43965
- }
43966
- }
43967
- const sizeGroups = /* @__PURE__ */ new Map();
43968
- for (const block of uniqueBlocks) {
43969
- const sizeKey = Math.floor(block.lineCount / SIZE_BUCKET_DIVISOR);
43970
- const existing = sizeGroups.get(sizeKey) ?? [];
43971
- existing.push(block);
43972
- sizeGroups.set(sizeKey, existing);
43973
- }
43974
- const fingerprints = /* @__PURE__ */ new Map();
43975
- for (const block of uniqueBlocks) {
43976
- fingerprints.set(block, getFingerprint(block.normalized));
43977
- }
43978
- const uf = new UnionFind();
43979
- const blockIndexMap = /* @__PURE__ */ new Map();
43980
- for (let i = 0; i < uniqueBlocks.length; i++) {
43981
- const block = uniqueBlocks[i];
43982
- if (block) blockIndexMap.set(block, i);
43983
- }
43984
- for (const [sizeKey, sizeGroup] of sizeGroups) {
43985
- const adjacentGroups = [
43986
- sizeGroups.get(sizeKey - 1) ?? [],
43987
- sizeGroup,
43988
- sizeGroups.get(sizeKey + 1) ?? []
43989
- ].flat();
43990
- const maxComparisons = 1e3;
43991
- let comparisons = 0;
43992
- for (let i = 0; i < sizeGroup.length && comparisons < maxComparisons; i++) {
43993
- const blockA = sizeGroup[i];
43994
- if (!blockA) continue;
43995
- const fpA = fingerprints.get(blockA) ?? "";
43996
- for (let j = 0; j < adjacentGroups.length && comparisons < maxComparisons; j++) {
43997
- const blockB = adjacentGroups[j];
43998
- if (!blockB) continue;
43999
- if (blockA === blockB) continue;
44000
- if (blockA.hash === blockB.hash) continue;
44001
- const fpB = fingerprints.get(blockB) ?? "";
44002
- const fpSimilarity = calculateSimilarityFast(fpA, fpB);
44003
- if (fpSimilarity < minSimilarity * 0.5) continue;
44004
- comparisons++;
44005
- const similarity = calculateSimilarityFast(blockA.normalized, blockB.normalized);
44006
- if (similarity >= minSimilarity) {
44007
- const idxA = blockIndexMap.get(blockA);
44008
- const idxB = blockIndexMap.get(blockB);
44009
- if (idxA !== void 0 && idxB !== void 0) {
44010
- uf.union(idxA, idxB);
44011
- }
44012
- }
44013
- }
44014
- }
44015
- }
44016
- const groupMap = /* @__PURE__ */ new Map();
44017
- for (const block of uniqueBlocks) {
44018
- const idx = blockIndexMap.get(block);
44019
- if (idx === void 0) continue;
44020
- const root = uf.find(idx);
44021
- const existing = groupMap.get(root) ?? [];
44022
- existing.push(block);
44023
- groupMap.set(root, existing);
44024
- }
44025
- for (const [, groupBlocks] of groupMap) {
44026
- if (groupBlocks.length < MIN_OCCURRENCES) continue;
44027
- const expandedBlocks = [];
44028
- for (const block of groupBlocks) {
44029
- const matching = hashGroups.get(block.hash) ?? [];
44030
- expandedBlocks.push(...matching);
44031
- }
44032
- const uniqueLocations = filterOverlappingBlocks(expandedBlocks);
44033
- if (uniqueLocations.length >= MIN_OCCURRENCES) {
44034
- let totalSim = 0;
44035
- let comparisons = 0;
44036
- const sampleSize = Math.min(groupBlocks.length, MAX_SIMILARITY_SAMPLES);
44037
- for (let i = 0; i < sampleSize; i++) {
44038
- for (let j = i + 1; j < sampleSize; j++) {
44039
- const blockI = groupBlocks[i];
44040
- const blockJ = groupBlocks[j];
44041
- if (blockI && blockJ) {
44042
- totalSim += calculateSimilarityFast(blockI.normalized, blockJ.normalized);
44043
- comparisons++;
44044
- }
44045
- }
44046
- }
44047
- const avgSimilarity = comparisons > 0 ? totalSim / comparisons : 1;
44048
- similarDuplicates.push({
44049
- id: groupId++,
44050
- similarity: avgSimilarity,
44051
- lineCount: Math.round(
44052
- uniqueLocations.reduce((sum, b) => sum + b.lineCount, 0) / uniqueLocations.length
44053
- ),
44054
- occurrences: uniqueLocations.length,
44055
- matches: uniqueLocations.map((b) => ({
44056
- filePath: b.filePath,
44057
- startLine: b.startLine,
44058
- endLine: b.endLine,
44059
- content: b.content
44060
- })),
44061
- pattern: groupBlocks[0]?.normalized ?? ""
44062
- });
44063
- }
44064
- }
44065
- }
44066
- const filteredSimilar = similarDuplicates.filter((g) => g.similarity >= minSimilarity);
44067
- const allDuplicates = [...exactDuplicates, ...filteredSimilar];
44068
- allDuplicates.sort((a, b) => {
44069
- const impactA = a.occurrences * a.lineCount;
44070
- const impactB = b.occurrences * b.lineCount;
44071
- return impactB - impactA;
44072
- });
44073
- const dedupedGroups = deduplicateGroups(allDuplicates);
44074
- return dedupedGroups.map((group) => ({
44075
- ...group,
44076
- suggestion: generateRefactoringSuggestion(group, basePath)
44077
- }));
44078
- }
44079
- function filterOverlappingBlocks(blocks) {
44080
- const byFile = /* @__PURE__ */ new Map();
44081
- for (const block of blocks) {
44082
- const existing = byFile.get(block.filePath) ?? [];
44083
- existing.push(block);
44084
- byFile.set(block.filePath, existing);
44085
- }
44086
- const result = [];
44087
- for (const [, fileBlocks] of byFile) {
44088
- fileBlocks.sort((a, b) => a.startLine - b.startLine);
44089
- const kept = [];
44090
- for (const block of fileBlocks) {
44091
- const overlaps = kept.some(
44092
- (k) => block.startLine >= k.startLine && block.startLine <= k.endLine || block.endLine >= k.startLine && block.endLine <= k.endLine || block.startLine <= k.startLine && block.endLine >= k.endLine
44093
- );
44094
- if (!overlaps) {
44095
- kept.push(block);
44096
- }
44097
- }
44098
- result.push(...kept);
44099
- }
44100
- return result;
44101
- }
44102
- function extractPackageInfo(filePath) {
44103
- const match2 = filePath.match(/(apps|packages|libs)\/([^/]+)\/(.+)/);
44104
- if (match2) {
44105
- return {
44106
- type: match2[1],
44107
- name: match2[2] ?? "unknown",
44108
- subPath: match2[3] ?? ""
44109
- };
44110
- }
44111
- const parts = filePath.split("/");
44112
- return {
44113
- type: "unknown",
44114
- name: parts[0] ?? "unknown",
44115
- subPath: parts.slice(1).join("/")
44116
- };
44117
- }
44118
- function inferSuggestedName(_pattern, matches) {
44119
- const firstMatch = matches[0];
44120
- if (!firstMatch) return void 0;
44121
- const content = firstMatch.content;
44122
- const patterns = [
44123
- // Schema definitions (Zod, etc)
44124
- { regex: /(?:const|export const)\s+([A-Z]\w*Schema)\s*=/, minLength: 6 },
44125
- // Type/interface definitions
44126
- { regex: /(?:export\s+)?interface\s+([A-Z]\w+)/, minLength: 3 },
44127
- { regex: /(?:export\s+)?type\s+([A-Z]\w+)\s*=/, minLength: 3 },
44128
- // Class definitions
44129
- { regex: /(?:export\s+)?class\s+([A-Z]\w+)/, minLength: 3 },
44130
- // Function definitions (exported or async)
44131
- { regex: /(?:export\s+)?(?:async\s+)?function\s+(\w{3,})\s*[(<]/, minLength: 3 },
44132
- // React component definitions
44133
- { regex: /(?:export\s+)?(?:const|function)\s+([A-Z]\w+)\s*[=:].*(?:React|FC|Component|=>)/, minLength: 3 },
44134
- // Named exports with PascalCase (likely important)
44135
- { regex: /(?:export\s+)?const\s+([A-Z]\w{2,})\s*=/, minLength: 3 },
44136
- // Arrow function assignments (camelCase, min 4 chars)
44137
- { regex: /(?:export\s+)?const\s+([a-z][a-zA-Z]{3,})\s*=\s*(?:async\s*)?\(/, minLength: 4 }
44138
- ];
44139
- for (const { regex, minLength } of patterns) {
44140
- const match2 = content.match(regex);
44141
- if (match2?.[1] && match2[1].length >= minLength) {
44142
- const skipNames = /* @__PURE__ */ new Set(["result", "data", "error", "response", "value", "item", "index", "key", "match", "pool", "client", "db"]);
44143
- if (!skipNames.has(match2[1].toLowerCase())) {
44144
- return match2[1];
44145
- }
44146
- }
44147
- }
44148
- const fileNames = matches.map((m) => {
44149
- const parts = m.filePath.split("/");
44150
- const fileName = parts[parts.length - 1] ?? "";
44151
- return fileName.replace(/\.(ts|tsx|js|jsx)$/, "");
44152
- });
44153
- const uniqueNames = [...new Set(fileNames)];
44154
- if (uniqueNames.length === 1 && uniqueNames[0] && uniqueNames[0].length >= 3) {
44155
- const name = uniqueNames[0];
44156
- if (name.includes("-") || name.includes("_")) {
44157
- return name.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
44158
- }
44159
- return name;
44160
- }
44161
- return void 0;
44162
- }
44163
- function generateRefactoringSuggestion(group, _basePath) {
44164
- const matches = group.matches;
44165
- const packageInfos = matches.map((m) => extractPackageInfo(m.filePath));
44166
- const uniquePackages = /* @__PURE__ */ new Map();
44167
- for (const info of packageInfos) {
44168
- const key = `${info.type}/${info.name}`;
44169
- if (!uniquePackages.has(key)) {
44170
- uniquePackages.set(key, info);
44171
- }
44172
- }
44173
- const packageList = Array.from(uniquePackages.values());
44174
- const suggestedName = inferSuggestedName(group.pattern, matches);
44175
- if (packageList.length === 1 && packageList[0]) {
44176
- const pkg = packageList[0];
44177
- const subPaths = packageInfos.map((p) => p.subPath);
44178
- const commonPrefix = findCommonPrefix(subPaths);
44179
- if (pkg.type === "app") {
44180
- return {
44181
- targetLocation: `${pkg.type}s/${pkg.name}/lib/shared/${commonPrefix || "utils"}`,
44182
- reason: `All ${matches.length} occurrences are within ${pkg.name}`,
44183
- confidence: "high",
44184
- suggestedName
44185
- };
44186
- } else {
44187
- return {
44188
- targetLocation: `${pkg.type}/${pkg.name}/src/shared`,
44189
- reason: `All ${matches.length} occurrences are within ${pkg.name}`,
44190
- confidence: "high",
44191
- suggestedName
44192
- };
44193
- }
44194
- }
44195
- const hasOnlyApps = packageList.every((p) => p.type === "app");
44196
- if (hasOnlyApps) {
44197
- const appNames = packageList.map((p) => p.name);
44198
- return {
44199
- targetLocation: "packages/shared/src",
44200
- reason: `Duplicated across ${appNames.length} apps: ${appNames.join(", ")}`,
44201
- confidence: "high",
44202
- suggestedName
44203
- };
44204
- }
44205
- const packages = packageList.filter((p) => p.type === "package");
44206
- const apps = packageList.filter((p) => p.type === "app");
44207
- if (packages.length > 0) {
44208
- const sharedPackage = packages.find(
44209
- (p) => p.name === "shared" || p.name === "common" || p.name === "utils"
44210
- ) ?? packages[0];
44211
- if (!sharedPackage) return { targetLocation: "packages/shared/src", reason: "Duplicated across packages", confidence: "low", suggestedName };
44212
- return {
44213
- targetLocation: `packages/${sharedPackage.name}/src`,
44214
- reason: `Already exists in ${sharedPackage.name}, also duplicated in ${apps.map((a) => a.name).join(", ")}`,
44215
- confidence: "medium",
44216
- suggestedName
44217
- };
44218
- }
44219
- const libs = packageList.filter((p) => p.type === "lib");
44220
- if (libs.length > 0) {
44221
- return {
44222
- targetLocation: `libs/shared/src`,
44223
- reason: `Duplicated across ${libs.length} libraries`,
44224
- confidence: "medium",
44225
- suggestedName
44226
- };
44227
- }
44228
- return {
44229
- targetLocation: "packages/shared/src",
44230
- reason: `Duplicated across ${packageList.length} locations`,
44231
- confidence: "low",
44232
- suggestedName
44233
- };
44234
- }
44235
- function findCommonPrefix(paths) {
44236
- if (paths.length === 0) return "";
44237
- if (paths.length === 1) return paths[0]?.split("/")[0] ?? "";
44238
- const splitPaths = paths.map((p) => p.split("/"));
44239
- const minLength = Math.min(...splitPaths.map((p) => p.length));
44240
- const commonParts = [];
44241
- for (let i = 0; i < minLength - 1; i++) {
44242
- const part = splitPaths[0]?.[i];
44243
- if (part && splitPaths.every((p) => p[i] === part)) {
44244
- commonParts.push(part);
44245
- } else {
44246
- break;
44247
- }
44248
- }
44249
- return commonParts.join("/");
44250
- }
44251
- function rangesOverlap(aStart, aEnd, bStart, bEnd) {
44252
- return aStart <= bEnd && bStart <= aEnd;
44253
- }
44254
- function deduplicateGroups(groups) {
44255
- const result = [];
44256
- for (const group of groups) {
44257
- let coveredCount = 0;
44258
- for (const match2 of group.matches) {
44259
- let isCovered = false;
44260
- for (const existing of result) {
44261
- for (const existingMatch of existing.matches) {
44262
- if (match2.filePath === existingMatch.filePath && rangesOverlap(
44263
- match2.startLine,
44264
- match2.endLine,
44265
- existingMatch.startLine,
44266
- existingMatch.endLine
44267
- )) {
44268
- isCovered = true;
44269
- break;
44270
- }
44271
- }
44272
- if (isCovered) break;
44273
- }
44274
- if (isCovered) coveredCount++;
44275
- }
44276
- if (coveredCount < group.matches.length * GROUP_OVERLAP_THRESHOLD) {
44277
- result.push(group);
44278
- }
44279
- }
44280
- return result;
44281
- }
44282
- function findDeclarationDuplicates(declarations, minSimilarity) {
44283
- const duplicates = [];
44284
- let groupId = 0;
44285
- const byType = /* @__PURE__ */ new Map();
44286
- for (const decl of declarations) {
44287
- const existing = byType.get(decl.type) ?? [];
44288
- existing.push(decl);
44289
- byType.set(decl.type, existing);
44290
- }
44291
- for (const [type, typeDecls] of byType) {
44292
- const processed = /* @__PURE__ */ new Set();
44293
- for (let i = 0; i < typeDecls.length; i++) {
44294
- if (processed.has(i)) continue;
44295
- const declA = typeDecls[i];
44296
- if (!declA) continue;
44297
- const matches = [{
44298
- name: declA.name,
44299
- filePath: declA.filePath,
44300
- startLine: declA.startLine,
44301
- endLine: declA.endLine,
44302
- content: declA.content,
44303
- exported: declA.exported
44304
- }];
44305
- let bestNameSim = 0;
44306
- let bestContentSim = 0;
44307
- for (let j = i + 1; j < typeDecls.length; j++) {
44308
- if (processed.has(j)) continue;
44309
- const declB = typeDecls[j];
44310
- if (!declB) continue;
44311
- if (declA.filePath === declB.filePath && Math.abs(declA.startLine - declB.startLine) < 5) continue;
44312
- const nameSim = calculateNameSimilarity(declA.name, declB.name);
44313
- const contentSim = calculateSimilarityFast(declA.normalized, declB.normalized);
44314
- const combined = Math.max(
44315
- nameSim * 0.4 + contentSim * 0.6,
44316
- nameSim >= 0.9 ? nameSim : 0,
44317
- contentSim >= 0.9 ? contentSim : 0
44318
- );
44319
- if (combined >= minSimilarity || nameSim >= 0.8 && contentSim >= 0.5) {
44320
- processed.add(j);
44321
- matches.push({
44322
- name: declB.name,
44323
- filePath: declB.filePath,
44324
- startLine: declB.startLine,
44325
- endLine: declB.endLine,
44326
- content: declB.content,
44327
- exported: declB.exported
44328
- });
44329
- bestNameSim = Math.max(bestNameSim, nameSim);
44330
- bestContentSim = Math.max(bestContentSim, contentSim);
44331
- }
44332
- }
44333
- if (matches.length >= 2) {
44334
- processed.add(i);
44335
- const exported = matches.find((m) => m.exported);
44336
- const suggestion = exported ? `Import \`${exported.name}\` from \`${exported.filePath.replace(/.*\/(src|lib)\//, "")}\`` : `Consider extracting \`${declA.name}\` to a shared location`;
44337
- duplicates.push({
44338
- id: groupId++,
44339
- type,
44340
- similarity: Math.max(bestNameSim, bestContentSim),
44341
- nameSimilarity: bestNameSim,
44342
- contentSimilarity: bestContentSim,
44343
- matches,
44344
- suggestion
44345
- });
44346
- }
44347
- }
44348
- }
44349
- duplicates.sort((a, b) => {
44350
- const scoreA = a.matches.length * a.similarity;
44351
- const scoreB = b.matches.length * b.similarity;
44352
- return scoreB - scoreA;
44353
- });
44354
- return duplicates;
44355
- }
44356
-
44357
43573
  // src/ast.ts
44358
43574
  var import_parser = __toESM(require_lib(), 1);
44359
43575
  var import_traverse = __toESM(require_lib8(), 1);
44360
43576
  var t = __toESM(require_lib4(), 1);
44361
43577
  var traverse = import_traverse.default.default || import_traverse.default;
44362
- function simpleHash2(str) {
43578
+ function simpleHash(str) {
44363
43579
  let hash = 0;
44364
43580
  for (let i = 0; i < str.length; i++) {
44365
43581
  hash = (hash << 5) - hash + str.charCodeAt(i);
@@ -44584,8 +43800,8 @@ function extractASTBlocks(content, filePath) {
44584
43800
  errorRecovery: true
44585
43801
  });
44586
43802
  traverse(ast, {
44587
- FunctionDeclaration(path5) {
44588
- const node = path5.node;
43803
+ FunctionDeclaration(path6) {
43804
+ const node = path6.node;
44589
43805
  if (!node.id || !node.loc || node.start === null || node.end === null) return;
44590
43806
  const idMap = /* @__PURE__ */ new Map();
44591
43807
  const counter = { val: 0 };
@@ -44595,15 +43811,15 @@ function extractASTBlocks(content, filePath) {
44595
43811
  name: node.id.name,
44596
43812
  content: content.slice(node.start, node.end),
44597
43813
  normalized,
44598
- hash: simpleHash2(normalized),
43814
+ hash: simpleHash(normalized),
44599
43815
  filePath,
44600
43816
  startLine: node.loc.start.line,
44601
43817
  endLine: node.loc.end.line,
44602
- exported: t.isExportNamedDeclaration(path5.parent) || t.isExportDefaultDeclaration(path5.parent)
43818
+ exported: t.isExportNamedDeclaration(path6.parent) || t.isExportDefaultDeclaration(path6.parent)
44603
43819
  });
44604
43820
  },
44605
- VariableDeclaration(path5) {
44606
- const node = path5.node;
43821
+ VariableDeclaration(path6) {
43822
+ const node = path6.node;
44607
43823
  for (const decl of node.declarations) {
44608
43824
  if (!t.isIdentifier(decl.id) || !decl.init || !decl.loc) continue;
44609
43825
  if (decl.start === null || decl.end === null) continue;
@@ -44616,16 +43832,16 @@ function extractASTBlocks(content, filePath) {
44616
43832
  name: decl.id.name,
44617
43833
  content: content.slice(decl.start, decl.end),
44618
43834
  normalized,
44619
- hash: simpleHash2(normalized),
43835
+ hash: simpleHash(normalized),
44620
43836
  filePath,
44621
43837
  startLine: decl.loc.start.line,
44622
43838
  endLine: decl.loc.end.line,
44623
- exported: t.isExportNamedDeclaration(path5.parent)
43839
+ exported: t.isExportNamedDeclaration(path6.parent)
44624
43840
  });
44625
43841
  }
44626
43842
  },
44627
- ClassDeclaration(path5) {
44628
- const node = path5.node;
43843
+ ClassDeclaration(path6) {
43844
+ const node = path6.node;
44629
43845
  if (!node.id || !node.loc || node.start === null || node.end === null) return;
44630
43846
  const idMap = /* @__PURE__ */ new Map();
44631
43847
  const counter = { val: 0 };
@@ -44635,15 +43851,15 @@ function extractASTBlocks(content, filePath) {
44635
43851
  name: node.id.name,
44636
43852
  content: content.slice(node.start, node.end),
44637
43853
  normalized,
44638
- hash: simpleHash2(normalized),
43854
+ hash: simpleHash(normalized),
44639
43855
  filePath,
44640
43856
  startLine: node.loc.start.line,
44641
43857
  endLine: node.loc.end.line,
44642
- exported: t.isExportNamedDeclaration(path5.parent) || t.isExportDefaultDeclaration(path5.parent)
43858
+ exported: t.isExportNamedDeclaration(path6.parent) || t.isExportDefaultDeclaration(path6.parent)
44643
43859
  });
44644
43860
  },
44645
- TSTypeAliasDeclaration(path5) {
44646
- const node = path5.node;
43861
+ TSTypeAliasDeclaration(path6) {
43862
+ const node = path6.node;
44647
43863
  if (!node.loc || node.start === null || node.end === null) return;
44648
43864
  const nodeContent = content.slice(node.start, node.end);
44649
43865
  blocks.push({
@@ -44651,15 +43867,15 @@ function extractASTBlocks(content, filePath) {
44651
43867
  name: node.id.name,
44652
43868
  content: nodeContent,
44653
43869
  normalized: nodeContent.replace(/\s+/g, " "),
44654
- hash: simpleHash2(nodeContent.replace(/\s+/g, " ")),
43870
+ hash: simpleHash(nodeContent.replace(/\s+/g, " ")),
44655
43871
  filePath,
44656
43872
  startLine: node.loc.start.line,
44657
43873
  endLine: node.loc.end.line,
44658
- exported: t.isExportNamedDeclaration(path5.parent)
43874
+ exported: t.isExportNamedDeclaration(path6.parent)
44659
43875
  });
44660
43876
  },
44661
- TSInterfaceDeclaration(path5) {
44662
- const node = path5.node;
43877
+ TSInterfaceDeclaration(path6) {
43878
+ const node = path6.node;
44663
43879
  if (!node.loc || node.start === null || node.end === null) return;
44664
43880
  const nodeContent = content.slice(node.start, node.end);
44665
43881
  blocks.push({
@@ -44667,11 +43883,11 @@ function extractASTBlocks(content, filePath) {
44667
43883
  name: node.id.name,
44668
43884
  content: nodeContent,
44669
43885
  normalized: nodeContent.replace(/\s+/g, " "),
44670
- hash: simpleHash2(nodeContent.replace(/\s+/g, " ")),
43886
+ hash: simpleHash(nodeContent.replace(/\s+/g, " ")),
44671
43887
  filePath,
44672
43888
  startLine: node.loc.start.line,
44673
43889
  endLine: node.loc.end.line,
44674
- exported: t.isExportNamedDeclaration(path5.parent)
43890
+ exported: t.isExportNamedDeclaration(path6.parent)
44675
43891
  });
44676
43892
  }
44677
43893
  });
@@ -44713,22 +43929,37 @@ function findASTDuplicates(blocks, _minSimilarity) {
44713
43929
  });
44714
43930
  }
44715
43931
  groups.sort((a, b) => b.matches.length - a.matches.length);
44716
- return groups;
43932
+ const crossFileGroups = groups.filter((group) => {
43933
+ const uniqueFiles = new Set(group.matches.map((m) => m.filePath));
43934
+ return uniqueFiles.size > 1;
43935
+ });
43936
+ return crossFileGroups;
44717
43937
  }
44718
43938
 
44719
43939
  // src/formatter.ts
44720
43940
  var import_node_path = __toESM(require("node:path"), 1);
43941
+ var MAX_PATH_LENGTH = 60;
43942
+ var SEPARATOR = "\u2500".repeat(80);
43943
+ var COLORS = {
43944
+ reset: "\x1B[0m",
43945
+ bold: "\x1B[1m",
43946
+ dim: "\x1B[2m",
43947
+ red: "\x1B[31m",
43948
+ green: "\x1B[32m",
43949
+ yellow: "\x1B[33m",
43950
+ cyan: "\x1B[36m",
43951
+ magenta: "\x1B[35m",
43952
+ gray: "\x1B[90m"
43953
+ };
44721
43954
  var { reset, bold, dim, red, green, yellow, cyan, magenta, gray } = COLORS;
44722
43955
  function truncatePath(filePath, basePath) {
44723
43956
  const absoluteBase = import_node_path.default.resolve(basePath);
44724
43957
  let relativePath = filePath;
44725
43958
  if (filePath.startsWith(absoluteBase)) {
44726
43959
  relativePath = filePath.slice(absoluteBase.length);
44727
- if (relativePath.startsWith("/") || relativePath.startsWith("\\")) {
44728
- relativePath = relativePath.slice(1);
44729
- }
43960
+ if (relativePath.startsWith("/")) relativePath = relativePath.slice(1);
44730
43961
  }
44731
- if (relativePath.length > MAX_PATH_DISPLAY_LENGTH) {
43962
+ if (relativePath.length > MAX_PATH_LENGTH) {
44732
43963
  const parts = relativePath.split(import_node_path.default.sep);
44733
43964
  if (parts.length > 3) {
44734
43965
  relativePath = `${parts[0]}/.../${parts.slice(-2).join("/")}`;
@@ -44736,176 +43967,7 @@ function truncatePath(filePath, basePath) {
44736
43967
  }
44737
43968
  return relativePath;
44738
43969
  }
44739
- function getSimilarityBadge(similarity) {
44740
- const percent = Math.round(similarity * 100);
44741
- if (similarity === 1) {
44742
- return `${red}${bold}EXACT${reset}`;
44743
- } else if (similarity >= 0.9) {
44744
- return `${yellow}${percent}%${reset}`;
44745
- } else {
44746
- return `${cyan}${percent}%${reset}`;
44747
- }
44748
- }
44749
- function formatGroup(group, index, basePath) {
44750
- const lines = [];
44751
- const badge = getSimilarityBadge(group.similarity);
44752
- const impact = group.occurrences * group.lineCount;
44753
- lines.push(`${bold}Group ${index + 1}${reset} \u2502 ${badge} \u2502 ${group.lineCount} lines \xD7 ${group.occurrences} occurrences = ${green}${impact} lines${reset} of duplication`);
44754
- lines.push("");
44755
- const matchesToShow = group.matches.slice(0, MAX_MATCHES_IN_SUMMARY);
44756
- const hasMore = group.matches.length > MAX_MATCHES_IN_SUMMARY;
44757
- for (const match2 of matchesToShow) {
44758
- const displayPath = truncatePath(match2.filePath, basePath);
44759
- lines.push(` ${dim}\u251C\u2500${reset} ${displayPath}:${yellow}${match2.startLine}${reset}-${yellow}${match2.endLine}${reset}`);
44760
- }
44761
- if (hasMore) {
44762
- lines.push(` ${dim}\u2514\u2500${reset} ${gray}... and ${group.matches.length - MAX_MATCHES_IN_SUMMARY} more${reset}`);
44763
- }
44764
- const firstMatch = group.matches[0];
44765
- if (firstMatch) {
44766
- lines.push("");
44767
- lines.push(` ${dim}Code preview:${reset}`);
44768
- const previewLines = firstMatch.content.split("\n").slice(0, CODE_PREVIEW_CONTEXT_LINES).map((line) => ` ${gray}\u2502${reset} ${dim}${line.slice(0, 80)}${line.length > 80 ? "..." : ""}${reset}`);
44769
- lines.push(...previewLines);
44770
- if (firstMatch.content.split("\n").length > CODE_PREVIEW_CONTEXT_LINES) {
44771
- lines.push(` ${gray}\u2502${reset} ${dim}...${reset}`);
44772
- }
44773
- }
44774
- if (group.suggestion) {
44775
- lines.push("");
44776
- const confidenceColor = group.suggestion.confidence === "high" ? green : group.suggestion.confidence === "medium" ? yellow : gray;
44777
- lines.push(` ${magenta}\u2192 Suggestion:${reset} Move to ${cyan}${group.suggestion.targetLocation}${reset}`);
44778
- if (group.suggestion.suggestedName) {
44779
- lines.push(` ${dim} Name: ${group.suggestion.suggestedName}${reset}`);
44780
- }
44781
- lines.push(` ${dim} ${group.suggestion.reason} ${confidenceColor}[${group.suggestion.confidence}]${reset}`);
44782
- }
44783
- return lines.join("\n");
44784
- }
44785
- function formatOutput(groups, basePath) {
44786
- if (groups.length === 0) {
44787
- return `${green}No duplicates found!${reset}`;
44788
- }
44789
- const lines = [];
44790
- lines.push(SECTION_SEPARATOR);
44791
- lines.push(`${bold}DUPLICATE CODE DETECTED${reset}`);
44792
- lines.push(SECTION_SEPARATOR);
44793
- lines.push("");
44794
- const groupsToShow = groups.slice(0, MAX_GROUPS_DETAILED);
44795
- for (let i = 0; i < groupsToShow.length; i++) {
44796
- const group = groupsToShow[i];
44797
- if (group) {
44798
- lines.push(formatGroup(group, i, basePath));
44799
- lines.push("");
44800
- }
44801
- }
44802
- if (groups.length > MAX_GROUPS_DETAILED) {
44803
- lines.push(`${dim}... and ${groups.length - MAX_GROUPS_DETAILED} more groups${reset}`);
44804
- lines.push("");
44805
- }
44806
- lines.push(SECTION_SEPARATOR);
44807
- return lines.join("\n");
44808
- }
44809
- function formatStats(groups) {
44810
- if (groups.length === 0) {
44811
- return "";
44812
- }
44813
- const totalDuplicateLines = groups.reduce(
44814
- (sum, g) => sum + g.lineCount * g.occurrences,
44815
- 0
44816
- );
44817
- const exactMatches = groups.filter((g) => g.similarity === 1).length;
44818
- const similarMatches = groups.length - exactMatches;
44819
- const avgSimilarity = groups.reduce((sum, g) => sum + g.similarity, 0) / groups.length;
44820
- const uniqueFiles = /* @__PURE__ */ new Set();
44821
- for (const group of groups) {
44822
- for (const match2 of group.matches) {
44823
- uniqueFiles.add(match2.filePath);
44824
- }
44825
- }
44826
- const lines = [];
44827
- lines.push(`${bold}SUMMARY${reset}`);
44828
- lines.push(SECTION_SEPARATOR);
44829
- lines.push(` Total duplicate groups: ${bold}${groups.length}${reset}`);
44830
- lines.push(` Exact matches: ${bold}${exactMatches}${reset}`);
44831
- lines.push(` Similar matches: ${bold}${similarMatches}${reset}`);
44832
- lines.push(` Files affected: ${bold}${uniqueFiles.size}${reset}`);
44833
- lines.push(` Total duplicate lines: ${red}${bold}${totalDuplicateLines.toLocaleString()}${reset}`);
44834
- lines.push(` Average similarity: ${bold}${Math.round(avgSimilarity * 100)}%${reset}`);
44835
- lines.push(SECTION_SEPARATOR);
44836
- lines.push("");
44837
- lines.push(`${dim}Tip: Use --json for machine-readable output${reset}`);
44838
- return lines.join("\n");
44839
- }
44840
43970
  var TYPE_LABELS = {
44841
- type: "Type",
44842
- interface: "Interface",
44843
- function: "Function",
44844
- class: "Class",
44845
- const: "Constant",
44846
- enum: "Enum"
44847
- };
44848
- function formatDeclarationGroup(group, index, basePath) {
44849
- const lines = [];
44850
- const typeLabel = TYPE_LABELS[group.type] || group.type;
44851
- const simBadge = group.similarity >= 0.95 ? `${red}${bold}EXACT${reset}` : `${yellow}${Math.round(group.similarity * 100)}%${reset}`;
44852
- lines.push(`${bold}${typeLabel} ${index + 1}${reset} \u2502 ${simBadge} \u2502 ${group.matches.length} occurrences`);
44853
- if (group.nameSimilarity > 0 && group.nameSimilarity < 1) {
44854
- lines.push(` ${dim}Name similarity: ${Math.round(group.nameSimilarity * 100)}%${reset}`);
44855
- }
44856
- lines.push("");
44857
- for (const match2 of group.matches.slice(0, 5)) {
44858
- const displayPath = truncatePath(match2.filePath, basePath);
44859
- const exportBadge = match2.exported ? `${green}exported${reset}` : `${gray}local${reset}`;
44860
- lines.push(` ${dim}\u251C\u2500${reset} ${cyan}${match2.name}${reset} [${exportBadge}]`);
44861
- lines.push(` ${displayPath}:${yellow}${match2.startLine}${reset}-${yellow}${match2.endLine}${reset}`);
44862
- }
44863
- if (group.matches.length > 5) {
44864
- lines.push(` ${dim}\u2514\u2500${reset} ${gray}... and ${group.matches.length - 5} more${reset}`);
44865
- }
44866
- lines.push("");
44867
- lines.push(` ${magenta}\u2192${reset} ${group.suggestion}`);
44868
- return lines.join("\n");
44869
- }
44870
- function formatDeclarations(groups, basePath) {
44871
- if (groups.length === 0) {
44872
- return "";
44873
- }
44874
- const lines = [];
44875
- lines.push("");
44876
- lines.push(SECTION_SEPARATOR);
44877
- lines.push(`${bold}DUPLICATE DECLARATIONS${reset}`);
44878
- lines.push(SECTION_SEPARATOR);
44879
- lines.push("");
44880
- const byType = /* @__PURE__ */ new Map();
44881
- for (const group of groups) {
44882
- const existing = byType.get(group.type) || [];
44883
- existing.push(group);
44884
- byType.set(group.type, existing);
44885
- }
44886
- let globalIndex = 0;
44887
- for (const [type, typeGroups] of byType) {
44888
- const typeLabel = TYPE_LABELS[type] || type;
44889
- lines.push(`${bold}${typeLabel}s (${typeGroups.length})${reset}`);
44890
- lines.push("");
44891
- for (const group of typeGroups.slice(0, 10)) {
44892
- lines.push(formatDeclarationGroup(group, globalIndex++, basePath));
44893
- lines.push("");
44894
- }
44895
- if (typeGroups.length > 10) {
44896
- lines.push(`${dim}... and ${typeGroups.length - 10} more ${typeLabel.toLowerCase()}s${reset}`);
44897
- lines.push("");
44898
- }
44899
- }
44900
- lines.push(SECTION_SEPARATOR);
44901
- const totalDups = groups.reduce((sum, g) => sum + g.matches.length, 0);
44902
- lines.push(`${bold}Declaration Summary${reset}`);
44903
- lines.push(` Duplicate groups: ${bold}${groups.length}${reset}`);
44904
- lines.push(` Total occurrences: ${bold}${totalDups}${reset}`);
44905
- lines.push(SECTION_SEPARATOR);
44906
- return lines.join("\n");
44907
- }
44908
- var AST_TYPE_LABELS = {
44909
43971
  function: "Function",
44910
43972
  arrow: "Arrow Function",
44911
43973
  class: "Class",
@@ -44915,17 +43977,16 @@ var AST_TYPE_LABELS = {
44915
43977
  function formatASTDuplicates(groups, basePath) {
44916
43978
  if (groups.length === 0) return "";
44917
43979
  const lines = [];
43980
+ lines.push(SEPARATOR);
43981
+ lines.push(`${bold}DUPLICATE FUNCTIONS/TYPES${reset}`);
43982
+ lines.push(SEPARATOR);
44918
43983
  lines.push("");
44919
- lines.push(SECTION_SEPARATOR);
44920
- lines.push(`${bold}DUPLICATE FUNCTIONS (AST-based)${reset}`);
44921
- lines.push(SECTION_SEPARATOR);
44922
- lines.push("");
44923
- lines.push(`${dim}These functions have identical structure (ignoring variable names)${reset}`);
43984
+ lines.push(`${dim}These have identical structure (ignoring variable names)${reset}`);
44924
43985
  lines.push("");
44925
43986
  for (let i = 0; i < Math.min(groups.length, 20); i++) {
44926
43987
  const group = groups[i];
44927
43988
  if (!group) continue;
44928
- const typeLabel = AST_TYPE_LABELS[group.type] || group.type;
43989
+ const typeLabel = TYPE_LABELS[group.type] || group.type;
44929
43990
  lines.push(`${bold}${typeLabel} ${i + 1}${reset} \u2502 ${red}${bold}IDENTICAL${reset} \u2502 ${group.matches.length} occurrences`);
44930
43991
  lines.push("");
44931
43992
  for (const match2 of group.matches.slice(0, 5)) {
@@ -44948,21 +44009,18 @@ function formatASTDuplicates(groups, basePath) {
44948
44009
  lines.push("");
44949
44010
  }
44950
44011
  if (groups.length > 20) {
44951
- lines.push(`${dim}... and ${groups.length - 20} more duplicate functions${reset}`);
44012
+ lines.push(`${dim}... and ${groups.length - 20} more${reset}`);
44952
44013
  lines.push("");
44953
44014
  }
44954
- lines.push(SECTION_SEPARATOR);
44955
- const totalDups = groups.reduce((sum, g) => sum + g.matches.length, 0);
44956
- lines.push(`${bold}AST Summary${reset}`);
44957
- lines.push(` Duplicate groups: ${bold}${groups.length}${reset}`);
44958
- lines.push(` Total occurrences: ${bold}${totalDups}${reset}`);
44959
- lines.push(SECTION_SEPARATOR);
44015
+ lines.push(SEPARATOR);
44016
+ lines.push(`${bold}Summary${reset}: ${groups.length} duplicate groups, ${groups.reduce((sum, g) => sum + g.matches.length, 0)} total occurrences`);
44017
+ lines.push(SEPARATOR);
44960
44018
  return lines.join("\n");
44961
44019
  }
44962
44020
 
44963
44021
  // src/scanner.ts
44964
- var import_promises2 = require("node:fs/promises");
44965
- var import_node_path3 = __toESM(require("node:path"), 1);
44022
+ var import_promises3 = require("node:fs/promises");
44023
+ var import_node_path4 = __toESM(require("node:path"), 1);
44966
44024
 
44967
44025
  // node_modules/@isaacs/balanced-match/dist/esm/index.js
44968
44026
  var balanced = (a, b, str) => {
@@ -49093,12 +48151,12 @@ var PathBase = class {
49093
48151
  /**
49094
48152
  * Get the Path object referenced by the string path, resolved from this Path
49095
48153
  */
49096
- resolve(path5) {
49097
- if (!path5) {
48154
+ resolve(path6) {
48155
+ if (!path6) {
49098
48156
  return this;
49099
48157
  }
49100
- const rootPath = this.getRootString(path5);
49101
- const dir = path5.substring(rootPath.length);
48158
+ const rootPath = this.getRootString(path6);
48159
+ const dir = path6.substring(rootPath.length);
49102
48160
  const dirParts = dir.split(this.splitSep);
49103
48161
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
49104
48162
  return result;
@@ -49850,8 +48908,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
49850
48908
  /**
49851
48909
  * @internal
49852
48910
  */
49853
- getRootString(path5) {
49854
- return import_node_path2.win32.parse(path5).root;
48911
+ getRootString(path6) {
48912
+ return import_node_path2.win32.parse(path6).root;
49855
48913
  }
49856
48914
  /**
49857
48915
  * @internal
@@ -49897,8 +48955,8 @@ var PathPosix = class _PathPosix extends PathBase {
49897
48955
  /**
49898
48956
  * @internal
49899
48957
  */
49900
- getRootString(path5) {
49901
- return path5.startsWith("/") ? "/" : "";
48958
+ getRootString(path6) {
48959
+ return path6.startsWith("/") ? "/" : "";
49902
48960
  }
49903
48961
  /**
49904
48962
  * @internal
@@ -49987,11 +49045,11 @@ var PathScurryBase = class {
49987
49045
  /**
49988
49046
  * Get the depth of a provided path, string, or the cwd
49989
49047
  */
49990
- depth(path5 = this.cwd) {
49991
- if (typeof path5 === "string") {
49992
- path5 = this.cwd.resolve(path5);
49048
+ depth(path6 = this.cwd) {
49049
+ if (typeof path6 === "string") {
49050
+ path6 = this.cwd.resolve(path6);
49993
49051
  }
49994
- return path5.depth();
49052
+ return path6.depth();
49995
49053
  }
49996
49054
  /**
49997
49055
  * Return the cache of child entries. Exposed so subclasses can create
@@ -50478,9 +49536,9 @@ var PathScurryBase = class {
50478
49536
  process2();
50479
49537
  return results;
50480
49538
  }
50481
- chdir(path5 = this.cwd) {
49539
+ chdir(path6 = this.cwd) {
50482
49540
  const oldCwd = this.cwd;
50483
- this.cwd = typeof path5 === "string" ? this.cwd.resolve(path5) : path5;
49541
+ this.cwd = typeof path6 === "string" ? this.cwd.resolve(path6) : path6;
50484
49542
  this.cwd[setAsCwd](oldCwd);
50485
49543
  }
50486
49544
  };
@@ -50836,8 +49894,8 @@ var MatchRecord = class {
50836
49894
  }
50837
49895
  // match, absolute, ifdir
50838
49896
  entries() {
50839
- return [...this.store.entries()].map(([path5, n]) => [
50840
- path5,
49897
+ return [...this.store.entries()].map(([path6, n]) => [
49898
+ path6,
50841
49899
  !!(n & 2),
50842
49900
  !!(n & 1)
50843
49901
  ]);
@@ -51042,9 +50100,9 @@ var GlobUtil = class {
51042
50100
  signal;
51043
50101
  maxDepth;
51044
50102
  includeChildMatches;
51045
- constructor(patterns, path5, opts) {
50103
+ constructor(patterns, path6, opts) {
51046
50104
  this.patterns = patterns;
51047
- this.path = path5;
50105
+ this.path = path6;
51048
50106
  this.opts = opts;
51049
50107
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
51050
50108
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -51063,11 +50121,11 @@ var GlobUtil = class {
51063
50121
  });
51064
50122
  }
51065
50123
  }
51066
- #ignored(path5) {
51067
- return this.seen.has(path5) || !!this.#ignore?.ignored?.(path5);
50124
+ #ignored(path6) {
50125
+ return this.seen.has(path6) || !!this.#ignore?.ignored?.(path6);
51068
50126
  }
51069
- #childrenIgnored(path5) {
51070
- return !!this.#ignore?.childrenIgnored?.(path5);
50127
+ #childrenIgnored(path6) {
50128
+ return !!this.#ignore?.childrenIgnored?.(path6);
51071
50129
  }
51072
50130
  // backpressure mechanism
51073
50131
  pause() {
@@ -51282,8 +50340,8 @@ var GlobUtil = class {
51282
50340
  };
51283
50341
  var GlobWalker = class extends GlobUtil {
51284
50342
  matches = /* @__PURE__ */ new Set();
51285
- constructor(patterns, path5, opts) {
51286
- super(patterns, path5, opts);
50343
+ constructor(patterns, path6, opts) {
50344
+ super(patterns, path6, opts);
51287
50345
  }
51288
50346
  matchEmit(e) {
51289
50347
  this.matches.add(e);
@@ -51320,8 +50378,8 @@ var GlobWalker = class extends GlobUtil {
51320
50378
  };
51321
50379
  var GlobStream = class extends GlobUtil {
51322
50380
  results;
51323
- constructor(patterns, path5, opts) {
51324
- super(patterns, path5, opts);
50381
+ constructor(patterns, path6, opts) {
50382
+ super(patterns, path6, opts);
51325
50383
  this.results = new Minipass({
51326
50384
  signal: this.signal,
51327
50385
  objectMode: true
@@ -51614,59 +50672,113 @@ var glob = Object.assign(glob_, {
51614
50672
  });
51615
50673
  glob.glob = glob;
51616
50674
 
51617
- // src/scanner.ts
51618
- function simpleHash3(str) {
51619
- let hash = 0;
51620
- for (let i = 0; i < str.length; i++) {
51621
- const char = str.charCodeAt(i);
51622
- hash = (hash << 5) - hash + char;
51623
- hash = hash & hash;
50675
+ // src/cache.ts
50676
+ var import_promises2 = require("node:fs/promises");
50677
+ var import_node_path3 = __toESM(require("node:path"), 1);
50678
+ var CACHE_VERSION = 2;
50679
+ var CACHE_FILE = ".dslop-cache";
50680
+ var ASTCache = class {
50681
+ cache = { version: CACHE_VERSION, files: {} };
50682
+ cachePath;
50683
+ dirty = false;
50684
+ hits = 0;
50685
+ misses = 0;
50686
+ constructor(targetPath) {
50687
+ this.cachePath = import_node_path3.default.join(import_node_path3.default.resolve(targetPath), CACHE_FILE);
50688
+ }
50689
+ async load() {
50690
+ try {
50691
+ const data = await (0, import_promises2.readFile)(this.cachePath, "utf-8");
50692
+ const parsed = JSON.parse(data);
50693
+ if (parsed.version !== CACHE_VERSION) {
50694
+ this.cache = { version: CACHE_VERSION, files: {} };
50695
+ return;
50696
+ }
50697
+ this.cache = parsed;
50698
+ } catch {
50699
+ this.cache = { version: CACHE_VERSION, files: {} };
50700
+ }
51624
50701
  }
51625
- return hash.toString(36);
51626
- }
51627
- function isSkippableLine(line) {
51628
- const trimmed = line.trim();
51629
- if (trimmed.length === 0) return true;
51630
- return SKIP_LINE_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
51631
- }
51632
- function extractBlocks(content, filePath, minLines, shouldNormalize) {
51633
- const lines = content.split("\n");
51634
- const blocks = [];
51635
- if (lines.length < minLines) {
51636
- return blocks;
51637
- }
51638
- const blockSizes = [minLines];
51639
- const maxSize = Math.min(MAX_BLOCK_SIZE, lines.length);
51640
- for (let size = Math.floor(minLines * BLOCK_SIZE_MULTIPLIER); size <= maxSize; size = Math.floor(size * BLOCK_SIZE_MULTIPLIER)) {
51641
- blockSizes.push(size);
51642
- }
51643
- for (const blockSize of blockSizes) {
51644
- const step = blockSize < 10 ? 1 : Math.max(1, Math.floor(blockSize / SLIDING_WINDOW_STEP_DIVISOR));
51645
- for (let i = 0; i <= lines.length - blockSize; i += step) {
51646
- const blockLines = lines.slice(i, i + blockSize);
51647
- const blockContent = blockLines.join("\n");
51648
- const meaningfulLines = blockLines.filter(
51649
- (line) => !isSkippableLine(line)
51650
- );
51651
- if (meaningfulLines.length < blockSize * MIN_MEANINGFUL_LINE_RATIO) {
51652
- continue;
50702
+ async get(filePath) {
50703
+ const cached = this.cache.files[filePath];
50704
+ if (!cached) {
50705
+ this.misses++;
50706
+ return null;
50707
+ }
50708
+ try {
50709
+ const fileStat = await (0, import_promises2.stat)(filePath);
50710
+ if (fileStat.mtimeMs !== cached.mtime || fileStat.size !== cached.size) {
50711
+ this.misses++;
50712
+ return null;
51653
50713
  }
51654
- const normalized = shouldNormalize ? normalizeCode(blockContent) : blockContent;
51655
- const hash = simpleHash3(normalized);
51656
- blocks.push({
51657
- content: blockContent,
51658
- normalized,
51659
- hash,
50714
+ this.hits++;
50715
+ return cached.blocks.map((b) => ({
50716
+ type: b.type,
50717
+ name: b.name,
50718
+ content: "",
50719
+ // Don't cache content - we can re-read if needed
50720
+ normalized: b.normalized,
50721
+ hash: b.hash,
51660
50722
  filePath,
51661
- startLine: i + 1,
51662
- // 1-indexed
51663
- endLine: i + blockSize,
51664
- lineCount: blockSize
51665
- });
50723
+ startLine: b.startLine,
50724
+ endLine: b.endLine,
50725
+ exported: b.exported
50726
+ }));
50727
+ } catch {
50728
+ this.misses++;
50729
+ return null;
51666
50730
  }
51667
50731
  }
51668
- return blocks;
51669
- }
50732
+ async set(filePath, blocks) {
50733
+ try {
50734
+ const fileStat = await (0, import_promises2.stat)(filePath);
50735
+ this.cache.files[filePath] = {
50736
+ mtime: fileStat.mtimeMs,
50737
+ size: fileStat.size,
50738
+ blocks: blocks.map((b) => ({
50739
+ type: b.type,
50740
+ name: b.name,
50741
+ hash: b.hash,
50742
+ normalized: b.normalized,
50743
+ startLine: b.startLine,
50744
+ endLine: b.endLine,
50745
+ exported: b.exported
50746
+ }))
50747
+ };
50748
+ this.dirty = true;
50749
+ } catch {
50750
+ }
50751
+ }
50752
+ async save() {
50753
+ if (!this.dirty) return;
50754
+ try {
50755
+ const dir = import_node_path3.default.dirname(this.cachePath);
50756
+ await (0, import_promises2.mkdir)(dir, { recursive: true });
50757
+ const prunedFiles = {};
50758
+ for (const [filePath, cached] of Object.entries(this.cache.files)) {
50759
+ try {
50760
+ await (0, import_promises2.stat)(filePath);
50761
+ prunedFiles[filePath] = cached;
50762
+ } catch {
50763
+ }
50764
+ }
50765
+ this.cache.files = prunedFiles;
50766
+ await (0, import_promises2.writeFile)(this.cachePath, JSON.stringify(this.cache), "utf-8");
50767
+ } catch {
50768
+ }
50769
+ }
50770
+ getStats() {
50771
+ const total = this.hits + this.misses;
50772
+ return {
50773
+ hits: this.hits,
50774
+ misses: this.misses,
50775
+ hitRate: total > 0 ? this.hits / total : 0
50776
+ };
50777
+ }
50778
+ };
50779
+
50780
+ // src/scanner.ts
50781
+ var MAX_FILE_SIZE = 1024 * 1024;
51670
50782
  function shouldIgnore(filePath, ignorePatterns) {
51671
50783
  const normalizedPath = filePath.toLowerCase();
51672
50784
  return ignorePatterns.some((pattern) => {
@@ -51674,14 +50786,16 @@ function shouldIgnore(filePath, ignorePatterns) {
51674
50786
  return normalizedPath.includes(`/${normalizedPattern}/`) || normalizedPath.includes(`\\${normalizedPattern}\\`) || normalizedPath.endsWith(`/${normalizedPattern}`) || normalizedPath.endsWith(`\\${normalizedPattern}`);
51675
50787
  });
51676
50788
  }
51677
- async function scanDirectory(targetPath, options, enableAST = true) {
51678
- const { extensions, ignorePatterns, minLines, normalize: normalize2 } = options;
51679
- const absolutePath = import_node_path3.default.resolve(targetPath);
51680
- const blocks = [];
51681
- const declarations = [];
50789
+ async function scanDirectory(targetPath, options, useCache = true) {
50790
+ const { extensions, ignorePatterns } = options;
50791
+ const absolutePath = import_node_path4.default.resolve(targetPath);
51682
50792
  const astBlocks = [];
51683
50793
  let fileCount = 0;
51684
50794
  let totalLines = 0;
50795
+ const cache = useCache ? new ASTCache(targetPath) : null;
50796
+ if (cache) {
50797
+ await cache.load();
50798
+ }
51685
50799
  const pattern = extensions.length === 1 ? `**/*.${extensions[0]}` : `**/*.{${extensions.join(",")}}`;
51686
50800
  const files = await glob(pattern, {
51687
50801
  cwd: absolutePath,
@@ -51689,49 +50803,70 @@ async function scanDirectory(targetPath, options, enableAST = true) {
51689
50803
  nodir: true,
51690
50804
  ignore: ignorePatterns.map((p) => `**/${p}/**`)
51691
50805
  });
51692
- const isTypeScript = extensions.some((ext2) => ext2 === "ts" || ext2 === "tsx");
51693
50806
  for (const filePath of files) {
51694
50807
  if (shouldIgnore(filePath, ignorePatterns)) {
51695
50808
  continue;
51696
50809
  }
50810
+ if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") && !filePath.endsWith(".js") && !filePath.endsWith(".jsx")) {
50811
+ continue;
50812
+ }
51697
50813
  try {
51698
- const fileStat = await (0, import_promises2.stat)(filePath);
50814
+ const fileStat = await (0, import_promises3.stat)(filePath);
51699
50815
  if (fileStat.size > MAX_FILE_SIZE) {
51700
50816
  continue;
51701
50817
  }
51702
- const content = await (0, import_promises2.readFile)(filePath, "utf-8");
51703
- const lines = content.split("\n").length;
51704
- totalLines += lines;
51705
- fileCount++;
51706
- const fileBlocks = extractBlocks(
51707
- content,
51708
- filePath,
51709
- minLines,
51710
- normalize2
51711
- );
51712
- blocks.push(...fileBlocks);
51713
- if (enableAST && isTypeScript && (filePath.endsWith(".ts") || filePath.endsWith(".tsx"))) {
50818
+ const cachedAST = cache ? await cache.get(filePath) : null;
50819
+ if (cachedAST) {
50820
+ astBlocks.push(...cachedAST);
50821
+ const content = await (0, import_promises3.readFile)(filePath, "utf-8");
50822
+ totalLines += content.split("\n").length;
50823
+ fileCount++;
50824
+ } else {
50825
+ const content = await (0, import_promises3.readFile)(filePath, "utf-8");
50826
+ totalLines += content.split("\n").length;
50827
+ fileCount++;
51714
50828
  const fileAST = extractASTBlocks(content, filePath);
51715
50829
  astBlocks.push(...fileAST);
51716
- const fileDeclarations = extractDeclarations(content, filePath);
51717
- declarations.push(...fileDeclarations);
50830
+ if (cache) {
50831
+ await cache.set(filePath, fileAST);
50832
+ }
51718
50833
  }
51719
50834
  } catch {
51720
- console.warn(`Warning: Could not read ${filePath}`);
51721
50835
  }
51722
50836
  }
51723
- return { blocks, declarations, astBlocks, fileCount, totalLines };
50837
+ if (cache) {
50838
+ await cache.save();
50839
+ }
50840
+ return {
50841
+ astBlocks,
50842
+ fileCount,
50843
+ totalLines,
50844
+ cacheStats: cache?.getStats()
50845
+ };
51724
50846
  }
51725
50847
 
51726
50848
  // index.ts
51727
- var VERSION = process.env.npm_package_version || "1.6.1";
50849
+ var VERSION = process.env.npm_package_version || "1.7.1";
50850
+ var DEFAULT_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
50851
+ var DEFAULT_IGNORE_PATTERNS = [
50852
+ "node_modules",
50853
+ "dist",
50854
+ ".git",
50855
+ "build",
50856
+ ".next",
50857
+ "coverage",
50858
+ ".turbo",
50859
+ ".cache",
50860
+ "migrations",
50861
+ "__generated__"
50862
+ ];
51728
50863
  function parseDiffOutput(diff, cwd) {
51729
50864
  const changes = /* @__PURE__ */ new Map();
51730
50865
  let currentFile = null;
51731
50866
  let newLineNum = 0;
51732
50867
  for (const line of diff.split("\n")) {
51733
50868
  if (line.startsWith("+++ b/")) {
51734
- currentFile = import_node_path4.default.resolve(cwd, line.slice(6));
50869
+ currentFile = import_node_path5.default.resolve(cwd, line.slice(6));
51735
50870
  if (!changes.has(currentFile)) {
51736
50871
  changes.set(currentFile, []);
51737
50872
  }
@@ -51759,7 +50894,7 @@ function parseDiffOutput(diff, cwd) {
51759
50894
  return changes;
51760
50895
  }
51761
50896
  function getChangedLines(targetPath) {
51762
- const absolutePath = import_node_path4.default.resolve(targetPath);
50897
+ const absolutePath = import_node_path5.default.resolve(targetPath);
51763
50898
  const allChanges = /* @__PURE__ */ new Map();
51764
50899
  const mergeChanges = (newChanges) => {
51765
50900
  for (const [file, ranges] of newChanges) {
@@ -51769,16 +50904,14 @@ function getChangedLines(targetPath) {
51769
50904
  }
51770
50905
  };
51771
50906
  const addFullFile = (filePath) => {
51772
- const resolved = import_node_path4.default.resolve(absolutePath, filePath);
50907
+ const resolved = import_node_path5.default.resolve(absolutePath, filePath);
51773
50908
  if (!allChanges.has(resolved)) {
51774
50909
  allChanges.set(resolved, [{ start: 1, end: 999999 }]);
51775
50910
  }
51776
50911
  };
51777
50912
  try {
51778
- const stagedDiff = (0, import_node_child_process.execSync)("git diff --cached", { cwd: absolutePath, encoding: "utf-8" });
51779
- mergeChanges(parseDiffOutput(stagedDiff, absolutePath));
51780
- const unstagedDiff = (0, import_node_child_process.execSync)("git diff", { cwd: absolutePath, encoding: "utf-8" });
51781
- mergeChanges(parseDiffOutput(unstagedDiff, absolutePath));
50913
+ mergeChanges(parseDiffOutput((0, import_node_child_process.execSync)("git diff --cached", { cwd: absolutePath, encoding: "utf-8" }), absolutePath));
50914
+ mergeChanges(parseDiffOutput((0, import_node_child_process.execSync)("git diff", { cwd: absolutePath, encoding: "utf-8" }), absolutePath));
51782
50915
  const untracked = (0, import_node_child_process.execSync)("git ls-files --others --exclude-standard", { cwd: absolutePath, encoding: "utf-8" });
51783
50916
  for (const file of untracked.split("\n")) {
51784
50917
  if (file.trim()) addFullFile(file.trim());
@@ -51789,8 +50922,7 @@ function getChangedLines(targetPath) {
51789
50922
  if (currentBranch !== baseBranch) {
51790
50923
  const mergeBase = (0, import_node_child_process.execSync)(`git merge-base ${baseBranch} HEAD 2>/dev/null || echo ""`, { cwd: absolutePath, encoding: "utf-8" }).trim();
51791
50924
  if (mergeBase) {
51792
- const branchDiff = (0, import_node_child_process.execSync)(`git diff ${mergeBase}...HEAD`, { cwd: absolutePath, encoding: "utf-8" });
51793
- mergeChanges(parseDiffOutput(branchDiff, absolutePath));
50925
+ mergeChanges(parseDiffOutput((0, import_node_child_process.execSync)(`git diff ${mergeBase}...HEAD`, { cwd: absolutePath, encoding: "utf-8" }), absolutePath));
51794
50926
  }
51795
50927
  }
51796
50928
  } catch {
@@ -51807,50 +50939,35 @@ function isInChangedLines(filePath, blockStart, blockEnd, changes) {
51807
50939
  }
51808
50940
  function showHelp() {
51809
50941
  console.log(`
51810
- dslop - Detect Similar/Duplicate Lines Of Programming
50942
+ dslop - Find duplicate functions and types
51811
50943
 
51812
50944
  Usage:
51813
50945
  dslop [path] [options]
51814
50946
 
51815
- By default, checks your branch changes against the codebase.
51816
- If no changes are found, automatically scans the entire path.
51817
-
51818
- Arguments:
51819
- path Directory to scan (default: current directory)
51820
-
51821
50947
  Options:
51822
50948
  -a, --all Force full codebase scan
51823
50949
  -c, --changes Force changes-only mode (exit if no changes found)
51824
- -m, --min-lines <n> Minimum block size in lines (default: ${DEFAULT_MIN_LINES})
51825
- -s, --similarity <n> Minimum similarity threshold 0-100 (default: ${Math.round(DEFAULT_SIMILARITY * 100)})
51826
- -e, --extensions <s> File extensions to scan (default: ${DEFAULT_EXTENSIONS.join(",")})
51827
- -i, --ignore <s> Patterns to ignore (default: ${DEFAULT_IGNORE_PATTERNS.slice(0, 4).join(",")},...)
51828
- --no-normalize Disable string/number normalization
51829
- --cross-package Only show duplicates across different packages/apps (monorepo mode)
51830
- --json Output as JSON
51831
- -h, --help Show this help message
50950
+ -e, --extensions <s> File extensions (default: ts,tsx,js,jsx)
50951
+ -i, --ignore <s> Patterns to ignore
50952
+ --no-cache Disable caching
50953
+ --cross-package Only cross-package duplicates (monorepos)
50954
+ --json JSON output
50955
+ -h, --help Show help
51832
50956
  -v, --version Show version
51833
50957
 
51834
50958
  Examples:
51835
- dslop Check your PR changes (or full scan if none)
51836
- dslop ./apps/web Scan apps/web (full scan if no changes there)
51837
- dslop -c Check PR changes only, exit if none
51838
- dslop --cross-package Cross-package duplicates
50959
+ dslop Check PR changes (or full scan if none)
50960
+ dslop --all Full codebase scan
50961
+ dslop --cross-package Cross-package duplicates
51839
50962
  `);
51840
50963
  }
51841
- function showVersion() {
51842
- console.log(`dslop v${VERSION}`);
51843
- }
51844
50964
  async function main() {
51845
50965
  const { values, positionals } = (0, import_node_util.parseArgs)({
51846
50966
  args: process.argv.slice(2),
51847
50967
  options: {
51848
- "min-lines": { type: "string", short: "m", default: String(DEFAULT_MIN_LINES) },
51849
- similarity: { type: "string", short: "s", default: String(Math.round(DEFAULT_SIMILARITY * 100)) },
51850
50968
  extensions: { type: "string", short: "e", default: DEFAULT_EXTENSIONS.join(",") },
51851
50969
  ignore: { type: "string", short: "i", default: DEFAULT_IGNORE_PATTERNS.join(",") },
51852
- normalize: { type: "boolean", default: true },
51853
- "no-normalize": { type: "boolean", default: false },
50970
+ "no-cache": { type: "boolean", default: false },
51854
50971
  all: { type: "boolean", short: "a", default: false },
51855
50972
  changes: { type: "boolean", short: "c", default: false },
51856
50973
  "cross-package": { type: "boolean", default: false },
@@ -51865,109 +50982,66 @@ async function main() {
51865
50982
  process.exit(0);
51866
50983
  }
51867
50984
  if (values.version) {
51868
- showVersion();
50985
+ console.log(`dslop v${VERSION}`);
51869
50986
  process.exit(0);
51870
50987
  }
51871
50988
  const targetPath = positionals[0] || ".";
51872
- const minLines = parseInt(values["min-lines"], 10);
51873
- const similarity = parseInt(values.similarity, 10) / 100;
51874
50989
  const extensions = values.extensions.split(",").map((e) => e.trim());
51875
50990
  const ignorePatterns = values.ignore.split(",").map((p) => p.trim());
51876
- const normalize2 = !values["no-normalize"];
50991
+ const useCache = !values["no-cache"];
51877
50992
  const forceAll = values.all;
51878
50993
  const forceChanges = values.changes;
51879
50994
  const crossPackage = values["cross-package"];
51880
50995
  const jsonOutput = values.json;
51881
- const hasExplicitPath = positionals.length > 0;
51882
- if (minLines < 2) {
51883
- console.error("Error: --min-lines must be at least 2");
51884
- process.exit(1);
51885
- }
51886
- if (similarity < 0 || similarity > 1) {
51887
- console.error("Error: --similarity must be between 0 and 100");
51888
- process.exit(1);
51889
- }
51890
- const scanOptions = {
51891
- extensions,
51892
- ignorePatterns,
51893
- minLines,
51894
- normalize: normalize2
51895
- };
50996
+ const scanOptions = { extensions, ignorePatterns };
51896
50997
  let scanAll = forceAll;
51897
50998
  let changedLines = null;
51898
50999
  if (!forceAll) {
51899
51000
  changedLines = getChangedLines(targetPath);
51900
51001
  if (changedLines.size === 0) {
51901
51002
  if (forceChanges) {
51902
- console.log("\nNo changes found on current branch.");
51003
+ console.log("\nNo changes found.");
51903
51004
  process.exit(0);
51904
51005
  }
51905
51006
  scanAll = true;
51906
51007
  if (!jsonOutput) {
51907
51008
  console.log(`
51908
- No changes detected${hasExplicitPath ? ` in ${targetPath}` : ""}, defaulting to full scan...`);
51009
+ No changes detected, running full scan...`);
51909
51010
  }
51910
51011
  }
51911
51012
  }
51912
51013
  if (!jsonOutput) {
51913
51014
  console.log(`
51914
51015
  Scanning ${targetPath}...`);
51915
- if (!scanAll && changedLines && changedLines.size > 0) {
51916
- console.log(` Mode: checking changed lines in ${changedLines.size} files`);
51917
- } else {
51918
- console.log(` Mode: full codebase scan`);
51919
- }
51920
- console.log(` Extensions: ${extensions.join(", ")}`);
51921
- console.log(` Min block size: ${minLines} lines`);
51922
- console.log(` Similarity threshold: ${Math.round(similarity * 100)}%`);
51923
- if (crossPackage) {
51924
- console.log(` Cross-package: enabled`);
51925
- }
51016
+ console.log(` Mode: ${scanAll ? "full scan" : `checking ${changedLines?.size} changed files`}`);
51017
+ if (crossPackage) console.log(` Cross-package: enabled`);
51926
51018
  console.log();
51927
51019
  }
51928
51020
  try {
51929
51021
  const startTime = performance.now();
51930
- const { blocks, declarations, astBlocks, fileCount, totalLines } = await scanDirectory(targetPath, scanOptions, true);
51022
+ const { astBlocks, fileCount, totalLines, cacheStats } = await scanDirectory(targetPath, scanOptions, useCache);
51931
51023
  const scanTime = performance.now() - startTime;
51932
51024
  if (!jsonOutput) {
51933
51025
  console.log(`Scanned ${fileCount} files (${totalLines.toLocaleString()} lines) in ${Math.round(scanTime)}ms`);
51934
- console.log(`Extracted ${blocks.length.toLocaleString()} blocks, ${astBlocks.length.toLocaleString()} functions/classes
51026
+ if (cacheStats && (cacheStats.hits > 0 || cacheStats.misses > 0)) {
51027
+ console.log(`Cache: ${cacheStats.hits} hits, ${cacheStats.misses} misses (${Math.round(cacheStats.hitRate * 100)}% hit rate)`);
51028
+ }
51029
+ console.log(`Found ${astBlocks.length.toLocaleString()} functions/types
51935
51030
  `);
51936
51031
  }
51937
- if (blocks.length === 0 && astBlocks.length === 0) {
51938
- console.log("No code found to analyze.");
51032
+ if (astBlocks.length === 0) {
51033
+ if (jsonOutput) {
51034
+ console.log(JSON.stringify({ summary: { duplicateGroups: 0 }, duplicates: [] }, null, 2));
51035
+ } else {
51036
+ console.log("No code found to analyze.");
51037
+ }
51939
51038
  process.exit(0);
51940
51039
  }
51941
51040
  const detectStart = performance.now();
51942
- let duplicates = findDuplicates(blocks, similarity, targetPath);
51943
- let astDuplicates = findASTDuplicates(astBlocks, similarity);
51944
- let declDuplicates = findDeclarationDuplicates(declarations, similarity);
51041
+ let duplicates = findASTDuplicates(astBlocks, 0.7);
51945
51042
  const detectTime = performance.now() - detectStart;
51946
51043
  if (!scanAll && changedLines) {
51947
- const changedFilePaths = new Set(changedLines.keys());
51948
51044
  duplicates = duplicates.filter((group) => {
51949
- const inChanged = group.matches.filter(
51950
- (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51951
- );
51952
- const notInChanged = group.matches.filter(
51953
- (m) => !isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51954
- );
51955
- if (inChanged.length === 0 || notInChanged.length === 0) return false;
51956
- const inOtherFiles = notInChanged.some((m) => !changedFilePaths.has(m.filePath));
51957
- const inSameFileOutsideChanges = notInChanged.some((m) => changedFilePaths.has(m.filePath));
51958
- if (inOtherFiles && group.matches.length > 10) return false;
51959
- return inOtherFiles || inSameFileOutsideChanges;
51960
- });
51961
- astDuplicates = astDuplicates.filter((group) => {
51962
- const inChanged = group.matches.filter(
51963
- (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51964
- );
51965
- const notInChanged = group.matches.filter(
51966
- (m) => !isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51967
- );
51968
- return inChanged.length > 0 && notInChanged.length > 0;
51969
- });
51970
- declDuplicates = declDuplicates.filter((group) => {
51971
51045
  const inChanged = group.matches.filter(
51972
51046
  (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51973
51047
  );
@@ -51978,52 +51052,30 @@ Scanning ${targetPath}...`);
51978
51052
  });
51979
51053
  }
51980
51054
  if (crossPackage) {
51981
- const filterCrossPackage = (groups) => {
51982
- return groups.filter((group) => {
51983
- const packages = new Set(
51984
- group.matches.map((m) => {
51985
- const match2 = m.filePath.match(/(?:apps|packages|libs)\/([^/]+)/);
51986
- return match2 ? match2[1] : m.filePath.split("/")[0];
51987
- })
51988
- );
51989
- return packages.size > 1;
51990
- });
51991
- };
51992
- duplicates = filterCrossPackage(duplicates);
51993
- astDuplicates = filterCrossPackage(astDuplicates);
51994
- declDuplicates = filterCrossPackage(declDuplicates);
51055
+ duplicates = duplicates.filter((group) => {
51056
+ const packages = new Set(
51057
+ group.matches.map((m) => {
51058
+ const match2 = m.filePath.match(/(?:apps|packages|libs)\/([^/]+)/);
51059
+ return match2 ? match2[1] : m.filePath.split("/")[0];
51060
+ })
51061
+ );
51062
+ return packages.size > 1;
51063
+ });
51995
51064
  }
51996
- const totalGroups = duplicates.length + astDuplicates.length + declDuplicates.length;
51997
51065
  if (!jsonOutput) {
51998
- console.log(`Found ${totalGroups} duplicate groups in ${Math.round(detectTime)}ms`);
51999
- if (astDuplicates.length > 0 || declDuplicates.length > 0) {
52000
- console.log(` (${duplicates.length} blocks, ${astDuplicates.length} AST, ${declDuplicates.length} declarations)
51066
+ console.log(`Found ${duplicates.length} duplicate groups in ${Math.round(detectTime)}ms
52001
51067
  `);
52002
- } else {
52003
- console.log();
52004
- }
52005
51068
  }
52006
- if (totalGroups === 0) {
51069
+ if (duplicates.length === 0) {
52007
51070
  if (jsonOutput) {
52008
- console.log(JSON.stringify({ duplicates: [], ast: [], declarations: [] }, null, 2));
52009
- } else if (!scanAll) {
52010
- console.log("No duplicates in your changes. You're good!");
52011
- } else if (crossPackage) {
52012
- console.log("No cross-package duplicates found!");
51071
+ console.log(JSON.stringify({ summary: { duplicateGroups: 0 }, duplicates: [] }, null, 2));
52013
51072
  } else {
52014
- console.log("No duplicates found!");
51073
+ console.log(crossPackage ? "No cross-package duplicates found!" : "No duplicates found!");
52015
51074
  }
52016
51075
  process.exit(0);
52017
51076
  }
52018
51077
  if (jsonOutput) {
52019
- const compactDuplicates = duplicates.slice(0, 100).map((d) => ({
52020
- lines: d.lineCount,
52021
- occurrences: d.occurrences,
52022
- similarity: Math.round(d.similarity * 100),
52023
- preview: d.matches[0]?.content.split("\n").slice(0, 3).join("\n") || "",
52024
- locations: d.matches.slice(0, 10).map((m) => `${m.filePath.replace(process.cwd() + "/", "")}:${m.startLine}`)
52025
- }));
52026
- const compactAST = astDuplicates.slice(0, 50).map((a) => ({
51078
+ const compactAST = duplicates.slice(0, 50).map((a) => ({
52027
51079
  type: a.type,
52028
51080
  name: a.matches[0]?.name || "unknown",
52029
51081
  occurrences: a.matches.length,
@@ -52035,25 +51087,11 @@ Scanning ${targetPath}...`);
52035
51087
  }))
52036
51088
  }));
52037
51089
  console.log(JSON.stringify({
52038
- summary: {
52039
- duplicateGroups: duplicates.length,
52040
- astGroups: astDuplicates.length,
52041
- declarationGroups: declDuplicates.length
52042
- },
52043
- duplicates: compactDuplicates,
52044
- ast: compactAST
51090
+ summary: { duplicateGroups: duplicates.length },
51091
+ duplicates: compactAST
52045
51092
  }, null, 2));
52046
51093
  } else {
52047
- if (astDuplicates.length > 0) {
52048
- console.log(formatASTDuplicates(astDuplicates, targetPath));
52049
- }
52050
- if (duplicates.length > 0) {
52051
- console.log(formatOutput(duplicates, targetPath));
52052
- console.log(formatStats(duplicates));
52053
- }
52054
- if (declDuplicates.length > 0) {
52055
- console.log(formatDeclarations(declDuplicates, targetPath));
52056
- }
51094
+ console.log(formatASTDuplicates(duplicates, targetPath));
52057
51095
  }
52058
51096
  } catch (error) {
52059
51097
  console.error("Error:", error instanceof Error ? error.message : error);