]> rtime.felk.cvut.cz Git - sojka/company-mode.git/blob - company-tests.el
Run tests non-interactively
[sojka/company-mode.git] / company-tests.el
1 ;;; company-tests.el --- company-mode tests  -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 2011, 2013-2014  Free Software Foundation, Inc.
4
5 ;; Author: Nikolaj Schumacher
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
21
22
23 ;;; Commentary:
24 ;;
25
26 ;;; Code:
27
28 (require 'ert)
29 (require 'company)
30 (require 'company-keywords)
31 (require 'company-clang)
32
33 ;;; Core
34
35 (ert-deftest company-sorted-keywords ()
36   "Test that keywords in `company-keywords-alist' are in alphabetical order."
37   (dolist (pair company-keywords-alist)
38     (when (consp (cdr pair))
39       (let ((prev (cadr pair)))
40         (dolist (next (cddr pair))
41           (should (not (equal prev next)))
42           (should (string< prev next))
43           (setq prev next))))))
44
45 (ert-deftest company-good-prefix ()
46   (let ((company-minimum-prefix-length 5)
47         company-abort-manual-when-too-short
48         company--manual-action            ;idle begin
49         (company-selection-changed t))    ;has no effect
50     (should (eq t (company--good-prefix-p "!@#$%")))
51     (should (eq nil (company--good-prefix-p "abcd")))
52     (should (eq nil (company--good-prefix-p 'stop)))
53     (should (eq t (company--good-prefix-p '("foo" . 5))))
54     (should (eq nil (company--good-prefix-p '("foo" . 4))))
55     (should (eq t (company--good-prefix-p '("foo" . t))))))
56
57 (ert-deftest company--manual-prefix-set-and-unset ()
58   (with-temp-buffer
59     (insert "ab")
60     (company-mode)
61     (let (company-frontends
62           (company-backends
63            (list (lambda (command &optional arg)
64                    (cl-case command
65                      (prefix (buffer-substring (point-min) (point)))
66                      (candidates '("abc" "abd")))))))
67       (company-manual-begin)
68       (should (equal "ab" company--manual-prefix))
69       (company-abort)
70       (should (null company--manual-prefix)))))
71
72 (ert-deftest company-abort-manual-when-too-short ()
73   (let ((company-minimum-prefix-length 5)
74         (company-abort-manual-when-too-short t)
75         (company-selection-changed t))    ;has not effect
76     (let ((company--manual-action nil))   ;idle begin
77       (should (eq t (company--good-prefix-p "!@#$%")))
78       (should (eq t (company--good-prefix-p '("foo" . 5))))
79       (should (eq t (company--good-prefix-p '("foo" . t)))))
80     (let ((company--manual-action t)
81           (company--manual-prefix "abc")) ;manual begin from this prefix
82       (should (eq t (company--good-prefix-p "!@#$")))
83       (should (eq nil (company--good-prefix-p "ab")))
84       (should (eq nil (company--good-prefix-p 'stop)))
85       (should (eq t (company--good-prefix-p '("foo" . 4))))
86       (should (eq t (company--good-prefix-p "abcd")))
87       (should (eq t (company--good-prefix-p "abc")))
88       (should (eq t (company--good-prefix-p '("bar" . t)))))))
89
90 (ert-deftest company-multi-backend-with-lambdas ()
91   (let ((company-backend
92          (list (lambda (command &optional arg &rest ignore)
93                  (cl-case command
94                    (prefix "z")
95                    (candidates '("a" "b"))))
96                (lambda (command &optional arg &rest ignore)
97                  (cl-case command
98                    (prefix "z")
99                    (candidates '("c" "d")))))))
100     (should (equal (company-call-backend 'candidates "z") '("a" "b" "c" "d")))))
101
102 (ert-deftest company-multi-backend-filters-backends-by-prefix ()
103   (let ((company-backend
104          (list (lambda (command &optional arg &rest ignore)
105                  (cl-case command
106                    (prefix (cons "z" t))
107                    (candidates '("a" "b"))))
108                (lambda (command &optional arg &rest ignore)
109                  (cl-case command
110                    (prefix "t")
111                    (candidates '("c" "d"))))
112                (lambda (command &optional arg &rest ignore)
113                  (cl-case command
114                    (prefix "z")
115                    (candidates '("e" "f")))))))
116     (should (equal (company-call-backend 'candidates "z") '("a" "b" "e" "f")))))
117
118 (ert-deftest company-multi-backend-remembers-candidate-backend ()
119   (let ((company-backend
120          (list (lambda (command &optional arg)
121                  (cl-case command
122                    (ignore-case nil)
123                    (annotation "1")
124                    (candidates '("a" "c"))
125                    (post-completion "13")))
126                (lambda (command &optional arg)
127                  (cl-case command
128                    (ignore-case t)
129                    (annotation "2")
130                    (candidates '("b" "d"))
131                    (post-completion "42")))
132                (lambda (command &optional arg)
133                  (cl-case command
134                    (annotation "3")
135                    (candidates '("e"))
136                    (post-completion "74"))))))
137     (let ((candidates (company-calculate-candidates nil)))
138       (should (equal candidates '("a" "b" "c" "d" "e")))
139       (should (equal t (company-call-backend 'ignore-case)))
140       (should (equal "1" (company-call-backend 'annotation (nth 0 candidates))))
141       (should (equal "2" (company-call-backend 'annotation (nth 1 candidates))))
142       (should (equal "13" (company-call-backend 'post-completion (nth 2 candidates))))
143       (should (equal "42" (company-call-backend 'post-completion (nth 3 candidates))))
144       (should (equal "3" (company-call-backend 'annotation (nth 4 candidates))))
145       (should (equal "74" (company-call-backend 'post-completion (nth 4 candidates)))))))
146
147 (ert-deftest company-multi-backend-handles-keyword-with ()
148   (let ((primo (lambda (command &optional arg)
149                  (cl-case command
150                    (prefix "a")
151                    (candidates '("abb" "abc" "abd")))))
152         (secundo (lambda (command &optional arg)
153                    (cl-case command
154                      (prefix "a")
155                      (candidates '("acc" "acd"))))))
156     (let ((company-backend (list 'ignore 'ignore :with secundo)))
157       (should (null (company-call-backend 'prefix))))
158     (let ((company-backend (list 'ignore primo :with secundo)))
159       (should (equal "a" (company-call-backend 'prefix)))
160       (should (equal '("abb" "abc" "abd" "acc" "acd")
161                      (company-call-backend 'candidates "a"))))))
162
163 (ert-deftest company-begin-backend-failure-doesnt-break-company-backends ()
164   (with-temp-buffer
165     (insert "a")
166     (company-mode)
167     (should-error
168      (company-begin-backend (lambda (command &rest ignore))))
169     (let (company-frontends
170           (company-backends
171            (list (lambda (command &optional arg)
172                    (cl-case command
173                      (prefix "a")
174                      (candidates '("a" "ab" "ac")))))))
175       (let (this-command)
176         (company-call 'complete))
177       (should (eq 3 company-candidates-length)))))
178
179 (ert-deftest company-require-match-explicit ()
180   (with-temp-buffer
181     (insert "ab")
182     (company-mode)
183     (let (company-frontends
184           (company-require-match 'company-explicit-action-p)
185           (company-backends
186            (list (lambda (command &optional arg)
187                    (cl-case command
188                      (prefix (buffer-substring (point-min) (point)))
189                      (candidates '("abc" "abd")))))))
190       (let (this-command)
191         (company-complete))
192       (let ((last-command-event ?e))
193         (company-call 'self-insert-command 1))
194       (should (eq 2 company-candidates-length))
195       (should (eq 3 (point))))))
196
197 (ert-deftest company-dont-require-match-when-idle ()
198   (with-temp-buffer
199     (insert "ab")
200     (company-mode)
201     (let (company-frontends
202           (company-minimum-prefix-length 2)
203           (company-require-match 'company-explicit-action-p)
204           (company-backends
205            (list (lambda (command &optional arg)
206                    (cl-case command
207                      (prefix (buffer-substring (point-min) (point)))
208                      (candidates '("abc" "abd")))))))
209       (company-idle-begin (current-buffer) (selected-window)
210                           (buffer-chars-modified-tick) (point))
211       (should (eq 2 company-candidates-length))
212       (let ((last-command-event ?e))
213         (company-call 'self-insert-command 1))
214       (should (eq nil company-candidates-length))
215       (should (eq 4 (point))))))
216
217 (ert-deftest company-dont-require-match-if-old-prefix-ended-and-was-a-match ()
218   (with-temp-buffer
219     (insert "ab")
220     (company-mode)
221     (let (company-frontends
222           (company-require-match 'company-explicit-action-p)
223           (company-backends
224            (list (lambda (command &optional arg)
225                    (cl-case command
226                      (prefix (company-grab-word))
227                      (candidates '("abc" "ab" "abd"))
228                      (sorted t))))))
229       (let (this-command)
230         (company-complete))
231       (let ((last-command-event ?e))
232         (company-call 'self-insert-command 1))
233       (should (eq 3 company-candidates-length))
234       (should (eq 3 (point)))
235       (let ((last-command-event ? ))
236         (company-call 'self-insert-command 1))
237       (should (null company-candidates-length))
238       (should (eq 4 (point))))))
239
240 (ert-deftest company-should-complete-whitelist ()
241   (with-temp-buffer
242     (insert "ab")
243     (company-mode)
244     (let (company-frontends
245           company-begin-commands
246           (company-backends
247            (list (lambda (command &optional arg)
248                    (cl-case command
249                      (prefix (buffer-substring (point-min) (point)))
250                      (candidates '("abc" "abd")))))))
251       (let ((company-continue-commands nil))
252         (let (this-command)
253           (company-complete))
254         (company-call 'backward-delete-char 1)
255         (should (null company-candidates-length)))
256       (let ((company-continue-commands '(backward-delete-char)))
257         (let (this-command)
258           (company-complete))
259         (company-call 'backward-delete-char 1)
260         (should (eq 2 company-candidates-length))))))
261
262 (ert-deftest company-should-complete-blacklist ()
263   (with-temp-buffer
264     (insert "ab")
265     (company-mode)
266     (let (company-frontends
267           company-begin-commands
268           (company-backends
269            (list (lambda (command &optional arg)
270                    (cl-case command
271                      (prefix (buffer-substring (point-min) (point)))
272                      (candidates '("abc" "abd")))))))
273       (let ((company-continue-commands '(not backward-delete-char)))
274         (let (this-command)
275           (company-complete))
276         (company-call 'backward-delete-char 1)
277         (should (null company-candidates-length)))
278       (let ((company-continue-commands '(not backward-delete-char-untabify)))
279         (let (this-command)
280           (company-complete))
281         (company-call 'backward-delete-char 1)
282         (should (eq 2 company-candidates-length))))))
283
284 (ert-deftest company-auto-complete-explicit ()
285   (with-temp-buffer
286     (insert "ab")
287     (company-mode)
288     (let (company-frontends
289           (company-auto-complete 'company-explicit-action-p)
290           (company-auto-complete-chars '(? ))
291           (company-backends
292            (list (lambda (command &optional arg)
293                    (cl-case command
294                      (prefix (buffer-substring (point-min) (point)))
295                      (candidates '("abcd" "abef")))))))
296       (let (this-command)
297         (company-complete))
298       (let ((last-command-event ? ))
299         (company-call 'self-insert-command 1))
300       (should (string= "abcd " (buffer-string))))))
301
302 (ert-deftest company-no-auto-complete-when-idle ()
303   (with-temp-buffer
304     (insert "ab")
305     (company-mode)
306     (let (company-frontends
307           (company-auto-complete 'company-explicit-action-p)
308           (company-auto-complete-chars '(? ))
309           (company-minimum-prefix-length 2)
310           (company-backends
311            (list (lambda (command &optional arg)
312                    (cl-case command
313                      (prefix (buffer-substring (point-min) (point)))
314                      (candidates '("abcd" "abef")))))))
315       (company-idle-begin (current-buffer) (selected-window)
316                           (buffer-chars-modified-tick) (point))
317       (let ((last-command-event ? ))
318         (company-call 'self-insert-command 1))
319       (should (string= "ab " (buffer-string))))))
320
321 (ert-deftest company-clears-explicit-action-when-no-matches ()
322   (with-temp-buffer
323     (company-mode)
324     (let (company-frontends
325           company-backends)
326       (company-call 'manual-begin) ;; fails
327       (should (null company-candidates))
328       (should (null (company-explicit-action-p))))))
329
330 (ert-deftest company-ignore-case-replaces-prefix ()
331   (with-temp-buffer
332     (company-mode)
333     (let (company-frontends
334           company-end-of-buffer-workaround
335           (company-backends
336            (list (lambda (command &optional arg)
337                    (cl-case command
338                      (prefix (buffer-substring (point-min) (point)))
339                      (candidates '("abcd" "abef"))
340                      (ignore-case t))))))
341       (insert "A")
342       (let (this-command)
343         (company-complete))
344       (should (string= "ab" (buffer-string)))
345       (delete-char -2)
346       (insert "A") ; hack, to keep it in one test
347       (company-complete-selection)
348       (should (string= "abcd" (buffer-string))))))
349
350 (ert-deftest company-ignore-case-with-keep-prefix ()
351   (with-temp-buffer
352     (insert "AB")
353     (company-mode)
354     (let (company-frontends
355           (company-backends
356            (list (lambda (command &optional arg)
357                    (cl-case command
358                      (prefix (buffer-substring (point-min) (point)))
359                      (candidates '("abcd" "abef"))
360                      (ignore-case 'keep-prefix))))))
361       (let (this-command)
362         (company-complete))
363       (company-complete-selection)
364       (should (string= "ABcd" (buffer-string))))))
365
366 (ert-deftest company-non-prefix-completion ()
367   (with-temp-buffer
368     (insert "tc")
369     (company-mode)
370     (let (company-frontends
371           company-end-of-buffer-workaround
372           (company-backends
373            (list (lambda (command &optional arg)
374                    (cl-case command
375                      (prefix (buffer-substring (point-min) (point)))
376                      (candidates '("tea-cup" "teal-color")))))))
377       (let (this-command)
378         (company-complete))
379       (should (string= "tc" (buffer-string)))
380       (company-complete-selection)
381       (should (string= "tea-cup" (buffer-string))))))
382
383 (ert-deftest company-pseudo-tooltip-does-not-get-displaced ()
384   :tags '(interactive)
385   (with-temp-buffer
386     (save-window-excursion
387       (set-window-buffer nil (current-buffer))
388       (save-excursion (insert " ff"))
389       (company-mode)
390       (let ((company-frontends '(company-pseudo-tooltip-frontend))
391             (company-begin-commands '(self-insert-command))
392             (company-backends
393              (list (lambda (c &optional arg)
394                      (cl-case c (prefix "") (candidates '("a" "b" "c")))))))
395         (let (this-command)
396           (company-call 'complete))
397         (company-call 'open-line 1)
398         (should (eq 2 (overlay-start company-pseudo-tooltip-overlay)))))))
399
400 (ert-deftest company-pseudo-tooltip-show ()
401   :tags '(interactive)
402   (with-temp-buffer
403     (save-window-excursion
404     (set-window-buffer nil (current-buffer))
405     (insert "aaaa\n  bb\nccccccc\nddd")
406     (search-backward "bb")
407     (let ((col (company--column))
408           (company-candidates-length 2)
409           (company-candidates '("123" "45"))
410           (company-backend 'ignore))
411       (company-pseudo-tooltip-show (company--row) col 0)
412       (let ((ov company-pseudo-tooltip-overlay))
413         ;; With margins.
414         (should (eq (overlay-get ov 'company-width) 5))
415         ;; FIXME: Make it 2?
416         (should (eq (overlay-get ov 'company-height) company-tooltip-limit))
417         (should (eq (overlay-get ov 'company-column) col))
418         (should (string= (overlay-get ov 'company-after)
419                          "  123 \nc 45  c\nddd\n")))))))
420
421 (ert-deftest company-pseudo-tooltip-edit-updates-width ()
422   :tags '(interactive)
423   (with-temp-buffer
424     (set-window-buffer nil (current-buffer))
425     (let ((company-candidates-length 5)
426           (company-candidates '("123" "45" "67" "89" "1011"))
427           (company-backend 'ignore)
428           (company-tooltip-limit 4)
429           (company-tooltip-offset-display 'scrollbar))
430       (company-pseudo-tooltip-show (company--row)
431                                    (company--column)
432                                    0)
433       (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width)
434                   6))
435       (company-pseudo-tooltip-edit 4)
436       (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width)
437                   7)))))
438
439 (ert-deftest company-preview-show-with-annotations ()
440   :tags '(interactive)
441   (with-temp-buffer
442     (save-window-excursion
443       (set-window-buffer nil (current-buffer))
444       (save-excursion (insert "\n"))
445       (let ((company-candidates-length 1)
446             (company-candidates '("123")))
447         (company-preview-show-at-point (point))
448         (let ((ov company-preview-overlay))
449           (should (string= (overlay-get ov 'display) "123\n")))))))
450
451 (ert-deftest company-pseudo-tooltip-show-with-annotations ()
452   :tags '(interactive)
453   (with-temp-buffer
454     (save-window-excursion
455       (set-window-buffer nil (current-buffer))
456       (insert " ")
457       (save-excursion (insert "\n"))
458       (let ((company-candidates-length 2)
459             (company-backend (lambda (action &optional arg &rest _ignore)
460                                (when (eq action 'annotation)
461                                  (cdr (assoc arg '(("123" . "(4)")))))))
462             (company-candidates '("123" "45"))
463             company-tooltip-align-annotations)
464         (company-pseudo-tooltip-show-at-point (point) 0)
465         (let ((ov company-pseudo-tooltip-overlay))
466           ;; With margins.
467           (should (eq (overlay-get ov 'company-width) 8))
468           (should (string= (overlay-get ov 'company-after)
469                            " 123(4) \n 45     \n")))))))
470
471 (ert-deftest company-pseudo-tooltip-show-with-annotations-right-aligned ()
472   :tags '(interactive)
473   (with-temp-buffer
474     (save-window-excursion
475       (set-window-buffer nil (current-buffer))
476       (insert " ")
477       (save-excursion (insert "\n"))
478       (let ((company-candidates-length 3)
479             (company-backend (lambda (action &optional arg &rest _ignore)
480                                (when (eq action 'annotation)
481                                  (cdr (assoc arg '(("123" . "(4)")
482                                                    ("67" . "(891011)")))))))
483             (company-candidates '("123" "45" "67"))
484             (company-tooltip-align-annotations t))
485         (company-pseudo-tooltip-show-at-point (point) 0)
486         (let ((ov company-pseudo-tooltip-overlay))
487           ;; With margins.
488           (should (eq (overlay-get ov 'company-width) 13))
489           (should (string= (overlay-get ov 'company-after)
490                            " 123     (4) \n 45          \n 67 (891011) \n")))))))
491
492 (ert-deftest company-create-lines-shows-numbers ()
493   (let ((company-show-numbers t)
494         (company-candidates '("x" "y" "z"))
495         (company-candidates-length 3)
496         (company-backend 'ignore))
497     (should (equal '(" x 1 " " y 2 " " z 3 ")
498                    (company--create-lines 0 999)))))
499
500 (ert-deftest company-create-lines-truncates-annotations ()
501   (let* ((ww (company--window-width))
502          (data `(("1" . "(123)")
503                  ("2" . nil)
504                  ("3" . ,(concat "(" (make-string (- ww 2) ?4) ")"))
505                  (,(make-string ww ?4) . "<4>")))
506          (company-candidates (mapcar #'car data))
507          (company-candidates-length 4)
508          (company-tooltip-margin 1)
509          (company-backend (lambda (cmd &optional arg)
510                             (when (eq cmd 'annotation)
511                               (cdr (assoc arg data)))))
512          company-tooltip-align-annotations)
513     (should (equal (list (format " 1(123)%s " (company-space-string (- ww 8)))
514                          (format " 2%s " (company-space-string (- ww 3)))
515                          (format " 3(444%s " (make-string (- ww 7) ?4))
516                          (format " %s " (make-string (- ww 2) ?4)))
517                    (company--create-lines 0 999)))
518     (let ((company-tooltip-align-annotations t))
519       (should (equal (list (format " 1%s(123) " (company-space-string (- ww 8)))
520                            (format " 2%s " (company-space-string (- ww 3)))
521                            (format " 3 (444%s " (make-string (- ww 8) ?4))
522                            (format " %s " (make-string (- ww 2) ?4)))
523                      (company--create-lines 0 999))))))
524
525 (ert-deftest company-create-lines-truncates-common-part ()
526   (let* ((ww (company--window-width))
527          (company-candidates-length 2)
528          (company-tooltip-margin 1)
529          (company-backend #'ignore))
530     (let* ((company-common (make-string (- ww 3) ?1))
531            (company-candidates `(,(concat company-common "2")
532                                  ,(concat company-common "3"))))
533       (should (equal (list (format " %s2 " (make-string (- ww 3) ?1))
534                            (format " %s3 " (make-string (- ww 3) ?1)))
535                      (company--create-lines 0 999))))
536     (let* ((company-common (make-string (- ww 2) ?1))
537            (company-candidates `(,(concat company-common "2")
538                                  ,(concat company-common "3"))))
539       (should (equal (list (format " %s " company-common)
540                            (format " %s " company-common))
541                      (company--create-lines 0 999))))
542     (let* ((company-common (make-string ww ?1))
543            (company-candidates `(,(concat company-common "2")
544                                  ,(concat company-common "3")))
545            (res (company--create-lines 0 999)))
546       (should (equal (list (format " %s " (make-string (- ww 2) ?1))
547                            (format " %s " (make-string (- ww 2) ?1)))
548                      res))
549       (should (eq 'company-tooltip-common-selection
550                     (get-text-property (- ww 2) 'face
551                                        (car res))))
552       (should (eq 'company-tooltip-selection
553                   (get-text-property (1- ww) 'face
554                                      (car res))))
555
556 )))
557
558 (ert-deftest company-column-with-composition ()
559   (with-temp-buffer
560     (insert "lambda ()")
561     (compose-region 1 (1+ (length "lambda")) "\\")
562     (should (= (company--column) 4))))
563
564 (ert-deftest company-column-with-line-prefix ()
565   (with-temp-buffer
566     (insert "foo")
567     (put-text-property (point-min) (point) 'line-prefix "  ")
568     (should (= (company--column) 5))))
569
570 (ert-deftest company-column-wth-line-prefix-on-empty-line ()
571   (with-temp-buffer
572     (insert "\n")
573     (forward-char -1)
574     (put-text-property (point-min) (point-max) 'line-prefix "  ")
575     (should (= (company--column) 2))))
576
577 (ert-deftest company-plainify ()
578   (let ((tab-width 8))
579     (should (equal-including-properties
580              (company-plainify "\tabc\td\t")
581              (concat "        "
582                      "abc     "
583                      "d       "))))
584   (should (equal-including-properties
585            (company-plainify (propertize "foobar" 'line-prefix "-*-"))
586            "-*-foobar")))
587
588 (ert-deftest company-modify-line ()
589   (let ((str "-*-foobar"))
590     (should (equal-including-properties
591              (company-modify-line str "zz" 4)
592              "-*-fzzbar"))
593     (should (equal-including-properties
594              (company-modify-line str "xx" 0)
595              "xx-foobar"))
596     (should (equal-including-properties
597              (company-modify-line str "zz" 10)
598              "-*-foobar zz"))))
599
600 (ert-deftest company-scrollbar-bounds ()
601   (should (equal nil (company--scrollbar-bounds 0 3 3)))
602   (should (equal nil (company--scrollbar-bounds 0 4 3)))
603   (should (equal '(0 . 0) (company--scrollbar-bounds 0 1 2)))
604   (should (equal '(1 . 1) (company--scrollbar-bounds 2 2 4)))
605   (should (equal '(2 . 3) (company--scrollbar-bounds 7 4 12)))
606   (should (equal '(1 . 2) (company--scrollbar-bounds 3 4 12)))
607   (should (equal '(1 . 3) (company--scrollbar-bounds 4 5 11))))
608
609 ;;; Async
610
611 (defun company-async-backend (command &optional arg)
612   (pcase command
613     (`prefix "foo")
614     (`candidates
615      (cons :async
616            (lambda (cb)
617              (run-with-timer 0.05 nil
618                              #'funcall cb '("abc" "abd")))))))
619
620 (ert-deftest company-call-backend-forces-sync ()
621   (let ((company-backend 'company-async-backend)
622         (company-async-timeout 0.1))
623     (should (equal '("abc" "abd") (company-call-backend 'candidates)))))
624
625 (ert-deftest company-call-backend-errors-on-timeout ()
626   (with-temp-buffer
627     (let* ((company-backend (lambda (command &optional _arg)
628                               (pcase command
629                                 (`candidates (cons :async 'ignore)))))
630            (company-async-timeout 0.1)
631            (err (should-error (company-call-backend 'candidates "foo"))))
632       (should (string-match-p "async timeout" (cadr err))))))
633
634 (ert-deftest company-call-backend-raw-passes-return-value-verbatim ()
635   (let ((company-backend 'company-async-backend))
636     (should (equal "foo" (company-call-backend-raw 'prefix)))
637     (should (equal :async (car (company-call-backend-raw 'candidates "foo"))))
638     (should (equal 'closure (cadr (company-call-backend-raw 'candidates "foo"))))))
639
640 (ert-deftest company-manual-begin-forces-async-candidates-to-sync ()
641   (with-temp-buffer
642     (company-mode)
643     (let (company-frontends
644           company-transformers
645           (company-backends (list 'company-async-backend)))
646       (company-manual-begin)
647       (should (equal "foo" company-prefix))
648       (should (equal '("abc" "abd") company-candidates)))))
649
650 (ert-deftest company-idle-begin-allows-async-candidates ()
651   (with-temp-buffer
652     (company-mode)
653     (let (company-frontends
654           company-transformers
655           (company-backends (list 'company-async-backend)))
656       (company-idle-begin (current-buffer) (selected-window)
657                           (buffer-chars-modified-tick) (point))
658       (should (null company-candidates))
659       (sleep-for 0.1)
660       (should (equal "foo" company-prefix))
661       (should (equal '("abc" "abd") company-candidates)))))
662
663 (ert-deftest company-idle-begin-cancels-async-candidates-if-buffer-changed ()
664   (with-temp-buffer
665     (company-mode)
666     (let (company-frontends
667           (company-backends (list 'company-async-backend)))
668       (company-idle-begin (current-buffer) (selected-window)
669                           (buffer-chars-modified-tick) (point))
670       (should (null company-candidates))
671       (insert "a")
672       (sleep-for 0.1)
673       (should (null company-candidates)))))
674
675 (ert-deftest company-idle-begin-async-allows-immediate-callbacks ()
676   (with-temp-buffer
677     (company-mode)
678     (let (company-frontends
679           (company-backends
680            (list (lambda (command &optional arg)
681                    (pcase command
682                      (`prefix (buffer-substring (point-min) (point)))
683                      (`candidates
684                       (let ((c (all-completions arg '("abc" "def"))))
685                         (cons :async
686                               (lambda (cb) (funcall cb c)))))
687                      (`no-cache t)))))
688           (company-minimum-prefix-length 0))
689       (company-idle-begin (current-buffer) (selected-window)
690                           (buffer-chars-modified-tick) (point))
691       (should (equal '("abc" "def") company-candidates))
692       (let ((last-command-event ?a))
693         (company-call 'self-insert-command 1))
694       (should (equal '("abc") company-candidates)))))
695
696 (ert-deftest company-multi-backend-forces-prefix-to-sync ()
697   (with-temp-buffer
698     (let ((company-backend (list 'ignore
699                                  (lambda (command)
700                                    (should (eq command 'prefix))
701                                    (cons :async
702                                          (lambda (cb)
703                                            (run-with-timer
704                                             0.01 nil
705                                             (lambda () (funcall cb nil))))))
706                                  (lambda (command)
707                                    (should (eq command 'prefix))
708                                    "foo"))))
709       (should (equal "foo" (company-call-backend-raw 'prefix))))
710     (let ((company-backend (list (lambda (_command)
711                                    (cons :async
712                                          (lambda (cb)
713                                            (run-with-timer
714                                             0.01 nil
715                                             (lambda () (funcall cb "bar"))))))
716                                  (lambda (_command)
717                                    "foo"))))
718       (should (equal "bar" (company-call-backend-raw 'prefix))))))
719
720 (ert-deftest company-multi-backend-merges-deferred-candidates ()
721   (with-temp-buffer
722     (let* ((immediate (lambda (command &optional arg)
723                         (pcase command
724                           (`prefix "foo")
725                           (`candidates
726                            (cons :async
727                                  (lambda (cb) (funcall cb '("f"))))))))
728            (company-backend (list 'ignore
729                                   (lambda (command &optional arg)
730                                     (pcase command
731                                       (`prefix "foo")
732                                       (`candidates
733                                        (should (equal arg "foo"))
734                                        (cons :async
735                                              (lambda (cb)
736                                                (run-with-timer
737                                                 0.01 nil
738                                                 (lambda () (funcall cb '("a" "b")))))))))
739                                   (lambda (command &optional arg)
740                                     (pcase command
741                                       (`prefix "foo")
742                                       (`candidates '("c" "d" "e"))))
743                                   immediate)))
744       (should (equal :async (car (company-call-backend-raw 'candidates "foo"))))
745       (should (equal '("a" "b" "c" "d" "e" "f")
746                      (company-call-backend 'candidates "foo")))
747       (let ((company-backend (list immediate)))
748         (should (equal '("f") (company-call-backend 'candidates "foo")))))))
749
750 ;;; Transformers
751
752 (ert-deftest company-occurrence-prefer-closest-above ()
753   (with-temp-buffer
754     (save-window-excursion
755       (set-window-buffer nil (current-buffer))
756       (insert "foo0
757 foo1
758 ")
759       (save-excursion
760         (insert "
761 foo3
762 foo2"))
763       (let ((company-backend 'company-dabbrev)
764             (company-occurrence-weight-function
765              'company-occurrence-prefer-closest-above))
766         (should (equal '("foo1" "foo0" "foo3" "foo2" "foo4")
767                        (company-sort-by-occurrence
768                         '("foo0" "foo1" "foo2" "foo3" "foo4"))))))))
769
770 (ert-deftest company-occurrence-prefer-any-closest ()
771   (with-temp-buffer
772     (save-window-excursion
773       (set-window-buffer nil (current-buffer))
774       (insert "foo0
775 foo1
776 ")
777       (save-excursion
778         (insert "
779 foo3
780 foo2"))
781       (let ((company-backend 'company-dabbrev)
782             (company-occurrence-weight-function
783              'company-occurrence-prefer-any-closest))
784         (should (equal '("foo1" "foo3" "foo0" "foo2" "foo4")
785                        (company-sort-by-occurrence
786                         '("foo0" "foo1" "foo2" "foo3" "foo4"))))))))
787
788 ;;; Template
789
790 (ert-deftest company-template-removed-after-the-last-jump ()
791   (with-temp-buffer
792     (insert "{ }")
793     (goto-char 2)
794     (let ((tpl (company-template-declare-template (point) (1- (point-max)))))
795       (save-excursion
796         (dotimes (i 2)
797           (insert " ")
798           (company-template-add-field tpl (point) "foo")))
799       (company-call 'template-forward-field)
800       (should (= 3 (point)))
801       (company-call 'template-forward-field)
802       (should (= 7 (point)))
803       (company-call 'template-forward-field)
804       (should (= 11 (point)))
805       (should (zerop (length (overlay-get tpl 'company-template-fields))))
806       (should (null (overlay-buffer tpl))))))
807
808 (ert-deftest company-template-removed-after-input-and-jump ()
809   (with-temp-buffer
810     (insert "{ }")
811     (goto-char 2)
812     (let ((tpl (company-template-declare-template (point) (1- (point-max)))))
813       (save-excursion
814         (insert " ")
815         (company-template-add-field tpl (point) "bar"))
816       (company-call 'template-move-to-first tpl)
817       (should (= 3 (point)))
818       (dolist (c (string-to-list "tee"))
819         (let ((last-command-event c))
820           (company-call 'self-insert-command 1)))
821       (should (string= "{ tee }" (buffer-string)))
822       (should (overlay-buffer tpl))
823       (company-call 'template-forward-field)
824       (should (= 7 (point)))
825       (should (null (overlay-buffer tpl))))))
826
827 (defun company-call (name &rest args)
828   (let* ((maybe (intern (format "company-%s" name)))
829          (command (if (fboundp maybe) maybe name)))
830     (let ((this-command command))
831       (run-hooks 'pre-command-hook))
832     (apply command args)
833     (let ((this-command command))
834       (run-hooks 'post-command-hook))))
835
836 (ert-deftest company-template-c-like-templatify ()
837   (with-temp-buffer
838     (let ((text "foo(int a, short b)"))
839       (insert text)
840       (company-template-c-like-templatify text)
841       (should (equal "foo(arg0, arg1)" (buffer-string)))
842       (should (looking-at "arg0"))
843       (should (equal "int a"
844                      (overlay-get (company-template-field-at) 'display))))))
845
846 (ert-deftest company-template-c-like-templatify-trims-after-closing-paren ()
847   (with-temp-buffer
848     (let ((text "foo(int a, short b)!@ #1334 a"))
849       (insert text)
850       (company-template-c-like-templatify text)
851       (should (equal "foo(arg0, arg1)" (buffer-string)))
852       (should (looking-at "arg0")))))
853
854 ;;; Clang
855
856 (ert-deftest company-clang-objc-templatify ()
857   (with-temp-buffer
858     (let ((text "createBookWithTitle:andAuthor:"))
859       (insert text)
860       (company-clang-objc-templatify text)
861       (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string)))
862       (should (looking-at "arg0"))
863       (should (null (overlay-get (company-template-field-at) 'display))))))