From 032e89325299463c59afce132ff639bd307caa83 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Sat, 25 Jan 2025 18:39:23 +0100 Subject: [PATCH] Start refactoring scope.el --- lisp/emacs-lisp/scope.el | 29 +++++++++++++++++--- lisp/progmodes/elisp-mode.el | 21 ++++----------- lisp/progmodes/refactor-elisp.el | 45 +++++++++----------------------- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/lisp/emacs-lisp/scope.el b/lisp/emacs-lisp/scope.el index d80d907eb0b..7473c62bb36 100644 --- a/lisp/emacs-lisp/scope.el +++ b/lisp/emacs-lisp/scope.el @@ -32,6 +32,10 @@ (defvar scope-callback #'ignore) +(defvar scope-current-let-alist-form nil) + +(defvar scope-gen-id-alist nil) + (defsubst scope-local-get (sym local) "Get binding position of symbol SYM in local context LOCAL." (alist-get sym local)) @@ -50,14 +54,25 @@ Optional argument LOCAL is a local context to extend." ((symbolp sym) sym) ((symbol-with-pos-p sym) (bare-symbol sym)))) +(defsubst scope-report (type beg len &optional def _id) + (funcall scope-callback type beg len def)) + (defun scope-s (local sym) (let* ((beg (scope-sym-pos sym)) (bare (bare-symbol sym)) - (len (length (symbol-name bare)))) + (name (symbol-name bare)) + (len (length name))) (when (and beg (not (booleanp bare))) - (if (keywordp bare) - (funcall scope-callback 'constant beg len nil) - (funcall scope-callback 'variable beg len (scope-local-get bare local)))))) + (cond + ((keywordp bare) (scope-report 'constant beg len)) + ((and scope-current-let-alist-form (= (aref name 0) ?.)) + ;; FIXME: Support jumping to `let-alist' call as the + ;; "definition" of the `.foo' variables. + (scope-report 'variable beg len (cdr scope-current-let-alist-form) + (list 'let-alist (car scope-current-let-alist-form) bare))) + (t (scope-report 'variable beg len (scope-local-get bare local) + (or (alist-get bare scope-gen-id-alist) + (scope-local-get bare local)))))))) (defun scope-let-1 (local0 local bindings body) (if bindings @@ -1360,6 +1375,12 @@ a (possibly empty) list of safe macros.") (symbol-with-pos-pos f) (length (symbol-name bare)) nil)) (cond + ((memq bare '(let-alist)) + (scope-1 local (car forms)) + (let ((scope-current-let-alist-form + (or (scope-sym-pos f) + (cons 'gen (cl-incf scope-counter))))) + (scope-n local (cdr forms)))) ((eq (get bare 'edebug-form-spec) t) (scope-n local forms)) ((eq bare 'lambda) (scope-lambda local (car forms) (cdr forms))) ((eq bare 'cl-loop) (scope-loop local forms)) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 5627e0c5558..b77ad25c548 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -382,20 +382,10 @@ happens in interactive invocations." (defun elisp-highlight-variable (pos) "Highlight variable at POS along with its co-occurrences." - (let* (all dec) - (save-excursion - (goto-char pos) - (beginning-of-defun) - (scope (lambda (_type beg len bin) - (when (<= beg pos (+ beg len)) - (setq dec bin)) - (when bin (push (list beg len bin) all))) - (current-buffer))) - (pcase-dolist (`(,sym ,len ,bin) all) - (when (equal bin dec) - (let ((ov (make-overlay sym (+ sym len)))) - (overlay-put ov 'face 'elisp-variable-at-point) - (overlay-put ov 'elisp-highlight-variable t)))))) + (pcase-dolist (`(,beg . ,len) (elisp-local-references pos)) + (let ((ov (make-overlay beg (+ beg len)))) + (overlay-put ov 'face 'elisp-variable-at-point) + (overlay-put ov 'elisp-highlight-variable t)))) (defun elisp-unhighlight-variable (pos) "Remove variable highlighting across top-level form at POS." @@ -1189,8 +1179,7 @@ confidence." (require 'find-func) (let ((sym (intern-soft identifier))) (when sym - (let* ((pos (get-text-property 0 'pos identifier)) - (namespace (if (and pos + (let* ((namespace (if (and pos ;; Reusing it in Help Mode. (derived-mode-p 'emacs-lisp-mode)) (elisp--xref-infer-namespace pos) diff --git a/lisp/progmodes/refactor-elisp.el b/lisp/progmodes/refactor-elisp.el index 172476741f7..e4de59e02e1 100644 --- a/lisp/progmodes/refactor-elisp.el +++ b/lisp/progmodes/refactor-elisp.el @@ -44,40 +44,22 @@ (cl-defmethod refactor-backend-rename-edits ((_backend (eql elisp)) old new (_scope (eql nil))) - (let* ((pos (get-text-property 0 'pos old)) - all dec) - (save-excursion - (goto-char pos) - (beginning-of-defun) - (scope (lambda (_type beg len bin) - (when (<= beg pos (+ beg len)) - (setq dec bin)) - (when bin (push (list beg len bin) all))))) - (list - (cons (current-buffer) - (let (res) - (pcase-dolist (`(,beg ,len ,bin) all) - (when (equal bin dec) - (alist-set beg res (list (+ beg len) new)))) - res))))) + (list (cons (current-buffer) + (let (res) + (pcase-dolist (`(,beg . ,len) + (elisp-local-references + (get-text-property 0 'pos old))) + (alist-set beg res (list (+ beg len) new))) + res)))) (cl-defmethod refactor-backend-rename-highlight-regions ((_backend (eql elisp)) old (_scope (eql nil))) - (let* ((pos (get-text-property 0 'pos old)) - all dec) - (save-excursion - (goto-char pos) - (beginning-of-defun) - (scope (lambda (_type beg len bin) - (when (<= beg pos (+ beg len)) - (setq dec bin)) - (when bin (push (list beg len bin) all))))) - (when dec - (let (res) - (pcase-dolist (`(,beg ,len ,bin) all) - (when (equal bin dec) - (alist-set beg res (+ beg len)))) - res)))) + (let (res) + (pcase-dolist (`(,beg . ,len) + (elisp-local-references + (get-text-property 0 'pos old))) + (alist-set beg res (+ beg len))) + res)) (cl-defmethod refactor-backend-extract-validate-region ((_backend (eql elisp)) beg end) @@ -91,7 +73,6 @@ ;; - Handle local function bindings (e.g. `named-let'). ;; - Remove redundant `progn' around extracted forms. ;; - Find more occurrences of extracted form, maybe with el-search. - ;; - Extract form to local/global variable. (goto-char beg) (beginning-of-defun-raw) (let (bound) -- 2.39.5