Function: elisp--xref-infer-namespace

elisp--xref-infer-namespace is a byte-compiled function defined in elisp-mode.el.gz.

Signature

(elisp--xref-infer-namespace POS)

Documentation

Find the likely namespace of the identifier at POS.

Return one of function, variable maybe-variable, feature, face, or any (indicating any namespace). maybe-variable indicates a variable namespace but with lower confidence.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/elisp-mode.el.gz
(defun elisp--xref-infer-namespace (pos)
  "Find the likely namespace of the identifier at POS.
Return one of `function', `variable' `maybe-variable', `feature', `face', or
`any' (indicating any namespace).  `maybe-variable' indicates a variable
namespace but with lower confidence."
  (save-excursion
    (goto-char pos)
    (cl-flet ((looking-at-sym ()
                (let ((val (save-excursion
                             (ignore-errors (read (current-buffer))))))
                  (and (symbolp val) val))))
      (cond
       ((and (eq (char-before pos) ?\')
             (eq (char-before (1- pos)) ?#))
        ;; #'IDENT
        'function)
       ((memq (char-before pos) '(?\' ?`))
        ;; 'IDENT or `IDENT -- try to disambiguate.
        (backward-char)                 ; Step over '
        (let ((i (elisp--xref-list-index))
              (sym (looking-at-sym)))
          (cond
           ((eql i 1)
            (cond
             ((memq sym '( featurep require provide))
              'feature)
             ((memq sym
                    '(
                      ;; We are mostly interested in functions that take a
                      ;; function symbol as argument:
                      fboundp symbol-function fset
                      ;; ... but we include some common higher-order functions
                      ;; as well, even though the argument really should
                      ;; be #'-quoted:
                      function-get function-put
                      func-arity functionp
                      funcall funcall-interactively
                      apply mapcar mapc mapcan mapconcat
                      apply-partially
                      substitute-key-definition))
              'function)
             ((memq sym
                    '(
                      ;; Functions taking a variable symbol as first argument.
                      ;; More of these could be added for greater precision.
                      boundp set symbol-value
                      special-variable-p local-variable-p
                      local-variable-if-set-p
                      make-variable-buffer-local
                      default-value set-default make-local-variable
                      buffer-local-value))
              'variable)
             ((memq sym
                    '(
                      ;; FIXME: Add more functions taking a face
                      ;; symbol for greater precision.
                      facep face-name face-id))
              'face)
             (t 'any)))
           ((and (eql i 2)
                 (memq sym '( global-set-key local-set-key
                              substitute-key-definition
                              add-hook)))
            'function)
           ((and (eql i 3)
                 (memq sym '( define-key add-function)))
            'function)
           (t 'any))))
       ((or (and (eq (char-before (1- pos)) ?,)
                 (eq (char-before pos) ?@))
            (eq (char-before pos) ?,))
        ;; ,IDENT or ,@IDENT
        'variable)
       (t
        ;; Unquoted name -- look at the context.  General scheme:
        ;; (K-HEAD ... (J-HEAD ... (I-HEAD ... IDENT
        ;;             ^ index K   ^ index J   ^ index I
        (let* ((i (elisp--xref-list-index))
               (i-head (looking-at-sym))
               (i-paren (and i (eq (char-before) ?\()
                             (progn (backward-char) t)))
               (i-quoted (and i-paren (memq (char-before) '(?\' ?`))))
               (j (and i-paren (elisp--xref-list-index)))
               (j-head (and j (looking-at-sym)))
               (j-paren (and j (eq (char-before) ?\()
                             (progn (backward-char) t)))
               (j-quoted (and j-paren (memq (char-before) '(?\' ?`))))
               (k (and j-paren (elisp--xref-list-index)))
               (k-head (and k (looking-at-sym)))
               (k-paren (and k (eq (char-before) ?\()
                             (progn (backward-char) t)))
               (k-quoted (and k-paren (memq (char-before) '(?\' ?`)))))
          (cond
           ((or i-quoted j-quoted k-quoted)
            ;; '(... IDENT or '(... (... IDENT or '(... (... (... IDENT
            'any)
           ((and (eql j 1)
                 (memq j-head '( let let* letrec dlet lambda)))
            ;; (let (... IDENT
            'variable)
           ((and (eql j 2)
                 (memq j-head '( defun defmacro defsubst
                                 define-inline declare-function
                                 defadvice
                                 cl-defmethod cl-defgeneric)))
            ;; (defun FUNC (... IDENT
            'variable)
           ((eq j-head 'cond)
            ;; (cond ... (... IDENT
            'variable)
           ((and (eql k 1)
                 (memq k-head '( let let* letrec dlet )))
            ;; (let (... (... IDENT
            'variable)
           ((eql i 0)
            ;; (IDENT ...
            'function)
           ((functionp i-head)
            ;; (FUNC ... IDENT
            'variable)
           ((and (eql i 1)
                 (cond
                  ((memq i-head '( function
                                   defun defmacro defsubst
                                   define-inline declare-function
                                   defadvice
                                   cl-defmethod cl-defgeneric))
                   'function)
                  ((memq i-head '( defvar defvar-local defconst defcustom))
                   'variable)
                  ((eq i-head 'defface)
                   'face))))
           ((memq i-head '( if while and or when unless progn prog1
                            let let* lambda defun defsubst defvar defconst))
            ;; arg to some common non-function forms
            'variable)
           ;; Anything else: probably a variable, but since i-head may be
           ;; a macro we cannot be sure.
           (t 'maybe-variable))))))))