@lzehrung/codegraph 2.3.18 → 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 (28) hide show
  1. package/codegraph-skill/codegraph/SKILL.md +2 -0
  2. package/dist/bin/cli.js +1606 -1128
  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/options.d.ts +7 -1
  18. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  19. package/dist/indexer/build-cache/options.js +7 -1
  20. package/dist/indexer/build-cache/options.js.map +1 -1
  21. package/dist/indexer/navigation-goto.d.ts +6 -0
  22. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  23. package/dist/indexer/navigation-goto.js +6 -1
  24. package/dist/indexer/navigation-goto.js.map +1 -1
  25. package/dist/util/memberAccess.d.ts.map +1 -1
  26. package/dist/util/memberAccess.js +12 -2
  27. package/dist/util/memberAccess.js.map +1 -1
  28. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -32938,7 +32938,7 @@ var init_options2 = __esm({
32938
32938
  init_projectFiles();
32939
32939
  init_treeSitterNative();
32940
32940
  init_languages();
32941
- CORE_ALGORITHM_EPOCH = 2;
32941
+ CORE_ALGORITHM_EPOCH = 3;
32942
32942
  LANGUAGE_BEHAVIOR_EPOCH = 1;
32943
32943
  }
32944
32944
  });
@@ -57700,7 +57700,7 @@ function memberAccessTraversalTypes(sup) {
57700
57700
  }
57701
57701
  function isMemberAccessNode(sup, node) {
57702
57702
  const memberExpressionType = memberExpressionTypeFor(sup);
57703
- 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";
57704
57704
  }
57705
57705
  function isMemberObjectIdentifier(nodeType) {
57706
57706
  return nodeType === "identifier" || nodeType === "type_identifier" || nodeType === "package_identifier" || nodeType === "constant" || nodeType === "namespace_identifier";
@@ -57721,6 +57721,12 @@ function fieldParts(node, objectField, propertyField) {
57721
57721
  };
57722
57722
  }
57723
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
+ }
57724
57730
  if (sup.id === "python") {
57725
57731
  return fieldParts(memberNode, "object", "attribute");
57726
57732
  }
@@ -57745,7 +57751,7 @@ function getMemberAccessParts(sup, memberNode) {
57745
57751
  return fieldParts(memberNode, "receiver", "method");
57746
57752
  }
57747
57753
  if (sup.id === "php") {
57748
- if (memberNode.type === "member_call_expression") {
57754
+ if (memberNode.type === "member_call_expression" || memberNode.type === "nullsafe_member_call_expression") {
57749
57755
  return fieldParts(memberNode, "object", "name");
57750
57756
  }
57751
57757
  if (memberNode.type === "scoped_call_expression") {
@@ -57824,6 +57830,23 @@ var init_memberAccess = __esm({
57824
57830
  });
57825
57831
 
57826
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
+ }
57827
57850
  function collectDetailedDeclarations(rootNode, sup, source, locals) {
57828
57851
  const functionNodes = [];
57829
57852
  const classNodes = [];
@@ -57841,6 +57864,7 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57841
57864
  "function_item",
57842
57865
  "function_signature_item",
57843
57866
  "method",
57867
+ "protocol_function_declaration",
57844
57868
  "singleton_method"
57845
57869
  ]);
57846
57870
  const typeNodeTypes = /* @__PURE__ */ new Set([
@@ -57850,8 +57874,10 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57850
57874
  "class_definition",
57851
57875
  "class",
57852
57876
  "interface_declaration",
57877
+ "module",
57853
57878
  "protocol_declaration",
57854
57879
  "trait_item",
57880
+ "trait_declaration",
57855
57881
  "struct_item",
57856
57882
  "struct_declaration",
57857
57883
  "class_specifier",
@@ -57871,7 +57897,7 @@ function collectDetailedDeclarations(rootNode, sup, source, locals) {
57871
57897
  };
57872
57898
  const walk = (node) => {
57873
57899
  if (functionNodeTypes.has(node.type)) {
57874
- const nameNode = node.childForFieldName("name") ?? node.childForFieldName("type");
57900
+ const nameNode = functionNameNode(node);
57875
57901
  const name = nameNode ? sliceText(nameNode, source) : void 0;
57876
57902
  if (name) {
57877
57903
  const def = findDefinition(name, nameNode);
@@ -57976,389 +58002,1375 @@ var init_ast2 = __esm({
57976
58002
  }
57977
58003
  });
57978
58004
 
57979
- // dist/graphs/symbol-graph-detailed/edgePasses.js
57980
- function ensureNode(context, def) {
57981
- const id = defNodeId(def);
57982
- if (!context.nodes.has(id))
57983
- context.nodes.set(id, nodeForDef(def));
57984
- return id;
57985
- }
57986
- function markImplementationTarget(context, id, declarationNode, def) {
57987
- const declaration = sliceText(declarationNode, context.source);
57988
- const nameIndex = declaration.indexOf(def.localName);
57989
- const prefix = nameIndex >= 0 ? declaration.slice(0, nameIndex) : declaration;
57990
- if (!/\b(?:abstract|virtual|override)\b/.test(prefix))
57991
- return;
57992
- const node = context.nodes.get(id);
57993
- if (node)
57994
- node.implementationTarget = true;
57995
- }
57996
- function markMemberArity(context, id, declarationNode) {
57997
- let parameters = declarationNode.childForFieldName("parameters");
57998
- if (!parameters) {
57999
- for (const type of [
58000
- "formal_parameters",
58001
- "parameter_list",
58002
- "parameters",
58003
- "method_parameters",
58004
- "function_parameter_clause"
58005
- ]) {
58006
- parameters = findFirstNodeByType(declarationNode, type);
58007
- if (parameters)
58008
- break;
58009
- }
58005
+ // dist/indexer/navigation-provenance.js
58006
+ function getNavigationBackend(index) {
58007
+ if (index.nativeMode === "on") {
58008
+ return "native";
58010
58009
  }
58011
- if (!parameters)
58012
- return;
58013
- const arity = (parameters.namedChildren ?? []).filter((child) => child.type !== "comment").length;
58014
- const node = context.nodes.get(id);
58015
- if (node)
58016
- node.memberArity = arity;
58010
+ if (index.nativeMode === "off") {
58011
+ return "graph-only";
58012
+ }
58013
+ return void 0;
58017
58014
  }
58018
- function recordDefEdge(context, fromId, target, label, siteNode) {
58019
- const toId = ensureNode(context, target);
58020
- 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
+ };
58021
58022
  }
58022
- function tryResolveChain(context, node, fromId, label = "uses") {
58023
- const targetDef = context.resolveMemberChainTarget(node);
58024
- if (targetDef && fromId) {
58025
- recordDefEdge(context, fromId, targetDef, label, node);
58026
- return true;
58027
- }
58028
- 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
+ };
58029
58030
  }
58030
- function tryResolveNode(context, node, fromId, label) {
58031
- if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
58032
- const name = sliceText(node, context.source);
58033
- const target = context.resolveIdentifier(name);
58034
- if (target) {
58035
- recordDefEdge(context, fromId, target, label, node);
58036
- return;
58037
- }
58031
+ var init_navigation_provenance = __esm({
58032
+ "dist/indexer/navigation-provenance.js"() {
58033
+ "use strict";
58038
58034
  }
58039
- if (context.optionalMemberTypes.has(node.type)) {
58040
- 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;
58041
58043
  }
58042
- }
58043
- function getCallTarget(node) {
58044
- const explicitTarget = node.childForFieldName("function") ?? node.childForFieldName("callee") ?? node.childForFieldName("name") ?? node.childForFieldName("method") ?? node.childForFieldName("member") ?? node.childForFieldName("expression");
58045
- if (explicitTarget)
58046
- return explicitTarget;
58047
- const nonArgumentChildren = node.namedChildren.filter((child) => child.type !== "argument_list");
58048
- return nonArgumentChildren.length === 1 ? nonArgumentChildren[0] ?? null : null;
58049
- }
58050
- function getNewTarget(node) {
58051
- return node.childForFieldName("constructor") ?? node.childForFieldName("type") ?? node.childForFieldName("name") ?? node.namedChildren.find((child) => child.type === "type_identifier") ?? node.child(0);
58052
- }
58053
- function emitPythonDecoratorEdges(context, rootNode) {
58054
- if (context.sup.id !== "python")
58055
- return;
58056
- const addDecoratorUses = (node) => {
58057
- if (node.type === "decorated_definition") {
58058
- const fn = node.namedChildren.find((child) => child.type === "function_definition");
58059
- if (fn)
58060
- addDecoratorUses(fn);
58061
- for (const decoratorChild of node.namedChildren) {
58062
- if (decoratorChild.type !== "decorator")
58063
- continue;
58064
- const nameNode = fn?.childForFieldName("name");
58065
- if (!nameNode)
58066
- continue;
58067
- const name = sliceText(nameNode, context.source);
58068
- const def = context.moduleEntry.locals.find((local) => local.localName === name);
58069
- if (!def)
58070
- continue;
58071
- const fromId = ensureNode(context, def);
58072
- const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
58073
- if (expr)
58074
- tryResolveNode(context, expr, fromId, "decorates");
58075
- }
58076
- } else if (node.type === "function_definition") {
58077
- const nameNode = node.childForFieldName("name");
58078
- if (nameNode) {
58079
- const name = sliceText(nameNode, context.source);
58080
- const def = context.moduleEntry.locals.find((local) => local.localName === name);
58081
- if (def) {
58082
- const fromId = ensureNode(context, def);
58083
- let prev = node.previousSibling;
58084
- while (prev) {
58085
- if (prev.type === "decorated_definition") {
58086
- for (const decoratorChild of prev.namedChildren) {
58087
- if (decoratorChild.type === "decorator") {
58088
- const expr = decoratorChild.childForFieldName?.("name") ?? decoratorChild.namedChildren?.[0] ?? decoratorChild.child(1);
58089
- if (expr)
58090
- tryResolveNode(context, expr, fromId, "decorates");
58091
- } else if (decoratorChild.type === "attribute") {
58092
- tryResolveNode(context, decoratorChild, fromId, "decorates");
58093
- }
58094
- }
58095
- } else if (prev.type === "decorator") {
58096
- const expr = prev.childForFieldName?.("name") ?? prev.namedChildren?.[0] ?? prev.child(1);
58097
- if (expr)
58098
- tryResolveNode(context, expr, fromId, "decorates");
58099
- }
58100
- 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 };
58101
58066
  }
58067
+ return { kind: "resolved", def: result };
58102
58068
  }
58103
58069
  }
58104
- }
58105
- for (const child of node.namedChildren)
58106
- addDecoratorUses(child);
58107
- };
58108
- addDecoratorUses(rootNode);
58109
- }
58110
- function emitMemberOwnershipEdges(context, functionNodes, classNodes) {
58111
- for (const fn of functionNodes) {
58112
- 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));
58113
- const owner = owners[0];
58114
- if (!owner)
58115
- continue;
58116
- const memberId = ensureNode(context, fn.def);
58117
- markImplementationTarget(context, memberId, fn.node, fn.def);
58118
- markMemberArity(context, memberId, fn.node);
58119
- recordDefEdge(context, memberId, owner.def, "member_of");
58120
- }
58121
- }
58122
- function emitFunctionBodyEdges(context, functionNodes) {
58123
- const callNodeTypes = /* @__PURE__ */ new Set(["call_expression", "call", "method_invocation", "invocation_expression"]);
58124
- const newNodeTypes = /* @__PURE__ */ new Set([
58125
- "new_expression",
58126
- "object_creation_expression",
58127
- "struct_expression",
58128
- "composite_literal"
58129
- ]);
58130
- for (const fn of functionNodes) {
58131
- const fromId = ensureNode(context, fn.def);
58132
- const seenAliases = /* @__PURE__ */ new Set();
58133
- 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));
58134
- const recordAliasUse = (node) => {
58135
- if (context.membersOnly || !isIdentifierType(context.sup, node.type))
58136
- return;
58137
- const name = sliceText(node, context.source);
58138
- if (seenAliases.has(name))
58139
- return;
58140
- let target = context.aliasToTargetDef.get(name) ?? null;
58141
- if (!target) {
58142
- const modFile = context.aliasToTargetModule.get(name);
58143
- if (modFile) {
58144
- let exportedName = null;
58145
- const parent = node.parent;
58146
- if (parent && (parent.type === context.memberExpressionType || parent.type === "optional_member_expression")) {
58147
- const { property: prop } = getMemberAccessParts(context.sup, parent);
58148
- if (prop && context.propertyIdentifierTypes.includes(prop.type)) {
58149
- exportedName = sliceText(prop, context.source);
58150
- }
58151
- }
58152
- if (exportedName) {
58153
- target = context.resolveExportFrom(modFile, exportedName);
58154
- if (!target) {
58155
- const targetModule = context.index.byFile.get(fileIdentityKey(modFile));
58156
- target = (targetModule?.locals ?? []).find((local) => local.localName === exportedName) ?? null;
58157
- }
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 };
58158
58078
  }
58079
+ return { kind: "resolved", def: result };
58159
58080
  }
58160
58081
  }
58161
- if (!target)
58162
- return;
58163
- seenAliases.add(name);
58164
- recordDefEdge(context, fromId, target, "uses");
58165
- };
58166
- const recordMemberUse = (node) => {
58167
- if (!context.optionalMemberTypes.has(node.type))
58168
- return;
58169
- const targetDef = context.resolveMemberChainTarget(node);
58170
- if (targetDef) {
58171
- 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);
58172
58090
  }
58173
- };
58174
- const recordCallOrInstantiation = (node) => {
58175
- if (callNodeTypes.has(node.type)) {
58176
- if (context.sup.id === "go") {
58177
- const callTarget = getCallTarget(node);
58178
- const calleeName = callTarget && isIdentifierType(context.sup, callTarget.type) ? sliceText(callTarget, context.source) : null;
58179
- if (calleeName === "new" || calleeName === "make") {
58180
- const argList = node.childForFieldName("arguments") ?? node.childForFieldName("argument_list");
58181
- const typeNode = argList?.namedChildren?.find((child) => child.type === "type_identifier") ?? null;
58182
- if (typeNode) {
58183
- tryResolveNode(context, typeNode, fromId, "instantiates");
58184
- }
58185
- return false;
58186
- }
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 });
58187
58096
  }
58188
- if (context.sup.id === "ruby" && node.type === "call") {
58189
- const methodNode = node.childForFieldName("method");
58190
- const receiverNode = node.childForFieldName("receiver");
58191
- const methodName = methodNode ? sliceText(methodNode, context.source) : null;
58192
- if (methodName === "new" && receiverNode) {
58193
- tryResolveNode(context, receiverNode, fromId, "instantiates");
58194
- 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;
58195
58101
  }
58196
- if (methodNode) {
58197
- tryResolveNode(context, methodNode, fromId, "calls");
58198
- 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;
58199
58109
  }
58110
+ return null;
58200
58111
  }
58201
- const callee = getCallTarget(node);
58202
- if (callee)
58203
- tryResolveNode(context, callee, fromId, "calls");
58204
- }
58205
- if (newNodeTypes.has(node.type)) {
58206
- const target = getNewTarget(node);
58207
- if (target)
58208
- tryResolveNode(context, target, fromId, "instantiates");
58209
58112
  }
58210
- return true;
58211
- };
58212
- const walkFunctionBody = (node, allowCallProcessing) => {
58213
- if (node !== fn.node && nestedFunctions.has(node))
58214
- return;
58215
- recordAliasUse(node);
58216
- recordMemberUse(node);
58217
- const allowChildCallProcessing = allowCallProcessing ? recordCallOrInstantiation(node) : false;
58218
- for (const child of node.namedChildren ?? [])
58219
- walkFunctionBody(child, allowChildCallProcessing);
58220
- };
58221
- walkFunctionBody(fn.node, true);
58222
- }
58223
- }
58224
- function recordIdentifierRelations(context, fromId, container, relationForTarget) {
58225
- const identifiers = [];
58226
- const collect = (node) => {
58227
- if (isIdentifierType(context.sup, node.type) || node.type === "type_identifier") {
58228
- identifiers.push(node);
58229
- return;
58230
58113
  }
58231
- for (const child of node.namedChildren ?? [])
58232
- collect(child);
58233
- };
58234
- collect(container);
58235
- const seen = /* @__PURE__ */ new Set();
58236
- for (const [index, identifier] of identifiers.entries()) {
58237
- const target = context.resolveIdentifier(sliceText(identifier, context.source));
58238
- if (!target)
58239
- continue;
58240
- const targetId = defNodeId(target);
58241
- if (seen.has(targetId))
58242
- continue;
58243
- seen.add(targetId);
58244
- recordDefEdge(context, fromId, target, relationForTarget(target, index), identifier);
58245
- }
58246
- }
58247
- function collectDirectCallsExcludingNestedScopes(node, out) {
58248
- for (const child of node.namedChildren ?? []) {
58249
- if (child.type === "call")
58250
- out.push(child);
58251
- if (RUBY_NESTED_SCOPE_TYPES.has(child.type))
58252
- continue;
58253
- collectDirectCallsExcludingNestedScopes(child, out);
58254
- }
58255
- }
58256
- function emitClassInheritanceEdges(context, classNodes) {
58257
- 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)));
58258
- for (const cls of classNodes) {
58259
- const fromId = ensureNode(context, cls.def);
58260
- markImplementationTarget(context, fromId, cls.node, cls.def);
58261
- if (context.sup.id === "java") {
58262
- const superClass = findFirstNodeByType(cls.node, "superclass");
58263
- const superNode2 = superClass?.childForFieldName("name") ?? superClass?.namedChildren?.[0] ?? null;
58264
- if (superNode2)
58265
- tryResolveNode(context, superNode2, fromId, "extends");
58266
- const interfaces = findFirstNodeByType(cls.node, "super_interfaces");
58267
- if (interfaces) {
58268
- const names = [];
58269
- collectIdentifiers(interfaces, context.sup, context.source, names);
58270
- for (const name of names) {
58271
- const target = context.resolveIdentifier(name);
58272
- if (target)
58273
- 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;
58274
58126
  }
58275
58127
  }
58276
- continue;
58277
- }
58278
- if (context.sup.id === "csharp") {
58279
- const baseList = findFirstNodeByType(cls.node, "base_list");
58280
- if (baseList) {
58281
- recordIdentifierRelations(context, fromId, baseList, (target, index) => interfaceIds.has(defNodeId(target)) || index > 0 ? "implements" : "extends");
58282
- }
58283
- continue;
58284
- }
58285
- if (context.sup.id === "python") {
58286
- const bases = cls.node.childForFieldName("superclasses") ?? findFirstNodeByType(cls.node, "argument_list");
58287
- if (bases)
58288
- recordIdentifierRelations(context, fromId, bases, () => "extends");
58289
- continue;
58290
- }
58291
- if (context.sup.id === "php") {
58292
- const base = findFirstNodeByType(cls.node, "base_clause");
58293
- if (base)
58294
- recordIdentifierRelations(context, fromId, base, () => "extends");
58295
- const interfaces = findFirstNodeByType(cls.node, "class_interface_clause");
58296
- if (interfaces)
58297
- recordIdentifierRelations(context, fromId, interfaces, () => "implements");
58298
- const traitUses = [];
58299
- collectNodesByType(cls.node, "use_declaration", traitUses);
58300
- for (const traitUse of traitUses)
58301
- recordIdentifierRelations(context, fromId, traitUse, () => "trait");
58302
- continue;
58303
- }
58304
- if (context.sup.id === "ruby") {
58305
- const superclass = findFirstNodeByType(cls.node, "superclass");
58306
- if (superclass)
58307
- recordIdentifierRelations(context, fromId, superclass, () => "extends");
58308
- const calls = [];
58309
- collectDirectCallsExcludingNestedScopes(cls.node, calls);
58310
- for (const call of calls) {
58311
- if (call.childForFieldName("receiver"))
58312
- continue;
58313
- const methodNode = call.childForFieldName("method");
58314
- const methodName = methodNode ? sliceText(methodNode, context.source) : void 0;
58315
- if (methodName !== "include" && methodName !== "extend" && methodName !== "prepend")
58316
- continue;
58317
- const args = call.childForFieldName("arguments");
58318
- if (args)
58319
- recordIdentifierRelations(context, fromId, args, () => "mixin");
58320
- }
58321
- continue;
58322
58128
  }
58323
- if (context.sup.id === "cpp") {
58324
- const bases = findFirstNodeByType(cls.node, "base_class_clause");
58325
- if (bases)
58326
- recordIdentifierRelations(context, fromId, bases, () => "extends");
58327
- 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
+ });
58328
58139
  }
58329
- if (context.sup.id === "kotlin") {
58330
- const bases = findFirstNodeByType(cls.node, "delegation_specifiers");
58331
- if (bases) {
58332
- 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
+ });
58333
58149
  }
58334
- continue;
58335
58150
  }
58336
- if (context.sup.id === "swift") {
58337
- const bases = [];
58338
- collectNodesByType(cls.node, "inheritance_specifier", bases);
58339
- for (const [index, base] of bases.entries()) {
58340
- 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
+ });
58341
58165
  }
58342
- continue;
58343
58166
  }
58344
- const superClause = findFirstNodeByType(cls.node, "extends_clause");
58345
- const superNode = superClause?.namedChildren?.[0] ?? superClause?.child(1);
58346
- if (superNode)
58347
- tryResolveNode(context, superNode, fromId, "extends");
58348
- const implementsClauses = [];
58349
- collectNodesByType(cls.node, "implements_clause", implementsClauses);
58350
- for (const clause of implementsClauses) {
58351
- const names = [];
58352
- collectIdentifiers(clause, context.sup, context.source, names);
58353
- for (const name of names) {
58354
- const target = context.resolveIdentifier(name);
58355
- if (target)
58356
- 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
+ }
58357
58190
  }
58358
58191
  }
58359
58192
  }
58193
+ return null;
58360
58194
  }
58361
- function emitRustImplEdges(context, rootNode) {
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;
58200
+ }
58201
+ current = current.parent;
58202
+ }
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
+ }
58215
+ }
58216
+ if (isJsTsLanguage(sup.id)) {
58217
+ if (sup.nodeTypes.identifier.includes(obj.type)) {
58218
+ return null;
58219
+ }
58220
+ }
58221
+ const direct = await resolveExpression(obj);
58222
+ if (direct?.kind === "resolved") {
58223
+ return direct.def;
58224
+ }
58225
+ return null;
58226
+ }
58227
+ function receiverConstructorExpression(obj, source, sup) {
58228
+ if (obj.type === "new_expression" || obj.type === "object_creation_expression") {
58229
+ return constructorNameNode(obj, sup);
58230
+ }
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);
58241
+ }
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;
58250
+ }
58251
+ }
58252
+ return null;
58253
+ }
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;
58258
+ }
58259
+ function rootOf(node) {
58260
+ let current = node;
58261
+ while (current.parent) {
58262
+ current = current.parent;
58263
+ }
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;
58273
+ }
58274
+ }
58275
+ current = current.parent;
58276
+ }
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;
58284
+ }
58285
+ if (current !== node && isSkippableBindingContainer(current, receiver)) {
58286
+ return true;
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;
58301
+ }
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;
58311
+ }
58312
+ }
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
+ }
58322
+ }
58323
+ for (const child of current.namedChildren) {
58324
+ if (!visit(child)) {
58325
+ return false;
58326
+ }
58327
+ }
58328
+ return true;
58329
+ };
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;
58346
+ }
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;
58354
+ }
58355
+ }
58356
+ for (const child of current.namedChildren) {
58357
+ if (visit(child)) {
58358
+ return true;
58359
+ }
58360
+ }
58361
+ return false;
58362
+ };
58363
+ return visit(node);
58364
+ }
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);
58380
+ }
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);
58386
+ }
58387
+ return null;
58388
+ }
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);
58402
+ }
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
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);
58424
+ }
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;
58442
+ });
58443
+ }
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;
58453
+ }
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;
58468
+ }
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
+ }
58483
+ }
58484
+ for (const child of node.namedChildren) {
58485
+ if (!visit(child))
58486
+ return false;
58487
+ }
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;
58599
+ }
58600
+ const nested = current.childForFieldName("declarator");
58601
+ if (nested) {
58602
+ current = nested;
58603
+ continue;
58604
+ }
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
+ }
58627
+ }
58628
+ if (VALUE_BINDING_TYPES[node.type]) {
58629
+ const name = bindingIdentifier(node, sup);
58630
+ if (name && sliceText(name, source) === receiverName)
58631
+ return true;
58632
+ }
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;
58638
+ }
58639
+ return false;
58640
+ }
58641
+ function containsIndex(node, index) {
58642
+ return node.startIndex <= index && node.endIndex >= index;
58643
+ }
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 };
58676
+ }
58677
+ function declaresMembers(def) {
58678
+ return def.kind === SymbolKind.Class || def.kind === SymbolKind.Interface || def.kind === SymbolKind.TypeAlias;
58679
+ }
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;
58688
+ }
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;
58698
+ }
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);
58718
+ continue;
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)
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;
58755
+ }
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);
58766
+ }
58767
+ }
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" };
58778
+ }
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"() {
58782
+ "use strict";
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;
58905
+ }
58906
+ });
58907
+
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) {
58362
59374
  if (context.sup.id !== "rust")
58363
59375
  return;
58364
59376
  const walkImpls = (node) => {
@@ -58436,6 +59448,7 @@ var init_edgePasses = __esm({
58436
59448
  init_paths();
58437
59449
  init_symbol_graph();
58438
59450
  init_ast2();
59451
+ init_receiverCalls();
58439
59452
  RUBY_NESTED_SCOPE_TYPES = /* @__PURE__ */ new Set(["class", "module", "method", "singleton_method", "block", "do_block"]);
58440
59453
  }
58441
59454
  });
@@ -58600,6 +59613,20 @@ async function buildSymbolGraphDetailed(index, opts) {
58600
59613
  return moduleEntry?.locals.find((entry) => entry.localName === lastName) ?? null;
58601
59614
  };
58602
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
+ };
58603
59630
  const optionFileKeys = opts?.files ? new Set(Array.from(opts.files, fileIdentityKey)) : void 0;
58604
59631
  for (const moduleEntry of index.byFile.values()) {
58605
59632
  const file2 = moduleEntry.file;
@@ -58669,7 +59696,9 @@ async function buildSymbolGraphDetailed(index, opts) {
58669
59696
  resolveIdentifier,
58670
59697
  resolveExportFrom,
58671
59698
  resolveMemberChainTarget,
58672
- recordEdge
59699
+ recordEdge,
59700
+ receiverCalls,
59701
+ hasCallableNamed
58673
59702
  };
58674
59703
  emitPythonDecoratorEdges(edgePassContext, tree.rootNode);
58675
59704
  emitFunctionBodyEdges(edgePassContext, functionNodes);
@@ -58686,6 +59715,7 @@ async function buildSymbolGraphDetailed(index, opts) {
58686
59715
  logWithLevel(opts?.logLevel, "warn", `Warning: Failed to build detailed symbol edges for ${file2}:`, error51);
58687
59716
  }
58688
59717
  }
59718
+ emitReceiverCallEdges({ nodes, edges }, receiverCalls, recordEdge);
58689
59719
  emitMemberImplementationEdges({ nodes, edges }, recordEdge);
58690
59720
  if (skippedSyntaxTreeFiles > 0) {
58691
59721
  logWithLevel(opts?.logLevel, "warn", `Warning: Skipped detailed symbol edges for ${skippedSyntaxTreeFiles} file(s) because no syntax-tree backend was available.`);
@@ -58715,6 +59745,7 @@ var init_symbol_graph_detailed = __esm({
58715
59745
  init_edgePasses();
58716
59746
  init_importAliases();
58717
59747
  init_memberChains();
59748
+ init_receiverCalls();
58718
59749
  }
58719
59750
  });
58720
59751
 
@@ -61717,8 +62748,8 @@ ${block}
61717
62748
  function removeMarkedTomlBlock(existing, configPath) {
61718
62749
  if (inspectCodexTomlOwnership(existing, configPath) === null)
61719
62750
  return existing;
61720
- const begin = escapeRegExp(CODEGRAPH_TOML_MARKER_BEGIN);
61721
- const end = escapeRegExp(CODEGRAPH_TOML_MARKER_END);
62751
+ const begin = escapeRegExp2(CODEGRAPH_TOML_MARKER_BEGIN);
62752
+ const end = escapeRegExp2(CODEGRAPH_TOML_MARKER_END);
61722
62753
  const pattern = new RegExp(`\\n?${begin}[\\s\\S]*?${end}\\n?`, "g");
61723
62754
  return existing.replace(pattern, "\n").replace(/\n{3,}/g, "\n\n");
61724
62755
  }
@@ -62143,7 +63174,7 @@ async function renameTemporaryFile(temporaryPath, filePath) {
62143
63174
  }
62144
63175
  }
62145
63176
  }
62146
- function escapeRegExp(value) {
63177
+ function escapeRegExp2(value) {
62147
63178
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62148
63179
  }
62149
63180
  var InstallerCollisionError, TARGET_DEFINITIONS, CODEGRAPH_TOML_MARKER_BEGIN, CODEGRAPH_TOML_MARKER_END, DEFAULT_TARGET_IDS;
@@ -65268,806 +66299,253 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
65268
66299
  }
65269
66300
  }
65270
66301
  }
65271
- failures.sort(compareFailures);
65272
- return {
65273
- schemaVersion: 1,
65274
- root: normalizePath(root),
65275
- summary: {
65276
- filesScanned: markdownFiles.length,
65277
- linksChecked,
65278
- externalSkipped,
65279
- failures: failures.length
65280
- },
65281
- failures
65282
- };
65283
- }
65284
- async function recoverDisplayFileCasing(file2) {
65285
- const dir = path64.dirname(file2);
65286
- const base = path64.basename(file2);
65287
- try {
65288
- const entries = await fsp34.readdir(dir);
65289
- const match = entries.find((entry) => entry.toLowerCase() === base.toLowerCase());
65290
- return match ? path64.join(dir, match) : file2;
65291
- } catch {
65292
- return file2;
65293
- }
65294
- }
65295
- function parseLocalLinkTarget(destination) {
65296
- let trimmed = destination.trim();
65297
- if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
65298
- trimmed = trimmed.slice(1, -1).trim();
65299
- }
65300
- if (!trimmed)
65301
- return null;
65302
- const hashIndex = trimmed.indexOf("#");
65303
- const pathWithQuery = hashIndex >= 0 ? trimmed.slice(0, hashIndex) : trimmed;
65304
- const queryIndex = pathWithQuery.indexOf("?");
65305
- const targetPath = queryIndex >= 0 ? pathWithQuery.slice(0, queryIndex) : pathWithQuery;
65306
- const fragment = hashIndex >= 0 ? decodeFragment(trimmed.slice(hashIndex + 1)) : void 0;
65307
- return {
65308
- path: decodeMarkdownPath(targetPath),
65309
- ...fragment ? { fragment } : {}
65310
- };
65311
- }
65312
- function decodeMarkdownPath(targetPath) {
65313
- return decodeUriComponent(unescapeMarkdownPunctuation(targetPath));
65314
- }
65315
- function decodeFragment(fragment) {
65316
- return decodeUriComponent(fragment);
65317
- }
65318
- function decodeUriComponent(value) {
65319
- try {
65320
- return decodeURIComponent(value);
65321
- } catch {
65322
- return value;
65323
- }
65324
- }
65325
- function unescapeMarkdownPunctuation(value) {
65326
- let unescaped = "";
65327
- for (let index = 0; index < value.length; index += 1) {
65328
- const character = value.charAt(index);
65329
- const escapedCharacter = value.charAt(index + 1);
65330
- if (character === "\\" && isMarkdownPunctuation(escapedCharacter)) {
65331
- unescaped += escapedCharacter;
65332
- index += 1;
65333
- continue;
65334
- }
65335
- unescaped += character;
65336
- }
65337
- return unescaped;
65338
- }
65339
- function isMarkdownPunctuation(value) {
65340
- const code = value.charCodeAt(0);
65341
- return code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
65342
- }
65343
- function resolveMarkdownTarget(root, sourceFile, destination) {
65344
- if (!destination)
65345
- return sourceFile;
65346
- if (WINDOWS_ABSOLUTE_PATH.test(destination))
65347
- return path64.resolve(destination);
65348
- if (destination.startsWith("/"))
65349
- return path64.join(root, destination);
65350
- return path64.resolve(path64.dirname(sourceFile), destination);
65351
- }
65352
- async function cachedTargetStatus(target, targetStatusByPath) {
65353
- let status = targetStatusByPath.get(target);
65354
- if (!status) {
65355
- status = readTargetStatus(target);
65356
- targetStatusByPath.set(target, status);
65357
- }
65358
- return await status;
65359
- }
65360
- async function readTargetStatus(target) {
65361
- try {
65362
- const realPath = await fsp34.realpath(target);
65363
- const stats = await fsp34.stat(realPath);
65364
- return { status: "found", isDirectory: stats.isDirectory(), realPath };
65365
- } catch (error51) {
65366
- if (isMissingPathError3(error51))
65367
- return { status: "missing" };
65368
- throw new Error(`Failed to inspect Markdown link target ${normalizePath(target)}: ${error51 instanceof Error ? error51.message : String(error51)}`);
65369
- }
65370
- }
65371
- function isMissingPathError3(error51) {
65372
- return error51 instanceof Error && "code" in error51 && (error51.code === "ENOENT" || error51.code === "ENOTDIR");
65373
- }
65374
- async function cachedMarkdownAnchors(target, anchorsByPath) {
65375
- let anchors = anchorsByPath.get(target);
65376
- if (!anchors) {
65377
- anchors = readMarkdownFile(target).then(collectMarkdownAnchors);
65378
- anchorsByPath.set(target, anchors);
65379
- }
65380
- return await anchors;
65381
- }
65382
- async function readMarkdownFile(file2) {
65383
- try {
65384
- return await fsp34.readFile(file2, "utf8");
65385
- } catch (error51) {
65386
- if (error51 instanceof Error) {
65387
- throw new Error(`Failed to read Markdown file ${normalizePath(file2)}: ${error51.message}`);
65388
- }
65389
- throw error51;
65390
- }
65391
- }
65392
- function collectMarkdownAnchors(source) {
65393
- const anchors = /* @__PURE__ */ new Set();
65394
- const lines = source.split(/\r?\n/);
65395
- let fence = null;
65396
- for (let index = 0; index < lines.length; index += 1) {
65397
- const line = lines[index] ?? "";
65398
- const fenceMatch = line.match(/^ {0,3}(`{3,}|~{3,})/);
65399
- if (fenceMatch) {
65400
- const marker = fenceMatch[1]?.charAt(0);
65401
- if (marker === "`" || marker === "~") {
65402
- fence = fence === marker ? null : fence ?? marker;
65403
- }
65404
- continue;
65405
- }
65406
- if (fence || /^(?: {4}|\t)/.test(line))
65407
- continue;
65408
- const atx = line.match(/^ {0,3}#{1,6}[ \t]+(.+?)(?:[ \t]+#+[ \t]*)?$/);
65409
- if (atx?.[1]) {
65410
- addMarkdownAnchor(anchors, atx[1]);
65411
- continue;
65412
- }
65413
- const underline = lines[index + 1];
65414
- if (line.trim() && underline && /^ {0,3}(?:=+|-+)[ \t]*$/.test(underline)) {
65415
- addMarkdownAnchor(anchors, line);
65416
- index += 1;
65417
- }
65418
- }
65419
- return anchors;
65420
- }
65421
- function addMarkdownAnchor(anchors, heading) {
65422
- const baseSlug = markdownHeadingSlug(heading);
65423
- if (!baseSlug)
65424
- return;
65425
- let slug = baseSlug;
65426
- let suffix = 1;
65427
- while (anchors.has(slug)) {
65428
- slug = `${baseSlug}-${suffix}`;
65429
- suffix += 1;
65430
- }
65431
- anchors.add(slug);
65432
- }
65433
- function markdownHeadingSlug(heading) {
65434
- return renderMarkdownHeading(heading).trim().toLowerCase().replace(/[^\p{L}\p{N}_\-\s]/gu, "").replace(/\s+/g, "-");
65435
- }
65436
- function renderMarkdownHeading(heading) {
65437
- 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, "");
65438
- }
65439
- function toFailure(root, file2, occurrence, reason, target) {
65440
- return {
65441
- file: toProjectDisplayPath(root, file2),
65442
- range: {
65443
- start: { line: occurrence.range.start.line, column: occurrence.range.start.column },
65444
- end: { line: occurrence.range.end.line, column: occurrence.range.end.column }
65445
- },
65446
- raw: occurrence.raw,
65447
- reason,
65448
- ...target ? { target: toProjectDisplayPath(root, target) } : {}
65449
- };
65450
- }
65451
- function compareFailures(left, right) {
65452
- const fileOrder = left.file.localeCompare(right.file);
65453
- if (fileOrder)
65454
- return fileOrder;
65455
- const lineOrder = left.range.start.line - right.range.start.line;
65456
- if (lineOrder)
65457
- return lineOrder;
65458
- return left.range.start.column - right.range.start.column;
65459
- }
65460
- var URI_SCHEME, WINDOWS_ABSOLUTE_PATH;
65461
- var init_check = __esm({
65462
- "dist/documentLinks/check.js"() {
65463
- "use strict";
65464
- init_markdown2();
65465
- init_languages();
65466
- init_paths();
65467
- init_projectFiles();
65468
- URI_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/;
65469
- WINDOWS_ABSOLUTE_PATH = /^[A-Za-z]:[\\/]/;
65470
- }
65471
- });
65472
-
65473
- // dist/indexer/load-current-index.js
65474
- var load_current_index_exports = {};
65475
- __export(load_current_index_exports, {
65476
- createCurrentProjectIndexLoader: () => createCurrentProjectIndexLoader,
65477
- currentProjectIndexBuildOptions: () => currentProjectIndexBuildOptions,
65478
- loadCurrentProjectIndex: () => loadCurrentProjectIndex
65479
- });
65480
- function currentProjectIndexBuildOptions(scope, options) {
65481
- const buildOptions = { ...options };
65482
- for (const key of NON_CURRENT_STATE_OPTION_KEYS) {
65483
- delete buildOptions[key];
65484
- }
65485
- buildOptions.cache = options?.cache ?? "disk";
65486
- if (scope.kind === "resolved-files") {
65487
- buildOptions.files = [...scope.files];
65488
- buildOptions.filesAreProjectScope = true;
65489
- return buildOptions;
65490
- }
65491
- if (scope.additionalFiles?.length) {
65492
- buildOptions.additionalFiles = [...scope.additionalFiles];
65493
- }
65494
- return buildOptions;
65495
- }
65496
- async function loadCurrentProjectIndex(request) {
65497
- const { buildProjectIndexIncremental: buildProjectIndexIncremental2 } = await Promise.resolve().then(() => (init_build_index(), build_index_exports));
65498
- return await buildProjectIndexIncremental2(request.root, currentProjectIndexBuildOptions(request.scope, request.options));
65499
- }
65500
- function createCurrentProjectIndexLoader(root, options, scope = { kind: "project" }) {
65501
- return async () => await loadCurrentProjectIndex({ root, scope, ...options ? { options } : {} });
65502
- }
65503
- var NON_CURRENT_STATE_OPTION_KEYS;
65504
- var init_load_current_index = __esm({
65505
- "dist/indexer/load-current-index.js"() {
65506
- "use strict";
65507
- NON_CURRENT_STATE_OPTION_KEYS = [
65508
- "files",
65509
- "additionalFiles",
65510
- "filesAreProjectScope",
65511
- "gitBase",
65512
- "gitHead",
65513
- "changedSince",
65514
- "reconciledManifestUpdatedAt",
65515
- "reconciledWorkingTreeDiffFiles",
65516
- "reconciledUntrackedFiles"
65517
- ];
65518
- }
65519
- });
65520
-
65521
- // dist/indexer/navigation-provenance.js
65522
- function getNavigationBackend(index) {
65523
- if (index.nativeMode === "on") {
65524
- return "native";
65525
- }
65526
- if (index.nativeMode === "off") {
65527
- return "graph-only";
65528
- }
65529
- return void 0;
65530
- }
65531
- function createNavigationProvenance(index, resolution, confidence) {
65532
- const backend = getNavigationBackend(index);
65533
- return {
65534
- ...backend ? { backend } : {},
65535
- ...resolution ? { resolution } : {},
65536
- ...confidence ? { confidence } : {}
65537
- };
65538
- }
65539
- function okGoToResult(index, definition, options) {
65540
- return {
65541
- status: "ok",
65542
- definition,
65543
- ...options.via ? { via: options.via } : {},
65544
- provenance: createNavigationProvenance(index, options.resolution, options.confidence)
65545
- };
65546
- }
65547
- var init_navigation_provenance = __esm({
65548
- "dist/indexer/navigation-provenance.js"() {
65549
- "use strict";
65550
- }
65551
- });
65552
-
65553
- // dist/indexer/navigation-goto.js
65554
- async function resolveMemberAccessDefinition(params) {
65555
- const { index, mod: mod2, node, source, sup, resolveLexicalBinding } = params;
65556
- const parent = node.parent;
65557
- if (!parent || !sup.supportsCrossModuleSymbols || !isMemberAccessNode(sup, parent)) {
65558
- return null;
65559
- }
65560
- const memberNode = parent;
65561
- const { object: obj, property: prop } = getMemberAccessParts(sup, memberNode);
65562
- const optionalMemberTypes = memberAccessTraversalTypes(sup);
65563
- const resolveExpression = async (expr) => {
65564
- const exprIsId = sup.nodeTypes.identifier.includes(expr.type) && !isMemberAccessNode(sup, expr);
65565
- if (exprIsId || expr.type === "identifier" || expr.type === "type_identifier" || expr.type === "constant") {
65566
- const lexicalBinding = resolveLexicalBinding?.(expr);
65567
- if (lexicalBinding)
65568
- return { kind: "resolved", def: lexicalBinding };
65569
- const exprName = sliceText(expr, source);
65570
- const imp = mod2.imports.find((candidate) => candidate.kind === "named" && candidate.local === exprName || candidate.kind === "default" && candidate.local === exprName || candidate.kind === "namespace" && candidate.localNS === exprName);
65571
- if (imp) {
65572
- if (imp.kind === "namespace") {
65573
- return {
65574
- kind: "namespace",
65575
- file: typeof imp.resolved === "string" ? imp.resolved.replace(/\\/g, "/") : imp.resolved?.external || ""
65576
- };
65577
- }
65578
- const result = resolveImported(index, imp, imp.kind === "named" ? imp.imported : "default");
65579
- if (result) {
65580
- if ("namespace" in result) {
65581
- return { kind: "namespace", file: result.namespace };
65582
- }
65583
- return { kind: "resolved", def: result };
65584
- }
65585
- }
65586
- const local = mod2.locals.find((candidate) => candidate.localName === exprName);
65587
- if (local)
65588
- return { kind: "resolved", def: local };
65589
- for (const starImport of mod2.imports.filter((candidate) => candidate.kind === "star")) {
65590
- const result = resolveImported(index, starImport, exprName);
65591
- if (result) {
65592
- if ("namespace" in result) {
65593
- return { kind: "namespace", file: result.namespace };
65594
- }
65595
- return { kind: "resolved", def: result };
65596
- }
65597
- }
65598
- return null;
65599
- }
65600
- if (optionalMemberTypes.has(expr.type)) {
65601
- const parts = getMemberAccessParts(sup, expr);
65602
- const subObj = parts.object;
65603
- let subProp = parts.property;
65604
- if (!subProp && expr.type === "navigation_expression") {
65605
- subProp = getNavigationExpressionProperty(expr);
65606
- }
65607
- if (subObj && subProp) {
65608
- const base = await resolveExpression(subObj);
65609
- const memberName = sliceText(subProp, source);
65610
- if (base?.kind === "namespace") {
65611
- return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
65612
- }
65613
- if (base?.kind === "resolved") {
65614
- if (sup.id === "java") {
65615
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65616
- return memberDef ? { kind: "resolved", def: memberDef } : null;
65617
- }
65618
- if (sup.id === "ruby") {
65619
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65620
- if (memberDef)
65621
- return { kind: "resolved", def: memberDef };
65622
- const localHit = resolveExport(index, base.def.file, memberName);
65623
- if (localHit)
65624
- return localHit;
65625
- }
65626
- return null;
65627
- }
65628
- }
65629
- }
65630
- if (sup.id === "java" && (expr.type === "scoped_identifier" || expr.type === "scoped_type_identifier")) {
65631
- const subObj = expr.childForFieldName("scope") ?? expr.child(0);
65632
- const subProp = expr.childForFieldName("name") ?? expr.child(2);
65633
- if (subObj && subProp) {
65634
- const base = await resolveExpression(subObj);
65635
- const memberName = sliceText(subProp, source);
65636
- if (base?.kind === "namespace") {
65637
- return resolveExport(index, base.file, memberName, { allowLocalFallback: false });
65638
- }
65639
- if (base?.kind === "resolved") {
65640
- const memberDef = await resolveMemberDefinitionForBase(index, base.def, memberName);
65641
- return memberDef ? { kind: "resolved", def: memberDef } : null;
65642
- }
65643
- }
65644
- }
65645
- return null;
65646
- };
65647
- const chain = await resolveExpression(memberNode);
65648
- if (chain && prop && node.id === prop.id) {
65649
- if (chain.kind === "resolved") {
65650
- return okGoToResult(index, chain.def, {
65651
- via: { exportedName: sliceText(prop, source) },
65652
- resolution: "member-access",
65653
- confidence: "medium"
65654
- });
65655
- }
65656
- if (chain.kind === "namespace") {
65657
- const targetMod = index.byFile.get(fileIdentityKey(chain.file));
65658
- const first = targetMod?.exports.find((entry) => entry.type === "local");
65659
- if (first) {
65660
- return okGoToResult(index, first.target, {
65661
- via: { exportedName: first.exportedAs },
65662
- resolution: "namespace",
65663
- confidence: "medium"
65664
- });
65665
- }
65666
- }
65667
- }
65668
- const receiverName = obj ? sliceText(obj, source) : "";
65669
- const implicitClassReceiver = isJsTsLanguage(sup.id) && receiverName === "this" || sup.id === "php" && /^(?:\$this|self|static)$/.test(receiverName) || sup.id === "rust" && /^(?:self|Self)$/.test(receiverName);
65670
- if (obj && prop && node.id === prop.id && (supportsReceiverMemberResolution(sup.id) || implicitClassReceiver)) {
65671
- const member = sliceText(prop, source);
65672
- if (!sup.membersAreImplicitlyInScope && implicitClassReceiver) {
65673
- const classContainer = findEnclosingClassContainer(node);
65674
- const memberDef = classContainer ? findLocalWithinNode(mod2.locals, member, classContainer, sup.normalizeIdentifier) : void 0;
65675
- if (memberDef) {
65676
- return okGoToResult(index, memberDef, {
65677
- via: { exportedName: member },
65678
- resolution: "member-access",
65679
- confidence: "medium"
65680
- });
65681
- }
65682
- }
65683
- const objDef = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
65684
- if (objDef) {
65685
- const targetContext = await ensureParsedContext(objDef.file, void 0, index.languageExtensions);
65686
- const start = objDef.range.start;
65687
- const targetPosition = {
65688
- row: start.line - 1,
65689
- column: start.column - 1
65690
- };
65691
- const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
65692
- const container = nameNode.parent;
65693
- if (container) {
65694
- const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
65695
- if (targetModule) {
65696
- const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
65697
- const memberDef = targetContext.sup.id === "java" ? findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier) : findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier);
65698
- if (memberDef) {
65699
- return okGoToResult(index, memberDef, {
65700
- via: { exportedName: member },
65701
- resolution: "member-access",
65702
- confidence: "medium"
65703
- });
65704
- }
65705
- }
65706
- }
65707
- }
65708
- }
65709
- return null;
65710
- }
65711
- function findEnclosingClassContainer(node) {
65712
- let current = node.parent;
65713
- while (current) {
65714
- if (current.type === "class_declaration" || current.type === "abstract_class_declaration" || current.type === "class_definition" || current.type === "impl_item") {
65715
- return current;
65716
- }
65717
- current = current.parent;
65718
- }
65719
- return null;
65720
- }
65721
- function supportsReceiverMemberResolution(languageId) {
65722
- return languageId === "csharp" || languageId === "python" || languageId === "js" || languageId === "java" || languageId === "javascript" || languageId === "jsx" || languageId === "rust" || languageId === "ts" || languageId === "typescript" || languageId === "tsx";
65723
- }
65724
- async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
65725
- const constructor = receiverConstructorExpression(obj, source, sup);
65726
- if (constructor) {
65727
- const result = await resolveExpression(constructor);
65728
- if (result?.kind === "resolved") {
65729
- return result.def;
65730
- }
65731
- }
65732
- if (isJsTsLanguage(sup.id)) {
65733
- if (sup.nodeTypes.identifier.includes(obj.type)) {
65734
- return null;
65735
- }
65736
- }
65737
- const direct = await resolveExpression(obj);
65738
- if (direct?.kind === "resolved") {
65739
- return direct.def;
65740
- }
65741
- 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
+ };
65742
66314
  }
65743
- function receiverConstructorExpression(obj, source, sup) {
65744
- if (obj.type === "new_expression" || obj.type === "object_creation_expression") {
65745
- 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;
65746
66324
  }
65747
- if (sup.id === "ruby" && obj.type === "call") {
65748
- const rubyConstructor = rubyNewReceiverNameNode(obj, source, sup);
65749
- if (rubyConstructor)
65750
- 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();
65751
66330
  }
65752
- if (!sup.nodeTypes.identifier.includes(obj.type)) {
66331
+ if (!trimmed)
65753
66332
  return null;
65754
- }
65755
- const receiverName = sliceText(obj, source);
65756
- 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
+ };
65757
66342
  }
65758
- function constructorNameNode(node, sup) {
65759
- const constructor = node.childForFieldName("constructor") ?? node.child(0);
65760
- if (constructor && sup.nodeTypes.identifier.includes(constructor.type)) {
65761
- 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;
65762
66354
  }
65763
- for (const child of node.namedChildren) {
65764
- if (sup.nodeTypes.identifier.includes(child.type) || child.type === "type_identifier" || child.type === "constant") {
65765
- 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;
65766
66365
  }
66366
+ unescaped += character;
65767
66367
  }
65768
- return null;
66368
+ return unescaped;
65769
66369
  }
65770
- function rubyNewReceiverNameNode(node, source, sup) {
65771
- if (!new RegExp(String.raw`^(?:${RUBY_CONSTANT_SOURCE})\.new$`, "u").test(sliceText(node, source)))
65772
- return null;
65773
- 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;
65774
66373
  }
65775
- function rootOf(node) {
65776
- let current = node;
65777
- while (current.parent) {
65778
- 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);
65779
66388
  }
65780
- return current;
66389
+ return await status;
65781
66390
  }
65782
- function findVisiblePriorNewConstructor(receiver, receiverName, source, sup) {
65783
- let current = receiver;
65784
- while (current) {
65785
- if (BINDING_CONTAINER_TYPES.has(current.type)) {
65786
- const constructor = findPriorNewConstructorInContainer(current, receiver, receiverName, source, sup);
65787
- if (constructor || bindingContainerDeclaresNameBefore(current, receiver, receiverName, source, sup)) {
65788
- return constructor;
65789
- }
65790
- }
65791
- 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)}`);
65792
66400
  }
65793
- return findPriorNewConstructorInContainer(rootOf(receiver), receiver, receiverName, source, sup);
65794
66401
  }
65795
- function findPriorNewConstructorInContainer(node, receiver, receiverName, source, sup) {
65796
- let constructor = null;
65797
- const visit = (current) => {
65798
- if (current.startIndex >= receiver.startIndex) {
65799
- return true;
65800
- }
65801
- if (current !== node && isSkippableBindingContainer(current, receiver)) {
65802
- return true;
65803
- }
65804
- if (current.type === "variable_declarator") {
65805
- const name = current.childForFieldName("name") ?? current.child(0);
65806
- const value = current.childForFieldName("value");
65807
- 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) {
65808
- const candidate = constructorNameNode(value, sup);
65809
- if (!candidate) {
65810
- return true;
65811
- }
65812
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65813
- constructor = null;
65814
- return false;
65815
- }
65816
- constructor = candidate;
65817
- }
65818
- }
65819
- if (current.type === "assignment" || current.type === "let_declaration") {
65820
- const candidate = constructorFromAssignmentLike(current, receiverName, source, sup);
65821
- if (candidate) {
65822
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65823
- constructor = null;
65824
- return false;
65825
- }
65826
- constructor = candidate;
65827
- }
65828
- }
65829
- if (current.type === "local_variable_declaration" || current.type === "local_declaration_statement" || current.type === "variable_declaration") {
65830
- const candidate = constructorFromTypedLocalDeclaration(current, receiverName, source, sup);
65831
- if (candidate) {
65832
- if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
65833
- constructor = null;
65834
- return false;
65835
- }
65836
- constructor = candidate;
65837
- }
65838
- }
65839
- for (const child of current.namedChildren) {
65840
- if (!visit(child)) {
65841
- return false;
65842
- }
65843
- }
65844
- return true;
65845
- };
65846
- visit(node);
65847
- return constructor;
66402
+ function isMissingPathError3(error51) {
66403
+ return error51 instanceof Error && "code" in error51 && (error51.code === "ENOENT" || error51.code === "ENOTDIR");
65848
66404
  }
65849
- function constructorFromTypedLocalDeclaration(node, receiverName, source, sup) {
65850
- if (sup.id !== "csharp" && sup.id !== "java")
65851
- return null;
65852
- const text = sliceText(node, source);
65853
- const typeNameSource = sup.id === "java" ? JAVA_CONSTANT_SOURCE : CSHARP_CONSTANT_SOURCE;
65854
- 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"));
65855
- const typeName = match?.[2] ?? match?.[1];
65856
- 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;
65857
66412
  }
65858
- function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source, sup) {
65859
- const visit = (current) => {
65860
- if (current.startIndex >= receiver.startIndex) {
65861
- return false;
65862
- }
65863
- if (current !== node && isSkippableBindingContainer(current, receiver)) {
65864
- 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}`);
65865
66419
  }
65866
- if (BINDING_DECLARATION_TYPES.has(current.type)) {
65867
- const name = current.childForFieldName("name") ?? current.child(0);
65868
- if (name && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
65869
- 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;
65870
66434
  }
66435
+ continue;
65871
66436
  }
65872
- for (const child of current.namedChildren) {
65873
- if (visit(child)) {
65874
- return true;
65875
- }
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;
65876
66448
  }
65877
- return false;
65878
- };
65879
- return visit(node);
65880
- }
65881
- function isSkippableBindingContainer(node, receiver) {
65882
- return BINDING_CONTAINER_TYPES.has(node.type) && !nodeContainsIndex(node, receiver.startIndex);
65883
- }
65884
- function nodeContainsIndex(node, index) {
65885
- return node.startIndex <= index && node.endIndex >= index;
65886
- }
65887
- function constructorFromAssignmentLike(node, receiverName, source, sup) {
65888
- const text = sliceText(node, source);
65889
- if (!new RegExp(String.raw`(?<!${IDENTIFIER_BOUNDARY_SOURCE})${escapeRegExp2(receiverName)}(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u").test(text))
65890
- return null;
65891
- if (sup.id === "ruby") {
65892
- const match = text.match(new RegExp(String.raw`^\s*${escapeRegExp2(receiverName)}\s*=\s*(${RUBY_CONSTANT_SOURCE})\.new(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
65893
- if (!match?.[1])
65894
- return null;
65895
- return findNamedChildText(node, match[1], source, sup);
65896
66449
  }
65897
- if (sup.id === "rust") {
65898
- const match = text.match(new RegExp(String.raw`^\s*(?:let\s+)?${escapeRegExp2(receiverName)}\s*=\s*(${RUST_CONSTANT_SOURCE})(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
65899
- if (!match?.[1])
65900
- return null;
65901
- 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;
65902
66461
  }
65903
- return null;
66462
+ anchors.add(slug);
65904
66463
  }
65905
- function findNamedChildText(node, name, source, sup) {
65906
- const isNameNode = (candidate) => (sup.nodeTypes.identifier.includes(candidate.type) || candidate.type === "type_identifier" || candidate.type === "constant") && sliceText(candidate, source) === name;
65907
- const visit = (current) => {
65908
- if (isNameNode(current))
65909
- return current;
65910
- for (const child of current.namedChildren) {
65911
- const hit = visit(child);
65912
- if (hit)
65913
- return hit;
65914
- }
65915
- return null;
65916
- };
65917
- return visit(node);
66464
+ function markdownHeadingSlug(heading) {
66465
+ return renderMarkdownHeading(heading).trim().toLowerCase().replace(/[^\p{L}\p{N}_\-\s]/gu, "").replace(/\s+/g, "-");
65918
66466
  }
65919
- async function resolveMemberDefinitionForBase(index, baseDef, member) {
65920
- const targetContext = await ensureParsedContext(baseDef.file, void 0, index.languageExtensions);
65921
- const start = baseDef.range.start;
65922
- const targetPosition = {
65923
- row: start.line - 1,
65924
- column: start.column - 1
65925
- };
65926
- const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
65927
- const container = nameNode.parent;
65928
- if (!container)
65929
- return void 0;
65930
- const targetModule = index.byFile.get(fileIdentityKey(baseDef.file));
65931
- if (!targetModule)
65932
- return void 0;
65933
- const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
65934
- const directHit = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
65935
- if (directHit)
65936
- return directHit;
65937
- if (targetContext.sup.id === "java")
65938
- return void 0;
65939
- 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, "");
65940
66469
  }
65941
- function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier) {
65942
- const containerHit = findLocalWithinNode(locals, member, container, normalizeIdentifier);
65943
- if (containerHit)
65944
- return containerHit;
65945
- if (targetContext.sup.id !== "rust")
65946
- return void 0;
65947
- const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
65948
- 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
+ };
65949
66481
  }
65950
- function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name) {
65951
- const containerStart = node.startIndex;
65952
- const containerEnd = node.endIndex;
65953
- const normalizedMember = normalizeIdentifier(member);
65954
- return locals.find((local) => {
65955
- const startIndex = local.range.start.index;
65956
- const endIndex = local.range.end.index;
65957
- return normalizeIdentifier(local.localName) === normalizedMember && startIndex !== void 0 && endIndex !== void 0 && startIndex >= containerStart && endIndex <= containerEnd;
65958
- });
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;
65959
66490
  }
65960
- function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier) {
65961
- const containerStart = container.startIndex;
65962
- const containerEnd = container.endIndex;
65963
- const normalizedMember = normalizeIdentifier(member);
65964
- for (const local of locals) {
65965
- const startIndex = local.range.start.index;
65966
- const endIndex = local.range.end.index;
65967
- if (normalizeIdentifier(local.localName) !== normalizedMember || startIndex === void 0 || endIndex === void 0 || startIndex < containerStart || endIndex > containerEnd) {
65968
- continue;
65969
- }
65970
- const start = local.range.start;
65971
- const position = {
65972
- row: start.line - 1,
65973
- column: start.column - 1
65974
- };
65975
- let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
65976
- let isDeclarationParent = true;
65977
- while (current && current !== container) {
65978
- if (!isDeclarationParent && (current.type === "class_body" && current.parent !== container || NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
65979
- current = null;
65980
- break;
65981
- }
65982
- isDeclarationParent = false;
65983
- current = current.parent;
65984
- }
65985
- if (current)
65986
- 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]:[\\/]/;
65987
66501
  }
65988
- 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;
65989
66526
  }
65990
- function findRustImplForType(root, typeName, source) {
65991
- let found = null;
65992
- const visit = (node) => {
65993
- if (node.type === "impl_item") {
65994
- const text = sliceText(node, source);
65995
- if (new RegExp(`^\\s*impl\\s+${escapeRegExp2(typeName)}\\b`).test(text)) {
65996
- found = node;
65997
- return false;
65998
- }
65999
- }
66000
- for (const child of node.namedChildren) {
66001
- if (!visit(child))
66002
- return false;
66003
- }
66004
- return true;
66005
- };
66006
- visit(root);
66007
- 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));
66008
66530
  }
66009
- function escapeRegExp2(value) {
66010
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
66531
+ function createCurrentProjectIndexLoader(root, options, scope = { kind: "project" }) {
66532
+ return async () => await loadCurrentProjectIndex({ root, scope, ...options ? { options } : {} });
66011
66533
  }
66012
- 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;
66013
- var init_navigation_goto = __esm({
66014
- "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"() {
66015
66537
  "use strict";
66016
- init_js_family();
66017
- init_ast();
66018
- init_paths();
66019
- init_memberAccess();
66020
- init_identifiers();
66021
- init_parse_context();
66022
- init_navigation_provenance();
66023
- init_navigation_resolve();
66024
- RUBY_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
66025
- CSHARP_CONSTANT_SOURCE = String.raw`(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
66026
- JAVA_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
66027
- RUST_CONSTANT_SOURCE = String.raw`(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
66028
- IDENTIFIER_BOUNDARY_SOURCE = String.raw`[$_\p{ID_Continue}\u200c\u200d]`;
66029
- BINDING_CONTAINER_TYPES = /* @__PURE__ */ new Set([
66030
- "program",
66031
- "compilation_unit",
66032
- "source_file",
66033
- "statement_block",
66034
- "block",
66035
- "function_declaration",
66036
- "function_item",
66037
- "function",
66038
- "function_expression",
66039
- "arrow_function",
66040
- "method_definition",
66041
- "method_declaration",
66042
- "method"
66043
- ]);
66044
- BINDING_DECLARATION_TYPES = /* @__PURE__ */ new Set([
66045
- "variable_declarator",
66046
- "let_declaration",
66047
- "assignment",
66048
- "formal_parameter",
66049
- "required_parameter",
66050
- "optional_parameter"
66051
- ]);
66052
- NESTED_MEMBER_LOCAL_CONTAINERS = /* @__PURE__ */ new Set([
66053
- "block",
66054
- "class",
66055
- "class_declaration",
66056
- "class_definition",
66057
- "constructor_declaration",
66058
- "enum_declaration",
66059
- "enum_item",
66060
- "enum_specifier",
66061
- "function_declaration",
66062
- "function_definition",
66063
- "function_item",
66064
- "interface_declaration",
66065
- "method",
66066
- "method_declaration",
66067
- "method_definition",
66068
- "module",
66069
- "statement_block"
66070
- ]);
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
+ ];
66071
66549
  }
66072
66550
  });
66073
66551