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

Function goGrpcStubImplEdges

src/resolution/callback-synthesizer.ts:1138–1222  ·  view source on GitHub ↗

* Go gRPC stub → impl bridge. The protoc-gen-go-grpc codegen emits an * `UnimplementedXxxServer` struct in `*_grpc.pb.go` carrying one method * per service RPC; the real handler is a hand-written struct in another * file (`x/bank/keeper/msg_server.go::msgServer.Send` in cosmos-sdk). * Go's struc

(queries: QueryBuilder, onYield: MaybeYield)

Source from the content-addressed store, hash-verified

1136 * stub's source line is the wiring site shown in the trace trail.
1137 */
1138async function goGrpcStubImplEdges(queries: QueryBuilder, onYield: MaybeYield): Promise<Edge[]> {
1139 let scanned255 = 0;
1140 const edges: Edge[] = [];
1141 const seen = new Set<string>();
1142
1143 const STUB_RE = /^Unimplemented.*Server$/;
1144 // gRPC internal-helper methods that appear on every Unimplemented*Server;
1145 // not part of the service contract, so exclude when computing the RPC-method
1146 // signature used to match impls.
1147 const isInternalMarker = (n: string) => n.startsWith('mustEmbed') || n === 'testEmbeddedByValue';
1148
1149 // Methods directly contained by each Go struct, name-only. Built once.
1150 const methodNamesByStruct = new Map<string, Set<string>>();
1151 const methodNodesByStruct = new Map<string, Node[]>();
1152 const goStructs: Node[] = [];
1153 for (const s of queries.iterateNodesByKind('struct')) {
1154 if ((++scanned255 & 63) === 0) await onYield();
1155 if (s.language !== 'go') continue;
1156 goStructs.push(s);
1157 const ms = queries
1158 .getOutgoingEdges(s.id, ['contains'])
1159 .map((e) => queries.getNodeById(e.target))
1160 .filter((n): n is Node => !!n && n.kind === 'method');
1161 methodNodesByStruct.set(s.id, ms);
1162 methodNamesByStruct.set(s.id, new Set(ms.map((m) => m.name)));
1163 }
1164
1165 for (const stub of goStructs) {
1166 if (!STUB_RE.test(stub.name)) continue;
1167 // The stub MUST live in a generated file — that's what tells us this is
1168 // a protoc-emitted scaffold rather than someone naming a struct
1169 // `UnimplementedXxxServer` by hand. Without this gate we'd also bridge
1170 // such hand-written structs and create misleading edges.
1171 if (!isGeneratedFile(stub.filePath)) continue;
1172
1173 const stubMethods = (methodNodesByStruct.get(stub.id) ?? []).filter(
1174 (m) => !isInternalMarker(m.name),
1175 );
1176 if (stubMethods.length === 0) continue;
1177 const stubMethodNames = stubMethods.map((m) => m.name);
1178
1179 for (const cand of goStructs) {
1180 if (cand.id === stub.id) continue;
1181 // Skip generated-file candidates — they're siblings (msgClient,
1182 // UnsafeMsgServer, …) whose method sets coincidentally match.
1183 if (isGeneratedFile(cand.filePath)) continue;
1184
1185 const candNames = methodNamesByStruct.get(cand.id);
1186 if (!candNames) continue;
1187 // Subset: every RPC method must exist on the candidate by name.
1188 // Signature-level match would tighten this further, but name-match
1189 // alone already gives one-to-one pairing in real codebases because
1190 // gRPC method-name sets are highly distinctive (Send + MultiSend +
1191 // UpdateParams + SetSendEnabled is unique to bank's MsgServer).
1192 if (!stubMethodNames.every((n) => candNames.has(n))) continue;
1193
1194 const candMethods = methodNodesByStruct.get(cand.id) ?? [];
1195 let added = 0;

Callers 1

Calls 8

isGeneratedFileFunction · 0.90
isInternalMarkerFunction · 0.85
hasMethod · 0.80
iterateNodesByKindMethod · 0.65
getNodeByIdMethod · 0.65
getMethod · 0.65
getOutgoingEdgesMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected