Skip to content

Commit d249d40

Browse files
committed
merge: integrate origin/main into fix/flow-kind-regression
Resolve conflict in src/flow.js: combine CORE_SYMBOL_KINDS default (from this PR) with opts.kind passthrough (from main/PR #378). Impact: 42 functions changed, 65 affected
2 parents 5e12131 + 127d459 commit d249d40

12 files changed

Lines changed: 2634 additions & 2556 deletions

src/ast.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,12 @@ export function astQueryData(pattern, customDbPath, opts = {}) {
342342
ORDER BY a.file, a.line
343343
`;
344344

345-
const rows = db.prepare(sql).all(...params);
346-
db.close();
345+
let rows;
346+
try {
347+
rows = db.prepare(sql).all(...params);
348+
} finally {
349+
db.close();
350+
}
347351

348352
const results = rows.map((r) => ({
349353
kind: r.kind,

src/branch-compare.js

Lines changed: 79 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -83,55 +83,57 @@ function makeSymbolKey(kind, file, name) {
8383

8484
function loadSymbolsFromDb(dbPath, changedFiles, noTests) {
8585
const db = new Database(dbPath, { readonly: true });
86-
const symbols = new Map();
86+
try {
87+
const symbols = new Map();
8788

88-
if (changedFiles.length === 0) {
89-
db.close();
90-
return symbols;
91-
}
89+
if (changedFiles.length === 0) {
90+
return symbols;
91+
}
9292

93-
// Query nodes in changed files
94-
const placeholders = changedFiles.map(() => '?').join(', ');
95-
const rows = db
96-
.prepare(
97-
`SELECT n.id, n.name, n.kind, n.file, n.line, n.end_line
98-
FROM nodes n
99-
WHERE n.file IN (${placeholders})
100-
AND n.kind NOT IN ('file', 'directory')
101-
ORDER BY n.file, n.line`,
102-
)
103-
.all(...changedFiles);
104-
105-
// Compute fan_in and fan_out for each node
106-
const fanInStmt = db.prepare(
107-
`SELECT COUNT(*) AS cnt FROM edges WHERE target_id = ? AND kind = 'calls'`,
108-
);
109-
const fanOutStmt = db.prepare(
110-
`SELECT COUNT(*) AS cnt FROM edges WHERE source_id = ? AND kind = 'calls'`,
111-
);
93+
// Query nodes in changed files
94+
const placeholders = changedFiles.map(() => '?').join(', ');
95+
const rows = db
96+
.prepare(
97+
`SELECT n.id, n.name, n.kind, n.file, n.line, n.end_line
98+
FROM nodes n
99+
WHERE n.file IN (${placeholders})
100+
AND n.kind NOT IN ('file', 'directory')
101+
ORDER BY n.file, n.line`,
102+
)
103+
.all(...changedFiles);
104+
105+
// Compute fan_in and fan_out for each node
106+
const fanInStmt = db.prepare(
107+
`SELECT COUNT(*) AS cnt FROM edges WHERE target_id = ? AND kind = 'calls'`,
108+
);
109+
const fanOutStmt = db.prepare(
110+
`SELECT COUNT(*) AS cnt FROM edges WHERE source_id = ? AND kind = 'calls'`,
111+
);
112112

113-
for (const row of rows) {
114-
if (noTests && isTestFile(row.file)) continue;
115-
116-
const lineCount = row.end_line ? row.end_line - row.line + 1 : 0;
117-
const fanIn = fanInStmt.get(row.id).cnt;
118-
const fanOut = fanOutStmt.get(row.id).cnt;
119-
const key = makeSymbolKey(row.kind, row.file, row.name);
120-
121-
symbols.set(key, {
122-
id: row.id,
123-
name: row.name,
124-
kind: row.kind,
125-
file: row.file,
126-
line: row.line,
127-
lineCount,
128-
fanIn,
129-
fanOut,
130-
});
131-
}
113+
for (const row of rows) {
114+
if (noTests && isTestFile(row.file)) continue;
115+
116+
const lineCount = row.end_line ? row.end_line - row.line + 1 : 0;
117+
const fanIn = fanInStmt.get(row.id).cnt;
118+
const fanOut = fanOutStmt.get(row.id).cnt;
119+
const key = makeSymbolKey(row.kind, row.file, row.name);
120+
121+
symbols.set(key, {
122+
id: row.id,
123+
name: row.name,
124+
kind: row.kind,
125+
file: row.file,
126+
line: row.line,
127+
lineCount,
128+
fanIn,
129+
fanOut,
130+
});
131+
}
132132

133-
db.close();
134-
return symbols;
133+
return symbols;
134+
} finally {
135+
db.close();
136+
}
135137
}
136138

137139
// ─── Caller BFS ─────────────────────────────────────────────────────────
@@ -140,40 +142,43 @@ function loadCallersFromDb(dbPath, nodeIds, maxDepth, noTests) {
140142
if (nodeIds.length === 0) return [];
141143

142144
const db = new Database(dbPath, { readonly: true });
143-
const allCallers = new Set();
144-
145-
for (const startId of nodeIds) {
146-
const visited = new Set([startId]);
147-
let frontier = [startId];
148-
149-
for (let d = 1; d <= maxDepth; d++) {
150-
const nextFrontier = [];
151-
for (const fid of frontier) {
152-
const callers = db
153-
.prepare(
154-
`SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line
155-
FROM edges e JOIN nodes n ON e.source_id = n.id
156-
WHERE e.target_id = ? AND e.kind = 'calls'`,
157-
)
158-
.all(fid);
159-
160-
for (const c of callers) {
161-
if (!visited.has(c.id) && (!noTests || !isTestFile(c.file))) {
162-
visited.add(c.id);
163-
nextFrontier.push(c.id);
164-
allCallers.add(
165-
JSON.stringify({ name: c.name, kind: c.kind, file: c.file, line: c.line }),
166-
);
145+
try {
146+
const allCallers = new Set();
147+
148+
for (const startId of nodeIds) {
149+
const visited = new Set([startId]);
150+
let frontier = [startId];
151+
152+
for (let d = 1; d <= maxDepth; d++) {
153+
const nextFrontier = [];
154+
for (const fid of frontier) {
155+
const callers = db
156+
.prepare(
157+
`SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line
158+
FROM edges e JOIN nodes n ON e.source_id = n.id
159+
WHERE e.target_id = ? AND e.kind = 'calls'`,
160+
)
161+
.all(fid);
162+
163+
for (const c of callers) {
164+
if (!visited.has(c.id) && (!noTests || !isTestFile(c.file))) {
165+
visited.add(c.id);
166+
nextFrontier.push(c.id);
167+
allCallers.add(
168+
JSON.stringify({ name: c.name, kind: c.kind, file: c.file, line: c.line }),
169+
);
170+
}
167171
}
168172
}
173+
frontier = nextFrontier;
174+
if (frontier.length === 0) break;
169175
}
170-
frontier = nextFrontier;
171-
if (frontier.length === 0) break;
172176
}
173-
}
174177

175-
db.close();
176-
return [...allCallers].map((s) => JSON.parse(s));
178+
return [...allCallers].map((s) => JSON.parse(s));
179+
} finally {
180+
db.close();
181+
}
177182
}
178183

179184
// ─── Symbol Comparison ──────────────────────────────────────────────────

src/cfg.js

Lines changed: 63 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,72 +1029,73 @@ function findNodes(db, name, opts = {}) {
10291029
*/
10301030
export function cfgData(name, customDbPath, opts = {}) {
10311031
const db = openReadonlyOrFail(customDbPath);
1032-
const noTests = opts.noTests || false;
1033-
1034-
if (!hasCfgTables(db)) {
1035-
db.close();
1036-
return {
1037-
name,
1038-
results: [],
1039-
warning:
1040-
'No CFG data found. Rebuild with `codegraph build` (CFG is now included by default).',
1041-
};
1042-
}
1032+
try {
1033+
const noTests = opts.noTests || false;
1034+
1035+
if (!hasCfgTables(db)) {
1036+
return {
1037+
name,
1038+
results: [],
1039+
warning:
1040+
'No CFG data found. Rebuild with `codegraph build` (CFG is now included by default).',
1041+
};
1042+
}
10431043

1044-
const nodes = findNodes(db, name, { noTests, file: opts.file, kind: opts.kind });
1045-
if (nodes.length === 0) {
1046-
db.close();
1047-
return { name, results: [] };
1048-
}
1044+
const nodes = findNodes(db, name, { noTests, file: opts.file, kind: opts.kind });
1045+
if (nodes.length === 0) {
1046+
return { name, results: [] };
1047+
}
10491048

1050-
const blockStmt = db.prepare(
1051-
`SELECT id, block_index, block_type, start_line, end_line, label
1052-
FROM cfg_blocks WHERE function_node_id = ?
1053-
ORDER BY block_index`,
1054-
);
1055-
const edgeStmt = db.prepare(
1056-
`SELECT e.kind,
1057-
sb.block_index AS source_index, sb.block_type AS source_type,
1058-
tb.block_index AS target_index, tb.block_type AS target_type
1059-
FROM cfg_edges e
1060-
JOIN cfg_blocks sb ON e.source_block_id = sb.id
1061-
JOIN cfg_blocks tb ON e.target_block_id = tb.id
1062-
WHERE e.function_node_id = ?
1063-
ORDER BY sb.block_index, tb.block_index`,
1064-
);
1049+
const blockStmt = db.prepare(
1050+
`SELECT id, block_index, block_type, start_line, end_line, label
1051+
FROM cfg_blocks WHERE function_node_id = ?
1052+
ORDER BY block_index`,
1053+
);
1054+
const edgeStmt = db.prepare(
1055+
`SELECT e.kind,
1056+
sb.block_index AS source_index, sb.block_type AS source_type,
1057+
tb.block_index AS target_index, tb.block_type AS target_type
1058+
FROM cfg_edges e
1059+
JOIN cfg_blocks sb ON e.source_block_id = sb.id
1060+
JOIN cfg_blocks tb ON e.target_block_id = tb.id
1061+
WHERE e.function_node_id = ?
1062+
ORDER BY sb.block_index, tb.block_index`,
1063+
);
10651064

1066-
const results = nodes.map((node) => {
1067-
const cfgBlocks = blockStmt.all(node.id);
1068-
const cfgEdges = edgeStmt.all(node.id);
1069-
1070-
return {
1071-
name: node.name,
1072-
kind: node.kind,
1073-
file: node.file,
1074-
line: node.line,
1075-
blocks: cfgBlocks.map((b) => ({
1076-
index: b.block_index,
1077-
type: b.block_type,
1078-
startLine: b.start_line,
1079-
endLine: b.end_line,
1080-
label: b.label,
1081-
})),
1082-
edges: cfgEdges.map((e) => ({
1083-
source: e.source_index,
1084-
sourceType: e.source_type,
1085-
target: e.target_index,
1086-
targetType: e.target_type,
1087-
kind: e.kind,
1088-
})),
1089-
summary: {
1090-
blockCount: cfgBlocks.length,
1091-
edgeCount: cfgEdges.length,
1092-
},
1093-
};
1094-
});
1065+
const results = nodes.map((node) => {
1066+
const cfgBlocks = blockStmt.all(node.id);
1067+
const cfgEdges = edgeStmt.all(node.id);
1068+
1069+
return {
1070+
name: node.name,
1071+
kind: node.kind,
1072+
file: node.file,
1073+
line: node.line,
1074+
blocks: cfgBlocks.map((b) => ({
1075+
index: b.block_index,
1076+
type: b.block_type,
1077+
startLine: b.start_line,
1078+
endLine: b.end_line,
1079+
label: b.label,
1080+
})),
1081+
edges: cfgEdges.map((e) => ({
1082+
source: e.source_index,
1083+
sourceType: e.source_type,
1084+
target: e.target_index,
1085+
targetType: e.target_type,
1086+
kind: e.kind,
1087+
})),
1088+
summary: {
1089+
blockCount: cfgBlocks.length,
1090+
edgeCount: cfgEdges.length,
1091+
},
1092+
};
1093+
});
10951094

1096-
db.close();
1097-
return paginateResult({ name, results }, 'results', opts);
1095+
return paginateResult({ name, results }, 'results', opts);
1096+
} finally {
1097+
db.close();
1098+
}
10981099
}
10991100

11001101
// ─── Export Formats ─────────────────────────────────────────────────────

src/communities.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,15 @@ function getDirectory(filePath) {
9797
export function communitiesData(customDbPath, opts = {}) {
9898
const db = openReadonlyOrFail(customDbPath);
9999
const resolution = opts.resolution ?? 1.0;
100-
101-
const graph = buildGraphologyGraph(db, {
102-
functions: opts.functions,
103-
noTests: opts.noTests,
104-
});
105-
db.close();
100+
let graph;
101+
try {
102+
graph = buildGraphologyGraph(db, {
103+
functions: opts.functions,
104+
noTests: opts.noTests,
105+
});
106+
} finally {
107+
db.close();
108+
}
106109

107110
// Handle empty or trivial graphs
108111
if (graph.order === 0 || graph.size === 0) {

0 commit comments

Comments
 (0)