@lzehrung/codegraph 2.3.17 → 2.3.19

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 (41) hide show
  1. package/codegraph-skill/codegraph/SKILL.md +2 -0
  2. package/dist/bin/cli.js +2223 -1691
  3. package/dist/graphs/symbol-graph-detailed/ast.d.ts.map +1 -1
  4. package/dist/graphs/symbol-graph-detailed/ast.js +22 -1
  5. package/dist/graphs/symbol-graph-detailed/ast.js.map +1 -1
  6. package/dist/graphs/symbol-graph-detailed/edgePasses.d.ts +5 -0
  7. package/dist/graphs/symbol-graph-detailed/edgePasses.d.ts.map +1 -1
  8. package/dist/graphs/symbol-graph-detailed/edgePasses.js +110 -8
  9. package/dist/graphs/symbol-graph-detailed/edgePasses.js.map +1 -1
  10. package/dist/graphs/symbol-graph-detailed/receiverCalls.d.ts +69 -0
  11. package/dist/graphs/symbol-graph-detailed/receiverCalls.d.ts.map +1 -0
  12. package/dist/graphs/symbol-graph-detailed/receiverCalls.js +408 -0
  13. package/dist/graphs/symbol-graph-detailed/receiverCalls.js.map +1 -0
  14. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  15. package/dist/graphs/symbol-graph-detailed.js +22 -0
  16. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  17. package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
  18. package/dist/indexer/build-cache/manifest.js +8 -1
  19. package/dist/indexer/build-cache/manifest.js.map +1 -1
  20. package/dist/indexer/build-cache/options.d.ts +7 -1
  21. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  22. package/dist/indexer/build-cache/options.js +7 -1
  23. package/dist/indexer/build-cache/options.js.map +1 -1
  24. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  25. package/dist/indexer/build-cache/project-snapshot.js +30 -1
  26. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  27. package/dist/indexer/build-index.d.ts.map +1 -1
  28. package/dist/indexer/build-index.js +1 -61
  29. package/dist/indexer/build-index.js.map +1 -1
  30. package/dist/indexer/expand-star-imports.d.ts +15 -0
  31. package/dist/indexer/expand-star-imports.d.ts.map +1 -0
  32. package/dist/indexer/expand-star-imports.js +95 -0
  33. package/dist/indexer/expand-star-imports.js.map +1 -0
  34. package/dist/indexer/navigation-goto.d.ts +6 -0
  35. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  36. package/dist/indexer/navigation-goto.js +6 -1
  37. package/dist/indexer/navigation-goto.js.map +1 -1
  38. package/dist/util/memberAccess.d.ts.map +1 -1
  39. package/dist/util/memberAccess.js +12 -2
  40. package/dist/util/memberAccess.js.map +1 -1
  41. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -29469,6 +29469,88 @@ var init_locals_and_exports = __esm({
29469
29469
  }
29470
29470
  });
29471
29471
 
29472
+ // dist/indexer/expand-star-imports.js
29473
+ function symbolsForStarImport(target) {
29474
+ const localExports = [];
29475
+ for (const entry of target.exports) {
29476
+ if (entry.type === "local") {
29477
+ localExports.push({ name: entry.exportedAs, symbol: entry.target });
29478
+ }
29479
+ }
29480
+ if (localExports.length)
29481
+ return localExports;
29482
+ const visible = [];
29483
+ for (const local of target.locals) {
29484
+ if (local.localName.startsWith("_"))
29485
+ continue;
29486
+ visible.push({ name: local.localName, symbol: local });
29487
+ }
29488
+ return visible;
29489
+ }
29490
+ function expandStarImports(modules, opts) {
29491
+ const expandedImportKey = (binding) => {
29492
+ const typeOnly = binding.typeOnly ?? false;
29493
+ if (binding.kind === "named") {
29494
+ return JSON.stringify(["named", binding.from, binding.resolved, typeOnly, binding.local, binding.imported]);
29495
+ }
29496
+ if (binding.kind === "namespace") {
29497
+ return JSON.stringify(["namespace", binding.from, binding.resolved, typeOnly, binding.localNS]);
29498
+ }
29499
+ return null;
29500
+ };
29501
+ for (const mod2 of modules.values()) {
29502
+ const expandedImportKeys = /* @__PURE__ */ new Set();
29503
+ for (const existing of mod2.imports) {
29504
+ const key = expandedImportKey(existing);
29505
+ if (key)
29506
+ expandedImportKeys.add(key);
29507
+ }
29508
+ for (const imp of [...mod2.imports]) {
29509
+ if (imp.kind !== "star" || typeof imp.resolved !== "string")
29510
+ continue;
29511
+ const target = modules.get(fileIdentityKey(imp.resolved));
29512
+ if (!target)
29513
+ continue;
29514
+ const targetSupport = supportForFile(imp.resolved, opts?.languageExtensions);
29515
+ const exportedSymbols = symbolsForStarImport(target);
29516
+ const seen = /* @__PURE__ */ new Set();
29517
+ for (const { name, symbol: symbol2 } of exportedSymbols) {
29518
+ if (!name || seen.has(name))
29519
+ continue;
29520
+ seen.add(name);
29521
+ const treatAsNamespace = targetSupport?.id === "ruby" && symbol2.kind === SymbolKind.Class;
29522
+ const expandedImport = treatAsNamespace ? {
29523
+ kind: "namespace",
29524
+ localNS: name,
29525
+ from: imp.from,
29526
+ resolved: imp.resolved,
29527
+ ...imp.typeOnly !== void 0 ? { typeOnly: imp.typeOnly } : {}
29528
+ } : {
29529
+ kind: "named",
29530
+ local: name,
29531
+ imported: name,
29532
+ from: imp.from,
29533
+ resolved: imp.resolved,
29534
+ ...imp.typeOnly !== void 0 ? { typeOnly: imp.typeOnly } : {}
29535
+ };
29536
+ const expandedImportKeyValue = expandedImportKey(expandedImport);
29537
+ if (!expandedImportKeyValue || expandedImportKeys.has(expandedImportKeyValue))
29538
+ continue;
29539
+ expandedImportKeys.add(expandedImportKeyValue);
29540
+ mod2.imports.push(expandedImport);
29541
+ }
29542
+ }
29543
+ }
29544
+ }
29545
+ var init_expand_star_imports = __esm({
29546
+ "dist/indexer/expand-star-imports.js"() {
29547
+ "use strict";
29548
+ init_languages();
29549
+ init_paths();
29550
+ init_types2();
29551
+ }
29552
+ });
29553
+
29472
29554
  // dist/languages/queryGenerator.js
29473
29555
  function generateChunkingQuery(def) {
29474
29556
  const parts = [];
@@ -32856,7 +32938,7 @@ var init_options2 = __esm({
32856
32938
  init_projectFiles();
32857
32939
  init_treeSitterNative();
32858
32940
  init_languages();
32859
- CORE_ALGORITHM_EPOCH = 2;
32941
+ CORE_ALGORITHM_EPOCH = 3;
32860
32942
  LANGUAGE_BEHAVIOR_EPOCH = 1;
32861
32943
  }
32862
32944
  });
@@ -51698,11 +51780,14 @@ async function loadManifest(projectRoot, opts, report) {
51698
51780
  return null;
51699
51781
  }
51700
51782
  }
51783
+ function serializeIndexManifest(manifest) {
51784
+ return JSON.stringify(manifest);
51785
+ }
51701
51786
  async function writeManifest2(projectRoot, opts, manifest) {
51702
51787
  try {
51703
51788
  const manifestPath = manifestFilePath(projectRoot, opts);
51704
51789
  await fsp21.mkdir(path41.dirname(manifestPath), { recursive: true });
51705
- await writeManifestAtomically(manifestPath, JSON.stringify(manifest, null, 2));
51790
+ await writeManifestAtomically(manifestPath, serializeIndexManifest(manifest));
51706
51791
  return true;
51707
51792
  } catch (error51) {
51708
51793
  logWithLevel(opts?.logLevel, "warn", "Warning: Failed to write manifest:", error51);
@@ -53000,6 +53085,17 @@ function isSupportedProjectSnapshotVersion(version3) {
53000
53085
  function snapshotHydratesModulesFromDisk(version3) {
53001
53086
  return version3 === PROJECT_SNAPSHOT_VERSION;
53002
53087
  }
53088
+ function mutableModuleIndex(mod2) {
53089
+ if (!Object.isFrozen(mod2) && !Object.isFrozen(mod2.imports) && !Object.isFrozen(mod2.exports) && !Object.isFrozen(mod2.locals)) {
53090
+ return mod2;
53091
+ }
53092
+ return {
53093
+ file: mod2.file,
53094
+ exports: [...mod2.exports],
53095
+ imports: [...mod2.imports],
53096
+ locals: [...mod2.locals]
53097
+ };
53098
+ }
53003
53099
  function modulesForThinSnapshot(index, projectRoot, opts) {
53004
53100
  const modules = [...index.byFile.values()];
53005
53101
  const cachedFiles = listDiskCachedModuleFiles(projectRoot, opts);
@@ -53025,9 +53121,20 @@ function collectSnapshotModules(projectRoot, opts, payload, snapshotPath, identi
53025
53121
  for (const [key, row] of cachedModules) {
53026
53122
  if (modules.has(key))
53027
53123
  continue;
53028
- modules.set(key, freezeSnapshotPayload(row.mod));
53124
+ modules.set(key, row.mod);
53029
53125
  }
53030
53126
  }
53127
+ for (const [key, mod2] of modules) {
53128
+ if (!mod2.imports.some((binding) => binding.kind === "star"))
53129
+ continue;
53130
+ modules.set(key, mutableModuleIndex(mod2));
53131
+ }
53132
+ expandStarImports(modules, opts);
53133
+ for (const [key, mod2] of modules) {
53134
+ if (Object.isFrozen(mod2))
53135
+ continue;
53136
+ modules.set(key, freezeSnapshotPayload(mod2));
53137
+ }
53031
53138
  }
53032
53139
  const entry = { identity, root: projectRoot, modules };
53033
53140
  setBoundedSnapshotCache(hydratedSnapshotModulesCache, snapshotPath, entry);
@@ -53648,6 +53755,7 @@ var init_project_snapshot = __esm({
53648
53755
  init_options2();
53649
53756
  init_module_cache();
53650
53757
  init_location();
53758
+ init_expand_star_imports();
53651
53759
  SNAPSHOT_SYMBOL_KINDS = new Set(Object.values(SymbolKind));
53652
53760
  PROJECT_SNAPSHOT_VERSION = 11;
53653
53761
  LEGACY_EMBEDDED_MODULE_SNAPSHOT_VERSION = 10;
@@ -55998,61 +56106,6 @@ function projectPatternsForLanguageExtensions(opts) {
55998
56106
  return void 0;
55999
56107
  return [...DEFAULT_PROJECT_PATTERNS, ...customPatterns];
56000
56108
  }
56001
- function expandStarImports(modules, opts) {
56002
- const expandedImportKey = (binding) => {
56003
- const typeOnly = binding.typeOnly ?? false;
56004
- if (binding.kind === "named") {
56005
- return JSON.stringify(["named", binding.from, binding.resolved, typeOnly, binding.local, binding.imported]);
56006
- }
56007
- if (binding.kind === "namespace") {
56008
- return JSON.stringify(["namespace", binding.from, binding.resolved, typeOnly, binding.localNS]);
56009
- }
56010
- return null;
56011
- };
56012
- for (const mod2 of modules.values()) {
56013
- const expandedImportKeys = /* @__PURE__ */ new Set();
56014
- for (const existing of mod2.imports) {
56015
- const key = expandedImportKey(existing);
56016
- if (key)
56017
- expandedImportKeys.add(key);
56018
- }
56019
- for (const imp of [...mod2.imports]) {
56020
- if (imp.kind !== "star" || typeof imp.resolved !== "string")
56021
- continue;
56022
- const target = modules.get(fileIdentityKey(imp.resolved));
56023
- if (!target)
56024
- continue;
56025
- const targetSupport = supportForFile(imp.resolved, opts?.languageExtensions);
56026
- const exportedSymbols = target.exports.filter((entry) => entry.type === "local").length ? target.exports.filter((entry) => entry.type === "local").map((entry) => entry.target) : target.locals.filter((local) => !local.localName.startsWith("_"));
56027
- const seen = /* @__PURE__ */ new Set();
56028
- for (const symbol2 of exportedSymbols) {
56029
- if (!symbol2.localName || seen.has(symbol2.localName))
56030
- continue;
56031
- seen.add(symbol2.localName);
56032
- const treatAsNamespace = targetSupport?.id === "ruby" && symbol2.kind === SymbolKind.Class;
56033
- const expandedImport = treatAsNamespace ? {
56034
- kind: "namespace",
56035
- localNS: symbol2.localName,
56036
- from: imp.from,
56037
- resolved: imp.resolved,
56038
- ...imp.typeOnly !== void 0 ? { typeOnly: imp.typeOnly } : {}
56039
- } : {
56040
- kind: "named",
56041
- local: symbol2.localName,
56042
- imported: symbol2.localName,
56043
- from: imp.from,
56044
- resolved: imp.resolved,
56045
- ...imp.typeOnly !== void 0 ? { typeOnly: imp.typeOnly } : {}
56046
- };
56047
- const expandedImportKeyValue = expandedImportKey(expandedImport);
56048
- if (!expandedImportKeyValue || expandedImportKeys.has(expandedImportKeyValue))
56049
- continue;
56050
- expandedImportKeys.add(expandedImportKeyValue);
56051
- mod2.imports.push(expandedImport);
56052
- }
56053
- }
56054
- }
56055
- }
56056
56109
  function toProjectIndexManifestEntry(entry) {
56057
56110
  const cacheSig = entry.cacheSig ?? entry.gitSig;
56058
56111
  return {
@@ -57582,6 +57635,7 @@ var init_build_index = __esm({
57582
57635
  init_projectedTree();
57583
57636
  init_imports();
57584
57637
  init_locals_and_exports();
57638
+ init_expand_star_imports();
57585
57639
  init_shared2();
57586
57640
  init_bloomFilter();
57587
57641
  init_nativeBackendReport();
@@ -57646,7 +57700,7 @@ function memberAccessTraversalTypes(sup) {
57646
57700
  }
57647
57701
  function isMemberAccessNode(sup, node) {
57648
57702
  const memberExpressionType = memberExpressionTypeFor(sup);
57649
- return node.type === memberExpressionType || sup.id === "go" && node.type === "qualified_type" || sup.id === "php" && (node.type === "member_call_expression" || node.type === "scoped_call_expression") || node.type === "member_access_expression" || node.type === "qualified_name" || node.type === "field_access" || node.type === "method_invocation" || node.type === "scoped_identifier" || node.type === "scoped_type_identifier" || node.type === "call" || node.type === "scope_resolution" || node.type === "field_expression" || node.type === "attribute" || node.type === "navigation_expression";
57703
+ return node.type === memberExpressionType || sup.id === "go" && node.type === "qualified_type" || sup.id === "php" && (node.type === "member_call_expression" || node.type === "nullsafe_member_call_expression" || node.type === "scoped_call_expression") || node.type === "member_access_expression" || node.type === "qualified_name" || node.type === "field_access" || node.type === "method_invocation" || node.type === "scoped_identifier" || node.type === "scoped_type_identifier" || node.type === "qualified_identifier" || node.type === "call" || node.type === "scope_resolution" || node.type === "field_expression" || node.type === "attribute" || node.type === "navigation_expression";
57650
57704
  }
57651
57705
  function isMemberObjectIdentifier(nodeType) {
57652
57706
  return nodeType === "identifier" || nodeType === "type_identifier" || nodeType === "package_identifier" || nodeType === "constant" || nodeType === "namespace_identifier";
@@ -57667,6 +57721,12 @@ function fieldParts(node, objectField, propertyField) {
57667
57721
  };
57668
57722
  }
57669
57723
  function getMemberAccessParts(sup, memberNode) {
57724
+ if (sup.id === "c" || sup.id === "cpp") {
57725
+ if (memberNode.type === "field_expression")
57726
+ return fieldParts(memberNode, "argument", "field");
57727
+ if (memberNode.type === "qualified_identifier")
57728
+ return fieldParts(memberNode, "scope", "name");
57729
+ }
57670
57730
  if (sup.id === "python") {
57671
57731
  return fieldParts(memberNode, "object", "attribute");
57672
57732
  }
@@ -57691,7 +57751,7 @@ function getMemberAccessParts(sup, memberNode) {
57691
57751
  return fieldParts(memberNode, "receiver", "method");
57692
57752
  }
57693
57753
  if (sup.id === "php") {
57694
- if (memberNode.type === "member_call_expression") {
57754
+ if (memberNode.type === "member_call_expression" || memberNode.type === "nullsafe_member_call_expression") {
57695
57755
  return fieldParts(memberNode, "object", "name");
57696
57756
  }
57697
57757
  if (memberNode.type === "scoped_call_expression") {
@@ -57770,6 +57830,23 @@ var init_memberAccess = __esm({
57770
57830
  });
57771
57831
 
57772
57832
  // dist/graphs/symbol-graph-detailed/ast.js
57833
+ function functionNameNode(node) {
57834
+ const named = node.childForFieldName("name");
57835
+ if (named)
57836
+ return named;
57837
+ let current = node.childForFieldName("declarator");
57838
+ while (current) {
57839
+ if (current.type === "identifier" || current.type === "field_identifier")
57840
+ return current;
57841
+ const nested = current.childForFieldName("declarator");
57842
+ if (nested) {
57843
+ current = nested;
57844
+ continue;
57845
+ }
57846
+ return current.namedChildren.find((child) => child.type === "identifier" || child.type === "field_identifier") ?? null;
57847
+ }
57848
+ return node.childForFieldName("type");
57849
+ }
57773
57850
  function collectDetailedDeclarations(rootNode, sup, source, locals) {
57774
57851
  const functionNodes = [];
57775
57852
  const classNodes = [];
@@ -57787,6 +57864,7 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57787
57864
  "function_item",
57788
57865
  "function_signature_item",
57789
57866
  "method",
57867
+ "protocol_function_declaration",
57790
57868
  "singleton_method"
57791
57869
  ]);
57792
57870
  const typeNodeTypes = /* @__PURE__ */ new Set([
@@ -57796,8 +57874,10 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57796
57874
  "class_definition",
57797
57875
  "class",
57798
57876
  "interface_declaration",
57877
+ "module",
57799
57878
  "protocol_declaration",
57800
57879
  "trait_item",
57880
+ "trait_declaration",
57801
57881
  "struct_item",
57802
57882
  "struct_declaration",
57803
57883
  "class_specifier",
@@ -57817,7 +57897,7 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57817
57897
  };
57818
57898
  const walk = (node) => {
57819
57899
  if (functionNodeTypes.has(node.type)) {
57820
- const nameNode = node.childForFieldName("name") ?? node.childForFieldName("type");
57900
+ const nameNode = functionNameNode(node);
57821
57901
  const name = nameNode ? sliceText(nameNode, source) : void 0;
57822
57902
  if (name) {
57823
57903
  const def = findDefinition(name, nameNode);
@@ -57922,958 +58002,1963 @@ var init_ast2 = __esm({
57922
58002
  }
57923
58003
  });
57924
58004
 
57925
- // dist/graphs/symbol-graph-detailed/edgePasses.js
57926
- function ensureNode(context, def) {
57927
- const id = defNodeId(def);
57928
- if (!context.nodes.has(id))
57929
- context.nodes.set(id, nodeForDef(def));
57930
- return id;
57931
- }
57932
- function markImplementationTarget(context, id, declarationNode, def) {
57933
- const declaration = sliceText(declarationNode, context.source);
57934
- const nameIndex = declaration.indexOf(def.localName);
57935
- const prefix = nameIndex >= 0 ? declaration.slice(0, nameIndex) : declaration;
57936
- if (!/\b(?:abstract|virtual|override)\b/.test(prefix))
57937
- return;
57938
- const node = context.nodes.get(id);
57939
- if (node)
57940
- node.implementationTarget = true;
57941
- }
57942
- function markMemberArity(context, id, declarationNode) {
57943
- let parameters = declarationNode.childForFieldName("parameters");
57944
- if (!parameters) {
57945
- for (const type of [
57946
- "formal_parameters",
57947
- "parameter_list",
57948
- "parameters",
57949
- "method_parameters",
57950
- "function_parameter_clause"
57951
- ]) {
57952
- parameters = findFirstNodeByType(declarationNode, type);
57953
- if (parameters)
57954
- break;
57955
- }
58005
+ // dist/indexer/navigation-provenance.js
58006
+ function getNavigationBackend(index) {
58007
+ if (index.nativeMode === "on") {
58008
+ return "native";
57956
58009
  }
57957
- if (!parameters)
57958
- return;
57959
- const arity = (parameters.namedChildren ?? []).filter((child) => child.type !== "comment").length;
57960
- const node = context.nodes.get(id);
57961
- if (node)
57962
- node.memberArity = arity;
58010
+ if (index.nativeMode === "off") {
58011
+ return "graph-only";
58012
+ }
58013
+ return void 0;
57963
58014
  }
57964
- function recordDefEdge(context, fromId, target, label, siteNode) {
57965
- const toId = ensureNode(context, target);
57966
- return context.recordEdge(fromId, toId, label, siteNode ? { file: context.moduleEntry.file, range: toRange(siteNode) } : void 0);
58015
+ function createNavigationProvenance(index, resolution, confidence) {
58016
+ const backend = getNavigationBackend(index);
58017
+ return {
58018
+ ...backend ? { backend } : {},
58019
+ ...resolution ? { resolution } : {},
58020
+ ...confidence ? { confidence } : {}
58021
+ };
57967
58022
  }
57968
- function tryResolveChain(context, node, fromId, label = "uses") {
57969
- const targetDef = context.resolveMemberChainTarget(node);
57970
- if (targetDef && fromId) {
57971
- recordDefEdge(context, fromId, targetDef, label, node);
57972
- return true;
57973
- }
57974
- return !!targetDef;
58023
+ function okGoToResult(index, definition, options) {
58024
+ return {
58025
+ status: "ok",
58026
+ definition,
58027
+ ...options.via ? { via: options.via } : {},
58028
+ provenance: createNavigationProvenance(index, options.resolution, options.confidence)
58029
+ };
57975
58030
  }
57976
- function tryResolveNode(context, node, fromId, label) {
57977
- if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
57978
- const name = sliceText(node, context.source);
57979
- const target = context.resolveIdentifier(name);
57980
- if (target) {
57981
- recordDefEdge(context, fromId, target, label, node);
57982
- return;
57983
- }
58031
+ var init_navigation_provenance = __esm({
58032
+ "dist/indexer/navigation-provenance.js"() {
58033
+ "use strict";
57984
58034
  }
57985
- if (context.optionalMemberTypes.has(node.type)) {
57986
- tryResolveChain(context, node, fromId, label);
58035
+ });
58036
+
58037
+ // dist/indexer/navigation-goto.js
58038
+ async function resolveMemberAccessDefinition(params) {
58039
+ const { index, mod: mod2, node, source, sup, resolveLexicalBinding } = params;
58040
+ const parent = node.parent;
58041
+ if (!parent || !sup.supportsCrossModuleSymbols || !isMemberAccessNode(sup, parent)) {
58042
+ return null;
57987
58043
  }
57988
- }
57989
- function getCallTarget(node) {
57990
- const explicitTarget = node.childForFieldName("function") ?? node.childForFieldName("callee") ?? node.childForFieldName("name") ?? node.childForFieldName("method") ?? node.childForFieldName("member") ?? node.childForFieldName("expression");
57991
- if (explicitTarget)
57992
- return explicitTarget;
57993
- const nonArgumentChildren = node.namedChildren.filter((child) => child.type !== "argument_list");
57994
- return nonArgumentChildren.length === 1 ? nonArgumentChildren[0] ?? null : null;
57995
- }
57996
- function getNewTarget(node) {
57997
- return node.childForFieldName("constructor") ?? node.childForFieldName("type") ?? node.childForFieldName("name") ?? node.namedChildren.find((child) => child.type === "type_identifier") ?? node.child(0);
57998
- }
57999
- function emitPythonDecoratorEdges(context, rootNode) {
58000
- if (context.sup.id !== "python")
58001
- return;
58002
- const addDecoratorUses = (node) => {
58003
- if (node.type === "decorated_definition") {
58004
- const fn = node.namedChildren.find((child) => child.type === "function_definition");
58005
- if (fn)
58006
- addDecoratorUses(fn);
58007
- for (const decoratorChild of node.namedChildren) {
58008
- if (decoratorChild.type !== "decorator")
58009
- continue;
58010
- const nameNode = fn?.childForFieldName("name");
58011
- if (!nameNode)
58012
- continue;
58013
- const name = sliceText(nameNode, context.source);
58014
- const def = context.moduleEntry.locals.find((local) => local.localName === name);
58015
- if (!def)
58016
- continue;
58017
- const fromId = ensureNode(context, def);
58018
- const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
58019
- if (expr)
58020
- tryResolveNode(context, expr, fromId, "decorates");
58021
- }
58022
- } else if (node.type === "function_definition") {
58023
- const nameNode = node.childForFieldName("name");
58024
- if (nameNode) {
58025
- const name = sliceText(nameNode, context.source);
58026
- const def = context.moduleEntry.locals.find((local) => local.localName === name);
58027
- if (def) {
58028
- const fromId = ensureNode(context, def);
58029
- let prev = node.previousSibling;
58030
- while (prev) {
58031
- if (prev.type === "decorated_definition") {
58032
- for (const decoratorChild of prev.namedChildren) {
58033
- if (decoratorChild.type === "decorator") {
58034
- const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
58035
- if (expr)
58036
- tryResolveNode(context, expr, fromId, "decorates");
58037
- } else if (decoratorChild.type === "attribute") {
58038
- tryResolveNode(context, decoratorChild, fromId, "decorates");
58039
- }
58040
- }
58041
- } else if (prev.type === "decorator") {
58042
- const expr = prev.childForFieldName?.("name") ?? prev.namedChildren?.[0] ?? prev.child(1);
58043
- if (expr)
58044
- tryResolveNode(context, expr, fromId, "decorates");
58045
- }
58046
- prev = prev.previousSibling;
58044
+ const memberNode = parent;
58045
+ const { object: obj, property: prop } = getMemberAccessParts(sup, memberNode);
58046
+ const optionalMemberTypes = memberAccessTraversalTypes(sup);
58047
+ const resolveExpression = async (expr) => {
58048
+ const exprIsId = sup.nodeTypes.identifier.includes(expr.type) && !isMemberAccessNode(sup, expr);
58049
+ if (exprIsId || expr.type === "identifier" || expr.type === "type_identifier" || expr.type === "constant") {
58050
+ const lexicalBinding = resolveLexicalBinding?.(expr);
58051
+ if (lexicalBinding)
58052
+ return { kind: "resolved", def: lexicalBinding };
58053
+ const exprName = sliceText(expr, source);
58054
+ const imp = mod2.imports.find((candidate) => candidate.kind === "named" && candidate.local === exprName || candidate.kind === "default" && candidate.local === exprName || candidate.kind === "namespace" && candidate.localNS === exprName);
58055
+ if (imp) {
58056
+ if (imp.kind === "namespace") {
58057
+ return {
58058
+ kind: "namespace",
58059
+ file: typeof imp.resolved === "string" ? imp.resolved.replace(/\\/g, "/") : imp.resolved?.external || ""
58060
+ };
58061
+ }
58062
+ const result = resolveImported(index, imp, imp.kind === "named" ? imp.imported : "default");
58063
+ if (result) {
58064
+ if ("namespace" in result) {
58065
+ return { kind: "namespace", file: result.namespace };
58047
58066
  }
58067
+ return { kind: "resolved", def: result };
58048
58068
  }
58049
58069
  }
58050
- }
58051
- for (const child of node.namedChildren)
58052
- addDecoratorUses(child);
58053
- };
58054
- addDecoratorUses(rootNode);
58055
- }
58056
- function emitMemberOwnershipEdges(context, functionNodes, classNodes) {
58057
- for (const fn of functionNodes) {
58058
- const owners = classNodes.filter((candidate) => candidate.node.startIndex <= fn.node.startIndex && candidate.node.endIndex >= fn.node.endIndex).sort((left, right) => left.node.endIndex - left.node.startIndex - (right.node.endIndex - right.node.startIndex));
58059
- const owner = owners[0];
58060
- if (!owner)
58061
- continue;
58062
- const memberId = ensureNode(context, fn.def);
58063
- markImplementationTarget(context, memberId, fn.node, fn.def);
58064
- markMemberArity(context, memberId, fn.node);
58065
- recordDefEdge(context, memberId, owner.def, "member_of");
58066
- }
58067
- }
58068
- function emitFunctionBodyEdges(context, functionNodes) {
58069
- const callNodeTypes = /* @__PURE__ */ new Set(["call_expression", "call", "method_invocation", "invocation_expression"]);
58070
- const newNodeTypes = /* @__PURE__ */ new Set([
58071
- "new_expression",
58072
- "object_creation_expression",
58073
- "struct_expression",
58074
- "composite_literal"
58075
- ]);
58076
- for (const fn of functionNodes) {
58077
- const fromId = ensureNode(context, fn.def);
58078
- const seenAliases = /* @__PURE__ */ new Set();
58079
- const nestedFunctions = new Set(functionNodes.filter((candidate) => candidate.node !== fn.node && candidate.node.startIndex >= fn.node.startIndex && candidate.node.endIndex <= fn.node.endIndex).map((candidate) => candidate.node));
58080
- const recordAliasUse = (node) => {
58081
- if (context.membersOnly || !isIdentifierType(context.sup, node.type))
58082
- return;
58083
- const name = sliceText(node, context.source);
58084
- if (seenAliases.has(name))
58085
- return;
58086
- let target = context.aliasToTargetDef.get(name) ?? null;
58087
- if (!target) {
58088
- const modFile = context.aliasToTargetModule.get(name);
58089
- if (modFile) {
58090
- let exportedName = null;
58091
- const parent = node.parent;
58092
- if (parent && (parent.type === context.memberExpressionType || parent.type === "optional_member_expression")) {
58093
- const { property: prop } = getMemberAccessParts(context.sup, parent);
58094
- if (prop && context.propertyIdentifierTypes.includes(prop.type)) {
58095
- exportedName = sliceText(prop, context.source);
58096
- }
58097
- }
58098
- if (exportedName) {
58099
- target = context.resolveExportFrom(modFile, exportedName);
58100
- if (!target) {
58101
- const targetModule = context.index.byFile.get(fileIdentityKey(modFile));
58102
- target = (targetModule?.locals ?? []).find((local) => local.localName === exportedName) ?? null;
58103
- }
58070
+ const local = mod2.locals.find((candidate) => candidate.localName === exprName);
58071
+ if (local)
58072
+ return { kind: "resolved", def: local };
58073
+ for (const starImport of mod2.imports.filter((candidate) => candidate.kind === "star")) {
58074
+ const result = resolveImported(index, starImport, exprName);
58075
+ if (result) {
58076
+ if ("namespace" in result) {
58077
+ return { kind: "namespace", file: result.namespace };
58104
58078
  }
58079
+ return { kind: "resolved", def: result };
58105
58080
  }
58106
58081
  }
58107
- if (!target)
58108
- return;
58109
- seenAliases.add(name);
58110
- recordDefEdge(context, fromId, target, "uses");
58111
- };
58112
- const recordMemberUse = (node) => {
58113
- if (!context.optionalMemberTypes.has(node.type))
58114
- return;
58115
- const targetDef = context.resolveMemberChainTarget(node);
58116
- if (targetDef) {
58117
- recordDefEdge(context, fromId, targetDef, "uses");
58082
+ return null;
58083
+ }
58084
+ if (optionalMemberTypes.has(expr.type)) {
58085
+ const parts = getMemberAccessParts(sup, expr);
58086
+ const subObj = parts.object;
58087
+ let subProp = parts.property;
58088
+ if (!subProp && expr.type === "navigation_expression") {
58089
+ subProp = getNavigationExpressionProperty(expr);
58118
58090
  }
58119
- };
58120
- const recordCallOrInstantiation = (node) => {
58121
- if (callNodeTypes.has(node.type)) {
58122
- if (context.sup.id === "go") {
58123
- const callTarget = getCallTarget(node);
58124
- const calleeName = callTarget && isIdentifierType(context.sup, callTarget.type) ? sliceText(callTarget, context.source) : null;
58125
- if (calleeName === "new" || calleeName === "make") {
58126
- const argList = node.childForFieldName("arguments") ?? node.childForFieldName("argument_list");
58127
- const typeNode = argList?.namedChildren?.find((child) => child.type === "type_identifier") ?? null;
58128
- if (typeNode) {
58129
- tryResolveNode(context, typeNode, fromId, "instantiates");
58130
- }
58131
- return false;
58132
- }
58091
+ if (subObj && subProp) {
58092
+ const base = await resolveExpression(subObj);
58093
+ const memberName = sliceText(subProp, source);
58094
+ if (base?.kind === "namespace") {
58095
+ return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
58133
58096
  }
58134
- if (context.sup.id === "ruby" && node.type === "call") {
58135
- const methodNode = node.childForFieldName("method");
58136
- const receiverNode = node.childForFieldName("receiver");
58137
- const methodName = methodNode ? sliceText(methodNode, context.source) : null;
58138
- if (methodName === "new" && receiverNode) {
58139
- tryResolveNode(context, receiverNode, fromId, "instantiates");
58140
- return false;
58097
+ if (base?.kind === "resolved") {
58098
+ if (sup.id === "java") {
58099
+ const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
58100
+ return memberDef ? { kind: "resolved", def: memberDef } : null;
58141
58101
  }
58142
- if (methodNode) {
58143
- tryResolveNode(context, methodNode, fromId, "calls");
58144
- return false;
58102
+ if (sup.id === "ruby") {
58103
+ const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
58104
+ if (memberDef)
58105
+ return { kind: "resolved", def: memberDef };
58106
+ const localHit = resolveExport(index, base.def.file, memberName);
58107
+ if (localHit)
58108
+ return localHit;
58145
58109
  }
58110
+ return null;
58146
58111
  }
58147
- const callee = getCallTarget(node);
58148
- if (callee)
58149
- tryResolveNode(context, callee, fromId, "calls");
58150
- }
58151
- if (newNodeTypes.has(node.type)) {
58152
- const target = getNewTarget(node);
58153
- if (target)
58154
- tryResolveNode(context, target, fromId, "instantiates");
58155
58112
  }
58156
- return true;
58157
- };
58158
- const walkFunctionBody = (node, allowCallProcessing) => {
58159
- if (node !== fn.node && nestedFunctions.has(node))
58160
- return;
58161
- recordAliasUse(node);
58162
- recordMemberUse(node);
58163
- const allowChildCallProcessing = allowCallProcessing ? recordCallOrInstantiation(node) : false;
58164
- for (const child of node.namedChildren ?? [])
58165
- walkFunctionBody(child, allowChildCallProcessing);
58166
- };
58167
- walkFunctionBody(fn.node, true);
58168
- }
58169
- }
58170
- function recordIdentifierRelations(context, fromId, container, relationForTarget) {
58171
- const identifiers = [];
58172
- const collect = (node) => {
58173
- if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
58174
- identifiers.push(node);
58175
- return;
58176
58113
  }
58177
- for (const child of node.namedChildren ?? [])
58178
- collect(child);
58179
- };
58180
- collect(container);
58181
- const seen = /* @__PURE__ */ new Set();
58182
- for (const [index, identifier] of identifiers.entries()) {
58183
- const target = context.resolveIdentifier(sliceText(identifier, context.source));
58184
- if (!target)
58185
- continue;
58186
- const targetId = defNodeId(target);
58187
- if (seen.has(targetId))
58188
- continue;
58189
- seen.add(targetId);
58190
- recordDefEdge(context, fromId, target, relationForTarget(target, index), identifier);
58191
- }
58192
- }
58193
- function collectDirectCallsExcludingNestedScopes(node, out) {
58194
- for (const child of node.namedChildren ?? []) {
58195
- if (child.type === "call")
58196
- out.push(child);
58197
- if (RUBY_NESTED_SCOPE_TYPES.has(child.type))
58198
- continue;
58199
- collectDirectCallsExcludingNestedScopes(child, out);
58200
- }
58201
- }
58202
- function emitClassInheritanceEdges(context, classNodes) {
58203
- const interfaceIds = new Set(classNodes.filter((candidate) => candidate.node.type === "interface_declaration" || candidate.node.type === "protocol_declaration" || candidate.node.type === "trait_item" || /^(?:interface|protocol|trait)\b/.test(sliceText(candidate.node, context.source).trimStart())).map((candidate) => defNodeId(candidate.def)));
58204
- for (const cls of classNodes) {
58205
- const fromId = ensureNode(context, cls.def);
58206
- markImplementationTarget(context, fromId, cls.node, cls.def);
58207
- if (context.sup.id === "java") {
58208
- const superClass = findFirstNodeByType(cls.node, "superclass");
58209
- const superNode2 = superClass?.childForFieldName("name") ?? superClass?.namedChildren?.[0] ?? null;
58210
- if (superNode2)
58211
- tryResolveNode(context, superNode2, fromId, "extends");
58212
- const interfaces = findFirstNodeByType(cls.node, "super_interfaces");
58213
- if (interfaces) {
58214
- const names = [];
58215
- collectIdentifiers(interfaces, context.sup, context.source, names);
58216
- for (const name of names) {
58217
- const target = context.resolveIdentifier(name);
58218
- if (target)
58219
- recordDefEdge(context, fromId, target, "implements", interfaces);
58114
+ if (sup.id === "java" && (expr.type === "scoped_identifier" || expr.type === "scoped_type_identifier")) {
58115
+ const subObj = expr.childForFieldName("scope") ?? expr.child(0);
58116
+ const subProp = expr.childForFieldName("name") ?? expr.child(2);
58117
+ if (subObj && subProp) {
58118
+ const base = await resolveExpression(subObj);
58119
+ const memberName = sliceText(subProp, source);
58120
+ if (base?.kind === "namespace") {
58121
+ return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
58122
+ }
58123
+ if (base?.kind === "resolved") {
58124
+ const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
58125
+ return memberDef ? { kind: "resolved", def: memberDef } : null;
58220
58126
  }
58221
58127
  }
58222
- continue;
58223
- }
58224
- if (context.sup.id === "csharp") {
58225
- const baseList = findFirstNodeByType(cls.node, "base_list");
58226
- if (baseList) {
58227
- recordIdentifierRelations(context, fromId, baseList, (target, index) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
58228
- }
58229
- continue;
58230
- }
58231
- if (context.sup.id === "python") {
58232
- const bases = cls.node.childForFieldName("superclasses") ?? findFirstNodeByType(cls.node, "argument_list");
58233
- if (bases)
58234
- recordIdentifierRelations(context, fromId, bases, () => "extends");
58235
- continue;
58236
58128
  }
58237
- if (context.sup.id === "php") {
58238
- const base = findFirstNodeByType(cls.node, "base_clause");
58239
- if (base)
58240
- recordIdentifierRelations(context, fromId, base, () => "extends");
58241
- const interfaces = findFirstNodeByType(cls.node, "class_interface_clause");
58242
- if (interfaces)
58243
- recordIdentifierRelations(context, fromId, interfaces, () => "implements");
58244
- const traitUses = [];
58245
- collectNodesByType(cls.node, "use_declaration", traitUses);
58246
- for (const traitUse of traitUses)
58247
- recordIdentifierRelations(context, fromId, traitUse, () => "trait");
58248
- continue;
58249
- }
58250
- if (context.sup.id === "ruby") {
58251
- const superclass = findFirstNodeByType(cls.node, "superclass");
58252
- if (superclass)
58253
- recordIdentifierRelations(context, fromId, superclass, () => "extends");
58254
- const calls = [];
58255
- collectDirectCallsExcludingNestedScopes(cls.node, calls);
58256
- for (const call of calls) {
58257
- if (call.childForFieldName("receiver"))
58258
- continue;
58259
- const methodNode = call.childForFieldName("method");
58260
- const methodName = methodNode ? sliceText(methodNode, context.source) : void 0;
58261
- if (methodName !== "include" && methodName !== "extend" && methodName !== "prepend")
58262
- continue;
58263
- const args = call.childForFieldName("arguments");
58264
- if (args)
58265
- recordIdentifierRelations(context, fromId, args, () => "mixin");
58266
- }
58267
- continue;
58268
- }
58269
- if (context.sup.id === "cpp") {
58270
- const bases = findFirstNodeByType(cls.node, "base_class_clause");
58271
- if (bases)
58272
- recordIdentifierRelations(context, fromId, bases, () => "extends");
58273
- continue;
58129
+ return null;
58130
+ };
58131
+ const chain = await resolveExpression(memberNode);
58132
+ if (chain && prop && node.id === prop.id) {
58133
+ if (chain.kind === "resolved") {
58134
+ return okGoToResult(index, chain.def, {
58135
+ via: { exportedName: sliceText(prop, source) },
58136
+ resolution: "member-access",
58137
+ confidence: "medium"
58138
+ });
58274
58139
  }
58275
- if (context.sup.id === "kotlin") {
58276
- const bases = findFirstNodeByType(cls.node, "delegation_specifiers");
58277
- if (bases) {
58278
- recordIdentifierRelations(context, fromId, bases, (target, index) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
58140
+ if (chain.kind === "namespace") {
58141
+ const targetMod = index.byFile.get(fileIdentityKey(chain.file));
58142
+ const first = targetMod?.exports.find((entry) => entry.type === "local");
58143
+ if (first) {
58144
+ return okGoToResult(index, first.target, {
58145
+ via: { exportedName: first.exportedAs },
58146
+ resolution: "namespace",
58147
+ confidence: "medium"
58148
+ });
58279
58149
  }
58280
- continue;
58281
58150
  }
58282
- if (context.sup.id === "swift") {
58283
- const bases = [];
58284
- collectNodesByType(cls.node, "inheritance_specifier", bases);
58285
- for (const [index, base] of bases.entries()) {
58286
- recordIdentifierRelations(context, fromId, base, (target) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
58151
+ }
58152
+ const receiverName = obj ? sliceText(obj, source) : "";
58153
+ const implicitClassReceiver = isJsTsLanguage(sup.id) && receiverName === "this" || sup.id === "php" && /^(?:\$this|self|static)$/.test(receiverName) || sup.id === "rust" && /^(?:self|Self)$/.test(receiverName);
58154
+ if (obj && prop && node.id === prop.id && (supportsReceiverMemberResolution(sup.id) || implicitClassReceiver)) {
58155
+ const member = sliceText(prop, source);
58156
+ if (!sup.membersAreImplicitlyInScope && implicitClassReceiver) {
58157
+ const classContainer = findEnclosingClassContainer(node);
58158
+ const memberDef = classContainer ? findLocalWithinNode(mod2.locals, member, classContainer, sup.normalizeIdentifier) : void 0;
58159
+ if (memberDef) {
58160
+ return okGoToResult(index, memberDef, {
58161
+ via: { exportedName: member },
58162
+ resolution: "member-access",
58163
+ confidence: "medium"
58164
+ });
58287
58165
  }
58288
- continue;
58289
58166
  }
58290
- const superClause = findFirstNodeByType(cls.node, "extends_clause");
58291
- const superNode = superClause?.namedChildren?.[0] ?? superClause?.child(1);
58292
- if (superNode)
58293
- tryResolveNode(context, superNode, fromId, "extends");
58294
- const implementsClauses = [];
58295
- collectNodesByType(cls.node, "implements_clause", implementsClauses);
58296
- for (const clause of implementsClauses) {
58297
- const names = [];
58298
- collectIdentifiers(clause, context.sup, context.source, names);
58299
- for (const name of names) {
58300
- const target = context.resolveIdentifier(name);
58301
- if (target)
58302
- recordDefEdge(context, fromId, target, "implements", clause);
58167
+ const objDef = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
58168
+ if (objDef) {
58169
+ const targetContext = await ensureParsedContext(objDef.file, void 0, index.languageExtensions);
58170
+ const start = objDef.range.start;
58171
+ const targetPosition = {
58172
+ row: start.line - 1,
58173
+ column: start.column - 1
58174
+ };
58175
+ const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
58176
+ const container = nameNode.parent;
58177
+ if (container) {
58178
+ const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
58179
+ if (targetModule) {
58180
+ const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
58181
+ const memberDef = targetContext.sup.id === "java" ? findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier) : findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier);
58182
+ if (memberDef) {
58183
+ return okGoToResult(index, memberDef, {
58184
+ via: { exportedName: member },
58185
+ resolution: "member-access",
58186
+ confidence: "medium"
58187
+ });
58188
+ }
58189
+ }
58303
58190
  }
58304
58191
  }
58305
58192
  }
58193
+ return null;
58306
58194
  }
58307
- function emitRustImplEdges(context, rootNode) {
58308
- if (context.sup.id !== "rust")
58309
- return;
58310
- const walkImpls = (node) => {
58311
- if (node.type === "impl_item") {
58312
- const typeIdentifiers = node.namedChildren?.filter((child) => child.type === "type_identifier") ?? [];
58313
- if (typeIdentifiers.length >= 2) {
58314
- const traitName = sliceText(typeIdentifiers[0], context.source);
58315
- const typeName = sliceText(typeIdentifiers[1], context.source);
58316
- const typeDef = context.resolveIdentifier(typeName);
58317
- const traitDef = context.resolveIdentifier(traitName);
58318
- if (typeDef && traitDef) {
58319
- const fromId = ensureNode(context, typeDef);
58320
- recordDefEdge(context, fromId, traitDef, "implements", node);
58321
- }
58322
- }
58195
+ function findEnclosingClassContainer(node) {
58196
+ let current = node.parent;
58197
+ while (current) {
58198
+ if (current.type === "class_declaration" || current.type === "abstract_class_declaration" || current.type === "class_definition" || current.type === "impl_item") {
58199
+ return current;
58323
58200
  }
58324
- for (const child of node.namedChildren ?? [])
58325
- walkImpls(child);
58326
- };
58327
- walkImpls(rootNode);
58328
- }
58329
- function emitMemberImplementationEdges(graph, recordEdge) {
58330
- const membersByOwner = /* @__PURE__ */ new Map();
58331
- for (const edge of graph.edges) {
58332
- if (edge.label !== "member_of")
58333
- continue;
58334
- const members = membersByOwner.get(edge.to) ?? [];
58335
- members.push(edge.from);
58336
- membersByOwner.set(edge.to, members);
58201
+ current = current.parent;
58337
58202
  }
58338
- const hierarchyByKey = /* @__PURE__ */ new Map();
58339
- for (const edge of graph.edges) {
58340
- if (edge.label !== "extends" && edge.label !== "implements" && edge.label !== "trait" && edge.label !== "mixin")
58341
- continue;
58342
- const key = `${edge.from}->${edge.to}::${edge.label}`;
58343
- const existing = hierarchyByKey.get(key);
58344
- if (!existing || !existing.site && edge.site)
58345
- hierarchyByKey.set(key, edge);
58203
+ return null;
58204
+ }
58205
+ function supportsReceiverMemberResolution(languageId) {
58206
+ return languageId === "csharp" || languageId === "python" || languageId === "js" || languageId === "java" || languageId === "javascript" || languageId === "jsx" || languageId === "rust" || languageId === "ts" || languageId === "typescript" || languageId === "tsx";
58207
+ }
58208
+ async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
58209
+ const constructor = receiverConstructorExpression(obj, source, sup);
58210
+ if (constructor) {
58211
+ const result = await resolveExpression(constructor);
58212
+ if (result?.kind === "resolved") {
58213
+ return result.def;
58214
+ }
58346
58215
  }
58347
- const hierarchyEdges = [...hierarchyByKey.values()];
58348
- for (const hierarchyEdge of hierarchyEdges) {
58349
- const parentMembers = membersByOwner.get(hierarchyEdge.to) ?? [];
58350
- const childMembers = membersByOwner.get(hierarchyEdge.from) ?? [];
58351
- for (const parentMemberId of parentMembers) {
58352
- const parentMember = graph.nodes.get(parentMemberId);
58353
- if (!parentMember)
58354
- continue;
58355
- if (parentMember.memberArity === void 0)
58356
- continue;
58357
- const parentIdentityMatches = parentMembers.filter((memberId) => {
58358
- const candidate = graph.nodes.get(memberId);
58359
- return candidate?.name === parentMember.name && candidate.memberArity === parentMember.memberArity;
58360
- });
58361
- if (parentIdentityMatches.length !== 1)
58362
- continue;
58363
- const isContractMember = hierarchyEdge.label !== "extends" || parentMember.implementationTarget;
58364
- if (!isContractMember)
58365
- continue;
58366
- const compatibleMembers = childMembers.filter((memberId) => {
58367
- const childMember = graph.nodes.get(memberId);
58368
- return childMember?.name === parentMember.name && childMember.memberArity === parentMember.memberArity;
58369
- });
58370
- if (compatibleMembers.length !== 1)
58371
- continue;
58372
- recordEdge(compatibleMembers[0], parentMemberId, hierarchyEdge.label === "extends" ? "overrides" : "implements_member", hierarchyEdge.site);
58216
+ if (isJsTsLanguage(sup.id)) {
58217
+ if (sup.nodeTypes.identifier.includes(obj.type)) {
58218
+ return null;
58373
58219
  }
58374
58220
  }
58221
+ const direct = await resolveExpression(obj);
58222
+ if (direct?.kind === "resolved") {
58223
+ return direct.def;
58224
+ }
58225
+ return null;
58375
58226
  }
58376
- var RUBY_NESTED_SCOPE_TYPES;
58377
- var init_edgePasses = __esm({
58378
- "dist/graphs/symbol-graph-detailed/edgePasses.js"() {
58379
- "use strict";
58380
- init_ast();
58381
- init_memberAccess();
58382
- init_paths();
58383
- init_symbol_graph();
58384
- init_ast2();
58385
- RUBY_NESTED_SCOPE_TYPES = /* @__PURE__ */ new Set(["class", "module", "method", "singleton_method", "block", "do_block"]);
58227
+ function receiverConstructorExpression(obj, source, sup) {
58228
+ if (obj.type === "new_expression" || obj.type === "object_creation_expression") {
58229
+ return constructorNameNode(obj, sup);
58386
58230
  }
58387
- });
58388
-
58389
- // dist/graphs/symbol-graph-detailed/importAliases.js
58390
- function targetModuleForImport(index, imp) {
58391
- const targetFile = typeof imp.resolved === "string" ? normalizePath(imp.resolved) : void 0;
58392
- return targetFile ? index.byFile.get(fileIdentityKey(targetFile)) : void 0;
58231
+ if (sup.id === "ruby" && obj.type === "call") {
58232
+ const rubyConstructor = rubyNewReceiverNameNode(obj, source, sup);
58233
+ if (rubyConstructor)
58234
+ return rubyConstructor;
58235
+ }
58236
+ if (!sup.nodeTypes.identifier.includes(obj.type)) {
58237
+ return null;
58238
+ }
58239
+ const receiverName = sliceText(obj, source);
58240
+ return findVisiblePriorNewConstructor(obj, receiverName, source, sup);
58393
58241
  }
58394
- function buildImportAliasMaps(index, moduleEntry, resolveExportNamespace, resolveExportFrom) {
58395
- const aliasToTargetDef = /* @__PURE__ */ new Map();
58396
- const aliasToTargetModule = /* @__PURE__ */ new Map();
58397
- for (const imp of moduleEntry.imports) {
58398
- const targetModule = targetModuleForImport(index, imp);
58399
- const targetFile = typeof imp.resolved === "string" ? normalizePath(imp.resolved) : void 0;
58400
- if (!targetModule || !targetFile)
58401
- continue;
58402
- if (imp.kind === "named") {
58403
- const localFallback = targetModule.locals.find((local) => local.localName === imp.imported);
58404
- const fallbackResolved = localFallback ? {
58405
- kind: "resolved",
58406
- def: localFallback
58407
- } : null;
58408
- const resolved = resolveExportNamespace(targetFile, imp.imported) ?? fallbackResolved;
58409
- if (resolved?.kind === "resolved") {
58410
- aliasToTargetDef.set(imp.local, resolved.def);
58411
- } else if (resolved?.kind === "namespace") {
58412
- aliasToTargetModule.set(imp.local, normalizePath(resolved.file));
58413
- }
58414
- } else if (imp.kind === "default") {
58415
- const defaultExport = resolveExportFrom(targetFile, "default");
58416
- const fallbackExport = targetModule.exports.find((entry) => entry.type === "local")?.target;
58417
- const def = defaultExport ?? fallbackExport;
58418
- if (def)
58419
- aliasToTargetDef.set(imp.local, def);
58420
- aliasToTargetModule.set(imp.local, targetFile);
58421
- } else if (imp.kind === "namespace") {
58422
- aliasToTargetModule.set(imp.localNS, targetFile);
58242
+ function constructorNameNode(node, sup) {
58243
+ const constructor = node.childForFieldName("constructor") ?? node.child(0);
58244
+ if (constructor && sup.nodeTypes.identifier.includes(constructor.type)) {
58245
+ return constructor;
58246
+ }
58247
+ for (const child of node.namedChildren) {
58248
+ if (sup.nodeTypes.identifier.includes(child.type) || child.type === "type_identifier" || child.type === "constant") {
58249
+ return child;
58423
58250
  }
58424
58251
  }
58425
- return { aliasToTargetDef, aliasToTargetModule };
58252
+ return null;
58426
58253
  }
58427
- var init_importAliases = __esm({
58428
- "dist/graphs/symbol-graph-detailed/importAliases.js"() {
58429
- "use strict";
58430
- init_paths();
58431
- }
58432
- });
58433
-
58434
- // dist/graphs/symbol-graph-detailed/memberChains.js
58435
- function createMemberChainResolver(args) {
58436
- const memberExpressionType = memberExpressionTypeFor(args.sup);
58437
- const propertyIdentifierTypes = memberPropertyIdentifierTypes(args.sup);
58438
- const optionalMemberTypes = memberAccessTraversalTypes(args.sup);
58439
- const resolveMemberChainTarget = (chainNode) => {
58440
- const chain = collectMemberAccessChain({
58441
- sup: args.sup,
58442
- source: args.source,
58443
- chainNode,
58444
- constStringOf: args.constStringOf
58445
- });
58446
- if (!chain || !isIdentifierType(args.sup, chain.base.type))
58447
- return null;
58448
- const alias = sliceText(chain.base, args.source);
58449
- const targetFile = args.aliasToTargetModule.get(alias);
58450
- if (!targetFile)
58451
- return null;
58452
- return args.resolveMemberPathFromModule(targetFile, chain.names);
58453
- };
58454
- return {
58455
- memberExpressionType,
58456
- propertyIdentifierTypes,
58457
- optionalMemberTypes,
58458
- resolveMemberChainTarget
58459
- };
58254
+ function rubyNewReceiverNameNode(node, source, sup) {
58255
+ if (!new RegExp(String.raw`^(?:${RUBY_CONSTANT_SOURCE})\.new$`, "u").test(sliceText(node, source)))
58256
+ return null;
58257
+ return node.namedChildren.find((child) => sup.nodeTypes.identifier.includes(child.type) || child.type === "constant") ?? null;
58460
58258
  }
58461
- var init_memberChains = __esm({
58462
- "dist/graphs/symbol-graph-detailed/memberChains.js"() {
58463
- "use strict";
58464
- init_ast();
58465
- init_memberAccess();
58466
- init_ast2();
58259
+ function rootOf(node) {
58260
+ let current = node;
58261
+ while (current.parent) {
58262
+ current = current.parent;
58467
58263
  }
58468
- });
58469
-
58470
- // dist/graphs/symbol-graph-detailed.js
58471
- async function buildSymbolGraphDetailed(index, opts) {
58472
- assertNativeRequiredAvailable(index.nativeMode);
58473
- const base = await buildSymbolGraph(index, opts?.files ? { files: opts.files } : void 0);
58474
- const configuredMaxEdges = typeof opts?.maxEdges === "number" && opts.maxEdges > 0 ? Math.floor(opts.maxEdges) : void 0;
58475
- const maxEdges = configuredMaxEdges ?? Number.POSITIVE_INFINITY;
58476
- const nodes = new Map(base.nodes);
58477
- const edges = base.edges.slice(0, maxEdges);
58478
- let omittedEdges = Math.max(0, base.edges.length - edges.length);
58479
- let skippedSyntaxTreeFiles = 0;
58480
- const added = /* @__PURE__ */ new Set();
58481
- const membersOnly = !!opts?.membersOnly;
58482
- const scopeMode = opts?.scope ?? "all";
58483
- const importedByOthers = /* @__PURE__ */ new Set();
58484
- if (scopeMode === "imported") {
58485
- for (const moduleEntry of index.byFile.values()) {
58486
- for (const imp of moduleEntry.imports) {
58487
- const target = typeof imp.resolved === "string" ? fileIdentityKey(imp.resolved) : void 0;
58488
- if (target)
58489
- importedByOthers.add(target);
58264
+ return current;
58265
+ }
58266
+ function findVisiblePriorNewConstructor(receiver, receiverName, source, sup) {
58267
+ let current = receiver;
58268
+ while (current) {
58269
+ if (BINDING_CONTAINER_TYPES.has(current.type)) {
58270
+ const constructor = findPriorNewConstructorInContainer(current, receiver, receiverName, source, sup);
58271
+ if (constructor || bindingContainerDeclaresNameBefore(current, receiver, receiverName, source, sup)) {
58272
+ return constructor;
58490
58273
  }
58491
58274
  }
58275
+ current = current.parent;
58492
58276
  }
58493
- let edgeCount = edges.length;
58494
- const maybePushEdge = (fromId, toId, label, site) => {
58495
- if (edgeCount >= maxEdges) {
58496
- omittedEdges += 1;
58497
- return false;
58277
+ return findPriorNewConstructorInContainer(rootOf(receiver), receiver, receiverName, source, sup);
58278
+ }
58279
+ function findPriorNewConstructorInContainer(node, receiver, receiverName, source, sup) {
58280
+ let constructor = null;
58281
+ const visit = (current) => {
58282
+ if (current.startIndex >= receiver.startIndex) {
58283
+ return true;
58498
58284
  }
58499
- edges.push({
58500
- from: fromId,
58501
- to: toId,
58502
- ...label ? { label } : {},
58503
- ...site ? { site } : {}
58504
- });
58505
- edgeCount++;
58506
- return true;
58507
- };
58508
- const recordEdge = (fromId, toId, label, site) => {
58509
- const siteKey = site ? `${site.file}:${site.range.start.index ?? ""}:${site.range.end.index ?? ""}` : "";
58510
- const key = `${fromId}->${toId}::${label ?? ""}::${siteKey}`;
58511
- if (added.has(key))
58285
+ if (current !== node && isSkippableBindingContainer(current, receiver)) {
58512
58286
  return true;
58513
- added.add(key);
58514
- return maybePushEdge(fromId, toId, label, site);
58515
- };
58516
- const resolveExportNamespace = (file2, exportedName) => resolveExport(index, file2, exportedName);
58517
- const resolveExportDef = (file2, exportedName) => {
58518
- const resolved = resolveExportNamespace(file2, exportedName);
58519
- return resolved?.kind === "resolved" ? resolved.def : null;
58520
- };
58521
- const resolveMemberPathFromModule = (startFile, names) => {
58522
- let file2 = normalizePath(startFile);
58523
- let targetDef = null;
58524
- for (const segment of [...names].reverse()) {
58525
- if (!file2)
58526
- break;
58527
- const resolved = resolveExportNamespace(file2, segment);
58528
- if (!resolved) {
58529
- targetDef = null;
58530
- break;
58287
+ }
58288
+ if (current.type === "variable_declarator") {
58289
+ const name = current.childForFieldName("name") ?? current.child(0);
58290
+ const value = current.childForFieldName("value");
58291
+ if (name && value && (value.type === "new_expression" || value.type === "object_creation_expression" || sup.nodeTypes.identifier.includes(value.type)) && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
58292
+ const candidate = constructorNameNode(value, sup);
58293
+ if (!candidate) {
58294
+ return true;
58295
+ }
58296
+ if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
58297
+ constructor = null;
58298
+ return false;
58299
+ }
58300
+ constructor = candidate;
58531
58301
  }
58532
- if (resolved.kind === "namespace") {
58533
- file2 = normalizePath(resolved.file);
58534
- targetDef = null;
58535
- continue;
58302
+ }
58303
+ if (current.type === "assignment" || current.type === "let_declaration") {
58304
+ const candidate = constructorFromAssignmentLike(current, receiverName, source, sup);
58305
+ if (candidate) {
58306
+ if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
58307
+ constructor = null;
58308
+ return false;
58309
+ }
58310
+ constructor = candidate;
58536
58311
  }
58537
- targetDef = resolved.def;
58538
- file2 = normalizePath(targetDef.file);
58539
58312
  }
58540
- if (targetDef) {
58541
- return targetDef;
58313
+ if (current.type === "local_variable_declaration" || current.type === "local_declaration_statement" || current.type === "variable_declaration") {
58314
+ const candidate = constructorFromTypedLocalDeclaration(current, receiverName, source, sup);
58315
+ if (candidate) {
58316
+ if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
58317
+ constructor = null;
58318
+ return false;
58319
+ }
58320
+ constructor = candidate;
58321
+ }
58542
58322
  }
58543
- const fileKey = typeof file2 === "string" ? fileIdentityKey(file2) : null;
58544
- const moduleEntry = fileKey ? index.byFile.get(fileKey) : void 0;
58545
- const lastName = names[0];
58546
- return moduleEntry?.locals.find((entry) => entry.localName === lastName) ?? null;
58323
+ for (const child of current.namedChildren) {
58324
+ if (!visit(child)) {
58325
+ return false;
58326
+ }
58327
+ }
58328
+ return true;
58547
58329
  };
58548
- const resolveExportFrom = (file2, exportedName) => resolveExportDef(file2, exportedName);
58549
- const optionFileKeys = opts?.files ? new Set(Array.from(opts.files, fileIdentityKey)) : void 0;
58550
- for (const moduleEntry of index.byFile.values()) {
58551
- const file2 = moduleEntry.file;
58552
- if (optionFileKeys && !optionFileKeys.has(fileIdentityKey(file2)))
58553
- continue;
58554
- if (scopeMode === "imported") {
58555
- const hasFuncOrClass = moduleEntry.locals.some((local) => local.kind === SymbolKind.Function || local.kind === SymbolKind.Class);
58556
- const isImportedOrImports = importedByOthers.has(fileIdentityKey(file2)) || !!moduleEntry.imports.length;
58557
- if (!(hasFuncOrClass && isImportedOrImports))
58558
- continue;
58330
+ visit(node);
58331
+ return constructor;
58332
+ }
58333
+ function constructorFromTypedLocalDeclaration(node, receiverName, source, sup) {
58334
+ if (sup.id !== "csharp" && sup.id !== "java")
58335
+ return null;
58336
+ const text = sliceText(node, source);
58337
+ const typeNameSource = sup.id === "java" ? JAVA_CONSTANT_SOURCE : CSHARP_CONSTANT_SOURCE;
58338
+ const match = text.match(new RegExp(String.raw`^\s*(${typeNameSource})\s+${escapeRegExp(receiverName)}\s*=\s*new\s+(${typeNameSource})(?![\p{L}\p{Nl}\p{Sc}\p{Pc}\p{Nd}\p{Mn}\p{Mc}\p{Cf}])`, "u"));
58339
+ const typeName = match?.[2] ?? match?.[1];
58340
+ return typeName ? findNamedChildText(node, typeName, source, sup) : null;
58341
+ }
58342
+ function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source, sup) {
58343
+ const visit = (current) => {
58344
+ if (current.startIndex >= receiver.startIndex) {
58345
+ return false;
58559
58346
  }
58560
- try {
58561
- const parsedEntry = index.parsed?.get(fileIdentityKey(file2));
58562
- let sup = parsedEntry?.sup;
58563
- let src = parsedEntry?.source;
58564
- let tree = parsedEntry?.tree;
58565
- if (!sup || src === void 0) {
58566
- const prep = await prepareSourceInput(file2, {
58567
- languageExtensions: index.languageExtensions
58568
- });
58569
- sup = prep.sup;
58570
- src = prep.source;
58571
- }
58572
- if (sup && !sup.supportsCrossModuleSymbols) {
58573
- continue;
58574
- }
58575
- if (sup && src !== void 0 && !tree) {
58576
- const nativeTreeExecution = getNativeSyntaxTreeExecution(src, sup, index.nativeMode);
58577
- if (nativeTreeExecution.tree) {
58578
- tree = new ProjectedSyntaxTree(src, nativeTreeExecution.tree);
58579
- } else {
58580
- skippedSyntaxTreeFiles += 1;
58581
- continue;
58582
- }
58347
+ if (current !== node && isSkippableBindingContainer(current, receiver)) {
58348
+ return false;
58349
+ }
58350
+ if (BINDING_DECLARATION_TYPES.has(current.type)) {
58351
+ const name = current.childForFieldName("name") ?? current.child(0);
58352
+ if (name && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
58353
+ return true;
58583
58354
  }
58584
- if (!sup || src === void 0 || !tree) {
58585
- throw new Error(`Failed to parse ${file2}`);
58355
+ }
58356
+ for (const child of current.namedChildren) {
58357
+ if (visit(child)) {
58358
+ return true;
58586
58359
  }
58587
- const { aliasToTargetDef, aliasToTargetModule } = buildImportAliasMaps(index, moduleEntry, resolveExportNamespace, resolveExportFrom);
58588
- const { functionNodes, classNodes, constStringOf } = collectDetailedDeclarations(tree.rootNode, sup, src, moduleEntry.locals);
58589
- const memberResolver = createMemberChainResolver({
58590
- sup,
58591
- source: src,
58592
- constStringOf,
58593
- aliasToTargetModule,
58594
- resolveMemberPathFromModule
58595
- });
58596
- const { memberExpressionType, optionalMemberTypes, propertyIdentifierTypes, resolveMemberChainTarget } = memberResolver;
58597
- const resolveIdentifier = (name) => {
58598
- const fromAlias = aliasToTargetDef.get(name);
58599
- if (fromAlias)
58600
- return fromAlias;
58601
- return moduleEntry.locals.find((local) => local.localName === name) ?? null;
58602
- };
58603
- const edgePassContext = {
58604
- index,
58605
- sup,
58606
- source: src,
58607
- moduleEntry,
58608
- nodes,
58609
- membersOnly,
58610
- memberExpressionType,
58611
- propertyIdentifierTypes,
58612
- optionalMemberTypes,
58613
- aliasToTargetDef,
58614
- aliasToTargetModule,
58615
- resolveIdentifier,
58616
- resolveExportFrom,
58617
- resolveMemberChainTarget,
58618
- recordEdge
58619
- };
58620
- emitPythonDecoratorEdges(edgePassContext, tree.rootNode);
58621
- emitFunctionBodyEdges(edgePassContext, functionNodes);
58622
- emitMemberOwnershipEdges(edgePassContext, functionNodes, classNodes);
58623
- emitClassInheritanceEdges(edgePassContext, classNodes);
58624
- emitRustImplEdges(edgePassContext, tree.rootNode);
58625
- } catch (error51) {
58626
- if (isNativeRequiredUnavailableError(error51)) {
58627
- throw error51;
58628
- }
58629
- if (isUnsupportedParserInputError(error51)) {
58630
- continue;
58631
- }
58632
- logWithLevel(opts?.logLevel, "warn", `Warning: Failed to build detailed symbol edges for ${file2}:`, error51);
58633
58360
  }
58634
- }
58635
- emitMemberImplementationEdges({ nodes, edges }, recordEdge);
58636
- if (skippedSyntaxTreeFiles > 0) {
58637
- logWithLevel(opts?.logLevel, "warn", `Warning: Skipped detailed symbol edges for ${skippedSyntaxTreeFiles} file(s) because no syntax-tree backend was available.`);
58638
- }
58639
- return {
58640
- nodes,
58641
- edges,
58642
- ...configuredMaxEdges !== void 0 ? {
58643
- truncated: omittedEdges > 0,
58644
- limits: { edges: configuredMaxEdges },
58645
- omittedCounts: { edges: omittedEdges }
58646
- } : {}
58361
+ return false;
58647
58362
  };
58363
+ return visit(node);
58648
58364
  }
58649
- var init_symbol_graph_detailed = __esm({
58650
- "dist/graphs/symbol-graph-detailed.js"() {
58651
- "use strict";
58652
- init_filePrep();
58653
- init_logging();
58654
- init_projectedTree();
58655
- init_treeSitterNative();
58656
- init_navigation_resolve();
58657
- init_types2();
58658
- init_paths();
58659
- init_symbol_graph();
58660
- init_ast2();
58661
- init_edgePasses();
58662
- init_importAliases();
58663
- init_memberChains();
58664
- }
58665
- });
58666
-
58667
- // dist/util/sourceLocation.js
58668
- function parseSourceLocationInput(value) {
58669
- const lineColumnMatch = FILE_LINE_COLUMN_PATTERN.exec(value);
58670
- if (lineColumnMatch?.[1] && lineColumnMatch[2] && lineColumnMatch[3]) {
58671
- return {
58672
- file: lineColumnMatch[1],
58673
- line: Number(lineColumnMatch[2]),
58674
- column: Number(lineColumnMatch[3])
58675
- };
58365
+ function isSkippableBindingContainer(node, receiver) {
58366
+ return BINDING_CONTAINER_TYPES.has(node.type) && !nodeContainsIndex(node, receiver.startIndex);
58367
+ }
58368
+ function nodeContainsIndex(node, index) {
58369
+ return node.startIndex <= index && node.endIndex >= index;
58370
+ }
58371
+ function constructorFromAssignmentLike(node, receiverName, source, sup) {
58372
+ const text = sliceText(node, source);
58373
+ if (!new RegExp(String.raw`(?<!${IDENTIFIER_BOUNDARY_SOURCE})${escapeRegExp(receiverName)}(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u").test(text))
58374
+ return null;
58375
+ if (sup.id === "ruby") {
58376
+ const match = text.match(new RegExp(String.raw`^\s*${escapeRegExp(receiverName)}\s*=\s*(${RUBY_CONSTANT_SOURCE})\.new(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
58377
+ if (!match?.[1])
58378
+ return null;
58379
+ return findNamedChildText(node, match[1], source, sup);
58676
58380
  }
58677
- const lineMatch = FILE_LINE_PATTERN.exec(value);
58678
- if (lineMatch?.[1] && lineMatch[2]) {
58679
- return { file: lineMatch[1], line: Number(lineMatch[2]) };
58381
+ if (sup.id === "rust") {
58382
+ const match = text.match(new RegExp(String.raw`^\s*(?:let\s+)?${escapeRegExp(receiverName)}\s*=\s*(${RUST_CONSTANT_SOURCE})(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
58383
+ if (!match?.[1])
58384
+ return null;
58385
+ return findNamedChildText(node, match[1], source, sup);
58680
58386
  }
58681
- return { file: value };
58387
+ return null;
58682
58388
  }
58683
- var FILE_LINE_COLUMN_PATTERN, FILE_LINE_PATTERN;
58684
- var init_sourceLocation = __esm({
58685
- "dist/util/sourceLocation.js"() {
58686
- "use strict";
58687
- FILE_LINE_COLUMN_PATTERN = /^(.*):(\d+):(\d+)$/;
58688
- FILE_LINE_PATTERN = /^(.*):(\d+)$/;
58689
- }
58690
- });
58691
-
58692
- // dist/agent/shell.js
58693
- function quoteShellArg(value) {
58694
- if (/^[A-Za-z0-9_./:@-]+$/.test(value))
58695
- return value;
58696
- return `'${value.replace(/'/g, "'\\''")}'`;
58389
+ function findNamedChildText(node, name, source, sup) {
58390
+ const isNameNode = (candidate) => (sup.nodeTypes.identifier.includes(candidate.type) || candidate.type === "type_identifier" || candidate.type === "constant") && sliceText(candidate, source) === name;
58391
+ const visit = (current) => {
58392
+ if (isNameNode(current))
58393
+ return current;
58394
+ for (const child of current.namedChildren) {
58395
+ const hit = visit(child);
58396
+ if (hit)
58397
+ return hit;
58398
+ }
58399
+ return null;
58400
+ };
58401
+ return visit(node);
58697
58402
  }
58698
- var init_shell = __esm({
58699
- "dist/agent/shell.js"() {
58700
- "use strict";
58701
- }
58702
- });
58703
-
58704
- // dist/agent/followUps.js
58705
- function toolFollowUp(tool, arguments_ = {}, label) {
58706
- return {
58707
- tool,
58708
- arguments: { ...arguments_ },
58709
- ...label !== void 0 ? { label } : {}
58403
+ async function resolveMemberDefinitionForBase(index, baseDef, member) {
58404
+ const targetContext = await ensureParsedContext(baseDef.file, void 0, index.languageExtensions);
58405
+ const start = baseDef.range.start;
58406
+ const targetPosition = {
58407
+ row: start.line - 1,
58408
+ column: start.column - 1
58710
58409
  };
58410
+ const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
58411
+ const container = nameNode.parent;
58412
+ if (!container)
58413
+ return void 0;
58414
+ const targetModule = index.byFile.get(fileIdentityKey(baseDef.file));
58415
+ if (!targetModule)
58416
+ return void 0;
58417
+ const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
58418
+ const directHit = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
58419
+ if (directHit)
58420
+ return directHit;
58421
+ if (targetContext.sup.id === "java")
58422
+ return void 0;
58423
+ return findReceiverMemberDefinition(targetModule.locals, member, baseDef, container, targetContext, normalizeIdentifier);
58711
58424
  }
58712
- function dedupeAgentFollowUps(followUps) {
58713
- const seen = /* @__PURE__ */ new Set();
58714
- return followUps.filter((followUp) => {
58715
- const serializedArguments = JSON.stringify(followUp.arguments);
58716
- const key = `${followUp.tool.length}|${followUp.tool}${serializedArguments}`;
58717
- if (seen.has(key))
58718
- return false;
58719
- seen.add(key);
58720
- return true;
58425
+ function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier) {
58426
+ const containerHit = findLocalWithinNode(locals, member, container, normalizeIdentifier);
58427
+ if (containerHit)
58428
+ return containerHit;
58429
+ if (targetContext.sup.id !== "rust")
58430
+ return void 0;
58431
+ const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
58432
+ return implNode ? findLocalWithinNode(locals, member, implNode, normalizeIdentifier) : void 0;
58433
+ }
58434
+ function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name) {
58435
+ const containerStart = node.startIndex;
58436
+ const containerEnd = node.endIndex;
58437
+ const normalizedMember = normalizeIdentifier(member);
58438
+ return locals.find((local) => {
58439
+ const startIndex = local.range.start.index;
58440
+ const endIndex = local.range.end.index;
58441
+ return normalizeIdentifier(local.localName) === normalizedMember && startIndex !== void 0 && endIndex !== void 0 && startIndex >= containerStart && endIndex <= containerEnd;
58721
58442
  });
58722
58443
  }
58723
- function formatAgentFollowUpAsCli(followUp) {
58724
- const args = followUp.arguments;
58725
- switch (followUp.tool) {
58726
- case "file_deps": {
58727
- const file2 = stringArgument(args, "file");
58728
- const direction = args.direction === "rdeps" ? "rdeps" : "deps";
58729
- return appendJson(`codegraph ${direction}${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`, args);
58730
- }
58731
- case "calls": {
58732
- const handle = stringArgument(args, "handle");
58733
- const direction = args.direction === "callees" ? "callees" : "callers";
58734
- return appendJson(`codegraph ${direction}${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
58735
- }
58736
- case "type_hierarchy": {
58737
- const handle = stringArgument(args, "handle");
58738
- const direction = args.direction === "subtypes" ? "subtypes" : "supertypes";
58739
- return appendJson(`codegraph ${direction}${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
58740
- }
58741
- case "get_file": {
58742
- const file2 = stringArgument(args, "file");
58743
- return `codegraph file${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`;
58744
- }
58745
- case "packet_get": {
58746
- const target = stringArgument(args, "target");
58747
- return `codegraph packet get${target === void 0 ? "" : ` ${formatPathArgument(target)}`}`;
58748
- }
58749
- case "chunk": {
58750
- const file2 = stringArgument(args, "file");
58751
- return `codegraph chunk${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`;
58752
- }
58753
- case "get_symbol": {
58754
- const handle = stringArgument(args, "handle");
58755
- return `codegraph explain${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`;
58756
- }
58757
- case "goto": {
58758
- const location = locationArgument(args);
58759
- return `codegraph goto ${quoteShellArg(location)}`;
58760
- }
58761
- case "refs": {
58762
- const target = stringArgument(args, "handle") ?? locationArgument(args);
58763
- return `codegraph refs ${quoteShellArg(target)}`;
58764
- }
58765
- case "search": {
58766
- const query = stringArgument(args, "query");
58767
- let command = `codegraph search${query === void 0 ? "" : ` ${quoteShellArg(query)}`}`;
58768
- if (typeof args.mode === "string")
58769
- command += ` --mode ${quoteShellArg(args.mode)}`;
58770
- if (typeof args.from === "string")
58771
- command += ` --from ${quoteShellArg(args.from)}`;
58772
- return `${command} --json`;
58444
+ function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier) {
58445
+ const containerStart = container.startIndex;
58446
+ const containerEnd = container.endIndex;
58447
+ const normalizedMember = normalizeIdentifier(member);
58448
+ for (const local of locals) {
58449
+ const startIndex = local.range.start.index;
58450
+ const endIndex = local.range.end.index;
58451
+ if (normalizeIdentifier(local.localName) !== normalizedMember || startIndex === void 0 || endIndex === void 0 || startIndex < containerStart || endIndex > containerEnd) {
58452
+ continue;
58773
58453
  }
58774
- case "explore": {
58775
- const query = stringArgument(args, "query");
58776
- return `codegraph explore${query === void 0 ? "" : ` ${quoteShellArg(query)}`}`;
58454
+ const start = local.range.start;
58455
+ const position = {
58456
+ row: start.line - 1,
58457
+ column: start.column - 1
58458
+ };
58459
+ let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
58460
+ let isDeclarationParent = true;
58461
+ while (current && current !== container) {
58462
+ if (!isDeclarationParent && (current.type === "class_body" && current.parent !== container || NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
58463
+ current = null;
58464
+ break;
58465
+ }
58466
+ isDeclarationParent = false;
58467
+ current = current.parent;
58777
58468
  }
58778
- case "orient": {
58779
- let command = "codegraph orient";
58780
- if (typeof args.root === "string")
58781
- command += ` --root ${quoteShellArg(args.root)}`;
58782
- if (typeof args.budget === "string")
58783
- command += ` --budget ${quoteShellArg(args.budget)}`;
58784
- return command;
58469
+ if (current)
58470
+ return local;
58471
+ }
58472
+ return void 0;
58473
+ }
58474
+ function findRustImplForType(root, typeName, source) {
58475
+ let found = null;
58476
+ const visit = (node) => {
58477
+ if (node.type === "impl_item") {
58478
+ const text = sliceText(node, source);
58479
+ if (new RegExp(`^\\s*impl\\s+${escapeRegExp(typeName)}\\b`).test(text)) {
58480
+ found = node;
58481
+ return false;
58482
+ }
58785
58483
  }
58786
- case "implementations": {
58787
- const handle = stringArgument(args, "handle");
58788
- return appendJson(`codegraph implementations${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
58484
+ for (const child of node.namedChildren) {
58485
+ if (!visit(child))
58486
+ return false;
58789
58487
  }
58790
- case "rename_preview": {
58791
- const handle = stringArgument(args, "handle");
58792
- const newName = stringArgument(args, "newName") ?? "<new-name>";
58793
- return `codegraph rename-preview${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`} ${quoteShellArg(newName)} --json`;
58488
+ return true;
58489
+ };
58490
+ visit(root);
58491
+ return found;
58492
+ }
58493
+ function escapeRegExp(value) {
58494
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58495
+ }
58496
+ var RUBY_CONSTANT_SOURCE, CSHARP_CONSTANT_SOURCE, JAVA_CONSTANT_SOURCE, RUST_CONSTANT_SOURCE, IDENTIFIER_BOUNDARY_SOURCE, BINDING_CONTAINER_TYPES, BINDING_DECLARATION_TYPES, NESTED_MEMBER_LOCAL_CONTAINERS;
58497
+ var init_navigation_goto = __esm({
58498
+ "dist/indexer/navigation-goto.js"() {
58499
+ "use strict";
58500
+ init_js_family();
58501
+ init_ast();
58502
+ init_paths();
58503
+ init_memberAccess();
58504
+ init_identifiers();
58505
+ init_parse_context();
58506
+ init_navigation_provenance();
58507
+ init_navigation_resolve();
58508
+ RUBY_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
58509
+ CSHARP_CONSTANT_SOURCE = String.raw`(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
58510
+ JAVA_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
58511
+ RUST_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
58512
+ IDENTIFIER_BOUNDARY_SOURCE = String.raw`[$_\p{ID_Continue}\u200c\u200d]`;
58513
+ BINDING_CONTAINER_TYPES = /* @__PURE__ */ new Set([
58514
+ "program",
58515
+ "compilation_unit",
58516
+ "source_file",
58517
+ "statement_block",
58518
+ "block",
58519
+ "function_declaration",
58520
+ "function_item",
58521
+ "function",
58522
+ "function_expression",
58523
+ "arrow_function",
58524
+ "method_definition",
58525
+ "method_declaration",
58526
+ "method"
58527
+ ]);
58528
+ BINDING_DECLARATION_TYPES = /* @__PURE__ */ new Set([
58529
+ "variable_declarator",
58530
+ "let_declaration",
58531
+ "assignment",
58532
+ "formal_parameter",
58533
+ "required_parameter",
58534
+ "optional_parameter"
58535
+ ]);
58536
+ NESTED_MEMBER_LOCAL_CONTAINERS = /* @__PURE__ */ new Set([
58537
+ "block",
58538
+ "class",
58539
+ "class_declaration",
58540
+ "class_definition",
58541
+ "constructor_declaration",
58542
+ "enum_declaration",
58543
+ "enum_item",
58544
+ "enum_specifier",
58545
+ "function_declaration",
58546
+ "function_definition",
58547
+ "function_item",
58548
+ "interface_declaration",
58549
+ "method",
58550
+ "method_declaration",
58551
+ "method_definition",
58552
+ "module",
58553
+ "statement_block"
58554
+ ]);
58555
+ }
58556
+ });
58557
+
58558
+ // dist/graphs/symbol-graph-detailed/receiverCalls.js
58559
+ function receiverCallAccess(sup, callNode, callee) {
58560
+ let accessNode = null;
58561
+ if (RECEIVER_CALL_NODE_TYPES[callNode.type]) {
58562
+ accessNode = callNode;
58563
+ } else if (callee && isMemberAccessNode(sup, callee)) {
58564
+ accessNode = callee;
58565
+ } else if (isMemberAccessNode(sup, callNode)) {
58566
+ accessNode = callNode;
58567
+ }
58568
+ if (!accessNode)
58569
+ return null;
58570
+ const parts = getMemberAccessParts(sup, accessNode);
58571
+ const receiver = parts.object;
58572
+ let property = parts.property;
58573
+ if (!property && accessNode.type === "navigation_expression") {
58574
+ property = getNavigationExpressionProperty(accessNode) ?? accessNode.namedChildren[1] ?? null;
58575
+ }
58576
+ if (!receiver || !property)
58577
+ return null;
58578
+ if (receiver.startIndex === property.startIndex)
58579
+ return null;
58580
+ if (!isMemberReferencePropertyIdentifier(sup, property.type))
58581
+ return null;
58582
+ return { accessNode, receiver, property };
58583
+ }
58584
+ function bindingIdentifier(node, sup) {
58585
+ const named = node.childForFieldName("name");
58586
+ if (named && (isIdentifierType(sup, named.type) || named.type === "identifier" || named.type === "field_identifier")) {
58587
+ return named;
58588
+ }
58589
+ if (node.type === "assignment" || node.type === "assignment_expression" || node.type === "assignment_statement") {
58590
+ const left = node.childForFieldName("left") ?? node.child(0);
58591
+ if (left && (isIdentifierType(sup, left.type) || left.type === "identifier"))
58592
+ return left;
58593
+ return null;
58594
+ }
58595
+ let current = node.childForFieldName("declarator");
58596
+ while (current) {
58597
+ if (current.type === "identifier" || current.type === "field_identifier" || isIdentifierType(sup, current.type)) {
58598
+ return current;
58794
58599
  }
58795
- case "review":
58796
- case "impact": {
58797
- let command = `codegraph ${followUp.tool}`;
58798
- if (typeof args.provider === "string")
58799
- command += ` --provider ${quoteShellArg(args.provider)}`;
58800
- if (typeof args.base === "string")
58801
- command += ` --base ${quoteShellArg(args.base)}`;
58802
- if (typeof args.head === "string")
58803
- command += ` --head ${quoteShellArg(args.head)}`;
58804
- return command;
58600
+ const nested = current.childForFieldName("declarator");
58601
+ if (nested) {
58602
+ current = nested;
58603
+ continue;
58805
58604
  }
58806
- case "duplicates": {
58807
- const root = stringArgument(args, "root") ?? ".";
58808
- const files = Array.isArray(args.files) ? args.files.filter((file2) => typeof file2 === "string") : [];
58809
- let command = `codegraph duplicates --root ${quoteShellArg(root)} ${files.map(quoteShellArg).join(" ")}`;
58810
- if (args.json === true)
58811
- command += " --json";
58812
- if (typeof args.minConfidence === "string")
58813
- command += ` --min-confidence ${quoteShellArg(args.minConfidence)}`;
58814
- if (args.includeSameFile === true)
58815
- command += " --include-same-file";
58816
- return command;
58605
+ return current.namedChildren.find((child) => child.type === "identifier" || child.type === "field_identifier") ?? null;
58606
+ }
58607
+ const identifiers = node.namedChildren.filter((child) => child.type === "identifier" || child.type === "field_identifier");
58608
+ return identifiers.length > 0 ? identifiers[identifiers.length - 1] : null;
58609
+ }
58610
+ function bindsLocalValue(receiver, receiverName, source, sup) {
58611
+ const declaresName = (node) => {
58612
+ if (node.startIndex >= receiver.startIndex)
58613
+ return false;
58614
+ if (node !== receiver && BINDING_SCOPE_TYPES[node.type] && !containsIndex(node, receiver.startIndex))
58615
+ return false;
58616
+ if (PARAMETER_LIST_TYPES[node.type]) {
58617
+ for (const child of node.namedChildren) {
58618
+ if (child.startIndex >= receiver.startIndex)
58619
+ continue;
58620
+ const names = child.type === "ERROR" ? child.namedChildren : [child];
58621
+ for (const name of names) {
58622
+ if ((isIdentifierType(sup, name.type) || name.type === "identifier" || name.type === "constant") && sliceText(name, source) === receiverName) {
58623
+ return true;
58624
+ }
58625
+ }
58626
+ }
58817
58627
  }
58818
- case "hotspots": {
58819
- const root = stringArgument(args, "root") ?? ".";
58820
- const limit = typeof args.limit === "number" ? ` --limit ${args.limit}` : "";
58821
- return `codegraph hotspots ${quoteShellArg(root)}${limit}`;
58628
+ if (VALUE_BINDING_TYPES[node.type]) {
58629
+ const name = bindingIdentifier(node, sup);
58630
+ if (name && sliceText(name, source) === receiverName)
58631
+ return true;
58822
58632
  }
58823
- default:
58824
- return formatUnknownFollowUp(followUp);
58633
+ return node.namedChildren.some(declaresName);
58634
+ };
58635
+ for (let current = receiver.parent; current; current = current.parent) {
58636
+ if (BINDING_SCOPE_TYPES[current.type] && current.namedChildren.some(declaresName))
58637
+ return true;
58825
58638
  }
58639
+ return false;
58826
58640
  }
58827
- function formatAgentFollowUpsAsCli(followUps) {
58828
- return followUps.map(formatAgentFollowUpAsCli);
58641
+ function containsIndex(node, index) {
58642
+ return node.startIndex <= index && node.endIndex >= index;
58829
58643
  }
58830
- function stringArgument(args, key) {
58831
- return typeof args[key] === "string" ? args[key] : void 0;
58644
+ function classifyReceiver(sup, receiver, source, proofCache, cacheScope, accessNode) {
58645
+ const keywords = RECEIVER_KEYWORDS[sup.id];
58646
+ const text = sliceText(receiver, source).trim();
58647
+ if (!text)
58648
+ return null;
58649
+ if (keywords?.own.includes(text))
58650
+ return { kind: "own-type" };
58651
+ if (keywords?.supertype.includes(text))
58652
+ return { kind: "supertype" };
58653
+ const receiverIsName = isIdentifierType(sup, receiver.type) || receiver.type === "type_identifier" || receiver.type === "constant";
58654
+ const cacheKey3 = `${cacheScope}\0${text}`;
58655
+ let proof = proofCache.get(cacheKey3);
58656
+ if (!proof) {
58657
+ const constructed = receiverConstructorExpression(receiver, source, sup);
58658
+ proof = {
58659
+ constructed,
58660
+ locallyBound: !constructed && receiverIsName && bindsLocalValue(receiver, text, source, sup)
58661
+ };
58662
+ proofCache.set(cacheKey3, proof);
58663
+ }
58664
+ if (proof.constructed)
58665
+ return { kind: "named-type", typeName: sliceText(proof.constructed, source) };
58666
+ if (!receiverIsName)
58667
+ return null;
58668
+ if (proof.locallyBound)
58669
+ return null;
58670
+ const property = getMemberAccessParts(sup, accessNode).property;
58671
+ const between = property ? source.slice(receiver.endIndex, property.startIndex) : "";
58672
+ const typeScoped = TYPE_SCOPED_ACCESS_TYPES[accessNode.type] === true || between.includes("::");
58673
+ if (receiver.type !== "type_identifier" && !typeScoped)
58674
+ return null;
58675
+ return { kind: "named-type", typeName: text };
58832
58676
  }
58833
- function locationArgument(args) {
58834
- const file2 = stringArgument(args, "file") ?? "<file>";
58835
- const line = typeof args.line === "number" ? args.line : 1;
58836
- const column = typeof args.column === "number" ? args.column : 0;
58837
- return `${file2}:${line}:${column}`;
58677
+ function declaresMembers(def) {
58678
+ return def.kind === SymbolKind.Class || def.kind === SymbolKind.Interface || def.kind === SymbolKind.TypeAlias;
58838
58679
  }
58839
- function formatPathArgument(value) {
58840
- const target = value.startsWith("-") || value.startsWith("file:") || value.startsWith("symbol:") || value.startsWith("chunk:") || value.startsWith("sql:") || value.startsWith("graph:") || value.startsWith("review:") ? `./${value}` : value;
58841
- return quoteShellArg(target);
58680
+ function nearestMemberContainer(node) {
58681
+ let current = node.parent;
58682
+ while (current) {
58683
+ if (MEMBER_CONTAINER_TYPES[current.type])
58684
+ return current;
58685
+ current = current.parent;
58686
+ }
58687
+ return null;
58842
58688
  }
58843
- function appendJson(command, args) {
58844
- let output = command;
58845
- if (typeof args.depth === "number")
58846
- output += ` --depth ${args.depth}`;
58847
- if (typeof args.limit === "number")
58848
- output += ` --limit ${args.limit}`;
58849
- if (args.includeHeuristic === true)
58850
- output += " --include-heuristic";
58851
- return `${output} --json`;
58689
+ function callArgumentCount(callNode) {
58690
+ const explicit = callNode.childForFieldName("arguments") ?? callNode.childForFieldName("argument_list");
58691
+ let argumentNode = explicit ?? (callNode.namedChildren ?? []).find((child) => CALL_ARGUMENT_NODE_TYPES[child.type]) ?? null;
58692
+ if (argumentNode?.type === "call_suffix") {
58693
+ argumentNode = (argumentNode.namedChildren ?? []).find((child) => child.type === "value_arguments") ?? null;
58694
+ }
58695
+ if (!argumentNode)
58696
+ return 0;
58697
+ return (argumentNode.namedChildren ?? []).filter((argument) => argument.type !== "comment").length;
58852
58698
  }
58853
- function formatUnknownFollowUp(followUp) {
58854
- let command = `codegraph ${followUp.tool}`;
58855
- for (const [key, value] of Object.entries(followUp.arguments)) {
58856
- if (value === void 0 || value === false)
58699
+ function emitReceiverCallEdges(graph, candidates, recordEdge) {
58700
+ if (!candidates.length)
58701
+ return;
58702
+ const membersByOwner = /* @__PURE__ */ new Map();
58703
+ const ownerByMember = /* @__PURE__ */ new Map();
58704
+ const supertypesByOwner = /* @__PURE__ */ new Map();
58705
+ const classAncestorsByOwner = /* @__PURE__ */ new Map();
58706
+ const pushUnique2 = (map2, from, to) => {
58707
+ const list = map2.get(from);
58708
+ if (!list)
58709
+ map2.set(from, [to]);
58710
+ else if (!list.includes(to))
58711
+ list.push(to);
58712
+ };
58713
+ for (const edge of graph.edges) {
58714
+ const label = edge.label;
58715
+ if (label === "member_of") {
58716
+ pushUnique2(membersByOwner, edge.to, edge.from);
58717
+ ownerByMember.set(edge.from, edge.to);
58857
58718
  continue;
58858
- if (value === true) {
58859
- command += ` --${key}`;
58719
+ }
58720
+ if (!label || !HIERARCHY_LABELS[label])
58721
+ continue;
58722
+ pushUnique2(supertypesByOwner, edge.from, edge.to);
58723
+ if (label === "extends")
58724
+ pushUnique2(classAncestorsByOwner, edge.from, edge.to);
58725
+ }
58726
+ const nextOwners = (ownerId, viaSupertypes) => {
58727
+ if (!viaSupertypes)
58728
+ return supertypesByOwner.get(ownerId) ?? [];
58729
+ return (classAncestorsByOwner.get(ownerId) ?? []).filter((id) => graph.nodes.get(id)?.kind === "class");
58730
+ };
58731
+ for (const candidate of candidates) {
58732
+ const owner = candidate.ownerId ?? ownerByMember.get(candidate.callerId);
58733
+ if (!owner)
58860
58734
  continue;
58735
+ let level = candidate.viaSupertypes ? nextOwners(owner, true) : [owner];
58736
+ const visited = new Set(level);
58737
+ for (let depth = 0; depth < MAX_SUPERTYPE_DEPTH && level.length; depth += 1) {
58738
+ const lookup = provenMemberTarget(graph, membersByOwner, level, candidate);
58739
+ if (lookup.status === "unique") {
58740
+ recordEdge(candidate.callerId, lookup.memberId, "calls", candidate.site);
58741
+ break;
58742
+ }
58743
+ if (lookup.status === "ambiguous")
58744
+ break;
58745
+ const next = [];
58746
+ for (const ownerId of level) {
58747
+ for (const supertype of nextOwners(ownerId, candidate.viaSupertypes)) {
58748
+ if (visited.has(supertype))
58749
+ continue;
58750
+ visited.add(supertype);
58751
+ next.push(supertype);
58752
+ }
58753
+ }
58754
+ level = next;
58861
58755
  }
58862
- if (typeof value === "string" || typeof value === "number") {
58863
- command += ` --${key} ${quoteShellArg(String(value))}`;
58756
+ }
58757
+ }
58758
+ function provenMemberTarget(graph, membersByOwner, owners, candidate) {
58759
+ const matches = /* @__PURE__ */ new Set();
58760
+ for (const ownerId of owners) {
58761
+ for (const memberId of membersByOwner.get(ownerId) ?? []) {
58762
+ const node = graph.nodes.get(memberId);
58763
+ if (!node || node.kind !== "function" || node.name !== candidate.memberName)
58764
+ continue;
58765
+ matches.add(memberId);
58864
58766
  }
58865
58767
  }
58866
- return command;
58768
+ if (!matches.size)
58769
+ return { status: "none" };
58770
+ if (matches.size === 1) {
58771
+ const [memberId] = matches;
58772
+ return { status: "unique", memberId };
58773
+ }
58774
+ const byArity = [...matches].filter((memberId) => graph.nodes.get(memberId)?.memberArity === candidate.argumentCount);
58775
+ if (byArity.length === 1)
58776
+ return { status: "unique", memberId: byArity[0] };
58777
+ return { status: "ambiguous" };
58867
58778
  }
58868
- var init_followUps = __esm({
58869
- "dist/agent/followUps.js"() {
58779
+ var THIS_SUPER_RECEIVERS, SELF_RECEIVERS, RECEIVER_KEYWORDS, RECEIVER_CALL_NODE_TYPES, MEMBER_CONTAINER_TYPES, CALL_ARGUMENT_NODE_TYPES, HIERARCHY_LABELS, VALUE_BINDING_TYPES, PARAMETER_LIST_TYPES, TYPE_SCOPED_ACCESS_TYPES, BINDING_SCOPE_TYPES, MAX_SUPERTYPE_DEPTH;
58780
+ var init_receiverCalls = __esm({
58781
+ "dist/graphs/symbol-graph-detailed/receiverCalls.js"() {
58870
58782
  "use strict";
58871
- init_shell();
58783
+ init_navigation_goto();
58784
+ init_types2();
58785
+ init_ast();
58786
+ init_memberAccess();
58787
+ init_ast2();
58788
+ THIS_SUPER_RECEIVERS = { own: ["this"], supertype: ["super"] };
58789
+ SELF_RECEIVERS = { own: ["self"], supertype: ["super"] };
58790
+ RECEIVER_KEYWORDS = {
58791
+ cpp: { own: ["this"], supertype: [] },
58792
+ csharp: { own: ["this"], supertype: ["base"] },
58793
+ java: THIS_SUPER_RECEIVERS,
58794
+ js: THIS_SUPER_RECEIVERS,
58795
+ kotlin: THIS_SUPER_RECEIVERS,
58796
+ php: { own: ["$this", "self", "static"], supertype: ["parent"] },
58797
+ python: { own: ["self", "cls"], supertype: [] },
58798
+ ruby: { own: ["self"], supertype: [] },
58799
+ rust: { own: ["self", "Self"], supertype: [] },
58800
+ svelte: THIS_SUPER_RECEIVERS,
58801
+ swift: SELF_RECEIVERS,
58802
+ ts: THIS_SUPER_RECEIVERS,
58803
+ tsx: THIS_SUPER_RECEIVERS,
58804
+ zig: { own: ["self"], supertype: [] }
58805
+ };
58806
+ RECEIVER_CALL_NODE_TYPES = {
58807
+ member_call_expression: true,
58808
+ method_invocation: true,
58809
+ nullsafe_member_call_expression: true,
58810
+ scoped_call_expression: true
58811
+ };
58812
+ MEMBER_CONTAINER_TYPES = {
58813
+ abstract_class_declaration: true,
58814
+ class: true,
58815
+ class_declaration: true,
58816
+ class_definition: true,
58817
+ class_specifier: true,
58818
+ enum_declaration: true,
58819
+ extension_declaration: true,
58820
+ impl_item: true,
58821
+ interface_declaration: true,
58822
+ module: true,
58823
+ object_declaration: true,
58824
+ protocol_declaration: true,
58825
+ record_declaration: true,
58826
+ singleton_class: true,
58827
+ struct_declaration: true,
58828
+ struct_item: true,
58829
+ struct_specifier: true,
58830
+ trait_declaration: true,
58831
+ trait_item: true
58832
+ };
58833
+ CALL_ARGUMENT_NODE_TYPES = {
58834
+ argument_list: true,
58835
+ arguments: true,
58836
+ // Swift wraps its argument list in a call suffix.
58837
+ call_suffix: true,
58838
+ value_arguments: true
58839
+ };
58840
+ HIERARCHY_LABELS = {
58841
+ extends: true,
58842
+ implements: true,
58843
+ mixin: true,
58844
+ trait: true
58845
+ };
58846
+ VALUE_BINDING_TYPES = {
58847
+ assignment: true,
58848
+ assignment_expression: true,
58849
+ assignment_statement: true,
58850
+ class_parameter: true,
58851
+ formal_parameter: true,
58852
+ init_declarator: true,
58853
+ let_declaration: true,
58854
+ optional_parameter: true,
58855
+ parameter: true,
58856
+ parameter_declaration: true,
58857
+ property_declaration: true,
58858
+ required_parameter: true,
58859
+ short_var_declaration: true,
58860
+ simple_parameter: true,
58861
+ typed_parameter: true,
58862
+ variable_declaration: true,
58863
+ variable_declarator: true
58864
+ };
58865
+ PARAMETER_LIST_TYPES = {
58866
+ block_parameters: true,
58867
+ formal_parameters: true,
58868
+ function_parameter_clause: true,
58869
+ lambda_parameters: true,
58870
+ method_parameters: true,
58871
+ parameter_list: true,
58872
+ parameters: true
58873
+ };
58874
+ TYPE_SCOPED_ACCESS_TYPES = {
58875
+ qualified_identifier: true,
58876
+ qualified_name: true,
58877
+ scope_resolution: true,
58878
+ scoped_call_expression: true,
58879
+ scoped_identifier: true,
58880
+ scoped_type_identifier: true
58881
+ };
58882
+ BINDING_SCOPE_TYPES = {
58883
+ arrow_function: true,
58884
+ block: true,
58885
+ compilation_unit: true,
58886
+ function: true,
58887
+ function_body: true,
58888
+ function_declaration: true,
58889
+ function_definition: true,
58890
+ function_expression: true,
58891
+ function_item: true,
58892
+ method: true,
58893
+ method_declaration: true,
58894
+ method_definition: true,
58895
+ module: true,
58896
+ program: true,
58897
+ source_file: true,
58898
+ statement_block: true,
58899
+ compound_statement: true,
58900
+ do_block: true,
58901
+ impl_item: true,
58902
+ translation_unit: true
58903
+ };
58904
+ MAX_SUPERTYPE_DEPTH = 16;
58872
58905
  }
58873
58906
  });
58874
58907
 
58875
- // dist/agent/normalize.js
58876
- import path48 from "node:path";
58908
+ // dist/graphs/symbol-graph-detailed/edgePasses.js
58909
+ function ensureNode(context, def) {
58910
+ const id = defNodeId(def);
58911
+ if (!context.nodes.has(id))
58912
+ context.nodes.set(id, nodeForDef(def));
58913
+ return id;
58914
+ }
58915
+ function markImplementationTarget(context, id, declarationNode, def) {
58916
+ const declaration = sliceText(declarationNode, context.source);
58917
+ const nameIndex = declaration.indexOf(def.localName);
58918
+ const prefix = nameIndex >= 0 ? declaration.slice(0, nameIndex) : declaration;
58919
+ if (!/\b(?:abstract|virtual|override)\b/.test(prefix))
58920
+ return;
58921
+ const node = context.nodes.get(id);
58922
+ if (node)
58923
+ node.implementationTarget = true;
58924
+ }
58925
+ function markMemberArity(context, id, declarationNode) {
58926
+ let parameters = declarationNode.childForFieldName("parameters");
58927
+ if (!parameters) {
58928
+ for (const type of [
58929
+ "formal_parameters",
58930
+ "parameter_list",
58931
+ "parameters",
58932
+ "method_parameters",
58933
+ "function_parameter_clause"
58934
+ ]) {
58935
+ parameters = findFirstNodeByType(declarationNode, type);
58936
+ if (parameters)
58937
+ break;
58938
+ }
58939
+ }
58940
+ if (!parameters)
58941
+ return;
58942
+ const arity = (parameters.namedChildren ?? []).filter((child) => child.type !== "comment").length;
58943
+ const node = context.nodes.get(id);
58944
+ if (node)
58945
+ node.memberArity = arity;
58946
+ }
58947
+ function recordDefEdge(context, fromId, target, label, siteNode) {
58948
+ const toId = ensureNode(context, target);
58949
+ return context.recordEdge(fromId, toId, label, siteNode ? { file: context.moduleEntry.file, range: toRange(siteNode) } : void 0);
58950
+ }
58951
+ function tryResolveChain(context, node, fromId, label = "uses") {
58952
+ const targetDef = context.resolveMemberChainTarget(node);
58953
+ if (targetDef && fromId) {
58954
+ recordDefEdge(context, fromId, targetDef, label, node);
58955
+ return true;
58956
+ }
58957
+ return !!targetDef;
58958
+ }
58959
+ function tryResolveNode(context, node, fromId, label) {
58960
+ if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
58961
+ const name = sliceText(node, context.source);
58962
+ const target = context.resolveIdentifier(name);
58963
+ if (target) {
58964
+ recordDefEdge(context, fromId, target, label, node);
58965
+ return true;
58966
+ }
58967
+ }
58968
+ if (context.optionalMemberTypes.has(node.type)) {
58969
+ return tryResolveChain(context, node, fromId, label);
58970
+ }
58971
+ return false;
58972
+ }
58973
+ function getCallTarget(node) {
58974
+ const explicitTarget = node.childForFieldName("function") ?? node.childForFieldName("callee") ?? node.childForFieldName("name") ?? node.childForFieldName("method") ?? node.childForFieldName("member") ?? node.childForFieldName("expression");
58975
+ if (explicitTarget)
58976
+ return explicitTarget;
58977
+ const nonArgumentChildren = node.namedChildren.filter((child) => !CALL_ARGUMENT_NODE_TYPES[child.type]);
58978
+ return nonArgumentChildren.length === 1 ? nonArgumentChildren[0] ?? null : null;
58979
+ }
58980
+ function getNewTarget(node) {
58981
+ return node.childForFieldName("constructor") ?? node.childForFieldName("type") ?? node.childForFieldName("name") ?? node.namedChildren.find((child) => child.type === "type_identifier") ?? node.child(0);
58982
+ }
58983
+ function emitPythonDecoratorEdges(context, rootNode) {
58984
+ if (context.sup.id !== "python")
58985
+ return;
58986
+ const addDecoratorUses = (node) => {
58987
+ if (node.type === "decorated_definition") {
58988
+ const fn = node.namedChildren.find((child) => child.type === "function_definition");
58989
+ if (fn)
58990
+ addDecoratorUses(fn);
58991
+ for (const decoratorChild of node.namedChildren) {
58992
+ if (decoratorChild.type !== "decorator")
58993
+ continue;
58994
+ const nameNode = fn?.childForFieldName("name");
58995
+ if (!nameNode)
58996
+ continue;
58997
+ const name = sliceText(nameNode, context.source);
58998
+ const def = context.moduleEntry.locals.find((local) => local.localName === name);
58999
+ if (!def)
59000
+ continue;
59001
+ const fromId = ensureNode(context, def);
59002
+ const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
59003
+ if (expr)
59004
+ tryResolveNode(context, expr, fromId, "decorates");
59005
+ }
59006
+ } else if (node.type === "function_definition") {
59007
+ const nameNode = node.childForFieldName("name");
59008
+ if (nameNode) {
59009
+ const name = sliceText(nameNode, context.source);
59010
+ const def = context.moduleEntry.locals.find((local) => local.localName === name);
59011
+ if (def) {
59012
+ const fromId = ensureNode(context, def);
59013
+ let prev = node.previousSibling;
59014
+ while (prev) {
59015
+ if (prev.type === "decorated_definition") {
59016
+ for (const decoratorChild of prev.namedChildren) {
59017
+ if (decoratorChild.type === "decorator") {
59018
+ const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
59019
+ if (expr)
59020
+ tryResolveNode(context, expr, fromId, "decorates");
59021
+ } else if (decoratorChild.type === "attribute") {
59022
+ tryResolveNode(context, decoratorChild, fromId, "decorates");
59023
+ }
59024
+ }
59025
+ } else if (prev.type === "decorator") {
59026
+ const expr = prev.childForFieldName?.("name") ?? prev.namedChildren?.[0] ?? prev.child(1);
59027
+ if (expr)
59028
+ tryResolveNode(context, expr, fromId, "decorates");
59029
+ }
59030
+ prev = prev.previousSibling;
59031
+ }
59032
+ }
59033
+ }
59034
+ }
59035
+ for (const child of node.namedChildren)
59036
+ addDecoratorUses(child);
59037
+ };
59038
+ addDecoratorUses(rootNode);
59039
+ }
59040
+ function emitMemberOwnershipEdges(context, functionNodes, classNodes) {
59041
+ for (const fn of functionNodes) {
59042
+ const owners = classNodes.filter((candidate) => candidate.node.startIndex <= fn.node.startIndex && candidate.node.endIndex >= fn.node.endIndex).sort((left, right) => left.node.endIndex - left.node.startIndex - (right.node.endIndex - right.node.startIndex));
59043
+ const owner = owners[0];
59044
+ if (!owner)
59045
+ continue;
59046
+ const memberId = ensureNode(context, fn.def);
59047
+ markImplementationTarget(context, memberId, fn.node, fn.def);
59048
+ markMemberArity(context, memberId, fn.node);
59049
+ recordDefEdge(context, memberId, owner.def, "member_of");
59050
+ }
59051
+ }
59052
+ function resolveNamedType(context, name) {
59053
+ const fromAlias = context.aliasToTargetDef.get(name);
59054
+ if (fromAlias && declaresMembers(fromAlias))
59055
+ return fromAlias;
59056
+ return context.moduleEntry.locals.find((local) => local.localName === name && declaresMembers(local)) ?? null;
59057
+ }
59058
+ function emitFunctionBodyEdges(context, functionNodes) {
59059
+ const callNodeTypes = /* @__PURE__ */ new Set([
59060
+ "call_expression",
59061
+ "call",
59062
+ "method_invocation",
59063
+ "invocation_expression",
59064
+ // PHP models plain calls and receiver calls as three distinct call nodes.
59065
+ "function_call_expression",
59066
+ "member_call_expression",
59067
+ "nullsafe_member_call_expression",
59068
+ "scoped_call_expression"
59069
+ ]);
59070
+ const newNodeTypes = /* @__PURE__ */ new Set([
59071
+ "new_expression",
59072
+ "object_creation_expression",
59073
+ "struct_expression",
59074
+ "composite_literal"
59075
+ ]);
59076
+ let membersByContainer;
59077
+ const lexicalMembers = (container) => {
59078
+ if (!membersByContainer) {
59079
+ membersByContainer = /* @__PURE__ */ new Map();
59080
+ for (const candidate of functionNodes) {
59081
+ const owner = nearestMemberContainer(candidate.node);
59082
+ if (!owner)
59083
+ continue;
59084
+ const members = membersByContainer.get(owner.startIndex);
59085
+ if (members)
59086
+ members.push(candidate);
59087
+ else
59088
+ membersByContainer.set(owner.startIndex, [candidate]);
59089
+ }
59090
+ }
59091
+ return membersByContainer.get(container.startIndex) ?? [];
59092
+ };
59093
+ const receiverProofs = /* @__PURE__ */ new Map();
59094
+ for (const fn of functionNodes) {
59095
+ const fromId = ensureNode(context, fn.def);
59096
+ const seenAliases = /* @__PURE__ */ new Set();
59097
+ const nestedFunctions = new Set(functionNodes.filter((candidate) => candidate.node !== fn.node && candidate.node.startIndex >= fn.node.startIndex && candidate.node.endIndex <= fn.node.endIndex).map((candidate) => candidate.node));
59098
+ const recordAliasUse = (node) => {
59099
+ if (context.membersOnly || !isIdentifierType(context.sup, node.type))
59100
+ return;
59101
+ const name = sliceText(node, context.source);
59102
+ if (seenAliases.has(name))
59103
+ return;
59104
+ let target = context.aliasToTargetDef.get(name) ?? null;
59105
+ if (!target) {
59106
+ const modFile = context.aliasToTargetModule.get(name);
59107
+ if (modFile) {
59108
+ let exportedName = null;
59109
+ const parent = node.parent;
59110
+ if (parent && (parent.type === context.memberExpressionType || parent.type === "optional_member_expression")) {
59111
+ const { property: prop } = getMemberAccessParts(context.sup, parent);
59112
+ if (prop && context.propertyIdentifierTypes.includes(prop.type)) {
59113
+ exportedName = sliceText(prop, context.source);
59114
+ }
59115
+ }
59116
+ if (exportedName) {
59117
+ target = context.resolveExportFrom(modFile, exportedName);
59118
+ if (!target) {
59119
+ const targetModule = context.index.byFile.get(fileIdentityKey(modFile));
59120
+ target = (targetModule?.locals ?? []).find((local) => local.localName === exportedName) ?? null;
59121
+ }
59122
+ }
59123
+ }
59124
+ }
59125
+ if (!target)
59126
+ return;
59127
+ seenAliases.add(name);
59128
+ recordDefEdge(context, fromId, target, "uses");
59129
+ };
59130
+ const recordMemberUse = (node) => {
59131
+ if (!context.optionalMemberTypes.has(node.type))
59132
+ return;
59133
+ const targetDef = context.resolveMemberChainTarget(node);
59134
+ if (targetDef) {
59135
+ recordDefEdge(context, fromId, targetDef, "uses");
59136
+ }
59137
+ };
59138
+ const recordReceiverCall = (node, access) => {
59139
+ const memberName = sliceText(access.property, context.source);
59140
+ if (!memberName || !context.hasCallableNamed(memberName))
59141
+ return;
59142
+ const binding = classifyReceiver(context.sup, access.receiver, context.source, receiverProofs, fn.node.startIndex, access.accessNode);
59143
+ if (!binding)
59144
+ return;
59145
+ const site = { file: context.moduleEntry.file, range: toRange(access.property) };
59146
+ const argumentCount = callArgumentCount(node);
59147
+ if (binding.kind === "named-type") {
59148
+ const typeDef = resolveNamedType(context, binding.typeName);
59149
+ if (!typeDef)
59150
+ return;
59151
+ context.receiverCalls.push({
59152
+ callerId: fromId,
59153
+ ownerId: ensureNode(context, typeDef),
59154
+ viaSupertypes: false,
59155
+ memberName,
59156
+ argumentCount,
59157
+ site
59158
+ });
59159
+ return;
59160
+ }
59161
+ if (binding.kind === "own-type") {
59162
+ const container = nearestMemberContainer(fn.node);
59163
+ const declared = container ? lexicalMembers(container).filter((candidate) => candidate.def.localName === memberName) : [];
59164
+ if (declared.length === 1) {
59165
+ recordDefEdge(context, fromId, declared[0].def, "calls", access.property);
59166
+ return;
59167
+ }
59168
+ }
59169
+ context.receiverCalls.push({
59170
+ callerId: fromId,
59171
+ ownerId: null,
59172
+ viaSupertypes: binding.kind === "supertype",
59173
+ memberName,
59174
+ argumentCount,
59175
+ site
59176
+ });
59177
+ };
59178
+ const resolveCallTarget = (node, callee) => {
59179
+ const access = receiverCallAccess(context.sup, node, callee);
59180
+ if (access) {
59181
+ if (!tryResolveChain(context, access.accessNode, fromId, "calls"))
59182
+ recordReceiverCall(node, access);
59183
+ return;
59184
+ }
59185
+ if (callee)
59186
+ tryResolveNode(context, callee, fromId, "calls");
59187
+ };
59188
+ const recordCallOrInstantiation = (node) => {
59189
+ if (callNodeTypes.has(node.type)) {
59190
+ if (context.sup.id === "go") {
59191
+ const callTarget = getCallTarget(node);
59192
+ const calleeName = callTarget && isIdentifierType(context.sup, callTarget.type) ? sliceText(callTarget, context.source) : null;
59193
+ if (calleeName === "new" || calleeName === "make") {
59194
+ const argList = node.childForFieldName("arguments") ?? node.childForFieldName("argument_list");
59195
+ const typeNode = argList?.namedChildren?.find((child) => child.type === "type_identifier") ?? null;
59196
+ if (typeNode) {
59197
+ tryResolveNode(context, typeNode, fromId, "instantiates");
59198
+ }
59199
+ return false;
59200
+ }
59201
+ }
59202
+ if (context.sup.id === "ruby" && node.type === "call") {
59203
+ const methodNode = node.childForFieldName("method");
59204
+ const receiverNode = node.childForFieldName("receiver");
59205
+ const methodName = methodNode ? sliceText(methodNode, context.source) : null;
59206
+ if (methodName === "new" && receiverNode) {
59207
+ tryResolveNode(context, receiverNode, fromId, "instantiates");
59208
+ return false;
59209
+ }
59210
+ if (methodNode) {
59211
+ resolveCallTarget(node, methodNode);
59212
+ return false;
59213
+ }
59214
+ }
59215
+ resolveCallTarget(node, getCallTarget(node));
59216
+ }
59217
+ if (newNodeTypes.has(node.type)) {
59218
+ const target = getNewTarget(node);
59219
+ if (target)
59220
+ tryResolveNode(context, target, fromId, "instantiates");
59221
+ }
59222
+ return true;
59223
+ };
59224
+ const walkFunctionBody = (node, allowCallProcessing) => {
59225
+ if (node !== fn.node && nestedFunctions.has(node))
59226
+ return;
59227
+ recordAliasUse(node);
59228
+ recordMemberUse(node);
59229
+ const allowChildCallProcessing = allowCallProcessing ? recordCallOrInstantiation(node) : false;
59230
+ for (const child of node.namedChildren ?? [])
59231
+ walkFunctionBody(child, allowChildCallProcessing);
59232
+ };
59233
+ walkFunctionBody(fn.node, true);
59234
+ }
59235
+ }
59236
+ function recordIdentifierRelations(context, fromId, container, relationForTarget) {
59237
+ const identifiers = [];
59238
+ const collect = (node) => {
59239
+ if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
59240
+ identifiers.push(node);
59241
+ return;
59242
+ }
59243
+ for (const child of node.namedChildren ?? [])
59244
+ collect(child);
59245
+ };
59246
+ collect(container);
59247
+ const seen = /* @__PURE__ */ new Set();
59248
+ for (const [index, identifier] of identifiers.entries()) {
59249
+ const target = context.resolveIdentifier(sliceText(identifier, context.source));
59250
+ if (!target)
59251
+ continue;
59252
+ const targetId = defNodeId(target);
59253
+ if (seen.has(targetId))
59254
+ continue;
59255
+ seen.add(targetId);
59256
+ recordDefEdge(context, fromId, target, relationForTarget(target, index), identifier);
59257
+ }
59258
+ }
59259
+ function collectDirectCallsExcludingNestedScopes(node, out) {
59260
+ for (const child of node.namedChildren ?? []) {
59261
+ if (child.type === "call")
59262
+ out.push(child);
59263
+ if (RUBY_NESTED_SCOPE_TYPES.has(child.type))
59264
+ continue;
59265
+ collectDirectCallsExcludingNestedScopes(child, out);
59266
+ }
59267
+ }
59268
+ function emitClassInheritanceEdges(context, classNodes) {
59269
+ const interfaceIds = new Set(classNodes.filter((candidate) => candidate.node.type === "interface_declaration" || candidate.node.type === "protocol_declaration" || candidate.node.type === "trait_item" || /^(?:interface|protocol|trait)\b/.test(sliceText(candidate.node, context.source).trimStart())).map((candidate) => defNodeId(candidate.def)));
59270
+ for (const cls of classNodes) {
59271
+ const fromId = ensureNode(context, cls.def);
59272
+ markImplementationTarget(context, fromId, cls.node, cls.def);
59273
+ if (context.sup.id === "java") {
59274
+ const superClass = findFirstNodeByType(cls.node, "superclass");
59275
+ const superNode2 = superClass?.childForFieldName("name") ?? superClass?.namedChildren?.[0] ?? null;
59276
+ if (superNode2)
59277
+ tryResolveNode(context, superNode2, fromId, "extends");
59278
+ const interfaces = findFirstNodeByType(cls.node, "super_interfaces");
59279
+ if (interfaces) {
59280
+ const names = [];
59281
+ collectIdentifiers(interfaces, context.sup, context.source, names);
59282
+ for (const name of names) {
59283
+ const target = context.resolveIdentifier(name);
59284
+ if (target)
59285
+ recordDefEdge(context, fromId, target, "implements", interfaces);
59286
+ }
59287
+ }
59288
+ continue;
59289
+ }
59290
+ if (context.sup.id === "csharp") {
59291
+ const baseList = findFirstNodeByType(cls.node, "base_list");
59292
+ if (baseList) {
59293
+ recordIdentifierRelations(context, fromId, baseList, (target, index) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
59294
+ }
59295
+ continue;
59296
+ }
59297
+ if (context.sup.id === "python") {
59298
+ const bases = cls.node.childForFieldName("superclasses") ?? findFirstNodeByType(cls.node, "argument_list");
59299
+ if (bases)
59300
+ recordIdentifierRelations(context, fromId, bases, () => "extends");
59301
+ continue;
59302
+ }
59303
+ if (context.sup.id === "php") {
59304
+ const base = findFirstNodeByType(cls.node, "base_clause");
59305
+ if (base)
59306
+ recordIdentifierRelations(context, fromId, base, () => "extends");
59307
+ const interfaces = findFirstNodeByType(cls.node, "class_interface_clause");
59308
+ if (interfaces)
59309
+ recordIdentifierRelations(context, fromId, interfaces, () => "implements");
59310
+ const traitUses = [];
59311
+ collectNodesByType(cls.node, "use_declaration", traitUses);
59312
+ for (const traitUse of traitUses)
59313
+ recordIdentifierRelations(context, fromId, traitUse, () => "trait");
59314
+ continue;
59315
+ }
59316
+ if (context.sup.id === "ruby") {
59317
+ const superclass = findFirstNodeByType(cls.node, "superclass");
59318
+ if (superclass)
59319
+ recordIdentifierRelations(context, fromId, superclass, () => "extends");
59320
+ const calls = [];
59321
+ collectDirectCallsExcludingNestedScopes(cls.node, calls);
59322
+ for (const call of calls) {
59323
+ if (call.childForFieldName("receiver"))
59324
+ continue;
59325
+ const methodNode = call.childForFieldName("method");
59326
+ const methodName = methodNode ? sliceText(methodNode, context.source) : void 0;
59327
+ if (methodName !== "include" && methodName !== "extend" && methodName !== "prepend")
59328
+ continue;
59329
+ const args = call.childForFieldName("arguments");
59330
+ if (args)
59331
+ recordIdentifierRelations(context, fromId, args, () => "mixin");
59332
+ }
59333
+ continue;
59334
+ }
59335
+ if (context.sup.id === "cpp") {
59336
+ const bases = findFirstNodeByType(cls.node, "base_class_clause");
59337
+ if (bases)
59338
+ recordIdentifierRelations(context, fromId, bases, () => "extends");
59339
+ continue;
59340
+ }
59341
+ if (context.sup.id === "kotlin") {
59342
+ const bases = findFirstNodeByType(cls.node, "delegation_specifiers");
59343
+ if (bases) {
59344
+ recordIdentifierRelations(context, fromId, bases, (target, index) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
59345
+ }
59346
+ continue;
59347
+ }
59348
+ if (context.sup.id === "swift") {
59349
+ const bases = [];
59350
+ collectNodesByType(cls.node, "inheritance_specifier", bases);
59351
+ for (const [index, base] of bases.entries()) {
59352
+ recordIdentifierRelations(context, fromId, base, (target) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
59353
+ }
59354
+ continue;
59355
+ }
59356
+ const superClause = findFirstNodeByType(cls.node, "extends_clause");
59357
+ const superNode = superClause?.namedChildren?.[0] ?? superClause?.child(1);
59358
+ if (superNode)
59359
+ tryResolveNode(context, superNode, fromId, "extends");
59360
+ const implementsClauses = [];
59361
+ collectNodesByType(cls.node, "implements_clause", implementsClauses);
59362
+ for (const clause of implementsClauses) {
59363
+ const names = [];
59364
+ collectIdentifiers(clause, context.sup, context.source, names);
59365
+ for (const name of names) {
59366
+ const target = context.resolveIdentifier(name);
59367
+ if (target)
59368
+ recordDefEdge(context, fromId, target, "implements", clause);
59369
+ }
59370
+ }
59371
+ }
59372
+ }
59373
+ function emitRustImplEdges(context, rootNode) {
59374
+ if (context.sup.id !== "rust")
59375
+ return;
59376
+ const walkImpls = (node) => {
59377
+ if (node.type === "impl_item") {
59378
+ const typeIdentifiers = node.namedChildren?.filter((child) => child.type === "type_identifier") ?? [];
59379
+ if (typeIdentifiers.length >= 2) {
59380
+ const traitName = sliceText(typeIdentifiers[0], context.source);
59381
+ const typeName = sliceText(typeIdentifiers[1], context.source);
59382
+ const typeDef = context.resolveIdentifier(typeName);
59383
+ const traitDef = context.resolveIdentifier(traitName);
59384
+ if (typeDef && traitDef) {
59385
+ const fromId = ensureNode(context, typeDef);
59386
+ recordDefEdge(context, fromId, traitDef, "implements", node);
59387
+ }
59388
+ }
59389
+ }
59390
+ for (const child of node.namedChildren ?? [])
59391
+ walkImpls(child);
59392
+ };
59393
+ walkImpls(rootNode);
59394
+ }
59395
+ function emitMemberImplementationEdges(graph, recordEdge) {
59396
+ const membersByOwner = /* @__PURE__ */ new Map();
59397
+ for (const edge of graph.edges) {
59398
+ if (edge.label !== "member_of")
59399
+ continue;
59400
+ const members = membersByOwner.get(edge.to) ?? [];
59401
+ members.push(edge.from);
59402
+ membersByOwner.set(edge.to, members);
59403
+ }
59404
+ const hierarchyByKey = /* @__PURE__ */ new Map();
59405
+ for (const edge of graph.edges) {
59406
+ if (edge.label !== "extends" && edge.label !== "implements" && edge.label !== "trait" && edge.label !== "mixin")
59407
+ continue;
59408
+ const key = `${edge.from}->${edge.to}::${edge.label}`;
59409
+ const existing = hierarchyByKey.get(key);
59410
+ if (!existing || !existing.site && edge.site)
59411
+ hierarchyByKey.set(key, edge);
59412
+ }
59413
+ const hierarchyEdges = [...hierarchyByKey.values()];
59414
+ for (const hierarchyEdge of hierarchyEdges) {
59415
+ const parentMembers = membersByOwner.get(hierarchyEdge.to) ?? [];
59416
+ const childMembers = membersByOwner.get(hierarchyEdge.from) ?? [];
59417
+ for (const parentMemberId of parentMembers) {
59418
+ const parentMember = graph.nodes.get(parentMemberId);
59419
+ if (!parentMember)
59420
+ continue;
59421
+ if (parentMember.memberArity === void 0)
59422
+ continue;
59423
+ const parentIdentityMatches = parentMembers.filter((memberId) => {
59424
+ const candidate = graph.nodes.get(memberId);
59425
+ return candidate?.name === parentMember.name && candidate.memberArity === parentMember.memberArity;
59426
+ });
59427
+ if (parentIdentityMatches.length !== 1)
59428
+ continue;
59429
+ const isContractMember = hierarchyEdge.label !== "extends" || parentMember.implementationTarget;
59430
+ if (!isContractMember)
59431
+ continue;
59432
+ const compatibleMembers = childMembers.filter((memberId) => {
59433
+ const childMember = graph.nodes.get(memberId);
59434
+ return childMember?.name === parentMember.name && childMember.memberArity === parentMember.memberArity;
59435
+ });
59436
+ if (compatibleMembers.length !== 1)
59437
+ continue;
59438
+ recordEdge(compatibleMembers[0], parentMemberId, hierarchyEdge.label === "extends" ? "overrides" : "implements_member", hierarchyEdge.site);
59439
+ }
59440
+ }
59441
+ }
59442
+ var RUBY_NESTED_SCOPE_TYPES;
59443
+ var init_edgePasses = __esm({
59444
+ "dist/graphs/symbol-graph-detailed/edgePasses.js"() {
59445
+ "use strict";
59446
+ init_ast();
59447
+ init_memberAccess();
59448
+ init_paths();
59449
+ init_symbol_graph();
59450
+ init_ast2();
59451
+ init_receiverCalls();
59452
+ RUBY_NESTED_SCOPE_TYPES = /* @__PURE__ */ new Set(["class", "module", "method", "singleton_method", "block", "do_block"]);
59453
+ }
59454
+ });
59455
+
59456
+ // dist/graphs/symbol-graph-detailed/importAliases.js
59457
+ function targetModuleForImport(index, imp) {
59458
+ const targetFile = typeof imp.resolved === "string" ? normalizePath(imp.resolved) : void 0;
59459
+ return targetFile ? index.byFile.get(fileIdentityKey(targetFile)) : void 0;
59460
+ }
59461
+ function buildImportAliasMaps(index, moduleEntry, resolveExportNamespace, resolveExportFrom) {
59462
+ const aliasToTargetDef = /* @__PURE__ */ new Map();
59463
+ const aliasToTargetModule = /* @__PURE__ */ new Map();
59464
+ for (const imp of moduleEntry.imports) {
59465
+ const targetModule = targetModuleForImport(index, imp);
59466
+ const targetFile = typeof imp.resolved === "string" ? normalizePath(imp.resolved) : void 0;
59467
+ if (!targetModule || !targetFile)
59468
+ continue;
59469
+ if (imp.kind === "named") {
59470
+ const localFallback = targetModule.locals.find((local) => local.localName === imp.imported);
59471
+ const fallbackResolved = localFallback ? {
59472
+ kind: "resolved",
59473
+ def: localFallback
59474
+ } : null;
59475
+ const resolved = resolveExportNamespace(targetFile, imp.imported) ?? fallbackResolved;
59476
+ if (resolved?.kind === "resolved") {
59477
+ aliasToTargetDef.set(imp.local, resolved.def);
59478
+ } else if (resolved?.kind === "namespace") {
59479
+ aliasToTargetModule.set(imp.local, normalizePath(resolved.file));
59480
+ }
59481
+ } else if (imp.kind === "default") {
59482
+ const defaultExport = resolveExportFrom(targetFile, "default");
59483
+ const fallbackExport = targetModule.exports.find((entry) => entry.type === "local")?.target;
59484
+ const def = defaultExport ?? fallbackExport;
59485
+ if (def)
59486
+ aliasToTargetDef.set(imp.local, def);
59487
+ aliasToTargetModule.set(imp.local, targetFile);
59488
+ } else if (imp.kind === "namespace") {
59489
+ aliasToTargetModule.set(imp.localNS, targetFile);
59490
+ }
59491
+ }
59492
+ return { aliasToTargetDef, aliasToTargetModule };
59493
+ }
59494
+ var init_importAliases = __esm({
59495
+ "dist/graphs/symbol-graph-detailed/importAliases.js"() {
59496
+ "use strict";
59497
+ init_paths();
59498
+ }
59499
+ });
59500
+
59501
+ // dist/graphs/symbol-graph-detailed/memberChains.js
59502
+ function createMemberChainResolver(args) {
59503
+ const memberExpressionType = memberExpressionTypeFor(args.sup);
59504
+ const propertyIdentifierTypes = memberPropertyIdentifierTypes(args.sup);
59505
+ const optionalMemberTypes = memberAccessTraversalTypes(args.sup);
59506
+ const resolveMemberChainTarget = (chainNode) => {
59507
+ const chain = collectMemberAccessChain({
59508
+ sup: args.sup,
59509
+ source: args.source,
59510
+ chainNode,
59511
+ constStringOf: args.constStringOf
59512
+ });
59513
+ if (!chain || !isIdentifierType(args.sup, chain.base.type))
59514
+ return null;
59515
+ const alias = sliceText(chain.base, args.source);
59516
+ const targetFile = args.aliasToTargetModule.get(alias);
59517
+ if (!targetFile)
59518
+ return null;
59519
+ return args.resolveMemberPathFromModule(targetFile, chain.names);
59520
+ };
59521
+ return {
59522
+ memberExpressionType,
59523
+ propertyIdentifierTypes,
59524
+ optionalMemberTypes,
59525
+ resolveMemberChainTarget
59526
+ };
59527
+ }
59528
+ var init_memberChains = __esm({
59529
+ "dist/graphs/symbol-graph-detailed/memberChains.js"() {
59530
+ "use strict";
59531
+ init_ast();
59532
+ init_memberAccess();
59533
+ init_ast2();
59534
+ }
59535
+ });
59536
+
59537
+ // dist/graphs/symbol-graph-detailed.js
59538
+ async function buildSymbolGraphDetailed(index, opts) {
59539
+ assertNativeRequiredAvailable(index.nativeMode);
59540
+ const base = await buildSymbolGraph(index, opts?.files ? { files: opts.files } : void 0);
59541
+ const configuredMaxEdges = typeof opts?.maxEdges === "number" && opts.maxEdges > 0 ? Math.floor(opts.maxEdges) : void 0;
59542
+ const maxEdges = configuredMaxEdges ?? Number.POSITIVE_INFINITY;
59543
+ const nodes = new Map(base.nodes);
59544
+ const edges = base.edges.slice(0, maxEdges);
59545
+ let omittedEdges = Math.max(0, base.edges.length - edges.length);
59546
+ let skippedSyntaxTreeFiles = 0;
59547
+ const added = /* @__PURE__ */ new Set();
59548
+ const membersOnly = !!opts?.membersOnly;
59549
+ const scopeMode = opts?.scope ?? "all";
59550
+ const importedByOthers = /* @__PURE__ */ new Set();
59551
+ if (scopeMode === "imported") {
59552
+ for (const moduleEntry of index.byFile.values()) {
59553
+ for (const imp of moduleEntry.imports) {
59554
+ const target = typeof imp.resolved === "string" ? fileIdentityKey(imp.resolved) : void 0;
59555
+ if (target)
59556
+ importedByOthers.add(target);
59557
+ }
59558
+ }
59559
+ }
59560
+ let edgeCount = edges.length;
59561
+ const maybePushEdge = (fromId, toId, label, site) => {
59562
+ if (edgeCount >= maxEdges) {
59563
+ omittedEdges += 1;
59564
+ return false;
59565
+ }
59566
+ edges.push({
59567
+ from: fromId,
59568
+ to: toId,
59569
+ ...label ? { label } : {},
59570
+ ...site ? { site } : {}
59571
+ });
59572
+ edgeCount++;
59573
+ return true;
59574
+ };
59575
+ const recordEdge = (fromId, toId, label, site) => {
59576
+ const siteKey = site ? `${site.file}:${site.range.start.index ?? ""}:${site.range.end.index ?? ""}` : "";
59577
+ const key = `${fromId}->${toId}::${label ?? ""}::${siteKey}`;
59578
+ if (added.has(key))
59579
+ return true;
59580
+ added.add(key);
59581
+ return maybePushEdge(fromId, toId, label, site);
59582
+ };
59583
+ const resolveExportNamespace = (file2, exportedName) => resolveExport(index, file2, exportedName);
59584
+ const resolveExportDef = (file2, exportedName) => {
59585
+ const resolved = resolveExportNamespace(file2, exportedName);
59586
+ return resolved?.kind === "resolved" ? resolved.def : null;
59587
+ };
59588
+ const resolveMemberPathFromModule = (startFile, names) => {
59589
+ let file2 = normalizePath(startFile);
59590
+ let targetDef = null;
59591
+ for (const segment of [...names].reverse()) {
59592
+ if (!file2)
59593
+ break;
59594
+ const resolved = resolveExportNamespace(file2, segment);
59595
+ if (!resolved) {
59596
+ targetDef = null;
59597
+ break;
59598
+ }
59599
+ if (resolved.kind === "namespace") {
59600
+ file2 = normalizePath(resolved.file);
59601
+ targetDef = null;
59602
+ continue;
59603
+ }
59604
+ targetDef = resolved.def;
59605
+ file2 = normalizePath(targetDef.file);
59606
+ }
59607
+ if (targetDef) {
59608
+ return targetDef;
59609
+ }
59610
+ const fileKey = typeof file2 === "string" ? fileIdentityKey(file2) : null;
59611
+ const moduleEntry = fileKey ? index.byFile.get(fileKey) : void 0;
59612
+ const lastName = names[0];
59613
+ return moduleEntry?.locals.find((entry) => entry.localName === lastName) ?? null;
59614
+ };
59615
+ const resolveExportFrom = (file2, exportedName) => resolveExportDef(file2, exportedName);
59616
+ const receiverCalls = [];
59617
+ let callableNames;
59618
+ const hasCallableNamed = (name) => {
59619
+ if (!callableNames) {
59620
+ callableNames = /* @__PURE__ */ new Set();
59621
+ for (const entry of index.byFile.values()) {
59622
+ for (const local of entry.locals) {
59623
+ if (local.kind === SymbolKind.Function)
59624
+ callableNames.add(local.localName);
59625
+ }
59626
+ }
59627
+ }
59628
+ return callableNames.has(name);
59629
+ };
59630
+ const optionFileKeys = opts?.files ? new Set(Array.from(opts.files, fileIdentityKey)) : void 0;
59631
+ for (const moduleEntry of index.byFile.values()) {
59632
+ const file2 = moduleEntry.file;
59633
+ if (optionFileKeys && !optionFileKeys.has(fileIdentityKey(file2)))
59634
+ continue;
59635
+ if (scopeMode === "imported") {
59636
+ const hasFuncOrClass = moduleEntry.locals.some((local) => local.kind === SymbolKind.Function || local.kind === SymbolKind.Class);
59637
+ const isImportedOrImports = importedByOthers.has(fileIdentityKey(file2)) || !!moduleEntry.imports.length;
59638
+ if (!(hasFuncOrClass && isImportedOrImports))
59639
+ continue;
59640
+ }
59641
+ try {
59642
+ const parsedEntry = index.parsed?.get(fileIdentityKey(file2));
59643
+ let sup = parsedEntry?.sup;
59644
+ let src = parsedEntry?.source;
59645
+ let tree = parsedEntry?.tree;
59646
+ if (!sup || src === void 0) {
59647
+ const prep = await prepareSourceInput(file2, {
59648
+ languageExtensions: index.languageExtensions
59649
+ });
59650
+ sup = prep.sup;
59651
+ src = prep.source;
59652
+ }
59653
+ if (sup && !sup.supportsCrossModuleSymbols) {
59654
+ continue;
59655
+ }
59656
+ if (sup && src !== void 0 && !tree) {
59657
+ const nativeTreeExecution = getNativeSyntaxTreeExecution(src, sup, index.nativeMode);
59658
+ if (nativeTreeExecution.tree) {
59659
+ tree = new ProjectedSyntaxTree(src, nativeTreeExecution.tree);
59660
+ } else {
59661
+ skippedSyntaxTreeFiles += 1;
59662
+ continue;
59663
+ }
59664
+ }
59665
+ if (!sup || src === void 0 || !tree) {
59666
+ throw new Error(`Failed to parse ${file2}`);
59667
+ }
59668
+ const { aliasToTargetDef, aliasToTargetModule } = buildImportAliasMaps(index, moduleEntry, resolveExportNamespace, resolveExportFrom);
59669
+ const { functionNodes, classNodes, constStringOf } = collectDetailedDeclarations(tree.rootNode, sup, src, moduleEntry.locals);
59670
+ const memberResolver = createMemberChainResolver({
59671
+ sup,
59672
+ source: src,
59673
+ constStringOf,
59674
+ aliasToTargetModule,
59675
+ resolveMemberPathFromModule
59676
+ });
59677
+ const { memberExpressionType, optionalMemberTypes, propertyIdentifierTypes, resolveMemberChainTarget } = memberResolver;
59678
+ const resolveIdentifier = (name) => {
59679
+ const fromAlias = aliasToTargetDef.get(name);
59680
+ if (fromAlias)
59681
+ return fromAlias;
59682
+ return moduleEntry.locals.find((local) => local.localName === name) ?? null;
59683
+ };
59684
+ const edgePassContext = {
59685
+ index,
59686
+ sup,
59687
+ source: src,
59688
+ moduleEntry,
59689
+ nodes,
59690
+ membersOnly,
59691
+ memberExpressionType,
59692
+ propertyIdentifierTypes,
59693
+ optionalMemberTypes,
59694
+ aliasToTargetDef,
59695
+ aliasToTargetModule,
59696
+ resolveIdentifier,
59697
+ resolveExportFrom,
59698
+ resolveMemberChainTarget,
59699
+ recordEdge,
59700
+ receiverCalls,
59701
+ hasCallableNamed
59702
+ };
59703
+ emitPythonDecoratorEdges(edgePassContext, tree.rootNode);
59704
+ emitFunctionBodyEdges(edgePassContext, functionNodes);
59705
+ emitMemberOwnershipEdges(edgePassContext, functionNodes, classNodes);
59706
+ emitClassInheritanceEdges(edgePassContext, classNodes);
59707
+ emitRustImplEdges(edgePassContext, tree.rootNode);
59708
+ } catch (error51) {
59709
+ if (isNativeRequiredUnavailableError(error51)) {
59710
+ throw error51;
59711
+ }
59712
+ if (isUnsupportedParserInputError(error51)) {
59713
+ continue;
59714
+ }
59715
+ logWithLevel(opts?.logLevel, "warn", `Warning: Failed to build detailed symbol edges for ${file2}:`, error51);
59716
+ }
59717
+ }
59718
+ emitReceiverCallEdges({ nodes, edges }, receiverCalls, recordEdge);
59719
+ emitMemberImplementationEdges({ nodes, edges }, recordEdge);
59720
+ if (skippedSyntaxTreeFiles > 0) {
59721
+ logWithLevel(opts?.logLevel, "warn", `Warning: Skipped detailed symbol edges for ${skippedSyntaxTreeFiles} file(s) because no syntax-tree backend was available.`);
59722
+ }
59723
+ return {
59724
+ nodes,
59725
+ edges,
59726
+ ...configuredMaxEdges !== void 0 ? {
59727
+ truncated: omittedEdges > 0,
59728
+ limits: { edges: configuredMaxEdges },
59729
+ omittedCounts: { edges: omittedEdges }
59730
+ } : {}
59731
+ };
59732
+ }
59733
+ var init_symbol_graph_detailed = __esm({
59734
+ "dist/graphs/symbol-graph-detailed.js"() {
59735
+ "use strict";
59736
+ init_filePrep();
59737
+ init_logging();
59738
+ init_projectedTree();
59739
+ init_treeSitterNative();
59740
+ init_navigation_resolve();
59741
+ init_types2();
59742
+ init_paths();
59743
+ init_symbol_graph();
59744
+ init_ast2();
59745
+ init_edgePasses();
59746
+ init_importAliases();
59747
+ init_memberChains();
59748
+ init_receiverCalls();
59749
+ }
59750
+ });
59751
+
59752
+ // dist/util/sourceLocation.js
59753
+ function parseSourceLocationInput(value) {
59754
+ const lineColumnMatch = FILE_LINE_COLUMN_PATTERN.exec(value);
59755
+ if (lineColumnMatch?.[1] && lineColumnMatch[2] && lineColumnMatch[3]) {
59756
+ return {
59757
+ file: lineColumnMatch[1],
59758
+ line: Number(lineColumnMatch[2]),
59759
+ column: Number(lineColumnMatch[3])
59760
+ };
59761
+ }
59762
+ const lineMatch = FILE_LINE_PATTERN.exec(value);
59763
+ if (lineMatch?.[1] && lineMatch[2]) {
59764
+ return { file: lineMatch[1], line: Number(lineMatch[2]) };
59765
+ }
59766
+ return { file: value };
59767
+ }
59768
+ var FILE_LINE_COLUMN_PATTERN, FILE_LINE_PATTERN;
59769
+ var init_sourceLocation = __esm({
59770
+ "dist/util/sourceLocation.js"() {
59771
+ "use strict";
59772
+ FILE_LINE_COLUMN_PATTERN = /^(.*):(\d+):(\d+)$/;
59773
+ FILE_LINE_PATTERN = /^(.*):(\d+)$/;
59774
+ }
59775
+ });
59776
+
59777
+ // dist/agent/shell.js
59778
+ function quoteShellArg(value) {
59779
+ if (/^[A-Za-z0-9_./:@-]+$/.test(value))
59780
+ return value;
59781
+ return `'${value.replace(/'/g, "'\\''")}'`;
59782
+ }
59783
+ var init_shell = __esm({
59784
+ "dist/agent/shell.js"() {
59785
+ "use strict";
59786
+ }
59787
+ });
59788
+
59789
+ // dist/agent/followUps.js
59790
+ function toolFollowUp(tool, arguments_ = {}, label) {
59791
+ return {
59792
+ tool,
59793
+ arguments: { ...arguments_ },
59794
+ ...label !== void 0 ? { label } : {}
59795
+ };
59796
+ }
59797
+ function dedupeAgentFollowUps(followUps) {
59798
+ const seen = /* @__PURE__ */ new Set();
59799
+ return followUps.filter((followUp) => {
59800
+ const serializedArguments = JSON.stringify(followUp.arguments);
59801
+ const key = `${followUp.tool.length}|${followUp.tool}${serializedArguments}`;
59802
+ if (seen.has(key))
59803
+ return false;
59804
+ seen.add(key);
59805
+ return true;
59806
+ });
59807
+ }
59808
+ function formatAgentFollowUpAsCli(followUp) {
59809
+ const args = followUp.arguments;
59810
+ switch (followUp.tool) {
59811
+ case "file_deps": {
59812
+ const file2 = stringArgument(args, "file");
59813
+ const direction = args.direction === "rdeps" ? "rdeps" : "deps";
59814
+ return appendJson(`codegraph ${direction}${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`, args);
59815
+ }
59816
+ case "calls": {
59817
+ const handle = stringArgument(args, "handle");
59818
+ const direction = args.direction === "callees" ? "callees" : "callers";
59819
+ return appendJson(`codegraph ${direction}${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
59820
+ }
59821
+ case "type_hierarchy": {
59822
+ const handle = stringArgument(args, "handle");
59823
+ const direction = args.direction === "subtypes" ? "subtypes" : "supertypes";
59824
+ return appendJson(`codegraph ${direction}${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
59825
+ }
59826
+ case "get_file": {
59827
+ const file2 = stringArgument(args, "file");
59828
+ return `codegraph file${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`;
59829
+ }
59830
+ case "packet_get": {
59831
+ const target = stringArgument(args, "target");
59832
+ return `codegraph packet get${target === void 0 ? "" : ` ${formatPathArgument(target)}`}`;
59833
+ }
59834
+ case "chunk": {
59835
+ const file2 = stringArgument(args, "file");
59836
+ return `codegraph chunk${file2 === void 0 ? "" : ` ${formatPathArgument(file2)}`}`;
59837
+ }
59838
+ case "get_symbol": {
59839
+ const handle = stringArgument(args, "handle");
59840
+ return `codegraph explain${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`;
59841
+ }
59842
+ case "goto": {
59843
+ const location = locationArgument(args);
59844
+ return `codegraph goto ${quoteShellArg(location)}`;
59845
+ }
59846
+ case "refs": {
59847
+ const target = stringArgument(args, "handle") ?? locationArgument(args);
59848
+ return `codegraph refs ${quoteShellArg(target)}`;
59849
+ }
59850
+ case "search": {
59851
+ const query = stringArgument(args, "query");
59852
+ let command = `codegraph search${query === void 0 ? "" : ` ${quoteShellArg(query)}`}`;
59853
+ if (typeof args.mode === "string")
59854
+ command += ` --mode ${quoteShellArg(args.mode)}`;
59855
+ if (typeof args.from === "string")
59856
+ command += ` --from ${quoteShellArg(args.from)}`;
59857
+ return `${command} --json`;
59858
+ }
59859
+ case "explore": {
59860
+ const query = stringArgument(args, "query");
59861
+ return `codegraph explore${query === void 0 ? "" : ` ${quoteShellArg(query)}`}`;
59862
+ }
59863
+ case "orient": {
59864
+ let command = "codegraph orient";
59865
+ if (typeof args.root === "string")
59866
+ command += ` --root ${quoteShellArg(args.root)}`;
59867
+ if (typeof args.budget === "string")
59868
+ command += ` --budget ${quoteShellArg(args.budget)}`;
59869
+ return command;
59870
+ }
59871
+ case "implementations": {
59872
+ const handle = stringArgument(args, "handle");
59873
+ return appendJson(`codegraph implementations${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`}`, args);
59874
+ }
59875
+ case "rename_preview": {
59876
+ const handle = stringArgument(args, "handle");
59877
+ const newName = stringArgument(args, "newName") ?? "<new-name>";
59878
+ return `codegraph rename-preview${handle === void 0 ? "" : ` ${quoteShellArg(handle)}`} ${quoteShellArg(newName)} --json`;
59879
+ }
59880
+ case "review":
59881
+ case "impact": {
59882
+ let command = `codegraph ${followUp.tool}`;
59883
+ if (typeof args.provider === "string")
59884
+ command += ` --provider ${quoteShellArg(args.provider)}`;
59885
+ if (typeof args.base === "string")
59886
+ command += ` --base ${quoteShellArg(args.base)}`;
59887
+ if (typeof args.head === "string")
59888
+ command += ` --head ${quoteShellArg(args.head)}`;
59889
+ return command;
59890
+ }
59891
+ case "duplicates": {
59892
+ const root = stringArgument(args, "root") ?? ".";
59893
+ const files = Array.isArray(args.files) ? args.files.filter((file2) => typeof file2 === "string") : [];
59894
+ let command = `codegraph duplicates --root ${quoteShellArg(root)} ${files.map(quoteShellArg).join(" ")}`;
59895
+ if (args.json === true)
59896
+ command += " --json";
59897
+ if (typeof args.minConfidence === "string")
59898
+ command += ` --min-confidence ${quoteShellArg(args.minConfidence)}`;
59899
+ if (args.includeSameFile === true)
59900
+ command += " --include-same-file";
59901
+ return command;
59902
+ }
59903
+ case "hotspots": {
59904
+ const root = stringArgument(args, "root") ?? ".";
59905
+ const limit = typeof args.limit === "number" ? ` --limit ${args.limit}` : "";
59906
+ return `codegraph hotspots ${quoteShellArg(root)}${limit}`;
59907
+ }
59908
+ default:
59909
+ return formatUnknownFollowUp(followUp);
59910
+ }
59911
+ }
59912
+ function formatAgentFollowUpsAsCli(followUps) {
59913
+ return followUps.map(formatAgentFollowUpAsCli);
59914
+ }
59915
+ function stringArgument(args, key) {
59916
+ return typeof args[key] === "string" ? args[key] : void 0;
59917
+ }
59918
+ function locationArgument(args) {
59919
+ const file2 = stringArgument(args, "file") ?? "<file>";
59920
+ const line = typeof args.line === "number" ? args.line : 1;
59921
+ const column = typeof args.column === "number" ? args.column : 0;
59922
+ return `${file2}:${line}:${column}`;
59923
+ }
59924
+ function formatPathArgument(value) {
59925
+ const target = value.startsWith("-") || value.startsWith("file:") || value.startsWith("symbol:") || value.startsWith("chunk:") || value.startsWith("sql:") || value.startsWith("graph:") || value.startsWith("review:") ? `./${value}` : value;
59926
+ return quoteShellArg(target);
59927
+ }
59928
+ function appendJson(command, args) {
59929
+ let output = command;
59930
+ if (typeof args.depth === "number")
59931
+ output += ` --depth ${args.depth}`;
59932
+ if (typeof args.limit === "number")
59933
+ output += ` --limit ${args.limit}`;
59934
+ if (args.includeHeuristic === true)
59935
+ output += " --include-heuristic";
59936
+ return `${output} --json`;
59937
+ }
59938
+ function formatUnknownFollowUp(followUp) {
59939
+ let command = `codegraph ${followUp.tool}`;
59940
+ for (const [key, value] of Object.entries(followUp.arguments)) {
59941
+ if (value === void 0 || value === false)
59942
+ continue;
59943
+ if (value === true) {
59944
+ command += ` --${key}`;
59945
+ continue;
59946
+ }
59947
+ if (typeof value === "string" || typeof value === "number") {
59948
+ command += ` --${key} ${quoteShellArg(String(value))}`;
59949
+ }
59950
+ }
59951
+ return command;
59952
+ }
59953
+ var init_followUps = __esm({
59954
+ "dist/agent/followUps.js"() {
59955
+ "use strict";
59956
+ init_shell();
59957
+ }
59958
+ });
59959
+
59960
+ // dist/agent/normalize.js
59961
+ import path48 from "node:path";
58877
59962
  function normalizeAgentFilePath(root, file2) {
58878
59963
  return toProjectRelativePath(root, file2) ?? normalizePath(path48.resolve(file2));
58879
59964
  }
@@ -61663,8 +62748,8 @@ ${block}
61663
62748
  function removeMarkedTomlBlock(existing, configPath) {
61664
62749
  if (inspectCodexTomlOwnership(existing, configPath) === null)
61665
62750
  return existing;
61666
- const begin = escapeRegExp(CODEGRAPH_TOML_MARKER_BEGIN);
61667
- const end = escapeRegExp(CODEGRAPH_TOML_MARKER_END);
62751
+ const begin = escapeRegExp2(CODEGRAPH_TOML_MARKER_BEGIN);
62752
+ const end = escapeRegExp2(CODEGRAPH_TOML_MARKER_END);
61668
62753
  const pattern = new RegExp(`\\n?${begin}[\\s\\S]*?${end}\\n?`, "g");
61669
62754
  return existing.replace(pattern, "\n").replace(/\n{3,}/g, "\n\n");
61670
62755
  }
@@ -62089,7 +63174,7 @@ async function renameTemporaryFile(temporaryPath, filePath) {
62089
63174
  }
62090
63175
  }
62091
63176
  }
62092
- function escapeRegExp(value) {
63177
+ function escapeRegExp2(value) {
62093
63178
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62094
63179
  }
62095
63180
  var InstallerCollisionError, TARGET_DEFINITIONS, CODEGRAPH_TOML_MARKER_BEGIN, CODEGRAPH_TOML_MARKER_END, DEFAULT_TARGET_IDS;
@@ -65214,806 +66299,253 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
65214
66299
  }
65215
66300
  }
65216
66301
  }
65217
- failures.sort(compareFailures);
65218
- return {
65219
- schemaVersion: 1,
65220
- root: normalizePath(root),
65221
- summary: {
65222
- filesScanned: markdownFiles.length,
65223
- linksChecked,
65224
- externalSkipped,
65225
- failures: failures.length
65226
- },
65227
- failures
65228
- };
65229
- }
65230
- async function recoverDisplayFileCasing(file2) {
65231
- const dir = path64.dirname(file2);
65232
- const base = path64.basename(file2);
65233
- try {
65234
- const entries = await fsp34.readdir(dir);
65235
- const match = entries.find((entry) => entry.toLowerCase() === base.toLowerCase());
65236
- return match ? path64.join(dir, match) : file2;
65237
- } catch {
65238
- return file2;
65239
- }
65240
- }
65241
- function parseLocalLinkTarget(destination) {
65242
- let trimmed = destination.trim();
65243
- if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
65244
- trimmed = trimmed.slice(1, -1).trim();
65245
- }
65246
- if (!trimmed)
65247
- return null;
65248
- const hashIndex = trimmed.indexOf("#");
65249
- const pathWithQuery = hashIndex >= 0 ? trimmed.slice(0, hashIndex) : trimmed;
65250
- const queryIndex = pathWithQuery.indexOf("?");
65251
- const targetPath = queryIndex >= 0 ? pathWithQuery.slice(0, queryIndex) : pathWithQuery;
65252
- const fragment = hashIndex >= 0 ? decodeFragment(trimmed.slice(hashIndex + 1)) : void 0;
65253
- return {
65254
- path: decodeMarkdownPath(targetPath),
65255
- ...fragment ? { fragment } : {}
65256
- };
65257
- }
65258
- function decodeMarkdownPath(targetPath) {
65259
- return decodeUriComponent(unescapeMarkdownPunctuation(targetPath));
65260
- }
65261
- function decodeFragment(fragment) {
65262
- return decodeUriComponent(fragment);
65263
- }
65264
- function decodeUriComponent(value) {
65265
- try {
65266
- return decodeURIComponent(value);
65267
- } catch {
65268
- return value;
65269
- }
65270
- }
65271
- function unescapeMarkdownPunctuation(value) {
65272
- let unescaped = "";
65273
- for (let index = 0; index < value.length; index += 1) {
65274
- const character = value.charAt(index);
65275
- const escapedCharacter = value.charAt(index + 1);
65276
- if (character === "\\" && isMarkdownPunctuation(escapedCharacter)) {
65277
- unescaped += escapedCharacter;
65278
- index += 1;
65279
- continue;
65280
- }
65281
- unescaped += character;
65282
- }
65283
- return unescaped;
65284
- }
65285
- function isMarkdownPunctuation(value) {
65286
- const code = value.charCodeAt(0);
65287
- return code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
65288
- }
65289
- function resolveMarkdownTarget(root, sourceFile, destination) {
65290
- if (!destination)
65291
- return sourceFile;
65292
- if (WINDOWS_ABSOLUTE_PATH.test(destination))
65293
- return path64.resolve(destination);
65294
- if (destination.startsWith("/"))
65295
- return path64.join(root, destination);
65296
- return path64.resolve(path64.dirname(sourceFile), destination);
65297
- }
65298
- async function cachedTargetStatus(target, targetStatusByPath) {
65299
- let status = targetStatusByPath.get(target);
65300
- if (!status) {
65301
- status = readTargetStatus(target);
65302
- targetStatusByPath.set(target, status);
65303
- }
65304
- return await status;
65305
- }
65306
- async function readTargetStatus(target) {
65307
- try {
65308
- const realPath = await fsp34.realpath(target);
65309
- const stats = await fsp34.stat(realPath);
65310
- return { status: "found", isDirectory: stats.isDirectory(), realPath };
65311
- } catch (error51) {
65312
- if (isMissingPathError3(error51))
65313
- return { status: "missing" };
65314
- throw new Error(`Failed to inspect Markdown link target ${normalizePath(target)}: ${error51 instanceof Error ? error51.message : String(error51)}`);
65315
- }
65316
- }
65317
- function isMissingPathError3(error51) {
65318
- return error51 instanceof Error && "code" in error51 && (error51.code === "ENOENT" || error51.code === "ENOTDIR");
65319
- }
65320
- async function cachedMarkdownAnchors(target, anchorsByPath) {
65321
- let anchors = anchorsByPath.get(target);
65322
- if (!anchors) {
65323
- anchors = readMarkdownFile(target).then(collectMarkdownAnchors);
65324
- anchorsByPath.set(target, anchors);
65325
- }
65326
- return await anchors;
65327
- }
65328
- async function readMarkdownFile(file2) {
65329
- try {
65330
- return await fsp34.readFile(file2, "utf8");
65331
- } catch (error51) {
65332
- if (error51 instanceof Error) {
65333
- throw new Error(`Failed to read Markdown file ${normalizePath(file2)}: ${error51.message}`);
65334
- }
65335
- throw error51;
65336
- }
65337
- }
65338
- function collectMarkdownAnchors(source) {
65339
- const anchors = /* @__PURE__ */ new Set();
65340
- const lines = source.split(/\r?\n/);
65341
- let fence = null;
65342
- for (let index = 0; index < lines.length; index += 1) {
65343
- const line = lines[index] ?? "";
65344
- const fenceMatch = line.match(/^ {0,3}(`{3,}|~{3,})/);
65345
- if (fenceMatch) {
65346
- const marker = fenceMatch[1]?.charAt(0);
65347
- if (marker === "`" || marker === "~") {
65348
- fence = fence === marker ? null : fence ?? marker;
65349
- }
65350
- continue;
65351
- }
65352
- if (fence || /^(?: {4}|\t)/.test(line))
65353
- continue;
65354
- const atx = line.match(/^ {0,3}#{1,6}[ \t]+(.+?)(?:[ \t]+#+[ \t]*)?$/);
65355
- if (atx?.[1]) {
65356
- addMarkdownAnchor(anchors, atx[1]);
65357
- continue;
65358
- }
65359
- const underline = lines[index + 1];
65360
- if (line.trim() && underline && /^ {0,3}(?:=+|-+)[ \t]*$/.test(underline)) {
65361
- addMarkdownAnchor(anchors, line);
65362
- index += 1;
65363
- }
65364
- }
65365
- return anchors;
65366
- }
65367
- function addMarkdownAnchor(anchors, heading) {
65368
- const baseSlug = markdownHeadingSlug(heading);
65369
- if (!baseSlug)
65370
- return;
65371
- let slug = baseSlug;
65372
- let suffix = 1;
65373
- while (anchors.has(slug)) {
65374
- slug = `${baseSlug}-${suffix}`;
65375
- suffix += 1;
65376
- }
65377
- anchors.add(slug);
65378
- }
65379
- function markdownHeadingSlug(heading) {
65380
- return renderMarkdownHeading(heading).trim().toLowerCase().replace(/[^\p{L}\p{N}_\-\s]/gu, "").replace(/\s+/g, "-");
65381
- }
65382
- function renderMarkdownHeading(heading) {
65383
- return unescapeMarkdownPunctuation(heading).replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\[[^\]]*\]/g, "$1").replace(/<[^>]*>/g, "").replace(/[\\`*~]/g, "").replace(/(^|[^\p{L}\p{N}])_+(?=\S)/gu, "$1").replace(/_+(?=\s|$)/g, "");
65384
- }
65385
- function toFailure(root, file2, occurrence, reason, target) {
65386
- return {
65387
- file: toProjectDisplayPath(root, file2),
65388
- range: {
65389
- start: { line: occurrence.range.start.line, column: occurrence.range.start.column },
65390
- end: { line: occurrence.range.end.line, column: occurrence.range.end.column }
65391
- },
65392
- raw: occurrence.raw,
65393
- reason,
65394
- ...target ? { target: toProjectDisplayPath(root, target) } : {}
65395
- };
65396
- }
65397
- function compareFailures(left, right) {
65398
- const fileOrder = left.file.localeCompare(right.file);
65399
- if (fileOrder)
65400
- return fileOrder;
65401
- const lineOrder = left.range.start.line - right.range.start.line;
65402
- if (lineOrder)
65403
- return lineOrder;
65404
- return left.range.start.column - right.range.start.column;
65405
- }
65406
- var URI_SCHEME, WINDOWS_ABSOLUTE_PATH;
65407
- var init_check = __esm({
65408
- "dist/documentLinks/check.js"() {
65409
- "use strict";
65410
- init_markdown2();
65411
- init_languages();
65412
- init_paths();
65413
- init_projectFiles();
65414
- URI_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/;
65415
- WINDOWS_ABSOLUTE_PATH = /^[A-Za-z]:[\\/]/;
65416
- }
65417
- });
65418
-
65419
- // dist/indexer/load-current-index.js
65420
- var load_current_index_exports = {};
65421
- __export(load_current_index_exports, {
65422
- createCurrentProjectIndexLoader: () => createCurrentProjectIndexLoader,
65423
- currentProjectIndexBuildOptions: () => currentProjectIndexBuildOptions,
65424
- loadCurrentProjectIndex: () => loadCurrentProjectIndex
65425
- });
65426
- function currentProjectIndexBuildOptions(scope, options) {
65427
- const buildOptions = { ...options };
65428
- for (const key of NON_CURRENT_STATE_OPTION_KEYS) {
65429
- delete buildOptions[key];
65430
- }
65431
- buildOptions.cache = options?.cache ?? "disk";
65432
- if (scope.kind === "resolved-files") {
65433
- buildOptions.files = [...scope.files];
65434
- buildOptions.filesAreProjectScope = true;
65435
- return buildOptions;
65436
- }
65437
- if (scope.additionalFiles?.length) {
65438
- buildOptions.additionalFiles = [...scope.additionalFiles];
65439
- }
65440
- return buildOptions;
65441
- }
65442
- async function loadCurrentProjectIndex(request) {
65443
- const { buildProjectIndexIncremental: buildProjectIndexIncremental2 } = await Promise.resolve().then(() => (init_build_index(), build_index_exports));
65444
- return await buildProjectIndexIncremental2(request.root, currentProjectIndexBuildOptions(request.scope, request.options));
65445
- }
65446
- function createCurrentProjectIndexLoader(root, options, scope = { kind: "project" }) {
65447
- return async () => await loadCurrentProjectIndex({ root, scope, ...options ? { options } : {} });
65448
- }
65449
- var NON_CURRENT_STATE_OPTION_KEYS;
65450
- var init_load_current_index = __esm({
65451
- "dist/indexer/load-current-index.js"() {
65452
- "use strict";
65453
- NON_CURRENT_STATE_OPTION_KEYS = [
65454
- "files",
65455
- "additionalFiles",
65456
- "filesAreProjectScope",
65457
- "gitBase",
65458
- "gitHead",
65459
- "changedSince",
65460
- "reconciledManifestUpdatedAt",
65461
- "reconciledWorkingTreeDiffFiles",
65462
- "reconciledUntrackedFiles"
65463
- ];
65464
- }
65465
- });
65466
-
65467
- // dist/indexer/navigation-provenance.js
65468
- function getNavigationBackend(index) {
65469
- if (index.nativeMode === "on") {
65470
- return "native";
65471
- }
65472
- if (index.nativeMode === "off") {
65473
- return "graph-only";
65474
- }
65475
- return void 0;
65476
- }
65477
- function createNavigationProvenance(index, resolution, confidence) {
65478
- const backend = getNavigationBackend(index);
65479
- return {
65480
- ...backend ? { backend } : {},
65481
- ...resolution ? { resolution } : {},
65482
- ...confidence ? { confidence } : {}
65483
- };
65484
- }
65485
- function okGoToResult(index, definition, options) {
65486
- return {
65487
- status: "ok",
65488
- definition,
65489
- ...options.via ? { via: options.via } : {},
65490
- provenance: createNavigationProvenance(index, options.resolution, options.confidence)
65491
- };
65492
- }
65493
- var init_navigation_provenance = __esm({
65494
- "dist/indexer/navigation-provenance.js"() {
65495
- "use strict";
65496
- }
65497
- });
65498
-
65499
- // dist/indexer/navigation-goto.js
65500
- async function resolveMemberAccessDefinition(params) {
65501
- const { index, mod: mod2, node, source, sup, resolveLexicalBinding } = params;
65502
- const parent = node.parent;
65503
- if (!parent || !sup.supportsCrossModuleSymbols || !isMemberAccessNode(sup, parent)) {
65504
- return null;
65505
- }
65506
- const memberNode = parent;
65507
- const { object: obj, property: prop } = getMemberAccessParts(sup, memberNode);
65508
- const optionalMemberTypes = memberAccessTraversalTypes(sup);
65509
- const resolveExpression = async (expr) => {
65510
- const exprIsId = sup.nodeTypes.identifier.includes(expr.type) && !isMemberAccessNode(sup, expr);
65511
- if (exprIsId || expr.type === "identifier" || expr.type === "type_identifier" || expr.type === "constant") {
65512
- const lexicalBinding = resolveLexicalBinding?.(expr);
65513
- if (lexicalBinding)
65514
- return { kind: "resolved", def: lexicalBinding };
65515
- const exprName = sliceText(expr, source);
65516
- const imp = mod2.imports.find((candidate) => candidate.kind === "named" && candidate.local === exprName || candidate.kind === "default" && candidate.local === exprName || candidate.kind === "namespace" && candidate.localNS === exprName);
65517
- if (imp) {
65518
- if (imp.kind === "namespace") {
65519
- return {
65520
- kind: "namespace",
65521
- file: typeof imp.resolved === "string" ? imp.resolved.replace(/\\/g, "/") : imp.resolved?.external || ""
65522
- };
65523
- }
65524
- const result = resolveImported(index, imp, imp.kind === "named" ? imp.imported : "default");
65525
- if (result) {
65526
- if ("namespace" in result) {
65527
- return { kind: "namespace", file: result.namespace };
65528
- }
65529
- return { kind: "resolved", def: result };
65530
- }
65531
- }
65532
- const local = mod2.locals.find((candidate) => candidate.localName === exprName);
65533
- if (local)
65534
- return { kind: "resolved", def: local };
65535
- for (const starImport of mod2.imports.filter((candidate) => candidate.kind === "star")) {
65536
- const result = resolveImported(index, starImport, exprName);
65537
- if (result) {
65538
- if ("namespace" in result) {
65539
- return { kind: "namespace", file: result.namespace };
65540
- }
65541
- return { kind: "resolved", def: result };
65542
- }
65543
- }
65544
- return null;
65545
- }
65546
- if (optionalMemberTypes.has(expr.type)) {
65547
- const parts = getMemberAccessParts(sup, expr);
65548
- const subObj = parts.object;
65549
- let subProp = parts.property;
65550
- if (!subProp && expr.type === "navigation_expression") {
65551
- subProp = getNavigationExpressionProperty(expr);
65552
- }
65553
- if (subObj && subProp) {
65554
- const base = await resolveExpression(subObj);
65555
- const memberName = sliceText(subProp, source);
65556
- if (base?.kind === "namespace") {
65557
- return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
65558
- }
65559
- if (base?.kind === "resolved") {
65560
- if (sup.id === "java") {
65561
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65562
- return memberDef ? { kind: "resolved", def: memberDef } : null;
65563
- }
65564
- if (sup.id === "ruby") {
65565
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65566
- if (memberDef)
65567
- return { kind: "resolved", def: memberDef };
65568
- const localHit = resolveExport(index, base.def.file, memberName);
65569
- if (localHit)
65570
- return localHit;
65571
- }
65572
- return null;
65573
- }
65574
- }
65575
- }
65576
- if (sup.id === "java" && (expr.type === "scoped_identifier" || expr.type === "scoped_type_identifier")) {
65577
- const subObj = expr.childForFieldName("scope") ?? expr.child(0);
65578
- const subProp = expr.childForFieldName("name") ?? expr.child(2);
65579
- if (subObj && subProp) {
65580
- const base = await resolveExpression(subObj);
65581
- const memberName = sliceText(subProp, source);
65582
- if (base?.kind === "namespace") {
65583
- return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
65584
- }
65585
- if (base?.kind === "resolved") {
65586
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65587
- return memberDef ? { kind: "resolved", def: memberDef } : null;
65588
- }
65589
- }
65590
- }
65591
- return null;
65592
- };
65593
- const chain = await resolveExpression(memberNode);
65594
- if (chain && prop && node.id === prop.id) {
65595
- if (chain.kind === "resolved") {
65596
- return okGoToResult(index, chain.def, {
65597
- via: { exportedName: sliceText(prop, source) },
65598
- resolution: "member-access",
65599
- confidence: "medium"
65600
- });
65601
- }
65602
- if (chain.kind === "namespace") {
65603
- const targetMod = index.byFile.get(fileIdentityKey(chain.file));
65604
- const first = targetMod?.exports.find((entry) => entry.type === "local");
65605
- if (first) {
65606
- return okGoToResult(index, first.target, {
65607
- via: { exportedName: first.exportedAs },
65608
- resolution: "namespace",
65609
- confidence: "medium"
65610
- });
65611
- }
65612
- }
65613
- }
65614
- const receiverName = obj ? sliceText(obj, source) : "";
65615
- const implicitClassReceiver = isJsTsLanguage(sup.id) && receiverName === "this" || sup.id === "php" && /^(?:\$this|self|static)$/.test(receiverName) || sup.id === "rust" && /^(?:self|Self)$/.test(receiverName);
65616
- if (obj && prop && node.id === prop.id && (supportsReceiverMemberResolution(sup.id) || implicitClassReceiver)) {
65617
- const member = sliceText(prop, source);
65618
- if (!sup.membersAreImplicitlyInScope && implicitClassReceiver) {
65619
- const classContainer = findEnclosingClassContainer(node);
65620
- const memberDef = classContainer ? findLocalWithinNode(mod2.locals, member, classContainer, sup.normalizeIdentifier) : void 0;
65621
- if (memberDef) {
65622
- return okGoToResult(index, memberDef, {
65623
- via: { exportedName: member },
65624
- resolution: "member-access",
65625
- confidence: "medium"
65626
- });
65627
- }
65628
- }
65629
- const objDef = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
65630
- if (objDef) {
65631
- const targetContext = await ensureParsedContext(objDef.file, void 0, index.languageExtensions);
65632
- const start = objDef.range.start;
65633
- const targetPosition = {
65634
- row: start.line - 1,
65635
- column: start.column - 1
65636
- };
65637
- const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
65638
- const container = nameNode.parent;
65639
- if (container) {
65640
- const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
65641
- if (targetModule) {
65642
- const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
65643
- const memberDef = targetContext.sup.id === "java" ? findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier) : findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier);
65644
- if (memberDef) {
65645
- return okGoToResult(index, memberDef, {
65646
- via: { exportedName: member },
65647
- resolution: "member-access",
65648
- confidence: "medium"
65649
- });
65650
- }
65651
- }
65652
- }
65653
- }
65654
- }
65655
- return null;
65656
- }
65657
- function findEnclosingClassContainer(node) {
65658
- let current = node.parent;
65659
- while (current) {
65660
- if (current.type === "class_declaration" || current.type === "abstract_class_declaration" || current.type === "class_definition" || current.type === "impl_item") {
65661
- return current;
65662
- }
65663
- current = current.parent;
65664
- }
65665
- return null;
65666
- }
65667
- function supportsReceiverMemberResolution(languageId) {
65668
- return languageId === "csharp" || languageId === "python" || languageId === "js" || languageId === "java" || languageId === "javascript" || languageId === "jsx" || languageId === "rust" || languageId === "ts" || languageId === "typescript" || languageId === "tsx";
65669
- }
65670
- async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
65671
- const constructor = receiverConstructorExpression(obj, source, sup);
65672
- if (constructor) {
65673
- const result = await resolveExpression(constructor);
65674
- if (result?.kind === "resolved") {
65675
- return result.def;
65676
- }
65677
- }
65678
- if (isJsTsLanguage(sup.id)) {
65679
- if (sup.nodeTypes.identifier.includes(obj.type)) {
65680
- return null;
65681
- }
65682
- }
65683
- const direct = await resolveExpression(obj);
65684
- if (direct?.kind === "resolved") {
65685
- return direct.def;
65686
- }
65687
- return null;
66302
+ failures.sort(compareFailures);
66303
+ return {
66304
+ schemaVersion: 1,
66305
+ root: normalizePath(root),
66306
+ summary: {
66307
+ filesScanned: markdownFiles.length,
66308
+ linksChecked,
66309
+ externalSkipped,
66310
+ failures: failures.length
66311
+ },
66312
+ failures
66313
+ };
65688
66314
  }
65689
- function receiverConstructorExpression(obj, source, sup) {
65690
- if (obj.type === "new_expression" || obj.type === "object_creation_expression") {
65691
- return constructorNameNode(obj, sup);
66315
+ async function recoverDisplayFileCasing(file2) {
66316
+ const dir = path64.dirname(file2);
66317
+ const base = path64.basename(file2);
66318
+ try {
66319
+ const entries = await fsp34.readdir(dir);
66320
+ const match = entries.find((entry) => entry.toLowerCase() === base.toLowerCase());
66321
+ return match ? path64.join(dir, match) : file2;
66322
+ } catch {
66323
+ return file2;
65692
66324
  }
65693
- if (sup.id === "ruby" && obj.type === "call") {
65694
- const rubyConstructor = rubyNewReceiverNameNode(obj, source, sup);
65695
- if (rubyConstructor)
65696
- return rubyConstructor;
66325
+ }
66326
+ function parseLocalLinkTarget(destination) {
66327
+ let trimmed = destination.trim();
66328
+ if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
66329
+ trimmed = trimmed.slice(1, -1).trim();
65697
66330
  }
65698
- if (!sup.nodeTypes.identifier.includes(obj.type)) {
66331
+ if (!trimmed)
65699
66332
  return null;
65700
- }
65701
- const receiverName = sliceText(obj, source);
65702
- return findVisiblePriorNewConstructor(obj, receiverName, source, sup);
66333
+ const hashIndex = trimmed.indexOf("#");
66334
+ const pathWithQuery = hashIndex >= 0 ? trimmed.slice(0, hashIndex) : trimmed;
66335
+ const queryIndex = pathWithQuery.indexOf("?");
66336
+ const targetPath = queryIndex >= 0 ? pathWithQuery.slice(0, queryIndex) : pathWithQuery;
66337
+ const fragment = hashIndex >= 0 ? decodeFragment(trimmed.slice(hashIndex + 1)) : void 0;
66338
+ return {
66339
+ path: decodeMarkdownPath(targetPath),
66340
+ ...fragment ? { fragment } : {}
66341
+ };
65703
66342
  }
65704
- function constructorNameNode(node, sup) {
65705
- const constructor = node.childForFieldName("constructor") ?? node.child(0);
65706
- if (constructor && sup.nodeTypes.identifier.includes(constructor.type)) {
65707
- return constructor;
66343
+ function decodeMarkdownPath(targetPath) {
66344
+ return decodeUriComponent(unescapeMarkdownPunctuation(targetPath));
66345
+ }
66346
+ function decodeFragment(fragment) {
66347
+ return decodeUriComponent(fragment);
66348
+ }
66349
+ function decodeUriComponent(value) {
66350
+ try {
66351
+ return decodeURIComponent(value);
66352
+ } catch {
66353
+ return value;
65708
66354
  }
65709
- for (const child of node.namedChildren) {
65710
- if (sup.nodeTypes.identifier.includes(child.type) || child.type === "type_identifier" || child.type === "constant") {
65711
- return child;
66355
+ }
66356
+ function unescapeMarkdownPunctuation(value) {
66357
+ let unescaped = "";
66358
+ for (let index = 0; index < value.length; index += 1) {
66359
+ const character = value.charAt(index);
66360
+ const escapedCharacter = value.charAt(index + 1);
66361
+ if (character === "\\" && isMarkdownPunctuation(escapedCharacter)) {
66362
+ unescaped += escapedCharacter;
66363
+ index += 1;
66364
+ continue;
65712
66365
  }
66366
+ unescaped += character;
65713
66367
  }
65714
- return null;
66368
+ return unescaped;
65715
66369
  }
65716
- function rubyNewReceiverNameNode(node, source, sup) {
65717
- if (!new RegExp(String.raw`^(?:${RUBY_CONSTANT_SOURCE})\.new$`, "u").test(sliceText(node, source)))
65718
- return null;
65719
- return node.namedChildren.find((child) => sup.nodeTypes.identifier.includes(child.type) || child.type === "constant") ?? null;
66370
+ function isMarkdownPunctuation(value) {
66371
+ const code = value.charCodeAt(0);
66372
+ return code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
65720
66373
  }
65721
- function rootOf(node) {
65722
- let current = node;
65723
- while (current.parent) {
65724
- current = current.parent;
66374
+ function resolveMarkdownTarget(root, sourceFile, destination) {
66375
+ if (!destination)
66376
+ return sourceFile;
66377
+ if (WINDOWS_ABSOLUTE_PATH.test(destination))
66378
+ return path64.resolve(destination);
66379
+ if (destination.startsWith("/"))
66380
+ return path64.join(root, destination);
66381
+ return path64.resolve(path64.dirname(sourceFile), destination);
66382
+ }
66383
+ async function cachedTargetStatus(target, targetStatusByPath) {
66384
+ let status = targetStatusByPath.get(target);
66385
+ if (!status) {
66386
+ status = readTargetStatus(target);
66387
+ targetStatusByPath.set(target, status);
65725
66388
  }
65726
- return current;
66389
+ return await status;
65727
66390
  }
65728
- function findVisiblePriorNewConstructor(receiver, receiverName, source, sup) {
65729
- let current = receiver;
65730
- while (current) {
65731
- if (BINDING_CONTAINER_TYPES.has(current.type)) {
65732
- const constructor = findPriorNewConstructorInContainer(current, receiver, receiverName, source, sup);
65733
- if (constructor || bindingContainerDeclaresNameBefore(current, receiver, receiverName, source, sup)) {
65734
- return constructor;
65735
- }
65736
- }
65737
- current = current.parent;
66391
+ async function readTargetStatus(target) {
66392
+ try {
66393
+ const realPath = await fsp34.realpath(target);
66394
+ const stats = await fsp34.stat(realPath);
66395
+ return { status: "found", isDirectory: stats.isDirectory(), realPath };
66396
+ } catch (error51) {
66397
+ if (isMissingPathError3(error51))
66398
+ return { status: "missing" };
66399
+ throw new Error(`Failed to inspect Markdown link target ${normalizePath(target)}: ${error51 instanceof Error ? error51.message : String(error51)}`);
65738
66400
  }
65739
- return findPriorNewConstructorInContainer(rootOf(receiver), receiver, receiverName, source, sup);
65740
66401
  }
65741
- function findPriorNewConstructorInContainer(node, receiver, receiverName, source, sup) {
65742
- let constructor = null;
65743
- const visit = (current) => {
65744
- if (current.startIndex >= receiver.startIndex) {
65745
- return true;
65746
- }
65747
- if (current !== node && isSkippableBindingContainer(current, receiver)) {
65748
- return true;
65749
- }
65750
- if (current.type === "variable_declarator") {
65751
- const name = current.childForFieldName("name") ?? current.child(0);
65752
- const value = current.childForFieldName("value");
65753
- if (name && value && (value.type === "new_expression" || value.type === "object_creation_expression" || sup.nodeTypes.identifier.includes(value.type)) && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
65754
- const candidate = constructorNameNode(value, sup);
65755
- if (!candidate) {
65756
- return true;
65757
- }
65758
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65759
- constructor = null;
65760
- return false;
65761
- }
65762
- constructor = candidate;
65763
- }
65764
- }
65765
- if (current.type === "assignment" || current.type === "let_declaration") {
65766
- const candidate = constructorFromAssignmentLike(current, receiverName, source, sup);
65767
- if (candidate) {
65768
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65769
- constructor = null;
65770
- return false;
65771
- }
65772
- constructor = candidate;
65773
- }
65774
- }
65775
- if (current.type === "local_variable_declaration" || current.type === "local_declaration_statement" || current.type === "variable_declaration") {
65776
- const candidate = constructorFromTypedLocalDeclaration(current, receiverName, source, sup);
65777
- if (candidate) {
65778
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65779
- constructor = null;
65780
- return false;
65781
- }
65782
- constructor = candidate;
65783
- }
65784
- }
65785
- for (const child of current.namedChildren) {
65786
- if (!visit(child)) {
65787
- return false;
65788
- }
65789
- }
65790
- return true;
65791
- };
65792
- visit(node);
65793
- return constructor;
66402
+ function isMissingPathError3(error51) {
66403
+ return error51 instanceof Error && "code" in error51 && (error51.code === "ENOENT" || error51.code === "ENOTDIR");
65794
66404
  }
65795
- function constructorFromTypedLocalDeclaration(node, receiverName, source, sup) {
65796
- if (sup.id !== "csharp" && sup.id !== "java")
65797
- return null;
65798
- const text = sliceText(node, source);
65799
- const typeNameSource = sup.id === "java" ? JAVA_CONSTANT_SOURCE : CSHARP_CONSTANT_SOURCE;
65800
- const match = text.match(new RegExp(String.raw`^\s*(${typeNameSource})\s+${escapeRegExp2(receiverName)}\s*=\s*new\s+(${typeNameSource})(?![\p{L}\p{Nl}\p{Sc}\p{Pc}\p{Nd}\p{Mn}\p{Mc}\p{Cf}])`, "u"));
65801
- const typeName = match?.[2] ?? match?.[1];
65802
- return typeName ? findNamedChildText(node, typeName, source, sup) : null;
66405
+ async function cachedMarkdownAnchors(target, anchorsByPath) {
66406
+ let anchors = anchorsByPath.get(target);
66407
+ if (!anchors) {
66408
+ anchors = readMarkdownFile(target).then(collectMarkdownAnchors);
66409
+ anchorsByPath.set(target, anchors);
66410
+ }
66411
+ return await anchors;
65803
66412
  }
65804
- function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source, sup) {
65805
- const visit = (current) => {
65806
- if (current.startIndex >= receiver.startIndex) {
65807
- return false;
65808
- }
65809
- if (current !== node && isSkippableBindingContainer(current, receiver)) {
65810
- return false;
66413
+ async function readMarkdownFile(file2) {
66414
+ try {
66415
+ return await fsp34.readFile(file2, "utf8");
66416
+ } catch (error51) {
66417
+ if (error51 instanceof Error) {
66418
+ throw new Error(`Failed to read Markdown file ${normalizePath(file2)}: ${error51.message}`);
65811
66419
  }
65812
- if (BINDING_DECLARATION_TYPES.has(current.type)) {
65813
- const name = current.childForFieldName("name") ?? current.child(0);
65814
- if (name && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
65815
- return true;
66420
+ throw error51;
66421
+ }
66422
+ }
66423
+ function collectMarkdownAnchors(source) {
66424
+ const anchors = /* @__PURE__ */ new Set();
66425
+ const lines = source.split(/\r?\n/);
66426
+ let fence = null;
66427
+ for (let index = 0; index < lines.length; index += 1) {
66428
+ const line = lines[index] ?? "";
66429
+ const fenceMatch = line.match(/^ {0,3}(`{3,}|~{3,})/);
66430
+ if (fenceMatch) {
66431
+ const marker = fenceMatch[1]?.charAt(0);
66432
+ if (marker === "`" || marker === "~") {
66433
+ fence = fence === marker ? null : fence ?? marker;
65816
66434
  }
66435
+ continue;
65817
66436
  }
65818
- for (const child of current.namedChildren) {
65819
- if (visit(child)) {
65820
- return true;
65821
- }
66437
+ if (fence || /^(?: {4}|\t)/.test(line))
66438
+ continue;
66439
+ const atx = line.match(/^ {0,3}#{1,6}[ \t]+(.+?)(?:[ \t]+#+[ \t]*)?$/);
66440
+ if (atx?.[1]) {
66441
+ addMarkdownAnchor(anchors, atx[1]);
66442
+ continue;
66443
+ }
66444
+ const underline = lines[index + 1];
66445
+ if (line.trim() && underline && /^ {0,3}(?:=+|-+)[ \t]*$/.test(underline)) {
66446
+ addMarkdownAnchor(anchors, line);
66447
+ index += 1;
65822
66448
  }
65823
- return false;
65824
- };
65825
- return visit(node);
65826
- }
65827
- function isSkippableBindingContainer(node, receiver) {
65828
- return BINDING_CONTAINER_TYPES.has(node.type) && !nodeContainsIndex(node, receiver.startIndex);
65829
- }
65830
- function nodeContainsIndex(node, index) {
65831
- return node.startIndex <= index && node.endIndex >= index;
65832
- }
65833
- function constructorFromAssignmentLike(node, receiverName, source, sup) {
65834
- const text = sliceText(node, source);
65835
- if (!new RegExp(String.raw`(?<!${IDENTIFIER_BOUNDARY_SOURCE})${escapeRegExp2(receiverName)}(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u").test(text))
65836
- return null;
65837
- if (sup.id === "ruby") {
65838
- const match = text.match(new RegExp(String.raw`^\s*${escapeRegExp2(receiverName)}\s*=\s*(${RUBY_CONSTANT_SOURCE})\.new(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
65839
- if (!match?.[1])
65840
- return null;
65841
- return findNamedChildText(node, match[1], source, sup);
65842
66449
  }
65843
- if (sup.id === "rust") {
65844
- const match = text.match(new RegExp(String.raw`^\s*(?:let\s+)?${escapeRegExp2(receiverName)}\s*=\s*(${RUST_CONSTANT_SOURCE})(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
65845
- if (!match?.[1])
65846
- return null;
65847
- return findNamedChildText(node, match[1], source, sup);
66450
+ return anchors;
66451
+ }
66452
+ function addMarkdownAnchor(anchors, heading) {
66453
+ const baseSlug = markdownHeadingSlug(heading);
66454
+ if (!baseSlug)
66455
+ return;
66456
+ let slug = baseSlug;
66457
+ let suffix = 1;
66458
+ while (anchors.has(slug)) {
66459
+ slug = `${baseSlug}-${suffix}`;
66460
+ suffix += 1;
65848
66461
  }
65849
- return null;
66462
+ anchors.add(slug);
65850
66463
  }
65851
- function findNamedChildText(node, name, source, sup) {
65852
- const isNameNode = (candidate) => (sup.nodeTypes.identifier.includes(candidate.type) || candidate.type === "type_identifier" || candidate.type === "constant") && sliceText(candidate, source) === name;
65853
- const visit = (current) => {
65854
- if (isNameNode(current))
65855
- return current;
65856
- for (const child of current.namedChildren) {
65857
- const hit = visit(child);
65858
- if (hit)
65859
- return hit;
65860
- }
65861
- return null;
65862
- };
65863
- return visit(node);
66464
+ function markdownHeadingSlug(heading) {
66465
+ return renderMarkdownHeading(heading).trim().toLowerCase().replace(/[^\p{L}\p{N}_\-\s]/gu, "").replace(/\s+/g, "-");
65864
66466
  }
65865
- async function resolveMemberDefinitionForBase(index, baseDef, member) {
65866
- const targetContext = await ensureParsedContext(baseDef.file, void 0, index.languageExtensions);
65867
- const start = baseDef.range.start;
65868
- const targetPosition = {
65869
- row: start.line - 1,
65870
- column: start.column - 1
65871
- };
65872
- const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
65873
- const container = nameNode.parent;
65874
- if (!container)
65875
- return void 0;
65876
- const targetModule = index.byFile.get(fileIdentityKey(baseDef.file));
65877
- if (!targetModule)
65878
- return void 0;
65879
- const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
65880
- const directHit = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
65881
- if (directHit)
65882
- return directHit;
65883
- if (targetContext.sup.id === "java")
65884
- return void 0;
65885
- return findReceiverMemberDefinition(targetModule.locals, member, baseDef, container, targetContext, normalizeIdentifier);
66467
+ function renderMarkdownHeading(heading) {
66468
+ return unescapeMarkdownPunctuation(heading).replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\[[^\]]*\]/g, "$1").replace(/<[^>]*>/g, "").replace(/[\\`*~]/g, "").replace(/(^|[^\p{L}\p{N}])_+(?=\S)/gu, "$1").replace(/_+(?=\s|$)/g, "");
65886
66469
  }
65887
- function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier) {
65888
- const containerHit = findLocalWithinNode(locals, member, container, normalizeIdentifier);
65889
- if (containerHit)
65890
- return containerHit;
65891
- if (targetContext.sup.id !== "rust")
65892
- return void 0;
65893
- const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
65894
- return implNode ? findLocalWithinNode(locals, member, implNode, normalizeIdentifier) : void 0;
66470
+ function toFailure(root, file2, occurrence, reason, target) {
66471
+ return {
66472
+ file: toProjectDisplayPath(root, file2),
66473
+ range: {
66474
+ start: { line: occurrence.range.start.line, column: occurrence.range.start.column },
66475
+ end: { line: occurrence.range.end.line, column: occurrence.range.end.column }
66476
+ },
66477
+ raw: occurrence.raw,
66478
+ reason,
66479
+ ...target ? { target: toProjectDisplayPath(root, target) } : {}
66480
+ };
65895
66481
  }
65896
- function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name) {
65897
- const containerStart = node.startIndex;
65898
- const containerEnd = node.endIndex;
65899
- const normalizedMember = normalizeIdentifier(member);
65900
- return locals.find((local) => {
65901
- const startIndex = local.range.start.index;
65902
- const endIndex = local.range.end.index;
65903
- return normalizeIdentifier(local.localName) === normalizedMember && startIndex !== void 0 && endIndex !== void 0 && startIndex >= containerStart && endIndex <= containerEnd;
65904
- });
66482
+ function compareFailures(left, right) {
66483
+ const fileOrder = left.file.localeCompare(right.file);
66484
+ if (fileOrder)
66485
+ return fileOrder;
66486
+ const lineOrder = left.range.start.line - right.range.start.line;
66487
+ if (lineOrder)
66488
+ return lineOrder;
66489
+ return left.range.start.column - right.range.start.column;
65905
66490
  }
65906
- function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier) {
65907
- const containerStart = container.startIndex;
65908
- const containerEnd = container.endIndex;
65909
- const normalizedMember = normalizeIdentifier(member);
65910
- for (const local of locals) {
65911
- const startIndex = local.range.start.index;
65912
- const endIndex = local.range.end.index;
65913
- if (normalizeIdentifier(local.localName) !== normalizedMember || startIndex === void 0 || endIndex === void 0 || startIndex < containerStart || endIndex > containerEnd) {
65914
- continue;
65915
- }
65916
- const start = local.range.start;
65917
- const position = {
65918
- row: start.line - 1,
65919
- column: start.column - 1
65920
- };
65921
- let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
65922
- let isDeclarationParent = true;
65923
- while (current && current !== container) {
65924
- if (!isDeclarationParent && (current.type === "class_body" && current.parent !== container || NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
65925
- current = null;
65926
- break;
65927
- }
65928
- isDeclarationParent = false;
65929
- current = current.parent;
65930
- }
65931
- if (current)
65932
- return local;
66491
+ var URI_SCHEME, WINDOWS_ABSOLUTE_PATH;
66492
+ var init_check = __esm({
66493
+ "dist/documentLinks/check.js"() {
66494
+ "use strict";
66495
+ init_markdown2();
66496
+ init_languages();
66497
+ init_paths();
66498
+ init_projectFiles();
66499
+ URI_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/;
66500
+ WINDOWS_ABSOLUTE_PATH = /^[A-Za-z]:[\\/]/;
65933
66501
  }
65934
- return void 0;
66502
+ });
66503
+
66504
+ // dist/indexer/load-current-index.js
66505
+ var load_current_index_exports = {};
66506
+ __export(load_current_index_exports, {
66507
+ createCurrentProjectIndexLoader: () => createCurrentProjectIndexLoader,
66508
+ currentProjectIndexBuildOptions: () => currentProjectIndexBuildOptions,
66509
+ loadCurrentProjectIndex: () => loadCurrentProjectIndex
66510
+ });
66511
+ function currentProjectIndexBuildOptions(scope, options) {
66512
+ const buildOptions = { ...options };
66513
+ for (const key of NON_CURRENT_STATE_OPTION_KEYS) {
66514
+ delete buildOptions[key];
66515
+ }
66516
+ buildOptions.cache = options?.cache ?? "disk";
66517
+ if (scope.kind === "resolved-files") {
66518
+ buildOptions.files = [...scope.files];
66519
+ buildOptions.filesAreProjectScope = true;
66520
+ return buildOptions;
66521
+ }
66522
+ if (scope.additionalFiles?.length) {
66523
+ buildOptions.additionalFiles = [...scope.additionalFiles];
66524
+ }
66525
+ return buildOptions;
65935
66526
  }
65936
- function findRustImplForType(root, typeName, source) {
65937
- let found = null;
65938
- const visit = (node) => {
65939
- if (node.type === "impl_item") {
65940
- const text = sliceText(node, source);
65941
- if (new RegExp(`^\\s*impl\\s+${escapeRegExp2(typeName)}\\b`).test(text)) {
65942
- found = node;
65943
- return false;
65944
- }
65945
- }
65946
- for (const child of node.namedChildren) {
65947
- if (!visit(child))
65948
- return false;
65949
- }
65950
- return true;
65951
- };
65952
- visit(root);
65953
- return found;
66527
+ async function loadCurrentProjectIndex(request) {
66528
+ const { buildProjectIndexIncremental: buildProjectIndexIncremental2 } = await Promise.resolve().then(() => (init_build_index(), build_index_exports));
66529
+ return await buildProjectIndexIncremental2(request.root, currentProjectIndexBuildOptions(request.scope, request.options));
65954
66530
  }
65955
- function escapeRegExp2(value) {
65956
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
66531
+ function createCurrentProjectIndexLoader(root, options, scope = { kind: "project" }) {
66532
+ return async () => await loadCurrentProjectIndex({ root, scope, ...options ? { options } : {} });
65957
66533
  }
65958
- var RUBY_CONSTANT_SOURCE, CSHARP_CONSTANT_SOURCE, JAVA_CONSTANT_SOURCE, RUST_CONSTANT_SOURCE, IDENTIFIER_BOUNDARY_SOURCE, BINDING_CONTAINER_TYPES, BINDING_DECLARATION_TYPES, NESTED_MEMBER_LOCAL_CONTAINERS;
65959
- var init_navigation_goto = __esm({
65960
- "dist/indexer/navigation-goto.js"() {
66534
+ var NON_CURRENT_STATE_OPTION_KEYS;
66535
+ var init_load_current_index = __esm({
66536
+ "dist/indexer/load-current-index.js"() {
65961
66537
  "use strict";
65962
- init_js_family();
65963
- init_ast();
65964
- init_paths();
65965
- init_memberAccess();
65966
- init_identifiers();
65967
- init_parse_context();
65968
- init_navigation_provenance();
65969
- init_navigation_resolve();
65970
- RUBY_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
65971
- CSHARP_CONSTANT_SOURCE = String.raw`(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
65972
- JAVA_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
65973
- RUST_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
65974
- IDENTIFIER_BOUNDARY_SOURCE = String.raw`[$_\p{ID_Continue}\u200c\u200d]`;
65975
- BINDING_CONTAINER_TYPES = /* @__PURE__ */ new Set([
65976
- "program",
65977
- "compilation_unit",
65978
- "source_file",
65979
- "statement_block",
65980
- "block",
65981
- "function_declaration",
65982
- "function_item",
65983
- "function",
65984
- "function_expression",
65985
- "arrow_function",
65986
- "method_definition",
65987
- "method_declaration",
65988
- "method"
65989
- ]);
65990
- BINDING_DECLARATION_TYPES = /* @__PURE__ */ new Set([
65991
- "variable_declarator",
65992
- "let_declaration",
65993
- "assignment",
65994
- "formal_parameter",
65995
- "required_parameter",
65996
- "optional_parameter"
65997
- ]);
65998
- NESTED_MEMBER_LOCAL_CONTAINERS = /* @__PURE__ */ new Set([
65999
- "block",
66000
- "class",
66001
- "class_declaration",
66002
- "class_definition",
66003
- "constructor_declaration",
66004
- "enum_declaration",
66005
- "enum_item",
66006
- "enum_specifier",
66007
- "function_declaration",
66008
- "function_definition",
66009
- "function_item",
66010
- "interface_declaration",
66011
- "method",
66012
- "method_declaration",
66013
- "method_definition",
66014
- "module",
66015
- "statement_block"
66016
- ]);
66538
+ NON_CURRENT_STATE_OPTION_KEYS = [
66539
+ "files",
66540
+ "additionalFiles",
66541
+ "filesAreProjectScope",
66542
+ "gitBase",
66543
+ "gitHead",
66544
+ "changedSince",
66545
+ "reconciledManifestUpdatedAt",
66546
+ "reconciledWorkingTreeDiffFiles",
66547
+ "reconciledUntrackedFiles"
66548
+ ];
66017
66549
  }
66018
66550
  });
66019
66551