@zuvia-software-solutions/code-mapper 1.4.0

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 (213) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/ai-context.d.ts +19 -0
  3. package/dist/cli/ai-context.js +168 -0
  4. package/dist/cli/analyze.d.ts +7 -0
  5. package/dist/cli/analyze.js +325 -0
  6. package/dist/cli/augment.d.ts +7 -0
  7. package/dist/cli/augment.js +27 -0
  8. package/dist/cli/clean.d.ts +5 -0
  9. package/dist/cli/clean.js +56 -0
  10. package/dist/cli/eval-server.d.ts +25 -0
  11. package/dist/cli/eval-server.js +365 -0
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +102 -0
  14. package/dist/cli/lazy-action.d.ts +6 -0
  15. package/dist/cli/lazy-action.js +19 -0
  16. package/dist/cli/list.d.ts +2 -0
  17. package/dist/cli/list.js +27 -0
  18. package/dist/cli/mcp.d.ts +8 -0
  19. package/dist/cli/mcp.js +35 -0
  20. package/dist/cli/refresh.d.ts +12 -0
  21. package/dist/cli/refresh.js +165 -0
  22. package/dist/cli/serve.d.ts +5 -0
  23. package/dist/cli/serve.js +8 -0
  24. package/dist/cli/setup.d.ts +6 -0
  25. package/dist/cli/setup.js +218 -0
  26. package/dist/cli/status.d.ts +2 -0
  27. package/dist/cli/status.js +33 -0
  28. package/dist/cli/tool.d.ts +28 -0
  29. package/dist/cli/tool.js +87 -0
  30. package/dist/config/ignore-service.d.ts +32 -0
  31. package/dist/config/ignore-service.js +282 -0
  32. package/dist/config/supported-languages.d.ts +23 -0
  33. package/dist/config/supported-languages.js +52 -0
  34. package/dist/core/augmentation/engine.d.ts +22 -0
  35. package/dist/core/augmentation/engine.js +232 -0
  36. package/dist/core/embeddings/embedder.d.ts +35 -0
  37. package/dist/core/embeddings/embedder.js +171 -0
  38. package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
  39. package/dist/core/embeddings/embedding-pipeline.js +402 -0
  40. package/dist/core/embeddings/index.d.ts +5 -0
  41. package/dist/core/embeddings/index.js +6 -0
  42. package/dist/core/embeddings/text-generator.d.ts +20 -0
  43. package/dist/core/embeddings/text-generator.js +159 -0
  44. package/dist/core/embeddings/types.d.ts +60 -0
  45. package/dist/core/embeddings/types.js +23 -0
  46. package/dist/core/graph/graph.d.ts +4 -0
  47. package/dist/core/graph/graph.js +65 -0
  48. package/dist/core/graph/types.d.ts +69 -0
  49. package/dist/core/graph/types.js +3 -0
  50. package/dist/core/incremental/child-process.d.ts +8 -0
  51. package/dist/core/incremental/child-process.js +649 -0
  52. package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
  53. package/dist/core/incremental/refresh-coordinator.js +147 -0
  54. package/dist/core/incremental/types.d.ts +78 -0
  55. package/dist/core/incremental/types.js +153 -0
  56. package/dist/core/incremental/watcher.d.ts +63 -0
  57. package/dist/core/incremental/watcher.js +338 -0
  58. package/dist/core/ingestion/ast-cache.d.ts +12 -0
  59. package/dist/core/ingestion/ast-cache.js +34 -0
  60. package/dist/core/ingestion/call-processor.d.ts +34 -0
  61. package/dist/core/ingestion/call-processor.js +937 -0
  62. package/dist/core/ingestion/call-routing.d.ts +40 -0
  63. package/dist/core/ingestion/call-routing.js +97 -0
  64. package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
  65. package/dist/core/ingestion/cluster-enricher.js +151 -0
  66. package/dist/core/ingestion/community-processor.d.ts +26 -0
  67. package/dist/core/ingestion/community-processor.js +272 -0
  68. package/dist/core/ingestion/constants.d.ts +5 -0
  69. package/dist/core/ingestion/constants.js +8 -0
  70. package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
  71. package/dist/core/ingestion/entry-point-scoring.js +317 -0
  72. package/dist/core/ingestion/export-detection.d.ts +11 -0
  73. package/dist/core/ingestion/export-detection.js +203 -0
  74. package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
  75. package/dist/core/ingestion/filesystem-walker.js +64 -0
  76. package/dist/core/ingestion/framework-detection.d.ts +42 -0
  77. package/dist/core/ingestion/framework-detection.js +405 -0
  78. package/dist/core/ingestion/heritage-processor.d.ts +15 -0
  79. package/dist/core/ingestion/heritage-processor.js +237 -0
  80. package/dist/core/ingestion/import-processor.d.ts +31 -0
  81. package/dist/core/ingestion/import-processor.js +416 -0
  82. package/dist/core/ingestion/language-config.d.ts +32 -0
  83. package/dist/core/ingestion/language-config.js +161 -0
  84. package/dist/core/ingestion/mro-processor.d.ts +32 -0
  85. package/dist/core/ingestion/mro-processor.js +343 -0
  86. package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
  87. package/dist/core/ingestion/named-binding-extraction.js +343 -0
  88. package/dist/core/ingestion/parsing-processor.d.ts +20 -0
  89. package/dist/core/ingestion/parsing-processor.js +282 -0
  90. package/dist/core/ingestion/pipeline.d.ts +3 -0
  91. package/dist/core/ingestion/pipeline.js +416 -0
  92. package/dist/core/ingestion/process-processor.d.ts +42 -0
  93. package/dist/core/ingestion/process-processor.js +357 -0
  94. package/dist/core/ingestion/resolution-context.d.ts +40 -0
  95. package/dist/core/ingestion/resolution-context.js +171 -0
  96. package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
  97. package/dist/core/ingestion/resolvers/csharp.js +101 -0
  98. package/dist/core/ingestion/resolvers/go.d.ts +8 -0
  99. package/dist/core/ingestion/resolvers/go.js +33 -0
  100. package/dist/core/ingestion/resolvers/index.d.ts +14 -0
  101. package/dist/core/ingestion/resolvers/index.js +10 -0
  102. package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
  103. package/dist/core/ingestion/resolvers/jvm.js +74 -0
  104. package/dist/core/ingestion/resolvers/php.d.ts +7 -0
  105. package/dist/core/ingestion/resolvers/php.js +30 -0
  106. package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
  107. package/dist/core/ingestion/resolvers/ruby.js +13 -0
  108. package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
  109. package/dist/core/ingestion/resolvers/rust.js +62 -0
  110. package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
  111. package/dist/core/ingestion/resolvers/standard.js +144 -0
  112. package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
  113. package/dist/core/ingestion/resolvers/utils.js +113 -0
  114. package/dist/core/ingestion/structure-processor.d.ts +4 -0
  115. package/dist/core/ingestion/structure-processor.js +39 -0
  116. package/dist/core/ingestion/symbol-table.d.ts +34 -0
  117. package/dist/core/ingestion/symbol-table.js +48 -0
  118. package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
  119. package/dist/core/ingestion/tree-sitter-queries.js +691 -0
  120. package/dist/core/ingestion/type-env.d.ts +52 -0
  121. package/dist/core/ingestion/type-env.js +349 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
  123. package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
  124. package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
  125. package/dist/core/ingestion/type-extractors/csharp.js +224 -0
  126. package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
  127. package/dist/core/ingestion/type-extractors/go.js +261 -0
  128. package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
  129. package/dist/core/ingestion/type-extractors/index.js +30 -0
  130. package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
  131. package/dist/core/ingestion/type-extractors/jvm.js +386 -0
  132. package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
  133. package/dist/core/ingestion/type-extractors/php.js +280 -0
  134. package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
  135. package/dist/core/ingestion/type-extractors/python.js +175 -0
  136. package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
  137. package/dist/core/ingestion/type-extractors/ruby.js +218 -0
  138. package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
  139. package/dist/core/ingestion/type-extractors/rust.js +290 -0
  140. package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
  141. package/dist/core/ingestion/type-extractors/shared.js +322 -0
  142. package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
  143. package/dist/core/ingestion/type-extractors/swift.js +140 -0
  144. package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
  145. package/dist/core/ingestion/type-extractors/types.js +4 -0
  146. package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
  147. package/dist/core/ingestion/type-extractors/typescript.js +227 -0
  148. package/dist/core/ingestion/utils.d.ts +73 -0
  149. package/dist/core/ingestion/utils.js +992 -0
  150. package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
  151. package/dist/core/ingestion/workers/parse-worker.js +1055 -0
  152. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
  153. package/dist/core/ingestion/workers/worker-pool.js +123 -0
  154. package/dist/core/lbug/csv-generator.d.ts +28 -0
  155. package/dist/core/lbug/csv-generator.js +355 -0
  156. package/dist/core/lbug/lbug-adapter.d.ts +96 -0
  157. package/dist/core/lbug/lbug-adapter.js +753 -0
  158. package/dist/core/lbug/schema.d.ts +46 -0
  159. package/dist/core/lbug/schema.js +402 -0
  160. package/dist/core/search/bm25-index.d.ts +20 -0
  161. package/dist/core/search/bm25-index.js +123 -0
  162. package/dist/core/search/hybrid-search.d.ts +32 -0
  163. package/dist/core/search/hybrid-search.js +131 -0
  164. package/dist/core/search/query-cache.d.ts +18 -0
  165. package/dist/core/search/query-cache.js +47 -0
  166. package/dist/core/search/query-expansion.d.ts +19 -0
  167. package/dist/core/search/query-expansion.js +75 -0
  168. package/dist/core/search/reranker.d.ts +29 -0
  169. package/dist/core/search/reranker.js +122 -0
  170. package/dist/core/search/types.d.ts +154 -0
  171. package/dist/core/search/types.js +51 -0
  172. package/dist/core/semantic/tsgo-service.d.ts +67 -0
  173. package/dist/core/semantic/tsgo-service.js +355 -0
  174. package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
  175. package/dist/core/tree-sitter/parser-loader.js +71 -0
  176. package/dist/lib/memory-guard.d.ts +35 -0
  177. package/dist/lib/memory-guard.js +70 -0
  178. package/dist/lib/utils.d.ts +3 -0
  179. package/dist/lib/utils.js +6 -0
  180. package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
  181. package/dist/mcp/compatible-stdio-transport.js +209 -0
  182. package/dist/mcp/core/embedder.d.ts +24 -0
  183. package/dist/mcp/core/embedder.js +168 -0
  184. package/dist/mcp/core/lbug-adapter.d.ts +29 -0
  185. package/dist/mcp/core/lbug-adapter.js +330 -0
  186. package/dist/mcp/local/local-backend.d.ts +188 -0
  187. package/dist/mcp/local/local-backend.js +2759 -0
  188. package/dist/mcp/resources.d.ts +22 -0
  189. package/dist/mcp/resources.js +379 -0
  190. package/dist/mcp/server.d.ts +10 -0
  191. package/dist/mcp/server.js +217 -0
  192. package/dist/mcp/staleness.d.ts +10 -0
  193. package/dist/mcp/staleness.js +25 -0
  194. package/dist/mcp/tools.d.ts +21 -0
  195. package/dist/mcp/tools.js +202 -0
  196. package/dist/server/api.d.ts +5 -0
  197. package/dist/server/api.js +340 -0
  198. package/dist/server/mcp-http.d.ts +7 -0
  199. package/dist/server/mcp-http.js +95 -0
  200. package/dist/storage/git.d.ts +6 -0
  201. package/dist/storage/git.js +35 -0
  202. package/dist/storage/repo-manager.d.ts +87 -0
  203. package/dist/storage/repo-manager.js +249 -0
  204. package/dist/types/pipeline.d.ts +35 -0
  205. package/dist/types/pipeline.js +20 -0
  206. package/hooks/claude/code-mapper-hook.cjs +238 -0
  207. package/hooks/claude/pre-tool-use.sh +79 -0
  208. package/hooks/claude/session-start.sh +42 -0
  209. package/models/mlx-embedder.py +185 -0
  210. package/package.json +100 -0
  211. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  212. package/vendor/leiden/index.cjs +355 -0
  213. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,343 @@
1
+ // code-mapper/src/core/ingestion/mro-processor.ts
2
+ /**
3
+ * @file mro-processor.ts
4
+ * @description Walks the inheritance DAG, collects methods from ancestors via HAS_METHOD
5
+ * edges, detects method-name collisions, and emits OVERRIDES edges using language-specific
6
+ * resolution rules (C++ leftmost base, C#/Java class-over-interface, Python C3 linearization,
7
+ * Rust requires qualified syntax). OVERRIDES edge direction: Class -> winning ancestor Method
8
+ */
9
+ import { generateId } from '../../lib/utils.js';
10
+ import { SupportedLanguages } from '../../config/supported-languages.js';
11
+ /** Collect EXTENDS, IMPLEMENTS, and HAS_METHOD adjacency from the graph */
12
+ function buildAdjacency(graph) {
13
+ // childId -> parentIds[] (in declaration order)
14
+ const parentMap = new Map();
15
+ // classId -> methodIds[]
16
+ const methodMap = new Map();
17
+ // Track which edge type each parent link came from
18
+ const parentEdgeType = new Map();
19
+ graph.forEachRelationship((rel) => {
20
+ if (rel.type === 'EXTENDS' || rel.type === 'IMPLEMENTS') {
21
+ let parents = parentMap.get(rel.sourceId);
22
+ if (!parents) {
23
+ parents = [];
24
+ parentMap.set(rel.sourceId, parents);
25
+ }
26
+ parents.push(rel.targetId);
27
+ let edgeTypes = parentEdgeType.get(rel.sourceId);
28
+ if (!edgeTypes) {
29
+ edgeTypes = new Map();
30
+ parentEdgeType.set(rel.sourceId, edgeTypes);
31
+ }
32
+ edgeTypes.set(rel.targetId, rel.type);
33
+ }
34
+ if (rel.type === 'HAS_METHOD') {
35
+ let methods = methodMap.get(rel.sourceId);
36
+ if (!methods) {
37
+ methods = [];
38
+ methodMap.set(rel.sourceId, methods);
39
+ }
40
+ methods.push(rel.targetId);
41
+ }
42
+ });
43
+ return { parentMap, methodMap, parentEdgeType };
44
+ }
45
+ /** Gather all ancestor IDs in BFS order, excluding the class itself */
46
+ function gatherAncestors(classId, parentMap) {
47
+ const visited = new Set();
48
+ const order = [];
49
+ const queue = [...(parentMap.get(classId) ?? [])];
50
+ while (queue.length > 0) {
51
+ const id = queue.shift();
52
+ if (visited.has(id))
53
+ continue;
54
+ visited.add(id);
55
+ order.push(id);
56
+ const grandparents = parentMap.get(id);
57
+ if (grandparents) {
58
+ for (const gp of grandparents) {
59
+ if (!visited.has(gp))
60
+ queue.push(gp);
61
+ }
62
+ }
63
+ }
64
+ return order;
65
+ }
66
+ /**
67
+ * Compute C3 linearization for Python MRO
68
+ *
69
+ * Returns ancestor IDs in C3 order, or null if linearization fails (cycle/inconsistency)
70
+ */
71
+ function c3Linearize(classId, parentMap, cache, inProgress) {
72
+ if (cache.has(classId))
73
+ return cache.get(classId);
74
+ // Cycle detection: if we're already computing this class, the hierarchy is cyclic
75
+ const visiting = inProgress ?? new Set();
76
+ if (visiting.has(classId)) {
77
+ cache.set(classId, null);
78
+ return null;
79
+ }
80
+ visiting.add(classId);
81
+ const directParents = parentMap.get(classId);
82
+ if (!directParents || directParents.length === 0) {
83
+ visiting.delete(classId);
84
+ cache.set(classId, []);
85
+ return [];
86
+ }
87
+ // Compute linearization for each parent first
88
+ const parentLinearizations = [];
89
+ for (const pid of directParents) {
90
+ const pLin = c3Linearize(pid, parentMap, cache, visiting);
91
+ if (pLin === null) {
92
+ visiting.delete(classId);
93
+ cache.set(classId, null);
94
+ return null;
95
+ }
96
+ parentLinearizations.push([pid, ...pLin]);
97
+ }
98
+ // Add the direct parents list as the final sequence
99
+ const sequences = [...parentLinearizations, [...directParents]];
100
+ const result = [];
101
+ while (sequences.some(s => s.length > 0)) {
102
+ // Find a good head: one that doesn't appear in the tail of any other sequence
103
+ let head = null;
104
+ for (const seq of sequences) {
105
+ if (seq.length === 0)
106
+ continue;
107
+ const candidate = seq[0];
108
+ const inTail = sequences.some(other => other.length > 1 && other.indexOf(candidate, 1) !== -1);
109
+ if (!inTail) {
110
+ head = candidate;
111
+ break;
112
+ }
113
+ }
114
+ if (head === null) {
115
+ // Inconsistent hierarchy
116
+ visiting.delete(classId);
117
+ cache.set(classId, null);
118
+ return null;
119
+ }
120
+ result.push(head);
121
+ // Remove the chosen head from all sequences
122
+ for (const seq of sequences) {
123
+ if (seq.length > 0 && seq[0] === head) {
124
+ seq.shift();
125
+ }
126
+ }
127
+ }
128
+ visiting.delete(classId);
129
+ cache.set(classId, result);
130
+ return result;
131
+ }
132
+ /** Resolve by MRO order — first ancestor in linearized order wins */
133
+ function resolveByMroOrder(methodName, defs, mroOrder, reasonPrefix) {
134
+ for (const ancestorId of mroOrder) {
135
+ const match = defs.find(d => d.classId === ancestorId);
136
+ if (match) {
137
+ return {
138
+ resolvedTo: match.methodId,
139
+ reason: `${reasonPrefix}: ${match.className}::${methodName}`,
140
+ };
141
+ }
142
+ }
143
+ return { resolvedTo: defs[0].methodId, reason: `${reasonPrefix} fallback: first definition` };
144
+ }
145
+ function resolveCsharpJava(methodName, defs, parentEdgeTypes) {
146
+ const classDefs = [];
147
+ const interfaceDefs = [];
148
+ for (const def of defs) {
149
+ const edgeType = parentEdgeTypes?.get(def.classId);
150
+ if (edgeType === 'IMPLEMENTS') {
151
+ interfaceDefs.push(def);
152
+ }
153
+ else {
154
+ classDefs.push(def);
155
+ }
156
+ }
157
+ if (classDefs.length > 0) {
158
+ return {
159
+ resolvedTo: classDefs[0].methodId,
160
+ reason: `class method wins: ${classDefs[0].className}::${methodName}`,
161
+ };
162
+ }
163
+ if (interfaceDefs.length > 1) {
164
+ return {
165
+ resolvedTo: null,
166
+ reason: `ambiguous: ${methodName} defined in multiple interfaces: ${interfaceDefs.map(d => d.className).join(', ')}`,
167
+ };
168
+ }
169
+ if (interfaceDefs.length === 1) {
170
+ return {
171
+ resolvedTo: interfaceDefs[0].methodId,
172
+ reason: `single interface default: ${interfaceDefs[0].className}::${methodName}`,
173
+ };
174
+ }
175
+ return { resolvedTo: null, reason: 'no resolution found' };
176
+ }
177
+ export function computeMRO(graph) {
178
+ const { parentMap, methodMap, parentEdgeType } = buildAdjacency(graph);
179
+ const c3Cache = new Map();
180
+ const entries = [];
181
+ let overrideEdges = 0;
182
+ let ambiguityCount = 0;
183
+ // Process every class that has at least one parent
184
+ for (const [classId, directParents] of parentMap) {
185
+ if (directParents.length === 0)
186
+ continue;
187
+ const classNode = graph.getNode(classId);
188
+ if (!classNode)
189
+ continue;
190
+ const language = classNode.properties.language;
191
+ if (!language)
192
+ continue;
193
+ const className = classNode.properties.name;
194
+ // Compute linearized MRO depending on language
195
+ let mroOrder;
196
+ if (language === SupportedLanguages.Python) {
197
+ const c3Result = c3Linearize(classId, parentMap, c3Cache);
198
+ mroOrder = c3Result ?? gatherAncestors(classId, parentMap);
199
+ }
200
+ else {
201
+ mroOrder = gatherAncestors(classId, parentMap);
202
+ }
203
+ // Get the parent names for the MRO entry
204
+ const mroNames = mroOrder
205
+ .map(id => graph.getNode(id)?.properties.name)
206
+ .filter((n) => n !== undefined);
207
+ // Collect methods from all ancestors, grouped by method name
208
+ const methodsByName = new Map();
209
+ for (const ancestorId of mroOrder) {
210
+ const ancestorNode = graph.getNode(ancestorId);
211
+ if (!ancestorNode)
212
+ continue;
213
+ const methods = methodMap.get(ancestorId) ?? [];
214
+ for (const methodId of methods) {
215
+ const methodNode = graph.getNode(methodId);
216
+ if (!methodNode)
217
+ continue;
218
+ // Properties don't participate in MRO
219
+ if (methodNode.label === 'Property')
220
+ continue;
221
+ const methodName = methodNode.properties.name;
222
+ let defs = methodsByName.get(methodName);
223
+ if (!defs) {
224
+ defs = [];
225
+ methodsByName.set(methodName, defs);
226
+ }
227
+ // Avoid duplicates (same method seen via multiple paths)
228
+ if (!defs.some(d => d.methodId === methodId)) {
229
+ defs.push({
230
+ classId: ancestorId,
231
+ className: ancestorNode.properties.name,
232
+ methodId,
233
+ });
234
+ }
235
+ }
236
+ }
237
+ // Detect collisions: methods defined in 2+ different ancestors
238
+ const ambiguities = [];
239
+ // Compute transitive edge types once per class (only needed for C#/Java)
240
+ const needsEdgeTypes = language === SupportedLanguages.CSharp || language === SupportedLanguages.Java || language === SupportedLanguages.Kotlin;
241
+ const classEdgeTypes = needsEdgeTypes
242
+ ? buildTransitiveEdgeTypes(classId, parentMap, parentEdgeType)
243
+ : undefined;
244
+ for (const [methodName, defs] of methodsByName) {
245
+ if (defs.length < 2)
246
+ continue;
247
+ // Own method shadows inherited — no ambiguity
248
+ const ownMethods = methodMap.get(classId) ?? [];
249
+ const ownDefinesIt = ownMethods.some(mid => {
250
+ const mn = graph.getNode(mid);
251
+ return mn?.properties.name === methodName;
252
+ });
253
+ if (ownDefinesIt)
254
+ continue;
255
+ let resolution;
256
+ switch (language) {
257
+ case SupportedLanguages.CPlusPlus:
258
+ resolution = resolveByMroOrder(methodName, defs, mroOrder, 'C++ leftmost base');
259
+ break;
260
+ case SupportedLanguages.CSharp:
261
+ case SupportedLanguages.Java:
262
+ case SupportedLanguages.Kotlin:
263
+ resolution = resolveCsharpJava(methodName, defs, classEdgeTypes);
264
+ break;
265
+ case SupportedLanguages.Python:
266
+ resolution = resolveByMroOrder(methodName, defs, mroOrder, 'Python C3 MRO');
267
+ break;
268
+ case SupportedLanguages.Rust:
269
+ resolution = {
270
+ resolvedTo: null,
271
+ reason: `Rust requires qualified syntax: <Type as Trait>::${methodName}()`,
272
+ };
273
+ break;
274
+ default:
275
+ resolution = resolveByMroOrder(methodName, defs, mroOrder, 'first definition');
276
+ break;
277
+ }
278
+ const ambiguity = {
279
+ methodName,
280
+ definedIn: defs,
281
+ resolvedTo: resolution.resolvedTo,
282
+ reason: resolution.reason,
283
+ };
284
+ ambiguities.push(ambiguity);
285
+ if (resolution.resolvedTo === null) {
286
+ ambiguityCount++;
287
+ }
288
+ // Emit OVERRIDES edge if resolution found
289
+ if (resolution.resolvedTo !== null) {
290
+ graph.addRelationship({
291
+ id: generateId('OVERRIDES', `${classId}->${resolution.resolvedTo}`),
292
+ sourceId: classId,
293
+ targetId: resolution.resolvedTo,
294
+ type: 'OVERRIDES',
295
+ confidence: 1.0,
296
+ reason: resolution.reason,
297
+ });
298
+ overrideEdges++;
299
+ }
300
+ }
301
+ entries.push({
302
+ classId,
303
+ className,
304
+ language,
305
+ mro: mroNames,
306
+ ambiguities,
307
+ });
308
+ }
309
+ return { entries, overrideEdges, ambiguityCount };
310
+ }
311
+ /**
312
+ * Build transitive edge types for a class via BFS to all ancestors
313
+ *
314
+ * Known limitation: BFS first-reach heuristic can misclassify an interface as
315
+ * EXTENDS if reachable via a class chain before IMPLEMENTS in rare diamond hierarchies
316
+ */
317
+ function buildTransitiveEdgeTypes(classId, parentMap, parentEdgeType) {
318
+ const result = new Map();
319
+ const directEdges = parentEdgeType.get(classId);
320
+ if (!directEdges)
321
+ return result;
322
+ // BFS: propagate edge type from direct parents
323
+ const queue = [];
324
+ const directParents = parentMap.get(classId) ?? [];
325
+ for (const pid of directParents) {
326
+ const et = directEdges.get(pid) ?? 'EXTENDS';
327
+ if (!result.has(pid)) {
328
+ result.set(pid, et);
329
+ queue.push({ id: pid, edgeType: et });
330
+ }
331
+ }
332
+ while (queue.length > 0) {
333
+ const { id, edgeType } = queue.shift();
334
+ const grandparents = parentMap.get(id) ?? [];
335
+ for (const gp of grandparents) {
336
+ if (!result.has(gp)) {
337
+ result.set(gp, edgeType);
338
+ queue.push({ id: gp, edgeType });
339
+ }
340
+ }
341
+ }
342
+ return result;
343
+ }
@@ -0,0 +1,51 @@
1
+ /** @file named-binding-extraction.ts @description Extracts named import bindings from AST import nodes and walks re-export chains through NamedImportMap to resolve barrel file indirection */
2
+ import { SupportedLanguages } from '../../config/supported-languages.js';
3
+ import type { SymbolTable, SymbolDefinition } from './symbol-table.js';
4
+ import type { NamedImportMap } from './import-processor.js';
5
+ /**
6
+ * Walk a named-binding re-export chain through NamedImportMap
7
+ *
8
+ * Follows A->B->C chains until a definition is found (max depth 5)
9
+ * Returns null if the chain breaks (missing binding, circular reference, or depth exceeded)
10
+ *
11
+ * @param allDefs - Complete unfiltered lookupFuzzy(name) result; file-filtered subsets cause silent misses
12
+ */
13
+ export declare function walkBindingChain(name: string, currentFilePath: string, symbolTable: SymbolTable, namedImportMap: NamedImportMap, allDefs: SymbolDefinition[]): SymbolDefinition[] | null;
14
+ /**
15
+ * Extract named bindings from an import AST node
16
+ *
17
+ * Returns undefined for non-named imports (import *, default, side-effect)
18
+ * Example: `import { User, Repo as R }` -> [{local:'User', exported:'User'}, {local:'R', exported:'Repo'}]
19
+ */
20
+ export declare function extractNamedBindings(importNode: any, language: SupportedLanguages): {
21
+ local: string;
22
+ exported: string;
23
+ }[] | undefined;
24
+ export declare function extractTsNamedBindings(importNode: any): {
25
+ local: string;
26
+ exported: string;
27
+ }[] | undefined;
28
+ export declare function extractPythonNamedBindings(importNode: any): {
29
+ local: string;
30
+ exported: string;
31
+ }[] | undefined;
32
+ export declare function extractKotlinNamedBindings(importNode: any): {
33
+ local: string;
34
+ exported: string;
35
+ }[] | undefined;
36
+ export declare function extractRustNamedBindings(importNode: any): {
37
+ local: string;
38
+ exported: string;
39
+ }[] | undefined;
40
+ export declare function extractPhpNamedBindings(importNode: any): {
41
+ local: string;
42
+ exported: string;
43
+ }[] | undefined;
44
+ export declare function extractCsharpNamedBindings(importNode: any): {
45
+ local: string;
46
+ exported: string;
47
+ }[] | undefined;
48
+ export declare function extractJavaNamedBindings(importNode: any): {
49
+ local: string;
50
+ exported: string;
51
+ }[] | undefined;