dslop 1.7.0 → 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.
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,801 +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 SECTION_SEPARATOR = "\u2500".repeat(80);
43620
- var COLORS = {
43621
- reset: "\x1B[0m",
43622
- bold: "\x1B[1m",
43623
- dim: "\x1B[2m",
43624
- red: "\x1B[31m",
43625
- green: "\x1B[32m",
43626
- yellow: "\x1B[33m",
43627
- blue: "\x1B[34m",
43628
- magenta: "\x1B[35m",
43629
- cyan: "\x1B[36m",
43630
- white: "\x1B[37m",
43631
- gray: "\x1B[90m"
43632
- };
43633
- var MAX_FILE_SIZE = 1024 * 1024;
43634
- var MAX_BLOCKS_FOR_SIMILARITY = 1e4;
43635
-
43636
- // src/normalizer.ts
43637
- function normalizeCode(code) {
43638
- let normalized = code;
43639
- normalized = normalized.replace(/"(?:[^"\\]|\\.)*"/g, `"${STRING_PLACEHOLDER}"`);
43640
- normalized = normalized.replace(/'(?:[^'\\]|\\.)*'/g, `'${STRING_PLACEHOLDER}'`);
43641
- normalized = normalized.replace(/`(?:[^`\\]|\\.)*`/g, `\`${TEMPLATE_PLACEHOLDER}\``);
43642
- normalized = normalized.replace(/\b\d+\.?\d*\b/g, NUMBER_PLACEHOLDER);
43643
- normalized = normalized.replace(/#[0-9a-fA-F]{3,8}\b/g, COLOR_PLACEHOLDER);
43644
- normalized = normalized.replace(/[ \t]+/g, " ");
43645
- normalized = normalized.split("\n").map((line) => line.trimEnd()).join("\n");
43646
- normalized = normalized.replace(/\n\s*\n/g, "\n");
43647
- return normalized;
43648
- }
43649
-
43650
- // src/declarations.ts
43651
- function simpleHash(str) {
43652
- let hash = 0;
43653
- for (let i = 0; i < str.length; i++) {
43654
- const char = str.charCodeAt(i);
43655
- hash = (hash << 5) - hash + char;
43656
- hash = hash & hash;
43657
- }
43658
- return hash.toString(36);
43659
- }
43660
- var DECLARATION_PATTERNS = [
43661
- // Type aliases: type X = ... or export type X = ...
43662
- { type: "type", regex: /^(export\s+)?type\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*=/m, nameGroup: 2 },
43663
- // Interfaces: interface X { or export interface X {
43664
- { type: "interface", regex: /^(export\s+)?interface\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*(?:extends\s+[^{]+)?\{/m, nameGroup: 2 },
43665
- // Classes: class X { or export class X {
43666
- { type: "class", regex: /^(export\s+)?(?:abstract\s+)?class\s+([A-Z]\w*)\s*(?:<[^>]*>)?\s*(?:extends\s+\w+)?\s*(?:implements\s+[^{]+)?\{/m, nameGroup: 2 },
43667
- // Enums: enum X { or export enum X {
43668
- { type: "enum", regex: /^(export\s+)?(?:const\s+)?enum\s+([A-Z]\w*)\s*\{/m, nameGroup: 2 },
43669
- // Named functions: function x( or export function x( or export async function x(
43670
- { type: "function", regex: /^(export\s+)?(?:async\s+)?function\s+([a-zA-Z]\w*)\s*(?:<[^>]*>)?\s*\(/m, nameGroup: 2 },
43671
- // Arrow functions: const x = ( or export const x = async (
43672
- { type: "function", regex: /^(export\s+)?const\s+([a-zA-Z]\w*)\s*(?::\s*[^=]+)?\s*=\s*(?:async\s*)?\(/m, nameGroup: 2 },
43673
- // Arrow functions with generics: const x = <T>(
43674
- { type: "function", regex: /^(export\s+)?const\s+([a-zA-Z]\w*)\s*=\s*<[^>]+>\s*\(/m, nameGroup: 2 },
43675
- // Constants (non-function): export const X = "..." or const X = {...}
43676
- { type: "const", regex: /^(export\s+)?const\s+([A-Z][A-Z_0-9]*)\s*(?::\s*[^=]+)?\s*=/m, nameGroup: 2 }
43677
- ];
43678
- function findMatchingBrace(content, startIndex) {
43679
- let depth = 0;
43680
- let inString = false;
43681
- let stringChar = "";
43682
- let inTemplate = false;
43683
- for (let i = startIndex; i < content.length; i++) {
43684
- const char = content[i];
43685
- const prevChar = content[i - 1];
43686
- if (inString) {
43687
- if (char === stringChar && prevChar !== "\\") {
43688
- inString = false;
43689
- }
43690
- continue;
43691
- }
43692
- if (inTemplate) {
43693
- if (char === "`" && prevChar !== "\\") {
43694
- inTemplate = false;
43695
- }
43696
- continue;
43697
- }
43698
- if (char === '"' || char === "'") {
43699
- inString = true;
43700
- stringChar = char;
43701
- continue;
43702
- }
43703
- if (char === "`") {
43704
- inTemplate = true;
43705
- continue;
43706
- }
43707
- if (char === "{") depth++;
43708
- if (char === "}") {
43709
- depth--;
43710
- if (depth === 0) return i;
43711
- }
43712
- }
43713
- return -1;
43714
- }
43715
- function findStatementEnd(content, startIndex) {
43716
- let depth = 0;
43717
- let inString = false;
43718
- let stringChar = "";
43719
- for (let i = startIndex; i < content.length; i++) {
43720
- const char = content[i];
43721
- const prevChar = content[i - 1];
43722
- if (inString) {
43723
- if (char === stringChar && prevChar !== "\\") {
43724
- inString = false;
43725
- }
43726
- continue;
43727
- }
43728
- if (char === '"' || char === "'") {
43729
- inString = true;
43730
- stringChar = char;
43731
- continue;
43732
- }
43733
- if (char === "(" || char === "{" || char === "[") depth++;
43734
- if (char === ")" || char === "}" || char === "]") depth--;
43735
- if (depth === 0 && (char === ";" || char === "\n")) {
43736
- const remaining = content.slice(i + 1).trimStart();
43737
- if (!remaining.startsWith("|") && !remaining.startsWith("&")) {
43738
- return i;
43739
- }
43740
- }
43741
- }
43742
- return content.length - 1;
43743
- }
43744
- var QUICK_CHECK = /^(export\s+)?(type|interface|class|enum|const|function|async\s+function)\s+/;
43745
- function extractDeclarations(content, filePath) {
43746
- const declarations = [];
43747
- const lines = content.split("\n");
43748
- let lineStart = 0;
43749
- for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
43750
- const line = lines[lineIndex];
43751
- if (!line) continue;
43752
- const trimmed = line.trimStart();
43753
- if (!QUICK_CHECK.test(trimmed)) {
43754
- lineStart += line.length + 1;
43755
- continue;
43756
- }
43757
- const remainingContent = content.slice(lineStart);
43758
- for (const pattern of DECLARATION_PATTERNS) {
43759
- const match2 = remainingContent.match(pattern.regex);
43760
- if (match2 && match2.index === 0) {
43761
- const name = match2[pattern.nameGroup];
43762
- if (!name) continue;
43763
- const exported = !!match2[1];
43764
- let endIndex;
43765
- if (pattern.type === "interface" || pattern.type === "class" || pattern.type === "enum") {
43766
- const braceStart = remainingContent.indexOf("{");
43767
- if (braceStart === -1) continue;
43768
- endIndex = findMatchingBrace(remainingContent, braceStart);
43769
- if (endIndex === -1) endIndex = remainingContent.indexOf("\n", braceStart + 1);
43770
- } else if (pattern.type === "type") {
43771
- endIndex = findStatementEnd(remainingContent, match2[0].length);
43772
- } else {
43773
- const hasArrow = remainingContent.slice(match2[0].length, match2[0].length + 100).includes("=>");
43774
- if (hasArrow) {
43775
- const arrowIndex = remainingContent.indexOf("=>", match2[0].length);
43776
- const afterArrow = remainingContent.slice(arrowIndex + 2).trimStart();
43777
- if (afterArrow.startsWith("{")) {
43778
- const braceStart = arrowIndex + 2 + (remainingContent.slice(arrowIndex + 2).length - afterArrow.length);
43779
- endIndex = findMatchingBrace(remainingContent, braceStart);
43780
- } else {
43781
- endIndex = findStatementEnd(remainingContent, arrowIndex + 2);
43782
- }
43783
- } else {
43784
- const braceIndex = remainingContent.indexOf("{", match2[0].length);
43785
- const newlineIndex = remainingContent.indexOf("\n", match2[0].length);
43786
- if (braceIndex !== -1 && (newlineIndex === -1 || braceIndex < newlineIndex)) {
43787
- endIndex = findMatchingBrace(remainingContent, braceIndex);
43788
- } else {
43789
- endIndex = findStatementEnd(remainingContent, match2[0].length);
43790
- }
43791
- }
43792
- }
43793
- if (endIndex === -1) endIndex = remainingContent.indexOf("\n\n");
43794
- if (endIndex === -1) endIndex = Math.min(remainingContent.length - 1, 500);
43795
- const declarationContent = remainingContent.slice(0, endIndex + 1).trim();
43796
- const endLineIndex = lineIndex + declarationContent.split("\n").length - 1;
43797
- const normalized = normalizeCode(declarationContent);
43798
- declarations.push({
43799
- type: pattern.type,
43800
- name,
43801
- content: declarationContent,
43802
- normalized,
43803
- hash: simpleHash(normalized),
43804
- filePath,
43805
- startLine: lineIndex + 1,
43806
- endLine: endLineIndex + 1,
43807
- exported
43808
- });
43809
- break;
43810
- }
43811
- }
43812
- lineStart += line.length + 1;
43813
- }
43814
- return declarations;
43815
- }
43816
- function calculateNameSimilarity(a, b) {
43817
- if (a === b) return 1;
43818
- const aLower = a.toLowerCase();
43819
- const bLower = b.toLowerCase();
43820
- if (aLower === bLower) return 0.95;
43821
- if (aLower.includes(bLower) || bLower.includes(aLower)) return 0.8;
43822
- const aWords = splitCamelCase(a);
43823
- const bWords = splitCamelCase(b);
43824
- const aSet = new Set(aWords.map((w) => w.toLowerCase()));
43825
- const bSet = new Set(bWords.map((w) => w.toLowerCase()));
43826
- let intersection = 0;
43827
- for (const word of aSet) {
43828
- if (bSet.has(word)) intersection++;
43829
- }
43830
- const union = aSet.size + bSet.size - intersection;
43831
- const wordSimilarity = union > 0 ? intersection / union : 0;
43832
- if (wordSimilarity > 0.5) return wordSimilarity * 0.9;
43833
- const distance = levenshteinDistance(aLower, bLower);
43834
- const maxLen = Math.max(aLower.length, bLower.length);
43835
- return Math.max(0, 1 - distance / maxLen) * 0.7;
43836
- }
43837
- function splitCamelCase(str) {
43838
- 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);
43839
- }
43840
- function levenshteinDistance(a, b) {
43841
- if (a.length === 0) return b.length;
43842
- if (b.length === 0) return a.length;
43843
- const matrix = Array.from(
43844
- { length: b.length + 1 },
43845
- (_, i) => Array.from({ length: a.length + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
43846
- );
43847
- for (let i = 1; i <= b.length; i++) {
43848
- for (let j = 1; j <= a.length; j++) {
43849
- const prevRow = matrix[i - 1];
43850
- const currRow = matrix[i];
43851
- if (!prevRow || !currRow) continue;
43852
- if (b[i - 1] === a[j - 1]) {
43853
- currRow[j] = prevRow[j - 1] ?? 0;
43854
- } else {
43855
- currRow[j] = Math.min(
43856
- (prevRow[j - 1] ?? 0) + 1,
43857
- (currRow[j - 1] ?? 0) + 1,
43858
- (prevRow[j] ?? 0) + 1
43859
- );
43860
- }
43861
- }
43862
- }
43863
- return matrix[b.length]?.[a.length] ?? Math.max(a.length, b.length);
43864
- }
43865
-
43866
- // src/detector.ts
43867
- function calculateSimilarityFast(a, b) {
43868
- if (a === b) return 1;
43869
- if (a.length === 0 || b.length === 0) return 0;
43870
- const linesA = a.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
43871
- const linesB = b.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
43872
- if (linesA.length === 0 || linesB.length === 0) return 0;
43873
- const lenRatio = Math.min(linesA.length, linesB.length) / Math.max(linesA.length, linesB.length);
43874
- if (lenRatio < 0.5) return lenRatio * 0.5;
43875
- const setA = new Set(linesA);
43876
- const setB = new Set(linesB);
43877
- let intersection = 0;
43878
- for (const line of setA) {
43879
- if (setB.has(line)) {
43880
- intersection++;
43881
- }
43882
- }
43883
- const union = setA.size + setB.size - intersection;
43884
- return union > 0 ? intersection / union : 0;
43885
- }
43886
- function getFingerprint(normalized) {
43887
- const lines = normalized.split("\n");
43888
- if (lines.length < 3) return normalized.slice(0, 100);
43889
- const first = lines.slice(0, 2).join("");
43890
- const mid = lines[Math.floor(lines.length / 2)] ?? "";
43891
- const last = lines.slice(-2).join("");
43892
- return (first + mid + last).slice(0, 200);
43893
- }
43894
- var UnionFind = class {
43895
- parent = /* @__PURE__ */ new Map();
43896
- rank = /* @__PURE__ */ new Map();
43897
- find(x) {
43898
- if (!this.parent.has(x)) {
43899
- this.parent.set(x, x);
43900
- this.rank.set(x, 0);
43901
- }
43902
- const parentVal = this.parent.get(x);
43903
- if (parentVal !== void 0 && parentVal !== x) {
43904
- const root = this.find(parentVal);
43905
- this.parent.set(x, root);
43906
- return root;
43907
- }
43908
- return this.parent.get(x) ?? x;
43909
- }
43910
- union(x, y) {
43911
- const rootX = this.find(x);
43912
- const rootY = this.find(y);
43913
- if (rootX === rootY) return;
43914
- const rankX = this.rank.get(rootX) ?? 0;
43915
- const rankY = this.rank.get(rootY) ?? 0;
43916
- if (rankX < rankY) {
43917
- this.parent.set(rootX, rootY);
43918
- } else if (rankX > rankY) {
43919
- this.parent.set(rootY, rootX);
43920
- } else {
43921
- this.parent.set(rootY, rootX);
43922
- this.rank.set(rootX, rankX + 1);
43923
- }
43924
- }
43925
- };
43926
- function findDuplicates(blocks, minSimilarity, basePath) {
43927
- const hashGroups = /* @__PURE__ */ new Map();
43928
- for (const block of blocks) {
43929
- const existing = hashGroups.get(block.hash) ?? [];
43930
- existing.push(block);
43931
- hashGroups.set(block.hash, existing);
43932
- }
43933
- const exactDuplicates = [];
43934
- let groupId = 0;
43935
- for (const [, groupBlocks] of hashGroups) {
43936
- const uniqueLocations = filterOverlappingBlocks(groupBlocks);
43937
- if (uniqueLocations.length >= MIN_OCCURRENCES) {
43938
- exactDuplicates.push({
43939
- id: groupId++,
43940
- similarity: 1,
43941
- lineCount: uniqueLocations[0]?.lineCount ?? 0,
43942
- occurrences: uniqueLocations.length,
43943
- matches: uniqueLocations.map((b) => ({
43944
- filePath: b.filePath,
43945
- startLine: b.startLine,
43946
- endLine: b.endLine,
43947
- content: b.content
43948
- })),
43949
- pattern: uniqueLocations[0]?.normalized ?? ""
43950
- });
43951
- }
43952
- }
43953
- const similarDuplicates = [];
43954
- const uniqueHashCount = hashGroups.size;
43955
- if (minSimilarity < 1 && uniqueHashCount <= MAX_BLOCKS_FOR_SIMILARITY) {
43956
- const uniqueBlocks = [];
43957
- const seenHashes = /* @__PURE__ */ new Set();
43958
- for (const block of blocks) {
43959
- if (!seenHashes.has(block.hash)) {
43960
- seenHashes.add(block.hash);
43961
- uniqueBlocks.push(block);
43962
- }
43963
- }
43964
- const sizeGroups = /* @__PURE__ */ new Map();
43965
- for (const block of uniqueBlocks) {
43966
- const sizeKey = Math.floor(block.lineCount / SIZE_BUCKET_DIVISOR);
43967
- const existing = sizeGroups.get(sizeKey) ?? [];
43968
- existing.push(block);
43969
- sizeGroups.set(sizeKey, existing);
43970
- }
43971
- const fingerprints = /* @__PURE__ */ new Map();
43972
- for (const block of uniqueBlocks) {
43973
- fingerprints.set(block, getFingerprint(block.normalized));
43974
- }
43975
- const uf = new UnionFind();
43976
- const blockIndexMap = /* @__PURE__ */ new Map();
43977
- for (let i = 0; i < uniqueBlocks.length; i++) {
43978
- const block = uniqueBlocks[i];
43979
- if (block) blockIndexMap.set(block, i);
43980
- }
43981
- for (const [sizeKey, sizeGroup] of sizeGroups) {
43982
- const adjacentGroups = [
43983
- sizeGroups.get(sizeKey - 1) ?? [],
43984
- sizeGroup,
43985
- sizeGroups.get(sizeKey + 1) ?? []
43986
- ].flat();
43987
- const maxComparisons = 1e3;
43988
- let comparisons = 0;
43989
- for (let i = 0; i < sizeGroup.length && comparisons < maxComparisons; i++) {
43990
- const blockA = sizeGroup[i];
43991
- if (!blockA) continue;
43992
- const fpA = fingerprints.get(blockA) ?? "";
43993
- for (let j = 0; j < adjacentGroups.length && comparisons < maxComparisons; j++) {
43994
- const blockB = adjacentGroups[j];
43995
- if (!blockB) continue;
43996
- if (blockA === blockB) continue;
43997
- if (blockA.hash === blockB.hash) continue;
43998
- const fpB = fingerprints.get(blockB) ?? "";
43999
- const fpSimilarity = calculateSimilarityFast(fpA, fpB);
44000
- if (fpSimilarity < minSimilarity * 0.5) continue;
44001
- comparisons++;
44002
- const similarity = calculateSimilarityFast(blockA.normalized, blockB.normalized);
44003
- if (similarity >= minSimilarity) {
44004
- const idxA = blockIndexMap.get(blockA);
44005
- const idxB = blockIndexMap.get(blockB);
44006
- if (idxA !== void 0 && idxB !== void 0) {
44007
- uf.union(idxA, idxB);
44008
- }
44009
- }
44010
- }
44011
- }
44012
- }
44013
- const groupMap = /* @__PURE__ */ new Map();
44014
- for (const block of uniqueBlocks) {
44015
- const idx = blockIndexMap.get(block);
44016
- if (idx === void 0) continue;
44017
- const root = uf.find(idx);
44018
- const existing = groupMap.get(root) ?? [];
44019
- existing.push(block);
44020
- groupMap.set(root, existing);
44021
- }
44022
- for (const [, groupBlocks] of groupMap) {
44023
- if (groupBlocks.length < MIN_OCCURRENCES) continue;
44024
- const expandedBlocks = [];
44025
- for (const block of groupBlocks) {
44026
- const matching = hashGroups.get(block.hash) ?? [];
44027
- expandedBlocks.push(...matching);
44028
- }
44029
- const uniqueLocations = filterOverlappingBlocks(expandedBlocks);
44030
- if (uniqueLocations.length >= MIN_OCCURRENCES) {
44031
- let totalSim = 0;
44032
- let comparisons = 0;
44033
- const sampleSize = Math.min(groupBlocks.length, MAX_SIMILARITY_SAMPLES);
44034
- for (let i = 0; i < sampleSize; i++) {
44035
- for (let j = i + 1; j < sampleSize; j++) {
44036
- const blockI = groupBlocks[i];
44037
- const blockJ = groupBlocks[j];
44038
- if (blockI && blockJ) {
44039
- totalSim += calculateSimilarityFast(blockI.normalized, blockJ.normalized);
44040
- comparisons++;
44041
- }
44042
- }
44043
- }
44044
- const avgSimilarity = comparisons > 0 ? totalSim / comparisons : 1;
44045
- similarDuplicates.push({
44046
- id: groupId++,
44047
- similarity: avgSimilarity,
44048
- lineCount: Math.round(
44049
- uniqueLocations.reduce((sum, b) => sum + b.lineCount, 0) / uniqueLocations.length
44050
- ),
44051
- occurrences: uniqueLocations.length,
44052
- matches: uniqueLocations.map((b) => ({
44053
- filePath: b.filePath,
44054
- startLine: b.startLine,
44055
- endLine: b.endLine,
44056
- content: b.content
44057
- })),
44058
- pattern: groupBlocks[0]?.normalized ?? ""
44059
- });
44060
- }
44061
- }
44062
- }
44063
- const filteredSimilar = similarDuplicates.filter((g) => g.similarity >= minSimilarity);
44064
- const allDuplicates = [...exactDuplicates, ...filteredSimilar];
44065
- allDuplicates.sort((a, b) => {
44066
- if (b.occurrences !== a.occurrences) {
44067
- return b.occurrences - a.occurrences;
44068
- }
44069
- return b.lineCount - a.lineCount;
44070
- });
44071
- const dedupedGroups = deduplicateGroups(allDuplicates);
44072
- const crossFileGroups = dedupedGroups.filter((group) => {
44073
- const uniqueFiles = new Set(group.matches.map((m) => m.filePath));
44074
- return uniqueFiles.size > 1;
44075
- });
44076
- return crossFileGroups.map((group) => ({
44077
- ...group,
44078
- suggestion: generateRefactoringSuggestion(group, basePath)
44079
- }));
44080
- }
44081
- function filterOverlappingBlocks(blocks) {
44082
- const byFile = /* @__PURE__ */ new Map();
44083
- for (const block of blocks) {
44084
- const existing = byFile.get(block.filePath) ?? [];
44085
- existing.push(block);
44086
- byFile.set(block.filePath, existing);
44087
- }
44088
- const result = [];
44089
- for (const [, fileBlocks] of byFile) {
44090
- fileBlocks.sort((a, b) => a.startLine - b.startLine);
44091
- const kept = [];
44092
- for (const block of fileBlocks) {
44093
- const overlaps = kept.some(
44094
- (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
44095
- );
44096
- if (!overlaps) {
44097
- kept.push(block);
44098
- }
44099
- }
44100
- result.push(...kept);
44101
- }
44102
- return result;
44103
- }
44104
- function extractPackageInfo(filePath) {
44105
- const match2 = filePath.match(/(apps|packages|libs)\/([^/]+)\/(.+)/);
44106
- if (match2) {
44107
- return {
44108
- type: match2[1],
44109
- name: match2[2] ?? "unknown",
44110
- subPath: match2[3] ?? ""
44111
- };
44112
- }
44113
- const parts = filePath.split("/");
44114
- return {
44115
- type: "unknown",
44116
- name: parts[0] ?? "unknown",
44117
- subPath: parts.slice(1).join("/")
44118
- };
44119
- }
44120
- function inferSuggestedName(_pattern, matches) {
44121
- const firstMatch = matches[0];
44122
- if (!firstMatch) return void 0;
44123
- const content = firstMatch.content;
44124
- const patterns = [
44125
- // Schema definitions (Zod, etc)
44126
- { regex: /(?:const|export const)\s+([A-Z]\w*Schema)\s*=/, minLength: 6 },
44127
- // Type/interface definitions
44128
- { regex: /(?:export\s+)?interface\s+([A-Z]\w+)/, minLength: 3 },
44129
- { regex: /(?:export\s+)?type\s+([A-Z]\w+)\s*=/, minLength: 3 },
44130
- // Class definitions
44131
- { regex: /(?:export\s+)?class\s+([A-Z]\w+)/, minLength: 3 },
44132
- // Function definitions (exported or async)
44133
- { regex: /(?:export\s+)?(?:async\s+)?function\s+(\w{3,})\s*[(<]/, minLength: 3 },
44134
- // React component definitions
44135
- { regex: /(?:export\s+)?(?:const|function)\s+([A-Z]\w+)\s*[=:].*(?:React|FC|Component|=>)/, minLength: 3 },
44136
- // Named exports with PascalCase (likely important)
44137
- { regex: /(?:export\s+)?const\s+([A-Z]\w{2,})\s*=/, minLength: 3 },
44138
- // Arrow function assignments (camelCase, min 4 chars)
44139
- { regex: /(?:export\s+)?const\s+([a-z][a-zA-Z]{3,})\s*=\s*(?:async\s*)?\(/, minLength: 4 }
44140
- ];
44141
- for (const { regex, minLength } of patterns) {
44142
- const match2 = content.match(regex);
44143
- if (match2?.[1] && match2[1].length >= minLength) {
44144
- const skipNames = /* @__PURE__ */ new Set(["result", "data", "error", "response", "value", "item", "index", "key", "match", "pool", "client", "db"]);
44145
- if (!skipNames.has(match2[1].toLowerCase())) {
44146
- return match2[1];
44147
- }
44148
- }
44149
- }
44150
- const fileNames = matches.map((m) => {
44151
- const parts = m.filePath.split("/");
44152
- const fileName = parts[parts.length - 1] ?? "";
44153
- return fileName.replace(/\.(ts|tsx|js|jsx)$/, "");
44154
- });
44155
- const uniqueNames = [...new Set(fileNames)];
44156
- if (uniqueNames.length === 1 && uniqueNames[0] && uniqueNames[0].length >= 3) {
44157
- const name = uniqueNames[0];
44158
- if (name.includes("-") || name.includes("_")) {
44159
- return name.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
44160
- }
44161
- return name;
44162
- }
44163
- return void 0;
44164
- }
44165
- function generateRefactoringSuggestion(group, _basePath) {
44166
- const matches = group.matches;
44167
- const packageInfos = matches.map((m) => extractPackageInfo(m.filePath));
44168
- const uniquePackages = /* @__PURE__ */ new Map();
44169
- for (const info of packageInfos) {
44170
- const key = `${info.type}/${info.name}`;
44171
- if (!uniquePackages.has(key)) {
44172
- uniquePackages.set(key, info);
44173
- }
44174
- }
44175
- const packageList = Array.from(uniquePackages.values());
44176
- const suggestedName = inferSuggestedName(group.pattern, matches);
44177
- if (packageList.length === 1 && packageList[0]) {
44178
- const pkg = packageList[0];
44179
- const subPaths = packageInfos.map((p) => p.subPath);
44180
- const commonPrefix = findCommonPrefix(subPaths);
44181
- if (pkg.type === "app") {
44182
- return {
44183
- targetLocation: `${pkg.type}s/${pkg.name}/lib/shared/${commonPrefix || "utils"}`,
44184
- reason: `All ${matches.length} occurrences are within ${pkg.name}`,
44185
- confidence: "high",
44186
- suggestedName
44187
- };
44188
- } else {
44189
- return {
44190
- targetLocation: `${pkg.type}/${pkg.name}/src/shared`,
44191
- reason: `All ${matches.length} occurrences are within ${pkg.name}`,
44192
- confidence: "high",
44193
- suggestedName
44194
- };
44195
- }
44196
- }
44197
- const hasOnlyApps = packageList.every((p) => p.type === "app");
44198
- if (hasOnlyApps) {
44199
- const appNames = packageList.map((p) => p.name);
44200
- return {
44201
- targetLocation: "packages/shared/src",
44202
- reason: `Duplicated across ${appNames.length} apps: ${appNames.join(", ")}`,
44203
- confidence: "high",
44204
- suggestedName
44205
- };
44206
- }
44207
- const packages = packageList.filter((p) => p.type === "package");
44208
- const apps = packageList.filter((p) => p.type === "app");
44209
- if (packages.length > 0) {
44210
- const sharedPackage = packages.find(
44211
- (p) => p.name === "shared" || p.name === "common" || p.name === "utils"
44212
- ) ?? packages[0];
44213
- if (!sharedPackage) return { targetLocation: "packages/shared/src", reason: "Duplicated across packages", confidence: "low", suggestedName };
44214
- return {
44215
- targetLocation: `packages/${sharedPackage.name}/src`,
44216
- reason: `Already exists in ${sharedPackage.name}, also duplicated in ${apps.map((a) => a.name).join(", ")}`,
44217
- confidence: "medium",
44218
- suggestedName
44219
- };
44220
- }
44221
- const libs = packageList.filter((p) => p.type === "lib");
44222
- if (libs.length > 0) {
44223
- return {
44224
- targetLocation: `libs/shared/src`,
44225
- reason: `Duplicated across ${libs.length} libraries`,
44226
- confidence: "medium",
44227
- suggestedName
44228
- };
44229
- }
44230
- return {
44231
- targetLocation: "packages/shared/src",
44232
- reason: `Duplicated across ${packageList.length} locations`,
44233
- confidence: "low",
44234
- suggestedName
44235
- };
44236
- }
44237
- function findCommonPrefix(paths) {
44238
- if (paths.length === 0) return "";
44239
- if (paths.length === 1) return paths[0]?.split("/")[0] ?? "";
44240
- const splitPaths = paths.map((p) => p.split("/"));
44241
- const minLength = Math.min(...splitPaths.map((p) => p.length));
44242
- const commonParts = [];
44243
- for (let i = 0; i < minLength - 1; i++) {
44244
- const part = splitPaths[0]?.[i];
44245
- if (part && splitPaths.every((p) => p[i] === part)) {
44246
- commonParts.push(part);
44247
- } else {
44248
- break;
44249
- }
44250
- }
44251
- return commonParts.join("/");
44252
- }
44253
- function rangesOverlap(aStart, aEnd, bStart, bEnd) {
44254
- return aStart <= bEnd && bStart <= aEnd;
44255
- }
44256
- function deduplicateGroups(groups) {
44257
- const result = [];
44258
- for (const group of groups) {
44259
- let coveredCount = 0;
44260
- for (const match2 of group.matches) {
44261
- let isCovered = false;
44262
- for (const existing of result) {
44263
- for (const existingMatch of existing.matches) {
44264
- if (match2.filePath === existingMatch.filePath && rangesOverlap(
44265
- match2.startLine,
44266
- match2.endLine,
44267
- existingMatch.startLine,
44268
- existingMatch.endLine
44269
- )) {
44270
- isCovered = true;
44271
- break;
44272
- }
44273
- }
44274
- if (isCovered) break;
44275
- }
44276
- if (isCovered) coveredCount++;
44277
- }
44278
- if (coveredCount < group.matches.length * GROUP_OVERLAP_THRESHOLD) {
44279
- result.push(group);
44280
- }
44281
- }
44282
- return result;
44283
- }
44284
- function findDeclarationDuplicates(declarations, minSimilarity) {
44285
- const duplicates = [];
44286
- let groupId = 0;
44287
- const byType = /* @__PURE__ */ new Map();
44288
- for (const decl of declarations) {
44289
- const existing = byType.get(decl.type) ?? [];
44290
- existing.push(decl);
44291
- byType.set(decl.type, existing);
44292
- }
44293
- for (const [type, typeDecls] of byType) {
44294
- const processed = /* @__PURE__ */ new Set();
44295
- for (let i = 0; i < typeDecls.length; i++) {
44296
- if (processed.has(i)) continue;
44297
- const declA = typeDecls[i];
44298
- if (!declA) continue;
44299
- const matches = [{
44300
- name: declA.name,
44301
- filePath: declA.filePath,
44302
- startLine: declA.startLine,
44303
- endLine: declA.endLine,
44304
- content: declA.content,
44305
- exported: declA.exported
44306
- }];
44307
- let bestNameSim = 0;
44308
- let bestContentSim = 0;
44309
- for (let j = i + 1; j < typeDecls.length; j++) {
44310
- if (processed.has(j)) continue;
44311
- const declB = typeDecls[j];
44312
- if (!declB) continue;
44313
- if (declA.filePath === declB.filePath && Math.abs(declA.startLine - declB.startLine) < 5) continue;
44314
- const nameSim = calculateNameSimilarity(declA.name, declB.name);
44315
- const contentSim = calculateSimilarityFast(declA.normalized, declB.normalized);
44316
- const combined = Math.max(
44317
- nameSim * 0.4 + contentSim * 0.6,
44318
- nameSim >= 0.9 ? nameSim : 0,
44319
- contentSim >= 0.9 ? contentSim : 0
44320
- );
44321
- if (combined >= minSimilarity || nameSim >= 0.8 && contentSim >= 0.5) {
44322
- processed.add(j);
44323
- matches.push({
44324
- name: declB.name,
44325
- filePath: declB.filePath,
44326
- startLine: declB.startLine,
44327
- endLine: declB.endLine,
44328
- content: declB.content,
44329
- exported: declB.exported
44330
- });
44331
- bestNameSim = Math.max(bestNameSim, nameSim);
44332
- bestContentSim = Math.max(bestContentSim, contentSim);
44333
- }
44334
- }
44335
- if (matches.length >= 2) {
44336
- processed.add(i);
44337
- const exported = matches.find((m) => m.exported);
44338
- const suggestion = exported ? `Import \`${exported.name}\` from \`${exported.filePath.replace(/.*\/(src|lib)\//, "")}\`` : `Consider extracting \`${declA.name}\` to a shared location`;
44339
- duplicates.push({
44340
- id: groupId++,
44341
- type,
44342
- similarity: Math.max(bestNameSim, bestContentSim),
44343
- nameSimilarity: bestNameSim,
44344
- contentSimilarity: bestContentSim,
44345
- matches,
44346
- suggestion
44347
- });
44348
- }
44349
- }
44350
- }
44351
- duplicates.sort((a, b) => {
44352
- const scoreA = a.matches.length * a.similarity;
44353
- const scoreB = b.matches.length * b.similarity;
44354
- return scoreB - scoreA;
44355
- });
44356
- return duplicates;
44357
- }
44358
-
44359
43573
  // src/ast.ts
44360
43574
  var import_parser = __toESM(require_lib(), 1);
44361
43575
  var import_traverse = __toESM(require_lib8(), 1);
44362
43576
  var t = __toESM(require_lib4(), 1);
44363
43577
  var traverse = import_traverse.default.default || import_traverse.default;
44364
- function simpleHash2(str) {
43578
+ function simpleHash(str) {
44365
43579
  let hash = 0;
44366
43580
  for (let i = 0; i < str.length; i++) {
44367
43581
  hash = (hash << 5) - hash + str.charCodeAt(i);
@@ -44586,8 +43800,8 @@ function extractASTBlocks(content, filePath) {
44586
43800
  errorRecovery: true
44587
43801
  });
44588
43802
  traverse(ast, {
44589
- FunctionDeclaration(path5) {
44590
- const node = path5.node;
43803
+ FunctionDeclaration(path6) {
43804
+ const node = path6.node;
44591
43805
  if (!node.id || !node.loc || node.start === null || node.end === null) return;
44592
43806
  const idMap = /* @__PURE__ */ new Map();
44593
43807
  const counter = { val: 0 };
@@ -44597,15 +43811,15 @@ function extractASTBlocks(content, filePath) {
44597
43811
  name: node.id.name,
44598
43812
  content: content.slice(node.start, node.end),
44599
43813
  normalized,
44600
- hash: simpleHash2(normalized),
43814
+ hash: simpleHash(normalized),
44601
43815
  filePath,
44602
43816
  startLine: node.loc.start.line,
44603
43817
  endLine: node.loc.end.line,
44604
- exported: t.isExportNamedDeclaration(path5.parent) || t.isExportDefaultDeclaration(path5.parent)
43818
+ exported: t.isExportNamedDeclaration(path6.parent) || t.isExportDefaultDeclaration(path6.parent)
44605
43819
  });
44606
43820
  },
44607
- VariableDeclaration(path5) {
44608
- const node = path5.node;
43821
+ VariableDeclaration(path6) {
43822
+ const node = path6.node;
44609
43823
  for (const decl of node.declarations) {
44610
43824
  if (!t.isIdentifier(decl.id) || !decl.init || !decl.loc) continue;
44611
43825
  if (decl.start === null || decl.end === null) continue;
@@ -44618,16 +43832,16 @@ function extractASTBlocks(content, filePath) {
44618
43832
  name: decl.id.name,
44619
43833
  content: content.slice(decl.start, decl.end),
44620
43834
  normalized,
44621
- hash: simpleHash2(normalized),
43835
+ hash: simpleHash(normalized),
44622
43836
  filePath,
44623
43837
  startLine: decl.loc.start.line,
44624
43838
  endLine: decl.loc.end.line,
44625
- exported: t.isExportNamedDeclaration(path5.parent)
43839
+ exported: t.isExportNamedDeclaration(path6.parent)
44626
43840
  });
44627
43841
  }
44628
43842
  },
44629
- ClassDeclaration(path5) {
44630
- const node = path5.node;
43843
+ ClassDeclaration(path6) {
43844
+ const node = path6.node;
44631
43845
  if (!node.id || !node.loc || node.start === null || node.end === null) return;
44632
43846
  const idMap = /* @__PURE__ */ new Map();
44633
43847
  const counter = { val: 0 };
@@ -44637,15 +43851,15 @@ function extractASTBlocks(content, filePath) {
44637
43851
  name: node.id.name,
44638
43852
  content: content.slice(node.start, node.end),
44639
43853
  normalized,
44640
- hash: simpleHash2(normalized),
43854
+ hash: simpleHash(normalized),
44641
43855
  filePath,
44642
43856
  startLine: node.loc.start.line,
44643
43857
  endLine: node.loc.end.line,
44644
- exported: t.isExportNamedDeclaration(path5.parent) || t.isExportDefaultDeclaration(path5.parent)
43858
+ exported: t.isExportNamedDeclaration(path6.parent) || t.isExportDefaultDeclaration(path6.parent)
44645
43859
  });
44646
43860
  },
44647
- TSTypeAliasDeclaration(path5) {
44648
- const node = path5.node;
43861
+ TSTypeAliasDeclaration(path6) {
43862
+ const node = path6.node;
44649
43863
  if (!node.loc || node.start === null || node.end === null) return;
44650
43864
  const nodeContent = content.slice(node.start, node.end);
44651
43865
  blocks.push({
@@ -44653,15 +43867,15 @@ function extractASTBlocks(content, filePath) {
44653
43867
  name: node.id.name,
44654
43868
  content: nodeContent,
44655
43869
  normalized: nodeContent.replace(/\s+/g, " "),
44656
- hash: simpleHash2(nodeContent.replace(/\s+/g, " ")),
43870
+ hash: simpleHash(nodeContent.replace(/\s+/g, " ")),
44657
43871
  filePath,
44658
43872
  startLine: node.loc.start.line,
44659
43873
  endLine: node.loc.end.line,
44660
- exported: t.isExportNamedDeclaration(path5.parent)
43874
+ exported: t.isExportNamedDeclaration(path6.parent)
44661
43875
  });
44662
43876
  },
44663
- TSInterfaceDeclaration(path5) {
44664
- const node = path5.node;
43877
+ TSInterfaceDeclaration(path6) {
43878
+ const node = path6.node;
44665
43879
  if (!node.loc || node.start === null || node.end === null) return;
44666
43880
  const nodeContent = content.slice(node.start, node.end);
44667
43881
  blocks.push({
@@ -44669,11 +43883,11 @@ function extractASTBlocks(content, filePath) {
44669
43883
  name: node.id.name,
44670
43884
  content: nodeContent,
44671
43885
  normalized: nodeContent.replace(/\s+/g, " "),
44672
- hash: simpleHash2(nodeContent.replace(/\s+/g, " ")),
43886
+ hash: simpleHash(nodeContent.replace(/\s+/g, " ")),
44673
43887
  filePath,
44674
43888
  startLine: node.loc.start.line,
44675
43889
  endLine: node.loc.end.line,
44676
- exported: t.isExportNamedDeclaration(path5.parent)
43890
+ exported: t.isExportNamedDeclaration(path6.parent)
44677
43891
  });
44678
43892
  }
44679
43893
  });
@@ -44724,17 +43938,28 @@ function findASTDuplicates(blocks, _minSimilarity) {
44724
43938
 
44725
43939
  // src/formatter.ts
44726
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
+ };
44727
43954
  var { reset, bold, dim, red, green, yellow, cyan, magenta, gray } = COLORS;
44728
43955
  function truncatePath(filePath, basePath) {
44729
43956
  const absoluteBase = import_node_path.default.resolve(basePath);
44730
43957
  let relativePath = filePath;
44731
43958
  if (filePath.startsWith(absoluteBase)) {
44732
43959
  relativePath = filePath.slice(absoluteBase.length);
44733
- if (relativePath.startsWith("/") || relativePath.startsWith("\\")) {
44734
- relativePath = relativePath.slice(1);
44735
- }
43960
+ if (relativePath.startsWith("/")) relativePath = relativePath.slice(1);
44736
43961
  }
44737
- if (relativePath.length > MAX_PATH_DISPLAY_LENGTH) {
43962
+ if (relativePath.length > MAX_PATH_LENGTH) {
44738
43963
  const parts = relativePath.split(import_node_path.default.sep);
44739
43964
  if (parts.length > 3) {
44740
43965
  relativePath = `${parts[0]}/.../${parts.slice(-2).join("/")}`;
@@ -44742,7 +43967,7 @@ function truncatePath(filePath, basePath) {
44742
43967
  }
44743
43968
  return relativePath;
44744
43969
  }
44745
- var AST_TYPE_LABELS = {
43970
+ var TYPE_LABELS = {
44746
43971
  function: "Function",
44747
43972
  arrow: "Arrow Function",
44748
43973
  class: "Class",
@@ -44752,17 +43977,16 @@ var AST_TYPE_LABELS = {
44752
43977
  function formatASTDuplicates(groups, basePath) {
44753
43978
  if (groups.length === 0) return "";
44754
43979
  const lines = [];
43980
+ lines.push(SEPARATOR);
43981
+ lines.push(`${bold}DUPLICATE FUNCTIONS/TYPES${reset}`);
43982
+ lines.push(SEPARATOR);
44755
43983
  lines.push("");
44756
- lines.push(SECTION_SEPARATOR);
44757
- lines.push(`${bold}DUPLICATE FUNCTIONS (AST-based)${reset}`);
44758
- lines.push(SECTION_SEPARATOR);
44759
- lines.push("");
44760
- lines.push(`${dim}These functions have identical structure (ignoring variable names)${reset}`);
43984
+ lines.push(`${dim}These have identical structure (ignoring variable names)${reset}`);
44761
43985
  lines.push("");
44762
43986
  for (let i = 0; i < Math.min(groups.length, 20); i++) {
44763
43987
  const group = groups[i];
44764
43988
  if (!group) continue;
44765
- const typeLabel = AST_TYPE_LABELS[group.type] || group.type;
43989
+ const typeLabel = TYPE_LABELS[group.type] || group.type;
44766
43990
  lines.push(`${bold}${typeLabel} ${i + 1}${reset} \u2502 ${red}${bold}IDENTICAL${reset} \u2502 ${group.matches.length} occurrences`);
44767
43991
  lines.push("");
44768
43992
  for (const match2 of group.matches.slice(0, 5)) {
@@ -44785,21 +44009,18 @@ function formatASTDuplicates(groups, basePath) {
44785
44009
  lines.push("");
44786
44010
  }
44787
44011
  if (groups.length > 20) {
44788
- lines.push(`${dim}... and ${groups.length - 20} more duplicate functions${reset}`);
44012
+ lines.push(`${dim}... and ${groups.length - 20} more${reset}`);
44789
44013
  lines.push("");
44790
44014
  }
44791
- lines.push(SECTION_SEPARATOR);
44792
- const totalDups = groups.reduce((sum, g) => sum + g.matches.length, 0);
44793
- lines.push(`${bold}AST Summary${reset}`);
44794
- lines.push(` Duplicate groups: ${bold}${groups.length}${reset}`);
44795
- lines.push(` Total occurrences: ${bold}${totalDups}${reset}`);
44796
- 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);
44797
44018
  return lines.join("\n");
44798
44019
  }
44799
44020
 
44800
44021
  // src/scanner.ts
44801
- var import_promises2 = require("node:fs/promises");
44802
- 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);
44803
44024
 
44804
44025
  // node_modules/@isaacs/balanced-match/dist/esm/index.js
44805
44026
  var balanced = (a, b, str) => {
@@ -48930,12 +48151,12 @@ var PathBase = class {
48930
48151
  /**
48931
48152
  * Get the Path object referenced by the string path, resolved from this Path
48932
48153
  */
48933
- resolve(path5) {
48934
- if (!path5) {
48154
+ resolve(path6) {
48155
+ if (!path6) {
48935
48156
  return this;
48936
48157
  }
48937
- const rootPath = this.getRootString(path5);
48938
- const dir = path5.substring(rootPath.length);
48158
+ const rootPath = this.getRootString(path6);
48159
+ const dir = path6.substring(rootPath.length);
48939
48160
  const dirParts = dir.split(this.splitSep);
48940
48161
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
48941
48162
  return result;
@@ -49687,8 +48908,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
49687
48908
  /**
49688
48909
  * @internal
49689
48910
  */
49690
- getRootString(path5) {
49691
- return import_node_path2.win32.parse(path5).root;
48911
+ getRootString(path6) {
48912
+ return import_node_path2.win32.parse(path6).root;
49692
48913
  }
49693
48914
  /**
49694
48915
  * @internal
@@ -49734,8 +48955,8 @@ var PathPosix = class _PathPosix extends PathBase {
49734
48955
  /**
49735
48956
  * @internal
49736
48957
  */
49737
- getRootString(path5) {
49738
- return path5.startsWith("/") ? "/" : "";
48958
+ getRootString(path6) {
48959
+ return path6.startsWith("/") ? "/" : "";
49739
48960
  }
49740
48961
  /**
49741
48962
  * @internal
@@ -49824,11 +49045,11 @@ var PathScurryBase = class {
49824
49045
  /**
49825
49046
  * Get the depth of a provided path, string, or the cwd
49826
49047
  */
49827
- depth(path5 = this.cwd) {
49828
- if (typeof path5 === "string") {
49829
- path5 = this.cwd.resolve(path5);
49048
+ depth(path6 = this.cwd) {
49049
+ if (typeof path6 === "string") {
49050
+ path6 = this.cwd.resolve(path6);
49830
49051
  }
49831
- return path5.depth();
49052
+ return path6.depth();
49832
49053
  }
49833
49054
  /**
49834
49055
  * Return the cache of child entries. Exposed so subclasses can create
@@ -50315,9 +49536,9 @@ var PathScurryBase = class {
50315
49536
  process2();
50316
49537
  return results;
50317
49538
  }
50318
- chdir(path5 = this.cwd) {
49539
+ chdir(path6 = this.cwd) {
50319
49540
  const oldCwd = this.cwd;
50320
- this.cwd = typeof path5 === "string" ? this.cwd.resolve(path5) : path5;
49541
+ this.cwd = typeof path6 === "string" ? this.cwd.resolve(path6) : path6;
50321
49542
  this.cwd[setAsCwd](oldCwd);
50322
49543
  }
50323
49544
  };
@@ -50673,8 +49894,8 @@ var MatchRecord = class {
50673
49894
  }
50674
49895
  // match, absolute, ifdir
50675
49896
  entries() {
50676
- return [...this.store.entries()].map(([path5, n]) => [
50677
- path5,
49897
+ return [...this.store.entries()].map(([path6, n]) => [
49898
+ path6,
50678
49899
  !!(n & 2),
50679
49900
  !!(n & 1)
50680
49901
  ]);
@@ -50879,9 +50100,9 @@ var GlobUtil = class {
50879
50100
  signal;
50880
50101
  maxDepth;
50881
50102
  includeChildMatches;
50882
- constructor(patterns, path5, opts) {
50103
+ constructor(patterns, path6, opts) {
50883
50104
  this.patterns = patterns;
50884
- this.path = path5;
50105
+ this.path = path6;
50885
50106
  this.opts = opts;
50886
50107
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
50887
50108
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -50900,11 +50121,11 @@ var GlobUtil = class {
50900
50121
  });
50901
50122
  }
50902
50123
  }
50903
- #ignored(path5) {
50904
- return this.seen.has(path5) || !!this.#ignore?.ignored?.(path5);
50124
+ #ignored(path6) {
50125
+ return this.seen.has(path6) || !!this.#ignore?.ignored?.(path6);
50905
50126
  }
50906
- #childrenIgnored(path5) {
50907
- return !!this.#ignore?.childrenIgnored?.(path5);
50127
+ #childrenIgnored(path6) {
50128
+ return !!this.#ignore?.childrenIgnored?.(path6);
50908
50129
  }
50909
50130
  // backpressure mechanism
50910
50131
  pause() {
@@ -51119,8 +50340,8 @@ var GlobUtil = class {
51119
50340
  };
51120
50341
  var GlobWalker = class extends GlobUtil {
51121
50342
  matches = /* @__PURE__ */ new Set();
51122
- constructor(patterns, path5, opts) {
51123
- super(patterns, path5, opts);
50343
+ constructor(patterns, path6, opts) {
50344
+ super(patterns, path6, opts);
51124
50345
  }
51125
50346
  matchEmit(e) {
51126
50347
  this.matches.add(e);
@@ -51157,8 +50378,8 @@ var GlobWalker = class extends GlobUtil {
51157
50378
  };
51158
50379
  var GlobStream = class extends GlobUtil {
51159
50380
  results;
51160
- constructor(patterns, path5, opts) {
51161
- super(patterns, path5, opts);
50381
+ constructor(patterns, path6, opts) {
50382
+ super(patterns, path6, opts);
51162
50383
  this.results = new Minipass({
51163
50384
  signal: this.signal,
51164
50385
  objectMode: true
@@ -51451,59 +50672,113 @@ var glob = Object.assign(glob_, {
51451
50672
  });
51452
50673
  glob.glob = glob;
51453
50674
 
51454
- // src/scanner.ts
51455
- function simpleHash3(str) {
51456
- let hash = 0;
51457
- for (let i = 0; i < str.length; i++) {
51458
- const char = str.charCodeAt(i);
51459
- hash = (hash << 5) - hash + char;
51460
- 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
+ }
51461
50701
  }
51462
- return hash.toString(36);
51463
- }
51464
- function isSkippableLine(line) {
51465
- const trimmed = line.trim();
51466
- if (trimmed.length === 0) return true;
51467
- return SKIP_LINE_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
51468
- }
51469
- function extractBlocks(content, filePath, minLines, shouldNormalize) {
51470
- const lines = content.split("\n");
51471
- const blocks = [];
51472
- if (lines.length < minLines) {
51473
- return blocks;
51474
- }
51475
- const blockSizes = [minLines];
51476
- const maxSize = Math.min(MAX_BLOCK_SIZE, lines.length);
51477
- for (let size = Math.floor(minLines * BLOCK_SIZE_MULTIPLIER); size <= maxSize; size = Math.floor(size * BLOCK_SIZE_MULTIPLIER)) {
51478
- blockSizes.push(size);
51479
- }
51480
- for (const blockSize of blockSizes) {
51481
- const step = blockSize < 10 ? 1 : Math.max(1, Math.floor(blockSize / SLIDING_WINDOW_STEP_DIVISOR));
51482
- for (let i = 0; i <= lines.length - blockSize; i += step) {
51483
- const blockLines = lines.slice(i, i + blockSize);
51484
- const blockContent = blockLines.join("\n");
51485
- const meaningfulLines = blockLines.filter(
51486
- (line) => !isSkippableLine(line)
51487
- );
51488
- if (meaningfulLines.length < blockSize * MIN_MEANINGFUL_LINE_RATIO) {
51489
- 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;
51490
50713
  }
51491
- const normalized = shouldNormalize ? normalizeCode(blockContent) : blockContent;
51492
- const hash = simpleHash3(normalized);
51493
- blocks.push({
51494
- content: blockContent,
51495
- normalized,
51496
- 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,
51497
50722
  filePath,
51498
- startLine: i + 1,
51499
- // 1-indexed
51500
- endLine: i + blockSize,
51501
- lineCount: blockSize
51502
- });
50723
+ startLine: b.startLine,
50724
+ endLine: b.endLine,
50725
+ exported: b.exported
50726
+ }));
50727
+ } catch {
50728
+ this.misses++;
50729
+ return null;
51503
50730
  }
51504
50731
  }
51505
- return blocks;
51506
- }
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;
51507
50782
  function shouldIgnore(filePath, ignorePatterns) {
51508
50783
  const normalizedPath = filePath.toLowerCase();
51509
50784
  return ignorePatterns.some((pattern) => {
@@ -51511,14 +50786,16 @@ function shouldIgnore(filePath, ignorePatterns) {
51511
50786
  return normalizedPath.includes(`/${normalizedPattern}/`) || normalizedPath.includes(`\\${normalizedPattern}\\`) || normalizedPath.endsWith(`/${normalizedPattern}`) || normalizedPath.endsWith(`\\${normalizedPattern}`);
51512
50787
  });
51513
50788
  }
51514
- async function scanDirectory(targetPath, options, enableAST = true) {
51515
- const { extensions, ignorePatterns, minLines, normalize: normalize2 } = options;
51516
- const absolutePath = import_node_path3.default.resolve(targetPath);
51517
- const blocks = [];
51518
- const declarations = [];
50789
+ async function scanDirectory(targetPath, options, useCache = true) {
50790
+ const { extensions, ignorePatterns } = options;
50791
+ const absolutePath = import_node_path4.default.resolve(targetPath);
51519
50792
  const astBlocks = [];
51520
50793
  let fileCount = 0;
51521
50794
  let totalLines = 0;
50795
+ const cache = useCache ? new ASTCache(targetPath) : null;
50796
+ if (cache) {
50797
+ await cache.load();
50798
+ }
51522
50799
  const pattern = extensions.length === 1 ? `**/*.${extensions[0]}` : `**/*.{${extensions.join(",")}}`;
51523
50800
  const files = await glob(pattern, {
51524
50801
  cwd: absolutePath,
@@ -51526,49 +50803,70 @@ async function scanDirectory(targetPath, options, enableAST = true) {
51526
50803
  nodir: true,
51527
50804
  ignore: ignorePatterns.map((p) => `**/${p}/**`)
51528
50805
  });
51529
- const isTypeScript = extensions.some((ext2) => ext2 === "ts" || ext2 === "tsx");
51530
50806
  for (const filePath of files) {
51531
50807
  if (shouldIgnore(filePath, ignorePatterns)) {
51532
50808
  continue;
51533
50809
  }
50810
+ if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") && !filePath.endsWith(".js") && !filePath.endsWith(".jsx")) {
50811
+ continue;
50812
+ }
51534
50813
  try {
51535
- const fileStat = await (0, import_promises2.stat)(filePath);
50814
+ const fileStat = await (0, import_promises3.stat)(filePath);
51536
50815
  if (fileStat.size > MAX_FILE_SIZE) {
51537
50816
  continue;
51538
50817
  }
51539
- const content = await (0, import_promises2.readFile)(filePath, "utf-8");
51540
- const lines = content.split("\n").length;
51541
- totalLines += lines;
51542
- fileCount++;
51543
- const fileBlocks = extractBlocks(
51544
- content,
51545
- filePath,
51546
- minLines,
51547
- normalize2
51548
- );
51549
- blocks.push(...fileBlocks);
51550
- 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++;
51551
50828
  const fileAST = extractASTBlocks(content, filePath);
51552
50829
  astBlocks.push(...fileAST);
51553
- const fileDeclarations = extractDeclarations(content, filePath);
51554
- declarations.push(...fileDeclarations);
50830
+ if (cache) {
50831
+ await cache.set(filePath, fileAST);
50832
+ }
51555
50833
  }
51556
50834
  } catch {
51557
- console.warn(`Warning: Could not read ${filePath}`);
51558
50835
  }
51559
50836
  }
51560
- 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
+ };
51561
50846
  }
51562
50847
 
51563
50848
  // index.ts
51564
- var VERSION = process.env.npm_package_version || "1.7.0";
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
+ ];
51565
50863
  function parseDiffOutput(diff, cwd) {
51566
50864
  const changes = /* @__PURE__ */ new Map();
51567
50865
  let currentFile = null;
51568
50866
  let newLineNum = 0;
51569
50867
  for (const line of diff.split("\n")) {
51570
50868
  if (line.startsWith("+++ b/")) {
51571
- currentFile = import_node_path4.default.resolve(cwd, line.slice(6));
50869
+ currentFile = import_node_path5.default.resolve(cwd, line.slice(6));
51572
50870
  if (!changes.has(currentFile)) {
51573
50871
  changes.set(currentFile, []);
51574
50872
  }
@@ -51596,7 +50894,7 @@ function parseDiffOutput(diff, cwd) {
51596
50894
  return changes;
51597
50895
  }
51598
50896
  function getChangedLines(targetPath) {
51599
- const absolutePath = import_node_path4.default.resolve(targetPath);
50897
+ const absolutePath = import_node_path5.default.resolve(targetPath);
51600
50898
  const allChanges = /* @__PURE__ */ new Map();
51601
50899
  const mergeChanges = (newChanges) => {
51602
50900
  for (const [file, ranges] of newChanges) {
@@ -51606,16 +50904,14 @@ function getChangedLines(targetPath) {
51606
50904
  }
51607
50905
  };
51608
50906
  const addFullFile = (filePath) => {
51609
- const resolved = import_node_path4.default.resolve(absolutePath, filePath);
50907
+ const resolved = import_node_path5.default.resolve(absolutePath, filePath);
51610
50908
  if (!allChanges.has(resolved)) {
51611
50909
  allChanges.set(resolved, [{ start: 1, end: 999999 }]);
51612
50910
  }
51613
50911
  };
51614
50912
  try {
51615
- const stagedDiff = (0, import_node_child_process.execSync)("git diff --cached", { cwd: absolutePath, encoding: "utf-8" });
51616
- mergeChanges(parseDiffOutput(stagedDiff, absolutePath));
51617
- const unstagedDiff = (0, import_node_child_process.execSync)("git diff", { cwd: absolutePath, encoding: "utf-8" });
51618
- 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));
51619
50915
  const untracked = (0, import_node_child_process.execSync)("git ls-files --others --exclude-standard", { cwd: absolutePath, encoding: "utf-8" });
51620
50916
  for (const file of untracked.split("\n")) {
51621
50917
  if (file.trim()) addFullFile(file.trim());
@@ -51626,8 +50922,7 @@ function getChangedLines(targetPath) {
51626
50922
  if (currentBranch !== baseBranch) {
51627
50923
  const mergeBase = (0, import_node_child_process.execSync)(`git merge-base ${baseBranch} HEAD 2>/dev/null || echo ""`, { cwd: absolutePath, encoding: "utf-8" }).trim();
51628
50924
  if (mergeBase) {
51629
- const branchDiff = (0, import_node_child_process.execSync)(`git diff ${mergeBase}...HEAD`, { cwd: absolutePath, encoding: "utf-8" });
51630
- mergeChanges(parseDiffOutput(branchDiff, absolutePath));
50925
+ mergeChanges(parseDiffOutput((0, import_node_child_process.execSync)(`git diff ${mergeBase}...HEAD`, { cwd: absolutePath, encoding: "utf-8" }), absolutePath));
51631
50926
  }
51632
50927
  }
51633
50928
  } catch {
@@ -51644,50 +50939,35 @@ function isInChangedLines(filePath, blockStart, blockEnd, changes) {
51644
50939
  }
51645
50940
  function showHelp() {
51646
50941
  console.log(`
51647
- dslop - Detect Similar/Duplicate Lines Of Programming
50942
+ dslop - Find duplicate functions and types
51648
50943
 
51649
50944
  Usage:
51650
50945
  dslop [path] [options]
51651
50946
 
51652
- By default, checks your branch changes against the codebase.
51653
- If no changes are found, automatically scans the entire path.
51654
-
51655
- Arguments:
51656
- path Directory to scan (default: current directory)
51657
-
51658
50947
  Options:
51659
50948
  -a, --all Force full codebase scan
51660
50949
  -c, --changes Force changes-only mode (exit if no changes found)
51661
- -m, --min-lines <n> Minimum block size in lines (default: ${DEFAULT_MIN_LINES})
51662
- -s, --similarity <n> Minimum similarity threshold 0-100 (default: ${Math.round(DEFAULT_SIMILARITY * 100)})
51663
- -e, --extensions <s> File extensions to scan (default: ${DEFAULT_EXTENSIONS.join(",")})
51664
- -i, --ignore <s> Patterns to ignore (default: ${DEFAULT_IGNORE_PATTERNS.slice(0, 4).join(",")},...)
51665
- --no-normalize Disable string/number normalization
51666
- --cross-package Only show duplicates across different packages/apps (monorepo mode)
51667
- --json Output as JSON
51668
- -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
51669
50956
  -v, --version Show version
51670
50957
 
51671
50958
  Examples:
51672
- dslop Check your PR changes (or full scan if none)
51673
- dslop ./apps/web Scan apps/web (full scan if no changes there)
51674
- dslop -c Check PR changes only, exit if none
51675
- 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
51676
50962
  `);
51677
50963
  }
51678
- function showVersion() {
51679
- console.log(`dslop v${VERSION}`);
51680
- }
51681
50964
  async function main() {
51682
50965
  const { values, positionals } = (0, import_node_util.parseArgs)({
51683
50966
  args: process.argv.slice(2),
51684
50967
  options: {
51685
- "min-lines": { type: "string", short: "m", default: String(DEFAULT_MIN_LINES) },
51686
- similarity: { type: "string", short: "s", default: String(Math.round(DEFAULT_SIMILARITY * 100)) },
51687
50968
  extensions: { type: "string", short: "e", default: DEFAULT_EXTENSIONS.join(",") },
51688
50969
  ignore: { type: "string", short: "i", default: DEFAULT_IGNORE_PATTERNS.join(",") },
51689
- normalize: { type: "boolean", default: true },
51690
- "no-normalize": { type: "boolean", default: false },
50970
+ "no-cache": { type: "boolean", default: false },
51691
50971
  all: { type: "boolean", short: "a", default: false },
51692
50972
  changes: { type: "boolean", short: "c", default: false },
51693
50973
  "cross-package": { type: "boolean", default: false },
@@ -51702,109 +50982,66 @@ async function main() {
51702
50982
  process.exit(0);
51703
50983
  }
51704
50984
  if (values.version) {
51705
- showVersion();
50985
+ console.log(`dslop v${VERSION}`);
51706
50986
  process.exit(0);
51707
50987
  }
51708
50988
  const targetPath = positionals[0] || ".";
51709
- const minLines = parseInt(values["min-lines"], 10);
51710
- const similarity = parseInt(values.similarity, 10) / 100;
51711
50989
  const extensions = values.extensions.split(",").map((e) => e.trim());
51712
50990
  const ignorePatterns = values.ignore.split(",").map((p) => p.trim());
51713
- const normalize2 = !values["no-normalize"];
50991
+ const useCache = !values["no-cache"];
51714
50992
  const forceAll = values.all;
51715
50993
  const forceChanges = values.changes;
51716
50994
  const crossPackage = values["cross-package"];
51717
50995
  const jsonOutput = values.json;
51718
- const hasExplicitPath = positionals.length > 0;
51719
- if (minLines < 2) {
51720
- console.error("Error: --min-lines must be at least 2");
51721
- process.exit(1);
51722
- }
51723
- if (similarity < 0 || similarity > 1) {
51724
- console.error("Error: --similarity must be between 0 and 100");
51725
- process.exit(1);
51726
- }
51727
- const scanOptions = {
51728
- extensions,
51729
- ignorePatterns,
51730
- minLines,
51731
- normalize: normalize2
51732
- };
50996
+ const scanOptions = { extensions, ignorePatterns };
51733
50997
  let scanAll = forceAll;
51734
50998
  let changedLines = null;
51735
50999
  if (!forceAll) {
51736
51000
  changedLines = getChangedLines(targetPath);
51737
51001
  if (changedLines.size === 0) {
51738
51002
  if (forceChanges) {
51739
- console.log("\nNo changes found on current branch.");
51003
+ console.log("\nNo changes found.");
51740
51004
  process.exit(0);
51741
51005
  }
51742
51006
  scanAll = true;
51743
51007
  if (!jsonOutput) {
51744
51008
  console.log(`
51745
- No changes detected${hasExplicitPath ? ` in ${targetPath}` : ""}, defaulting to full scan...`);
51009
+ No changes detected, running full scan...`);
51746
51010
  }
51747
51011
  }
51748
51012
  }
51749
51013
  if (!jsonOutput) {
51750
51014
  console.log(`
51751
51015
  Scanning ${targetPath}...`);
51752
- if (!scanAll && changedLines && changedLines.size > 0) {
51753
- console.log(` Mode: checking changed lines in ${changedLines.size} files`);
51754
- } else {
51755
- console.log(` Mode: full codebase scan`);
51756
- }
51757
- console.log(` Extensions: ${extensions.join(", ")}`);
51758
- console.log(` Min block size: ${minLines} lines`);
51759
- console.log(` Similarity threshold: ${Math.round(similarity * 100)}%`);
51760
- if (crossPackage) {
51761
- console.log(` Cross-package: enabled`);
51762
- }
51016
+ console.log(` Mode: ${scanAll ? "full scan" : `checking ${changedLines?.size} changed files`}`);
51017
+ if (crossPackage) console.log(` Cross-package: enabled`);
51763
51018
  console.log();
51764
51019
  }
51765
51020
  try {
51766
51021
  const startTime = performance.now();
51767
- const { blocks, declarations, astBlocks, fileCount, totalLines } = await scanDirectory(targetPath, scanOptions, true);
51022
+ const { astBlocks, fileCount, totalLines, cacheStats } = await scanDirectory(targetPath, scanOptions, useCache);
51768
51023
  const scanTime = performance.now() - startTime;
51769
51024
  if (!jsonOutput) {
51770
51025
  console.log(`Scanned ${fileCount} files (${totalLines.toLocaleString()} lines) in ${Math.round(scanTime)}ms`);
51771
- 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
51772
51030
  `);
51773
51031
  }
51774
- if (blocks.length === 0 && astBlocks.length === 0) {
51775
- 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
+ }
51776
51038
  process.exit(0);
51777
51039
  }
51778
51040
  const detectStart = performance.now();
51779
- let duplicates = findDuplicates(blocks, similarity, targetPath);
51780
- let astDuplicates = findASTDuplicates(astBlocks, similarity);
51781
- let declDuplicates = findDeclarationDuplicates(declarations, similarity);
51041
+ let duplicates = findASTDuplicates(astBlocks, 0.7);
51782
51042
  const detectTime = performance.now() - detectStart;
51783
51043
  if (!scanAll && changedLines) {
51784
- const changedFilePaths = new Set(changedLines.keys());
51785
51044
  duplicates = duplicates.filter((group) => {
51786
- const inChanged = group.matches.filter(
51787
- (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51788
- );
51789
- const notInChanged = group.matches.filter(
51790
- (m) => !isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51791
- );
51792
- if (inChanged.length === 0 || notInChanged.length === 0) return false;
51793
- const inOtherFiles = notInChanged.some((m) => !changedFilePaths.has(m.filePath));
51794
- const inSameFileOutsideChanges = notInChanged.some((m) => changedFilePaths.has(m.filePath));
51795
- if (inOtherFiles && group.matches.length > 10) return false;
51796
- return inOtherFiles || inSameFileOutsideChanges;
51797
- });
51798
- astDuplicates = astDuplicates.filter((group) => {
51799
- const inChanged = group.matches.filter(
51800
- (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51801
- );
51802
- const notInChanged = group.matches.filter(
51803
- (m) => !isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51804
- );
51805
- return inChanged.length > 0 && notInChanged.length > 0;
51806
- });
51807
- declDuplicates = declDuplicates.filter((group) => {
51808
51045
  const inChanged = group.matches.filter(
51809
51046
  (m) => isInChangedLines(m.filePath, m.startLine, m.endLine, changedLines)
51810
51047
  );
@@ -51815,39 +51052,30 @@ Scanning ${targetPath}...`);
51815
51052
  });
51816
51053
  }
51817
51054
  if (crossPackage) {
51818
- const filterCrossPackage = (groups) => {
51819
- return groups.filter((group) => {
51820
- const packages = new Set(
51821
- group.matches.map((m) => {
51822
- const match2 = m.filePath.match(/(?:apps|packages|libs)\/([^/]+)/);
51823
- return match2 ? match2[1] : m.filePath.split("/")[0];
51824
- })
51825
- );
51826
- return packages.size > 1;
51827
- });
51828
- };
51829
- duplicates = filterCrossPackage(duplicates);
51830
- astDuplicates = filterCrossPackage(astDuplicates);
51831
- 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
+ });
51832
51064
  }
51833
51065
  if (!jsonOutput) {
51834
- console.log(`Found ${astDuplicates.length} duplicate functions/types in ${Math.round(detectTime)}ms
51066
+ console.log(`Found ${duplicates.length} duplicate groups in ${Math.round(detectTime)}ms
51835
51067
  `);
51836
51068
  }
51837
- if (astDuplicates.length === 0) {
51069
+ if (duplicates.length === 0) {
51838
51070
  if (jsonOutput) {
51839
51071
  console.log(JSON.stringify({ summary: { duplicateGroups: 0 }, duplicates: [] }, null, 2));
51840
- } else if (!scanAll) {
51841
- console.log("No duplicates in your changes. You're good!");
51842
- } else if (crossPackage) {
51843
- console.log("No cross-package duplicates found!");
51844
51072
  } else {
51845
- console.log("No duplicates found!");
51073
+ console.log(crossPackage ? "No cross-package duplicates found!" : "No duplicates found!");
51846
51074
  }
51847
51075
  process.exit(0);
51848
51076
  }
51849
51077
  if (jsonOutput) {
51850
- const compactAST = astDuplicates.slice(0, 50).map((a) => ({
51078
+ const compactAST = duplicates.slice(0, 50).map((a) => ({
51851
51079
  type: a.type,
51852
51080
  name: a.matches[0]?.name || "unknown",
51853
51081
  occurrences: a.matches.length,
@@ -51859,17 +51087,11 @@ Scanning ${targetPath}...`);
51859
51087
  }))
51860
51088
  }));
51861
51089
  console.log(JSON.stringify({
51862
- summary: {
51863
- duplicateGroups: astDuplicates.length
51864
- },
51090
+ summary: { duplicateGroups: duplicates.length },
51865
51091
  duplicates: compactAST
51866
51092
  }, null, 2));
51867
51093
  } else {
51868
- if (astDuplicates.length > 0) {
51869
- console.log(formatASTDuplicates(astDuplicates, targetPath));
51870
- } else {
51871
- console.log("No duplicate functions or types found!");
51872
- }
51094
+ console.log(formatASTDuplicates(duplicates, targetPath));
51873
51095
  }
51874
51096
  } catch (error) {
51875
51097
  console.error("Error:", error instanceof Error ? error.message : error);