aboutsummaryrefslogtreecommitdiff
path: root/modules/coverage-core.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/coverage-core.el')
-rw-r--r--modules/coverage-core.el53
1 files changed, 53 insertions, 0 deletions
diff --git a/modules/coverage-core.el b/modules/coverage-core.el
index e7540434..f1e8ae88 100644
--- a/modules/coverage-core.el
+++ b/modules/coverage-core.el
@@ -12,6 +12,59 @@
;;; Code:
+(require 'seq)
+
+(defvar cj/coverage-backends nil
+ "Registry of coverage backends in priority order.
+Each entry is a plist with at least :name, :detect, :run, and :lcov-path.
+Use `cj/coverage-register-backend' to add or replace an entry.")
+
+(defvar-local cj/coverage-backend nil
+ "Override: name of the coverage backend to use for the current project.
+When nil (the default), resolution runs each registered backend's :detect
+function in registration order. Typically set buffer-locally via
+`.dir-locals.el' to pin a specific backend.")
+
+(defun cj/coverage-register-backend (backend)
+ "Register BACKEND, a plist with :name, :detect, :run, :lcov-path.
+Appends to `cj/coverage-backends' at the end, or replaces the existing
+entry with the same :name in its current position."
+ (let ((name (plist-get backend :name)))
+ (if (cj/--coverage-backend-by-name name)
+ (setq cj/coverage-backends
+ (mapcar (lambda (b)
+ (if (eq (plist-get b :name) name) backend b))
+ cj/coverage-backends))
+ (setq cj/coverage-backends
+ (append cj/coverage-backends (list backend))))))
+
+(defun cj/--coverage-backend-by-name (name)
+ "Return the registered backend whose :name equals NAME, or nil."
+ (seq-find (lambda (b) (eq name (plist-get b :name)))
+ cj/coverage-backends))
+
+(defun cj/--coverage-backend-for-project (root &optional override)
+ "Resolve the coverage backend to use for ROOT.
+OVERRIDE, if non-nil, is a backend name symbol (typically the value of
+`cj/coverage-backend' from .dir-locals.el). When given, the named
+backend is returned regardless of any :detect functions. Signals
+`user-error' when OVERRIDE names a backend that isn't registered.
+
+When OVERRIDE is nil, each backend's :detect is called in turn with
+ROOT as its sole argument; the first that returns non-nil wins.
+Returns the backend plist, or nil when no backend matches."
+ (cond
+ (override
+ (or (cj/--coverage-backend-by-name override)
+ (user-error
+ "Unknown coverage backend: %s (registered: %s)"
+ override
+ (mapcar (lambda (b) (plist-get b :name)) cj/coverage-backends))))
+ (t
+ (seq-find (lambda (backend)
+ (funcall (plist-get backend :detect) root))
+ cj/coverage-backends))))
+
(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