@lzehrung/codegraph 2.3.27 → 2.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/codegraph-skill/codegraph/SKILL.md +1 -0
  2. package/dist/agent/explain.d.ts +9 -1
  3. package/dist/agent/explain.d.ts.map +1 -1
  4. package/dist/agent/explain.js +18 -1
  5. package/dist/agent/explain.js.map +1 -1
  6. package/dist/agent/refactor-plan.d.ts +2 -0
  7. package/dist/agent/refactor-plan.d.ts.map +1 -1
  8. package/dist/agent/refactor-plan.js +11 -0
  9. package/dist/agent/refactor-plan.js.map +1 -1
  10. package/dist/agent/rename-preview.d.ts.map +1 -1
  11. package/dist/agent/rename-preview.js +49 -11
  12. package/dist/agent/rename-preview.js.map +1 -1
  13. package/dist/agent-tools.d.ts +2 -1
  14. package/dist/agent-tools.d.ts.map +1 -1
  15. package/dist/agent-tools.js +8 -0
  16. package/dist/agent-tools.js.map +1 -1
  17. package/dist/agent.d.ts +1 -1
  18. package/dist/agent.d.ts.map +1 -1
  19. package/dist/agent.js.map +1 -1
  20. package/dist/bin/cli.js +1389 -259
  21. package/dist/bin/query-index-worker.js +56 -18
  22. package/dist/cli/navigation.d.ts.map +1 -1
  23. package/dist/cli/navigation.js +4 -0
  24. package/dist/cli/navigation.js.map +1 -1
  25. package/dist/impact/call-compatibility.js +3 -3
  26. package/dist/impact/call-compatibility.js.map +1 -1
  27. package/dist/impact/direct.js +1 -1
  28. package/dist/impact/direct.js.map +1 -1
  29. package/dist/impact/reference-cache.d.ts +1 -0
  30. package/dist/impact/reference-cache.d.ts.map +1 -1
  31. package/dist/impact/reference-cache.js +44 -18
  32. package/dist/impact/reference-cache.js.map +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  37. package/dist/indexer/build-cache/module-cache.js +30 -0
  38. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  39. package/dist/indexer/build-cache/options.d.ts +13 -2
  40. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  41. package/dist/indexer/build-cache/options.js +13 -2
  42. package/dist/indexer/build-cache/options.js.map +1 -1
  43. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  44. package/dist/indexer/build-cache/project-snapshot.js +60 -5
  45. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  46. package/dist/indexer/import-types.d.ts +14 -1
  47. package/dist/indexer/import-types.d.ts.map +1 -1
  48. package/dist/indexer/imports/binding-ranges.d.ts +50 -0
  49. package/dist/indexer/imports/binding-ranges.d.ts.map +1 -0
  50. package/dist/indexer/imports/binding-ranges.js +297 -0
  51. package/dist/indexer/imports/binding-ranges.js.map +1 -0
  52. package/dist/indexer/imports/js-text-imports.d.ts +4 -0
  53. package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
  54. package/dist/indexer/imports/js-text-imports.js +210 -48
  55. package/dist/indexer/imports/js-text-imports.js.map +1 -1
  56. package/dist/indexer/imports/language-specific.d.ts +3 -0
  57. package/dist/indexer/imports/language-specific.d.ts.map +1 -1
  58. package/dist/indexer/imports/language-specific.js +97 -23
  59. package/dist/indexer/imports/language-specific.js.map +1 -1
  60. package/dist/indexer/imports/native-captures.d.ts.map +1 -1
  61. package/dist/indexer/imports/native-captures.js +52 -30
  62. package/dist/indexer/imports/native-captures.js.map +1 -1
  63. package/dist/indexer/imports/python.d.ts +2 -0
  64. package/dist/indexer/imports/python.d.ts.map +1 -1
  65. package/dist/indexer/imports/python.js +55 -18
  66. package/dist/indexer/imports/python.js.map +1 -1
  67. package/dist/indexer/imports.d.ts.map +1 -1
  68. package/dist/indexer/imports.js +15 -1
  69. package/dist/indexer/imports.js.map +1 -1
  70. package/dist/indexer/navigation-goto.d.ts +1 -1
  71. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  72. package/dist/indexer/navigation-goto.js +66 -17
  73. package/dist/indexer/navigation-goto.js.map +1 -1
  74. package/dist/indexer/navigation-references.d.ts +23 -2
  75. package/dist/indexer/navigation-references.d.ts.map +1 -1
  76. package/dist/indexer/navigation-references.js +196 -4
  77. package/dist/indexer/navigation-references.js.map +1 -1
  78. package/dist/indexer/navigation.d.ts +9 -3
  79. package/dist/indexer/navigation.d.ts.map +1 -1
  80. package/dist/indexer/navigation.js +154 -41
  81. package/dist/indexer/navigation.js.map +1 -1
  82. package/dist/indexer/scope.d.ts.map +1 -1
  83. package/dist/indexer/scope.js +18 -0
  84. package/dist/indexer/scope.js.map +1 -1
  85. package/dist/indexer/symbols.d.ts +1 -0
  86. package/dist/indexer/symbols.d.ts.map +1 -1
  87. package/dist/indexer/types.d.ts +10 -0
  88. package/dist/indexer/types.d.ts.map +1 -1
  89. package/dist/indexer.d.ts +1 -1
  90. package/dist/indexer.d.ts.map +1 -1
  91. package/dist/indexer.js.map +1 -1
  92. package/dist/languages/definitions/javascript.d.ts.map +1 -1
  93. package/dist/languages/definitions/javascript.js +10 -2
  94. package/dist/languages/definitions/javascript.js.map +1 -1
  95. package/dist/languages/definitions/php.d.ts.map +1 -1
  96. package/dist/languages/definitions/php.js +15 -8
  97. package/dist/languages/definitions/php.js.map +1 -1
  98. package/dist/languages/definitions/python.d.ts.map +1 -1
  99. package/dist/languages/definitions/python.js +11 -1
  100. package/dist/languages/definitions/python.js.map +1 -1
  101. package/dist/languages/definitions/typescript.d.ts.map +1 -1
  102. package/dist/languages/definitions/typescript.js +20 -3
  103. package/dist/languages/definitions/typescript.js.map +1 -1
  104. package/dist/languages/definitions/zig.d.ts.map +1 -1
  105. package/dist/languages/definitions/zig.js +10 -3
  106. package/dist/languages/definitions/zig.js.map +1 -1
  107. package/dist/languages/import-statement-parsers.d.ts +3 -0
  108. package/dist/languages/import-statement-parsers.d.ts.map +1 -1
  109. package/dist/languages/import-statement-parsers.js +4 -0
  110. package/dist/languages/import-statement-parsers.js.map +1 -1
  111. package/dist/mcp/handlers.d.ts +2 -1
  112. package/dist/mcp/handlers.d.ts.map +1 -1
  113. package/dist/mcp/handlers.js +15 -1
  114. package/dist/mcp/handlers.js.map +1 -1
  115. package/dist/review/summaries.d.ts.map +1 -1
  116. package/dist/review/summaries.js +11 -19
  117. package/dist/review/summaries.js.map +1 -1
  118. package/dist/review/types.d.ts +2 -1
  119. package/dist/review/types.d.ts.map +1 -1
  120. package/dist/review/types.js.map +1 -1
  121. package/dist/session.d.ts +2 -9
  122. package/dist/session.d.ts.map +1 -1
  123. package/dist/session.js.map +1 -1
  124. package/dist/sql/navigation.d.ts +6 -1
  125. package/dist/sql/navigation.d.ts.map +1 -1
  126. package/dist/sql/navigation.js +35 -3
  127. package/dist/sql/navigation.js.map +1 -1
  128. package/dist/util/comments.d.ts +10 -0
  129. package/dist/util/comments.d.ts.map +1 -1
  130. package/dist/util/comments.js +43 -2
  131. package/dist/util/comments.js.map +1 -1
  132. package/dist/util/lines.d.ts +2 -0
  133. package/dist/util/lines.d.ts.map +1 -1
  134. package/dist/util/lines.js +14 -0
  135. package/dist/util/lines.js.map +1 -1
  136. package/docs/mcp.md +1 -1
  137. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -2070,12 +2070,21 @@ function transformJsLikeTrivia(src, options) {
2070
2070
  if (preserveLength)
2071
2071
  out += " ";
2072
2072
  i += 2;
2073
- while (i < src.length) {
2073
+ let depth = 1;
2074
+ while (i < src.length && depth > 0) {
2075
+ if (options?.nestedBlockComments && src[i] === "/" && src[i + 1] === "*") {
2076
+ if (preserveLength)
2077
+ out += " ";
2078
+ depth += 1;
2079
+ i += 2;
2080
+ continue;
2081
+ }
2074
2082
  if (src[i] === "*" && src[i + 1] === "/") {
2075
2083
  if (preserveLength)
2076
2084
  out += " ";
2085
+ depth -= 1;
2077
2086
  i += 2;
2078
- break;
2087
+ continue;
2079
2088
  }
2080
2089
  if (preserveLength)
2081
2090
  out += maskedChar(src[i]);
@@ -2378,6 +2387,20 @@ function stripPythonCommentsAndStrings(src) {
2378
2387
  out = out.replace(/#.*$/gm, "");
2379
2388
  return out;
2380
2389
  }
2390
+ function maskMatchPreservingNewlines(match) {
2391
+ let out = "";
2392
+ for (const character of match) {
2393
+ out += character === "\n" ? "\n" : " ".repeat(character.length);
2394
+ }
2395
+ return out;
2396
+ }
2397
+ function maskPythonCommentsAndStrings(src) {
2398
+ let out = src;
2399
+ out = out.replace(/([rRuU]?[fF]?)("""|''')[\s\S]*?\2/g, maskMatchPreservingNewlines);
2400
+ out = out.replace(/([rRuU]?[fF]?)("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*')/g, maskMatchPreservingNewlines);
2401
+ out = out.replace(/#.*$/gm, maskMatchPreservingNewlines);
2402
+ return out;
2403
+ }
2381
2404
  var init_comments = __esm({
2382
2405
  "dist/util/comments.js"() {
2383
2406
  "use strict";
@@ -2567,6 +2590,7 @@ var init_typescript = __esm({
2567
2590
  (function_declaration name: (identifier) @name)
2568
2591
  (generator_function_declaration name: (identifier) @name)
2569
2592
  (method_definition name: (property_identifier) @name)
2593
+ (public_field_definition name: (property_identifier) @name)
2570
2594
  (method_signature name: (property_identifier) @name)
2571
2595
  (abstract_method_signature name: (property_identifier) @name)
2572
2596
  (function_signature name: (identifier) @name)
@@ -2575,6 +2599,8 @@ var init_typescript = __esm({
2575
2599
  (variable_declarator name: (identifier) @name)
2576
2600
  (interface_declaration name: (type_identifier) @name)
2577
2601
  (type_alias_declaration name: (type_identifier) @name)
2602
+ (enum_body (property_identifier) @name)
2603
+ (enum_assignment name: (property_identifier) @name)
2578
2604
  (enum_declaration name: [ (identifier) (type_identifier) ] @name)
2579
2605
  (internal_module name: (identifier) @name)
2580
2606
  (module name: (identifier) @name)
@@ -2623,13 +2649,23 @@ var init_typescript = __esm({
2623
2649
  return "variable";
2624
2650
  },
2625
2651
  isDeclarationName: (node) => {
2626
- const p = node.parent?.type;
2652
+ const parent = node.parent;
2653
+ const p = parent?.type;
2654
+ if (parent?.type === "variable_declarator") {
2655
+ return parent.childForFieldName("name")?.id === node.id;
2656
+ }
2657
+ if (parent?.type === "public_field_definition" || parent?.type === "enum_assignment") {
2658
+ const name = parent.childForFieldName("name") ?? parent.childForFieldName("property");
2659
+ return name?.id === node.id;
2660
+ }
2661
+ if (parent?.type === "enum_body") {
2662
+ return node.type === "property_identifier";
2663
+ }
2627
2664
  return !!p && [
2628
2665
  "generator_function_declaration",
2629
2666
  "function_declaration",
2630
2667
  "class_declaration",
2631
2668
  "abstract_class_declaration",
2632
- "variable_declarator",
2633
2669
  "interface_declaration",
2634
2670
  "type_alias_declaration",
2635
2671
  "enum_declaration",
@@ -2654,7 +2690,7 @@ var init_typescript = __esm({
2654
2690
  const parent = node.parent?.type;
2655
2691
  return parent === "function_signature" || parent === "internal_module" || parent === "module";
2656
2692
  },
2657
- createsBlockScope: (n) => n.type === "program" || n.type === "block" || n.type === "class_body" || n.type === "class_static_block",
2693
+ createsBlockScope: (n) => n.type === "program" || n.type === "block" || n.type === "class_body" || n.type === "class_static_block" || n.type === "enum_body",
2658
2694
  createsFunctionScope: (n) => n.type === "generator_function_declaration" || n.type === "function_declaration" || n.type === "function" || n.type === "function_expression" || n.type === "arrow_function" || n.type === "method_definition",
2659
2695
  membersAreImplicitlyInScope: false,
2660
2696
  supportsCrossModuleSymbols: true
@@ -2813,6 +2849,7 @@ var init_javascript = __esm({
2813
2849
  (function_declaration name: (identifier) @name)
2814
2850
  (generator_function_declaration name: (identifier) @name)
2815
2851
  (method_definition name: (property_identifier) @name)
2852
+ (field_definition property: (property_identifier) @name)
2816
2853
  (class_declaration name: (identifier) @name)
2817
2854
  (variable_declarator name: (identifier) @name)
2818
2855
  `,
@@ -2850,12 +2887,19 @@ var init_javascript = __esm({
2850
2887
  return "variable";
2851
2888
  },
2852
2889
  isDeclarationName: (node) => {
2853
- const p = node.parent?.type;
2890
+ const parent = node.parent;
2891
+ const p = parent?.type;
2892
+ if (parent?.type === "variable_declarator") {
2893
+ return parent.childForFieldName("name")?.id === node.id;
2894
+ }
2895
+ if (parent?.type === "field_definition") {
2896
+ const name = parent.childForFieldName("name") ?? parent.childForFieldName("property");
2897
+ return name?.id === node.id;
2898
+ }
2854
2899
  return !!p && [
2855
2900
  "function_declaration",
2856
2901
  "generator_function_declaration",
2857
2902
  "class_declaration",
2858
- "variable_declarator",
2859
2903
  "import_specifier",
2860
2904
  "namespace_import",
2861
2905
  "import_clause",
@@ -3093,9 +3137,13 @@ var init_python = __esm({
3093
3137
  return parent?.childForFieldName("name")?.id === node.id;
3094
3138
  if (t === "pattern_list" || t === "tuple_pattern")
3095
3139
  return true;
3140
+ if (t === "assignment")
3141
+ return parent?.childForFieldName("left")?.id === node.id;
3142
+ if (t === "aliased_import")
3143
+ return parent?.childForFieldName("alias")?.id === node.id;
3096
3144
  if (isTypeAliasLeftName(node))
3097
3145
  return true;
3098
- return !!t && ["function_definition", "class_definition", "assignment", "aliased_import"].includes(t);
3146
+ return !!t && ["function_definition", "class_definition"].includes(t);
3099
3147
  },
3100
3148
  createsBlockScope: (n) => n.type === "module" || n.type === "block",
3101
3149
  createsFunctionScope: (n) => n.type === "function_definition" || n.type === "lambda",
@@ -3158,7 +3206,7 @@ var init_php = __esm({
3158
3206
  },
3159
3207
  {
3160
3208
  type: "const_declaration",
3161
- nameQuery: "(const_element (name) @chunk.name)",
3209
+ nameQuery: "(const_element . (name) @chunk.name)",
3162
3210
  captureId: "const"
3163
3211
  }
3164
3212
  ],
@@ -3190,7 +3238,7 @@ var init_php = __esm({
3190
3238
  (enum_declaration name: (name) @name)
3191
3239
  (enum_case name: (name) @name)
3192
3240
  (function_definition name: (name) @name)
3193
- (const_declaration (const_element (name) @name))
3241
+ (const_declaration (const_element . (name) @name))
3194
3242
  `,
3195
3243
  locals: `
3196
3244
  (class_declaration name: (name) @name)
@@ -3200,8 +3248,8 @@ var init_php = __esm({
3200
3248
  (enum_case name: (name) @name)
3201
3249
  (function_definition name: (name) @name)
3202
3250
  (method_declaration name: (name) @name)
3203
- (const_declaration (const_element (name) @name))
3204
- (property_element (variable_name) @name)
3251
+ (const_declaration (const_element . (name) @name))
3252
+ (property_element name: (variable_name) @name)
3205
3253
  `,
3206
3254
  importBindings: `
3207
3255
  (require_expression) @stmt
@@ -3257,9 +3305,10 @@ var init_php = __esm({
3257
3305
  if (nameFieldOwnerTypes.has(parent.type)) {
3258
3306
  return parent.childForFieldName("name")?.id === node.id;
3259
3307
  }
3260
- if (parent.type === "property_element" && node.type === "variable_name")
3261
- return true;
3262
- return parent.type === "const_element" && parent.namedChildren.some((child) => child.id === node.id && child.type === "name");
3308
+ if (parent.type === "property_element") {
3309
+ return parent.childForFieldName("name")?.id === node.id;
3310
+ }
3311
+ return parent.type === "const_element" && parent.namedChildren[0]?.id === node.id && node.type === "name";
3263
3312
  },
3264
3313
  scopeDeclarationNames: (node) => node.type === "variable_name" && node.parent?.type === "property_element",
3265
3314
  createsFunctionScope: (node) => node.type === "function_definition" || node.type === "method_declaration",
@@ -5133,12 +5182,12 @@ var init_zig = __esm({
5133
5182
  `,
5134
5183
  exports: `
5135
5184
  (source_file (function_declaration name: (identifier) @name))
5136
- (source_file (variable_declaration (identifier) @name))
5185
+ (source_file (variable_declaration . (identifier) @name (_)))
5137
5186
  `,
5138
5187
  locals: `
5139
5188
  (function_declaration name: (identifier) @name)
5140
5189
  (parameter (identifier) @name)
5141
- (variable_declaration (identifier) @name)
5190
+ (variable_declaration . (identifier) @name (_))
5142
5191
  `,
5143
5192
  importBindings: `
5144
5193
  (variable_declaration
@@ -5193,7 +5242,10 @@ var init_zig = __esm({
5193
5242
  return false;
5194
5243
  if (parent.type === "function_declaration" && parent.childForFieldName("name")?.id === node.id)
5195
5244
  return true;
5196
- return parent.type === "variable_declaration";
5245
+ if (parent.type !== "variable_declaration")
5246
+ return false;
5247
+ const declaredName = parent.namedChildren.find((child) => child.type === "identifier");
5248
+ return declaredName?.id === node.id;
5197
5249
  }
5198
5250
  };
5199
5251
  registerLanguage(ZIG_DEF);
@@ -8742,11 +8794,11 @@ var require_pattern = __commonJS({
8742
8794
  if (openingBraceIndex === -1) {
8743
8795
  return false;
8744
8796
  }
8745
- const closingBraceIndex = pattern.indexOf("}", openingBraceIndex + 1);
8746
- if (closingBraceIndex === -1) {
8797
+ const closingBraceIndex2 = pattern.indexOf("}", openingBraceIndex + 1);
8798
+ if (closingBraceIndex2 === -1) {
8747
8799
  return false;
8748
8800
  }
8749
- const braceContent = pattern.slice(openingBraceIndex, closingBraceIndex);
8801
+ const braceContent = pattern.slice(openingBraceIndex, closingBraceIndex2);
8750
8802
  return BRACE_EXPANSION_SEPARATORS_RE.test(braceContent);
8751
8803
  }
8752
8804
  function convertToPositivePattern(pattern) {
@@ -32887,7 +32939,8 @@ function flattenRustUseTree(prefix, item) {
32887
32939
  kind: "member",
32888
32940
  from,
32889
32941
  imported,
32890
- local: alias ?? imported
32942
+ local: alias ?? imported,
32943
+ ...alias !== void 0 ? { explicitAlias: true } : {}
32891
32944
  }
32892
32945
  ];
32893
32946
  }
@@ -32943,6 +32996,7 @@ function parsePhpImportClause(rawClause, importType) {
32943
32996
  from: fullPath2,
32944
32997
  imported: imported2,
32945
32998
  local: aliasMatch2?.[2] ?? imported2,
32999
+ ...aliasMatch2 ? { explicitAlias: true } : {},
32946
33000
  importType: memberType
32947
33001
  });
32948
33002
  }
@@ -32960,6 +33014,7 @@ function parsePhpImportClause(rawClause, importType) {
32960
33014
  from: fullPath,
32961
33015
  imported,
32962
33016
  local: aliasMatch?.[2] ?? imported,
33017
+ ...aliasMatch ? { explicitAlias: true } : {},
32963
33018
  importType
32964
33019
  }
32965
33020
  ];
@@ -33144,7 +33199,8 @@ function parseKotlinImportStatement(stmtText) {
33144
33199
  kind: "named",
33145
33200
  from: rawSpec,
33146
33201
  imported,
33147
- local: match?.[2] ?? imported
33202
+ local: match?.[2] ?? imported,
33203
+ ...match?.[2] !== void 0 ? { explicitAlias: true } : {}
33148
33204
  };
33149
33205
  }
33150
33206
  function parseJavaImportStatement(stmtText) {
@@ -43127,6 +43183,19 @@ function collectLineStartOffsets(source) {
43127
43183
  }
43128
43184
  return lineStarts;
43129
43185
  }
43186
+ function positionAtOffset(lineStarts, index) {
43187
+ let low = 0;
43188
+ let high = lineStarts.length - 1;
43189
+ while (low < high) {
43190
+ const middle = Math.ceil((low + high) / 2);
43191
+ if (lineStarts[middle] <= index) {
43192
+ low = middle;
43193
+ } else {
43194
+ high = middle - 1;
43195
+ }
43196
+ }
43197
+ return { line: low + 1, column: index - lineStarts[low] + 1, index };
43198
+ }
43130
43199
  var init_lines = __esm({
43131
43200
  "dist/util/lines.js"() {
43132
43201
  "use strict";
@@ -45022,6 +45091,239 @@ var init_parse_context = __esm({
45022
45091
  }
45023
45092
  });
45024
45093
 
45094
+ // dist/indexer/imports/binding-ranges.js
45095
+ function maskTriviaSpan(text, start, end) {
45096
+ return text.slice(start, end).replace(/[^\r\n]/g, " ");
45097
+ }
45098
+ function nestedBlockCommentEnd(text, start) {
45099
+ let depth = 1;
45100
+ let index = start + 2;
45101
+ while (index < text.length && depth) {
45102
+ if (text.startsWith("/*", index)) {
45103
+ depth += 1;
45104
+ index += 2;
45105
+ } else if (text.startsWith("*/", index)) {
45106
+ depth -= 1;
45107
+ index += 2;
45108
+ } else {
45109
+ index += 1;
45110
+ }
45111
+ }
45112
+ return index;
45113
+ }
45114
+ function lineCommentEnd(text, start) {
45115
+ let index = start + 2;
45116
+ while (index < text.length && text[index] !== "\r" && text[index] !== "\n")
45117
+ index += 1;
45118
+ return index;
45119
+ }
45120
+ function escapedQuotedLiteralEnd(text, start, quote) {
45121
+ let index = start + 1;
45122
+ while (index < text.length) {
45123
+ if (text[index] === "\\") {
45124
+ index = Math.min(text.length, index + 2);
45125
+ } else if (text[index] === quote) {
45126
+ return index + 1;
45127
+ } else {
45128
+ index += 1;
45129
+ }
45130
+ }
45131
+ return text.length;
45132
+ }
45133
+ function kotlinLiteralEnd(text, start) {
45134
+ const quote = text[start];
45135
+ if (quote !== '"' && quote !== "'")
45136
+ return null;
45137
+ if (quote === '"' && text.startsWith('"""', start)) {
45138
+ const close = text.indexOf('"""', start + 3);
45139
+ return close === -1 ? text.length : close + 3;
45140
+ }
45141
+ return escapedQuotedLiteralEnd(text, start, quote);
45142
+ }
45143
+ function swiftStringEnd(text, start) {
45144
+ let quoteStart = start;
45145
+ while (text[quoteStart] === "#")
45146
+ quoteStart += 1;
45147
+ if (text[quoteStart] !== '"')
45148
+ return null;
45149
+ const hashCount = quoteStart - start;
45150
+ const quote = text.startsWith('"""', quoteStart) ? '"""' : '"';
45151
+ const close = `${quote}${"#".repeat(hashCount)}`;
45152
+ let index = quoteStart + quote.length;
45153
+ while (index < text.length) {
45154
+ if (!hashCount && text[index] === "\\") {
45155
+ index = Math.min(text.length, index + 2);
45156
+ } else if (text.startsWith(close, index)) {
45157
+ return index + close.length;
45158
+ } else {
45159
+ index += 1;
45160
+ }
45161
+ }
45162
+ return text.length;
45163
+ }
45164
+ function maskNestedLanguageCommentsAndStrings(text, languageId) {
45165
+ let masked = "";
45166
+ let copiedThrough = 0;
45167
+ for (let index = 0; index < text.length; ) {
45168
+ let end = null;
45169
+ if (text.startsWith("//", index)) {
45170
+ end = lineCommentEnd(text, index);
45171
+ } else if (text.startsWith("/*", index)) {
45172
+ end = nestedBlockCommentEnd(text, index);
45173
+ } else {
45174
+ end = languageId === "kotlin" ? kotlinLiteralEnd(text, index) : swiftStringEnd(text, index);
45175
+ }
45176
+ if (end === null) {
45177
+ index += 1;
45178
+ continue;
45179
+ }
45180
+ masked += text.slice(copiedThrough, index);
45181
+ masked += maskTriviaSpan(text, index, end);
45182
+ copiedThrough = end;
45183
+ index = end;
45184
+ }
45185
+ return masked + text.slice(copiedThrough);
45186
+ }
45187
+ function maskImportBindingTrivia(text, languageId) {
45188
+ if (languageId === "rust") {
45189
+ let masked2 = "";
45190
+ for (let index = 0; index < text.length; ) {
45191
+ const trivia = skipRustCommentOrLiteral(text, index);
45192
+ if (!trivia) {
45193
+ masked2 += text[index];
45194
+ index += 1;
45195
+ continue;
45196
+ }
45197
+ masked2 += text.slice(index, trivia.end).replace(/[^\r\n]/g, " ");
45198
+ index = trivia.end;
45199
+ }
45200
+ return masked2;
45201
+ }
45202
+ if (languageId === "kotlin" || languageId === "swift") {
45203
+ return maskNestedLanguageCommentsAndStrings(text, languageId);
45204
+ }
45205
+ const masked = maskJsLikeCommentsAndStrings(text);
45206
+ if (languageId !== "php")
45207
+ return masked;
45208
+ return masked.replace(/#[^\r\n]*/g, (comment) => " ".repeat(comment.length));
45209
+ }
45210
+ function attributeNamedBindingRanges(args) {
45211
+ const { bindings, fromIndex, text, textStartIndex, source, alwaysAliased } = args;
45212
+ const slots = buildRoleSlots(bindings, fromIndex, alwaysAliased);
45213
+ if (!slots.length)
45214
+ return;
45215
+ const matches = matchRoleSequenceBackward(text, slots);
45216
+ if (!matches)
45217
+ return;
45218
+ const lineStarts = collectLineStartOffsets(source);
45219
+ for (let index = 0; index < slots.length; index++) {
45220
+ const slot = slots[index];
45221
+ const binding = bindings[slot.bindingIndex];
45222
+ if (binding.kind !== "named")
45223
+ continue;
45224
+ const range = toSourceRange(lineStarts, textStartIndex, matches[index]);
45225
+ binding[slot.field] = range;
45226
+ if (slot.field === "importedRange" && binding.local === binding.imported && !binding.explicitAlias && binding.localRange === void 0) {
45227
+ binding.localRange = range;
45228
+ }
45229
+ }
45230
+ }
45231
+ function buildRoleSlots(bindings, fromIndex, alwaysAliased) {
45232
+ const slots = [];
45233
+ for (let index = fromIndex; index < bindings.length; index++) {
45234
+ const binding = bindings[index];
45235
+ if (binding.kind !== "named")
45236
+ continue;
45237
+ if (binding.importedRange !== void 0 || binding.localRange !== void 0)
45238
+ continue;
45239
+ if (alwaysAliased) {
45240
+ slots.push({ bindingIndex: index, field: "localRange", name: binding.local });
45241
+ slots.push({ bindingIndex: index, field: "importedRange", name: binding.imported });
45242
+ } else if (binding.local === binding.imported && !binding.explicitAlias) {
45243
+ slots.push({ bindingIndex: index, field: "importedRange", name: binding.imported });
45244
+ } else {
45245
+ slots.push({ bindingIndex: index, field: "importedRange", name: binding.imported });
45246
+ slots.push({ bindingIndex: index, field: "localRange", name: binding.local });
45247
+ }
45248
+ }
45249
+ return slots;
45250
+ }
45251
+ function matchRoleSequenceBackward(text, slots) {
45252
+ const matches = new Array(slots.length).fill(null);
45253
+ let upperBound = text.length;
45254
+ for (let index = slots.length - 1; index >= 0; index--) {
45255
+ const match = findRightmostWholeWordOccurrence(text, slots[index].name, upperBound);
45256
+ if (!match)
45257
+ return null;
45258
+ matches[index] = match;
45259
+ upperBound = match.start;
45260
+ }
45261
+ return matches;
45262
+ }
45263
+ function isIdentifierContinuationBefore(text, index) {
45264
+ if (index <= 0)
45265
+ return false;
45266
+ let charIndex = index - 1;
45267
+ const code = text.charCodeAt(charIndex);
45268
+ if (code >= 56320 && code <= 57343 && charIndex > 0) {
45269
+ const highCode = text.charCodeAt(charIndex - 1);
45270
+ if (highCode >= 55296 && highCode <= 56319)
45271
+ charIndex -= 1;
45272
+ }
45273
+ const codePoint = text.codePointAt(charIndex);
45274
+ return codePoint !== void 0 && IDENTIFIER_CONTINUATION_PATTERN.test(String.fromCodePoint(codePoint));
45275
+ }
45276
+ function isIdentifierContinuationAt(text, index) {
45277
+ if (index >= text.length)
45278
+ return false;
45279
+ const codePoint = text.codePointAt(index);
45280
+ return codePoint !== void 0 && IDENTIFIER_CONTINUATION_PATTERN.test(String.fromCodePoint(codePoint));
45281
+ }
45282
+ function isWholeWordMatchAt(text, start, word) {
45283
+ if (isIdentifierContinuationBefore(text, start))
45284
+ return false;
45285
+ if (isIdentifierContinuationAt(text, start + word.length))
45286
+ return false;
45287
+ return true;
45288
+ }
45289
+ function findRightmostWholeWordOccurrence(text, word, beforeIndex) {
45290
+ if (!word)
45291
+ return null;
45292
+ let best = null;
45293
+ let searchFrom = 0;
45294
+ for (; ; ) {
45295
+ const start = text.indexOf(word, searchFrom);
45296
+ if (start === -1)
45297
+ break;
45298
+ const end = start + word.length;
45299
+ if (end > beforeIndex)
45300
+ break;
45301
+ searchFrom = start + 1;
45302
+ if (isWholeWordMatchAt(text, start, word))
45303
+ best = { start, end };
45304
+ }
45305
+ return best;
45306
+ }
45307
+ function toSourceRange(lineStarts, textStartIndex, match) {
45308
+ return sourceRangeFromOffsets(lineStarts, textStartIndex + match.start, textStartIndex + match.end);
45309
+ }
45310
+ function sourceRangeFromOffsets(lineStarts, startIndex, endIndex) {
45311
+ return {
45312
+ start: positionAtOffset(lineStarts, startIndex),
45313
+ end: positionAtOffset(lineStarts, endIndex)
45314
+ };
45315
+ }
45316
+ var IDENTIFIER_CONTINUATION_PATTERN;
45317
+ var init_binding_ranges = __esm({
45318
+ "dist/indexer/imports/binding-ranges.js"() {
45319
+ "use strict";
45320
+ init_import_statement_parsers();
45321
+ init_comments();
45322
+ init_lines();
45323
+ IDENTIFIER_CONTINUATION_PATTERN = /[\p{ID_Continue}$@]/u;
45324
+ }
45325
+ });
45326
+
45025
45327
  // dist/indexer/imports/graph-only.js
45026
45328
  async function collectGraphOnlyImports(context) {
45027
45329
  const entries = Array.from(extractGraphOnlyModuleSpecifiers(context.languageId, context.source));
@@ -45074,20 +45376,136 @@ function sourceForTextImportExtraction(context) {
45074
45376
  }
45075
45377
  return context.source;
45076
45378
  }
45077
- function splitNamedImports(namedBlock) {
45078
- return namedBlock.replace(/[{}]/g, "").split(",").map((spec) => spec.trim()).filter(Boolean);
45379
+ function tokenRange(source, lineStarts, index, token) {
45380
+ if (index < 0 || !token)
45381
+ return void 0;
45382
+ if (source.slice(index, index + token.length) !== token)
45383
+ return void 0;
45384
+ return {
45385
+ start: positionAtOffset(lineStarts, index),
45386
+ end: positionAtOffset(lineStarts, index + token.length)
45387
+ };
45388
+ }
45389
+ function splitNamedImportsWithOffsets(namedBlock) {
45390
+ const out = [];
45391
+ let cursor = 0;
45392
+ for (const raw of namedBlock.split(",")) {
45393
+ const leading = raw.length - raw.trimStart().length;
45394
+ const spec = raw.trim();
45395
+ if (spec)
45396
+ out.push({ spec, start: cursor + leading });
45397
+ cursor += raw.length + 1;
45398
+ }
45399
+ return out;
45400
+ }
45401
+ function closingBraceIndex(maskedSource, openingIndex) {
45402
+ let depth = 0;
45403
+ for (let index = openingIndex; index < maskedSource.length; index += 1) {
45404
+ const character = maskedSource[index];
45405
+ if (character === "{") {
45406
+ depth += 1;
45407
+ } else if (character === "}") {
45408
+ depth -= 1;
45409
+ if (depth === 0)
45410
+ return index;
45411
+ }
45412
+ }
45413
+ return -1;
45414
+ }
45415
+ function splitNamedRequireBindingsWithOffsets(source, maskedSource, blockStart, blockEnd) {
45416
+ const out = [];
45417
+ let specStart = blockStart;
45418
+ let braceDepth = 0;
45419
+ let bracketDepth = 0;
45420
+ let parenDepth = 0;
45421
+ const push = (end) => {
45422
+ const raw = source.slice(specStart, end);
45423
+ const leading = raw.length - raw.trimStart().length;
45424
+ const spec = raw.trim();
45425
+ if (spec)
45426
+ out.push({ spec, start: specStart - blockStart + leading });
45427
+ };
45428
+ for (let index = blockStart; index < blockEnd; index += 1) {
45429
+ const character = maskedSource[index];
45430
+ if (character === "{")
45431
+ braceDepth += 1;
45432
+ else if (character === "}")
45433
+ braceDepth -= 1;
45434
+ else if (character === "[")
45435
+ bracketDepth += 1;
45436
+ else if (character === "]")
45437
+ bracketDepth -= 1;
45438
+ else if (character === "(")
45439
+ parenDepth += 1;
45440
+ else if (character === ")")
45441
+ parenDepth -= 1;
45442
+ else if (character === "," && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
45443
+ push(index);
45444
+ specStart = index + 1;
45445
+ }
45446
+ }
45447
+ push(blockEnd);
45448
+ return out;
45079
45449
  }
45080
45450
  function parseNamedImportSpecifier(spec) {
45081
45451
  const typeOnlyMatch = spec.match(TYPE_NAMED_IMPORT_SPECIFIER_PATTERN);
45082
45452
  if (typeOnlyMatch) {
45083
45453
  const imported2 = typeOnlyMatch[1];
45084
- return { imported: imported2, local: typeOnlyMatch[2] ?? imported2, typeOnly: true };
45454
+ const importedOffset = /^type\s+/.exec(spec)[0].length;
45455
+ if (typeOnlyMatch[2] !== void 0) {
45456
+ const local = typeOnlyMatch[2];
45457
+ return {
45458
+ imported: imported2,
45459
+ local,
45460
+ typeOnly: true,
45461
+ importedOffset,
45462
+ localOffset: spec.length - local.length,
45463
+ explicitAlias: true
45464
+ };
45465
+ }
45466
+ return {
45467
+ imported: imported2,
45468
+ local: imported2,
45469
+ typeOnly: true,
45470
+ importedOffset,
45471
+ localOffset: importedOffset,
45472
+ explicitAlias: false
45473
+ };
45085
45474
  }
45086
45475
  const namedMatch = spec.match(NAMED_IMPORT_SPECIFIER_PATTERN);
45087
45476
  if (!namedMatch)
45088
45477
  return null;
45089
45478
  const imported = namedMatch[1];
45090
- return { imported, local: namedMatch[2] ?? imported, typeOnly: false };
45479
+ if (namedMatch[2] !== void 0) {
45480
+ const local = namedMatch[2];
45481
+ return {
45482
+ imported,
45483
+ local,
45484
+ typeOnly: false,
45485
+ importedOffset: 0,
45486
+ localOffset: spec.length - local.length,
45487
+ explicitAlias: true
45488
+ };
45489
+ }
45490
+ return { imported, local: imported, typeOnly: false, importedOffset: 0, localOffset: 0, explicitAlias: false };
45491
+ }
45492
+ function parseNamedRequireSpecifier(spec) {
45493
+ const bindingSpec = spec.replace(/\s*=\s*[\s\S]*$/u, "").trimEnd();
45494
+ const namedMatch = bindingSpec.match(NAMED_REQUIRE_SPECIFIER_PATTERN);
45495
+ if (!namedMatch)
45496
+ return null;
45497
+ const imported = namedMatch[1];
45498
+ if (namedMatch[2] !== void 0) {
45499
+ const local = namedMatch[2];
45500
+ return {
45501
+ imported,
45502
+ local,
45503
+ importedOffset: 0,
45504
+ localOffset: bindingSpec.length - local.length,
45505
+ explicitAlias: true
45506
+ };
45507
+ }
45508
+ return { imported, local: imported, importedOffset: 0, localOffset: 0, explicitAlias: false };
45091
45509
  }
45092
45510
  function matchStartsInCode2(maskedSource, match) {
45093
45511
  const index = match.index;
@@ -45102,24 +45520,34 @@ function matchStartsInCode2(maskedSource, match) {
45102
45520
  }
45103
45521
  return true;
45104
45522
  }
45105
- async function collectEsImports(context, source, maskedSource) {
45523
+ async function collectEsImports(context, source, maskedSource, lineStarts) {
45106
45524
  const typeOnlyImport = /\bimport\s+type\b/;
45107
45525
  const fromPattern = /^\s*import\s+([^\n;]*?)\s+from\s+(["'])(?<module>[^"']+)\2/gm;
45108
45526
  for (const match of source.matchAll(fromPattern)) {
45109
45527
  if (!matchStartsInCode2(maskedSource, match))
45110
45528
  continue;
45111
- const clause = match[1].trim().replace(/^type\s+/, "");
45112
45529
  const moduleSpecifier = match.groups?.module;
45113
45530
  if (!moduleSpecifier)
45114
45531
  continue;
45532
+ const importPrefix = /^\s*import\s+/.exec(match[0]);
45533
+ const clauseStart = importPrefix && match.index !== void 0 ? match.index + importPrefix[0].length : -1;
45534
+ const clauseRaw = match[1];
45535
+ const leading = clauseRaw.length - clauseRaw.trimStart().length;
45536
+ const trimmedClause = clauseRaw.trim();
45537
+ const typePrefix = /^type\s+/.exec(trimmedClause);
45538
+ const clause = typePrefix ? trimmedClause.slice(typePrefix[0].length) : trimmedClause;
45539
+ const bodyStart = clauseStart < 0 ? -1 : clauseStart + leading + (typePrefix ? typePrefix[0].length : 0);
45115
45540
  const typeOnly = typeOnlyImport.test(match[0]);
45116
45541
  const resolved = await context.resolveFrom(moduleSpecifier);
45117
45542
  const namespaceMatch = clause.match(NAMESPACE_IMPORT_PATTERN);
45118
45543
  if (namespaceMatch) {
45544
+ const localNS = namespaceMatch[1];
45545
+ const localRange = bodyStart < 0 ? void 0 : tokenRange(source, lineStarts, bodyStart + namespaceMatch[0].indexOf(localNS), localNS);
45119
45546
  context.pushBinding({
45120
45547
  kind: "namespace",
45121
- localNS: namespaceMatch[1],
45548
+ localNS,
45122
45549
  from: moduleSpecifier,
45550
+ ...localRange ? { localRange } : {},
45123
45551
  resolved,
45124
45552
  typeOnly
45125
45553
  });
@@ -45128,33 +45556,44 @@ async function collectEsImports(context, source, maskedSource) {
45128
45556
  const namedBlockMatch = clause.match(/\{(?<named>[^}]*)\}/);
45129
45557
  const defaultPart = namedBlockMatch?.index === void 0 ? clause.split(",", 1)[0].trim() : clause.slice(0, namedBlockMatch.index).replace(/,\s*$/, "").trim();
45130
45558
  if (defaultPart) {
45559
+ const localRange = bodyStart < 0 ? void 0 : tokenRange(source, lineStarts, bodyStart + clause.indexOf(defaultPart), defaultPart);
45131
45560
  context.pushBinding({
45132
45561
  kind: "default",
45133
45562
  local: defaultPart,
45134
45563
  from: moduleSpecifier,
45564
+ ...localRange ? { localRange } : {},
45135
45565
  resolved,
45136
45566
  typeOnly
45137
45567
  });
45138
45568
  }
45139
- const namedBlock = namedBlockMatch?.groups?.named ?? "";
45140
- for (const spec of splitNamedImports(namedBlock)) {
45141
- const namedImport = parseNamedImportSpecifier(spec);
45142
- if (!namedImport)
45143
- continue;
45144
- const bindingTypeOnly = typeOnly || namedImport.typeOnly;
45145
- context.pushBinding({
45146
- kind: "named",
45147
- local: namedImport.local,
45148
- imported: namedImport.imported,
45149
- from: moduleSpecifier,
45150
- resolved,
45151
- typeOnly: bindingTypeOnly
45152
- });
45569
+ if (namedBlockMatch?.index !== void 0 && bodyStart >= 0) {
45570
+ const namedBlockContentStart = bodyStart + namedBlockMatch.index + namedBlockMatch[0].indexOf("{") + 1;
45571
+ for (const { spec, start } of splitNamedImportsWithOffsets(namedBlockMatch.groups?.named ?? "")) {
45572
+ const namedImport = parseNamedImportSpecifier(spec);
45573
+ if (!namedImport)
45574
+ continue;
45575
+ const specStart = namedBlockContentStart + start;
45576
+ const bindingTypeOnly = typeOnly || namedImport.typeOnly;
45577
+ const importedRange = tokenRange(source, lineStarts, specStart + namedImport.importedOffset, namedImport.imported);
45578
+ const localRange = tokenRange(source, lineStarts, specStart + namedImport.localOffset, namedImport.local);
45579
+ context.pushBinding({
45580
+ kind: "named",
45581
+ local: namedImport.local,
45582
+ imported: namedImport.imported,
45583
+ from: moduleSpecifier,
45584
+ ...namedImport.explicitAlias ? { explicitAlias: true } : {},
45585
+ ...importedRange ? { importedRange } : {},
45586
+ ...localRange ? { localRange } : {},
45587
+ resolved,
45588
+ typeOnly: bindingTypeOnly
45589
+ });
45590
+ }
45153
45591
  }
45154
45592
  }
45155
45593
  }
45156
- async function collectCommonJsRequireDeclarations(context, source, maskedSource) {
45594
+ async function collectCommonJsRequireDeclarations(context, source, maskedSource, lineStarts) {
45157
45595
  const defaultRequirePattern = DEFAULT_REQUIRE_PATTERN;
45596
+ const defaultRequirePrefix = /(?:^|[;{}])\s*(?:export\s+)?(?:const|let|var)\s+/;
45158
45597
  for (const match of source.matchAll(defaultRequirePattern)) {
45159
45598
  if (!matchStartsInCode2(maskedSource, match))
45160
45599
  continue;
@@ -45162,43 +45601,53 @@ async function collectCommonJsRequireDeclarations(context, source, maskedSource)
45162
45601
  const moduleSpecifier = match.groups?.module;
45163
45602
  if (!moduleSpecifier)
45164
45603
  continue;
45604
+ const localStart = (match.index ?? 0) + (defaultRequirePrefix.exec(match[0])?.[0].length ?? 0);
45605
+ const localRange = tokenRange(source, lineStarts, localStart, local);
45165
45606
  const resolved = await context.resolveFrom(moduleSpecifier);
45166
45607
  context.pushBinding({
45167
45608
  kind: "default",
45168
45609
  local,
45169
45610
  from: moduleSpecifier,
45611
+ ...localRange ? { localRange } : {},
45170
45612
  resolved,
45171
45613
  mechanism: "cjs"
45172
45614
  });
45173
45615
  }
45174
- const namedRequirePattern = /(?:^|[;{}])\s*(?:export\s+)?(?:const|let|var)\s*\{([^}]+)\}\s*=\s*require\s*\(\s*(["'])(?<module>[^"']+)\2\s*\)/gm;
45175
- for (const match of source.matchAll(namedRequirePattern)) {
45176
- if (!matchStartsInCode2(maskedSource, match))
45616
+ for (const match of maskedSource.matchAll(NAMED_REQUIRE_DECLARATION_PATTERN)) {
45617
+ const openingIndex = (match.index ?? 0) + match[0].lastIndexOf("{");
45618
+ const closingIndex = closingBraceIndex(maskedSource, openingIndex);
45619
+ if (closingIndex < 0)
45177
45620
  continue;
45178
- const specs = match[1].split(",").map((spec) => spec.trim()).filter(Boolean);
45179
- const moduleSpecifier = match.groups?.module;
45621
+ const requireMatch = REQUIRE_AFTER_BINDING_PATTERN.exec(source.slice(closingIndex + 1));
45622
+ const moduleSpecifier = requireMatch?.groups?.module;
45180
45623
  if (!moduleSpecifier)
45181
45624
  continue;
45625
+ const namedBlockStart = openingIndex + 1;
45182
45626
  const resolved = await context.resolveFrom(moduleSpecifier);
45183
- for (const spec of specs) {
45184
- const namedMatch = spec.match(NAMED_REQUIRE_SPECIFIER_PATTERN);
45185
- if (!namedMatch)
45627
+ for (const { spec, start } of splitNamedRequireBindingsWithOffsets(source, maskedSource, namedBlockStart, closingIndex)) {
45628
+ const namedRequire = parseNamedRequireSpecifier(spec);
45629
+ if (!namedRequire)
45186
45630
  continue;
45187
- const imported = namedMatch[1];
45188
- const local = namedMatch[2] ?? imported;
45631
+ const specStart = namedBlockStart + start;
45632
+ const importedRange = tokenRange(source, lineStarts, specStart + namedRequire.importedOffset, namedRequire.imported);
45633
+ const localRange = tokenRange(source, lineStarts, specStart + namedRequire.localOffset, namedRequire.local);
45189
45634
  context.pushBinding({
45190
45635
  kind: "named",
45191
- local,
45192
- imported,
45636
+ local: namedRequire.local,
45637
+ imported: namedRequire.imported,
45193
45638
  from: moduleSpecifier,
45639
+ ...namedRequire.explicitAlias ? { explicitAlias: true } : {},
45640
+ ...importedRange ? { importedRange } : {},
45641
+ ...localRange ? { localRange } : {},
45194
45642
  resolved,
45195
45643
  mechanism: "cjs"
45196
45644
  });
45197
45645
  }
45198
45646
  }
45199
45647
  }
45200
- async function collectCommonJsImportEquals(context, source, maskedSource) {
45648
+ async function collectCommonJsImportEquals(context, source, maskedSource, lineStarts) {
45201
45649
  const importEqualsPattern = IMPORT_EQUALS_REQUIRE_PATTERN;
45650
+ const importEqualsPrefix = /(?:^|[;{}])\s*import\s+/;
45202
45651
  for (const match of source.matchAll(importEqualsPattern)) {
45203
45652
  if (!matchStartsInCode2(maskedSource, match))
45204
45653
  continue;
@@ -45206,42 +45655,50 @@ async function collectCommonJsImportEquals(context, source, maskedSource) {
45206
45655
  const moduleSpecifier = match.groups?.module;
45207
45656
  if (!moduleSpecifier)
45208
45657
  continue;
45658
+ const localStart = (match.index ?? 0) + (importEqualsPrefix.exec(match[0])?.[0].length ?? 0);
45659
+ const localRange = tokenRange(source, lineStarts, localStart, local);
45209
45660
  const resolved = await context.resolveFrom(moduleSpecifier);
45210
45661
  context.pushBinding({
45211
45662
  kind: "default",
45212
45663
  local,
45213
45664
  from: moduleSpecifier,
45665
+ ...localRange ? { localRange } : {},
45214
45666
  resolved,
45215
45667
  mechanism: "cjs"
45216
45668
  });
45217
45669
  }
45218
45670
  }
45219
- async function collectCommonJsImports(context, source, maskedSource) {
45220
- await collectCommonJsRequireDeclarations(context, source, maskedSource);
45221
- await collectCommonJsImportEquals(context, source, maskedSource);
45671
+ async function collectCommonJsImports(context, source, maskedSource, lineStarts) {
45672
+ await collectCommonJsRequireDeclarations(context, source, maskedSource, lineStarts);
45673
+ await collectCommonJsImportEquals(context, source, maskedSource, lineStarts);
45222
45674
  }
45223
45675
  async function collectJsTextValueRequireImports(context) {
45224
45676
  const source = sourceForTextImportExtraction(context);
45225
- await collectCommonJsRequireDeclarations(context, source, maskJsLikeCommentsStringsAndRegex(source));
45677
+ const lineStarts = collectLineStartOffsets(source);
45678
+ await collectCommonJsRequireDeclarations(context, source, maskJsLikeCommentsStringsAndRegex(source), lineStarts);
45226
45679
  }
45227
45680
  async function collectJsTextImports(context) {
45228
45681
  const source = sourceForTextImportExtraction(context);
45229
45682
  const maskedSource = maskJsLikeCommentsStringsAndRegex(source);
45230
- await collectEsImports(context, source, maskedSource);
45231
- await collectCommonJsImports(context, source, maskedSource);
45683
+ const lineStarts = collectLineStartOffsets(source);
45684
+ await collectEsImports(context, source, maskedSource, lineStarts);
45685
+ await collectCommonJsImports(context, source, maskedSource, lineStarts);
45232
45686
  }
45233
- var TYPE_NAMED_IMPORT_SPECIFIER_PATTERN, NAMED_IMPORT_SPECIFIER_PATTERN, NAMESPACE_IMPORT_PATTERN, DEFAULT_REQUIRE_PATTERN, NAMED_REQUIRE_SPECIFIER_PATTERN, IMPORT_EQUALS_REQUIRE_PATTERN;
45687
+ var TYPE_NAMED_IMPORT_SPECIFIER_PATTERN, NAMED_IMPORT_SPECIFIER_PATTERN, NAMESPACE_IMPORT_PATTERN, DEFAULT_REQUIRE_PATTERN, NAMED_REQUIRE_SPECIFIER_PATTERN, IMPORT_EQUALS_REQUIRE_PATTERN, NAMED_REQUIRE_DECLARATION_PATTERN, REQUIRE_AFTER_BINDING_PATTERN;
45234
45688
  var init_js_text_imports = __esm({
45235
45689
  "dist/indexer/imports/js-text-imports.js"() {
45236
45690
  "use strict";
45237
45691
  init_comments();
45238
45692
  init_identifiers();
45693
+ init_lines();
45239
45694
  TYPE_NAMED_IMPORT_SPECIFIER_PATTERN = new RegExp(String.raw`^type\s+(${ECMASCRIPT_IDENTIFIER_SOURCE})(?:\s+as\s+(${ECMASCRIPT_IDENTIFIER_SOURCE}))?$`, "u");
45240
45695
  NAMED_IMPORT_SPECIFIER_PATTERN = new RegExp(String.raw`^(${ECMASCRIPT_IDENTIFIER_SOURCE})(?:\s+as\s+(${ECMASCRIPT_IDENTIFIER_SOURCE}))?$`, "u");
45241
45696
  NAMESPACE_IMPORT_PATTERN = new RegExp(String.raw`^\*\s+as\s+(${ECMASCRIPT_IDENTIFIER_SOURCE})$`, "u");
45242
45697
  DEFAULT_REQUIRE_PATTERN = new RegExp(String.raw`(?:^|[;{}])\s*(?:export\s+)?(?:const|let|var)\s+(${ECMASCRIPT_IDENTIFIER_SOURCE})\s*=\s*require\s*\(\s*(["'])(?<module>[^"']+)\2\s*\)`, "gmu");
45243
45698
  NAMED_REQUIRE_SPECIFIER_PATTERN = new RegExp(String.raw`^(${ECMASCRIPT_IDENTIFIER_SOURCE})(?::\s*(${ECMASCRIPT_IDENTIFIER_SOURCE}))?$`, "u");
45244
45699
  IMPORT_EQUALS_REQUIRE_PATTERN = new RegExp(String.raw`(?:^|[;{}])\s*import\s+(${ECMASCRIPT_IDENTIFIER_SOURCE})\s*=\s*require\s*\(\s*(["'])(?<module>[^"']+)\2\s*\)`, "gmu");
45700
+ NAMED_REQUIRE_DECLARATION_PATTERN = /(?:^|[;{}])\s*(?:export\s+)?(?:const|let|var)\s*\{/gmu;
45701
+ REQUIRE_AFTER_BINDING_PATTERN = /^\s*=\s*require\s*\(\s*(["'])(?<module>[^"']+)\1\s*\)/u;
45245
45702
  }
45246
45703
  });
45247
45704
 
@@ -45325,27 +45782,40 @@ async function appendJavaTextImports(context) {
45325
45782
  continue;
45326
45783
  const fromValue = isStatic ? parts.slice(0, -1).join(".") : rawSpec;
45327
45784
  const resolved = await context.resolveFrom(fromValue);
45328
- context.pushBinding({
45785
+ const namedBinding = {
45329
45786
  kind: "named",
45330
45787
  local: imported,
45331
45788
  imported,
45332
45789
  from: fromValue,
45333
45790
  resolved,
45334
45791
  typeOnly: false
45335
- });
45792
+ };
45793
+ if (match.index !== void 0) {
45794
+ attributeNamedBindingRanges({
45795
+ bindings: [namedBinding],
45796
+ fromIndex: 0,
45797
+ text: maskImportBindingTrivia(match[0], context.languageId),
45798
+ textStartIndex: match.index,
45799
+ source: context.source
45800
+ });
45801
+ }
45802
+ context.pushBinding(namedBinding);
45336
45803
  }
45337
45804
  }
45338
45805
  async function appendKotlinTextImports(context) {
45339
45806
  if (context.languageId !== "kotlin" || context.getBindings().length) {
45340
45807
  return;
45341
45808
  }
45342
- const importPattern = new RegExp(String.raw`^\s*import\s+(${KOTLIN_DOTTED_NAME_SOURCE}(?:\.\*)?)(?:\s+as\s+(${KOTLIN_IDENTIFIER_SOURCE}))?\s*;?\s*$`, "gmu");
45343
- for (const match of context.source.matchAll(importPattern)) {
45809
+ const dottedNameWithTrivia = String.raw`${KOTLIN_IDENTIFIER_SOURCE}(?:\s*\.\s*${KOTLIN_IDENTIFIER_SOURCE})*`;
45810
+ const importPattern = new RegExp(String.raw`^\s*import\s+(${dottedNameWithTrivia}(?:\s*\.\s*\*)?)(?:\s+as\s+(${KOTLIN_IDENTIFIER_SOURCE}))?\s*;?\s*$`, "gmu");
45811
+ const maskedSource = maskImportBindingTrivia(context.source, context.languageId);
45812
+ for (const match of maskedSource.matchAll(importPattern)) {
45344
45813
  const rawSpec = match[1];
45345
45814
  if (!rawSpec)
45346
45815
  continue;
45347
- if (rawSpec.endsWith(".*")) {
45348
- const fromValue = rawSpec.slice(0, -2);
45816
+ const normalizedSpec = rawSpec.replace(/\s+/gu, "");
45817
+ if (normalizedSpec.endsWith(".*")) {
45818
+ const fromValue = normalizedSpec.slice(0, -2);
45349
45819
  const resolved2 = await context.resolveFrom(fromValue);
45350
45820
  context.pushBinding({
45351
45821
  kind: "star",
@@ -45355,19 +45825,30 @@ async function appendKotlinTextImports(context) {
45355
45825
  });
45356
45826
  continue;
45357
45827
  }
45358
- const parts = rawSpec.split(".");
45828
+ const parts = normalizedSpec.split(".");
45359
45829
  const imported = parts[parts.length - 1];
45360
45830
  if (!imported)
45361
45831
  continue;
45362
- const resolved = await context.resolveFrom(rawSpec);
45363
- context.pushBinding({
45832
+ const resolved = await context.resolveFrom(normalizedSpec);
45833
+ const namedBinding = {
45364
45834
  kind: "named",
45365
45835
  local: match[2] ?? imported,
45366
45836
  imported,
45367
- from: rawSpec,
45837
+ from: normalizedSpec,
45838
+ ...match[2] !== void 0 ? { explicitAlias: true } : {},
45368
45839
  resolved,
45369
45840
  typeOnly: false
45370
- });
45841
+ };
45842
+ if (match.index !== void 0) {
45843
+ attributeNamedBindingRanges({
45844
+ bindings: [namedBinding],
45845
+ fromIndex: 0,
45846
+ text: maskImportBindingTrivia(match[0], context.languageId),
45847
+ textStartIndex: match.index,
45848
+ source: context.source
45849
+ });
45850
+ }
45851
+ context.pushBinding(namedBinding);
45371
45852
  }
45372
45853
  }
45373
45854
  async function appendPhpComposerImplicitImports(context) {
@@ -45411,6 +45892,7 @@ function pushCsharpOverride(context, parsed, typeOnly, fromValue, resolved) {
45411
45892
  local: parsed.alias,
45412
45893
  imported,
45413
45894
  from: fromValue,
45895
+ explicitAlias: true,
45414
45896
  resolved,
45415
45897
  typeOnly
45416
45898
  });
@@ -45481,6 +45963,7 @@ async function pushJvmImportBinding(context, parsed, local, typeOnly) {
45481
45963
  local: local ?? parsed.imported,
45482
45964
  imported: parsed.imported,
45483
45965
  from: parsed.from,
45966
+ ...parsed.explicitAlias ? { explicitAlias: true } : {},
45484
45967
  resolved,
45485
45968
  typeOnly
45486
45969
  });
@@ -45588,7 +46071,15 @@ function scanRustImportStatements(sourceText) {
45588
46071
  }
45589
46072
  function buildRustBinding(parsed, resolved, typeOnly) {
45590
46073
  if (parsed.kind === "member") {
45591
- return { kind: "named", local: parsed.local, imported: parsed.imported, from: parsed.from, resolved, typeOnly };
46074
+ return {
46075
+ kind: "named",
46076
+ local: parsed.local,
46077
+ imported: parsed.imported,
46078
+ from: parsed.from,
46079
+ ...parsed.explicitAlias ? { explicitAlias: true } : {},
46080
+ resolved,
46081
+ typeOnly
46082
+ };
45592
46083
  }
45593
46084
  if (parsed.kind === "module") {
45594
46085
  return { kind: "namespace", localNS: parsed.local, from: parsed.from, resolved, typeOnly };
@@ -45621,7 +46112,15 @@ async function appendRustTextImports(context) {
45621
46112
  const parsedList = parseRustImportStatements(statement.text);
45622
46113
  if (!parsedList.length)
45623
46114
  continue;
46115
+ const bindingCountBefore = context.getBindings().length;
45624
46116
  await pushParsedRustImports(context, parsedList, false, statement.start, seen);
46117
+ attributeNamedBindingRanges({
46118
+ bindings: context.getBindings(),
46119
+ fromIndex: bindingCountBefore,
46120
+ text: maskImportBindingTrivia(statement.text, context.languageId),
46121
+ textStartIndex: statement.start,
46122
+ source: context.source
46123
+ });
45625
46124
  }
45626
46125
  }
45627
46126
  function isRustTestOnlyStatement(context, normalizedStmt, statementStartIndex) {
@@ -45681,6 +46180,7 @@ async function applyPhpStatementOverride(context, normalizedStmt, typeOnly) {
45681
46180
  local: entry.local,
45682
46181
  imported: entry.imported,
45683
46182
  from: entry.from,
46183
+ ...entry.explicitAlias ? { explicitAlias: true } : {},
45684
46184
  phpImportType: entry.importType,
45685
46185
  resolved,
45686
46186
  typeOnly,
@@ -45696,17 +46196,25 @@ async function applyStatementImportOverride(context, state, stmtText, typeOnly,
45696
46196
  const statementKey = statementImportOverrideKey(context.languageId, normalizedStmt, statementStartIndex);
45697
46197
  if (state.handledStatements.has(statementKey))
45698
46198
  return true;
46199
+ let parserStmt = normalizedStmt;
46200
+ const canMaskStrings = context.languageId !== "rust" && (context.languageId !== "php" || /^\s*use\b/i.test(normalizedStmt));
46201
+ if (canMaskStrings) {
46202
+ parserStmt = maskImportBindingTrivia(normalizedStmt, context.languageId);
46203
+ if (context.languageId === "csharp" || context.languageId === "java" || context.languageId === "kotlin") {
46204
+ parserStmt = parserStmt.replace(/\s*\.\s*/gu, ".");
46205
+ }
46206
+ }
45699
46207
  let handled = false;
45700
46208
  if (context.languageId === "csharp") {
45701
- handled = await applyCsharpStatementOverride(context, normalizedStmt, typeOnly);
46209
+ handled = await applyCsharpStatementOverride(context, parserStmt, typeOnly);
45702
46210
  } else if (context.languageId === "java") {
45703
- handled = await applyJavaStatementOverride(context, normalizedStmt, typeOnly);
46211
+ handled = await applyJavaStatementOverride(context, parserStmt, typeOnly);
45704
46212
  } else if (context.languageId === "kotlin") {
45705
- handled = await applyKotlinStatementOverride(context, normalizedStmt, typeOnly);
46213
+ handled = await applyKotlinStatementOverride(context, parserStmt, typeOnly);
45706
46214
  } else if (context.languageId === "rust") {
45707
46215
  handled = await applyRustStatementOverride(context, normalizedStmt, typeOnly, statementStartIndex);
45708
46216
  } else if (context.languageId === "php") {
45709
- handled = await applyPhpStatementOverride(context, normalizedStmt, typeOnly);
46217
+ handled = await applyPhpStatementOverride(context, parserStmt, typeOnly);
45710
46218
  }
45711
46219
  if (!handled)
45712
46220
  return false;
@@ -45720,20 +46228,21 @@ function statementImportOverrideKey(languageId, normalizedStmt, statementStartIn
45720
46228
  return normalizedStmt;
45721
46229
  }
45722
46230
  function appendImplicitImportBinding(context, args) {
45723
- const { from, resolved, typeOnly, stmtText, alias, wildcard } = args;
46231
+ const { from, resolved, typeOnly, stmtText, stmtStartIndex, source, alias, wildcard } = args;
46232
+ const pushNamed = (binding, alwaysAliased) => pushNamedImplicitBinding(context, binding, stmtText, stmtStartIndex, source, alwaysAliased);
45724
46233
  if (context.languageId === "java") {
45725
46234
  const parts = from.split(".");
45726
46235
  const last = parts[parts.length - 1];
45727
46236
  if (last === "*") {
45728
46237
  context.pushBinding({ kind: "star", from, resolved, typeOnly });
45729
46238
  } else if (last) {
45730
- context.pushBinding({ kind: "named", local: last, imported: last, from, resolved, typeOnly });
46239
+ pushNamed({ kind: "named", local: last, imported: last, from, resolved, typeOnly });
45731
46240
  }
45732
46241
  } else if (context.languageId === "csharp") {
45733
46242
  if (alias) {
45734
46243
  const fromParts = from.split(".");
45735
46244
  const imported = fromParts[fromParts.length - 1] ?? alias;
45736
- context.pushBinding({ kind: "named", local: alias, imported, from, resolved, typeOnly });
46245
+ pushNamed({ kind: "named", local: alias, imported, from, explicitAlias: true, resolved, typeOnly }, true);
45737
46246
  } else {
45738
46247
  context.pushBinding({ kind: "star", from, resolved, typeOnly });
45739
46248
  }
@@ -45766,7 +46275,7 @@ function appendImplicitImportBinding(context, args) {
45766
46275
  if (last === "*") {
45767
46276
  context.pushBinding({ kind: "star", from, resolved });
45768
46277
  } else {
45769
- context.pushBinding({ kind: "named", local: last, imported: last, from, resolved });
46278
+ pushNamed({ kind: "named", local: last, imported: last, from, resolved });
45770
46279
  }
45771
46280
  }
45772
46281
  } else if (context.languageId === "kotlin") {
@@ -45776,7 +46285,15 @@ function appendImplicitImportBinding(context, args) {
45776
46285
  const parts = from.split(".");
45777
46286
  const imported = parts[parts.length - 1];
45778
46287
  if (imported)
45779
- context.pushBinding({ kind: "named", local: alias ?? imported, imported, from, resolved, typeOnly });
46288
+ pushNamed({
46289
+ kind: "named",
46290
+ local: alias ?? imported,
46291
+ imported,
46292
+ from,
46293
+ ...alias !== void 0 ? { explicitAlias: true } : {},
46294
+ resolved,
46295
+ typeOnly
46296
+ });
45780
46297
  }
45781
46298
  } else if (context.languageId === "swift") {
45782
46299
  const parts = from.split(".");
@@ -45787,7 +46304,7 @@ function appendImplicitImportBinding(context, args) {
45787
46304
  context.pushBinding({ kind: "namespace", localNS: last, from, resolved, typeOnly });
45788
46305
  context.pushBinding({ kind: "star", from, resolved, typeOnly });
45789
46306
  } else {
45790
- context.pushBinding({ kind: "named", local: last, imported: last, from, resolved, typeOnly });
46307
+ pushNamed({ kind: "named", local: last, imported: last, from, resolved, typeOnly });
45791
46308
  }
45792
46309
  } else if (context.languageId === "zig") {
45793
46310
  if (alias)
@@ -45796,6 +46313,19 @@ function appendImplicitImportBinding(context, args) {
45796
46313
  context.pushBinding({ kind: "star", from, resolved, typeOnly });
45797
46314
  }
45798
46315
  }
46316
+ function pushNamedImplicitBinding(context, binding, stmtText, stmtStartIndex, source, alwaysAliased) {
46317
+ if (stmtStartIndex !== void 0 && source !== void 0) {
46318
+ attributeNamedBindingRanges({
46319
+ bindings: [binding],
46320
+ fromIndex: 0,
46321
+ text: maskImportBindingTrivia(stmtText, context.languageId),
46322
+ textStartIndex: stmtStartIndex,
46323
+ source,
46324
+ ...alwaysAliased !== void 0 ? { alwaysAliased } : {}
46325
+ });
46326
+ }
46327
+ context.pushBinding(binding);
46328
+ }
45799
46329
  var RUST_IMPORT_KEYWORD_PATTERN;
45800
46330
  var init_language_specific = __esm({
45801
46331
  "dist/indexer/imports/language-specific.js"() {
@@ -45805,6 +46335,7 @@ var init_language_specific = __esm({
45805
46335
  init_rust_test_modules();
45806
46336
  init_resolution();
45807
46337
  init_rust2();
46338
+ init_binding_ranges();
45808
46339
  RUST_IMPORT_KEYWORD_PATTERN = /^(?:pub(?:\s*\([^)]*\))?\s+)?(use|extern\s+crate|mod)\b/;
45809
46340
  }
45810
46341
  });
@@ -45912,45 +46443,51 @@ var init_shared2 = __esm({
45912
46443
 
45913
46444
  // dist/indexer/imports/native-captures.js
45914
46445
  function parseObjectPatternBindings(patternText) {
45915
- const trimmed = patternText.trim();
45916
- if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
45917
- return [];
45918
- const body = trimmed.slice(1, -1).trim();
45919
- if (!body)
46446
+ const maskedPatternText = maskJsLikeCommentsStringsAndRegex(patternText);
46447
+ const openBrace = maskedPatternText.indexOf("{");
46448
+ const closeBrace = maskedPatternText.lastIndexOf("}");
46449
+ if (openBrace < 0 || closeBrace <= openBrace)
45920
46450
  return [];
45921
- const parts = body.split(",").map((part) => part.trim()).filter(Boolean);
46451
+ const bodyStart = openBrace + 1;
45922
46452
  const out = [];
45923
- for (const part of parts) {
45924
- const withoutDefault = part.replace(/\s*=\s*.+$/, "").trim();
46453
+ for (const { spec, start } of splitNamedRequireBindingsWithOffsets(maskedPatternText, maskedPatternText, bodyStart, closeBrace)) {
46454
+ const specStart = bodyStart + start;
46455
+ const withoutDefault = spec.replace(/\s*=\s*[\s\S]*$/u, "").trim();
45925
46456
  const match = withoutDefault.match(OBJECT_PATTERN_BINDING_PATTERN);
45926
46457
  if (!match)
45927
46458
  continue;
45928
46459
  const imported = match[1];
45929
46460
  const local = match[2] ?? imported;
45930
- out.push({ imported, local });
46461
+ const importedOffset = specStart + withoutDefault.indexOf(imported);
46462
+ const localOffset = match[2] === void 0 ? importedOffset : specStart + withoutDefault.lastIndexOf(local);
46463
+ out.push({ imported, local, importedOffset, localOffset, explicitAlias: match[2] !== void 0 });
45931
46464
  }
45932
46465
  return out;
45933
46466
  }
45934
- async function pushTextObjectPatternBindings(context, patterns, from, typeOnly) {
46467
+ async function pushTextObjectPatternBindings(context, patterns, from, typeOnly, byteIndexMap, lineStarts) {
45935
46468
  if (!from)
45936
46469
  return;
45937
46470
  for (const pattern of patterns) {
45938
46471
  if (pattern.nodeType !== "object_pattern")
45939
46472
  continue;
45940
46473
  const resolved = await context.resolveFrom(from);
45941
- for (const binding of parseObjectPatternBindings(pattern.text)) {
45942
- context.pushBinding({
45943
- kind: "named",
45944
- local: binding.local,
45945
- imported: binding.imported,
45946
- from,
45947
- resolved,
45948
- typeOnly
45949
- });
45950
- }
46474
+ const patternStartIndex = stringIndexForByte(byteIndexMap, pattern.start.index);
46475
+ const patternBindings = parseObjectPatternBindings(pattern.text).map((binding) => ({
46476
+ kind: "named",
46477
+ local: binding.local,
46478
+ imported: binding.imported,
46479
+ from,
46480
+ ...binding.explicitAlias ? { explicitAlias: true } : {},
46481
+ importedRange: sourceRangeFromOffsets(lineStarts, patternStartIndex + binding.importedOffset, patternStartIndex + binding.importedOffset + binding.imported.length),
46482
+ localRange: sourceRangeFromOffsets(lineStarts, patternStartIndex + binding.localOffset, patternStartIndex + binding.localOffset + binding.local.length),
46483
+ resolved,
46484
+ typeOnly
46485
+ }));
46486
+ for (const binding of patternBindings)
46487
+ context.pushBinding(binding);
45951
46488
  }
45952
46489
  }
45953
- function pushNamespaceBinding(context, caps, stmtText, from, resolved, typeOnly) {
46490
+ function pushNamespaceBinding(context, caps, stmtText, from, resolved, typeOnly, byteIndexMap) {
45954
46491
  const namespaceCapture = caps["ns"];
45955
46492
  if (!namespaceCapture)
45956
46493
  return;
@@ -45978,11 +46515,12 @@ function pushNamespaceBinding(context, caps, stmtText, from, resolved, typeOnly)
45978
46515
  kind: "namespace",
45979
46516
  localNS: namespaceCapture.text,
45980
46517
  from,
46518
+ localRange: rangeFromNativeCapture(namespaceCapture, byteIndexMap),
45981
46519
  resolved,
45982
46520
  typeOnly
45983
46521
  });
45984
46522
  }
45985
- async function pushStandardBindings(context, match, caps, stmtText, from, patternCount, typeOnly) {
46523
+ async function pushStandardBindings(context, match, caps, stmtText, from, patternCount, typeOnly, byteIndexMap, statementStartIndex) {
45986
46524
  if (!from)
45987
46525
  return;
45988
46526
  const resolved = await context.resolveFrom(from);
@@ -45992,21 +46530,27 @@ async function pushStandardBindings(context, match, caps, stmtText, from, patter
45992
46530
  kind: "default",
45993
46531
  local: defaultCapture.text,
45994
46532
  from,
46533
+ localRange: rangeFromNativeCapture(defaultCapture, byteIndexMap),
45995
46534
  resolved,
45996
46535
  typeOnly
45997
46536
  });
45998
46537
  }
45999
- pushNamespaceBinding(context, caps, stmtText, from, resolved, typeOnly);
46538
+ pushNamespaceBinding(context, caps, stmtText, from, resolved, typeOnly, byteIndexMap);
46000
46539
  const inames = capturesNamed(match, "iname");
46001
46540
  const aliases = capturesNamed(match, "alias");
46002
46541
  for (let i = 0; i < inames.length; i++) {
46003
46542
  const imported = inames[i].text;
46004
- const alias = aliases[i]?.text ?? imported;
46543
+ const importedRange = rangeFromNativeCapture(inames[i], byteIndexMap);
46544
+ const aliasCapture = aliases[i];
46545
+ const alias = aliasCapture?.text ?? imported;
46005
46546
  context.pushBinding({
46006
46547
  kind: "named",
46007
46548
  local: alias,
46008
46549
  imported,
46009
46550
  from,
46551
+ ...aliasCapture ? { explicitAlias: true } : {},
46552
+ importedRange,
46553
+ localRange: aliasCapture ? rangeFromNativeCapture(aliasCapture, byteIndexMap) : importedRange,
46010
46554
  resolved,
46011
46555
  typeOnly
46012
46556
  });
@@ -46017,12 +46561,15 @@ async function pushStandardBindings(context, match, caps, stmtText, from, patter
46017
46561
  resolved,
46018
46562
  typeOnly,
46019
46563
  stmtText,
46564
+ ...statementStartIndex !== void 0 ? { stmtStartIndex: statementStartIndex, source: context.source } : {},
46020
46565
  ...caps["alias"]?.text ? { alias: caps["alias"].text } : {},
46021
46566
  ...caps["wild"] ? { wildcard: true } : {}
46022
46567
  });
46023
46568
  }
46024
46569
  }
46025
46570
  async function collectNativeCaptureImportBindings(context, matches) {
46571
+ const byteIndexMap = buildByteToStringIndexMap(context.source);
46572
+ let lineStarts;
46026
46573
  for (const match of matches) {
46027
46574
  const caps = capturesByName(match);
46028
46575
  const statementCapture = caps["stmt"];
@@ -46035,20 +46582,29 @@ async function collectNativeCaptureImportBindings(context, matches) {
46035
46582
  }
46036
46583
  const from = caps["from"] ? unquote(caps["from"].text) : void 0;
46037
46584
  const patterns = capturesNamed(match, "pattern");
46038
- await pushTextObjectPatternBindings(context, patterns, from, statementTypeOnly);
46039
- await pushStandardBindings(context, match, caps, stmtText, from, patterns.length, typeOnly);
46585
+ if (patterns.length) {
46586
+ const rangeLineStarts = lineStarts ?? collectLineStartOffsets(context.source);
46587
+ lineStarts = rangeLineStarts;
46588
+ await pushTextObjectPatternBindings(context, patterns, from, statementTypeOnly, byteIndexMap, rangeLineStarts);
46589
+ }
46590
+ await pushStandardBindings(context, match, caps, stmtText, from, patterns.length, typeOnly, byteIndexMap, statementStartIndex);
46040
46591
  }
46041
46592
  }
46042
46593
  var OBJECT_PATTERN_BINDING_PATTERN;
46043
46594
  var init_native_captures = __esm({
46044
46595
  "dist/indexer/imports/native-captures.js"() {
46045
46596
  "use strict";
46597
+ init_byte_index();
46046
46598
  init_query_results();
46047
46599
  init_ast();
46600
+ init_comments();
46048
46601
  init_identifiers();
46602
+ init_lines();
46049
46603
  init_rust_test_modules();
46050
46604
  init_shared2();
46605
+ init_binding_ranges();
46051
46606
  init_language_specific();
46607
+ init_js_text_imports();
46052
46608
  OBJECT_PATTERN_BINDING_PATTERN = new RegExp(String.raw`^(${ECMASCRIPT_IDENTIFIER_SOURCE})(?::\s*(${ECMASCRIPT_IDENTIFIER_SOURCE}))?$`, "u");
46053
46609
  }
46054
46610
  });
@@ -46105,7 +46661,7 @@ async function pushStarImport(context, moduleSpec, moduleLevel) {
46105
46661
  moduleLevel
46106
46662
  });
46107
46663
  }
46108
- async function pushNamedImport(context, moduleSpec, imported, local, moduleLevel) {
46664
+ async function pushNamedImport(context, moduleSpec, imported, local, moduleLevel, explicitAlias) {
46109
46665
  const { relDots, mod } = splitRelativeModuleSpec(moduleSpec);
46110
46666
  const resolved = await resolvePythonModule(context.projectRoot, context.file, mod, relDots);
46111
46667
  const namespaceResolved = resolvePythonNamespaceMember(resolved, imported);
@@ -46125,6 +46681,7 @@ async function pushNamedImport(context, moduleSpec, imported, local, moduleLevel
46125
46681
  local,
46126
46682
  imported,
46127
46683
  from: moduleSpec,
46684
+ ...explicitAlias ? { explicitAlias: true } : {},
46128
46685
  resolved,
46129
46686
  mechanism: "python",
46130
46687
  moduleLevel
@@ -46167,20 +46724,21 @@ function isPythonModuleLevelImportPrefix(prefix) {
46167
46724
  return false;
46168
46725
  return true;
46169
46726
  }
46170
- function isModuleLevelKeywordInStrippedSource(strippedSrc, keywordStart) {
46171
- const lineStart = strippedSrc.lastIndexOf("\n", keywordStart - 1) + 1;
46172
- return isPythonModuleLevelImportPrefix(strippedSrc.slice(lineStart, keywordStart));
46727
+ function isModuleLevelKeywordInStrippedSource(maskedSrc, keywordStart) {
46728
+ const lineStart = maskedSrc.lastIndexOf("\n", keywordStart - 1) + 1;
46729
+ return isPythonModuleLevelImportPrefix(maskedSrc.slice(lineStart, keywordStart));
46173
46730
  }
46174
46731
  function normalizePythonImportStatement(statement) {
46175
46732
  return stripPythonCommentsAndStrings(statement).replace(/\\\r?\n[\t ]*/g, " ").trim();
46176
46733
  }
46177
- async function collectPythonImportStatement(context, statement, moduleLevel) {
46734
+ async function collectPythonImportStatement(context, statement, moduleLevel, statementStartIndex) {
46178
46735
  const normalized = normalizePythonImportStatement(statement);
46179
46736
  const fromMatch = normalized.match(/^from\s+([^\s]+)\s+import\s+([\s\S]+)$/u);
46180
46737
  if (fromMatch) {
46181
46738
  const moduleSpec = fromMatch[1];
46182
46739
  const importedList = fromMatch[2].trim().replace(/^\(\s*|\s*\)$/g, "");
46183
- for (const item of importedList.split(",").map((entry) => entry.trim()).filter(Boolean)) {
46740
+ const bindingCountBefore = context.getBindings().length;
46741
+ for (const item of maskPythonCommentsAndStrings(importedList).replace(/^\(\s*|\s*\)$/g, "").split(",").map((x) => x.trim()).filter(Boolean)) {
46184
46742
  if (item === "*") {
46185
46743
  await pushStarImport(context, moduleSpec, moduleLevel);
46186
46744
  continue;
@@ -46189,7 +46747,17 @@ async function collectPythonImportStatement(context, statement, moduleLevel) {
46189
46747
  if (!aliasMatch)
46190
46748
  continue;
46191
46749
  const imported = aliasMatch[1];
46192
- await pushNamedImport(context, moduleSpec, imported, aliasMatch[2] ?? imported, moduleLevel);
46750
+ await pushNamedImport(context, moduleSpec, imported, aliasMatch[2] ?? imported, moduleLevel, aliasMatch[2] !== void 0);
46751
+ }
46752
+ if (statementStartIndex !== void 0) {
46753
+ const searchText = maskPythonCommentsAndStrings(statement);
46754
+ attributeNamedBindingRanges({
46755
+ bindings: context.getBindings(),
46756
+ fromIndex: bindingCountBefore,
46757
+ text: searchText,
46758
+ textStartIndex: statementStartIndex,
46759
+ source: context.source
46760
+ });
46193
46761
  }
46194
46762
  return true;
46195
46763
  }
@@ -46214,17 +46782,20 @@ async function collectPythonImportsFromNativeMatches(context, matches) {
46214
46782
  const lineStart = context.source.lastIndexOf("\n", startIndex - 1) + 1;
46215
46783
  const prefix = context.source.slice(lineStart, startIndex);
46216
46784
  const moduleLevel = isPythonModuleLevelImportPrefix(prefix);
46217
- await collectPythonImportStatement(context, statementCapture.text, moduleLevel);
46785
+ await collectPythonImportStatement(context, statementCapture.text, moduleLevel, startIndex);
46218
46786
  }
46219
46787
  }
46220
46788
  async function collectPythonImportsFromSource(context) {
46221
- const pySrc = stripPythonCommentsAndStrings(context.source);
46222
- const fromLinePattern = /(^[\t ]*|;[\t ]*)from\s+([^\s]+)\s+import\s+([^\n;#]+)/gm;
46789
+ const pySrc = maskPythonCommentsAndStrings(context.source);
46790
+ const fromLinePattern = /(^[\t ]*|;[\t ]*)from\s+([^\s]+)\s+import\s+(\([\s\S]*?\)|[^\n;#]+)/gm;
46223
46791
  for (const match of pySrc.matchAll(fromLinePattern)) {
46224
46792
  const keywordStart = match.index + match[1].length;
46225
46793
  const mod = match[2].trim();
46226
46794
  const moduleLevel = isModuleLevelKeywordInStrippedSource(pySrc, keywordStart);
46227
- const items = match[3].split(",").map((item) => item.trim());
46795
+ const listText = match[3];
46796
+ const bindingListText = maskPythonCommentsAndStrings(listText);
46797
+ const bindingCountBefore = context.getBindings().length;
46798
+ const items = bindingListText.replace(/^\(\s*|\s*\)$/g, "").split(",").map((item) => item.trim());
46228
46799
  for (const item of items) {
46229
46800
  if (item === "*") {
46230
46801
  await pushStarImport(context, mod, moduleLevel);
@@ -46235,8 +46806,16 @@ async function collectPythonImportsFromSource(context) {
46235
46806
  continue;
46236
46807
  const imported = aliasMatch[1];
46237
46808
  const local = aliasMatch[2] ?? imported;
46238
- await pushNamedImport(context, mod, imported, local, moduleLevel);
46809
+ await pushNamedImport(context, mod, imported, local, moduleLevel, aliasMatch[2] !== void 0);
46239
46810
  }
46811
+ const listStart = match.index + match[0].length - listText.length;
46812
+ attributeNamedBindingRanges({
46813
+ bindings: context.getBindings(),
46814
+ fromIndex: bindingCountBefore,
46815
+ text: listText,
46816
+ textStartIndex: listStart,
46817
+ source: context.source
46818
+ });
46240
46819
  }
46241
46820
  const importPattern = PYTHON_MODULE_IMPORT_PATTERN;
46242
46821
  for (const match of pySrc.matchAll(importPattern)) {
@@ -46255,6 +46834,7 @@ var init_python3 = __esm({
46255
46834
  init_comments();
46256
46835
  init_identifiers();
46257
46836
  init_rust_test_modules();
46837
+ init_binding_ranges();
46258
46838
  PYTHON_NAMED_IMPORT_PATTERN = new RegExp(String.raw`^(${PYTHON_IDENTIFIER_SOURCE})(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
46259
46839
  PYTHON_MODULE_IMPORT_PATTERN = new RegExp(String.raw`(^[\t ]*|;[\t ]*)import\s+(${PYTHON_IDENTIFIER_SOURCE}(?:\.${PYTHON_IDENTIFIER_SOURCE})*)\s*(?:as\s+(${PYTHON_IDENTIFIER_SOURCE}))?`, "gmu");
46260
46840
  PYTHON_MODULE_LIST_ITEM_PATTERN = new RegExp(String.raw`^(${PYTHON_IDENTIFIER_SOURCE}(?:\.${PYTHON_IDENTIFIER_SOURCE})*)(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
@@ -46304,7 +46884,8 @@ async function collectImportsForFile(file2, projectRoot, opts) {
46304
46884
  file: file2,
46305
46885
  projectRoot,
46306
46886
  source: resolvedSource,
46307
- pushBinding: (binding) => imports.push(binding)
46887
+ pushBinding: (binding) => imports.push(binding),
46888
+ getBindings: () => imports
46308
46889
  };
46309
46890
  if (resolvedNativeQueries) {
46310
46891
  await collectPythonImportsFromNativeMatches(context, resolvedNativeQueries.importBindings);
@@ -46358,7 +46939,19 @@ async function collectImportsForFile(file2, projectRoot, opts) {
46358
46939
  await finalizeLanguageSpecificImports(languageContext);
46359
46940
  };
46360
46941
  const applyStatementOverride = async (stmtText, typeOnly, statementStartIndex) => {
46361
- return await applyStatementImportOverride(languageContext, statementOverrideState, stmtText, typeOnly, statementStartIndex);
46942
+ const bindingCountBefore = imports.length;
46943
+ const handled = await applyStatementImportOverride(languageContext, statementOverrideState, stmtText, typeOnly, statementStartIndex);
46944
+ if (handled && statementStartIndex !== void 0) {
46945
+ attributeNamedBindingRanges({
46946
+ bindings: imports,
46947
+ fromIndex: bindingCountBefore,
46948
+ text: maskImportBindingTrivia(stmtText, resolvedSup.id),
46949
+ textStartIndex: statementStartIndex,
46950
+ source: resolvedSource,
46951
+ alwaysAliased: resolvedSup.id === "csharp"
46952
+ });
46953
+ }
46954
+ return handled;
46362
46955
  };
46363
46956
  const runFallback = async () => {
46364
46957
  await collectJsTextImports({
@@ -46443,6 +47036,7 @@ var init_imports = __esm({
46443
47036
  init_document_links();
46444
47037
  init_comments();
46445
47038
  init_tree_sitter_native();
47039
+ init_binding_ranges();
46446
47040
  init_graph_only();
46447
47041
  init_js_text_imports();
46448
47042
  init_language_specific();
@@ -46734,6 +47328,13 @@ function buildScopeIndexFromSource(file2, source, support, imports = [], opts) {
46734
47328
  addPatternDecls(left, "local", addBindingToScope);
46735
47329
  return;
46736
47330
  }
47331
+ if (support.id === "zig" && node.type === "variable_declaration") {
47332
+ const name = node.namedChildren.find((child) => child.type === "identifier");
47333
+ const isImportDeclaration = name !== void 0 && hasImportBinding(name) && /@(?:import|cImport)\s*\(/.test(sliceText(node, source));
47334
+ if (name && !isImportDeclaration)
47335
+ addBindingToScope(name, "local");
47336
+ return;
47337
+ }
46737
47338
  for (const child of node.namedChildren) {
46738
47339
  if (child.type === "variable_declarator" || child.type === "var_spec" || child.type === "const_spec") {
46739
47340
  const name = child.childForFieldName("name");
@@ -46822,6 +47423,13 @@ function buildScopeIndexFromSource(file2, source, support, imports = [], opts) {
46822
47423
  extraBindings.push(buildBinding(name, "local"));
46823
47424
  }
46824
47425
  }
47426
+ if (node.type === "enum_assignment") {
47427
+ const name = node.childForFieldName("name");
47428
+ if (name)
47429
+ addDecl(name, "local");
47430
+ } else if (node.type === "property_identifier" && node.parent?.type === "enum_body") {
47431
+ addDecl(node, "local");
47432
+ }
46825
47433
  let pushed = false;
46826
47434
  if (support.createsFunctionScope(node)) {
46827
47435
  const scope = {
@@ -51384,8 +51992,8 @@ var init_options2 = __esm({
51384
51992
  init_project_files();
51385
51993
  init_tree_sitter_native();
51386
51994
  init_languages();
51387
- CORE_ALGORITHM_EPOCH = 12;
51388
- LANGUAGE_BEHAVIOR_EPOCH = 3;
51995
+ CORE_ALGORITHM_EPOCH = 18;
51996
+ LANGUAGE_BEHAVIOR_EPOCH = 6;
51389
51997
  }
51390
51998
  });
51391
51999
 
@@ -51671,7 +52279,28 @@ function isModuleIndex(value) {
51671
52279
  if (!value || typeof value !== "object")
51672
52280
  return false;
51673
52281
  const mod = value;
51674
- return typeof mod.file === "string" && Array.isArray(mod.exports) && Array.isArray(mod.imports) && Array.isArray(mod.locals);
52282
+ return typeof mod.file === "string" && Array.isArray(mod.exports) && Array.isArray(mod.imports) && mod.imports.every(hasValidImportBindingRanges) && Array.isArray(mod.locals);
52283
+ }
52284
+ function hasValidImportBindingRanges(value) {
52285
+ if (!value || typeof value !== "object")
52286
+ return false;
52287
+ const binding = value;
52288
+ return (binding.explicitAlias === void 0 || typeof binding.explicitAlias === "boolean") && isOptionalRange(binding.importedRange) && isOptionalRange(binding.localRange);
52289
+ }
52290
+ function isOptionalRange(value) {
52291
+ return value === void 0 || isRange(value);
52292
+ }
52293
+ function isRange(value) {
52294
+ if (!value || typeof value !== "object")
52295
+ return false;
52296
+ const range = value;
52297
+ return isPos(range.start) && isPos(range.end);
52298
+ }
52299
+ function isPos(value) {
52300
+ if (!value || typeof value !== "object")
52301
+ return false;
52302
+ const pos = value;
52303
+ return typeof pos.line === "number" && typeof pos.column === "number" && (pos.index === void 0 || typeof pos.index === "number");
51675
52304
  }
51676
52305
  function transformPersistedExportFromModule(projectRoot, entry, toRelative) {
51677
52306
  if (toRelative) {
@@ -56033,13 +56662,53 @@ function transformModule(root, module2, toRelative) {
56033
56662
  }))
56034
56663
  };
56035
56664
  }
56665
+ function transformSnapshotAnalysisReport(root, persistedProjectRoot, report, toRelative) {
56666
+ const reportFile = (file2) => {
56667
+ if (file2 === "unknown")
56668
+ return file2;
56669
+ if (!toRelative && path44.isAbsolute(file2) && !isFilePathWithinRoot(root, file2) && isFilePathWithinRoot(persistedProjectRoot, file2)) {
56670
+ return transformPath(root, cacheRelativePath(persistedProjectRoot, file2), false);
56671
+ }
56672
+ return transformPath(root, file2, toRelative);
56673
+ };
56674
+ const transformed = {};
56675
+ if (report.backend) {
56676
+ const backend = {
56677
+ ...report.backend,
56678
+ native: {
56679
+ ...report.backend.native,
56680
+ errors: report.backend.native.errors.map((error51) => ({ ...error51, file: reportFile(error51.file) }))
56681
+ }
56682
+ };
56683
+ if (report.backend.parser) {
56684
+ backend.parser = {
56685
+ ...report.backend.parser,
56686
+ files: report.backend.parser.files.map((entry) => ({
56687
+ ...entry,
56688
+ file: reportFile(entry.file)
56689
+ }))
56690
+ };
56691
+ }
56692
+ transformed.backend = backend;
56693
+ }
56694
+ if (report.graph) {
56695
+ transformed.graph = {
56696
+ ...report.graph,
56697
+ fallbackImportExtraction: {
56698
+ ...report.graph.fallbackImportExtraction,
56699
+ files: Object.fromEntries(Object.entries(report.graph.fallbackImportExtraction.files).map(([file2, entry]) => [reportFile(file2), entry]))
56700
+ }
56701
+ };
56702
+ }
56703
+ return transformed;
56704
+ }
56036
56705
  function transformSnapshotPaths(payload, root, toRelative) {
56037
56706
  const bloomFilters = payload.bloomFilters ? Object.fromEntries(Object.entries(payload.bloomFilters).map(([file2, filter]) => [transformPath(root, file2, toRelative), filter])) : void 0;
56038
56707
  const fileSignatures = Object.fromEntries(Object.entries(payload.fileSignatures ?? {}).map(([file2, signature]) => [
56039
56708
  transformPath(root, file2, toRelative),
56040
56709
  signature
56041
56710
  ]));
56042
- return {
56711
+ const transformed = {
56043
56712
  ...payload,
56044
56713
  graph: {
56045
56714
  nodes: payload.graph.nodes.map((node) => transformPath(root, node, toRelative)),
@@ -56060,6 +56729,10 @@ function transformSnapshotPaths(payload, root, toRelative) {
56060
56729
  ...bloomFilters ? { bloomFilters } : {},
56061
56730
  fileSignatures
56062
56731
  };
56732
+ if (payload.analysisReport) {
56733
+ transformed.analysisReport = transformSnapshotAnalysisReport(root, payload.projectRoot, payload.analysisReport, toRelative);
56734
+ }
56735
+ return transformed;
56063
56736
  }
56064
56737
  function migrateProjectSnapshotPayload(value, currentRoot) {
56065
56738
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -57046,7 +57719,7 @@ function isSymbolDef(value) {
57046
57719
  if (!value || typeof value !== "object")
57047
57720
  return false;
57048
57721
  const symbol2 = value;
57049
- return typeof symbol2.file === "string" && typeof symbol2.localName === "string" && isSymbolKind(symbol2.kind) && isRange(symbol2.range) && (symbol2.docstring === void 0 || typeof symbol2.docstring === "string") && (symbol2.lineSpan === void 0 || typeof symbol2.lineSpan === "number") && (symbol2.complexity === void 0 || typeof symbol2.complexity === "number");
57722
+ return typeof symbol2.file === "string" && typeof symbol2.localName === "string" && isSymbolKind(symbol2.kind) && isRange2(symbol2.range) && (symbol2.docstring === void 0 || typeof symbol2.docstring === "string") && (symbol2.lineSpan === void 0 || typeof symbol2.lineSpan === "number") && (symbol2.complexity === void 0 || typeof symbol2.complexity === "number");
57050
57723
  }
57051
57724
  function isImportBinding(value) {
57052
57725
  if (!value || typeof value !== "object")
@@ -57055,13 +57728,15 @@ function isImportBinding(value) {
57055
57728
  if (typeof binding.from !== "string" || !isResolvedImportTarget(binding.resolved) || !isOptionalBoolean(binding.typeOnly) || !isImportMechanism(binding.mechanism) || !isResolvedType(binding.resolvedType) || !isOptionalNumber(binding.confidence)) {
57056
57729
  return false;
57057
57730
  }
57058
- if (binding.kind === "default")
57059
- return typeof binding.local === "string";
57731
+ if (binding.kind === "default") {
57732
+ return typeof binding.local === "string" && isOptionalRange2(binding.localRange);
57733
+ }
57060
57734
  if (binding.kind === "named") {
57061
- return typeof binding.local === "string" && typeof binding.imported === "string" && (binding.phpImportType === void 0 || binding.phpImportType === "class" || binding.phpImportType === "function" || binding.phpImportType === "const");
57735
+ return typeof binding.local === "string" && typeof binding.imported === "string" && isOptionalBoolean(binding.explicitAlias) && isOptionalRange2(binding.importedRange) && isOptionalRange2(binding.localRange) && (binding.phpImportType === void 0 || binding.phpImportType === "class" || binding.phpImportType === "function" || binding.phpImportType === "const");
57736
+ }
57737
+ if (binding.kind === "namespace") {
57738
+ return typeof binding.localNS === "string" && isOptionalRange2(binding.localRange);
57062
57739
  }
57063
- if (binding.kind === "namespace")
57064
- return typeof binding.localNS === "string";
57065
57740
  return binding.kind === "star";
57066
57741
  }
57067
57742
  function isExportEntry(value) {
@@ -57098,16 +57773,19 @@ function isOptionalBoolean(value) {
57098
57773
  function isOptionalNumber(value) {
57099
57774
  return value === void 0 || typeof value === "number";
57100
57775
  }
57776
+ function isOptionalRange2(value) {
57777
+ return value === void 0 || isRange2(value);
57778
+ }
57101
57779
  function isSymbolKind(value) {
57102
57780
  return SNAPSHOT_SYMBOL_KINDS.has(value);
57103
57781
  }
57104
- function isRange(value) {
57782
+ function isRange2(value) {
57105
57783
  if (!value || typeof value !== "object")
57106
57784
  return false;
57107
57785
  const range = value;
57108
- return isPos(range.start) && isPos(range.end);
57786
+ return isPos2(range.start) && isPos2(range.end);
57109
57787
  }
57110
- function isPos(value) {
57788
+ function isPos2(value) {
57111
57789
  if (!value || typeof value !== "object")
57112
57790
  return false;
57113
57791
  const pos = value;
@@ -60544,8 +61222,9 @@ async function resolveMemberAccessDefinition(params) {
60544
61222
  });
60545
61223
  }
60546
61224
  }
60547
- const objDef = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
60548
- if (objDef) {
61225
+ const receiver = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
61226
+ if (receiver) {
61227
+ const objDef = receiver.def;
60549
61228
  const targetContext = await ensureParsedContext(objDef.file, void 0, index.languageExtensions);
60550
61229
  const start = objDef.range.start;
60551
61230
  const targetPosition = {
@@ -60554,11 +61233,21 @@ async function resolveMemberAccessDefinition(params) {
60554
61233
  };
60555
61234
  const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
60556
61235
  const container = nameNode.parent;
61236
+ if (receiver.runtimeTypeOnly && container && container.type !== "enum_declaration" && container.type !== "internal_module" && container.type !== "module") {
61237
+ return null;
61238
+ }
60557
61239
  if (container) {
60558
61240
  const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
60559
61241
  if (targetModule) {
60560
61242
  const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
60561
- const memberDef = targetContext.sup.id === "java" ? findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier) : findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier);
61243
+ let memberDef;
61244
+ if (receiver.runtimeTypeOnly) {
61245
+ memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
61246
+ } else if (targetContext.sup.id === "java") {
61247
+ memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
61248
+ } else {
61249
+ memberDef = findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier, receiver.memberScope);
61250
+ }
60562
61251
  if (memberDef) {
60563
61252
  return okGoToResult(index, memberDef, {
60564
61253
  via: { exportedName: member },
@@ -60590,17 +61279,24 @@ async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
60590
61279
  if (constructor) {
60591
61280
  const result = await resolveExpression(constructor);
60592
61281
  if (result?.kind === "resolved") {
60593
- return result.def;
61282
+ return {
61283
+ def: result.def,
61284
+ memberScope: isJsTsLanguage(sup.id) ? "instance" : "any"
61285
+ };
60594
61286
  }
60595
61287
  }
60596
- if (isJsTsLanguage(sup.id)) {
60597
- if (sup.nodeTypes.identifier.includes(obj.type)) {
60598
- return null;
61288
+ const direct = await resolveExpression(obj);
61289
+ if (isJsTsLanguage(sup.id) && sup.nodeTypes.identifier.includes(obj.type)) {
61290
+ if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.Class) {
61291
+ return { def: direct.def, memberScope: "static" };
61292
+ }
61293
+ if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.TypeAlias) {
61294
+ return { def: direct.def, memberScope: "any", runtimeTypeOnly: true };
60599
61295
  }
61296
+ return null;
60600
61297
  }
60601
- const direct = await resolveExpression(obj);
60602
61298
  if (direct?.kind === "resolved") {
60603
- return direct.def;
61299
+ return { def: direct.def, memberScope: "any" };
60604
61300
  }
60605
61301
  return null;
60606
61302
  }
@@ -60802,8 +61498,9 @@ async function resolveMemberDefinitionForBase(index, baseDef, member) {
60802
61498
  return void 0;
60803
61499
  return findReceiverMemberDefinition(targetModule.locals, member, baseDef, container, targetContext, normalizeIdentifier);
60804
61500
  }
60805
- function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier) {
60806
- const containerHit = findLocalWithinNode(locals, member, container, normalizeIdentifier);
61501
+ function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier, memberScope = "any") {
61502
+ const memberPredicate = memberScope === "any" ? void 0 : (local) => hasStaticModifier(local, targetContext, container) === (memberScope === "static");
61503
+ const containerHit = memberScope === "any" ? findLocalWithinNode(locals, member, container, normalizeIdentifier) : findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, memberPredicate);
60807
61504
  if (containerHit)
60808
61505
  return containerHit;
60809
61506
  if (targetContext.sup.id !== "rust")
@@ -60811,17 +61508,35 @@ function findReceiverMemberDefinition(locals, member, receiverDef, container, ta
60811
61508
  const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
60812
61509
  return implNode ? findLocalWithinNode(locals, member, implNode, normalizeIdentifier) : void 0;
60813
61510
  }
60814
- function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name) {
61511
+ function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name, predicate) {
60815
61512
  const containerStart = node.startIndex;
60816
61513
  const containerEnd = node.endIndex;
60817
61514
  const normalizedMember = normalizeIdentifier(member);
60818
61515
  return locals.find((local) => {
60819
61516
  const startIndex = local.range.start.index;
60820
61517
  const endIndex = local.range.end.index;
60821
- return normalizeIdentifier(local.localName) === normalizedMember && startIndex !== void 0 && endIndex !== void 0 && startIndex >= containerStart && endIndex <= containerEnd;
61518
+ return normalizeIdentifier(local.localName) === normalizedMember && startIndex !== void 0 && endIndex !== void 0 && startIndex >= containerStart && endIndex <= containerEnd && (!predicate || predicate(local));
60822
61519
  });
60823
61520
  }
60824
- function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier) {
61521
+ function hasStaticModifier(local, targetContext, container) {
61522
+ const position = {
61523
+ row: local.range.start.line - 1,
61524
+ column: local.range.start.column - 1
61525
+ };
61526
+ let current = targetContext.tree.rootNode.descendantForPosition(position, position);
61527
+ while (current && current !== container) {
61528
+ for (let childIndex = 0; ; childIndex += 1) {
61529
+ const child = current.child(childIndex);
61530
+ if (!child)
61531
+ break;
61532
+ if (child.type === "static")
61533
+ return true;
61534
+ }
61535
+ current = current.parent;
61536
+ }
61537
+ return false;
61538
+ }
61539
+ function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, predicate) {
60825
61540
  const containerStart = container.startIndex;
60826
61541
  const containerEnd = container.endIndex;
60827
61542
  const normalizedMember = normalizeIdentifier(member);
@@ -60839,14 +61554,15 @@ function findDirectLocalWithinNode(locals, member, container, targetContext, nor
60839
61554
  let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
60840
61555
  let isDeclarationParent = true;
60841
61556
  while (current && current !== container) {
60842
- if (!isDeclarationParent && (current.type === "class_body" && current.parent !== container || NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
61557
+ const isDirectBody = current.type === "statement_block" && current.parent === container;
61558
+ if (!isDeclarationParent && !isDirectBody && (current.type === "class_body" && current.parent !== container || NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
60843
61559
  current = null;
60844
61560
  break;
60845
61561
  }
60846
61562
  isDeclarationParent = false;
60847
61563
  current = current.parent;
60848
61564
  }
60849
- if (current)
61565
+ if (current && (!predicate || predicate(local)))
60850
61566
  return local;
60851
61567
  }
60852
61568
  return void 0;
@@ -60885,6 +61601,7 @@ var init_navigation_goto = __esm({
60885
61601
  init_parse_context();
60886
61602
  init_navigation_provenance();
60887
61603
  init_navigation_resolve();
61604
+ init_types2();
60888
61605
  RUBY_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
60889
61606
  CSHARP_CONSTANT_SOURCE = String.raw`(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
60890
61607
  JAVA_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
@@ -68676,9 +69393,14 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
68676
69393
  ]);
68677
69394
  const canonicalSymbolName = parsed.sup.normalizeIdentifier(symbolName);
68678
69395
  const ranges = [];
69396
+ const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
69397
+ const importDeclarationKeys = importBindingDeclarationRangeKeys(moduleIndex);
68679
69398
  const walk = (node) => {
68680
69399
  if (identifierTypes.has(node.type) && parsed.sup.normalizeIdentifier(sliceText(node, parsed.source)) === canonicalSymbolName) {
68681
- ranges.push(toRange(node));
69400
+ const range = toRange(node);
69401
+ if (!importDeclarationKeys.has(rangeIdentityKey(range))) {
69402
+ ranges.push(range);
69403
+ }
68682
69404
  }
68683
69405
  for (const child of node.namedChildren) {
68684
69406
  walk(child);
@@ -68690,12 +69412,16 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
68690
69412
  return null;
68691
69413
  }
68692
69414
  }
68693
- async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, expectedDef, resolveDefinition, maxVerified) {
69415
+ async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, expectedDef, resolveDefinition, maxVerified, includeReference) {
68694
69416
  const collected = await collectNamedNodeReferences(index, fileId, symbolName);
68695
69417
  if (!collected)
68696
69418
  return [];
68697
69419
  const { ranges, parsed } = collected;
68698
69420
  const verified = [];
69421
+ const pushVerified = (reference) => {
69422
+ if (!includeReference || includeReference(reference))
69423
+ verified.push(reference);
69424
+ };
68699
69425
  for (const range of ranges) {
68700
69426
  if (maxVerified !== void 0 && maxVerified > 0 && verified.length >= maxVerified) {
68701
69427
  break;
@@ -68705,7 +69431,7 @@ async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, exp
68705
69431
  const reexported = resolveExport(index, exportFrom.entry.fromModule, exportFrom.entry.sourceSpecifier);
68706
69432
  if (reexported?.kind === "resolved") {
68707
69433
  if (sameDef(reexported.def, expectedDef, index.languageExtensions)) {
68708
- verified.push({ range, via: { reexport: true } });
69434
+ pushVerified({ range, via: { reexport: true } });
68709
69435
  }
68710
69436
  continue;
68711
69437
  }
@@ -68718,7 +69444,7 @@ async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, exp
68718
69444
  if (resolved.status !== "ok" || !resolved.definition)
68719
69445
  continue;
68720
69446
  if (sameDef(resolved.definition, expectedDef, index.languageExtensions)) {
68721
- verified.push({
69447
+ pushVerified({
68722
69448
  range,
68723
69449
  ...exportFrom?.isExportFrom ? { via: { reexport: true } } : {},
68724
69450
  ...resolved.provenance ? { provenance: resolved.provenance } : {}
@@ -68884,7 +69610,183 @@ function getCachedReferenceCandidateFiles(index, def, exportedNames, hasGlobalNa
68884
69610
  cache.set(key, sorted);
68885
69611
  return sorted;
68886
69612
  }
68887
- var EXPORT_FROM_PATTERN, NAMESPACE_EXPORT_PATTERN, EXPORT_FROM_SPECIFIER_PATTERN, referenceCandidateCache;
69613
+ function rangeIdentityKey(range) {
69614
+ return `${range.start.line}:${range.start.column}:${range.start.index ?? ""}:${range.end.line}:${range.end.column}:${range.end.index ?? ""}`;
69615
+ }
69616
+ function referenceSiteKey(file2, range) {
69617
+ return `${fileIdentityKey(file2)}:${rangeIdentityKey(range)}`;
69618
+ }
69619
+ function rangesEqual(left, right) {
69620
+ if (!left || !right)
69621
+ return false;
69622
+ return rangeIdentityKey(left) === rangeIdentityKey(right);
69623
+ }
69624
+ function bindingTokenRanges(imp) {
69625
+ if (imp.kind === "named") {
69626
+ return { importedRange: imp.importedRange, localRange: imp.localRange };
69627
+ }
69628
+ if (imp.kind === "default" || imp.kind === "namespace") {
69629
+ return { importedRange: void 0, localRange: imp.localRange };
69630
+ }
69631
+ return { importedRange: void 0, localRange: void 0 };
69632
+ }
69633
+ function importBindingReferenceSites(imp) {
69634
+ const sites = [];
69635
+ if (imp.kind === "named") {
69636
+ const { importedRange, localRange } = bindingTokenRanges(imp);
69637
+ if (importedRange) {
69638
+ sites.push({ range: importedRange, importBinding: "imported" });
69639
+ } else if (localRange && imp.local === imp.imported) {
69640
+ sites.push({ range: localRange, importBinding: "imported" });
69641
+ }
69642
+ if (localRange && !rangesEqual(localRange, importedRange)) {
69643
+ sites.push({ range: localRange, importBinding: "local" });
69644
+ }
69645
+ } else if (imp.kind === "default") {
69646
+ const { localRange } = bindingTokenRanges(imp);
69647
+ if (localRange) {
69648
+ sites.push({ range: localRange, importBinding: "local" });
69649
+ }
69650
+ }
69651
+ return sites;
69652
+ }
69653
+ function importBindingIdentityVerificationSites(imp) {
69654
+ const sites = importBindingReferenceSites(imp);
69655
+ if (imp.kind !== "named" || imp.local === imp.imported) {
69656
+ return sites;
69657
+ }
69658
+ const localSites = sites.filter((site) => site.importBinding === "local");
69659
+ return localSites.length > 0 ? localSites : sites;
69660
+ }
69661
+ function importBindingDeclarationRangeKeys(moduleIndex) {
69662
+ const keys = /* @__PURE__ */ new Set();
69663
+ if (!moduleIndex)
69664
+ return keys;
69665
+ for (const imp of moduleIndex.imports) {
69666
+ const { importedRange, localRange } = bindingTokenRanges(imp);
69667
+ if (importedRange)
69668
+ keys.add(rangeIdentityKey(importedRange));
69669
+ if (localRange)
69670
+ keys.add(rangeIdentityKey(localRange));
69671
+ }
69672
+ return keys;
69673
+ }
69674
+ function structurallyExportsDefinition(index, moduleFile, exportedName, def, definitionExportedNames, visited = /* @__PURE__ */ new Set()) {
69675
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(moduleFile, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
69676
+ const canonicalName = normalizeIdentifier(exportedName);
69677
+ const fileKey = fileIdentityKey(moduleFile);
69678
+ const visitKey = `${fileKey}::${canonicalName}`;
69679
+ if (visited.has(visitKey))
69680
+ return false;
69681
+ visited.add(visitKey);
69682
+ if (fileKey === fileIdentityKey(def.file) && definitionExportedNames.some((name) => normalizeIdentifier(name) === canonicalName)) {
69683
+ return true;
69684
+ }
69685
+ const moduleIndex = index.byFile.get(fileKey);
69686
+ if (!moduleIndex)
69687
+ return false;
69688
+ for (const entry of moduleIndex.exports) {
69689
+ if (entry.type === "local") {
69690
+ if (normalizeIdentifier(entry.exportedAs) === canonicalName && sameDef(entry.target, def, index.languageExtensions)) {
69691
+ return true;
69692
+ }
69693
+ continue;
69694
+ }
69695
+ if (entry.type === "reexport" && normalizeIdentifier(entry.exportedAs) === canonicalName) {
69696
+ if (structurallyExportsDefinition(index, entry.fromModule, entry.sourceSpecifier || exportedName, def, definitionExportedNames, visited)) {
69697
+ return true;
69698
+ }
69699
+ } else if (entry.type === "exportStar" && structurallyExportsDefinition(index, entry.fromModule, exportedName, def, definitionExportedNames, visited)) {
69700
+ return true;
69701
+ }
69702
+ }
69703
+ return false;
69704
+ }
69705
+ function isUnresolvedIndexedImport(index, imp, def, exportedNames) {
69706
+ if (typeof imp.resolved !== "string")
69707
+ return false;
69708
+ let importedName;
69709
+ if (imp.kind === "named")
69710
+ importedName = imp.imported;
69711
+ else if (imp.kind === "default")
69712
+ importedName = "default";
69713
+ else
69714
+ return false;
69715
+ if (!structurallyExportsDefinition(index, imp.resolved, importedName, def, exportedNames))
69716
+ return false;
69717
+ return !importCanReferenceDefinition(index, imp, def, exportedNames);
69718
+ }
69719
+ function parserDegradedCandidateFiles(index, scannedFiles) {
69720
+ const report = index.buildReport?.backend?.parser;
69721
+ if (!report)
69722
+ return { files: [], hasUnlistedCandidate: false };
69723
+ const scanned = new Set(scannedFiles.map((file2) => fileIdentityKey(file2)));
69724
+ const listed = new Set(report.files.map((entry) => fileIdentityKey(entry.file)));
69725
+ const affected = [];
69726
+ const seen = /* @__PURE__ */ new Set();
69727
+ for (const entry of report.files) {
69728
+ const key = fileIdentityKey(entry.file);
69729
+ if (!scanned.has(key) || seen.has(key))
69730
+ continue;
69731
+ seen.add(key);
69732
+ affected.push(entry.file);
69733
+ }
69734
+ let hasUnlistedCandidate = false;
69735
+ if (report.total > report.files.length) {
69736
+ for (const fileKey of scanned) {
69737
+ if (listed.has(fileKey))
69738
+ continue;
69739
+ hasUnlistedCandidate = true;
69740
+ break;
69741
+ }
69742
+ }
69743
+ return { files: affected, hasUnlistedCandidate };
69744
+ }
69745
+ function buildIndexedCandidateCoverage(args) {
69746
+ const { index, def, exportedNames, candidateFiles, scannedFiles, truncated } = args;
69747
+ const reasons = [];
69748
+ const affectedFiles = [];
69749
+ const affectedSeen = /* @__PURE__ */ new Set();
69750
+ const addAffected = (file2) => {
69751
+ const key = fileIdentityKey(file2);
69752
+ if (affectedSeen.has(key))
69753
+ return;
69754
+ affectedSeen.add(key);
69755
+ affectedFiles.push(file2);
69756
+ };
69757
+ const degraded = parserDegradedCandidateFiles(index, scannedFiles);
69758
+ if (degraded.files.length || degraded.hasUnlistedCandidate) {
69759
+ reasons.push("parser_degraded");
69760
+ for (const file2 of degraded.files)
69761
+ addAffected(file2);
69762
+ }
69763
+ const unresolvedFiles = [];
69764
+ for (const fileId of candidateFiles) {
69765
+ const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
69766
+ if (!moduleIndex)
69767
+ continue;
69768
+ if (moduleIndex.imports.some((imp) => isUnresolvedIndexedImport(index, imp, def, exportedNames))) {
69769
+ unresolvedFiles.push(fileId);
69770
+ }
69771
+ }
69772
+ if (unresolvedFiles.length) {
69773
+ reasons.push("unresolved_import");
69774
+ for (const file2 of unresolvedFiles)
69775
+ addAffected(file2);
69776
+ }
69777
+ if (truncated)
69778
+ reasons.push("truncated");
69779
+ if (!reasons.length) {
69780
+ return { scope: "indexed_candidates", state: "complete" };
69781
+ }
69782
+ return {
69783
+ scope: "indexed_candidates",
69784
+ state: "partial",
69785
+ reasons: COVERAGE_REASON_ORDER.filter((reason) => reasons.includes(reason)),
69786
+ ...affectedFiles.length ? { affectedFiles } : {}
69787
+ };
69788
+ }
69789
+ var EXPORT_FROM_PATTERN, NAMESPACE_EXPORT_PATTERN, EXPORT_FROM_SPECIFIER_PATTERN, referenceCandidateCache, COVERAGE_REASON_ORDER;
68888
69790
  var init_navigation_references = __esm({
68889
69791
  "dist/indexer/navigation-references.js"() {
68890
69792
  "use strict";
@@ -68902,6 +69804,7 @@ var init_navigation_references = __esm({
68902
69804
  NAMESPACE_EXPORT_PATTERN = new RegExp(String.raw`\bexport\s*\*\s*as\s*(${ECMASCRIPT_IDENTIFIER_SOURCE})\s*from\s*(["'])([^"']+)\2`, "gu");
68903
69805
  EXPORT_FROM_SPECIFIER_PATTERN = new RegExp(String.raw`^(${ECMASCRIPT_IDENTIFIER_SOURCE})`, "u");
68904
69806
  referenceCandidateCache = /* @__PURE__ */ new WeakMap();
69807
+ COVERAGE_REASON_ORDER = ["parser_degraded", "unresolved_import", "truncated"];
68905
69808
  }
68906
69809
  });
68907
69810
 
@@ -69228,22 +70131,38 @@ async function goToSqlDefinition(index, req) {
69228
70131
  confidence: "high"
69229
70132
  });
69230
70133
  }
69231
- async function findSqlReferences(index, definition) {
70134
+ async function findSqlReferences(index, definition, options) {
69232
70135
  if (!isSqlFile2(definition.file))
69233
70136
  return null;
69234
70137
  const references = [];
69235
70138
  const seen = /* @__PURE__ */ new Set();
69236
70139
  const lookup = getSqlDefinitionLookup(index);
70140
+ const candidateFiles = sqlFiles(index);
70141
+ const scannedFiles = [];
70142
+ const includeDefinition = options?.includeDefinition ?? true;
70143
+ const maxReferences = typeof options?.maxReferences === "number" && options.maxReferences > 0 ? options.maxReferences : void 0;
70144
+ const collectionLimit = maxReferences === void 0 ? void 0 : maxReferences + 1;
70145
+ const definitionKey = `${fileIdentityKey(definition.file)}:${definition.range.start.line}:${definition.range.start.column}`;
70146
+ const hasReachedCollectionLimit = () => collectionLimit !== void 0 && references.length >= collectionLimit;
69237
70147
  const addReference = (file2, range) => {
69238
- const key = `${file2}:${range.start.line}:${range.start.column}`;
70148
+ if (hasReachedCollectionLimit())
70149
+ return;
70150
+ const key = `${fileIdentityKey(file2)}:${range.start.line}:${range.start.column}`;
70151
+ if (!includeDefinition && key === definitionKey)
70152
+ return;
69239
70153
  if (seen.has(key))
69240
70154
  return;
69241
70155
  seen.add(key);
69242
70156
  references.push({ file: file2, range });
69243
70157
  };
69244
- for (const file2 of sqlFiles(index)) {
70158
+ for (const file2 of candidateFiles) {
70159
+ if (hasReachedCollectionLimit())
70160
+ break;
70161
+ scannedFiles.push(file2);
69245
70162
  const facts = await sqlFactsForFile(index, file2);
69246
70163
  for (const fact of facts) {
70164
+ if (hasReachedCollectionLimit())
70165
+ break;
69247
70166
  for (const name of [fact.objectName, fact.relatedObjectName]) {
69248
70167
  if (!name || !sqlNameResolvesToDefinition(lookup, name, definition))
69249
70168
  continue;
@@ -69252,7 +70171,11 @@ async function findSqlReferences(index, definition) {
69252
70171
  }
69253
70172
  }
69254
70173
  }
70174
+ if (hasReachedCollectionLimit())
70175
+ break;
69255
70176
  for (const statement of sqlStatementSlices(facts)) {
70177
+ if (hasReachedCollectionLimit())
70178
+ break;
69256
70179
  for (const range of qualifiedReferenceRanges(lookup, statement, definition)) {
69257
70180
  addReference(file2, range);
69258
70181
  }
@@ -69264,11 +70187,22 @@ async function findSqlReferences(index, definition) {
69264
70187
  return fileCompare;
69265
70188
  return left.range.start.line - right.range.start.line || left.range.start.column - right.range.start.column;
69266
70189
  });
70190
+ const truncated = maxReferences !== void 0 && references.length > maxReferences;
70191
+ if (truncated)
70192
+ references.length = maxReferences;
69267
70193
  return {
69268
70194
  status: "ok",
69269
70195
  definition,
69270
70196
  references,
69271
- provenance: createNavigationProvenance(index, "exact", "high")
70197
+ provenance: createNavigationProvenance(index, "exact", "high"),
70198
+ referenceCoverage: buildIndexedCandidateCoverage({
70199
+ index,
70200
+ def: definition,
70201
+ exportedNames: [],
70202
+ candidateFiles,
70203
+ scannedFiles,
70204
+ truncated
70205
+ })
69272
70206
  };
69273
70207
  }
69274
70208
  var SQL_IDENTIFIER, SQL_DOTTED_TOKEN, SQL_DOTTED_TOKEN_RE, SQL_SOURCE_KEYWORDS, SQL_SOURCE_MODIFIERS, SQL_SOURCE_BOUNDARY_RE;
@@ -69276,6 +70210,7 @@ var init_navigation = __esm({
69276
70210
  "dist/sql/navigation.js"() {
69277
70211
  "use strict";
69278
70212
  init_navigation_provenance();
70213
+ init_navigation_references();
69279
70214
  init_paths();
69280
70215
  init_extract_facts();
69281
70216
  init_lookup();
@@ -69457,6 +70392,15 @@ function isUnresolvedReceiverMemberProperty(sup, node) {
69457
70392
  return !!property && node.id === property.id;
69458
70393
  }
69459
70394
  async function findReferences(index, req, opts) {
70395
+ return findReferencesInternal(index, req, opts, "all");
70396
+ }
70397
+ async function findUsageReferences(index, req, opts) {
70398
+ return findReferencesInternal(index, req, opts, "usages");
70399
+ }
70400
+ async function findRenameReferences(index, def, opts) {
70401
+ return findReferencesInternal(index, { def }, opts, "rename");
70402
+ }
70403
+ async function findReferencesInternal(index, req, opts, collectionMode) {
69460
70404
  let def = null;
69461
70405
  let provenance2;
69462
70406
  if ("def" in req) {
@@ -69482,10 +70426,37 @@ async function findReferences(index, req, opts) {
69482
70426
  if (!def) {
69483
70427
  return { status: "not_found", reason: "Could not resolve definition" };
69484
70428
  }
69485
- const sqlReferences = await findSqlReferences(index, def);
70429
+ const maxReferences = typeof opts?.maxReferences === "number" && opts.maxReferences > 0 ? opts.maxReferences : void 0;
70430
+ const sqlReferences = await findSqlReferences(index, def, {
70431
+ includeDefinition: collectionMode === "all",
70432
+ ...maxReferences === void 0 ? {} : { maxReferences }
70433
+ });
69486
70434
  if (sqlReferences)
69487
70435
  return sqlReferences;
69488
70436
  const definitionFile = def.file;
70437
+ const definitionSiteKey = referenceSiteKey(definitionFile, def.range);
70438
+ const includeReference = (ref) => {
70439
+ if (collectionMode === "all")
70440
+ return true;
70441
+ if (ref.via?.reexport || referenceSiteKey(ref.file, ref.range) === definitionSiteKey)
70442
+ return false;
70443
+ if (collectionMode === "usages")
70444
+ return ref.via?.importBinding === void 0;
70445
+ const binding = ref.via?.import;
70446
+ if (!binding || binding.kind === "star" || binding.kind === "namespace")
70447
+ return true;
70448
+ if (ref.via?.importBinding === "imported" && binding.kind === "named" && binding.imported === def.localName) {
70449
+ return true;
70450
+ }
70451
+ if (binding.kind === "default")
70452
+ return false;
70453
+ return !binding.explicitAlias && binding.local === def.localName;
70454
+ };
70455
+ const verifiedReferenceFilter = (fileId) => {
70456
+ if (collectionMode === "all")
70457
+ return void 0;
70458
+ return (reference) => !reference.via?.reexport && referenceSiteKey(fileId, reference.range) !== definitionSiteKey;
70459
+ };
69489
70460
  const parsedDef = index.parsed?.get(fileIdentityKey(definitionFile));
69490
70461
  const parsedContext = await ensureParsedContext(definitionFile, parsedDef, index.languageExtensions);
69491
70462
  const mod = index.byFile.get(fileIdentityKey(definitionFile));
@@ -69493,14 +70464,26 @@ async function findReferences(index, req, opts) {
69493
70464
  return { status: "not_found", reason: "Module not found" };
69494
70465
  const scope = getCachedScope(index, definitionFile, mod, parsedContext);
69495
70466
  const refs = [];
69496
- const maxReferences = typeof opts?.maxReferences === "number" && opts.maxReferences > 0 ? opts.maxReferences : void 0;
69497
- const seenRefs = /* @__PURE__ */ new Set();
69498
- const hasReachedMaxReferences = () => maxReferences !== void 0 && refs.length >= maxReferences;
70467
+ const seenRefs = /* @__PURE__ */ new Map();
70468
+ const collectionLimit = maxReferences !== void 0 ? maxReferences + 1 : void 0;
70469
+ const hasReachedCollectionLimit = () => collectionLimit !== void 0 && refs.length >= collectionLimit;
70470
+ const remainingCollectionSlots = () => collectionLimit !== void 0 ? Math.max(0, collectionLimit - refs.length) : void 0;
70471
+ const importBindingRank = (ref) => ref.via?.importBinding === "imported" ? 1 : 0;
69499
70472
  const pushRef = (ref) => {
69500
- const key = `${fileIdentityKey(ref.file)}:${ref.range.start.line}:${ref.range.start.column}`;
69501
- if (seenRefs.has(key))
70473
+ if (!includeReference(ref))
70474
+ return;
70475
+ const key = referenceSiteKey(ref.file, ref.range);
70476
+ const existingIndex = seenRefs.get(key);
70477
+ if (existingIndex !== void 0) {
70478
+ const existing = refs[existingIndex];
70479
+ if (importBindingRank(ref) > importBindingRank(existing)) {
70480
+ refs[existingIndex] = ref;
70481
+ }
70482
+ return;
70483
+ }
70484
+ if (hasReachedCollectionLimit())
69502
70485
  return;
69503
- seenRefs.add(key);
70486
+ seenRefs.set(key, refs.length);
69504
70487
  refs.push(ref);
69505
70488
  };
69506
70489
  const normalizedLocalName = parsedContext.sup.normalizeIdentifier(def.localName);
@@ -69509,7 +70492,7 @@ async function findReferences(index, req, opts) {
69509
70492
  pushRef({ file: definitionFile, range: def.range });
69510
70493
  if (localBinding) {
69511
70494
  for (const occurrence of localBinding.occurrences) {
69512
- if (hasReachedMaxReferences())
70495
+ if (hasReachedCollectionLimit())
69513
70496
  break;
69514
70497
  pushRef({ file: definitionFile, range: occurrence });
69515
70498
  }
@@ -69543,7 +70526,7 @@ async function findReferences(index, req, opts) {
69543
70526
  });
69544
70527
  }
69545
70528
  for (const fileId of candidateFiles) {
69546
- if (hasReachedMaxReferences())
70529
+ if (hasReachedCollectionLimit())
69547
70530
  break;
69548
70531
  const module2 = index.byFile.get(fileIdentityKey(fileId));
69549
70532
  if (!module2)
@@ -69566,7 +70549,7 @@ async function findReferences(index, req, opts) {
69566
70549
  };
69567
70550
  if (supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.supportsExportFromReferences) {
69568
70551
  for (const entry of module2.exports) {
69569
- if (hasReachedMaxReferences())
70552
+ if (hasReachedCollectionLimit())
69570
70553
  break;
69571
70554
  if (entry.type !== "reexport")
69572
70555
  continue;
@@ -69575,10 +70558,10 @@ async function findReferences(index, req, opts) {
69575
70558
  const resolved = resolveExport(index, entry.fromModule, entry.sourceSpecifier);
69576
70559
  if (resolved?.kind === "resolved" && !sameDef(resolved.def, def, index.languageExtensions))
69577
70560
  continue;
69578
- const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
69579
- const ranges = await collectVerifiedNamedNodeReferences(index, fileId, entry.sourceSpecifier, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences);
70561
+ const remainingReferences = remainingCollectionSlots();
70562
+ const ranges = await collectVerifiedNamedNodeReferences(index, fileId, entry.sourceSpecifier, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences, verifiedReferenceFilter(fileId));
69580
70563
  for (const { range, provenance: provenance3, via } of ranges) {
69581
- if (hasReachedMaxReferences())
70564
+ if (hasReachedCollectionLimit())
69582
70565
  break;
69583
70566
  if (!via?.reexport)
69584
70567
  continue;
@@ -69587,13 +70570,43 @@ async function findReferences(index, req, opts) {
69587
70570
  }
69588
70571
  }
69589
70572
  for (const imp of module2.imports) {
69590
- if (hasReachedMaxReferences())
70573
+ if (hasReachedCollectionLimit())
69591
70574
  break;
69592
70575
  const targetFile = typeof imp.resolved === "string" ? imp.resolved : void 0;
69593
- if (!targetFile)
70576
+ const bindingSites = importBindingReferenceSites(imp);
70577
+ let verifiedBindingMatches;
70578
+ const bindingMatchesDefinition = async () => {
70579
+ if (verifiedBindingMatches !== void 0)
70580
+ return verifiedBindingMatches;
70581
+ verifiedBindingMatches = false;
70582
+ const parsed = await ensureCandidateParsed();
70583
+ for (const verificationSite of importBindingIdentityVerificationSites(imp)) {
70584
+ const resolved = await goToDefinition(index, {
70585
+ file: fileId,
70586
+ line: verificationSite.range.start.line,
70587
+ column: verificationSite.range.start.column
70588
+ }, parsed);
70589
+ if (resolved.status === "ok" && sameDef(resolved.definition, def, index.languageExtensions)) {
70590
+ verifiedBindingMatches = true;
70591
+ break;
70592
+ }
70593
+ }
70594
+ return verifiedBindingMatches;
70595
+ };
70596
+ if (!targetFile) {
70597
+ if (!bindingSites.length || !await bindingMatchesDefinition())
70598
+ continue;
70599
+ for (const site of bindingSites) {
70600
+ pushRef({
70601
+ file: fileId,
70602
+ range: site.range,
70603
+ via: { import: imp, importBinding: site.importBinding }
70604
+ });
70605
+ }
69594
70606
  continue;
70607
+ }
69595
70608
  for (const exportedName of exportedNames) {
69596
- if (hasReachedMaxReferences())
70609
+ if (hasReachedCollectionLimit())
69597
70610
  break;
69598
70611
  if (imp.kind === "namespace") {
69599
70612
  const hit = resolveExport(index, targetFile, exportedName);
@@ -69603,7 +70616,7 @@ async function findReferences(index, req, opts) {
69603
70616
  const parsed = await ensureCandidateParsed();
69604
70617
  const ranges = await collectNamespaceMemberRefs(fileId, imp.localNS, exportedName, parsed, index.languageExtensions);
69605
70618
  for (const range of ranges) {
69606
- if (hasReachedMaxReferences())
70619
+ if (hasReachedCollectionLimit())
69607
70620
  break;
69608
70621
  pushRef({
69609
70622
  file: fileId,
@@ -69619,10 +70632,10 @@ async function findReferences(index, req, opts) {
69619
70632
  if (hasExpandedNamedImport(module2, targetFile, exportedName)) {
69620
70633
  continue;
69621
70634
  }
69622
- const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
69623
- const ranges = await collectVerifiedNamedNodeReferences(index, fileId, exportedName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences);
70635
+ const remainingReferences = remainingCollectionSlots();
70636
+ const ranges = await collectVerifiedNamedNodeReferences(index, fileId, exportedName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences, verifiedReferenceFilter(fileId));
69624
70637
  for (const { range, provenance: provenance3, via } of ranges) {
69625
- if (hasReachedMaxReferences())
70638
+ if (hasReachedCollectionLimit())
69626
70639
  break;
69627
70640
  pushRef({
69628
70641
  file: fileId,
@@ -69639,14 +70652,24 @@ async function findReferences(index, req, opts) {
69639
70652
  exported = "default";
69640
70653
  }
69641
70654
  const hit = resolveExport(index, targetFile, exported);
69642
- const matchesDef = hit?.kind === "resolved" && sameDef(hit.def, def, index.languageExtensions);
70655
+ let matchesDef = hit?.kind === "resolved" && sameDef(hit.def, def, index.languageExtensions);
70656
+ if (!matchesDef && bindingSites.length) {
70657
+ matchesDef = await bindingMatchesDefinition();
70658
+ }
69643
70659
  if (!matchesDef)
69644
70660
  continue;
70661
+ for (const site of bindingSites) {
70662
+ pushRef({
70663
+ file: fileId,
70664
+ range: site.range,
70665
+ via: { import: imp, importBinding: site.importBinding }
70666
+ });
70667
+ }
69645
70668
  if (fileIdentityKey(targetFile) !== fileIdentityKey(definitionFile)) {
69646
- const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
69647
- const ranges = await collectVerifiedNamedNodeReferences(index, fileId, imp.local, def, (params, parsed2) => goToDefinition(index, params, parsed2), remainingReferences);
70669
+ const remainingReferences = remainingCollectionSlots();
70670
+ const ranges = await collectVerifiedNamedNodeReferences(index, fileId, imp.local, def, (params, parsed2) => goToDefinition(index, params, parsed2), remainingReferences, verifiedReferenceFilter(fileId));
69648
70671
  for (const { range, provenance: provenance3, via } of ranges) {
69649
- if (hasReachedMaxReferences())
70672
+ if (hasReachedCollectionLimit())
69650
70673
  break;
69651
70674
  pushRef({
69652
70675
  file: fileId,
@@ -69660,12 +70683,15 @@ async function findReferences(index, req, opts) {
69660
70683
  const parsed = await ensureCandidateParsed();
69661
70684
  const resolvedScope = await ensureScope();
69662
70685
  const localName = parsed.sup.normalizeIdentifier(imp.local);
70686
+ const declarationKeys = importBindingDeclarationRangeKeys(module2);
69663
70687
  const bindings = resolvedScope.bindings.get(localName) ?? [];
69664
70688
  for (const binding of bindings) {
69665
70689
  if (binding.import === imp) {
69666
70690
  for (const occurrence of binding.occurrences) {
69667
- if (hasReachedMaxReferences())
70691
+ if (hasReachedCollectionLimit())
69668
70692
  break;
70693
+ if (declarationKeys.has(rangeIdentityKey(occurrence)))
70694
+ continue;
69669
70695
  pushRef({ file: fileId, range: occurrence, via: { import: imp } });
69670
70696
  }
69671
70697
  }
@@ -69674,36 +70700,42 @@ async function findReferences(index, req, opts) {
69674
70700
  }
69675
70701
  }
69676
70702
  if (phpQualifiedNames.length) {
69677
- const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
70703
+ const remainingReferences = remainingCollectionSlots();
69678
70704
  for (const candidateName of [...exportedNames, ...phpQualifiedNames]) {
69679
- if (hasReachedMaxReferences())
70705
+ if (hasReachedCollectionLimit())
69680
70706
  break;
69681
- const ranges = await collectVerifiedNamedNodeReferences(index, fileId, candidateName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences);
70707
+ const ranges = await collectVerifiedNamedNodeReferences(index, fileId, candidateName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences, verifiedReferenceFilter(fileId));
69682
70708
  for (const { range, provenance: provenance3, via } of ranges) {
69683
- if (hasReachedMaxReferences())
70709
+ if (hasReachedCollectionLimit())
69684
70710
  break;
69685
70711
  pushRef({ file: fileId, range, ...via ? { via } : {}, ...provenance3 ? { provenance: provenance3 } : {} });
69686
70712
  }
69687
70713
  }
69688
70714
  }
69689
70715
  }
70716
+ const receiverScannedFiles = [];
69690
70717
  if (shouldScanVerifiedReferences(def, phpQualifiedNames, parsedContext)) {
69691
70718
  for (const fileId of Array.from(index.byFile.values(), (module2) => module2.file).sort((left, right) => left.localeCompare(right))) {
69692
- if (hasReachedMaxReferences())
70719
+ if (hasReachedCollectionLimit())
69693
70720
  break;
70721
+ receiverScannedFiles.push(fileId);
69694
70722
  const filter = index.bloomFilters?.get(fileIdentityKey(fileId));
69695
70723
  const canonicalName = supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.normalizeIdentifier(def.localName) ?? def.localName;
69696
70724
  if (filter && !filter.mightContain(canonicalName))
69697
70725
  continue;
69698
- const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
69699
- const ranges = await collectVerifiedNamedNodeReferences(index, fileId, def.localName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences);
70726
+ const remainingReferences = remainingCollectionSlots();
70727
+ const ranges = await collectVerifiedNamedNodeReferences(index, fileId, def.localName, def, (params, parsed) => goToDefinition(index, params, parsed), remainingReferences, verifiedReferenceFilter(fileId));
69700
70728
  for (const { range, provenance: provenance3, via } of ranges) {
69701
- if (hasReachedMaxReferences())
70729
+ if (hasReachedCollectionLimit())
69702
70730
  break;
69703
70731
  pushRef({ file: fileId, range, ...via ? { via } : {}, ...provenance3 ? { provenance: provenance3 } : {} });
69704
70732
  }
69705
70733
  }
69706
70734
  }
70735
+ const truncated = maxReferences !== void 0 && refs.length > maxReferences;
70736
+ if (truncated) {
70737
+ refs.length = maxReferences;
70738
+ }
69707
70739
  refs.sort((left, right) => {
69708
70740
  if (fileIdentityKey(left.file) === fileIdentityKey(right.file)) {
69709
70741
  const leftIndex = left.range.start.index ?? 0;
@@ -69731,26 +70763,36 @@ async function findReferences(index, req, opts) {
69731
70763
  }
69732
70764
  }
69733
70765
  }
70766
+ const scannedFiles = [definitionFile, ...candidateFiles, ...receiverScannedFiles];
70767
+ const referenceCoverage = buildIndexedCandidateCoverage({
70768
+ index,
70769
+ def,
70770
+ exportedNames,
70771
+ candidateFiles,
70772
+ scannedFiles,
70773
+ truncated
70774
+ });
69734
70775
  return {
69735
70776
  status: "ok",
69736
70777
  definition: def,
69737
70778
  references: refs,
70779
+ referenceCoverage,
69738
70780
  ...provenance2 ? { provenance: provenance2 } : {}
69739
70781
  };
69740
70782
  }
69741
70783
  function shouldScanVerifiedReferences(def, phpQualifiedNames, parsedContext) {
69742
- if (def.kind !== SymbolKind.Function || phpQualifiedNames.length) {
70784
+ if (phpQualifiedNames.length)
69743
70785
  return false;
69744
- }
69745
- if (!supportsReceiverMemberResolution(parsedContext.sup.id)) {
70786
+ if (!supportsReceiverMemberResolution(parsedContext.sup.id))
69746
70787
  return false;
69747
- }
69748
- return isReceiverMethodDefinition(def, parsedContext);
70788
+ return isReceiverMemberDefinition(def, parsedContext);
69749
70789
  }
69750
70790
  function shouldUseLocalNameAsExportFallback(def, parsedContext) {
69751
- return !isReceiverMethodDefinition(def, parsedContext);
70791
+ return !isReceiverMemberDefinition(def, parsedContext);
69752
70792
  }
69753
- function isReceiverMethodDefinition(def, parsedContext) {
70793
+ function isReceiverMemberDefinition(def, parsedContext) {
70794
+ if (def.isMember)
70795
+ return true;
69754
70796
  if (def.kind !== SymbolKind.Function) {
69755
70797
  return false;
69756
70798
  }
@@ -73261,7 +74303,7 @@ async function attachCallCompatibilityHints(index, changedSymbols, options) {
73261
74303
  if (options.workBudget) {
73262
74304
  recordReferenceLookupStarted(options.workBudget);
73263
74305
  }
73264
- const referenceResult = await (options.referenceCache ? options.referenceCache.get(index, referenceDef, { maxReferences: referenceScanLimit }) : findReferences(index, { def: referenceDef }, { maxReferences: referenceScanLimit }));
74306
+ const referenceResult = await (options.referenceCache ? options.referenceCache.getUsages(index, referenceDef, { maxReferences: referenceScanLimit }) : findUsageReferences(index, { def: referenceDef }, { maxReferences: referenceScanLimit }));
73265
74307
  let refs = [];
73266
74308
  const shouldIncludeReference = options.shouldIncludeReference ?? (() => true);
73267
74309
  if (referenceResult.status === "ok") {
@@ -74170,17 +75212,19 @@ var init_map = __esm({
74170
75212
  // dist/impact/reference-cache.js
74171
75213
  function createReferenceLookupCache() {
74172
75214
  const cachesByIndex = /* @__PURE__ */ new WeakMap();
74173
- return {
74174
- async get(index, def, options) {
74175
- const maxReferences = normalizeMaxReferences(options?.maxReferences);
74176
- const indexCache = getIndexReferenceCache(cachesByIndex, index);
74177
- const baseResult = await getBaseReferences(index, def, maxReferences, indexCache);
74178
- const bounded = cloneReferenceResult(baseResult, maxReferences);
74179
- if (bounded.status !== "ok" || options?.context === void 0)
74180
- return bounded;
74181
- await attachReferenceContext(index, bounded.references, options);
75215
+ const lookup = async (mode, index, def, options) => {
75216
+ const maxReferences = normalizeMaxReferences(options?.maxReferences);
75217
+ const indexCache = getIndexReferenceCache(cachesByIndex, index);
75218
+ const baseResult = await getBaseReferences(index, def, maxReferences, indexCache, mode);
75219
+ const bounded = cloneReferenceResult(baseResult, maxReferences);
75220
+ if (bounded.status !== "ok" || options?.context === void 0)
74182
75221
  return bounded;
74183
- }
75222
+ await attachReferenceContext(index, bounded.references, options);
75223
+ return bounded;
75224
+ };
75225
+ return {
75226
+ get: (index, def, options) => lookup("all", index, def, options),
75227
+ getUsages: (index, def, options) => lookup("usages", index, def, options)
74184
75228
  };
74185
75229
  }
74186
75230
  function getIndexReferenceCache(cachesByIndex, index) {
@@ -74191,13 +75235,14 @@ function getIndexReferenceCache(cachesByIndex, index) {
74191
75235
  }
74192
75236
  return cache;
74193
75237
  }
74194
- function getBaseReferences(index, def, maxReferences, cache) {
74195
- const key = referenceLookupKey(def);
75238
+ function getBaseReferences(index, def, maxReferences, cache, mode) {
75239
+ const key = referenceLookupKey(def, mode);
74196
75240
  const entries = cache.get(key) ?? [];
74197
75241
  const reusable = entries.find((entry) => canReuseEntry(entry.maxReferences, maxReferences));
74198
75242
  if (reusable)
74199
75243
  return reusable.refs;
74200
- const refs = findReferences(index, { def }, maxReferences === void 0 ? void 0 : { maxReferences });
75244
+ const finder = mode === "usages" ? findUsageReferences : findReferences;
75245
+ const refs = finder(index, { def }, maxReferences === void 0 ? void 0 : { maxReferences });
74201
75246
  entries.push({ maxReferences, refs });
74202
75247
  cache.set(key, entries);
74203
75248
  return refs;
@@ -74214,24 +75259,45 @@ function normalizeMaxReferences(maxReferences) {
74214
75259
  return void 0;
74215
75260
  return maxReferences;
74216
75261
  }
75262
+ function cloneCoverage(coverage) {
75263
+ return {
75264
+ scope: coverage.scope,
75265
+ state: coverage.state,
75266
+ ...coverage.reasons ? { reasons: [...coverage.reasons] } : {},
75267
+ ...coverage.affectedFiles ? { affectedFiles: [...coverage.affectedFiles] } : {}
75268
+ };
75269
+ }
75270
+ function withTruncatedCoverage(coverage) {
75271
+ const reasons = new Set(coverage.reasons ?? []);
75272
+ reasons.add("truncated");
75273
+ return {
75274
+ scope: "indexed_candidates",
75275
+ state: "partial",
75276
+ reasons: COVERAGE_REASON_ORDER2.filter((reason) => reasons.has(reason)),
75277
+ ...coverage.affectedFiles ? { affectedFiles: [...coverage.affectedFiles] } : {}
75278
+ };
75279
+ }
74217
75280
  function cloneReferenceResult(result, maxReferences) {
74218
75281
  if (result.status !== "ok")
74219
75282
  return result;
75283
+ const truncatedByBound = maxReferences !== void 0 && result.references.length > maxReferences;
74220
75284
  const references = result.references.slice(0, maxReferences).map(cloneReference);
75285
+ const baseCoverage = cloneCoverage(result.referenceCoverage);
74221
75286
  return {
74222
75287
  status: "ok",
74223
75288
  definition: result.definition,
74224
75289
  references,
75290
+ referenceCoverage: truncatedByBound ? withTruncatedCoverage(baseCoverage) : baseCoverage,
74225
75291
  ...result.provenance ? { provenance: result.provenance } : {}
74226
75292
  };
74227
75293
  }
74228
75294
  function cloneReference(reference) {
74229
75295
  return {
74230
75296
  file: reference.file,
74231
- range: reference.range,
75297
+ range: { start: { ...reference.range.start }, end: { ...reference.range.end } },
74232
75298
  ...reference.context !== void 0 ? { context: reference.context } : {},
74233
- ...reference.via !== void 0 ? { via: reference.via } : {},
74234
- ...reference.provenance !== void 0 ? { provenance: reference.provenance } : {}
75299
+ ...reference.via !== void 0 ? { via: { ...reference.via } } : {},
75300
+ ...reference.provenance !== void 0 ? { provenance: { ...reference.provenance } } : {}
74235
75301
  };
74236
75302
  }
74237
75303
  async function attachReferenceContext(index, references, options) {
@@ -74252,8 +75318,9 @@ async function attachReferenceContext(index, references, options) {
74252
75318
  }
74253
75319
  }
74254
75320
  }
74255
- function referenceLookupKey(def) {
75321
+ function referenceLookupKey(def, mode) {
74256
75322
  return JSON.stringify({
75323
+ mode,
74257
75324
  file: def.file,
74258
75325
  name: def.localName,
74259
75326
  kind: def.kind,
@@ -74262,6 +75329,7 @@ function referenceLookupKey(def) {
74262
75329
  index: def.range.start.index
74263
75330
  });
74264
75331
  }
75332
+ var COVERAGE_REASON_ORDER2;
74265
75333
  var init_reference_cache = __esm({
74266
75334
  "dist/impact/reference-cache.js"() {
74267
75335
  "use strict";
@@ -74270,6 +75338,7 @@ var init_reference_cache = __esm({
74270
75338
  init_reference_context();
74271
75339
  init_shared2();
74272
75340
  init_paths();
75341
+ COVERAGE_REASON_ORDER2 = ["parser_degraded", "unresolved_import", "truncated"];
74273
75342
  }
74274
75343
  });
74275
75344
 
@@ -74519,21 +75588,6 @@ function collectDiffSnippets(source, range, changedLines, contextLines) {
74519
75588
  pushGroup(groupStart, groupEnd);
74520
75589
  return snippets;
74521
75590
  }
74522
- function sameRange(left, right) {
74523
- const leftStart = left.start.index;
74524
- const rightStart = right.start.index;
74525
- const leftEnd = left.end.index;
74526
- const rightEnd = right.end.index;
74527
- if (typeof leftStart === "number" && typeof rightStart === "number") {
74528
- if (leftStart !== rightStart)
74529
- return false;
74530
- if (typeof leftEnd === "number" && typeof rightEnd === "number") {
74531
- return leftEnd === rightEnd;
74532
- }
74533
- return true;
74534
- }
74535
- return left.start.line === right.start.line && left.start.column === right.start.column;
74536
- }
74537
75591
  async function summarizeChangedFiles2(input) {
74538
75592
  const { projectRoot, index, changedFileList, diffHunksByFile, diffKindsByFile, diffChangesByFile, explicitFiles, existenceByFile, deletedSnapshots, loadSource: suppliedLoadSource, includeSymbolDetails, includeDiffContext, diffContextLines, maxCallsites, referenceConcurrency, diagnostics, reviewTimings } = input;
74539
75593
  const readSource = suppliedLoadSource ?? (async (file2) => await fsp39.readFile(file2, "utf8"));
@@ -74644,8 +75698,8 @@ async function summarizeChangedFiles2(input) {
74644
75698
  const defsToResolve = fileEntries.flatMap((entry) => entry.locals);
74645
75699
  const referencesStart = performance11.now();
74646
75700
  const referenceResults = includeSymbolDetails && maxCallsites > 0 ? await mapLimit(defsToResolve, referenceConcurrency, async (def) => {
74647
- const refs = await referenceCache.get(index, def, {
74648
- maxReferences: maxCallsites + 1
75701
+ const refs = await referenceCache.getUsages(index, def, {
75702
+ maxReferences: maxCallsites
74649
75703
  });
74650
75704
  return { def, refs };
74651
75705
  }) : [];
@@ -74676,12 +75730,16 @@ async function summarizeChangedFiles2(input) {
74676
75730
  const diffLines = diffLinesByHandle.get(handle) ?? /* @__PURE__ */ new Set();
74677
75731
  const diffSnippets = includeDiffContext && diffLines.size ? collectDiffSnippets(source, local.range, diffLines, diffContextLines) : [];
74678
75732
  let callsites;
75733
+ let callsiteCoverage;
74679
75734
  if (maxCallsites > 0) {
74680
75735
  const entry = referencesByHandle.get(handle);
74681
75736
  const refs = entry?.refs;
74682
75737
  if (refs?.status === "ok") {
74683
- const candidates = refs.references.filter((ref) => !(fileIdentityKey(ref.file) === fileIdentityKey(local.file) && sameRange(ref.range, local.range)));
74684
- const limited = candidates.slice(0, maxCallsites).map((ref) => ({
75738
+ callsiteCoverage = refs.referenceCoverage.affectedFiles ? {
75739
+ ...refs.referenceCoverage,
75740
+ affectedFiles: refs.referenceCoverage.affectedFiles.map((file2) => relativePath2(projectRoot, file2))
75741
+ } : refs.referenceCoverage;
75742
+ const limited = refs.references.map((ref) => ({
74685
75743
  file: relativePath2(projectRoot, ref.file),
74686
75744
  range: ref.range
74687
75745
  }));
@@ -74693,7 +75751,8 @@ async function summarizeChangedFiles2(input) {
74693
75751
  ...base,
74694
75752
  ...definitionSnippet,
74695
75753
  ...diffSnippets.length ? { diffSnippets } : {},
74696
- ...callsites ? { callsites } : {}
75754
+ ...callsites ? { callsites } : {},
75755
+ ...callsiteCoverage ? { callsiteCoverage } : {}
74697
75756
  };
74698
75757
  };
74699
75758
  const summariesWithHandles = await mapLimit(fileEntries, Math.max(1, referenceConcurrency), async ({ file: file2, mod, hunks, locals, handles, diffLinesByHandle }) => {
@@ -76661,6 +77720,7 @@ async function buildExplanation(snapshot, lookup, resolved, request) {
76661
77720
  dependencies: dependencies.items,
76662
77721
  reverseDependencies: reverseDependencies.items,
76663
77722
  references: references.items,
77723
+ ...referenceContext.referenceCoverage ? { referenceCoverage: referenceContext.referenceCoverage } : {},
76664
77724
  relatedSqlObjects: relatedSqlObjects.items,
76665
77725
  duplicates: duplicates.items,
76666
77726
  snippets: snippets.items,
@@ -76878,7 +77938,8 @@ async function collectReferenceContext(snapshot, def, referenceLimit, snippetLim
76878
77938
  return emptyReferenceContext();
76879
77939
  const references = result.references.map((reference) => ({
76880
77940
  file: normalizeAgentFilePath(snapshot.root, reference.file),
76881
- range: reference.range
77941
+ range: reference.range,
77942
+ ...reference.via?.importBinding ? { importBinding: reference.via.importBinding } : {}
76882
77943
  })).sort((left, right) => {
76883
77944
  const fileDelta = left.file.localeCompare(right.file);
76884
77945
  if (fileDelta !== 0)
@@ -76897,7 +77958,21 @@ async function collectReferenceContext(snapshot, def, referenceLimit, snippetLim
76897
77958
  return {
76898
77959
  references: boundedReferences,
76899
77960
  snippets: boundedSnippets,
76900
- referencesOmittedLowerBound: result.references.length === collectionLimit && boundedReferences.omitted > 0
77961
+ // Core now reports `truncated` exactly (it probes one past `maxReferences` internally), so
77962
+ // reuse that signal instead of guessing from a boundary count: a returned length that merely
77963
+ // happens to equal `collectionLimit` is not by itself evidence of truncation.
77964
+ referencesOmittedLowerBound: Boolean(result.referenceCoverage.reasons?.includes("truncated")) && boundedReferences.omitted > 0,
77965
+ referenceCoverage: normalizeReferenceCoverage(snapshot, result.referenceCoverage)
77966
+ };
77967
+ }
77968
+ function normalizeReferenceCoverage(snapshot, coverage) {
77969
+ if (!coverage)
77970
+ return void 0;
77971
+ if (!coverage.affectedFiles)
77972
+ return coverage;
77973
+ return {
77974
+ ...coverage,
77975
+ affectedFiles: coverage.affectedFiles.map((file2) => normalizeAgentFilePath(snapshot.root, file2))
76901
77976
  };
76902
77977
  }
76903
77978
  function snippetFromReference(snapshot, reference) {
@@ -77049,7 +78124,8 @@ function emptyReferenceContext() {
77049
78124
  return {
77050
78125
  references: emptyAgentBoundedList(),
77051
78126
  snippets: emptyAgentBoundedList(),
77052
- referencesOmittedLowerBound: false
78127
+ referencesOmittedLowerBound: false,
78128
+ referenceCoverage: void 0
77053
78129
  };
77054
78130
  }
77055
78131
  function collectFollowUps(snapshot, resolved, symbols, relFile, duplicates) {
@@ -82285,7 +83361,7 @@ async function analyzeChangedSymbolReferences(context, changedSymbol) {
82285
83361
  let reason = "directRef";
82286
83362
  if (ref.via?.namespaceMember) {
82287
83363
  reason = "namespaceMember";
82288
- } else if (ref.via?.import) {
83364
+ } else if (ref.via?.import || ref.via?.importBinding) {
82289
83365
  reason = "importAlias";
82290
83366
  }
82291
83367
  const severityResult = calculateSeverity(changedSymbol, ref, [reason], 0, index, context.fanInByFile);
@@ -85439,6 +86515,14 @@ var init_semantic_symbols = __esm({
85439
86515
  // dist/agent/rename-preview.js
85440
86516
  import fs37 from "node:fs/promises";
85441
86517
  import path81 from "node:path";
86518
+ function incompleteReferenceCoverageReason(coverage) {
86519
+ if (coverage.state === "complete")
86520
+ return void 0;
86521
+ const reasons = (coverage.reasons ?? []).filter((reason) => reason !== "truncated");
86522
+ if (coverage.reasons?.length && !reasons.length)
86523
+ return void 0;
86524
+ return reasons.length ? `Reference coverage is partial (${reasons.join(", ")}).` : "Reference coverage is partial.";
86525
+ }
85442
86526
  async function previewRename(request) {
85443
86527
  const session = createAgentSession({
85444
86528
  root: request.root,
@@ -85459,11 +86543,15 @@ async function previewRenameInSnapshot(snapshot, request, freshness = { state: "
85459
86543
  const semanticReferences = [];
85460
86544
  let referenceFailure;
85461
86545
  try {
85462
- const referenceResult = await findReferences(snapshot.index, { def: resolved.def }, { maxReferences: maxEdits + 1 });
85463
- if (referenceResult.status === "ok")
86546
+ const referenceResult = await findRenameReferences(snapshot.index, resolved.def, {
86547
+ maxReferences: maxEdits + 1
86548
+ });
86549
+ if (referenceResult.status === "ok") {
85464
86550
  semanticReferences.push(...referenceResult.references);
85465
- else
86551
+ referenceFailure = incompleteReferenceCoverageReason(referenceResult.referenceCoverage);
86552
+ } else {
85466
86553
  referenceFailure = referenceResult.reason;
86554
+ }
85467
86555
  } catch (error51) {
85468
86556
  referenceFailure = errorMessage(error51);
85469
86557
  }
@@ -85525,11 +86613,15 @@ async function previewRenameInSnapshot(snapshot, request, freshness = { state: "
85525
86613
  }
85526
86614
  semanticDefinitions.set(implementation.symbolId, memberDef);
85527
86615
  try {
85528
- const memberReferences = await findReferences(snapshot.index, { def: memberDef }, { maxReferences: maxEdits + 1 });
85529
- if (memberReferences.status === "ok")
86616
+ const memberReferences = await findRenameReferences(snapshot.index, memberDef, {
86617
+ maxReferences: maxEdits + 1
86618
+ });
86619
+ if (memberReferences.status === "ok") {
85530
86620
  semanticReferences.push(...memberReferences.references);
85531
- else
86621
+ referenceFailure ??= incompleteReferenceCoverageReason(memberReferences.referenceCoverage);
86622
+ } else {
85532
86623
  referenceFailure ??= memberReferences.reason;
86624
+ }
85533
86625
  } catch (error51) {
85534
86626
  referenceFailure ??= errorMessage(error51);
85535
86627
  }
@@ -85590,7 +86682,7 @@ async function previewRenameInSnapshot(snapshot, request, freshness = { state: "
85590
86682
  ...selectedReferences.map((reference) => ({
85591
86683
  file: reference.file,
85592
86684
  range: reference.range,
85593
- kind: "reference",
86685
+ kind: reference.via?.importBinding === "imported" ? "import" : "reference",
85594
86686
  reference
85595
86687
  }))
85596
86688
  ];
@@ -86106,14 +87198,25 @@ async function collectImportDeclarationCandidates(references, oldName, loadSourc
86106
87198
  const candidates = [];
86107
87199
  const missing = [];
86108
87200
  const seenBindings = /* @__PURE__ */ new Set();
87201
+ const resolvedBindingKeys = /* @__PURE__ */ new Set();
87202
+ for (const reference of references) {
87203
+ if (reference.via?.importBinding !== "imported")
87204
+ continue;
87205
+ const binding = reference.via.import;
87206
+ if (binding && binding.kind === "named") {
87207
+ resolvedBindingKeys.add(namedImportBindingKey(reference.file, binding));
87208
+ }
87209
+ }
86109
87210
  for (const reference of references) {
86110
87211
  const binding = reference.via?.import;
86111
87212
  if (!binding || binding.kind !== "named" || binding.imported !== oldName)
86112
87213
  continue;
86113
- const key = `${reference.file}:${binding.from}:${binding.imported}:${binding.local}`;
87214
+ const key = namedImportBindingKey(reference.file, binding);
86114
87215
  if (seenBindings.has(key))
86115
87216
  continue;
86116
87217
  seenBindings.add(key);
87218
+ if (resolvedBindingKeys.has(key))
87219
+ continue;
86117
87220
  const source = await loadSource(reference.file);
86118
87221
  if (!source)
86119
87222
  continue;
@@ -86125,6 +87228,9 @@ async function collectImportDeclarationCandidates(references, oldName, loadSourc
86125
87228
  }
86126
87229
  return { candidates, missing };
86127
87230
  }
87231
+ function namedImportBindingKey(file2, binding) {
87232
+ return `${file2}:${binding.from}:${binding.imported}:${binding.local}`;
87233
+ }
86128
87234
  async function collectExportDeclarationCandidates(snapshot, target, loadSource) {
86129
87235
  const candidates = [];
86130
87236
  const missingFiles = [];
@@ -86316,9 +87422,12 @@ function isPreservedImportAlias(reference, text, oldName) {
86316
87422
  const binding = reference.via?.import;
86317
87423
  if (!binding || binding.kind === "star" || binding.kind === "namespace")
86318
87424
  return false;
87425
+ if (reference.via?.importBinding === "imported" && binding.kind === "named" && binding.imported === oldName) {
87426
+ return false;
87427
+ }
86319
87428
  if (binding.kind === "default")
86320
87429
  return true;
86321
- return binding.local !== oldName && text === binding.local;
87430
+ return (binding.explicitAlias || binding.local !== oldName) && text === binding.local;
86322
87431
  }
86323
87432
  function normalizeEdits(edits, unsafeSites, provenance2) {
86324
87433
  const byRange = /* @__PURE__ */ new Map();
@@ -86477,6 +87586,12 @@ async function buildRefactorPlanInSnapshot(snapshot, request, freshness = { stat
86477
87586
  ...includeContext && reference.context ? { context: reference.context } : {}
86478
87587
  };
86479
87588
  });
87589
+ const referenceCoverage = referenceResult.referenceCoverage ? {
87590
+ ...referenceResult.referenceCoverage,
87591
+ ...referenceResult.referenceCoverage.affectedFiles ? {
87592
+ affectedFiles: referenceResult.referenceCoverage.affectedFiles.map((file2) => normalizeAgentFilePath(snapshot.root, file2))
87593
+ } : {}
87594
+ } : void 0;
86480
87595
  const callersResult = findCallHierarchy(snapshot.symbolGraph, resolved.id, "incoming", {
86481
87596
  depth: 1,
86482
87597
  limit: callerLimit
@@ -86569,6 +87684,7 @@ async function buildRefactorPlanInSnapshot(snapshot, request, freshness = { stat
86569
87684
  target,
86570
87685
  definition: target.location,
86571
87686
  references,
87687
+ ...referenceCoverage ? { referenceCoverage } : {},
86572
87688
  callers,
86573
87689
  callees,
86574
87690
  supertypes,
@@ -104493,13 +105609,22 @@ function createCodegraphMcpHandlersForSession(options, session) {
104493
105609
  return { references: [], limit, totalSeen: 0, truncated: false, omitted: 0 };
104494
105610
  }
104495
105611
  const { items, omitted } = boundList(result.references, limit);
104496
- const references = items.map((reference) => ({ file: relative(reference.file), range: reference.range }));
105612
+ const references = items.map((reference) => ({
105613
+ file: relative(reference.file),
105614
+ range: reference.range,
105615
+ ...reference.via?.importBinding ? { importBinding: reference.via.importBinding } : {}
105616
+ }));
105617
+ const referenceCoverage = result.referenceCoverage ? {
105618
+ ...result.referenceCoverage,
105619
+ ...result.referenceCoverage.affectedFiles ? { affectedFiles: result.referenceCoverage.affectedFiles.map((file2) => relative(file2)) } : {}
105620
+ } : void 0;
104497
105621
  return {
104498
105622
  references,
104499
105623
  limit,
104500
105624
  totalSeen: result.references.length,
104501
105625
  truncated: Boolean(omitted),
104502
- omitted
105626
+ omitted,
105627
+ ...referenceCoverage ? { referenceCoverage } : {}
104503
105628
  };
104504
105629
  };
104505
105630
  const fileDeps = async (request) => await withFreshness(async () => {
@@ -104630,7 +105755,8 @@ function createCodegraphMcpHandlersForSession(options, session) {
104630
105755
  limit: explanation.limits.references,
104631
105756
  totalSeen: explanation.references.length + explanation.omittedCounts.references,
104632
105757
  truncated: explanation.omittedCounts.references > 0,
104633
- omitted: explanation.omittedCounts.references
105758
+ omitted: explanation.omittedCounts.references,
105759
+ ...explanation.referenceCoverage ? { referenceCoverage: explanation.referenceCoverage } : {}
104634
105760
  };
104635
105761
  }
104636
105762
  if (file2 === void 0 || line === void 0 || column === void 0) {
@@ -112501,6 +113627,10 @@ function writePrettyReferences(context, result) {
112501
113627
  const { line, column } = reference.range.start;
112502
113628
  context.writeStdoutLine(`${rel}:${line}:${column}`);
112503
113629
  }
113630
+ if (result.referenceCoverage?.state === "partial") {
113631
+ const reasons = result.referenceCoverage.reasons?.length ? ` (${result.referenceCoverage.reasons.join(", ")})` : "";
113632
+ context.writeStdoutLine(`note: reference coverage partial${reasons}`);
113633
+ }
112504
113634
  }
112505
113635
  async function handleGotoCommand(context) {
112506
113636
  let input;