Give '$' punctuation syntax in make-mode (Bug#24477)
[emacs.git] / test / lisp / progmodes / elisp-mode-tests.el
blob941e85bc890e31b5dc4d58b71b5210e10228f82c
1 ;;; elisp-mode-tests.el --- Tests for emacs-lisp-mode -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2015-2018 Free Software Foundation, Inc.
5 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
6 ;; Author: Stephen Leake <stephen_leake@member.fsf.org>
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
23 ;;; Code:
25 (require 'ert)
26 (require 'xref)
27 (eval-when-compile (require 'cl-lib))
29 ;;; Completion
31 (defun elisp--test-completions ()
32 (let ((data (elisp-completion-at-point)))
33 (all-completions (buffer-substring (nth 0 data) (nth 1 data))
34 (nth 2 data)
35 (plist-get (nthcdr 3 data) :predicate))))
37 (ert-deftest elisp-completes-functions ()
38 (with-temp-buffer
39 (emacs-lisp-mode)
40 (insert "(ba")
41 (let ((comps (elisp--test-completions)))
42 (should (member "backup-buffer" comps))
43 (should-not (member "backup-inhibited" comps)))))
45 (ert-deftest elisp-completes-variables ()
46 (with-temp-buffer
47 (emacs-lisp-mode)
48 (insert "(foo ba")
49 (let ((comps (elisp--test-completions)))
50 (should (member "backup-inhibited" comps))
51 (should-not (member "backup-buffer" comps)))))
53 (ert-deftest elisp-completes-anything-quoted ()
54 (dolist (text '("`(foo ba" "(foo 'ba"
55 "`(,foo ba" "`,(foo `ba"
56 "'(foo (ba"))
57 (with-temp-buffer
58 (emacs-lisp-mode)
59 (insert text)
60 (let ((comps (elisp--test-completions)))
61 (should (member "backup-inhibited" comps))
62 (should (member "backup-buffer" comps))
63 (should (member "backup" comps))))))
65 (ert-deftest elisp-completes-variables-unquoted ()
66 (dolist (text '("`(foo ,ba" "`(,(foo ba" "`(,ba"))
67 (with-temp-buffer
68 (emacs-lisp-mode)
69 (insert text)
70 (let ((comps (elisp--test-completions)))
71 (should (member "backup-inhibited" comps))
72 (should-not (member "backup-buffer" comps))))))
74 (ert-deftest elisp-completes-functions-in-special-macros ()
75 (dolist (text '("(declare-function ba" "(cl-callf2 ba"))
76 (with-temp-buffer
77 (emacs-lisp-mode)
78 (insert text)
79 (let ((comps (elisp--test-completions)))
80 (should (member "backup-buffer" comps))
81 (should-not (member "backup-inhibited" comps))))))
83 (ert-deftest elisp-completes-functions-after-hash-quote ()
84 (ert-deftest elisp-completes-functions-after-let-bindings ()
85 (with-temp-buffer
86 (emacs-lisp-mode)
87 (insert "#'ba")
88 (let ((comps (elisp--test-completions)))
89 (should (member "backup-buffer" comps))
90 (should-not (member "backup-inhibited" comps))))))
92 (ert-deftest elisp-completes-local-variables ()
93 (with-temp-buffer
94 (emacs-lisp-mode)
95 (insert "(let ((bar 1) baz) (foo ba")
96 (let ((comps (elisp--test-completions)))
97 (should (member "backup-inhibited" comps))
98 (should (member "bar" comps))
99 (should (member "baz" comps)))))
101 (ert-deftest elisp-completest-variables-in-let-bindings ()
102 (dolist (text '("(let (ba" "(let* ((ba"))
103 (with-temp-buffer
104 (emacs-lisp-mode)
105 (insert text)
106 (let ((comps (elisp--test-completions)))
107 (should (member "backup-inhibited" comps))
108 (should-not (member "backup-buffer" comps))))))
110 (ert-deftest elisp-completes-functions-after-let-bindings ()
111 (with-temp-buffer
112 (emacs-lisp-mode)
113 (insert "(let ((bar 1) (baz 2)) (ba")
114 (let ((comps (elisp--test-completions)))
115 (should (member "backup-buffer" comps))
116 (should-not (member "backup-inhibited" comps)))))
118 ;;; eval-last-sexp
120 (ert-deftest eval-last-sexp-print-format-sym ()
121 (with-temp-buffer
122 (let ((current-prefix-arg '(4)))
123 (erase-buffer) (insert "t")
124 (call-interactively #'eval-last-sexp)
125 (should (equal (buffer-string) "tt")))))
127 (ert-deftest eval-last-sexp-print-format-sym-echo ()
128 ;; We can only check the echo area when running interactive.
129 (skip-unless (not noninteractive))
130 (with-temp-buffer
131 (let ((current-prefix-arg nil))
132 (erase-buffer) (insert "t") (message nil)
133 (call-interactively #'eval-last-sexp)
134 (should (equal (current-message) "t")))))
136 (ert-deftest eval-last-sexp-print-format-small-int ()
137 (with-temp-buffer
138 (let ((current-prefix-arg '(4)))
139 (erase-buffer) (insert "?A")
140 (call-interactively #'eval-last-sexp)
141 (should (equal (buffer-string) "?A65")))
142 (let ((current-prefix-arg 0))
143 (erase-buffer) (insert "?A")
144 (call-interactively #'eval-last-sexp)
145 (should (equal (buffer-string) "?A65 (#o101, #x41, ?A)")))))
147 (ert-deftest eval-last-sexp-print-format-small-int-echo ()
148 (skip-unless (not noninteractive))
149 (with-temp-buffer
150 (let ((current-prefix-arg nil))
151 (erase-buffer) (insert "?A") (message nil)
152 (call-interactively #'eval-last-sexp)
153 (should (equal (current-message) "65 (#o101, #x41, ?A)")))))
155 (ert-deftest eval-last-sexp-print-format-large-int ()
156 (with-temp-buffer
157 (let ((eval-expression-print-maximum-character ?A))
158 (let ((current-prefix-arg '(4)))
159 (erase-buffer) (insert "?B")
160 (call-interactively #'eval-last-sexp)
161 (should (equal (buffer-string) "?B66")))
162 (let ((current-prefix-arg 0))
163 (erase-buffer) (insert "?B")
164 (call-interactively #'eval-last-sexp)
165 (should (equal (buffer-string) "?B66 (#o102, #x42)")))
166 (let ((current-prefix-arg -1))
167 (erase-buffer) (insert "?B")
168 (call-interactively #'eval-last-sexp)
169 (should (equal (buffer-string) "?B66 (#o102, #x42, ?B)"))))))
171 (ert-deftest eval-last-sexp-print-format-large-int-echo ()
172 (skip-unless (not noninteractive))
173 (with-temp-buffer
174 (let ((eval-expression-print-maximum-character ?A))
175 (let ((current-prefix-arg nil))
176 (erase-buffer) (insert "?B") (message nil)
177 (call-interactively #'eval-last-sexp)
178 (should (equal (current-message) "66 (#o102, #x42)")))
179 (let ((current-prefix-arg '-))
180 (erase-buffer) (insert "?B") (message nil)
181 (call-interactively #'eval-last-sexp)
182 (should (equal (current-message) "66 (#o102, #x42, ?B)"))))))
184 ;;; eldoc
186 (defun elisp-mode-tests--face-propertized-string (string)
187 "Return substring of STRING with a non-nil `face' property."
188 (let* ((start (next-single-property-change 0 'face string))
189 (end (and start (next-single-property-change start 'face string))))
190 (and end
191 (substring string start end))))
193 (ert-deftest elisp--highlight-function-argument-indexed ()
194 (dotimes (i 3)
195 (should
196 (equal (elisp-mode-tests--face-propertized-string
197 (elisp--highlight-function-argument 'foo "(A B C)" (1+ i) "foo: "))
198 (propertize (nth i '("A" "B" "C"))
199 'face 'eldoc-highlight-function-argument)))))
201 (ert-deftest elisp--highlight-function-argument-keyed-1 ()
202 (with-temp-buffer
203 (emacs-lisp-mode)
204 (insert "(foo prompt bar :b 2)")
205 (goto-char (1+ (point-min)))
206 (cl-flet ((bold-arg (i)
207 (elisp-mode-tests--face-propertized-string
208 (elisp--highlight-function-argument
209 'foo "(PROMPT LST &key A B C)" i "foo: "))))
210 (should-not (bold-arg 0))
211 (progn (forward-sexp) (forward-char))
212 (should (equal (bold-arg 1) "PROMPT"))
213 (progn (forward-sexp) (forward-char))
214 (should (equal (bold-arg 2) "LST"))
215 ;; Both `:b' and `2' should highlight the `B' arg.
216 (progn (forward-sexp) (forward-char))
217 (should (equal (bold-arg 3) "B"))
218 (progn (forward-sexp) (forward-char))
219 (should (equal (bold-arg 4) "B")))))
221 (ert-deftest elisp--highlight-function-argument-keyed-2 ()
222 (with-temp-buffer
223 (emacs-lisp-mode)
224 (insert "(foo :b :a 1)")
225 (goto-char (1+ (point-min)))
226 (cl-flet ((bold-arg (i)
227 (elisp-mode-tests--face-propertized-string
228 (elisp--highlight-function-argument
229 'foo "(X &key A B C)" i "foo: "))))
230 (should-not (bold-arg 0))
231 ;; The `:b' specifies positional arg `X'.
232 (progn (forward-sexp) (forward-char))
233 (should (equal (bold-arg 1) "X"))
234 (progn (forward-sexp) (forward-char))
235 (should (equal (bold-arg 2) "A"))
236 (progn (forward-sexp) (forward-char))
237 (should (equal (bold-arg 3) "A")))))
239 ;;; xref
241 (defun xref-elisp-test-descr-to-target (xref)
242 "Return an appropriate `looking-at' match string for XREF."
243 (let* ((loc (xref-item-location xref))
244 (type (or (xref-elisp-location-type loc)
245 'defun)))
247 (cl-case type
248 (defalias
249 ;; summary: "(defalias xref)"
250 ;; target : "(defalias 'xref"
251 (concat "(defalias '" (substring (xref-item-summary xref) 10 -1)))
253 (defun
254 (let ((summary (xref-item-summary xref))
255 (file (xref-elisp-location-file loc)))
256 (cond
257 ((string= "c" (file-name-extension file))
258 ;; summary: "(defun buffer-live-p)"
259 ;; target : "DEFUN (buffer-live-p"
260 (concat
261 (upcase (substring summary 1 6))
262 " (\""
263 (substring summary 7 -1)
264 "\""))
267 (substring summary 0 -1))
270 (defvar
271 (let ((summary (xref-item-summary xref))
272 (file (xref-elisp-location-file loc)))
273 (cond
274 ((string= "c" (file-name-extension file))
275 ;; summary: "(defvar system-name)"
276 ;; target : "DEFVAR_LISP ("system-name", "
277 ;; summary: "(defvar abbrev-mode)"
278 ;; target : DEFVAR_PER_BUFFER ("abbrev-mode"
279 (concat
280 (upcase (substring summary 1 7))
281 (if (bufferp (variable-binding-locus (xref-elisp-location-symbol loc)))
282 "_PER_BUFFER (\""
283 "_LISP (\"")
284 (substring summary 8 -1)
285 "\""))
288 (substring summary 0 -1))
291 (feature
292 ;; summary: "(feature xref)"
293 ;; target : "(provide 'xref)"
294 (concat "(provide '" (substring (xref-item-summary xref) 9 -1)))
296 (otherwise
297 (substring (xref-item-summary xref) 0 -1))
301 (defun xref-elisp-test-run (xrefs expected-xrefs)
302 (should (= (length xrefs) (length expected-xrefs)))
303 (while xrefs
304 (let* ((xref (pop xrefs))
305 (expected (pop expected-xrefs))
306 (expected-xref (or (when (consp expected) (car expected)) expected))
307 (expected-source (when (consp expected) (cdr expected))))
309 ;; Downcase the filenames for case-insensitive file systems.
310 (setf (xref-elisp-location-file (oref xref location))
311 (downcase (xref-elisp-location-file (oref xref location))))
313 (setf (xref-elisp-location-file (oref expected-xref location))
314 (downcase (xref-elisp-location-file (oref expected-xref location))))
316 (should (equal xref expected-xref))
318 (xref--goto-location (xref-item-location xref))
319 (back-to-indentation)
320 (should (looking-at (or expected-source
321 (xref-elisp-test-descr-to-target expected)))))
324 (defmacro xref-elisp-deftest (name computed-xrefs expected-xrefs)
325 "Define an ert test for an xref-elisp feature.
326 COMPUTED-XREFS and EXPECTED-XREFS are lists of xrefs, except if
327 an element of EXPECTED-XREFS is a cons (XREF . TARGET), TARGET is
328 matched to the found location; otherwise, match
329 to (xref-elisp-test-descr-to-target xref)."
330 (declare (indent defun)
331 (debug (symbolp "name")))
332 `(ert-deftest ,(intern (concat "xref-elisp-test-" (symbol-name name))) ()
333 (let ((find-file-suppress-same-file-warnings t))
334 (xref-elisp-test-run ,computed-xrefs ,expected-xrefs)
337 ;; When tests are run from the Makefile, 'default-directory' is $HOME,
338 ;; so we must provide this dir to expand-file-name in the expected
339 ;; results. This also allows running these tests from other
340 ;; directories.
342 ;; We add 'downcase' here to deliberately cause a potential problem on
343 ;; case-insensitive file systems. On such systems, `load-file-name'
344 ;; may not have the same case as the real file system, since the user
345 ;; can set `load-path' to have the wrong case (on my Windows system,
346 ;; `load-path' has the correct case, so this causes the expected test
347 ;; values to have the wrong case). This is handled in
348 ;; `xref-elisp-test-run'.
349 (defconst emacs-test-dir
350 (downcase
351 (file-truename (file-name-directory
352 (or load-file-name (buffer-file-name))))))
355 ;; alphabetical by test name
357 ;; Autoloads require no special support; they are handled as functions.
359 ;; FIXME: defalias-defun-c cmpl-prefix-entry-head
360 ;; FIXME: defalias-defvar-el allout-mode-map
362 (xref-elisp-deftest find-defs-constructor
363 (elisp--xref-find-definitions 'xref-make-elisp-location)
364 ;; 'xref-make-elisp-location' is just a name for the default
365 ;; constructor created by the cl-defstruct, so the location is the
366 ;; cl-defstruct location.
367 (list
368 (cons
369 (xref-make "(cl-defstruct (xref-elisp-location (:constructor xref-make-elisp-location)))"
370 (xref-make-elisp-location
371 'xref-elisp-location 'define-type
372 (expand-file-name "../../../lisp/progmodes/elisp-mode.el" emacs-test-dir)))
373 ;; It's not worth adding another special case to `xref-elisp-test-descr-to-target' for this
374 "(cl-defstruct (xref-elisp-location")
377 (xref-elisp-deftest find-defs-defalias-defun-el
378 (elisp--xref-find-definitions 'Buffer-menu-sort)
379 (list
380 (xref-make "(defalias Buffer-menu-sort)"
381 (xref-make-elisp-location
382 'Buffer-menu-sort 'defalias
383 (expand-file-name "../../../lisp/buff-menu.elc" emacs-test-dir)))
384 (xref-make "(defun tabulated-list-sort)"
385 (xref-make-elisp-location
386 'tabulated-list-sort nil
387 (expand-file-name "../../../lisp/emacs-lisp/tabulated-list.el" emacs-test-dir)))
390 ;; FIXME: defconst
392 ;; FIXME: eieio defclass
394 ;; Possible ways of defining the default method implementation for a
395 ;; generic function. We declare these here, so we know we cover all
396 ;; cases, and we don't rely on other code not changing.
398 ;; When the generic and default method are declared in the same place,
399 ;; elisp--xref-find-definitions only returns one.
401 (cl-defstruct (xref-elisp-root-type)
402 slot-1)
404 (cl-defgeneric xref-elisp-generic-no-methods (arg1 arg2)
405 "doc string generic no-methods"
406 ;; No default implementation, no methods, but fboundp is true for
407 ;; this symbol; it calls cl-no-applicable-method
410 ;; WORKAROUND: ‘this’ is unused, and the byte compiler complains, so
411 ;; it should be spelled ‘_this’. But for some unknown reason, that
412 ;; causes the batch mode test to fail; the symbol shows up as
413 ;; ‘this’. It passes in interactive tests, so I haven't been able to
414 ;; track down the problem.
415 (cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type) arg2)
416 "doc string generic no-default xref-elisp-root-type"
417 "non-default for no-default")
419 ;; defgeneric after defmethod in file to ensure the fallback search
420 ;; method of just looking for the function name will fail.
421 (cl-defgeneric xref-elisp-generic-no-default (arg1 arg2)
422 "doc string generic no-default generic"
423 ;; No default implementation; this function calls the cl-generic
424 ;; dispatching code.
427 (cl-defgeneric xref-elisp-generic-co-located-default (arg1 arg2)
428 "doc string generic co-located-default"
429 "co-located default")
431 (cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type) arg2)
432 "doc string generic co-located-default xref-elisp-root-type"
433 "non-default for co-located-default")
435 (cl-defgeneric xref-elisp-generic-separate-default (arg1 arg2)
436 "doc string generic separate-default"
437 ;; default implementation provided separately
440 (cl-defmethod xref-elisp-generic-separate-default (arg1 arg2)
441 "doc string generic separate-default default"
442 "separate default")
444 (cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type) arg2)
445 "doc string generic separate-default xref-elisp-root-type"
446 "non-default for separate-default")
448 (cl-defmethod xref-elisp-generic-implicit-generic (arg1 arg2)
449 "doc string generic implicit-generic default"
450 "default for implicit generic")
452 (cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type) arg2)
453 "doc string generic implicit-generic xref-elisp-root-type"
454 "non-default for implicit generic")
457 (xref-elisp-deftest find-defs-defgeneric-no-methods
458 (elisp--xref-find-definitions 'xref-elisp-generic-no-methods)
459 (list
460 (xref-make "(cl-defgeneric xref-elisp-generic-no-methods)"
461 (xref-make-elisp-location
462 'xref-elisp-generic-no-methods 'cl-defgeneric
463 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
466 (xref-elisp-deftest find-defs-defgeneric-no-default
467 (elisp--xref-find-definitions 'xref-elisp-generic-no-default)
468 (list
469 (xref-make "(cl-defgeneric xref-elisp-generic-no-default)"
470 (xref-make-elisp-location
471 'xref-elisp-generic-no-default 'cl-defgeneric
472 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
473 (xref-make "(cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type) arg2))"
474 (xref-make-elisp-location
475 (cl--generic-load-hist-format
476 'xref-elisp-generic-no-default nil '(xref-elisp-root-type t))
477 'cl-defmethod
478 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
481 (xref-elisp-deftest find-defs-defgeneric-co-located-default
482 (elisp--xref-find-definitions 'xref-elisp-generic-co-located-default)
483 (list
484 (xref-make "(cl-defgeneric xref-elisp-generic-co-located-default)"
485 (xref-make-elisp-location
486 'xref-elisp-generic-co-located-default 'cl-defgeneric
487 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
488 (xref-make "(cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type) arg2))"
489 (xref-make-elisp-location
490 (cl--generic-load-hist-format
491 'xref-elisp-generic-co-located-default nil
492 '(xref-elisp-root-type t))
493 'cl-defmethod
494 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
497 (xref-elisp-deftest find-defs-defgeneric-separate-default
498 (elisp--xref-find-definitions 'xref-elisp-generic-separate-default)
499 (list
500 (xref-make "(cl-defgeneric xref-elisp-generic-separate-default)"
501 (xref-make-elisp-location
502 'xref-elisp-generic-separate-default 'cl-defgeneric
503 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
504 (xref-make "(cl-defmethod xref-elisp-generic-separate-default (arg1 arg2))"
505 (xref-make-elisp-location
506 (cl--generic-load-hist-format
507 'xref-elisp-generic-separate-default nil '(t t))
508 'cl-defmethod
509 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
510 (xref-make "(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type) arg2))"
511 (xref-make-elisp-location
512 (cl--generic-load-hist-format
513 'xref-elisp-generic-separate-default nil
514 '(xref-elisp-root-type t))
515 'cl-defmethod
516 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
519 (xref-elisp-deftest find-defs-defgeneric-implicit-generic
520 (elisp--xref-find-definitions 'xref-elisp-generic-implicit-generic)
521 (list
522 (xref-make "(cl-defmethod xref-elisp-generic-implicit-generic (arg1 arg2))"
523 (xref-make-elisp-location
524 (cl--generic-load-hist-format
525 'xref-elisp-generic-implicit-generic nil '(t t))
526 'cl-defmethod
527 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
528 (xref-make "(cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type) arg2))"
529 (xref-make-elisp-location
530 (cl--generic-load-hist-format
531 'xref-elisp-generic-implicit-generic nil
532 '(xref-elisp-root-type t))
533 'cl-defmethod
534 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
537 ;; Test that we handle more than one method
539 ;; When run from the Makefile, etags is not loaded at compile time,
540 ;; but it is by the time this test is run. interactively; don't fail
541 ;; for that.
542 (require 'etags)
543 (xref-elisp-deftest find-defs-defgeneric-el
544 (elisp--xref-find-definitions 'xref-location-marker)
545 (list
546 (xref-make "(cl-defgeneric xref-location-marker)"
547 (xref-make-elisp-location
548 'xref-location-marker 'cl-defgeneric
549 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
550 (xref-make "(cl-defmethod xref-location-marker ((l xref-elisp-location)))"
551 (xref-make-elisp-location
552 (cl--generic-load-hist-format
553 'xref-location-marker nil '(xref-elisp-location))
554 'cl-defmethod
555 (expand-file-name "../../../lisp/progmodes/elisp-mode.el" emacs-test-dir)))
556 (xref-make "(cl-defmethod xref-location-marker ((l xref-file-location)))"
557 (xref-make-elisp-location
558 (cl--generic-load-hist-format
559 'xref-location-marker nil '(xref-file-location))
560 'cl-defmethod
561 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
562 (xref-make "(cl-defmethod xref-location-marker ((l xref-buffer-location)))"
563 (xref-make-elisp-location
564 (cl--generic-load-hist-format
565 'xref-location-marker nil '(xref-buffer-location))
566 'cl-defmethod
567 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
568 (xref-make "(cl-defmethod xref-location-marker ((l xref-bogus-location)))"
569 (xref-make-elisp-location
570 (cl--generic-load-hist-format
571 'xref-location-marker nil '(xref-bogus-location))
572 'cl-defmethod
573 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
574 (xref-make "(cl-defmethod xref-location-marker ((l xref-etags-location)))"
575 (xref-make-elisp-location
576 (cl--generic-load-hist-format
577 'xref-location-marker nil '(xref-etags-location))
578 'cl-defmethod
579 (expand-file-name "../../../lisp/progmodes/etags.el" emacs-test-dir)))
582 (xref-elisp-deftest find-defs-defgeneric-eval
583 (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ())))
584 nil)
586 ;; Define some mode-local overloadable/overridden functions for xref to find
587 (require 'mode-local)
589 (define-overloadable-function xref-elisp-overloadable-no-methods ()
590 "doc string overloadable no-methods")
592 (define-overloadable-function xref-elisp-overloadable-no-default ()
593 "doc string overloadable no-default")
595 ;; FIXME: byte compiler complains about unused lexical arguments
596 ;; generated by this macro.
597 (define-mode-local-override xref-elisp-overloadable-no-default c-mode
598 (start end &optional nonterminal depth returnonerror)
599 "doc string overloadable no-default c-mode."
600 "result overloadable no-default c-mode.")
602 (define-overloadable-function xref-elisp-overloadable-co-located-default ()
603 "doc string overloadable co-located-default"
604 "result overloadable co-located-default.")
606 (define-mode-local-override xref-elisp-overloadable-co-located-default c-mode
607 (start end &optional nonterminal depth returnonerror)
608 "doc string overloadable co-located-default c-mode."
609 "result overloadable co-located-default c-mode.")
611 (define-overloadable-function xref-elisp-overloadable-separate-default ()
612 "doc string overloadable separate-default.")
614 (defun xref-elisp-overloadable-separate-default-default ()
615 "doc string overloadable separate-default default"
616 "result overloadable separate-default.")
618 (define-mode-local-override xref-elisp-overloadable-separate-default c-mode
619 (start end &optional nonterminal depth returnonerror)
620 "doc string overloadable separate-default c-mode."
621 "result overloadable separate-default c-mode.")
623 (xref-elisp-deftest find-defs-define-overload-no-methods
624 (elisp--xref-find-definitions 'xref-elisp-overloadable-no-methods)
625 (list
626 (xref-make "(define-overloadable-function xref-elisp-overloadable-no-methods)"
627 (xref-make-elisp-location
628 'xref-elisp-overloadable-no-methods 'define-overloadable-function
629 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
632 (xref-elisp-deftest find-defs-define-overload-no-default
633 (elisp--xref-find-definitions 'xref-elisp-overloadable-no-default)
634 (list
635 (xref-make "(define-overloadable-function xref-elisp-overloadable-no-default)"
636 (xref-make-elisp-location
637 'xref-elisp-overloadable-no-default 'define-overloadable-function
638 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
639 (xref-make "(define-mode-local-override xref-elisp-overloadable-no-default c-mode)"
640 (xref-make-elisp-location
641 '(xref-elisp-overloadable-no-default-c-mode . c-mode) 'define-mode-local-override
642 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
645 (xref-elisp-deftest find-defs-define-overload-co-located-default
646 (elisp--xref-find-definitions 'xref-elisp-overloadable-co-located-default)
647 (list
648 (xref-make "(define-overloadable-function xref-elisp-overloadable-co-located-default)"
649 (xref-make-elisp-location
650 'xref-elisp-overloadable-co-located-default 'define-overloadable-function
651 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
652 (xref-make "(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode)"
653 (xref-make-elisp-location
654 '(xref-elisp-overloadable-co-located-default-c-mode . c-mode) 'define-mode-local-override
655 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
658 (xref-elisp-deftest find-defs-define-overload-separate-default
659 (elisp--xref-find-definitions 'xref-elisp-overloadable-separate-default)
660 (list
661 (xref-make "(define-overloadable-function xref-elisp-overloadable-separate-default)"
662 (xref-make-elisp-location
663 'xref-elisp-overloadable-separate-default 'define-overloadable-function
664 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
665 (xref-make "(defun xref-elisp-overloadable-separate-default-default)"
666 (xref-make-elisp-location
667 'xref-elisp-overloadable-separate-default-default nil
668 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
669 (xref-make "(define-mode-local-override xref-elisp-overloadable-separate-default c-mode)"
670 (xref-make-elisp-location
671 '(xref-elisp-overloadable-separate-default-c-mode . c-mode) 'define-mode-local-override
672 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
675 (xref-elisp-deftest find-defs-defun-el
676 (elisp--xref-find-definitions 'xref-find-definitions)
677 (list
678 (xref-make "(defun xref-find-definitions)"
679 (xref-make-elisp-location
680 'xref-find-definitions nil
681 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))))
683 (xref-elisp-deftest find-defs-defun-eval
684 (elisp--xref-find-definitions (eval '(defun stephe-leake-defun ())))
685 nil)
687 (xref-elisp-deftest find-defs-defun-c
688 (elisp--xref-find-definitions 'buffer-live-p)
689 (list
690 (xref-make "(defun buffer-live-p)"
691 (xref-make-elisp-location 'buffer-live-p nil "src/buffer.c"))))
693 ;; FIXME: deftype
695 (xref-elisp-deftest find-defs-defun-c-defvar-c
696 (xref-backend-definitions 'elisp "system-name")
697 (list
698 (xref-make "(defvar system-name)"
699 (xref-make-elisp-location 'system-name 'defvar "src/editfns.c"))
700 (xref-make "(defun system-name)"
701 (xref-make-elisp-location 'system-name nil "src/editfns.c")))
704 (xref-elisp-deftest find-defs-defun-el-defvar-c
705 (xref-backend-definitions 'elisp "abbrev-mode")
706 ;; It's a minor mode, but the variable is defined in buffer.c
707 (list
708 (xref-make "(defvar abbrev-mode)"
709 (xref-make-elisp-location 'abbrev-mode 'defvar "src/buffer.c"))
710 (cons
711 (xref-make "(defun abbrev-mode)"
712 (xref-make-elisp-location
713 'abbrev-mode nil
714 (expand-file-name "../../../lisp/abbrev.el" emacs-test-dir)))
715 "(define-minor-mode abbrev-mode"))
718 ;; Source for both variable and defun is "(define-minor-mode
719 ;; compilation-minor-mode". There is no way to tell that directly from
720 ;; the symbol, but we can use (memq sym minor-mode-list) to detect
721 ;; that the symbol is a minor mode. See `elisp--xref-find-definitions'
722 ;; for more comments.
724 ;; IMPROVEME: return defvar instead of defun if source near starting
725 ;; point indicates the user is searching for a variable, not a
726 ;; function.
727 (require 'compile) ;; not loaded by default at test time
728 (xref-elisp-deftest find-defs-defun-defvar-el
729 (elisp--xref-find-definitions 'compilation-minor-mode)
730 (list
731 (cons
732 (xref-make "(defun compilation-minor-mode)"
733 (xref-make-elisp-location
734 'compilation-minor-mode nil
735 (expand-file-name "../../../lisp/progmodes/compile.el" emacs-test-dir)))
736 "(define-minor-mode compilation-minor-mode")
739 (xref-elisp-deftest find-defs-defvar-el
740 (elisp--xref-find-definitions 'xref--marker-ring)
741 (list
742 (xref-make "(defvar xref--marker-ring)"
743 (xref-make-elisp-location
744 'xref--marker-ring 'defvar
745 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
748 (xref-elisp-deftest find-defs-defvar-c
749 (elisp--xref-find-definitions 'default-directory)
750 (list
751 (cons
752 (xref-make "(defvar default-directory)"
753 (xref-make-elisp-location 'default-directory 'defvar "src/buffer.c"))
754 ;; IMPROVEME: we might be able to compute this target
755 "DEFVAR_PER_BUFFER (\"default-directory\"")))
757 (xref-elisp-deftest find-defs-defvar-eval
758 (elisp--xref-find-definitions (eval '(defvar stephe-leake-defvar nil)))
759 nil)
761 (xref-elisp-deftest find-defs-face-el
762 (elisp--xref-find-definitions 'font-lock-keyword-face)
763 ;; 'font-lock-keyword-face is both a face and a var
764 (list
765 (xref-make "(defvar font-lock-keyword-face)"
766 (xref-make-elisp-location
767 'font-lock-keyword-face 'defvar
768 (expand-file-name "../../../lisp/font-lock.el" emacs-test-dir)))
769 (xref-make "(defface font-lock-keyword-face)"
770 (xref-make-elisp-location
771 'font-lock-keyword-face 'defface
772 (expand-file-name "../../../lisp/font-lock.el" emacs-test-dir)))
775 (xref-elisp-deftest find-defs-face-eval
776 (elisp--xref-find-definitions (eval '(defface stephe-leake-defface nil "")))
777 nil)
779 (xref-elisp-deftest find-defs-feature-el
780 (elisp--xref-find-definitions 'xref)
781 (list
782 (cons
783 (xref-make "(feature xref)"
784 (xref-make-elisp-location
785 'xref 'feature
786 (expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
787 ";;; Code:")
790 (xref-elisp-deftest find-defs-feature-eval
791 (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature)))
792 nil)
794 (ert-deftest elisp--preceding-sexp--char-name ()
795 (with-temp-buffer
796 (emacs-lisp-mode)
797 (insert "?\\N{HEAVY CHECK MARK}")
798 (should (equal (elisp--preceding-sexp) ?\N{HEAVY CHECK MARK}))))
800 (provide 'elisp-mode-tests)
801 ;;; elisp-mode-tests.el ends here