-
Notifications
You must be signed in to change notification settings - Fork 8
refactor: deduplicate BFS impact traversal and centralize config loading #463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d1dd922
2a51c29
6215e46
dd5e2e5
4fe685f
cc8bc26
404c2e9
f24b29b
5e5f356
05b0ba4
d6b80f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import { execFileSync } from 'node:child_process'; | |
| import fs from 'node:fs'; | ||
| import path from 'node:path'; | ||
| import { findDbPath, openReadonlyOrFail } from '../db/index.js'; | ||
| import { bfsTransitiveCallers } from '../domain/analysis/impact.js'; | ||
| import { findCycles } from '../domain/graph/cycles.js'; | ||
| import { loadConfig } from '../infrastructure/config.js'; | ||
| import { isTestFile } from '../infrastructure/test-filter.js'; | ||
|
|
@@ -96,31 +97,10 @@ export function checkMaxBlastRadius(db, changedRanges, threshold, noTests, maxDe | |
| } | ||
| if (!overlaps) continue; | ||
|
|
||
| // BFS transitive callers | ||
| const visited = new Set([def.id]); | ||
| let frontier = [def.id]; | ||
| let totalCallers = 0; | ||
| for (let d = 1; d <= maxDepth; d++) { | ||
| const nextFrontier = []; | ||
| for (const fid of frontier) { | ||
| const callers = db | ||
| .prepare( | ||
| `SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line | ||
| FROM edges e JOIN nodes n ON e.source_id = n.id | ||
| WHERE e.target_id = ? AND e.kind = 'calls'`, | ||
| ) | ||
| .all(fid); | ||
| for (const c of callers) { | ||
| if (!visited.has(c.id) && (!noTests || !isTestFile(c.file))) { | ||
| visited.add(c.id); | ||
| nextFrontier.push(c.id); | ||
| totalCallers++; | ||
| } | ||
| } | ||
| } | ||
| frontier = nextFrontier; | ||
| if (frontier.length === 0) break; | ||
| } | ||
| const { totalDependents: totalCallers } = bfsTransitiveCallers(db, def.id, { | ||
| noTests, | ||
| maxDepth, | ||
| }); | ||
|
|
||
| if (totalCallers > maxFound) maxFound = totalCallers; | ||
| if (totalCallers > threshold) { | ||
|
|
@@ -240,7 +220,10 @@ export function checkData(customDbPath, opts = {}) { | |
| const maxDepth = opts.depth || 3; | ||
|
|
||
| // Load config defaults for check predicates | ||
| const config = loadConfig(repoRoot); | ||
| // NOTE: opts.config is loaded from process.cwd() at startup (via CLI context), | ||
| // which may differ from the DB's parent repo root when --db points to an external | ||
| // project. This is an acceptable trade-off to avoid duplicate I/O on the hot path. | ||
| const config = opts.config || loadConfig(repoRoot); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Previously // old
const config = loadConfig(repoRoot); // repoRoot = dirname(dbPath)/..Now the CLI path passes The same observation applies to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a comment documenting the trade-off — opts.config is loaded from process.cwd() at startup, which may differ from the DB's parent repo root when --db points externally. Accepted trade-off to avoid duplicate I/O. |
||
| const checkConfig = config.check || {}; | ||
|
|
||
| // Resolve which predicates are enabled: CLI flags ?? config ?? built-in defaults | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSDoc
dbtype overly broad for an exported functionbfsTransitiveCallersis now part of the public API (export function). The JSDoc describesdbonly as{object} - Open SQLite database handle, but the function's body callsfindDistinctCallers(db, fid)from../../db/index.js, which relies oncachedStmt(aWeakMap-backed prepared-statement cache) and therefore requires a rawbetter-sqlite3handle — aRepositoryinstance would fail at runtime here.Tightening the type annotation and adding a note prevents future callers from accidentally passing a
Repository:Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 404c2e9 — tightened the JSDoc type from generic
objecttoimport(better-sqlite3).Databasewith a note that Repository instances are not accepted.