From 2b3696cbbbbd4113a3ccc0e8a39451f5b1afe10d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 19 Sep 2026 05:23:29 +0000 Subject: [PATCH] refactor: extract private addDetail helper in csharp/go/rust/python/jsLike analyzers Java's analyzer already had a private addDetail(increment, reason, line, column) helper to record a complexity detail and add its increment to the running total. The other five analyzers (C#, Go, Rust, Python, and the shared JS/TS analyzer) each repeated the same 7-line this.complexity += increment; this.details.push({...}) block inline at 8 call sites total, several duplicated 2x within the same file. Extracted the same addDetail() helper into each of those analyzers, matching Java's existing pattern, and replaced every inline occurrence with a single call. Pure refactor, no behavior change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../languages/csharpAnalyzer.ts | 28 +++++++++---- src/metricsAnalyzer/languages/goAnalyzer.ts | 37 +++++++++-------- .../languages/jsLikeAnalyzer.ts | 41 +++++++++++-------- .../languages/pythonAnalyzer.ts | 41 +++++++++++-------- src/metricsAnalyzer/languages/rustAnalyzer.ts | 27 ++++++++---- 5 files changed, 108 insertions(+), 66 deletions(-) diff --git a/src/metricsAnalyzer/languages/csharpAnalyzer.ts b/src/metricsAnalyzer/languages/csharpAnalyzer.ts index 3ca8acf..0ab38b1 100644 --- a/src/metricsAnalyzer/languages/csharpAnalyzer.ts +++ b/src/metricsAnalyzer/languages/csharpAnalyzer.ts @@ -464,16 +464,12 @@ export class CSharpMetricsAnalyzer { private visit(node: Parser.SyntaxNode): void { const increment = this.getComplexityIncrement(node); if (increment > 0) { - const reason = this.getComplexityReason(node); - this.complexity += increment; - - this.details.push({ + this.addDetail( increment, - reason, - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.getComplexityReason(node), + node.startPosition.row, + node.startPosition.column + ); } // Conditionally bump nesting, iterate children once, then restore. @@ -491,6 +487,20 @@ export class CSharpMetricsAnalyzer { if (isPreproc) { this.preprocessorDepth--; } } + /** + * Records a complexity-contributing detail and adds its increment to the running total. + */ + private addDetail(increment: number, reason: string, line: number, column: number): void { + this.complexity += increment; + this.details.push({ + increment, + reason, + line, + column, + nesting: this.nesting, + }); + } + /** * Calculates the complexity increment for a specific syntax node type. * diff --git a/src/metricsAnalyzer/languages/goAnalyzer.ts b/src/metricsAnalyzer/languages/goAnalyzer.ts index 71efad7..3cdef87 100644 --- a/src/metricsAnalyzer/languages/goAnalyzer.ts +++ b/src/metricsAnalyzer/languages/goAnalyzer.ts @@ -329,16 +329,12 @@ export class GoMetricsAnalyzer { private visit(node: Parser.SyntaxNode): void { const increment = this.getComplexityIncrement(node); if (increment > 0) { - const reason = this.getComplexityReason(node); - this.complexity += increment; - - this.details.push({ + this.addDetail( increment, - reason, - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.getComplexityReason(node), + node.startPosition.row, + node.startPosition.column + ); } // Conditionally bump nesting, iterate children once, then restore. @@ -366,6 +362,20 @@ export class GoMetricsAnalyzer { if (nests) { this.nesting--; } } + /** + * Records a complexity-contributing detail and adds its increment to the running total. + */ + private addDetail(increment: number, reason: string, line: number, column: number): void { + this.complexity += increment; + this.details.push({ + increment, + reason, + line, + column, + nesting: this.nesting, + }); + } + /** * Visits the alternative branch of a Go `if_statement` (the else / else-if part). * @@ -385,14 +395,7 @@ export class GoMetricsAnalyzer { const reason = isElseIf ? "else if clause" : "else clause"; // Flat +1 for else/else-if — no nesting penalty. - this.complexity += 1; - this.details.push({ - increment: 1, - reason, - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.addDetail(1, reason, node.startPosition.row, node.startPosition.column); if (isElseIf) { // else-if: visit the inner if_statement's children at the CURRENT nesting level diff --git a/src/metricsAnalyzer/languages/jsLikeAnalyzer.ts b/src/metricsAnalyzer/languages/jsLikeAnalyzer.ts index 5fc83cf..5ced871 100644 --- a/src/metricsAnalyzer/languages/jsLikeAnalyzer.ts +++ b/src/metricsAnalyzer/languages/jsLikeAnalyzer.ts @@ -327,14 +327,12 @@ export class JsLikeMetricsAnalyzer { if (!skipSelfIncrement) { const increment = this.getComplexityIncrement(node); if (increment > 0) { - this.details.push({ + this.addDetail( increment, - reason: this.getComplexityReason(node), - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); - this.complexity += increment; + this.getComplexityReason(node), + node.startPosition.row, + node.startPosition.column + ); } } @@ -350,15 +348,12 @@ export class JsLikeMetricsAnalyzer { // complexity inside the nested body (ternaries, loops, etc.) counts toward // the enclosing function rather than being silently discarded. if (this.isNestedFunction(child)) { - const increment = 1 + this.nesting; - this.complexity += increment; - this.details.push({ - increment, - reason: this.getFunctionReason(child.type), - line: child.startPosition.row, - column: child.startPosition.column, - nesting: this.nesting, - }); + this.addDetail( + 1 + this.nesting, + this.getFunctionReason(child.type), + child.startPosition.row, + child.startPosition.column + ); this.nesting++; for (let i = 0; i < child.childCount; i++) { this.analyzeNode(child.child(i)!); @@ -381,6 +376,20 @@ export class JsLikeMetricsAnalyzer { } } + /** + * Records a complexity-contributing detail and adds its increment to the running total. + */ + private addDetail(increment: number, reason: string, line: number, column: number): void { + this.complexity += increment; + this.details.push({ + increment, + reason, + line, + column, + nesting: this.nesting, + }); + } + /** * Checks if a node is a nested function definition. */ diff --git a/src/metricsAnalyzer/languages/pythonAnalyzer.ts b/src/metricsAnalyzer/languages/pythonAnalyzer.ts index 01e68b0..38caeac 100644 --- a/src/metricsAnalyzer/languages/pythonAnalyzer.ts +++ b/src/metricsAnalyzer/languages/pythonAnalyzer.ts @@ -224,15 +224,12 @@ export class PythonMetricsAnalyzer { // that tree-sitter includes as a child inside every lambda expression node. if (node.type === "lambda" && node.isNamed) { if (this.nesting > 0) { - const increment = 1 + this.nesting; - this.complexity += increment; - this.details.push({ - increment, - reason: "lambda (nested)", - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.addDetail( + 1 + this.nesting, + "lambda (nested)", + node.startPosition.row, + node.startPosition.column + ); } this.nesting++; for (let i = 0; i < node.childCount; i++) { @@ -245,14 +242,12 @@ export class PythonMetricsAnalyzer { const increment = this.getComplexityIncrement(node); if (increment > 0) { - this.complexity += increment; - this.details.push({ + this.addDetail( increment, - reason: this.getComplexityReason(node), - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.getComplexityReason(node), + node.startPosition.row, + node.startPosition.column + ); } // Conditionally bump nesting, iterate children once, then restore. @@ -265,6 +260,20 @@ export class PythonMetricsAnalyzer { if (nests) { this.nesting--; } } + /** + * Records a complexity-contributing detail and adds its increment to the running total. + */ + private addDetail(increment: number, reason: string, line: number, column: number): void { + this.complexity += increment; + this.details.push({ + increment, + reason, + line, + column, + nesting: this.nesting, + }); + } + /** * Calculates the base complexity increment for a syntax node. * diff --git a/src/metricsAnalyzer/languages/rustAnalyzer.ts b/src/metricsAnalyzer/languages/rustAnalyzer.ts index e56f154..b06a3db 100644 --- a/src/metricsAnalyzer/languages/rustAnalyzer.ts +++ b/src/metricsAnalyzer/languages/rustAnalyzer.ts @@ -256,15 +256,12 @@ export class RustMetricsAnalyzer { if (baseIncrement > 0) { const nestingPenalty = this.getNestingPenalty(node); const increment = baseIncrement + nestingPenalty; - const reason = this.getComplexityReason(node); - this.complexity += increment; - this.details.push({ + this.addDetail( increment, - reason, - line: node.startPosition.row, - column: node.startPosition.column, - nesting: this.nesting, - }); + this.getComplexityReason(node), + node.startPosition.row, + node.startPosition.column + ); } // Conditionally bump nesting, iterate children once, then restore. @@ -280,6 +277,20 @@ export class RustMetricsAnalyzer { if (nests) { this.nesting--; } } + /** + * Records a complexity-contributing detail and adds its increment to the running total. + */ + private addDetail(increment: number, reason: string, line: number, column: number): void { + this.complexity += increment; + this.details.push({ + increment, + reason, + line, + column, + nesting: this.nesting, + }); + } + /** * Returns the nesting penalty for a node's structural increment. * Else/else-if clauses are counted as a flat +1 without nesting penalty.