diff options
| author | Stephen Leake | 2015-08-10 21:53:19 -0500 |
|---|---|---|
| committer | Stephen Leake | 2015-08-10 21:55:37 -0500 |
| commit | d7df36e745a5ba480559b6c8b5ebc93a18fe9bd1 (patch) | |
| tree | 736918633a929b4f88e871509b699f9a00dcf398 /test | |
| parent | 21e1673be3738fb79bd92cf8bd003d86ac51130b (diff) | |
| download | emacs-d7df36e745a5ba480559b6c8b5ebc93a18fe9bd1.tar.gz emacs-d7df36e745a5ba480559b6c8b5ebc93a18fe9bd1.zip | |
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 @@ | |||
| 3 | ;; Copyright (C) 2015 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2015 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Dmitry Gutov <dgutov@yandex.ru> | 5 | ;; Author: Dmitry Gutov <dgutov@yandex.ru> |
| 6 | ;; Author: Stephen Leake <stephen_leake@member.fsf.org> | ||
| 6 | 7 | ||
| 7 | ;; This file is part of GNU Emacs. | 8 | ;; This file is part of GNU Emacs. |
| 8 | 9 | ||
| @@ -113,26 +114,287 @@ | |||
| 113 | (should (member "backup-buffer" comps)) | 114 | (should (member "backup-buffer" comps)) |
| 114 | (should-not (member "backup-inhibited" comps))))) | 115 | (should-not (member "backup-inhibited" comps))))) |
| 115 | 116 | ||
| 116 | ;;; Navigation | 117 | ;;; xref |
| 117 | 118 | ||
| 118 | (ert-deftest elisp-xref-finds-both-function-and-variable () | 119 | (defun xref-elisp-test-descr-to-target (xref) |
| 119 | ;; "system-name" is both: a variable and a function | 120 | "Return an appropiate `looking-at' match string for XREF." |
| 120 | (let ((defs (elisp-xref-find 'definitions "system-name"))) | 121 | (let* ((loc (xref-item-location xref)) |
| 121 | (should (= (length defs) 2)) | 122 | (type (or (xref-elisp-location-type loc) |
| 122 | (should (string= (xref-item-summary (nth 0 defs)) | 123 | 'defun))) |
| 123 | "(defun system-name)")) | 124 | |
| 124 | (should (string= (xref-item-summary (nth 1 defs)) | 125 | (cl-case type |
| 125 | "(defvar system-name)"))) | 126 | (defalias |
| 127 | ;; summary: "(defalias xref)" | ||
| 128 | ;; target : "(defalias 'xref)" | ||
| 129 | (concat "(defalias '" (substring (xref-item-summary xref) 10 -1))) | ||
| 130 | |||
| 131 | (defun | ||
| 132 | (let ((summary (xref-item-summary xref)) | ||
| 133 | (file (xref-elisp-location-file loc))) | ||
| 134 | (cond | ||
| 135 | ((string= "c" (file-name-extension file)) | ||
| 136 | ;; summary: "(defun buffer-live-p)" | ||
| 137 | ;; target : "DEFUN (buffer-live-p" | ||
| 138 | (concat | ||
| 139 | (upcase (substring summary 1 6)) | ||
| 140 | " (\"" | ||
| 141 | (substring summary 7 -1) | ||
| 142 | "\"")) | ||
| 143 | |||
| 144 | (t | ||
| 145 | (substring summary 0 -1)) | ||
| 146 | ))) | ||
| 147 | |||
| 148 | (defvar | ||
| 149 | (let ((summary (xref-item-summary xref)) | ||
| 150 | (file (xref-elisp-location-file loc))) | ||
| 151 | (cond | ||
| 152 | ((string= "c" (file-name-extension file)) | ||
| 153 | ;; summary: "(defvar system-name)" | ||
| 154 | ;; target : "DEFVAR_LISP ("system-name", " | ||
| 155 | ;; summary: "(defvar abbrev-mode)" | ||
| 156 | ;; target : DEFVAR_PER_BUFFER ("abbrev-mode" | ||
| 157 | (concat | ||
| 158 | (upcase (substring summary 1 7)) | ||
| 159 | (if (bufferp (variable-binding-locus (xref-elisp-location-symbol loc))) | ||
| 160 | "_PER_BUFFER (\"" | ||
| 161 | "_LISP (\"") | ||
| 162 | (substring summary 8 -1) | ||
| 163 | "\"")) | ||
| 164 | |||
| 165 | (t | ||
| 166 | (substring summary 0 -1)) | ||
| 167 | ))) | ||
| 168 | |||
| 169 | (feature | ||
| 170 | ;; summary: "(feature xref)" | ||
| 171 | ;; target : "(provide 'xref)" | ||
| 172 | (concat "(provide '" (substring (xref-item-summary xref) 9 -1))) | ||
| 173 | |||
| 174 | (otherwise | ||
| 175 | (substring (xref-item-summary xref) 0 -1)) | ||
| 176 | ))) | ||
| 177 | |||
| 178 | |||
| 179 | (defmacro xref-elisp-test (name computed-xrefs expected-xrefs) | ||
| 180 | "Define an ert test for an xref-elisp feature. | ||
| 181 | COMPUTED-XREFS and EXPECTED-XREFS are lists of xrefs, except if | ||
| 182 | an element of EXPECTED-XREFS is a cons (XREF . TARGET), TARGET is | ||
| 183 | matched to the found location; otherwise, match | ||
| 184 | to (xref-elisp-test-descr-to-target xref)." | ||
| 185 | (declare (indent defun)) | ||
| 186 | (declare (debug (symbolp "name"))) | ||
| 187 | `(ert-deftest ,(intern (concat "xref-elisp-test-" (symbol-name name))) () | ||
| 188 | (let ((xrefs ,computed-xrefs) | ||
| 189 | (expecteds ,expected-xrefs)) | ||
| 190 | (while xrefs | ||
| 191 | (let ((xref (pop xrefs)) | ||
| 192 | (expected (pop expecteds))) | ||
| 193 | |||
| 194 | (should (equal xref | ||
| 195 | (or (when (consp expected) (car expected)) expected))) | ||
| 196 | |||
| 197 | (xref--goto-location (xref-item-location xref)) | ||
| 198 | (should (looking-at (or (when (consp expected) (cdr expected)) | ||
| 199 | (xref-elisp-test-descr-to-target expected))))) | ||
| 200 | )) | ||
| 201 | )) | ||
| 202 | |||
| 203 | ;; When tests are run from the Makefile, 'default-directory' is $HOME, | ||
| 204 | ;; so we must provide this dir to expand-file-name in the expected | ||
| 205 | ;; results. The Makefile sets EMACS_TEST_DIRECTORY. | ||
| 206 | (defconst emacs-test-dir (getenv "EMACS_TEST_DIRECTORY")) | ||
| 207 | |||
| 208 | ;; alphabetical by test name | ||
| 209 | |||
| 210 | ;; FIXME: autoload | ||
| 211 | |||
| 212 | ;; FIXME: defalias-defun-c cmpl-prefix-entry-head | ||
| 213 | ;; FIXME: defalias-defvar-el allout-mode-map | ||
| 214 | |||
| 215 | (xref-elisp-test find-defs-defalias-defun-el | ||
| 216 | (elisp--xref-find-definitions 'Buffer-menu-sort) | ||
| 217 | (list | ||
| 218 | (xref-make "(defalias Buffer-menu-sort)" | ||
| 219 | (xref-make-elisp-location | ||
| 220 | 'Buffer-menu-sort 'defalias | ||
| 221 | (expand-file-name "../../lisp/buff-menu.elc" emacs-test-dir))) | ||
| 222 | (xref-make "(defun tabulated-list-sort)" | ||
| 223 | (xref-make-elisp-location | ||
| 224 | 'tabulated-list-sort nil | ||
| 225 | (expand-file-name "../../lisp/emacs-lisp/tabulated-list.el" emacs-test-dir))) | ||
| 226 | )) | ||
| 227 | |||
| 228 | ;; FIXME: defconst | ||
| 229 | |||
| 230 | (xref-elisp-test find-defs-defgeneric-el | ||
| 231 | (elisp--xref-find-definitions 'xref-location-marker) | ||
| 232 | (list | ||
| 233 | (xref-make "(cl-defgeneric xref-location-marker)" | ||
| 234 | (xref-make-elisp-location | ||
| 235 | 'xref-location-marker nil | ||
| 236 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | ||
| 237 | (xref-make "(cl-defmethod xref-location-marker ((l xref-elisp-location)))" | ||
| 238 | (xref-make-elisp-location | ||
| 239 | '(xref-location-marker xref-elisp-location) 'cl-defmethod | ||
| 240 | (expand-file-name "../../lisp/progmodes/elisp-mode.el" emacs-test-dir))) | ||
| 241 | (xref-make "(cl-defmethod xref-location-marker ((l xref-file-location)))" | ||
| 242 | (xref-make-elisp-location | ||
| 243 | '(xref-location-marker xref-file-location) 'cl-defmethod | ||
| 244 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | ||
| 245 | (xref-make "(cl-defmethod xref-location-marker ((l xref-buffer-location)))" | ||
| 246 | (xref-make-elisp-location | ||
| 247 | '(xref-location-marker xref-buffer-location) 'cl-defmethod | ||
| 248 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | ||
| 249 | (xref-make "(cl-defmethod xref-location-marker ((l xref-bogus-location)))" | ||
| 250 | (xref-make-elisp-location | ||
| 251 | '(xref-location-marker xref-bogus-location) 'cl-defmethod | ||
| 252 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | ||
| 253 | (xref-make "(cl-defmethod xref-location-marker ((l xref-etags-location)))" | ||
| 254 | (xref-make-elisp-location | ||
| 255 | '(xref-location-marker xref-etags-location) 'cl-defmethod | ||
| 256 | (expand-file-name "../../lisp/progmodes/etags.el" emacs-test-dir))) | ||
| 257 | )) | ||
| 258 | |||
| 259 | ;; FIXME: constructor xref-make-elisp-location; location is | ||
| 260 | ;; cl-defstruct location. use :constructor in description. | ||
| 261 | |||
| 262 | (xref-elisp-test find-defs-defgeneric-eval | ||
| 263 | (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ()))) | ||
| 264 | nil) | ||
| 265 | |||
| 266 | (xref-elisp-test find-defs-defun-el | ||
| 267 | (elisp--xref-find-definitions 'xref-find-definitions) | ||
| 268 | (list | ||
| 269 | (xref-make "(defun xref-find-definitions)" | ||
| 270 | (xref-make-elisp-location | ||
| 271 | 'xref-find-definitions nil | ||
| 272 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))))) | ||
| 273 | |||
| 274 | (xref-elisp-test find-defs-defun-eval | ||
| 275 | (elisp--xref-find-definitions (eval '(defun stephe-leake-defun ()))) | ||
| 276 | nil) | ||
| 277 | |||
| 278 | (xref-elisp-test find-defs-defun-c | ||
| 279 | (elisp--xref-find-definitions 'buffer-live-p) | ||
| 280 | (list | ||
| 281 | (xref-make "(defun buffer-live-p)" | ||
| 282 | (xref-make-elisp-location 'buffer-live-p nil "src/buffer.c")))) | ||
| 283 | |||
| 284 | ;; FIXME: deftype | ||
| 285 | |||
| 286 | (xref-elisp-test find-defs-defun-c-defvar-c | ||
| 287 | (elisp-xref-find 'definitions "system-name") | ||
| 288 | (list | ||
| 289 | (xref-make "(defvar system-name)" | ||
| 290 | (xref-make-elisp-location 'system-name 'defvar "src/editfns.c")) | ||
| 291 | (xref-make "(defun system-name)" | ||
| 292 | (xref-make-elisp-location 'system-name nil "src/editfns.c"))) | ||
| 293 | ) | ||
| 294 | |||
| 295 | (xref-elisp-test find-defs-defun-el-defvar-c | ||
| 296 | (elisp-xref-find 'definitions "abbrev-mode") | ||
| 126 | ;; It's a minor mode, but the variable is defined in buffer.c | 297 | ;; It's a minor mode, but the variable is defined in buffer.c |
| 127 | (let ((defs (elisp-xref-find 'definitions "abbrev-mode"))) | 298 | (list |
| 128 | (should (= (length defs) 2)))) | 299 | (xref-make "(defvar abbrev-mode)" |
| 129 | 300 | (xref-make-elisp-location 'abbrev-mode 'defvar "src/buffer.c")) | |
| 130 | (ert-deftest elisp-xref-finds-only-function-for-minor-mode () | 301 | (cons |
| 131 | ;; Both variable and function are defined in the same place. | 302 | (xref-make "(defun abbrev-mode)" |
| 132 | (let ((defs (elisp-xref-find 'definitions "visible-mode"))) | 303 | (xref-make-elisp-location |
| 133 | (should (= (length defs) 1)) | 304 | 'abbrev-mode nil |
| 134 | (should (string= (xref-item-summary (nth 0 defs)) | 305 | (expand-file-name "../../lisp/abbrev.el" emacs-test-dir))) |
| 135 | "(defun visible-mode)")))) | 306 | "(define-minor-mode abbrev-mode")) |
| 307 | ) | ||
| 308 | |||
| 309 | ;; Source for both variable and defun is "(define-minor-mode | ||
| 310 | ;; compilation-minor-mode". There is no way to tell that from the | ||
| 311 | ;; symbol. find-function-regexp-alist uses find-function-regexp for | ||
| 312 | ;; this, but that matches too many things for use in this test. | ||
| 313 | (xref-elisp-test find-defs-defun-defvar-el | ||
| 314 | (elisp--xref-find-definitions 'compilation-minor-mode) | ||
| 315 | (list | ||
| 316 | (cons | ||
| 317 | (xref-make "(defun compilation-minor-mode)" | ||
| 318 | (xref-make-elisp-location | ||
| 319 | 'compilation-minor-mode nil | ||
| 320 | (expand-file-name "../../lisp/progmodes/compile.el" emacs-test-dir))) | ||
| 321 | "(define-minor-mode compilation-minor-mode") | ||
| 322 | (cons | ||
| 323 | (xref-make "(defvar compilation-minor-mode)" | ||
| 324 | (xref-make-elisp-location | ||
| 325 | 'compilation-minor-mode 'defvar | ||
| 326 | (expand-file-name "../../lisp/progmodes/compile.el" emacs-test-dir))) | ||
| 327 | "(define-minor-mode compilation-minor-mode") | ||
| 328 | ) | ||
| 329 | ) | ||
| 330 | |||
| 331 | (xref-elisp-test find-defs-defvar-el | ||
| 332 | (elisp--xref-find-definitions 'xref--marker-ring) | ||
| 333 | ;; This is a defconst, which creates an alias and a variable. | ||
| 334 | ;; FIXME: try not to show the alias in this case | ||
| 335 | (list | ||
| 336 | (xref-make "(defvar xref--marker-ring)" | ||
| 337 | (xref-make-elisp-location | ||
| 338 | 'xref--marker-ring 'defvar | ||
| 339 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | ||
| 340 | (cons | ||
| 341 | (xref-make "(defalias xref--marker-ring)" | ||
| 342 | (xref-make-elisp-location | ||
| 343 | 'xref--marker-ring 'defalias | ||
| 344 | (expand-file-name "../../lisp/progmodes/xref.elc" emacs-test-dir))) | ||
| 345 | "(defvar xref--marker-ring") | ||
| 346 | )) | ||
| 347 | |||
| 348 | (xref-elisp-test find-defs-defvar-c | ||
| 349 | (elisp--xref-find-definitions 'default-directory) | ||
| 350 | (list | ||
| 351 | (cons | ||
| 352 | (xref-make "(defvar default-directory)" | ||
| 353 | (xref-make-elisp-location 'default-directory 'defvar "src/buffer.c")) | ||
| 354 | ;; IMPROVEME: we might be able to compute this target | ||
| 355 | "DEFVAR_PER_BUFFER (\"default-directory\""))) | ||
| 356 | |||
| 357 | (xref-elisp-test find-defs-defvar-eval | ||
| 358 | (elisp--xref-find-definitions (eval '(defvar stephe-leake-defvar nil))) | ||
| 359 | nil) | ||
| 360 | |||
| 361 | (xref-elisp-test find-defs-face-el | ||
| 362 | (elisp--xref-find-definitions 'font-lock-keyword-face) | ||
| 363 | ;; 'font-lock-keyword-face is both a face and a var | ||
| 364 | ;; defface creates both a face and an alias | ||
| 365 | ;; FIXME: try to not show the alias in this case | ||
| 366 | (list | ||
| 367 | (xref-make "(defvar font-lock-keyword-face)" | ||
| 368 | (xref-make-elisp-location | ||
| 369 | 'font-lock-keyword-face 'defvar | ||
| 370 | (expand-file-name "../../lisp/font-lock.el" emacs-test-dir))) | ||
| 371 | (xref-make "(defface font-lock-keyword-face)" | ||
| 372 | (xref-make-elisp-location | ||
| 373 | 'font-lock-keyword-face 'defface | ||
| 374 | (expand-file-name "../../lisp/font-lock.el" emacs-test-dir))) | ||
| 375 | (cons | ||
| 376 | (xref-make "(defalias font-lock-keyword-face)" | ||
| 377 | (xref-make-elisp-location | ||
| 378 | 'font-lock-keyword-face 'defalias | ||
| 379 | (expand-file-name "../../lisp/font-lock.elc" emacs-test-dir))) | ||
| 380 | "(defface font-lock-keyword-face") | ||
| 381 | )) | ||
| 382 | |||
| 383 | (xref-elisp-test find-defs-face-eval | ||
| 384 | (elisp--xref-find-definitions (eval '(defface stephe-leake-defface nil ""))) | ||
| 385 | nil) | ||
| 386 | |||
| 387 | (xref-elisp-test find-defs-feature-el | ||
| 388 | (elisp--xref-find-definitions 'xref) | ||
| 389 | (list | ||
| 390 | (xref-make "(feature xref)" | ||
| 391 | (xref-make-elisp-location | ||
| 392 | 'xref 'feature | ||
| 393 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))))) | ||
| 394 | |||
| 395 | (xref-elisp-test find-defs-feature-eval | ||
| 396 | (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature))) | ||
| 397 | nil) | ||
| 136 | 398 | ||
| 137 | (provide 'elisp-mode-tests) | 399 | (provide 'elisp-mode-tests) |
| 138 | ;;; elisp-mode-tests.el ends here | 400 | ;;; elisp-mode-tests.el ends here |