gitnexus 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -214
- package/dist/cli/ai-context.d.ts +1 -2
- package/dist/cli/ai-context.js +90 -117
- package/dist/cli/analyze.d.ts +0 -2
- package/dist/cli/analyze.js +2 -20
- package/dist/cli/index.js +25 -17
- package/dist/cli/setup.js +19 -17
- package/dist/core/augmentation/engine.js +20 -20
- package/dist/core/embeddings/embedding-pipeline.js +26 -26
- package/dist/core/graph/types.d.ts +2 -5
- package/dist/core/ingestion/ast-cache.js +2 -3
- package/dist/core/ingestion/call-processor.d.ts +5 -5
- package/dist/core/ingestion/call-processor.js +258 -173
- package/dist/core/ingestion/cluster-enricher.js +16 -16
- package/dist/core/ingestion/entry-point-scoring.d.ts +1 -2
- package/dist/core/ingestion/entry-point-scoring.js +22 -81
- package/dist/core/ingestion/framework-detection.d.ts +1 -5
- package/dist/core/ingestion/framework-detection.js +8 -39
- package/dist/core/ingestion/heritage-processor.d.ts +4 -13
- package/dist/core/ingestion/heritage-processor.js +28 -92
- package/dist/core/ingestion/import-processor.d.ts +19 -17
- package/dist/core/ingestion/import-processor.js +695 -170
- package/dist/core/ingestion/parsing-processor.d.ts +10 -1
- package/dist/core/ingestion/parsing-processor.js +177 -41
- package/dist/core/ingestion/pipeline.js +26 -49
- package/dist/core/ingestion/process-processor.js +1 -2
- package/dist/core/ingestion/symbol-table.d.ts +1 -12
- package/dist/core/ingestion/symbol-table.js +12 -19
- package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
- package/dist/core/ingestion/tree-sitter-queries.js +485 -590
- package/dist/core/ingestion/utils.d.ts +0 -67
- package/dist/core/ingestion/utils.js +9 -692
- package/dist/core/ingestion/workers/parse-worker.d.ts +3 -20
- package/dist/core/ingestion/workers/parse-worker.js +345 -84
- package/dist/core/ingestion/workers/worker-pool.js +0 -8
- package/dist/core/kuzu/csv-generator.js +3 -19
- package/dist/core/kuzu/kuzu-adapter.js +19 -14
- package/dist/core/kuzu/schema.d.ts +3 -3
- package/dist/core/kuzu/schema.js +288 -303
- package/dist/core/search/bm25-index.js +6 -7
- package/dist/core/search/hybrid-search.js +3 -3
- package/dist/core/wiki/diagrams.d.ts +27 -0
- package/dist/core/wiki/diagrams.js +163 -0
- package/dist/core/wiki/generator.d.ts +50 -2
- package/dist/core/wiki/generator.js +548 -49
- package/dist/core/wiki/graph-queries.d.ts +42 -0
- package/dist/core/wiki/graph-queries.js +276 -97
- package/dist/core/wiki/html-viewer.js +192 -192
- package/dist/core/wiki/llm-client.js +73 -11
- package/dist/core/wiki/prompts.d.ts +52 -8
- package/dist/core/wiki/prompts.js +200 -86
- package/dist/mcp/core/kuzu-adapter.d.ts +3 -1
- package/dist/mcp/core/kuzu-adapter.js +44 -13
- package/dist/mcp/local/local-backend.js +128 -128
- package/dist/mcp/resources.js +42 -42
- package/dist/mcp/server.js +19 -18
- package/dist/mcp/tools.js +104 -103
- package/hooks/claude/gitnexus-hook.cjs +155 -238
- package/hooks/claude/pre-tool-use.sh +79 -79
- package/hooks/claude/session-start.sh +42 -42
- package/package.json +96 -96
- package/scripts/patch-tree-sitter-swift.cjs +74 -74
- package/skills/gitnexus-cli.md +82 -82
- package/skills/gitnexus-debugging.md +89 -89
- package/skills/gitnexus-exploring.md +78 -78
- package/skills/gitnexus-guide.md +64 -64
- package/skills/gitnexus-impact-analysis.md +97 -97
- package/skills/gitnexus-pr-review.md +163 -163
- package/skills/gitnexus-refactoring.md +121 -121
- package/vendor/leiden/index.cjs +355 -355
- package/vendor/leiden/utils.cjs +392 -392
- package/dist/cli/lazy-action.d.ts +0 -6
- package/dist/cli/lazy-action.js +0 -18
- package/dist/cli/skill-gen.d.ts +0 -26
- package/dist/cli/skill-gen.js +0 -549
- package/dist/core/ingestion/constants.d.ts +0 -16
- package/dist/core/ingestion/constants.js +0 -16
- package/dist/core/ingestion/export-detection.d.ts +0 -18
- package/dist/core/ingestion/export-detection.js +0 -230
- package/dist/core/ingestion/language-config.d.ts +0 -46
- package/dist/core/ingestion/language-config.js +0 -167
- package/dist/core/ingestion/mro-processor.d.ts +0 -45
- package/dist/core/ingestion/mro-processor.js +0 -369
- package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
- package/dist/core/ingestion/named-binding-extraction.js +0 -363
- package/dist/core/ingestion/resolvers/csharp.d.ts +0 -22
- package/dist/core/ingestion/resolvers/csharp.js +0 -109
- package/dist/core/ingestion/resolvers/go.d.ts +0 -19
- package/dist/core/ingestion/resolvers/go.js +0 -42
- package/dist/core/ingestion/resolvers/index.d.ts +0 -16
- package/dist/core/ingestion/resolvers/index.js +0 -11
- package/dist/core/ingestion/resolvers/jvm.d.ts +0 -23
- package/dist/core/ingestion/resolvers/jvm.js +0 -87
- package/dist/core/ingestion/resolvers/php.d.ts +0 -15
- package/dist/core/ingestion/resolvers/php.js +0 -35
- package/dist/core/ingestion/resolvers/rust.d.ts +0 -15
- package/dist/core/ingestion/resolvers/rust.js +0 -73
- package/dist/core/ingestion/resolvers/standard.d.ts +0 -28
- package/dist/core/ingestion/resolvers/standard.js +0 -145
- package/dist/core/ingestion/resolvers/utils.d.ts +0 -33
- package/dist/core/ingestion/resolvers/utils.js +0 -120
- package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
- package/dist/core/ingestion/symbol-resolver.js +0 -83
- package/dist/core/ingestion/type-env.d.ts +0 -27
- package/dist/core/ingestion/type-env.js +0 -86
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/c-cpp.js +0 -60
- package/dist/core/ingestion/type-extractors/csharp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/csharp.js +0 -89
- package/dist/core/ingestion/type-extractors/go.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/go.js +0 -105
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -21
- package/dist/core/ingestion/type-extractors/index.js +0 -29
- package/dist/core/ingestion/type-extractors/jvm.d.ts +0 -3
- package/dist/core/ingestion/type-extractors/jvm.js +0 -121
- package/dist/core/ingestion/type-extractors/php.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/php.js +0 -31
- package/dist/core/ingestion/type-extractors/python.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/python.js +0 -41
- package/dist/core/ingestion/type-extractors/rust.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/rust.js +0 -39
- package/dist/core/ingestion/type-extractors/shared.d.ts +0 -17
- package/dist/core/ingestion/type-extractors/shared.js +0 -97
- package/dist/core/ingestion/type-extractors/swift.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/swift.js +0 -43
- package/dist/core/ingestion/type-extractors/types.d.ts +0 -14
- package/dist/core/ingestion/type-extractors/types.js +0 -1
- package/dist/core/ingestion/type-extractors/typescript.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/typescript.js +0 -46
- package/dist/mcp/compatible-stdio-transport.d.ts +0 -25
- package/dist/mcp/compatible-stdio-transport.js +0 -200
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MRO (Method Resolution Order) Processor
|
|
3
|
-
*
|
|
4
|
-
* Walks the inheritance DAG (EXTENDS/IMPLEMENTS edges), collects methods from
|
|
5
|
-
* each ancestor via HAS_METHOD edges, detects method-name collisions across
|
|
6
|
-
* parents, and applies language-specific resolution rules to emit OVERRIDES edges.
|
|
7
|
-
*
|
|
8
|
-
* Language-specific rules:
|
|
9
|
-
* - C++: leftmost base class in declaration order wins
|
|
10
|
-
* - C#/Java: class method wins over interface default; multiple interface
|
|
11
|
-
* methods with same name are ambiguous (null resolution)
|
|
12
|
-
* - Python: C3 linearization determines MRO; first in linearized order wins
|
|
13
|
-
* - Rust: no auto-resolution — requires qualified syntax, resolvedTo = null
|
|
14
|
-
* - Default: single inheritance — first definition wins
|
|
15
|
-
*
|
|
16
|
-
* OVERRIDES edge direction: Class → Method (not Method → Method).
|
|
17
|
-
* The source is the child class that inherits conflicting methods,
|
|
18
|
-
* the target is the winning ancestor method node.
|
|
19
|
-
* Cypher: MATCH (c:Class)-[r:CodeRelation {type: 'OVERRIDES'}]->(m:Method)
|
|
20
|
-
*/
|
|
21
|
-
import { generateId } from '../../lib/utils.js';
|
|
22
|
-
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Internal helpers
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
/** Collect EXTENDS, IMPLEMENTS, and HAS_METHOD adjacency from the graph. */
|
|
27
|
-
function buildAdjacency(graph) {
|
|
28
|
-
// parentMap: childId → parentIds[] (in insertion / declaration order)
|
|
29
|
-
const parentMap = new Map();
|
|
30
|
-
// methodMap: classId → methodIds[]
|
|
31
|
-
const methodMap = new Map();
|
|
32
|
-
// Track which edge type each parent link came from
|
|
33
|
-
const parentEdgeType = new Map();
|
|
34
|
-
graph.forEachRelationship((rel) => {
|
|
35
|
-
if (rel.type === 'EXTENDS' || rel.type === 'IMPLEMENTS') {
|
|
36
|
-
let parents = parentMap.get(rel.sourceId);
|
|
37
|
-
if (!parents) {
|
|
38
|
-
parents = [];
|
|
39
|
-
parentMap.set(rel.sourceId, parents);
|
|
40
|
-
}
|
|
41
|
-
parents.push(rel.targetId);
|
|
42
|
-
let edgeTypes = parentEdgeType.get(rel.sourceId);
|
|
43
|
-
if (!edgeTypes) {
|
|
44
|
-
edgeTypes = new Map();
|
|
45
|
-
parentEdgeType.set(rel.sourceId, edgeTypes);
|
|
46
|
-
}
|
|
47
|
-
edgeTypes.set(rel.targetId, rel.type);
|
|
48
|
-
}
|
|
49
|
-
if (rel.type === 'HAS_METHOD') {
|
|
50
|
-
let methods = methodMap.get(rel.sourceId);
|
|
51
|
-
if (!methods) {
|
|
52
|
-
methods = [];
|
|
53
|
-
methodMap.set(rel.sourceId, methods);
|
|
54
|
-
}
|
|
55
|
-
methods.push(rel.targetId);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
return { parentMap, methodMap, parentEdgeType };
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Gather all ancestor IDs in BFS / topological order.
|
|
62
|
-
* Returns the linearized list of ancestor IDs (excluding the class itself).
|
|
63
|
-
*/
|
|
64
|
-
function gatherAncestors(classId, parentMap) {
|
|
65
|
-
const visited = new Set();
|
|
66
|
-
const order = [];
|
|
67
|
-
const queue = [...(parentMap.get(classId) ?? [])];
|
|
68
|
-
while (queue.length > 0) {
|
|
69
|
-
const id = queue.shift();
|
|
70
|
-
if (visited.has(id))
|
|
71
|
-
continue;
|
|
72
|
-
visited.add(id);
|
|
73
|
-
order.push(id);
|
|
74
|
-
const grandparents = parentMap.get(id);
|
|
75
|
-
if (grandparents) {
|
|
76
|
-
for (const gp of grandparents) {
|
|
77
|
-
if (!visited.has(gp))
|
|
78
|
-
queue.push(gp);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return order;
|
|
83
|
-
}
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
// C3 linearization (Python MRO)
|
|
86
|
-
// ---------------------------------------------------------------------------
|
|
87
|
-
/**
|
|
88
|
-
* Compute C3 linearization for a class given a parentMap.
|
|
89
|
-
* Returns an array of ancestor IDs in C3 order (excluding the class itself),
|
|
90
|
-
* or null if linearization fails (inconsistent or cyclic hierarchy).
|
|
91
|
-
*/
|
|
92
|
-
function c3Linearize(classId, parentMap, cache, inProgress) {
|
|
93
|
-
if (cache.has(classId))
|
|
94
|
-
return cache.get(classId);
|
|
95
|
-
// Cycle detection: if we're already computing this class, the hierarchy is cyclic
|
|
96
|
-
const visiting = inProgress ?? new Set();
|
|
97
|
-
if (visiting.has(classId)) {
|
|
98
|
-
cache.set(classId, null);
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
visiting.add(classId);
|
|
102
|
-
const directParents = parentMap.get(classId);
|
|
103
|
-
if (!directParents || directParents.length === 0) {
|
|
104
|
-
visiting.delete(classId);
|
|
105
|
-
cache.set(classId, []);
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
// Compute linearization for each parent first
|
|
109
|
-
const parentLinearizations = [];
|
|
110
|
-
for (const pid of directParents) {
|
|
111
|
-
const pLin = c3Linearize(pid, parentMap, cache, visiting);
|
|
112
|
-
if (pLin === null) {
|
|
113
|
-
visiting.delete(classId);
|
|
114
|
-
cache.set(classId, null);
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
parentLinearizations.push([pid, ...pLin]);
|
|
118
|
-
}
|
|
119
|
-
// Add the direct parents list as the final sequence
|
|
120
|
-
const sequences = [...parentLinearizations, [...directParents]];
|
|
121
|
-
const result = [];
|
|
122
|
-
while (sequences.some(s => s.length > 0)) {
|
|
123
|
-
// Find a good head: one that doesn't appear in the tail of any other sequence
|
|
124
|
-
let head = null;
|
|
125
|
-
for (const seq of sequences) {
|
|
126
|
-
if (seq.length === 0)
|
|
127
|
-
continue;
|
|
128
|
-
const candidate = seq[0];
|
|
129
|
-
const inTail = sequences.some(other => other.length > 1 && other.indexOf(candidate, 1) !== -1);
|
|
130
|
-
if (!inTail) {
|
|
131
|
-
head = candidate;
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (head === null) {
|
|
136
|
-
// Inconsistent hierarchy
|
|
137
|
-
visiting.delete(classId);
|
|
138
|
-
cache.set(classId, null);
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
result.push(head);
|
|
142
|
-
// Remove the chosen head from all sequences
|
|
143
|
-
for (const seq of sequences) {
|
|
144
|
-
if (seq.length > 0 && seq[0] === head) {
|
|
145
|
-
seq.shift();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
visiting.delete(classId);
|
|
150
|
-
cache.set(classId, result);
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
/** Resolve by MRO order — first ancestor in linearized order wins. */
|
|
154
|
-
function resolveByMroOrder(methodName, defs, mroOrder, reasonPrefix) {
|
|
155
|
-
for (const ancestorId of mroOrder) {
|
|
156
|
-
const match = defs.find(d => d.classId === ancestorId);
|
|
157
|
-
if (match) {
|
|
158
|
-
return {
|
|
159
|
-
resolvedTo: match.methodId,
|
|
160
|
-
reason: `${reasonPrefix}: ${match.className}::${methodName}`,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return { resolvedTo: defs[0].methodId, reason: `${reasonPrefix} fallback: first definition` };
|
|
165
|
-
}
|
|
166
|
-
function resolveCsharpJava(methodName, defs, parentEdgeTypes) {
|
|
167
|
-
const classDefs = [];
|
|
168
|
-
const interfaceDefs = [];
|
|
169
|
-
for (const def of defs) {
|
|
170
|
-
const edgeType = parentEdgeTypes?.get(def.classId);
|
|
171
|
-
if (edgeType === 'IMPLEMENTS') {
|
|
172
|
-
interfaceDefs.push(def);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
classDefs.push(def);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (classDefs.length > 0) {
|
|
179
|
-
return {
|
|
180
|
-
resolvedTo: classDefs[0].methodId,
|
|
181
|
-
reason: `class method wins: ${classDefs[0].className}::${methodName}`,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
if (interfaceDefs.length > 1) {
|
|
185
|
-
return {
|
|
186
|
-
resolvedTo: null,
|
|
187
|
-
reason: `ambiguous: ${methodName} defined in multiple interfaces: ${interfaceDefs.map(d => d.className).join(', ')}`,
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
if (interfaceDefs.length === 1) {
|
|
191
|
-
return {
|
|
192
|
-
resolvedTo: interfaceDefs[0].methodId,
|
|
193
|
-
reason: `single interface default: ${interfaceDefs[0].className}::${methodName}`,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
return { resolvedTo: null, reason: 'no resolution found' };
|
|
197
|
-
}
|
|
198
|
-
// ---------------------------------------------------------------------------
|
|
199
|
-
// Main entry point
|
|
200
|
-
// ---------------------------------------------------------------------------
|
|
201
|
-
export function computeMRO(graph) {
|
|
202
|
-
const { parentMap, methodMap, parentEdgeType } = buildAdjacency(graph);
|
|
203
|
-
const c3Cache = new Map();
|
|
204
|
-
const entries = [];
|
|
205
|
-
let overrideEdges = 0;
|
|
206
|
-
let ambiguityCount = 0;
|
|
207
|
-
// Process every class that has at least one parent
|
|
208
|
-
for (const [classId, directParents] of parentMap) {
|
|
209
|
-
if (directParents.length === 0)
|
|
210
|
-
continue;
|
|
211
|
-
const classNode = graph.getNode(classId);
|
|
212
|
-
if (!classNode)
|
|
213
|
-
continue;
|
|
214
|
-
const language = classNode.properties.language;
|
|
215
|
-
if (!language)
|
|
216
|
-
continue;
|
|
217
|
-
const className = classNode.properties.name;
|
|
218
|
-
// Compute linearized MRO depending on language
|
|
219
|
-
let mroOrder;
|
|
220
|
-
if (language === SupportedLanguages.Python) {
|
|
221
|
-
const c3Result = c3Linearize(classId, parentMap, c3Cache);
|
|
222
|
-
mroOrder = c3Result ?? gatherAncestors(classId, parentMap);
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
mroOrder = gatherAncestors(classId, parentMap);
|
|
226
|
-
}
|
|
227
|
-
// Get the parent names for the MRO entry
|
|
228
|
-
const mroNames = mroOrder
|
|
229
|
-
.map(id => graph.getNode(id)?.properties.name)
|
|
230
|
-
.filter((n) => n !== undefined);
|
|
231
|
-
// Collect methods from all ancestors, grouped by method name
|
|
232
|
-
const methodsByName = new Map();
|
|
233
|
-
for (const ancestorId of mroOrder) {
|
|
234
|
-
const ancestorNode = graph.getNode(ancestorId);
|
|
235
|
-
if (!ancestorNode)
|
|
236
|
-
continue;
|
|
237
|
-
const methods = methodMap.get(ancestorId) ?? [];
|
|
238
|
-
for (const methodId of methods) {
|
|
239
|
-
const methodNode = graph.getNode(methodId);
|
|
240
|
-
if (!methodNode)
|
|
241
|
-
continue;
|
|
242
|
-
// Properties don't participate in method resolution order
|
|
243
|
-
if (methodNode.label === 'Property')
|
|
244
|
-
continue;
|
|
245
|
-
const methodName = methodNode.properties.name;
|
|
246
|
-
let defs = methodsByName.get(methodName);
|
|
247
|
-
if (!defs) {
|
|
248
|
-
defs = [];
|
|
249
|
-
methodsByName.set(methodName, defs);
|
|
250
|
-
}
|
|
251
|
-
// Avoid duplicates (same method seen via multiple paths)
|
|
252
|
-
if (!defs.some(d => d.methodId === methodId)) {
|
|
253
|
-
defs.push({
|
|
254
|
-
classId: ancestorId,
|
|
255
|
-
className: ancestorNode.properties.name,
|
|
256
|
-
methodId,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
// Detect collisions: methods defined in 2+ different ancestors
|
|
262
|
-
const ambiguities = [];
|
|
263
|
-
// Compute transitive edge types once per class (only needed for C#/Java)
|
|
264
|
-
const needsEdgeTypes = language === SupportedLanguages.CSharp || language === SupportedLanguages.Java || language === SupportedLanguages.Kotlin;
|
|
265
|
-
const classEdgeTypes = needsEdgeTypes
|
|
266
|
-
? buildTransitiveEdgeTypes(classId, parentMap, parentEdgeType)
|
|
267
|
-
: undefined;
|
|
268
|
-
for (const [methodName, defs] of methodsByName) {
|
|
269
|
-
if (defs.length < 2)
|
|
270
|
-
continue;
|
|
271
|
-
// Own method shadows inherited — no ambiguity
|
|
272
|
-
const ownMethods = methodMap.get(classId) ?? [];
|
|
273
|
-
const ownDefinesIt = ownMethods.some(mid => {
|
|
274
|
-
const mn = graph.getNode(mid);
|
|
275
|
-
return mn?.properties.name === methodName;
|
|
276
|
-
});
|
|
277
|
-
if (ownDefinesIt)
|
|
278
|
-
continue;
|
|
279
|
-
let resolution;
|
|
280
|
-
switch (language) {
|
|
281
|
-
case SupportedLanguages.CPlusPlus:
|
|
282
|
-
resolution = resolveByMroOrder(methodName, defs, mroOrder, 'C++ leftmost base');
|
|
283
|
-
break;
|
|
284
|
-
case SupportedLanguages.CSharp:
|
|
285
|
-
case SupportedLanguages.Java:
|
|
286
|
-
case SupportedLanguages.Kotlin:
|
|
287
|
-
resolution = resolveCsharpJava(methodName, defs, classEdgeTypes);
|
|
288
|
-
break;
|
|
289
|
-
case SupportedLanguages.Python:
|
|
290
|
-
resolution = resolveByMroOrder(methodName, defs, mroOrder, 'Python C3 MRO');
|
|
291
|
-
break;
|
|
292
|
-
case SupportedLanguages.Rust:
|
|
293
|
-
resolution = {
|
|
294
|
-
resolvedTo: null,
|
|
295
|
-
reason: `Rust requires qualified syntax: <Type as Trait>::${methodName}()`,
|
|
296
|
-
};
|
|
297
|
-
break;
|
|
298
|
-
default:
|
|
299
|
-
resolution = resolveByMroOrder(methodName, defs, mroOrder, 'first definition');
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
const ambiguity = {
|
|
303
|
-
methodName,
|
|
304
|
-
definedIn: defs,
|
|
305
|
-
resolvedTo: resolution.resolvedTo,
|
|
306
|
-
reason: resolution.reason,
|
|
307
|
-
};
|
|
308
|
-
ambiguities.push(ambiguity);
|
|
309
|
-
if (resolution.resolvedTo === null) {
|
|
310
|
-
ambiguityCount++;
|
|
311
|
-
}
|
|
312
|
-
// Emit OVERRIDES edge if resolution found
|
|
313
|
-
if (resolution.resolvedTo !== null) {
|
|
314
|
-
graph.addRelationship({
|
|
315
|
-
id: generateId('OVERRIDES', `${classId}->${resolution.resolvedTo}`),
|
|
316
|
-
sourceId: classId,
|
|
317
|
-
targetId: resolution.resolvedTo,
|
|
318
|
-
type: 'OVERRIDES',
|
|
319
|
-
confidence: 1.0,
|
|
320
|
-
reason: resolution.reason,
|
|
321
|
-
});
|
|
322
|
-
overrideEdges++;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
entries.push({
|
|
326
|
-
classId,
|
|
327
|
-
className,
|
|
328
|
-
language,
|
|
329
|
-
mro: mroNames,
|
|
330
|
-
ambiguities,
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
return { entries, overrideEdges, ambiguityCount };
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Build transitive edge types for a class using BFS from the class to all ancestors.
|
|
337
|
-
*
|
|
338
|
-
* Known limitation: BFS first-reach heuristic can misclassify an interface as
|
|
339
|
-
* EXTENDS if it's reachable via a class chain before being seen via IMPLEMENTS.
|
|
340
|
-
* E.g. if BaseClass also implements IFoo, IFoo may be classified as EXTENDS.
|
|
341
|
-
* This affects C#/Java/Kotlin conflict resolution in rare diamond hierarchies.
|
|
342
|
-
*/
|
|
343
|
-
function buildTransitiveEdgeTypes(classId, parentMap, parentEdgeType) {
|
|
344
|
-
const result = new Map();
|
|
345
|
-
const directEdges = parentEdgeType.get(classId);
|
|
346
|
-
if (!directEdges)
|
|
347
|
-
return result;
|
|
348
|
-
// BFS: propagate edge type from direct parents
|
|
349
|
-
const queue = [];
|
|
350
|
-
const directParents = parentMap.get(classId) ?? [];
|
|
351
|
-
for (const pid of directParents) {
|
|
352
|
-
const et = directEdges.get(pid) ?? 'EXTENDS';
|
|
353
|
-
if (!result.has(pid)) {
|
|
354
|
-
result.set(pid, et);
|
|
355
|
-
queue.push({ id: pid, edgeType: et });
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
while (queue.length > 0) {
|
|
359
|
-
const { id, edgeType } = queue.shift();
|
|
360
|
-
const grandparents = parentMap.get(id) ?? [];
|
|
361
|
-
for (const gp of grandparents) {
|
|
362
|
-
if (!result.has(gp)) {
|
|
363
|
-
result.set(gp, edgeType);
|
|
364
|
-
queue.push({ id: gp, edgeType });
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return result;
|
|
369
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
2
|
-
import type { SymbolTable, SymbolDefinition } from './symbol-table.js';
|
|
3
|
-
import type { NamedImportMap } from './import-processor.js';
|
|
4
|
-
/**
|
|
5
|
-
* Walk a named-binding re-export chain through NamedImportMap.
|
|
6
|
-
*
|
|
7
|
-
* When file A imports { User } from B, and B re-exports { User } from C,
|
|
8
|
-
* the NamedImportMap for A points to B, but B has no User definition.
|
|
9
|
-
* This function follows the chain: A→B→C until a definition is found.
|
|
10
|
-
*
|
|
11
|
-
* Returns the definitions found at the end of the chain, or null if the
|
|
12
|
-
* chain breaks (missing binding, circular reference, or depth exceeded).
|
|
13
|
-
* Max depth 5 to prevent infinite loops.
|
|
14
|
-
*
|
|
15
|
-
* @param allDefs Pre-computed `symbolTable.lookupFuzzy(name)` result — must be the
|
|
16
|
-
* complete unfiltered result. Passing a file-filtered subset will cause
|
|
17
|
-
* silent misses at depth=0 for non-aliased bindings.
|
|
18
|
-
*/
|
|
19
|
-
export declare function walkBindingChain(name: string, currentFilePath: string, symbolTable: SymbolTable, namedImportMap: NamedImportMap, allDefs: SymbolDefinition[]): SymbolDefinition[] | null;
|
|
20
|
-
/**
|
|
21
|
-
* Extract named bindings from an import AST node.
|
|
22
|
-
* Returns undefined if the import is not a named import (e.g., import * or default).
|
|
23
|
-
*
|
|
24
|
-
* TS: import { User, Repo as R } from './models'
|
|
25
|
-
* → [{local:'User', exported:'User'}, {local:'R', exported:'Repo'}]
|
|
26
|
-
*
|
|
27
|
-
* Python: from models import User, Repo as R
|
|
28
|
-
* → [{local:'User', exported:'User'}, {local:'R', exported:'Repo'}]
|
|
29
|
-
*/
|
|
30
|
-
export declare function extractNamedBindings(importNode: any, language: SupportedLanguages): {
|
|
31
|
-
local: string;
|
|
32
|
-
exported: string;
|
|
33
|
-
}[] | undefined;
|
|
34
|
-
export declare function extractTsNamedBindings(importNode: any): {
|
|
35
|
-
local: string;
|
|
36
|
-
exported: string;
|
|
37
|
-
}[] | undefined;
|
|
38
|
-
export declare function extractPythonNamedBindings(importNode: any): {
|
|
39
|
-
local: string;
|
|
40
|
-
exported: string;
|
|
41
|
-
}[] | undefined;
|
|
42
|
-
export declare function extractKotlinNamedBindings(importNode: any): {
|
|
43
|
-
local: string;
|
|
44
|
-
exported: string;
|
|
45
|
-
}[] | undefined;
|
|
46
|
-
export declare function extractRustNamedBindings(importNode: any): {
|
|
47
|
-
local: string;
|
|
48
|
-
exported: string;
|
|
49
|
-
}[] | undefined;
|
|
50
|
-
export declare function extractPhpNamedBindings(importNode: any): {
|
|
51
|
-
local: string;
|
|
52
|
-
exported: string;
|
|
53
|
-
}[] | undefined;
|
|
54
|
-
export declare function extractCsharpNamedBindings(importNode: any): {
|
|
55
|
-
local: string;
|
|
56
|
-
exported: string;
|
|
57
|
-
}[] | undefined;
|
|
58
|
-
export declare function extractJavaNamedBindings(importNode: any): {
|
|
59
|
-
local: string;
|
|
60
|
-
exported: string;
|
|
61
|
-
}[] | undefined;
|