]> git.eshelyaron.com Git - emacs.git/commitdiff
Start refactoring scope.el
authorEshel Yaron <me@eshelyaron.com>
Sat, 25 Jan 2025 17:39:23 +0000 (18:39 +0100)
committerEshel Yaron <me@eshelyaron.com>
Sat, 25 Jan 2025 17:39:46 +0000 (18:39 +0100)
lisp/emacs-lisp/scope.el
lisp/progmodes/elisp-mode.el
lisp/progmodes/refactor-elisp.el

index d80d907eb0ba616eac578c50a1dd6ff3c13ff45b..7473c62bb36446f937998c11e90a9c41142716d9 100644 (file)
 
 (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))
index 5627e0c55580ebe226aacdd9124def253fc7e894..b77ad25c54848d2adf0fcdeb02274c391ef9afc2 100644 (file)
@@ -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)
index 172476741f72e6fbfaf8ccc7b65c9a384c4a34a5..e4de59e02e1fc11eee98a577314b85e5740bd63e 100644 (file)
 
 (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)