diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/coverage-summary.el | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/scripts/coverage-summary.el b/scripts/coverage-summary.el index 4947171f..f2c66f4a 100644 --- a/scripts/coverage-summary.el +++ b/scripts/coverage-summary.el @@ -35,6 +35,80 @@ Returned keys are relative to PROJECT-ROOT for readable terminal output." table) result)) +(defun cj/coverage-summary--module-files (module-dir project-root) + "Return repository module files under MODULE-DIR, relative to PROJECT-ROOT. + +This intentionally uses only direct =modules/*.el= files. Compiled files, +subdirectories, and non-Elisp assets are outside this repository's module +coverage universe." + (let ((module-dir (file-name-as-directory (expand-file-name module-dir))) + (project-root (file-name-as-directory (expand-file-name project-root)))) + (sort + (mapcar (lambda (path) + (file-relative-name path project-root)) + (directory-files module-dir t "\\.el\\'")) + #'string<))) + +(defun cj/coverage-summary--missing-module-files (tracked-table module-dir project-root) + "Return modules present on disk but absent from TRACKED-TABLE. + +TRACKED-TABLE should use readable project-relative paths, such as the table +returned by `cj/coverage-summary--modules-only'." + (let (tracked) + (maphash (lambda (path _lines) (push path tracked)) tracked-table) + (seq-difference + (cj/coverage-summary--module-files module-dir project-root) + tracked + #'string=))) + +(defun cj/coverage-summary--format-missing-modules (missing) + "Return a report section for MISSING module files. + +MISSING is a list of project-relative module paths that are absent from the +SimpleCov report." + (with-temp-buffer + (insert (format "\nNot in SimpleCov report: %d module%s\n" + (length missing) + (if (= 1 (length missing)) "" "s"))) + (if missing + (progn + (insert "These modules had no coverage entry; they count as 0% in project module coverage.\n") + (dolist (path missing) + (insert (format " %s\n" path)))) + (insert "Every modules/*.el file appears in the SimpleCov report.\n")) + (buffer-string))) + +(defun cj/coverage-summary--record-module-percent (record) + "Return RECORD's per-module coverage percentage. + +RECORD is a plist from `cj/--coverage-intersect'. A tracked module with no +executable lines contributes 100%; there is nothing executable left uncovered." + (let ((total (length (plist-get record :changed-lines))) + (covered (length (plist-get record :covered-lines)))) + (if (> total 0) + (/ (* 100.0 covered) total) + 100.0))) + +(defun cj/coverage-summary--format-project-module-coverage (records missing) + "Return the project-module coverage policy section. + +The existing SimpleCov total is line-weighted over files present in the report. +This section is module-weighted over all direct `modules/*.el' files: tracked +modules contribute their per-file coverage percentage, while MISSING modules +contribute 0%." + (let* ((tracked (seq-filter (lambda (rec) (plist-get rec :tracked)) records)) + (tracked-count (length tracked)) + (missing-count (length missing)) + (total-count (+ tracked-count missing-count)) + (score (apply #'+ (mapcar #'cj/coverage-summary--record-module-percent + tracked))) + (pct (if (> total-count 0) + (/ score total-count) + 0.0))) + (format (concat "\nProject module coverage: %.1f%%" + " (%d tracked, %d missing, %d total; missing modules count as 0%%)\n") + pct tracked-count missing-count total-count))) + (defun cj/coverage-summary-text (report-file module-dir project-root) "Return a whole-project coverage summary for MODULE-DIR from REPORT-FILE." (let* ((covered (cj/coverage-summary--modules-only @@ -45,8 +119,14 @@ Returned keys are relative to PROJECT-ROOT for readable terminal output." (cj/--coverage-simplecov-executable-lines report-file) module-dir project-root)) - (records (cj/--coverage-intersect covered executable))) - (cj/--coverage-format-summary records "modules/"))) + (records (cj/--coverage-intersect covered executable)) + (missing (cj/coverage-summary--missing-module-files executable + module-dir + project-root))) + (concat + (cj/--coverage-format-summary records "modules/") + (cj/coverage-summary--format-project-module-coverage records missing) + (cj/coverage-summary--format-missing-modules missing)))) (defun cj/coverage-print-module-summary (report-file module-dir project-root) "Print a whole-project coverage summary for MODULE-DIR from REPORT-FILE." |
