MCPcopy
hub / github.com/giancarloerra/SocratiCode / buildCodeGraph

Function buildCodeGraph

src/services/code-graph.ts:644–802  ·  view source on GitHub ↗
(
  projectPath: string,
  extraExtensions?: Set<string>,
  progress?: GraphBuildProgress,
)

Source from the content-addressed store, hash-verified

642 * `symbolsByFile` / `outgoingCallsByFile` and persisted by `doRebuildGraph`.
643 */
644export async function buildCodeGraph(
645 projectPath: string,
646 extraExtensions?: Set<string>,
647 progress?: GraphBuildProgress,
648): Promise<CodeGraph & {
649 symbolsByFile: Map<string, SymbolNode[]>;
650 outgoingCallsByFile: Map<string, SymbolEdge[]>;
651}> {
652 ensureDynamicLanguages();
653
654 const resolvedPath = path.resolve(projectPath);
655 const aliases = await loadPathAliases(resolvedPath);
656 const files = await getGraphableFiles(resolvedPath, extraExtensions);
657 const fileSet = new Set(files);
658
659 if (progress) {
660 progress.filesTotal = files.length;
661 progress.phase = "analyzing imports";
662 }
663
664 logger.info("Building code graph", { projectPath: resolvedPath, fileCount: files.length });
665
666 const nodesMap = new Map<string, CodeGraphNode>();
667 const edges: CodeGraphEdge[] = [];
668 const symbolsByFile = new Map<string, SymbolNode[]>();
669 const outgoingCallsByFile = new Map<string, SymbolEdge[]>();
670
671 // Build a suffix lookup map for JVM multi-module projects (Java/Kotlin/Scala).
672 // This resolves FQNs like com.example.Foo when the class lives under a nested
673 // src/main/java/ tree (e.g. module-a/sub/src/main/java/com/example/Foo.java).
674 // Cost: O(n) once here, O(1) per import lookup (negligible vs. full AST parse).
675 const hasJvm = files.some((f) => {
676 const e = path.extname(f).toLowerCase();
677 return e === ".java" || e === ".kt" || e === ".kts" || e === ".scala";
678 });
679 const jvmSuffixMap = hasJvm ? buildJvmSuffixMap(fileSet) : undefined;
680
681 // Build a namespace lookup map for C# projects. Each `namespace X.Y.Z` block
682 // (or file-scoped `namespace X.Y.Z;`) is recorded so `using X.Y.Z;` directives
683 // can be resolved to the file(s) that contribute to that namespace. Without
684 // this, every C# import resolved to null and the file graph was empty.
685 const hasCs = files.some((f) => path.extname(f).toLowerCase() === ".cs");
686 const csNamespaceMap = hasCs ? buildCsNamespaceMap(fileSet, resolvedPath) : undefined;
687
688 // Build Go module-resolution info from go.mod (issue #45). Without this,
689 // every Go import resolved to null and Go projects produced an empty
690 // file graph. The info is null when go.mod is missing or unparseable;
691 // the resolver treats null as "no Go resolution available" and behaves
692 // exactly as it did before this PR for those cases.
693 const hasGo = files.some((f) => f.endsWith(".go"));
694 const goModuleInfo = hasGo ? buildGoModuleInfo(fileSet, resolvedPath) : undefined;
695
696 for (const relPath of files) {
697 const ext = path.extname(relPath).toLowerCase();
698 const lang = getAstGrepLang(ext);
699
700 // Files with no AST grammar (extra extensions) are included as leaf nodes
701 // so they can be targets of import edges from other files, but we skip

Callers 4

getOrBuildGraphFunction · 0.85
doRebuildGraphFunction · 0.85
code-graph.test.tsFile · 0.85

Calls 15

ensureDynamicLanguagesFunction · 0.85
loadPathAliasesFunction · 0.85
getGraphableFilesFunction · 0.85
buildJvmSuffixMapFunction · 0.85
buildCsNamespaceMapFunction · 0.85
buildGoModuleInfoFunction · 0.85
getAstGrepLangFunction · 0.85
getLanguageFromExtensionFunction · 0.85
extractImportsFunction · 0.85
extractSymbolsAndCallsFunction · 0.85
resolveImportFunction · 0.85

Tested by

no test coverage detected