MCPcopy Index your code
hub / github.com/PatrickSys/codebase-context / computeImpactCandidates

Function computeImpactCandidates

src/tools/search-codebase.ts:426–484  ·  view source on GitHub ↗
(resultPaths: string[])

Source from the content-addressed store, hash-verified

424 // Impact breadth estimate from the import graph (used for risk assessment).
425 // 2-hop: direct importers (hop 1) + importers of importers (hop 2).
426 function computeImpactCandidates(resultPaths: string[]): ImpactCandidate[] {
427 const allImports = getImportsGraph();
428 if (!allImports) return [];
429
430 const importDetails = getImportDetailsGraph();
431
432 const reverseImportsLocal = new Map<string, string[]>();
433 for (const [file, deps] of Object.entries<string[]>(allImports)) {
434 for (const dep of deps) {
435 if (!reverseImportsLocal.has(dep)) reverseImportsLocal.set(dep, []);
436 reverseImportsLocal.get(dep)!.push(file);
437 }
438 }
439
440 const targets = resultPaths.map((rp) => normalizeGraphPath(rp));
441
442 const candidates = new Map<string, ImpactCandidate>();
443
444 const addCandidate = (file: string, hop: 1 | 2, line?: number): void => {
445 const existing = candidates.get(file);
446 if (existing) {
447 if (existing.hop <= hop) return;
448 }
449 candidates.set(file, { file, hop, ...(line ? { line } : {}) });
450 };
451
452 const collectImporters = (
453 target: string
454 ): Array<{ importer: string; detail: ImportEdgeDetail | null }> => {
455 const matches: Array<{ importer: string; detail: ImportEdgeDetail | null }> = [];
456 for (const [dep, importers] of reverseImportsLocal) {
457 if (!pathsMatch(dep, target)) continue;
458 for (const importer of importers) {
459 matches.push({ importer, detail: findImportDetail(importDetails, importer, dep) });
460 }
461 }
462 return matches;
463 };
464
465 // Hop 1
466 const hop1Files: string[] = [];
467 for (const target of targets) {
468 for (const { importer, detail } of collectImporters(target)) {
469 addCandidate(importer, 1, detail?.line);
470 }
471 }
472 for (const candidate of candidates.values()) {
473 if (candidate.hop === 1) hop1Files.push(candidate.file);
474 }
475
476 // Hop 2
477 for (const mid of hop1Files) {
478 for (const { importer, detail } of collectImporters(mid)) {
479 addCandidate(importer, 2, detail?.line);
480 }
481 }
482
483 return Array.from(candidates.values()).slice(0, 20);

Callers 1

handleFunction · 0.85

Calls 8

getImportsGraphFunction · 0.85
getImportDetailsGraphFunction · 0.85
normalizeGraphPathFunction · 0.85
collectImportersFunction · 0.85
addCandidateFunction · 0.85
hasMethod · 0.80
setMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected