bindings)
(let ((l local))
(dolist (binding bindings)
- (let ((sym (if (consp binding) (car binding) binding)))
- (when binding
- (setq l (scope-local-new (bare-symbol sym) (symbol-with-pos-pos sym) l)))))
+ (when-let ((sym (if (consp binding) (car binding) binding)))
+ (setq l (scope-local-new (bare-symbol sym) (symbol-with-pos-pos sym) l))))
(scope-n l body))))
(defun scope-let* (local bindings body)
(mapcan (apply-partially #'scope-n local) clauses))
(defun scope-setq (local args)
- (cl-loop for (var val) on args by #'cddr
- nconc (nconc (scope-s local var) (scope-1 local val))))
+ (when args
+ (let ((var (car args)) (val (cadr args)))
+ (nconc (scope-s local var)
+ (scope-1 local val)
+ (scope-setq local (cddr args))))))
(defun scope-defvar (local _sym init) (scope-1 local init))
(scope-loop-with local (car rest) (cadr rest) (caddr rest) (cdddr rest)))
((memq bare '(do)) (scope-loop-do local (car rest) (cdr rest))))))))))
+(defun scope-named-let (local name bindings body)
+ (let ((bare (bare-symbol name))
+ (beg (symbol-with-pos-pos name)))
+ (cons
+ (list beg (length (symbol-name bare)) beg)
+ (nconc
+ (mapcan (lambda (binding)
+ (cond
+ ((consp binding)
+ (cons
+ (let* ((sym (car binding))
+ (beg (symbol-with-pos-pos sym))
+ (bare (bare-symbol sym))
+ (len (length (symbol-name bare))))
+ (list beg len beg))
+ (scope-1 local (cadr binding))))
+ (binding
+ (let* ((sym binding)
+ (beg (symbol-with-pos-pos sym))
+ (bare (bare-symbol sym))
+ (len (length (symbol-name bare))))
+ (list (list beg len beg))))))
+ bindings)
+ (let ((l (scope-local-new bare beg local)))
+ (dolist (binding bindings)
+ (when-let ((sym (if (consp binding) (car binding) binding)))
+ (setq l (scope-local-new (bare-symbol sym) (symbol-with-pos-pos sym) l))))
+ (let ((scope-flet-list (cons bare scope-flet-list))) (scope-n l body)))))))
+
(defvar scope-assume-func-p nil)
(defun scope-1 (local form &optional top-level)
((symbol-with-pos-p f)
(let ((bare (bare-symbol f)))
(cond
- ((or (functionp bare)
- (memq bare '( if and or while
+ ((functionp bare) ;; (scope-n local forms)
+ (cons
+ (list (symbol-with-pos-pos f) (length (symbol-name bare)) 'function)
+ (scope-n local forms)))
+ ((or (memq bare '( if and or while
save-excursion save-restriction save-current-buffer
catch unwind-protect
progn prog1 eval-when-compile eval-and-compile with-eval-after-load
((memq bare '(declare-function))
(scope-declare-function local (car forms) (cadr forms)
(caddr forms) (cadddr forms)))
+ ((memq bare '(let-when-compile))
+ (scope-let* local (car forms) (cdr forms)))
((memq bare '(if-let when-let and-let))
(scope-if-let local (car forms) (cdr forms)))
((memq bare '(if-let* when-let* and-let* while-let))
(scope-1 local (car forms)))
((memq bare '(letrec))
(scope-letrec local (car forms) (cdr forms)))
+ ((memq bare '(named-let))
+ (scope-named-let local (car forms) (cadr forms) (cdr forms)))
((memq bare '(cl-flet))
(scope-flet local (car forms) (cdr forms)))
((memq bare '(cl-labels))
`scope-n' to obtain bindings graphs for sub-forms. See also
`scope-local-new' for extending LOCAL with local bindings in TAIL.
-- If within the code under analysis HEAD is a `cl-letf'-bound local
+- If within the code under analysis HEAD is a `cl-flet'-bound local
function name, analyze the form as a function call.
- Otherwise, HEAD is unknown. If the HEAD of the top-level form that
(condition-case nil
(scope (current-buffer))
(end-of-file nil)))
- (if (null bin)
- (font-lock-append-text-property sym (+ sym len) 'face 'elisp-free-variable)
+ (cond
+ ((numberp bin)
(font-lock-append-text-property sym (+ sym len) 'face (if (= sym bin)
'elisp-binding-variable
'elisp-bound-variable))
(put-text-property sym (+ sym len 1) 'cursor-sensor-functions
- (elisp-cursor-sensor bin))))))
+ (elisp-cursor-sensor bin)))
+ ((eq bin 'function)
+ (font-lock-append-text-property sym (+ sym len) 'face 'font-lock-function-call-face))
+ (t (font-lock-append-text-property sym (+ sym len) 'face 'elisp-free-variable))))))
`(jit-lock-bounds ,beg . ,end)))
(font-lock-default-fontify-region beg end loudly)))
\\{emacs-lisp-mode-map}"
:group 'lisp
(defvar project-vc-external-roots-function)
+ (setq font-lock-defaults (copy-tree font-lock-defaults))
(setcar font-lock-defaults
'(lisp-el-font-lock-keywords
lisp-el-font-lock-keywords-1
(setcdr (nthcdr 4 font-lock-defaults)
(cons '(font-lock-fontify-region-function . elisp-fontify-region)
(nthcdr 5 font-lock-defaults)))
- (push 'cursor-sensor-functions
- (alist-get 'font-lock-extra-managed-props (nthcdr 5 font-lock-defaults)))
+ (unless (memq 'cursor-sensor-functions
+ (alist-get 'font-lock-extra-managed-props (nthcdr 5 font-lock-defaults)))
+ (push 'cursor-sensor-functions
+ (alist-get 'font-lock-extra-managed-props (nthcdr 5 font-lock-defaults))))
(setf (nth 2 font-lock-defaults) nil)
(add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
(if (boundp 'electric-pair-text-pairs)
(cl-defmethod xref-backend-definitions ((_backend (eql 'elisp)) identifier)
(let* ((pos (get-text-property 0 'pos identifier))
- (dec (seq-some
- (pcase-lambda (`(,beg ,len ,dec))
- (when (<= beg pos (+ beg len)) dec))
- (save-excursion
- (goto-char pos)
- (beginning-of-defun)
- (scope (current-buffer))))))
- (if dec (list (xref-make "lexical binding"
- (xref-make-buffer-location (current-buffer) dec)))
+ (dec (when pos
+ (seq-some
+ (pcase-lambda (`(,beg ,len ,dec))
+ (when (<= beg pos (+ beg len)) dec))
+ (save-excursion
+ (goto-char pos)
+ (beginning-of-defun)
+ (scope (current-buffer)))))))
+ (if (numberp dec)
+ (list (xref-make "lexical binding"
+ (xref-make-buffer-location (current-buffer) dec)))
(require 'find-func)
(let ((sym (intern-soft identifier)))
(when sym