MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / interfaceOverrideEdges

Function interfaceOverrideEdges

src/resolution/callback-synthesizer.ts:1043–1111  ·  view source on GitHub ↗
(queries: QueryBuilder, onYield: MaybeYield)

Source from the content-addressed store, hash-verified

1041}
1042
1043async function interfaceOverrideEdges(queries: QueryBuilder, onYield: MaybeYield): Promise<Edge[]> {
1044 let scanned255 = 0;
1045 const edges: Edge[] = [];
1046 const seen = new Set<string>();
1047 // Memoized: a popular base interface's method list is otherwise re-fetched
1048 // once per implementer (dubbo-style hub interfaces have hundreds), and the
1049 // memo only ever serves reads. Same rows, same order — byte-identical.
1050 const methodsMemo = new Map<string, Node[]>();
1051 const methodsOf = (classId: string): Node[] => {
1052 const hit = methodsMemo.get(classId);
1053 if (hit) return hit;
1054 const methods = queries
1055 .getOutgoingEdges(classId, ['contains'])
1056 .map((e) => queries.getNodeById(e.target))
1057 .filter((n): n is Node => !!n && n.kind === 'method');
1058 methodsMemo.set(classId, methods);
1059 return methods;
1060 };
1061 // Concrete-side kinds vary by language: `class` covers Java / Kotlin /
1062 // C# / TS / Swift-classes / Scala-classes; `struct` covers Swift value
1063 // types that conform to protocols. Iterate both.
1064 const concreteKinds = ['class', 'struct'] as const;
1065 for (const kind of concreteKinds) {
1066 for (const cls of queries.iterateNodesByKind(kind)) {
1067 if ((++scanned255 & 63) === 0) await onYield();
1068 // A class can only emit here if it HAS a supertype edge — check that
1069 // (one edge query) before materializing its methods: most classes in a
1070 // typical graph extend/implement nothing and skip in one hop.
1071 const sups = queries.getOutgoingEdges(cls.id, ['implements', 'extends']);
1072 if (sups.length === 0) continue;
1073 const implMethods = methodsOf(cls.id).filter((n) => IFACE_OVERRIDE_LANGS.has(n.language));
1074 if (implMethods.length === 0) continue;
1075 for (const sup of sups) {
1076 const base = queries.getNodeById(sup.target);
1077 if (!base || !IFACE_OVERRIDE_LANGS.has(base.language) || base.id === cls.id) continue;
1078 // Group impl methods by name to handle OVERLOADS: an interface `list()` and
1079 // `list(params)` are distinct nodes and a call may resolve to either, so
1080 // link every base overload → every same-name impl overload (keying by name
1081 // alone would drop all but one and miss the resolved overload).
1082 const implByName = new Map<string, Node[]>();
1083 for (const m of implMethods) {
1084 const arr = implByName.get(m.name);
1085 if (arr) arr.push(m); else implByName.set(m.name, [m]);
1086 }
1087 let added = 0;
1088 for (const bm of methodsOf(base.id)) {
1089 if (added >= MAX_CALLBACKS_PER_CHANNEL) break;
1090 for (const m of implByName.get(bm.name) ?? []) {
1091 if (added >= MAX_CALLBACKS_PER_CHANNEL) break;
1092 if (bm.id === m.id) continue;
1093 const key = `${bm.id}>${m.id}`;
1094 if (seen.has(key)) continue;
1095 seen.add(key);
1096 edges.push({
1097 source: bm.id,
1098 target: m.id,
1099 kind: 'calls',
1100 line: bm.startLine,

Callers 1

Calls 7

hasMethod · 0.80
methodsOfFunction · 0.70
iterateNodesByKindMethod · 0.65
getNodeByIdMethod · 0.65
getMethod · 0.65
getOutgoingEdgesMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected