diff options
author | Stephen Leake <stephen_leake@stephe-leake.org> | 2015-08-10 21:53:19 -0500 |
---|---|---|
committer | Stephen Leake <stephen_leake@stephe-leake.org> | 2015-08-10 21:55:37 -0500 |
commit | d7df36e745a5ba480559b6c8b5ebc93a18fe9bd1 (patch) | |
tree | 736918633a929b4f88e871509b699f9a00dcf398 /test | |
parent | 21e1673be3738fb79bd92cf8bd003d86ac51130b (diff) | |
download | emacs-d7df36e745a5ba480559b6c8b5ebc93a18fe9bd1.tar.gz |
Rewrite elisp--xref-find-definitions to handle many more cases; add tests.
* lisp/progmodes/elisp-mode.el (elisp--xref-identifier-location): deleted
(elisp--xref-format-cl-defmethod): new
(find-feature-regexp): new
(find-alias-regexp): new
(elisp--xref-make-xref): new
(elisp--xref-find-definitions): Rewrite using the above, handle many more
cases. Always output all available definitions.
(xref-location-marker): No need for special cases.
* test/automated/elisp-mode-tests.el: Add more tests of
elisp--xref-find-definitions, improve current tests.
Diffstat (limited to 'test')
-rw-r--r-- | test/automated/elisp-mode-tests.el | 298 |
1 files changed, 280 insertions, 18 deletions
diff --git a/test/automated/elisp-mode-tests.el b/test/automated/elisp-mode-tests.el index 2581de46931..114b71cfc63 100644 --- a/test/automated/elisp-mode-tests.el +++ b/test/automated/elisp-mode-tests.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2015 Free Software Foundation, Inc. ;; Author: Dmitry Gutov <dgutov@yandex.ru> +;; Author: Stephen Leake <stephen_leake@member.fsf.org> ;; This file is part of GNU Emacs. @@ -113,26 +114,287 @@ (should (member "backup-buffer" comps)) (should-not (member "backup-inhibited" comps))))) -;;; Navigation +;;; xref -(ert-deftest elisp-xref-finds-both-function-and-variable () - ;; "system-name" is both: a variable and a function - (let ((defs (elisp-xref-find 'definitions "system-name"))) - (should (= (length defs) 2)) - (should (string= (xref-item-summary (nth 0 defs)) - "(defun system-name)")) - (should (string= (xref-item-summary (nth 1 defs)) - "(defvar system-name)"))) +(defun xref-elisp-test-descr-to-target (xref) + "Return an appropiate `looking-at' match string for XREF." + (let* ((loc (xref-item-location xref)) + (type (or (xref-elisp-location-type loc) + 'defun))) + + (cl-case type + (defalias + ;; summary: "(defalias xref)" + ;; target : "(defalias 'xref)" + (concat "(defalias '" (substring (xref-item-summary xref) 10 -1))) + + (defun + (let ((summary (xref-item-summary xref)) + (file (xref-elisp-location-file loc))) + (cond + ((string= "c" (file-name-extension file)) + ;; summary: "(defun buffer-live-p)" + ;; target : "DEFUN (buffer-live-p" + (concat + (upcase (substring summary 1 6)) + " (\"" + (substring summary 7 -1) + "\"")) + + (t + (substring summary 0 -1)) + ))) + + (defvar + (let ((summary (xref-item-summary xref)) + (file (xref-elisp-location-file loc))) + (cond + ((string= "c" (file-name-extension file)) + ;; summary: "(defvar system-name)" + ;; target : "DEFVAR_LISP ("system-name", " + ;; summary: "(defvar abbrev-mode)" + ;; target : DEFVAR_PER_BUFFER ("abbrev-mode" + (concat + (upcase (substring summary 1 7)) + (if (bufferp (variable-binding-locus (xref-elisp-location-symbol loc))) + "_PER_BUFFER (\"" + "_LISP (\"") + (substring summary 8 -1) + "\"")) + + (t + (substring summary 0 -1)) + ))) + + (feature + ;; summary: "(feature xref)" + ;; target : "(provide 'xref)" + (concat "(provide '" (substring (xref-item-summary xref) 9 -1))) + + (otherwise + (substring (xref-item-summary xref) 0 -1)) + ))) + + +(defmacro xref-elisp-test (name computed-xrefs expected-xrefs) + "Define an ert test for an xref-elisp feature. +COMPUTED-XREFS and EXPECTED-XREFS are lists of xrefs, except if +an element of EXPECTED-XREFS is a cons (XREF . TARGET), TARGET is +matched to the found location; otherwise, match +to (xref-elisp-test-descr-to-target xref)." + (declare (indent defun)) + (declare (debug (symbolp "name"))) + `(ert-deftest ,(intern (concat "xref-elisp-test-" (symbol-name name))) () + (let ((xrefs ,computed-xrefs) + (expecteds ,expected-xrefs)) + (while xrefs + (let ((xref (pop xrefs)) + (expected (pop expecteds))) + + (should (equal xref + (or (when (consp expected) (car expected)) expected))) + + (xref--goto-location (xref-item-location xref)) + (should (looking-at (or (when (consp expected) (cdr expected)) + (xref-elisp-test-descr-to-target expected))))) + )) + )) + +;; When tests are run from the Makefile, 'default-directory' is $HOME, +;; so we must provide this dir to expand-file-name in the expected +;; results. The Makefile sets EMACS_TEST_DIRECTORY. +(defconst emacs-test-dir (getenv "EMACS_TEST_DIRECTORY")) + +;; alphabetical by test name + +;; FIXME: autoload + +;; FIXME: defalias-defun-c cmpl-prefix-entry-head +;; FIXME: defalias-defvar-el allout-mode-map + +(xref-elisp-test find-defs-defalias-defun-el + (elisp--xref-find-definitions 'Buffer-menu-sort) + (list + (xref-make "(defalias Buffer-menu-sort)" + (xref-make-elisp-location + 'Buffer-menu-sort 'defalias + (expand-file-name "../../lisp/buff-menu.elc" emacs-test-dir))) + (xref-make "(defun tabulated-list-sort)" + (xref-make-elisp-location + 'tabulated-list-sort nil + (expand-file-name "../../lisp/emacs-lisp/tabulated-list.el" emacs-test-dir))) + )) + +;; FIXME: defconst + +(xref-elisp-test find-defs-defgeneric-el + (elisp--xref-find-definitions 'xref-location-marker) + (list + (xref-make "(cl-defgeneric xref-location-marker)" + (xref-make-elisp-location + 'xref-location-marker nil + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) + (xref-make "(cl-defmethod xref-location-marker ((l xref-elisp-location)))" + (xref-make-elisp-location + '(xref-location-marker xref-elisp-location) 'cl-defmethod + (expand-file-name "../../lisp/progmodes/elisp-mode.el" emacs-test-dir))) + (xref-make "(cl-defmethod xref-location-marker ((l xref-file-location)))" + (xref-make-elisp-location + '(xref-location-marker xref-file-location) 'cl-defmethod + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) + (xref-make "(cl-defmethod xref-location-marker ((l xref-buffer-location)))" + (xref-make-elisp-location + '(xref-location-marker xref-buffer-location) 'cl-defmethod + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) + (xref-make "(cl-defmethod xref-location-marker ((l xref-bogus-location)))" + (xref-make-elisp-location + '(xref-location-marker xref-bogus-location) 'cl-defmethod + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) + (xref-make "(cl-defmethod xref-location-marker ((l xref-etags-location)))" + (xref-make-elisp-location + '(xref-location-marker xref-etags-location) 'cl-defmethod + (expand-file-name "../../lisp/progmodes/etags.el" emacs-test-dir))) + )) + +;; FIXME: constructor xref-make-elisp-location; location is +;; cl-defstruct location. use :constructor in description. + +(xref-elisp-test find-defs-defgeneric-eval + (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ()))) + nil) + +(xref-elisp-test find-defs-defun-el + (elisp--xref-find-definitions 'xref-find-definitions) + (list + (xref-make "(defun xref-find-definitions)" + (xref-make-elisp-location + 'xref-find-definitions nil + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))))) + +(xref-elisp-test find-defs-defun-eval + (elisp--xref-find-definitions (eval '(defun stephe-leake-defun ()))) + nil) + +(xref-elisp-test find-defs-defun-c + (elisp--xref-find-definitions 'buffer-live-p) + (list + (xref-make "(defun buffer-live-p)" + (xref-make-elisp-location 'buffer-live-p nil "src/buffer.c")))) + +;; FIXME: deftype + +(xref-elisp-test find-defs-defun-c-defvar-c + (elisp-xref-find 'definitions "system-name") + (list + (xref-make "(defvar system-name)" + (xref-make-elisp-location 'system-name 'defvar "src/editfns.c")) + (xref-make "(defun system-name)" + (xref-make-elisp-location 'system-name nil "src/editfns.c"))) + ) + +(xref-elisp-test find-defs-defun-el-defvar-c + (elisp-xref-find 'definitions "abbrev-mode") ;; It's a minor mode, but the variable is defined in buffer.c - (let ((defs (elisp-xref-find 'definitions "abbrev-mode"))) - (should (= (length defs) 2)))) - -(ert-deftest elisp-xref-finds-only-function-for-minor-mode () - ;; Both variable and function are defined in the same place. - (let ((defs (elisp-xref-find 'definitions "visible-mode"))) - (should (= (length defs) 1)) - (should (string= (xref-item-summary (nth 0 defs)) - "(defun visible-mode)")))) + (list + (xref-make "(defvar abbrev-mode)" + (xref-make-elisp-location 'abbrev-mode 'defvar "src/buffer.c")) + (cons + (xref-make "(defun abbrev-mode)" + (xref-make-elisp-location + 'abbrev-mode nil + (expand-file-name "../../lisp/abbrev.el" emacs-test-dir))) + "(define-minor-mode abbrev-mode")) + ) + +;; Source for both variable and defun is "(define-minor-mode +;; compilation-minor-mode". There is no way to tell that from the +;; symbol. find-function-regexp-alist uses find-function-regexp for +;; this, but that matches too many things for use in this test. +(xref-elisp-test find-defs-defun-defvar-el + (elisp--xref-find-definitions 'compilation-minor-mode) + (list + (cons + (xref-make "(defun compilation-minor-mode)" + (xref-make-elisp-location + 'compilation-minor-mode nil + (expand-file-name "../../lisp/progmodes/compile.el" emacs-test-dir))) + "(define-minor-mode compilation-minor-mode") + (cons + (xref-make "(defvar compilation-minor-mode)" + (xref-make-elisp-location + 'compilation-minor-mode 'defvar + (expand-file-name "../../lisp/progmodes/compile.el" emacs-test-dir))) + "(define-minor-mode compilation-minor-mode") + ) + ) + +(xref-elisp-test find-defs-defvar-el + (elisp--xref-find-definitions 'xref--marker-ring) + ;; This is a defconst, which creates an alias and a variable. + ;; FIXME: try not to show the alias in this case + (list + (xref-make "(defvar xref--marker-ring)" + (xref-make-elisp-location + 'xref--marker-ring 'defvar + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) + (cons + (xref-make "(defalias xref--marker-ring)" + (xref-make-elisp-location + 'xref--marker-ring 'defalias + (expand-file-name "../../lisp/progmodes/xref.elc" emacs-test-dir))) + "(defvar xref--marker-ring") + )) + +(xref-elisp-test find-defs-defvar-c + (elisp--xref-find-definitions 'default-directory) + (list + (cons + (xref-make "(defvar default-directory)" + (xref-make-elisp-location 'default-directory 'defvar "src/buffer.c")) + ;; IMPROVEME: we might be able to compute this target + "DEFVAR_PER_BUFFER (\"default-directory\""))) + +(xref-elisp-test find-defs-defvar-eval + (elisp--xref-find-definitions (eval '(defvar stephe-leake-defvar nil))) + nil) + +(xref-elisp-test find-defs-face-el + (elisp--xref-find-definitions 'font-lock-keyword-face) + ;; 'font-lock-keyword-face is both a face and a var + ;; defface creates both a face and an alias + ;; FIXME: try to not show the alias in this case + (list + (xref-make "(defvar font-lock-keyword-face)" + (xref-make-elisp-location + 'font-lock-keyword-face 'defvar + (expand-file-name "../../lisp/font-lock.el" emacs-test-dir))) + (xref-make "(defface font-lock-keyword-face)" + (xref-make-elisp-location + 'font-lock-keyword-face 'defface + (expand-file-name "../../lisp/font-lock.el" emacs-test-dir))) + (cons + (xref-make "(defalias font-lock-keyword-face)" + (xref-make-elisp-location + 'font-lock-keyword-face 'defalias + (expand-file-name "../../lisp/font-lock.elc" emacs-test-dir))) + "(defface font-lock-keyword-face") + )) + +(xref-elisp-test find-defs-face-eval + (elisp--xref-find-definitions (eval '(defface stephe-leake-defface nil ""))) + nil) + +(xref-elisp-test find-defs-feature-el + (elisp--xref-find-definitions 'xref) + (list + (xref-make "(feature xref)" + (xref-make-elisp-location + 'xref 'feature + (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))))) + +(xref-elisp-test find-defs-feature-eval + (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature))) + nil) (provide 'elisp-mode-tests) ;;; elisp-mode-tests.el ends here |