Skip to content

Commit

Permalink
Fix incorrect calculation issue with nesting (#14)
Browse files Browse the repository at this point in the history
* Tests that verifies current recursion logic and reproduces issue

* Test for C verifying part of the same issue as for go with nesting

* Fix stupid calculation error in go test

* Fix expected Kotlin test case after reading cognitive complexity paper

* Fix nesting issue, aka the incorrect calculation defect

* Minor stylistic changes in function use and init
  • Loading branch information
themkat committed Apr 11, 2024
1 parent 19adb98 commit fca5130
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 18 deletions.
4 changes: 2 additions & 2 deletions Eask
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
(depends-on "emacs" "27.1")
(depends-on "tree-sitter")
(depends-on "s")
(depends-on "dash")

(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432

(development
(depends-on "kotlin-mode")
(depends-on "go-mode")
(depends-on "tree-sitter-langs")
(depends-on "dash"))
(depends-on "tree-sitter-langs"))
35 changes: 22 additions & 13 deletions codemetrics.el
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
;; Maintainer: Shen, Jen-Chieh <jcs090218@gmail.com>
;; URL: https://github.com/emacs-vs/codemetrics
;; Version: 0.1.0
;; Package-Requires: ((emacs "27.1") (tree-sitter "0.15.1") (s "1.12.0"))
;; Package-Requires: ((emacs "27.1") (tree-sitter "0.15.1") (s "1.12.0") (dash "2.19.1"))
;; Keywords: convenience complexity

;; This file is not part of GNU Emacs.
Expand Down Expand Up @@ -35,6 +35,7 @@
(require 'pcase)
(require 'rect)

(require 'dash)
(require 's)
(require 'tree-sitter)

Expand Down Expand Up @@ -255,10 +256,14 @@ details. Optional argument DEPTH is used for recursive depth calculation."
(codemetrics--ensure-ts
(let* ((mode (or mode major-mode))
(rules (codemetrics--rules mode))
(nested-level) ; this is the "starting" nested level
;; Collection of nesting levels
(nested-depths)
(nested 0)
(score 0)
(data)
;; Helper for calculating nested value from our collection of nestings
(calculate-nested-value (lambda (nested-depths)
(max 0 (1- (length nested-depths)))))
;; Global Records
(codemetrics--recursion-identifier))
(with-temp-buffer
Expand All @@ -273,10 +278,12 @@ details. Optional argument DEPTH is used for recursive depth calculation."
(when (and codemetrics--recursion-identifier
(<= depth codemetrics--recursion-identifier-depth))
(setq codemetrics--recursion-identifier nil))
(when (and nested-level
(<= depth nested-level)) ; decrement out
(setq nested-level nil
nested 0))
;; Decrement out if needed
;; (if we have moved out of the last nesting)
(setq nested-depths (-drop-while (lambda (nested)
(<= depth nested))
nested-depths)
nested (funcall calculate-nested-value nested-depths))
(when-let* ((type (tsc-node-type node))
(a-rule (assoc type rules)) ; cons
(rule (cdr a-rule)))
Expand All @@ -286,13 +293,15 @@ details. Optional argument DEPTH is used for recursive depth calculation."
(weight (nth 0 rules-data))
(inc-nested (nth 1 rules-data)))
(when inc-nested
(if (null nested-level)
(setq nested-level depth
nested 0)
(cl-incf nested)))
(codemetrics--log "depth: %s, nested-level: %s, nested: %s"
depth nested-level nested)
(let ((node-score (+ weight nested)))
(let ((last-depth (or (nth 0 nested-depths)
depth)))
(when (or (< last-depth depth)
(zerop (length nested-depths)))
(push depth nested-depths)
(setq nested (funcall calculate-nested-value nested-depths)))))
(codemetrics--log "depth: %s, nested-depths: %s, nested: %s"
depth nested-depths nested)
(let ((node-score (if inc-nested (+ weight nested) weight)))
(codemetrics--log "%s" (cons type node-score))
(push (list node depth node-score) data)
;; The first value is plus, second is times.
Expand Down
13 changes: 13 additions & 0 deletions test/c-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,17 @@
("||" . 1)
("&&" . 0)))

;; Loosely inspired by go nested prints issue
;; (for verifying issue with multiple nested ifs inside a for-loop)
(codemetrics-test c-nested-prints
"test/c/NestedPrints.c"
c-mode
'(5
(function_definition . 0)
(for_statement . 1)
(if_statement . 2)
(call_expression . 0)
(if_statement . 2)
(call_expression . 0)))

;;; c-test.el ends here
14 changes: 14 additions & 0 deletions test/c/NestedPrints.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdio.h>

int main() {
int i;
for (i = 0; i < 10; i++) {
if(i == 0) {
printf("Hello there\n")
}

if(i == 9) {
printf("General Kenobi\n");
}
}
}
22 changes: 22 additions & 0 deletions test/go-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,26 @@
(call_expression . 0)
(for_statement . 1)))

(codemetrics-test recursion-go-code
"test/go/Recursion.go"
go-mode
'(2
(function_declaration . 0)
(if_statement . 1)
(call_expression . 1)))

;; Test of issue:
;; https://github.com/emacs-vs/codemetrics/issues/7
(codemetrics-test go-nested-print-calls
"test/go/NestedPrints.go"
go-mode
'(6
(function_declaration . 0)
(for_statement . 1)
(if_statement . 2)
(call_expression . 0)
(if_statement . 2)
(call_expression . 0)
(for_statement . 1)))

;;; go-test.el ends here
18 changes: 18 additions & 0 deletions test/go/NestedPrints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import "fmt"

func main() {
v1 := false
v2 := true

for {
if v1 {
fmt.Println(v1)
}

if v2 {
fmt.Println(v2)
}
}

for {}
}
7 changes: 7 additions & 0 deletions test/go/Recursion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func factorial(n int) int {
if n <= 1 {
return 1
}

return n * factorial(n - 1)
}
6 changes: 3 additions & 3 deletions test/kotlin-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@
(codemetrics-test kotlin-break-continue
"test/kotlin/BreakContinue.kt"
kotlin-mode
'(8
'(6
(function_declaration . 0)
(call_expression . 0)
(for_statement . 1)
(if_expression . 2)
("break" . 1)
("break" . 0)
(for_statement . 1)
(if_expression . 2)
("continue" . 1)))
("continue" . 0)))

;;; kotlin-test.el ends here

0 comments on commit fca5130

Please sign in to comment.