diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el index 022c077c6d5..e4855c9d900 100644 --- a/misc/emacs/go-mode.el +++ b/misc/emacs/go-mode.el @@ -1014,22 +1014,49 @@ current coverage buffer or by prompting for it." 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. +(defun go--coverage-face (count divisor) + "Return the intensity face for COUNT when using DIVISOR +to scale it to a range [0,10]. -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) "")) - (max-count 0) - divisor) +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 @@ -1040,62 +1067,48 @@ for." (destructuring-bind (start-line start-column end-line end-column num count) - (mapcar 'string-to-number rest) + (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))) + (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) "")) + (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) + (go--coverage-clear-overlays) + (dolist (range (car ranges-and-divisor)) + (go--coverage-make-overlay range (cadr ranges-and-divisor)))) - (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))))) (if (not (eq cur-buffer (current-buffer))) (display-buffer (current-buffer) 'display-buffer-reuse-window)))))