Skip to content

Commit 476ddaa

Browse files
author
Your Name
committed
fix(store): deduplicate entry points + add [module] prefix to process labels
Two process detection improvements: 1. Deduplicate entry points after Route resolution (step 1c). Route resolution (step 1b) resolves each Route to ALL functions in the handler file. When N routes point to the same file with M functions, each function appeared N times in the entry point list. The BFS loop then generated N identical processes per entry point. Fix: O(n^2) dedup pass over ep_ids[] after Route resolution, before BFS. Compacts the array in-place, frees duplicate name strings. 2. Add [module] prefix to process labels for navigability. Labels were just entry -> terminal which is useless for finding the right flow among 50+ processes. Now derives the parent directory from the entry point file_path and prepends it as a module tag. Before: funcA -> funcZ After: [controllers] funcA -> funcZ Tested on multiple repos with significant dedup ratios. Requires full reindex to regenerate process tables.
1 parent 2997cdb commit 476ddaa

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

src/store/store.c

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4768,6 +4768,34 @@ int cbm_store_detect_processes(cbm_store_t *s, const char *project, int max_proc
47684768
}
47694769
}
47704770

4771+
/* 1c. Deduplicate entry points.
4772+
* Route resolution (1b) adds ALL functions from a handler file for EACH Route
4773+
* that maps to it. If 8 Routes → same file with 5 functions, each function
4774+
* appears 8 times. Remove duplicates by ep_id to avoid 8x duplicate processes. */
4775+
{
4776+
int deduped = 0;
4777+
for (int i = 0; i < ep_count; i++) {
4778+
bool dup = false;
4779+
for (int j = 0; j < deduped; j++) {
4780+
if (ep_ids[j] == ep_ids[i]) { dup = true; break; }
4781+
}
4782+
if (!dup) {
4783+
/* Keep this entry — compact it into position [deduped] */
4784+
if (deduped != i) {
4785+
ep_ids[deduped] = ep_ids[i];
4786+
ep_names[deduped] = ep_names[i];
4787+
ep_names[i] = NULL; /* prevent double-free in cleanup */
4788+
}
4789+
deduped++;
4790+
} else {
4791+
/* Duplicate — free the name string */
4792+
free(ep_names[i]);
4793+
ep_names[i] = NULL;
4794+
}
4795+
}
4796+
ep_count = deduped;
4797+
}
4798+
47714799
/* 2. Load nodes + CALLS edges for Louvain */
47724800
const char *nsql = "SELECT id FROM nodes WHERE project=?1 "
47734801
"AND label IN ('Function','Method','Class','Interface')";
@@ -4964,9 +4992,45 @@ int cbm_store_detect_processes(cbm_store_t *s, const char *project, int max_proc
49644992
}
49654993
}
49664994

4967-
/* Label: "EntryPoint → Terminal" (UTF-8 arrow) */
4995+
/* Label: "[module] EntryPoint → Terminal" (UTF-8 arrow)
4996+
* Derive module from entry point's parent directory for navigability.
4997+
* "server/src/controllers/clients-controller.js" → "controllers" */
4998+
char module[128] = "";
4999+
{
5000+
const char *fp_sql = "SELECT file_path FROM nodes WHERE id=?1";
5001+
sqlite3_stmt *fp_stmt = NULL;
5002+
sqlite3_prepare_v2(s->db, fp_sql, -1, &fp_stmt, NULL);
5003+
if (fp_stmt) {
5004+
sqlite3_bind_int64(fp_stmt, 1, ep_ids[ei]);
5005+
if (sqlite3_step(fp_stmt) == SQLITE_ROW) {
5006+
const char *fp = (const char *)sqlite3_column_text(fp_stmt, 0);
5007+
if (fp) {
5008+
/* Find the parent directory name (second-to-last path segment) */
5009+
const char *last_slash = strrchr(fp, '/');
5010+
if (last_slash && last_slash > fp) {
5011+
const char *seg_start = last_slash - 1;
5012+
while (seg_start > fp && *seg_start != '/') seg_start--;
5013+
if (*seg_start == '/') seg_start++;
5014+
int mlen = (int)(last_slash - seg_start);
5015+
if (mlen > 0 && mlen < (int)sizeof(module)) {
5016+
memcpy(module, seg_start, (size_t)mlen);
5017+
module[mlen] = '\0';
5018+
}
5019+
}
5020+
}
5021+
}
5022+
sqlite3_finalize(fp_stmt);
5023+
}
5024+
}
5025+
49685026
char label[512];
4969-
snprintf(label, sizeof(label), "%s \xe2\x86\x92 %s", ep_names[ei], terminal_name);
5027+
if (module[0]) {
5028+
snprintf(label, sizeof(label), "[%s] %s \xe2\x86\x92 %s",
5029+
module, ep_names[ei], terminal_name);
5030+
} else {
5031+
snprintf(label, sizeof(label), "%s \xe2\x86\x92 %s",
5032+
ep_names[ei], terminal_name);
5033+
}
49705034

49715035
if (ins_proc) {
49725036
sqlite3_reset(ins_proc);

0 commit comments

Comments
 (0)