blob: 4a3112ce8973042cff8accef0eca84a563bace64 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
;;; coverage-core.el --- Coverage reporting engine and backend registry -*- lexical-binding: t; coding: utf-8; -*-
;; author: Craig Jennings <c@cjennings.net>
;;; Commentary:
;; Language-agnostic core for diff-aware coverage reporting.
;;
;; Reads an LCOV file, shells to git diff at a selectable scope,
;; intersects the results, and displays a report buffer. Languages
;; plug in via the backend registry (see `cj/coverage-backends').
;;
;; See docs/design/coverage.org for the design rationale.
;;; Code:
(defun cj/--coverage-parse-lcov (file)
"Parse FILE as LCOV and return a hash table of covered lines.
Keys are source-file paths (strings). Values are hash tables whose
keys are line numbers (integers) that had a hit count greater than
zero. Only the SF, DA, and end_of_record fields are read; other
LCOV fields are ignored. Malformed DA lines are skipped silently.
Signals `user-error' if FILE does not exist."
(unless (file-exists-p file)
(user-error "LCOV file not found: %s" file))
(let ((result (make-hash-table :test 'equal))
(current-file nil)
(current-lines nil))
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(while (not (eobp))
(let ((line (buffer-substring-no-properties
(line-beginning-position) (line-end-position))))
(cond
((string-prefix-p "SF:" line)
(setq current-file (substring line 3))
(setq current-lines (make-hash-table :test 'eql)))
((string-prefix-p "DA:" line)
(when current-lines
(let* ((rest (substring line 3))
(parts (split-string rest ","))
(line-str (car parts))
(hits-str (cadr parts))
(line-num (and line-str (string-match-p "\\`[0-9]+\\'" line-str)
(string-to-number line-str)))
(hits (and hits-str (string-match-p "\\`[0-9]+\\'" hits-str)
(string-to-number hits-str))))
(when (and line-num hits (> hits 0))
(puthash line-num t current-lines)))))
((string= line "end_of_record")
(when current-file
(puthash current-file current-lines result))
(setq current-file nil
current-lines nil))))
(forward-line 1)))
result))
(provide 'coverage-core)
;;; coverage-core.el ends here
|