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