go--coverage-origin-buffer
(current-buffer)))
-(defun go-coverage (&optional coverage-file)
- "Open a clone of the current buffer and overlay it with
-coverage information gathered via go test -coverprofile=COVERAGE-FILE.
-
-If COVERAGE-FILE is nil, it will either be infered from the
-current buffer if it's already a coverage buffer, or be prompted
-for."
- (interactive)
- (setq coverage-file (or coverage-file (go--coverage-file)))
- (let* ((ranges '())
- (cur-buffer (current-buffer))
- (origin-buffer (go--coverage-origin-buffer))
- (file-name (file-name-nondirectory (buffer-file-name origin-buffer)))
- (gocov-buffer-name (concat (buffer-name origin-buffer) "<gocov>"))
- (max-count 0)
- divisor)
+(defun go--coverage-face (count divisor)
+ "Return the intensity face for COUNT when using DIVISOR
+to scale it to a range [0,10].
+
+DIVISOR scales the absolute cover count to values from 0 to 10.
+For DIVISOR = 0 the count will always translate to 8."
+ (let* ((count (go--covered-count range))
+ (norm (cond
+ ((= count 0)
+ -0.1) ;; Uncovered code, set to -0.1 so n becomes 0.
+ ((= divisor 0)
+ 0.8) ;; covermode=set, set to 0.8 so n becomes 8.
+ (t
+ (/ (log count) divisor))))
+ (n (1+ (floor (* norm 9))))) ;; Convert normalized count [0,1] to intensity [0,10]
+ (concat "go-coverage-" (number-to-string n))))
+
+(defun go--coverage-make-overlay (range divisor)
+ "Create a coverage overlay for a RANGE of covered/uncovered
+code. Uses DIVISOR to scale absolute counts to a [0,10] scale."
+ (let* ((count (go--covered-count range))
+ (face (go--coverage-face count divisor))
+ (ov (make-overlay (go--line-column-to-point (go--covered-start-line range)
+ (go--covered-start-column range))
+ (go--line-column-to-point (go--covered-end-line range)
+ (go--covered-end-column range)))))
+
+ (overlay-put ov 'face face)
+ (overlay-put ov 'help-echo (format "Count: %d" count))))
+
+(defun go--coverage-clear-overlays ()
+ "Remove existing overlays and put a single untracked overlay
+over the entire buffer."
+ (remove-overlays)
+ (overlay-put (make-overlay (point-min) (point-max))
+ 'face
+ 'go-coverage-untracked))
+
+(defun go--coverage-parse-file (coverage-file file-name)
+ "Parse COVERAGE-FILE and extract coverage information and
+divisor for FILE-NAME."
+ (let (ranges
+ (max-count 0))
(with-temp-buffer
(insert-file-contents coverage-file)
(go--goto-line 2) ;; Skip over mode
(destructuring-bind
(start-line start-column end-line end-column num count)
- (mapcar 'string-to-number rest)
-
- (if (> count max-count)
- (setq max-count count))
-
- (if (and (string= (file-name-nondirectory file) file-name))
- (push
- (make-go--covered
- :start-line start-line
- :start-column start-column
- :end-line end-line
- :end-column end-column
- :covered (/= count 0)
- :count count)
- ranges)))
+ (mapcar #'string-to-number rest)
+
+ (when (and (string= (file-name-nondirectory file) file-name))
+ (if (> count max-count)
+ (setq max-count count))
+ (push (make-go--covered :start-line start-line
+ :start-column start-column
+ :end-line end-line
+ :end-column end-column
+ :covered (/= count 0)
+ :count count)
+ ranges)))
(forward-line)))
- (if (> max-count 0)
- (setq divisor (log max-count))))
+ (list ranges (if (> max-count 0) (log max-count) 0)))))
- (with-current-buffer (or
- (get-buffer gocov-buffer-name)
- (make-indirect-buffer origin-buffer gocov-buffer-name t))
+(defun go-coverage (&optional coverage-file)
+ "Open a clone of the current buffer and overlay it with
+coverage information gathered via go test -coverprofile=COVERAGE-FILE.
+
+If COVERAGE-FILE is nil, it will either be infered from the
+current buffer if it's already a coverage buffer, or be prompted
+for."
+ (interactive)
+ (let* ((cur-buffer (current-buffer))
+ (origin-buffer (go--coverage-origin-buffer))
+ (gocov-buffer-name (concat (buffer-name origin-buffer) "<gocov>"))
+ (coverage-file (or coverage-file (go--coverage-file)))
+ (ranges-and-divisor (go--coverage-parse-file
+ coverage-file
+ (file-name-nondirectory (buffer-file-name origin-buffer)))))
+ (with-current-buffer (or (get-buffer gocov-buffer-name)
+ (make-indirect-buffer origin-buffer gocov-buffer-name t))
(set (make-local-variable 'go--coverage-origin-buffer) origin-buffer)
(set (make-local-variable 'go--coverage-current-file-name) coverage-file)
(save-excursion
- (remove-overlays)
- (overlay-put
- (make-overlay
- (point-min)
- (point-max))
- 'face 'go-coverage-untracked)
-
- (dolist (range ranges)
- (let* ((count (go--covered-count range))
- (norm (cond
- ((= count 0)
- -0.1)
- ((= max-count 1)
- 0.8)
- (t
- (/ (log count) divisor))))
- (n (1+ (floor (* norm 9))))
- (face (concat "go-coverage-" (number-to-string n)))
- (ov (make-overlay
- (go--line-column-to-point
- (go--covered-start-line range)
- (go--covered-start-column range))
- (go--line-column-to-point
- (go--covered-end-line range)
- (go--covered-end-column range)))))
-
- (overlay-put ov 'face face)
- (overlay-put ov 'help-echo (format "Count: %d" count)))))
+ (go--coverage-clear-overlays)
+ (dolist (range (car ranges-and-divisor))
+ (go--coverage-make-overlay range (cadr ranges-and-divisor))))
+
(if (not (eq cur-buffer (current-buffer)))
(display-buffer (current-buffer) 'display-buffer-reuse-window)))))