From 0fd032956df132c89ff895a44f5fda01280fe9e3 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Thu, 4 Jan 2007 01:25:36 -0700 Subject: [PATCH] more figleaf emacs work: enable the minor mode, then type C-cA to toggle annotations --- Makefile | 3 ++ misc/figleaf.el | 114 +++++++++++++++++++++++++++++++++------------ misc/figleaf2el.py | 37 ++++++++++----- 3 files changed, 111 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index fe42dd10..515edc76 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,9 @@ figleaf-output: # after doing test-figleaf and figleaf-output, point your browser at # coverage-html/index.html +.figleaf.el: .figleaf + python misc/figleaf2el.py .figleaf `python ./builddir.py` + pyflakes: pyflakes src/allmydata diff --git a/misc/figleaf.el b/misc/figleaf.el index a5fbb12b..33ecef46 100644 --- a/misc/figleaf.el +++ b/misc/figleaf.el @@ -20,12 +20,23 @@ (defvar figleaf-annotation-file ".figleaf.el") (defvar figleaf-annotations nil) +(defun find-figleaf-annotation-file () + (let ((dir (file-name-directory buffer-file-name)) + (olddir "/")) + (while (and (not (equal dir olddir)) + (not (file-regular-p (concat dir figleaf-annotation-file)))) + (setq olddir dir + dir (file-name-directory (directory-file-name dir)))) + (and (not (equal dir olddir)) (concat dir figleaf-annotation-file)) +)) + (defun load-figleaf-annotations () - (let ((coverage - (with-temp-buffer - (insert-file-contents figleaf-annotation-file) - (let ((form (read (current-buffer)))) - (eval form))))) + (let* ((annotation-file (find-figleaf-annotation-file)) + (coverage + (with-temp-buffer + (insert-file-contents annotation-file) + (let ((form (read (current-buffer)))) + (eval form))))) (setq figleaf-annotations coverage) coverage )) @@ -35,34 +46,75 @@ (save-excursion (dolist (ov (overlays-in (point-min) (point-max))) (delete-overlay ov)) + (setq figleaf-this-buffer-is-annotated nil) )) -(defun figleaf-annotate (filename) - (interactive) - (let* ((allcoverage (load-figleaf-annotations)) - (thiscoverage (gethash filename allcoverage)) - (covered-lines (car thiscoverage)) - (code-lines (car (cdr thiscoverage))) - ) - (save-excursion - (dolist (ov (overlays-in (point-min) (point-max))) - (delete-overlay ov)) - (dolist (covered-line covered-lines) - (goto-line covered-line) - ;;(add-text-properties (point) (line-end-position) '(face bold) ) - (overlay-put (make-overlay (point) (line-end-position)) +(defun figleaf-annotate (&optional show-code) + (interactive "P") + (let ((allcoverage (load-figleaf-annotations)) + (filename-key buffer-file-name) + thiscoverage code-lines covered-lines uncovered-code-lines + ) + (while (and (not (gethash filename-key allcoverage nil)) + (string-match "/" filename-key)) + ;; eat everything up to and including the first slash, then look again + (setq filename-key (substring filename-key + (+ 1 (string-match "/" filename-key))))) + (setq thiscoverage (gethash filename-key allcoverage nil)) + (if thiscoverage + (progn + (setq figleaf-this-buffer-is-annotated t) + (setq code-lines (nth 0 thiscoverage) + covered-lines (nth 1 thiscoverage) + uncovered-code-lines (nth 2 thiscoverage) + ) + + (save-excursion + (dolist (ov (overlays-in (point-min) (point-max))) + (delete-overlay ov)) + (if show-code + (dolist (line code-lines) + (goto-line line) + ;;(add-text-properties (point) (line-end-position) '(face bold) ) + (overlay-put (make-overlay (point) (line-end-position)) ;'before-string "C" ;'face '(background-color . "green") - 'face '(:background "dark green") - ) - ) - (dolist (code-line code-lines) - (goto-line code-line) - (overlay-put (make-overlay (point) (line-end-position)) + 'face '(:background "dark green") + ) + )) + (dolist (line uncovered-code-lines) + (goto-line line) + (overlay-put (make-overlay (point) (line-end-position)) ;'before-string "D" - ;'face '(:background "blue") - ;'face '(:underline "blue") - 'face '(:box "blue") - ) - ) -))) + ;'face '(:background "blue") + ;'face '(:underline "blue") + 'face '(:box "red") + ) + ) + ) + ) + (message "unable to find coverage for this file")) +)) + +(defun figleaf-toggle-annotations (show-code) + (interactive "P") + (if figleaf-this-buffer-is-annotated + (figleaf-unannotate) + (figleaf-annotate show-code)) +) + + +(setq figleaf-this-buffer-is-annotated nil) +(make-variable-buffer-local 'figleaf-this-buffer-is-annotated) + +(define-minor-mode figleaf-annotation-minor-mode + "Minor mode to annotate code-coverage information" + nil + " FA" + '( + ("\C-ca" . figleaf-toggle-annotations) + ) + + () ; forms run on mode entry/exit +) + diff --git a/misc/figleaf2el.py b/misc/figleaf2el.py index 77db435b..bc15d335 100644 --- a/misc/figleaf2el.py +++ b/misc/figleaf2el.py @@ -16,28 +16,41 @@ def longest_common_prefix_2(a, b): return a[:i] return "" -def write_el(r2): - filenames = sorted(r2.keys()) - out = open(".figleaf.el", "w") - out.write("(setq figleaf-results '(\n") - for f in filenames: - linenumbers = r2[f] - out.write(' ("%s" (%s))\n' % (f, " ".join([str(ln) - for ln in linenumbers]))) - out.write(" ))\n") - out.close() +## def write_el(r2): +## filenames = sorted(r2.keys()) +## out = open(".figleaf.el", "w") +## out.write("(setq figleaf-results '(\n") +## for f in filenames: +## linenumbers = r2[f] +## out.write(' ("%s" (%s))\n' % (f, " ".join([str(ln) +## for ln in linenumbers]))) +## out.write(" ))\n") +## out.close() def write_el(r2, source): filenames = sorted(r2.keys()) out = open(".figleaf.el", "w") + out.write(""" +;; This is an elisp-readable form of the figleaf coverage data. It defines a +;; single top-level hash table in which the load-path-relative filename (like +;; allmydata/download.py) is the key, and the value is a three-element list. +;; The first element of this list is a list of line numbers that represent +;; actual code. The second is a list of line numbers for lines which got used +;; during the unit test. The third is a list of line numbers for code lines +;; that were not covered (since 'code' and 'covered' start as sets, this last +;; list is equal to 'code - covered'). + +""") out.write("(let ((results (make-hash-table :test 'equal)))\n") for f in filenames: covered_linenumbers = r2[f] code_linenumbers = source[f] - out.write(" (puthash \"%s\" '((%s) (%s)) results)\n" + uncovered_code = code_linenumbers - covered_linenumbers + out.write(" (puthash \"%s\" '((%s) (%s) (%s)) results)\n" % (f, - " ".join([str(ln) for ln in sorted(covered_linenumbers)]), " ".join([str(ln) for ln in sorted(code_linenumbers)]), + " ".join([str(ln) for ln in sorted(covered_linenumbers)]), + " ".join([str(ln) for ln in sorted(uncovered_code)]), )) out.write(" results)\n") out.close() -- 2.45.2