(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))
((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
(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))
(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."
(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)
(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)
;; - 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)