New variable 'macroexp-enable-pos-preservation' (bug#79599)

* lisp/emacs-lisp/macroexp.el
(macroexp-enable-pos-preservation): New variable.
(macroexp-preserve-posification): Respect it.
* lisp/emacs-lisp/elisp-scope.el (elisp-scope-1): Use it.
* test/lisp/emacs-lisp/macroexp-tests.el
(macroexp--test-macroexp-enable-pos-preservation): New test.
This commit is contained in:
Eshel Yaron 2026-06-20 17:35:09 +02:00 committed by Sean Whitton
parent 00c290be85
commit 2066a0c9e8
3 changed files with 26 additions and 1 deletions

View file

@ -2794,6 +2794,7 @@ are analyzed."
(symbols-with-pos-enabled t)
(message-log-max nil)
(inhibit-message t)
(macroexp-enable-pos-preservation nil)
(macroexpand-all-environment
(append (mapcar #'list elisp-scope-unsafe-macros) macroexpand-all-environment)))
(ignore-errors (macroexpand-1 form macroexpand-all-environment)))

View file

@ -304,6 +304,9 @@ modified FORM."
(let ((new-form (macroexp--posify-form-1 form call-pos 10)))
(or new-form form)))
(defvar macroexp-enable-pos-preservation t
"Whether to attach position of a macro call to the expanded form.")
(defmacro macroexp-preserve-posification (pos-form &rest body)
"Evaluate BODY..., posifying the result with POS-FORM's position, if any.
If the result of body happens to have a position already, we do not
@ -316,7 +319,7 @@ change this."
((symbol-with-pos-p ,pos-form)
(symbol-with-pos-pos ,pos-form))))
(new-value (progn ,@body)))
(if (and call-pos
(if (and macroexp-enable-pos-preservation call-pos
(not (or (and (consp new-value)
(symbol-with-pos-p (car new-value)))
(and (symbol-with-pos-p new-value)))))

View file

@ -182,4 +182,25 @@
(user-error (error-message-string err))))))
(should (and (stringp res) (string-match "new-replacement" res))))))
(defmacro macroexp--test-with-foo (&rest body)
"Eagerly macro-expand BODY."
(macroexpand-all `(progn . ,body) macroexpand-all-environment))
(ert-deftest macroexp--test-macroexp-enable-pos-preservation ()
(let* ((symbols-with-pos-enabled t)
(form (read-positioning-symbols
"(macroexp--test-with-foo (pop command-history))"))
(pop-pos (symbol-with-pos-pos (caadr form)))
(exp1 (macroexpand-1 form))
(macroexp-enable-pos-preservation nil)
(exp2 (macroexpand-1 form)))
;; Position of `pop' preserved in EXP1. There's no way to tell that
;; the position information in EXP1 is synthetic, which may confuse
;; consumers such as semantic highlighting.
(should (symbol-with-pos-p (caadr exp1)))
(should (= (symbol-with-pos-pos (caadr exp1)) pop-pos))
;; Position preservation was disabled, so EXP2 is clean of synthetic
;; position information.
(should-not (symbol-with-pos-p (caadr exp2)))))
;;; macroexp-tests.el ends here