diff options
| author | Lars Ingebrigtsen | 2019-10-20 13:10:59 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2019-10-20 13:11:04 +0200 |
| commit | a4e7c15484a9330fb9e1a1b425fcf1b37bad04e1 (patch) | |
| tree | 33db809baf378a77d04002d338c291232e12acb7 | |
| parent | 0cbcd2869e46f2ede0d08fd183d6c0ad0ebd8394 (diff) | |
| download | emacs-a4e7c15484a9330fb9e1a1b425fcf1b37bad04e1.tar.gz emacs-a4e7c15484a9330fb9e1a1b425fcf1b37bad04e1.zip | |
Preserve breakpoints when Edebug-reinstrumenting functions
* lisp/emacs-lisp/edebug.el (edebug--overlay-breakpoints): New
function (bug#23470).
* lisp/emacs-lisp/seq.el (seq-position): Autoload.
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/emacs-lisp/edebug.el | 33 | ||||
| -rw-r--r-- | lisp/emacs-lisp/seq.el | 1 |
3 files changed, 33 insertions, 6 deletions
| @@ -1462,6 +1462,11 @@ the Elisp manual for documentation of the new mode and its commands. | |||
| 1462 | 1462 | ||
| 1463 | ** Edebug | 1463 | ** Edebug |
| 1464 | 1464 | ||
| 1465 | --- | ||
| 1466 | *** Re-instrumenting a function with Edebug will now try to preserve | ||
| 1467 | previously-set breakpoints. If the code has changed substantially, | ||
| 1468 | this may not be possible. | ||
| 1469 | |||
| 1465 | +++ | 1470 | +++ |
| 1466 | *** New command 'edebug-remove-instrumentation. | 1471 | *** New command 'edebug-remove-instrumentation. |
| 1467 | This command removes Edebug instrumentation from all functions that | 1472 | This command removes Edebug instrumentation from all functions that |
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 893c821f086..68b2126345f 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el | |||
| @@ -1403,15 +1403,33 @@ contains a circular object." | |||
| 1403 | (put edebug-def-name 'edebug | 1403 | (put edebug-def-name 'edebug |
| 1404 | ;; A struct or vector would be better here!! | 1404 | ;; A struct or vector would be better here!! |
| 1405 | (list edebug-form-begin-marker | 1405 | (list edebug-form-begin-marker |
| 1406 | nil ; clear breakpoints | 1406 | (edebug--restore-breakpoints edebug-old-def-name) |
| 1407 | edebug-offset-list | 1407 | edebug-offset-list |
| 1408 | edebug-top-window-data | 1408 | edebug-top-window-data)) |
| 1409 | )) | ||
| 1410 | 1409 | ||
| 1411 | (funcall edebug-new-definition-function edebug-def-name) | 1410 | (funcall edebug-new-definition-function edebug-def-name) |
| 1412 | result | 1411 | result |
| 1413 | ))) | 1412 | ))) |
| 1414 | 1413 | ||
| 1414 | (defun edebug--restore-breakpoints (name) | ||
| 1415 | (let* ((data (get name 'edebug)) | ||
| 1416 | (offsets (nth 2 data)) | ||
| 1417 | (breakpoints (nth 1 data)) | ||
| 1418 | (start (nth 0 data)) | ||
| 1419 | index) | ||
| 1420 | ;; Breakpoints refer to offsets from the start of the function. | ||
| 1421 | ;; The start position is a marker, so it'll move around in a | ||
| 1422 | ;; similar fashion as the breakpoint markers. If we find a | ||
| 1423 | ;; breakpoint marker that refers to an offset (which is a place | ||
| 1424 | ;; where breakpoints can be made), then we restore it. | ||
| 1425 | (cl-loop for breakpoint in breakpoints | ||
| 1426 | for marker = (nth 3 breakpoint) | ||
| 1427 | when (and (marker-position marker) | ||
| 1428 | (setq index (seq-position | ||
| 1429 | offsets | ||
| 1430 | (- (marker-position marker) start)))) | ||
| 1431 | collect (cons index (cdr breakpoint))))) | ||
| 1432 | |||
| 1415 | (defun edebug-new-definition (def-name) | 1433 | (defun edebug-new-definition (def-name) |
| 1416 | "Set up DEF-NAME to use Edebug's instrumentation functions." | 1434 | "Set up DEF-NAME to use Edebug's instrumentation functions." |
| 1417 | (put def-name 'edebug-behavior 'edebug) | 1435 | (put def-name 'edebug-behavior 'edebug) |
| @@ -3166,6 +3184,7 @@ the breakpoint." | |||
| 3166 | (edebug-def-mark (car edebug-data)) | 3184 | (edebug-def-mark (car edebug-data)) |
| 3167 | (edebug-breakpoints (car (cdr edebug-data))) | 3185 | (edebug-breakpoints (car (cdr edebug-data))) |
| 3168 | (offset-vector (nth 2 edebug-data)) | 3186 | (offset-vector (nth 2 edebug-data)) |
| 3187 | (position (+ edebug-def-mark (aref offset-vector index))) | ||
| 3169 | present) | 3188 | present) |
| 3170 | ;; delete it either way | 3189 | ;; delete it either way |
| 3171 | (setq present (assq index edebug-breakpoints)) | 3190 | (setq present (assq index edebug-breakpoints)) |
| @@ -3176,8 +3195,10 @@ the breakpoint." | |||
| 3176 | (setq edebug-breakpoints | 3195 | (setq edebug-breakpoints |
| 3177 | (edebug-sort-alist | 3196 | (edebug-sort-alist |
| 3178 | (cons | 3197 | (cons |
| 3179 | (list index condition temporary) | 3198 | (list index condition temporary |
| 3180 | edebug-breakpoints) '<)) | 3199 | (set-marker (make-marker) position)) |
| 3200 | edebug-breakpoints) | ||
| 3201 | '<)) | ||
| 3181 | (if condition | 3202 | (if condition |
| 3182 | (message "Breakpoint set in %s with condition: %s" | 3203 | (message "Breakpoint set in %s with condition: %s" |
| 3183 | edebug-def-name condition) | 3204 | edebug-def-name condition) |
| @@ -3187,7 +3208,7 @@ the breakpoint." | |||
| 3187 | (message "No breakpoint here"))) | 3208 | (message "No breakpoint here"))) |
| 3188 | 3209 | ||
| 3189 | (setcar (cdr edebug-data) edebug-breakpoints) | 3210 | (setcar (cdr edebug-data) edebug-breakpoints) |
| 3190 | (goto-char (+ edebug-def-mark (aref offset-vector index))) | 3211 | (goto-char position) |
| 3191 | (edebug--overlay-breakpoints edebug-def-name))))) | 3212 | (edebug--overlay-breakpoints edebug-def-name))))) |
| 3192 | 3213 | ||
| 3193 | (defun edebug--overlay-breakpoints (function) | 3214 | (defun edebug--overlay-breakpoints (function) |
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index f001dceecec..8d4093004a7 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el | |||
| @@ -380,6 +380,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil." | |||
| 380 | (and (seq-every-p (lambda (item1) (seq-contains-p sequence2 item1 testfn)) sequence1) | 380 | (and (seq-every-p (lambda (item1) (seq-contains-p sequence2 item1 testfn)) sequence1) |
| 381 | (seq-every-p (lambda (item2) (seq-contains-p sequence1 item2 testfn)) sequence2))) | 381 | (seq-every-p (lambda (item2) (seq-contains-p sequence1 item2 testfn)) sequence2))) |
| 382 | 382 | ||
| 383 | ;;;###autoload | ||
| 383 | (cl-defgeneric seq-position (sequence elt &optional testfn) | 384 | (cl-defgeneric seq-position (sequence elt &optional testfn) |
| 384 | "Return the index of the first element in SEQUENCE that is equal to ELT. | 385 | "Return the index of the first element in SEQUENCE that is equal to ELT. |
| 385 | Equality is defined by TESTFN if non-nil or by `equal' if nil." | 386 | Equality is defined by TESTFN if non-nil or by `equal' if nil." |