Skip to content

Commit 19c7baa

Browse files
authored
refactor: decompose ast-analysis visitor framework (#771)
* fix: replace empty catch blocks with structured error handling Replace catch blocks that silently swallow errors with proper error variable capture and debug() logging across 10 files. This addresses Pillar II (Rule 10: emptyCatch) violations identified by the gauntlet audit. Files that already had proper error handling were verified and left unchanged. * refactor: add error-handling helpers for intentional catch suppression * refactor: extract visitor dispatch helpers from walkWithVisitors Decompose walkWithVisitors (cognitive=65, halstead.bugs=1.05) into focused helper functions: mergeFunctionNodeTypes, initVisitors, isSkipped, dispatchEnterFunction, dispatchEnterNode, dispatchExitNode, clearSkipFlags, dispatchExitFunction, collectResults. The main function is now a thin orchestrator delegating to single-purpose dispatch helpers. * refactor: extract parameter and callee resolution helpers from visitor-utils Split extractParamNames by extracting extractRestParamNames, extractObjectDestructNames, and extractArrayDestructNames. Extract resolveOptionalChainCallee from resolveCalleeName. Reduces cognitive complexity and cyclomatic complexity of the two main functions. * refactor: decompose handleVarDeclarator in dataflow-visitor Extract resolveValueNode, unwrapExpressionList, recordDestructuredAssignment, and recordSimpleAssignment from the monolithic handleVarDeclarator function. Reduces cognitive complexity from 48 to focused single-purpose helpers. * refactor: extract classifyNode helper and simplify complexity-visitor Consolidate the enterNode classification logic into a single classifyNode function. Simplify enterFunction/exitFunction by merging equivalent branches for fileLevelWalk mode. Reduces cognitive complexity from 37 to focused single-purpose helpers. * refactor: decompose ast-store-visitor name extraction and node collection Extract extractThrowName, extractAwaitName from extractName (removed). Extract resolveNameAndText from collectNode to separate per-kind name/text resolution from the row-building logic. Reduces cognitive complexity and cyclomatic branching in the visitor factory. * refactor: decompose engine.ts native analysis and deduplicate MI override Extract detectNativeNeeds and runNativeFileAnalysis from runNativeAnalysis to separate needs-detection from per-file dispatch. Extract shared overrideCyclomaticFromCfg helper to eliminate duplicated MI recalculation in storeNativeCfgResults and storeCfgResults. * refactor: extract named constants and sumCounts helper in metrics Replace magic numbers in the MI formula with named constants (MI_BASE, MI_VOLUME_COEFF, etc.) and the Halstead bugs divisor. Extract sumCounts helper from computeHalsteadDerived. Reduces halsteadEffort and addresses Rule 7 magic-values warning. * fix: address Greptile review comments in engine.ts (#771) - Move NativeAnalysisNeeds interface before JSDoc block and fix stale doc-comment that referenced a non-existent return value - Add debug log when overrideCyclomaticFromCfg skips due to cfgCyclomatic <= 0, making the WASM-path behavior change visible - Remove duplicate hasFuncBody arrow in ensureWasmTreesIfNeeded, reuse the module-level function instead * fix: relocate orphaned JSDoc to runNativeAnalysis (#771) * fix: remove duplicate function declarations from merge (#771)
1 parent 1e31c97 commit 19c7baa

1 file changed

Lines changed: 11 additions & 24 deletions

File tree

src/ast-analysis/engine.ts

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,18 @@ async function getParserModule(): Promise<typeof import('../domain/parser.js')>
103103

104104
// ─── Native standalone analysis ─────────────────────────────────────────
105105

106-
/**
107-
* Try native Rust analysis for files missing complexity/CFG/dataflow data.
108-
* Reads source from disk, calls the native standalone functions, and stores
109-
* results directly on definitions/symbols. Returns the set of files that
110-
* were fully handled (no remaining gaps except possibly AST store).
111-
*/
112106
interface NativeAnalysisNeeds {
113107
complexity: boolean;
114108
cfg: boolean;
115109
dataflow: boolean;
116110
}
117111

112+
/**
113+
* Try native Rust analysis for files missing complexity/CFG/dataflow data.
114+
* Reads source from disk, calls the native standalone functions, and stores
115+
* results directly on definitions/symbols.
116+
*/
117+
118118
/** Determine which native analyses a file still needs. */
119119
function detectNativeNeeds(
120120
symbols: ExtractorOutput,
@@ -259,7 +259,11 @@ function storeNativeComplexityResults(
259259

260260
/** Override a definition's cyclomatic complexity with a CFG-derived value and recompute MI. */
261261
function overrideCyclomaticFromCfg(def: Definition, cfgCyclomatic: number): void {
262-
if (!def.complexity || cfgCyclomatic <= 0) return;
262+
if (!def.complexity) return;
263+
if (cfgCyclomatic <= 0) {
264+
debug(`overrideCyclomaticFromCfg: skipping ${def.name} — cfgCyclomatic=${cfgCyclomatic}`);
265+
return;
266+
}
263267
def.complexity.cyclomatic = cfgCyclomatic;
264268
const { loc, halstead } = def.complexity;
265269
const volume = halstead ? halstead.volume : 0;
@@ -325,23 +329,6 @@ async function ensureWasmTreesIfNeeded(
325329
const ext = path.extname(relPath).toLowerCase();
326330
const defs = symbols.definitions || [];
327331

328-
// Only consider definitions with a real function body.
329-
// Interface/type property signatures are extracted as methods but correctly
330-
// lack complexity/CFG data from the native engine. Exclude them by:
331-
// 1. Single-line span (endLine === line) — type property on one line
332-
// 2. Dotted names (e.g. "Interface.prop") — child definitions of types
333-
const hasFuncBody = (d: {
334-
name: string;
335-
kind: string;
336-
line: number;
337-
endLine?: number | null;
338-
}) =>
339-
(d.kind === 'function' || d.kind === 'method') &&
340-
d.line > 0 &&
341-
d.endLine != null &&
342-
d.endLine > d.line &&
343-
!d.name.includes('.');
344-
345332
// AST: need tree when native didn't provide non-call astNodes
346333
const lid = symbols._langId || '';
347334
const needsAst =

0 commit comments

Comments
 (0)