diff options
| author | Jonathan Yavner | 2004-07-17 17:06:26 +0000 |
|---|---|---|
| committer | Jonathan Yavner | 2004-07-17 17:06:26 +0000 |
| commit | 3e39672fd35c40e1dedc8213858a3ac424a31824 (patch) | |
| tree | b2bd9cef4b59d03d117283c85a1a3759f0d29419 | |
| parent | 3751eb00d78a352422c67fc2285eb38ee5c56b92 (diff) | |
| download | emacs-3e39672fd35c40e1dedc8213858a3ac424a31824.tar.gz emacs-3e39672fd35c40e1dedc8213858a3ac424a31824.zip | |
Added some additional functions to the `1-valued', `compose', and progn groups.
Bugfix for marking up the definition for an empty function.
New category "potentially-1valued" for functions that are not erroneous if either 1-valued or multi-valued.
| -rw-r--r-- | lisp/ChangeLog | 10 | ||||
| -rw-r--r-- | lisp/emacs-lisp/testcover.el | 223 |
2 files changed, 160 insertions, 73 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 2b249918d7f..cf0600b7605 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2004-07-17 Jonathan Yavner <jyavner@member.fsf.org> | ||
| 2 | |||
| 3 | * emacs-lisp/testcover.el: New category "potentially-1valued" for | ||
| 4 | functions that are not erroneous if either 1-valued or | ||
| 5 | multi-valued. Detect functions in this class. | ||
| 6 | (testcover-1value-functions, testcover-compose-functions, | ||
| 7 | testcover-progn-functions) Added some additional functions to lists. | ||
| 8 | (testcover-mark): Bugfix when marking up the definition for an | ||
| 9 | empty function. | ||
| 10 | |||
| 1 | 2004-07-17 Richard M. Stallman <rms@gnu.org> | 11 | 2004-07-17 Richard M. Stallman <rms@gnu.org> |
| 2 | 12 | ||
| 3 | * replace.el (occur-read-primary-args): Pass default to read-from-minibuffer. | 13 | * replace.el (occur-read-primary-args): Pass default to read-from-minibuffer. |
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 547e2cbd32d..23e9a54b1bb 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el | |||
| @@ -38,9 +38,9 @@ | |||
| 38 | ;; instrumentation callbacks, then replace edebug's callbacks with ours. | 38 | ;; instrumentation callbacks, then replace edebug's callbacks with ours. |
| 39 | ;; * To show good coverage, we want to see two values for every form, except | 39 | ;; * To show good coverage, we want to see two values for every form, except |
| 40 | ;; functions that always return the same value and `defconst' variables | 40 | ;; functions that always return the same value and `defconst' variables |
| 41 | ;; need show only value for good coverage. To avoid the brown splotch, the | 41 | ;; need show only one value for good coverage. To avoid the brown |
| 42 | ;; definitions for constants and 1-valued functions must precede the | 42 | ;; splotch, the definitions for constants and 1-valued functions must |
| 43 | ;; references. | 43 | ;; precede the references. |
| 44 | ;; * Use the macro `1value' in your Lisp code to mark spots where the local | 44 | ;; * Use the macro `1value' in your Lisp code to mark spots where the local |
| 45 | ;; code environment causes a function or variable to always have the same | 45 | ;; code environment causes a function or variable to always have the same |
| 46 | ;; value, but the function or variable is not intrinsically 1-valued. | 46 | ;; value, but the function or variable is not intrinsically 1-valued. |
| @@ -55,12 +55,14 @@ | |||
| 55 | ;; call has the same value! Also, equal thinks two strings are the same | 55 | ;; call has the same value! Also, equal thinks two strings are the same |
| 56 | ;; if they differ only in properties. | 56 | ;; if they differ only in properties. |
| 57 | ;; * Because we have only a "1value" class and no "always nil" class, we have | 57 | ;; * Because we have only a "1value" class and no "always nil" class, we have |
| 58 | ;; to treat as 1-valued any `and' whose last term is 1-valued, in case the | 58 | ;; to treat as potentially 1-valued any `and' whose last term is 1-valued, |
| 59 | ;; last term is always nil. Example: | 59 | ;; in case the last term is always nil. Example: |
| 60 | ;; (and (< (point) 1000) (forward-char 10)) | 60 | ;; (and (< (point) 1000) (forward-char 10)) |
| 61 | ;; This form always returns nil. Similarly, `if' and `cond' are | 61 | ;; This form always returns nil. Similarly, `or', `if', and `cond' are |
| 62 | ;; treated as 1-valued if all clauses are, in case those values are | 62 | ;; treated as potentially 1-valued if all clauses are, in case those |
| 63 | ;; always nil. | 63 | ;; values are always nil. Unlike truly 1-valued functions, it is not an |
| 64 | ;; error if these "potentially" 1-valued forms actually return differing | ||
| 65 | ;; values. | ||
| 64 | 66 | ||
| 65 | (require 'edebug) | 67 | (require 'edebug) |
| 66 | (provide 'testcover) | 68 | (provide 'testcover) |
| @@ -86,12 +88,14 @@ these. This list is quite incomplete!" | |||
| 86 | 88 | ||
| 87 | (defcustom testcover-1value-functions | 89 | (defcustom testcover-1value-functions |
| 88 | '(backward-char barf-if-buffer-read-only beginning-of-line | 90 | '(backward-char barf-if-buffer-read-only beginning-of-line |
| 89 | buffer-disable-undo buffer-enable-undo current-global-map deactivate-mark | 91 | buffer-disable-undo buffer-enable-undo current-global-map |
| 90 | delete-char delete-region ding error forward-char function* insert | 92 | deactivate-mark delete-backward-char delete-char delete-region ding |
| 91 | insert-and-inherit kill-all-local-variables lambda mapc narrow-to-region | 93 | forward-char function* insert insert-and-inherit kill-all-local-variables |
| 92 | noreturn push-mark put-text-property run-hooks set-text-properties signal | 94 | kill-line kill-paragraph kill-region kill-sexp lambda |
| 93 | substitute-key-definition suppress-keymap throw undo use-local-map while | 95 | minibuffer-complete-and-exit narrow-to-region next-line push-mark |
| 94 | widen yank) | 96 | put-text-property run-hooks set-match-data signal |
| 97 | substitute-key-definition suppress-keymap undo use-local-map while widen | ||
| 98 | yank) | ||
| 95 | "Functions that always return the same value. No brown splotch is shown | 99 | "Functions that always return the same value. No brown splotch is shown |
| 96 | for these. This list is quite incomplete! Notes: Nobody ever changes the | 100 | for these. This list is quite incomplete! Notes: Nobody ever changes the |
| 97 | current global map. The macro `lambda' is self-evaluating, hence always | 101 | current global map. The macro `lambda' is self-evaluating, hence always |
| @@ -108,9 +112,9 @@ them as having returned nil just before calling them." | |||
| 108 | :type 'hook) | 112 | :type 'hook) |
| 109 | 113 | ||
| 110 | (defcustom testcover-compose-functions | 114 | (defcustom testcover-compose-functions |
| 111 | '(+ - * / length list make-keymap make-sparse-keymap message propertize | 115 | '(+ - * / = append length list make-keymap make-sparse-keymap |
| 112 | replace-regexp-in-string run-with-idle-timer | 116 | mapcar message propertize replace-regexp-in-string |
| 113 | set-buffer-modified-p) | 117 | run-with-idle-timer set-buffer-modified-p) |
| 114 | "Functions that are 1-valued if all their args are either constants or | 118 | "Functions that are 1-valued if all their args are either constants or |
| 115 | calls to one of the `testcover-1value-functions', so if that's true then no | 119 | calls to one of the `testcover-1value-functions', so if that's true then no |
| 116 | brown splotch is shown for these. This list is quite incomplete! Most | 120 | brown splotch is shown for these. This list is quite incomplete! Most |
| @@ -119,16 +123,16 @@ side-effect-free functions should be here." | |||
| 119 | :type 'hook) | 123 | :type 'hook) |
| 120 | 124 | ||
| 121 | (defcustom testcover-progn-functions | 125 | (defcustom testcover-progn-functions |
| 122 | '(define-key fset function goto-char or overlay-put progn save-current-buffer | 126 | '(define-key fset function goto-char mapc overlay-put progn |
| 123 | save-excursion save-match-data save-restriction save-selected-window | 127 | save-current-buffer save-excursion save-match-data |
| 124 | save-window-excursion set set-default setq setq-default | 128 | save-restriction save-selected-window save-window-excursion |
| 125 | with-output-to-temp-buffer with-syntax-table with-temp-buffer | 129 | set set-default set-marker-insertion-type setq setq-default |
| 126 | with-temp-file with-temp-message with-timeout) | 130 | with-current-buffer with-output-to-temp-buffer with-syntax-table |
| 131 | with-temp-buffer with-temp-file with-temp-message with-timeout) | ||
| 127 | "Functions whose return value is the same as their last argument. No | 132 | "Functions whose return value is the same as their last argument. No |
| 128 | brown splotch is shown for these if the last argument is a constant or a | 133 | brown splotch is shown for these if the last argument is a constant or a |
| 129 | call to one of the `testcover-1value-functions'. This list is probably | 134 | call to one of the `testcover-1value-functions'. This list is probably |
| 130 | incomplete! Note: `or' is here in case the last argument is a function that | 135 | incomplete!" |
| 131 | always returns nil." | ||
| 132 | :group 'testcover | 136 | :group 'testcover |
| 133 | :type 'hook) | 137 | :type 'hook) |
| 134 | 138 | ||
| @@ -140,6 +144,11 @@ call to one of the `testcover-1value-functions'." | |||
| 140 | :group 'testcover | 144 | :group 'testcover |
| 141 | :type 'hook) | 145 | :type 'hook) |
| 142 | 146 | ||
| 147 | (defcustom testcover-potentially-1value-functions | ||
| 148 | '(add-hook and beep or remove-hook unless when) | ||
| 149 | "Functions that are potentially 1-valued. No brown splotch if actually | ||
| 150 | 1-valued, no error if actually multi-valued.") | ||
| 151 | |||
| 143 | (defface testcover-nohits-face | 152 | (defface testcover-nohits-face |
| 144 | '((t (:background "DeepPink2"))) | 153 | '((t (:background "DeepPink2"))) |
| 145 | "Face for forms that had no hits during coverage test" | 154 | "Face for forms that had no hits during coverage test" |
| @@ -161,7 +170,11 @@ call to one of the `testcover-1value-functions'." | |||
| 161 | 170 | ||
| 162 | (defvar testcover-module-1value-functions nil | 171 | (defvar testcover-module-1value-functions nil |
| 163 | "Symbols declared with defun in the last file processed by | 172 | "Symbols declared with defun in the last file processed by |
| 164 | `testcover-start', whose functions always return the same value.") | 173 | `testcover-start', whose functions should always return the same value.") |
| 174 | |||
| 175 | (defvar testcover-module-potentially-1value-functions nil | ||
| 176 | "Symbols declared with defun in the last file processed by | ||
| 177 | `testcover-start', whose functions might always return the same value.") | ||
| 165 | 178 | ||
| 166 | (defvar testcover-vector nil | 179 | (defvar testcover-vector nil |
| 167 | "Locally bound to coverage vector for function in progress.") | 180 | "Locally bound to coverage vector for function in progress.") |
| @@ -206,25 +219,32 @@ non-nil, byte-compiles each function after instrumenting." | |||
| 206 | x)) | 219 | x)) |
| 207 | 220 | ||
| 208 | (defun testcover-reinstrument (form) | 221 | (defun testcover-reinstrument (form) |
| 209 | "Reinstruments FORM to use testcover instead of edebug. This function | 222 | "Reinstruments FORM to use testcover instead of edebug. This |
| 210 | modifies the list that FORM points to. Result is non-nil if FORM will | 223 | function modifies the list that FORM points to. Result is nil if |
| 211 | always return the same value." | 224 | FORM should return multiple vlues, t if should always return same |
| 225 | value, 'maybe if either is acceptable." | ||
| 212 | (let ((fun (car-safe form)) | 226 | (let ((fun (car-safe form)) |
| 213 | id) | 227 | id val) |
| 214 | (cond | 228 | (cond |
| 215 | ((not fun) ;Atom | 229 | ((not fun) ;Atom |
| 216 | (or (not (symbolp form)) | 230 | (when (or (not (symbolp form)) |
| 217 | (memq form testcover-constants) | 231 | (memq form testcover-constants) |
| 218 | (memq form testcover-module-constants))) | 232 | (memq form testcover-module-constants)) |
| 219 | ((consp fun) ;Embedded list | 233 | t)) |
| 234 | ((consp fun) ;Embedded list | ||
| 220 | (testcover-reinstrument fun) | 235 | (testcover-reinstrument fun) |
| 221 | (testcover-reinstrument-list (cdr form)) | 236 | (testcover-reinstrument-list (cdr form)) |
| 222 | nil) | 237 | nil) |
| 223 | ((or (memq fun testcover-1value-functions) | 238 | ((or (memq fun testcover-1value-functions) |
| 224 | (memq fun testcover-module-1value-functions)) | 239 | (memq fun testcover-module-1value-functions)) |
| 225 | ;;Always return same value | 240 | ;;Should always return same value |
| 226 | (testcover-reinstrument-list (cdr form)) | 241 | (testcover-reinstrument-list (cdr form)) |
| 227 | t) | 242 | t) |
| 243 | ((or (memq fun testcover-potentially-1value-functions) | ||
| 244 | (memq fun testcover-module-potentially-1value-functions)) | ||
| 245 | ;;Might always return same value | ||
| 246 | (testcover-reinstrument-list (cdr form)) | ||
| 247 | 'maybe) | ||
| 228 | ((memq fun testcover-progn-functions) | 248 | ((memq fun testcover-progn-functions) |
| 229 | ;;1-valued if last argument is | 249 | ;;1-valued if last argument is |
| 230 | (testcover-reinstrument-list (cdr form))) | 250 | (testcover-reinstrument-list (cdr form))) |
| @@ -233,11 +253,9 @@ always return the same value." | |||
| 233 | (testcover-reinstrument-list (cddr form)) | 253 | (testcover-reinstrument-list (cddr form)) |
| 234 | (testcover-reinstrument (cadr form))) | 254 | (testcover-reinstrument (cadr form))) |
| 235 | ((memq fun testcover-compose-functions) | 255 | ((memq fun testcover-compose-functions) |
| 236 | ;;1-valued if all arguments are | 256 | ;;1-valued if all arguments are. Potentially 1-valued if all |
| 237 | (setq id t) | 257 | ;;arguments are either definitely or potentially. |
| 238 | (mapc #'(lambda (x) (setq id (or (testcover-reinstrument x) id))) | 258 | (testcover-reinstrument-compose (cdr form) 'testcover-reinstrument)) |
| 239 | (cdr form)) | ||
| 240 | id) | ||
| 241 | ((eq fun 'edebug-enter) | 259 | ((eq fun 'edebug-enter) |
| 242 | ;;(edebug-enter 'SYM ARGS #'(lambda nil FORMS)) | 260 | ;;(edebug-enter 'SYM ARGS #'(lambda nil FORMS)) |
| 243 | ;; => (testcover-enter 'SYM #'(lambda nil FORMS)) | 261 | ;; => (testcover-enter 'SYM #'(lambda nil FORMS)) |
| @@ -252,33 +270,44 @@ always return the same value." | |||
| 252 | (aset testcover-vector (cadr (cadr form)) 'ok-coverage)) | 270 | (aset testcover-vector (cadr (cadr form)) 'ok-coverage)) |
| 253 | (setq id (nth 2 form)) | 271 | (setq id (nth 2 form)) |
| 254 | (setcdr form (nthcdr 2 form)) | 272 | (setcdr form (nthcdr 2 form)) |
| 273 | (setq val (testcover-reinstrument (nth 2 form))) | ||
| 274 | (if (eq val t) | ||
| 275 | (setcar form 'testcover-1value) | ||
| 276 | (setcar form 'testcover-after)) | ||
| 277 | (when val | ||
| 278 | ;;1-valued or potentially 1-valued | ||
| 279 | (aset testcover-vector id '1value)) | ||
| 255 | (cond | 280 | (cond |
| 256 | ((memq (car-safe (nth 2 form)) testcover-noreturn-functions) | 281 | ((memq (car-safe (nth 2 form)) testcover-noreturn-functions) |
| 257 | ;;This function won't return, so set the value in advance | 282 | ;;This function won't return, so set the value in advance |
| 258 | ;;(edebug-after (edebug-before XXX) YYY FORM) | 283 | ;;(edebug-after (edebug-before XXX) YYY FORM) |
| 259 | ;; => (progn (edebug-after YYY nil) FORM) | 284 | ;; => (progn (edebug-after YYY nil) FORM) |
| 285 | (setcar (cdr form) `(,(car form) ,id nil)) | ||
| 260 | (setcar form 'progn) | 286 | (setcar form 'progn) |
| 261 | (setcar (cdr form) `(testcover-after ,id nil))) | 287 | (aset testcover-vector id '1value) |
| 288 | (setq val t)) | ||
| 262 | ((eq (car-safe (nth 2 form)) '1value) | 289 | ((eq (car-safe (nth 2 form)) '1value) |
| 263 | ;;This function is always supposed to return the same value | 290 | ;;This function is always supposed to return the same value |
| 264 | (setcar form 'testcover-1value)) | 291 | (setq val t) |
| 265 | (t | 292 | (aset testcover-vector id '1value) |
| 266 | (setcar form 'testcover-after))) | 293 | (setcar form 'testcover-1value))) |
| 267 | (when (testcover-reinstrument (nth 2 form)) | 294 | val) |
| 268 | (aset testcover-vector id '1value))) | ||
| 269 | ((eq fun 'defun) | 295 | ((eq fun 'defun) |
| 270 | (if (testcover-reinstrument-list (nthcdr 3 form)) | 296 | (setq val (testcover-reinstrument-list (nthcdr 3 form))) |
| 271 | (push (cadr form) testcover-module-1value-functions))) | 297 | (when (eq val t) |
| 272 | ((eq fun 'defconst) | 298 | (push (cadr form) testcover-module-1value-functions)) |
| 299 | (when (eq val 'maybe) | ||
| 300 | (push (cadr form) testcover-module-potentially-1value-functions))) | ||
| 301 | ((memq fun '(defconst defcustom)) | ||
| 273 | ;;Define this symbol as 1-valued | 302 | ;;Define this symbol as 1-valued |
| 274 | (push (cadr form) testcover-module-constants) | 303 | (push (cadr form) testcover-module-constants) |
| 275 | (testcover-reinstrument-list (cddr form))) | 304 | (testcover-reinstrument-list (cddr form))) |
| 276 | ((memq fun '(dotimes dolist)) | 305 | ((memq fun '(dotimes dolist)) |
| 277 | ;;Always returns third value from SPEC | 306 | ;;Always returns third value from SPEC |
| 278 | (testcover-reinstrument-list (cddr form)) | 307 | (testcover-reinstrument-list (cddr form)) |
| 279 | (setq fun (testcover-reinstrument-list (cadr form))) | 308 | (setq val (testcover-reinstrument-list (cadr form))) |
| 280 | (if (nth 2 (cadr form)) | 309 | (if (nth 2 (cadr form)) |
| 281 | fun | 310 | val |
| 282 | ;;No third value, always returns nil | 311 | ;;No third value, always returns nil |
| 283 | t)) | 312 | t)) |
| 284 | ((memq fun '(let let*)) | 313 | ((memq fun '(let let*)) |
| @@ -286,23 +315,23 @@ always return the same value." | |||
| 286 | (mapc 'testcover-reinstrument-list (cadr form)) | 315 | (mapc 'testcover-reinstrument-list (cadr form)) |
| 287 | (testcover-reinstrument-list (cddr form))) | 316 | (testcover-reinstrument-list (cddr form))) |
| 288 | ((eq fun 'if) | 317 | ((eq fun 'if) |
| 289 | ;;1-valued if both THEN and ELSE clauses are | 318 | ;;Potentially 1-valued if both THEN and ELSE clauses are |
| 290 | (testcover-reinstrument (cadr form)) | 319 | (testcover-reinstrument (cadr form)) |
| 291 | (let ((then (testcover-reinstrument (nth 2 form))) | 320 | (let ((then (testcover-reinstrument (nth 2 form))) |
| 292 | (else (testcover-reinstrument-list (nthcdr 3 form)))) | 321 | (else (testcover-reinstrument-list (nthcdr 3 form)))) |
| 293 | (and then else))) | 322 | (and then else 'maybe))) |
| 294 | ((memq fun '(when unless and)) | ||
| 295 | ;;1-valued if last clause of BODY is | ||
| 296 | (testcover-reinstrument-list (cdr form))) | ||
| 297 | ((eq fun 'cond) | 323 | ((eq fun 'cond) |
| 298 | ;;1-valued if all clauses are | 324 | ;;Potentially 1-valued if all clauses are |
| 299 | (testcover-reinstrument-clauses (cdr form))) | 325 | (when (testcover-reinstrument-compose (cdr form) |
| 326 | 'testcover-reinstrument-list) | ||
| 327 | 'maybe)) | ||
| 300 | ((eq fun 'condition-case) | 328 | ((eq fun 'condition-case) |
| 301 | ;;1-valued if BODYFORM is and all HANDLERS are | 329 | ;;Potentially 1-valued if BODYFORM is and all HANDLERS are |
| 302 | (let ((body (testcover-reinstrument (nth 2 form))) | 330 | (let ((body (testcover-reinstrument (nth 2 form))) |
| 303 | (errs (testcover-reinstrument-clauses (mapcar #'cdr | 331 | (errs (testcover-reinstrument-compose |
| 304 | (nthcdr 3 form))))) | 332 | (mapcar #'cdr (nthcdr 3 form)) |
| 305 | (and body errs))) | 333 | 'testcover-reinstrument-list))) |
| 334 | (and body errs 'maybe))) | ||
| 306 | ((eq fun 'quote) | 335 | ((eq fun 'quote) |
| 307 | ;;Don't reinstrument what's inside! | 336 | ;;Don't reinstrument what's inside! |
| 308 | ;;This doesn't apply within a backquote | 337 | ;;This doesn't apply within a backquote |
| @@ -317,16 +346,55 @@ always return the same value." | |||
| 317 | (let ((testcover-1value-functions | 346 | (let ((testcover-1value-functions |
| 318 | (remq 'quote testcover-1value-functions))) | 347 | (remq 'quote testcover-1value-functions))) |
| 319 | (testcover-reinstrument (cadr form)))) | 348 | (testcover-reinstrument (cadr form)))) |
| 320 | ((memq fun '(1value noreturn)) | 349 | ((eq fun '1value) |
| 321 | ;;Hack - pretend the arg is 1-valued here | 350 | ;;Hack - pretend the arg is 1-valued here |
| 322 | (if (symbolp (cadr form)) ;A pseudoconstant variable | 351 | (cond |
| 323 | t | 352 | ((symbolp (cadr form)) |
| 353 | ;;A pseudoconstant variable | ||
| 354 | t) | ||
| 355 | ((and (eq (car (cadr form)) 'edebug-after) | ||
| 356 | (symbolp (nth 3 (cadr form)))) | ||
| 357 | ;;Reference to pseudoconstant | ||
| 358 | (aset testcover-vector (nth 2 (cadr form)) '1value) | ||
| 359 | (setcar (cdr form) `(testcover-1value ,(nth 2 (cadr form)) | ||
| 360 | ,(nth 3 (cadr form)))) | ||
| 361 | t) | ||
| 362 | (t | ||
| 324 | (if (eq (car (cadr form)) 'edebug-after) | 363 | (if (eq (car (cadr form)) 'edebug-after) |
| 325 | (setq id (car (nth 3 (cadr form)))) | 364 | (setq id (car (nth 3 (cadr form)))) |
| 326 | (setq id (car (cadr form)))) | 365 | (setq id (car (cadr form)))) |
| 327 | (let ((testcover-1value-functions | 366 | (let ((testcover-1value-functions |
| 328 | (cons id testcover-1value-functions))) | 367 | (cons id testcover-1value-functions))) |
| 329 | (testcover-reinstrument (cadr form))))) | 368 | (testcover-reinstrument (cadr form)))))) |
| 369 | ((eq fun 'noreturn) | ||
| 370 | ;;Hack - pretend the arg has no return | ||
| 371 | (cond | ||
| 372 | ((symbolp (cadr form)) | ||
| 373 | ;;A pseudoconstant variable | ||
| 374 | 'maybe) | ||
| 375 | ((and (eq (car (cadr form)) 'edebug-after) | ||
| 376 | (symbolp (nth 3 (cadr form)))) | ||
| 377 | ;;Reference to pseudoconstant | ||
| 378 | (aset testcover-vector (nth 2 (cadr form)) '1value) | ||
| 379 | (setcar (cdr form) `(progn (testcover-after ,(nth 2 (cadr form)) nil) | ||
| 380 | ,(nth 3 (cadr form)))) | ||
| 381 | 'maybe) | ||
| 382 | (t | ||
| 383 | (if (eq (car (cadr form)) 'edebug-after) | ||
| 384 | (setq id (car (nth 3 (cadr form)))) | ||
| 385 | (setq id (car (cadr form)))) | ||
| 386 | (let ((testcover-noreturn-functions | ||
| 387 | (cons id testcover-noreturn-functions))) | ||
| 388 | (testcover-reinstrument (cadr form)))))) | ||
| 389 | ((and (eq fun 'apply) | ||
| 390 | (eq (car-safe (cadr form)) 'quote) | ||
| 391 | (symbolp (cadr (cadr form)))) | ||
| 392 | ;;Apply of a constant symbol. Process as 1value or noreturn | ||
| 393 | ;;depending on symbol. | ||
| 394 | (setq fun (cons (cadr (cadr form)) (cddr form)) | ||
| 395 | val (testcover-reinstrument fun)) | ||
| 396 | (setcdr (cdr form) (cdr fun)) | ||
| 397 | val) | ||
| 330 | (t ;Some other function or weird thing | 398 | (t ;Some other function or weird thing |
| 331 | (testcover-reinstrument-list (cdr form)) | 399 | (testcover-reinstrument-list (cdr form)) |
| 332 | nil)))) | 400 | nil)))) |
| @@ -341,13 +409,22 @@ always be nil, so we return t for 1-valued." | |||
| 341 | (setq result (testcover-reinstrument (pop list)))) | 409 | (setq result (testcover-reinstrument (pop list)))) |
| 342 | result)) | 410 | result)) |
| 343 | 411 | ||
| 344 | (defun testcover-reinstrument-clauses (clauselist) | 412 | (defun testcover-reinstrument-compose (list fun) |
| 345 | "Reinstrument each list in CLAUSELIST. | 413 | "For a compositional function, the result is 1-valued if all |
| 346 | Result is t if every clause is 1-valued." | 414 | arguments are, potentially 1-valued if all arguments are either |
| 415 | definitely or potentially 1-valued, and multi-valued otherwise. | ||
| 416 | FUN should be `testcover-reinstrument' for compositional functions, | ||
| 417 | `testcover-reinstrument-list' for clauses in a `cond'." | ||
| 347 | (let ((result t)) | 418 | (let ((result t)) |
| 348 | (mapc #'(lambda (x) | 419 | (mapc #'(lambda (x) |
| 349 | (setq result (and (testcover-reinstrument-list x) result))) | 420 | (setq x (funcall fun x)) |
| 350 | clauselist) | 421 | (cond |
| 422 | ((eq result t) | ||
| 423 | (setq result x)) | ||
| 424 | ((eq result 'maybe) | ||
| 425 | (when (not x) | ||
| 426 | (setq result nil))))) | ||
| 427 | list) | ||
| 351 | result)) | 428 | result)) |
| 352 | 429 | ||
| 353 | (defun testcover-end (buffer) | 430 | (defun testcover-end (buffer) |
| @@ -387,7 +464,7 @@ same value during coverage testing." | |||
| 387 | (aset testcover-vector idx (cons '1value val))) | 464 | (aset testcover-vector idx (cons '1value val))) |
| 388 | ((not (and (eq (car-safe (aref testcover-vector idx)) '1value) | 465 | ((not (and (eq (car-safe (aref testcover-vector idx)) '1value) |
| 389 | (equal (cdr (aref testcover-vector idx)) val))) | 466 | (equal (cdr (aref testcover-vector idx)) val))) |
| 390 | (error "Value of form marked with `1value' does vary."))) | 467 | (error "Value of form marked with `1value' does vary: %s" val))) |
| 391 | val) | 468 | val) |
| 392 | 469 | ||
| 393 | 470 | ||
| @@ -415,7 +492,7 @@ eliminated by adding more test cases." | |||
| 415 | ov j item) | 492 | ov j item) |
| 416 | (or (and def-mark points coverage) | 493 | (or (and def-mark points coverage) |
| 417 | (error "Missing edebug data for function %s" def)) | 494 | (error "Missing edebug data for function %s" def)) |
| 418 | (when len | 495 | (when (> len 0) |
| 419 | (set-buffer (marker-buffer def-mark)) | 496 | (set-buffer (marker-buffer def-mark)) |
| 420 | (mapc 'delete-overlay | 497 | (mapc 'delete-overlay |
| 421 | (overlays-in def-mark (+ def-mark (aref points (1- len)) 1))) | 498 | (overlays-in def-mark (+ def-mark (aref points (1- len)) 1))) |