@@ -22,15 +22,19 @@ type Operand struct {
2222
2323// MetricsResult stores the complexity metrics for a single file or function
2424type MetricsResult struct {
25- Name string `json:"name"`
26- CyclomaticComplexity int `json:"cyclomaticComplexity"`
27- CognitiveComplexity int `json:"cognitiveComplexity"`
28- LinesOfCode int `json:"linesOfCode"`
29- HalsteadVolume float64 `json:"halsteadVolume"`
30- HalsteadDifficulty float64 `json:"halsteadDifficulty"`
31- HalsteadEffort float64 `json:"halsteadEffort"`
32- MaintainabilityIndex float64 `json:"maintainabilityIndex"`
33- NestingLevel int `json:"nestingLevel"`
25+ Name string `json:"name"`
26+ CyclomaticComplexity int `json:"cyclomaticComplexity"`
27+ CognitiveComplexity int `json:"cognitiveComplexity"`
28+ LinesOfCode int `json:"linesOfCode"`
29+ HalsteadVolume float64 `json:"halsteadVolume"`
30+ HalsteadDifficulty float64 `json:"halsteadDifficulty"`
31+ HalsteadEffort float64 `json:"halsteadEffort"`
32+ MaintainabilityIndex float64 `json:"maintainabilityIndex"`
33+ NestingLevel int `json:"nestingLevel"`
34+ NestedDepth int `json:"nestedDepth"`
35+ CommentDensity float64 `json:"commentDensity"`
36+ FunctionParameters int `json:"functionParameters"`
37+ ReturnStatements int `json:"returnStatements"`
3438}
3539
3640// FileAnalyzer handles the analysis of a single file
@@ -132,8 +136,8 @@ func (fa *FileAnalyzer) calculateHalsteadMetrics(node ast.Node) (volume, difficu
132136
133137 n1 := float64 (len (operators )) // unique operators
134138 n2 := float64 (len (operands )) // unique operands
135- N1 := float64 (0 ) // total operators
136- N2 := float64 (0 ) // total operands
139+ N1 := float64 (0 ) // total operators
140+ N2 := float64 (0 ) // total operands
137141
138142 for _ , count := range operators {
139143 N1 += float64 (count )
@@ -177,19 +181,31 @@ func (fa *FileAnalyzer) AnalyzeFunction(funcDecl *ast.FuncDecl) *MetricsResult {
177181 cyclomaticComplexity := fa .CalculateCyclomaticComplexity (funcDecl )
178182 cognitiveComplexity := fa .CalculateCognitiveComplexity (funcDecl )
179183 linesOfCode := fa .CountLinesOfCode (funcDecl )
180-
184+
181185 volume , difficulty , effort := fa .calculateHalsteadMetrics (funcDecl )
182-
186+
183187 // Add validation for edge cases
184188 if volume <= 0 {
185189 volume = 1 // Avoid log(0) in maintainability index calculation
186190 }
187191 if linesOfCode <= 0 {
188192 linesOfCode = 1
189193 }
190-
194+
191195 maintainabilityIndex := fa .CalculateMaintainabilityIndex (cyclomaticComplexity , volume , linesOfCode )
192196
197+ // Calculate nested depth
198+ nestedDepth := fa .calculateNestedDepth (funcDecl )
199+
200+ // Calculate comment density
201+ commentDensity := fa .calculateCommentDensity (funcDecl )
202+
203+ // Count parameters
204+ paramCount := len (funcDecl .Type .Params .List )
205+
206+ // Count return statements
207+ returnCount := fa .countReturnStatements (funcDecl )
208+
193209 // Ensure all metrics are valid
194210 if math .IsNaN (volume ) || math .IsInf (volume , 0 ) {
195211 volume = 0
@@ -205,14 +221,18 @@ func (fa *FileAnalyzer) AnalyzeFunction(funcDecl *ast.FuncDecl) *MetricsResult {
205221 }
206222
207223 return & MetricsResult {
208- Name : funcDecl .Name .Name ,
224+ Name : funcDecl .Name .Name ,
209225 CyclomaticComplexity : cyclomaticComplexity ,
210226 CognitiveComplexity : cognitiveComplexity ,
211227 LinesOfCode : linesOfCode ,
212228 HalsteadVolume : math .Round (volume * 100 ) / 100 ,
213229 HalsteadDifficulty : math .Round (difficulty * 100 ) / 100 ,
214230 HalsteadEffort : math .Round (effort * 100 ) / 100 ,
215231 MaintainabilityIndex : math .Round (maintainabilityIndex * 100 ) / 100 ,
232+ NestedDepth : nestedDepth ,
233+ CommentDensity : commentDensity ,
234+ FunctionParameters : paramCount ,
235+ ReturnStatements : returnCount ,
216236 }
217237}
218238
@@ -229,3 +249,44 @@ func (fa *FileAnalyzer) AnalyzeFile() []*MetricsResult {
229249
230250 return results
231251}
252+
253+ // Add new analysis methods
254+ func (fa * FileAnalyzer ) calculateNestedDepth (node ast.Node ) int {
255+ maxDepth := 0
256+ currentDepth := 0
257+
258+ ast .Inspect (node , func (n ast.Node ) bool {
259+ switch n .(type ) {
260+ case * ast.IfStmt , * ast.ForStmt , * ast.RangeStmt , * ast.SwitchStmt , * ast.SelectStmt :
261+ currentDepth ++
262+ if currentDepth > maxDepth {
263+ maxDepth = currentDepth
264+ }
265+ return true
266+ }
267+ currentDepth = 0
268+ return true
269+ })
270+
271+ return maxDepth
272+ }
273+
274+ func (fa * FileAnalyzer ) calculateCommentDensity (node ast.Node ) float64 {
275+ comments := len (fa .ast .Comments )
276+ lines := fa .CountLinesOfCode (node )
277+ if lines == 0 {
278+ return 0
279+ }
280+ return float64 (comments ) / float64 (lines )
281+ }
282+
283+ func (fa * FileAnalyzer ) countReturnStatements (node ast.Node ) int {
284+ count := 0
285+ ast .Inspect (node , func (n ast.Node ) bool {
286+ if _ , ok := n .(* ast.ReturnStmt ); ok {
287+ count ++
288+ }
289+ return true
290+ })
291+ return count
292+ }
0 commit comments