aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/lisp/progmodes/eglot-tests.el197
1 files changed, 85 insertions, 112 deletions
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el
index b11ce942b7d..aa0b71a3ae7 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -47,7 +47,6 @@
47(require 'tramp) 47(require 'tramp)
48(require 'ert-x) ; ert-simulate-command 48(require 'ert-x) ; ert-simulate-command
49(require 'edebug) 49(require 'edebug)
50(require 'python) ; some tests use pylsp
51(require 'cc-mode) ; c-mode-hook 50(require 'cc-mode) ; c-mode-hook
52(require 'company nil t) 51(require 'company nil t)
53(require 'yasnippet nil t) 52(require 'yasnippet nil t)
@@ -122,8 +121,6 @@ then restored."
122 ,(format "HOME=%s" 121 ,(format "HOME=%s"
123 (expand-file-name (format "~%s" (user-login-name))))) 122 (expand-file-name (format "~%s" (user-login-name)))))
124 process-environment)) 123 process-environment))
125 ;; Prevent "Can't guess python-indent-offset ..." messages.
126 (python-indent-guess-indent-offset-verbose . nil)
127 (eglot-server-initialized-hook 124 (eglot-server-initialized-hook
128 (lambda (server) (push server new-servers)))) 125 (lambda (server) (push server new-servers))))
129 (setq created-files (mapcan #'eglot--make-file-or-dir file-specs)) 126 (setq created-files (mapcan #'eglot--make-file-or-dir file-specs))
@@ -551,90 +548,101 @@ then restored."
551 (should (equal (buffer-string) 548 (should (equal (buffer-string)
552 "int bar() {return 42;} int main() {return bar();}"))))) 549 "int bar() {return 42;} int main() {return bar();}")))))
553 550
551(defun eglot--wait-for-clangd ()
552 (eglot--sniffing (:server-notifications s-notifs)
553 (should (eglot--tests-connect))
554 (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
555 (string= method "textDocument/publishDiagnostics"))))
556
554(ert-deftest eglot-test-basic-completions () 557(ert-deftest eglot-test-basic-completions ()
555 "Test basic autocompletion in a python LSP." 558 "Test basic autocompletion in a clangd LSP."
556 (skip-unless (executable-find "pylsp")) 559 (skip-unless (executable-find "clangd"))
557 (eglot--with-fixture 560 (eglot--with-fixture
558 `(("project" . (("something.py" . "import sys\nsys.exi")))) 561 `(("project" . (("coiso.c" . "#include <stdio.h>\nint main () {fprin"))))
559 (with-current-buffer 562 (with-current-buffer
560 (eglot--find-file-noselect "project/something.py") 563 (eglot--find-file-noselect "project/coiso.c")
561 (should (eglot--tests-connect)) 564 (eglot--sniffing (:server-notifications s-notifs)
565 (eglot--wait-for-clangd)
566 (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
567 (string= method "textDocument/publishDiagnostics")))
562 (goto-char (point-max)) 568 (goto-char (point-max))
563 (completion-at-point) 569 (completion-at-point)
564 (should (looking-back "sys.exit"))))) 570 (message (buffer-string))
571 (should (looking-back "fprintf.?")))))
565 572
566(ert-deftest eglot-test-non-unique-completions () 573(ert-deftest eglot-test-non-unique-completions ()
567 "Test completion resulting in 'Complete, but not unique'." 574 "Test completion resulting in 'Complete, but not unique'."
568 (skip-unless (executable-find "pylsp")) 575 (skip-unless (executable-find "clangd"))
569 (eglot--with-fixture 576 (eglot--with-fixture
570 '(("project" . (("something.py" . "foo=1\nfoobar=2\nfoo")))) 577 `(("project" . (("coiso.c" .
578 ,(concat "int foo; int fooey;"
579 "int main() {foo")))))
571 (with-current-buffer 580 (with-current-buffer
572 (eglot--find-file-noselect "project/something.py") 581 (eglot--find-file-noselect "project/coiso.c")
573 (should (eglot--tests-connect)) 582 (eglot--wait-for-clangd)
574 (goto-char (point-max)) 583 (goto-char (point-max))
575 (completion-at-point)) 584 (completion-at-point)
576 ;; FIXME: `current-message' doesn't work here :-( 585 ;; FIXME: `current-message' doesn't work here :-(
577 (with-current-buffer (messages-buffer) 586 (with-current-buffer (messages-buffer)
578 (save-excursion 587 (save-excursion
579 (goto-char (point-max)) 588 (goto-char (point-max))
580 (forward-line -1) 589 (forward-line -1)
581 (should (looking-at "Complete, but not unique")))))) 590 (should (looking-at "Complete, but not unique")))))))
582 591
583(ert-deftest eglot-test-basic-xref () 592(ert-deftest eglot-test-basic-xref ()
584 "Test basic xref functionality in a python LSP." 593 "Test basic xref functionality in a clangd LSP."
585 (skip-unless (executable-find "pylsp")) 594 (skip-unless (executable-find "clangd"))
586 (eglot--with-fixture 595 (eglot--with-fixture
587 `(("project" . (("something.py" . "def foo(): pass\ndef bar(): foo()")))) 596 `(("project" . (("coiso.c" .
597 ,(concat "int foo=42; int fooey;"
598 "int main() {foo=82;}")))))
588 (with-current-buffer 599 (with-current-buffer
589 (eglot--find-file-noselect "project/something.py") 600 (eglot--find-file-noselect "project/coiso.c")
590 (should (eglot--tests-connect)) 601 (should (eglot--tests-connect))
591 (search-forward "bar(): f") 602 (search-forward "{foo")
592 (call-interactively 'xref-find-definitions) 603 (call-interactively 'xref-find-definitions)
593 (should (looking-at "foo(): pass"))))) 604 (should (looking-at "foo=42")))))
594 605
595(defvar eglot--test-python-buffer 606(defvar eglot--test-c-buffer
596 "\ 607 "\
597def foobarquux(a, b, c=True): pass 608void foobarquux(int a, int b, int c){};
598def foobazquuz(d, e, f): pass 609void foobazquuz(int a, int b, int f){};
610int main() {
599") 611")
600 612
601(declare-function yas-minor-mode nil) 613(declare-function yas-minor-mode nil)
602 614
603(ert-deftest eglot-test-snippet-completions () 615(ert-deftest eglot-test-snippet-completions ()
604 "Test simple snippet completion in a python LSP." 616 "Test simple snippet completion in a clangd LSP."
605 (skip-unless (and (executable-find "pylsp") 617 (skip-unless (and (executable-find "clangd")
606 (functionp 'yas-minor-mode))) 618 (functionp 'yas-minor-mode)))
607 (eglot--with-fixture 619 (eglot--with-fixture
608 `(("project" . (("something.py" . ,eglot--test-python-buffer)))) 620 `(("project" . (("coiso.c" . ,eglot--test-c-buffer))))
609 (with-current-buffer 621 (with-current-buffer
610 (eglot--find-file-noselect "project/something.py") 622 (eglot--find-file-noselect "project/coiso.c")
611 (yas-minor-mode 1) 623 (yas-minor-mode 1)
612 (let ((eglot-workspace-configuration 624 (eglot--wait-for-clangd)
613 `((:pylsp . (:plugins (:jedi_completion (:include_params t)))))))
614 (should (eglot--tests-connect)))
615 (goto-char (point-max)) 625 (goto-char (point-max))
616 (insert "foobar") 626 (insert "foobar")
617 (completion-at-point) 627 (completion-at-point)
618 (should (looking-back "foobarquux(")) 628 (should (looking-back "foobarquux("))
619 (should (looking-at "a, b)"))))) 629 (should (looking-at "int a, int b, int c)")))))
620 630
621(defvar company-candidates) 631(defvar company-candidates)
622(declare-function company-mode nil) 632(declare-function company-mode nil)
623(declare-function company-complete nil) 633(declare-function company-complete nil)
624 634
625(ert-deftest eglot-test-snippet-completions-with-company () 635(ert-deftest eglot-test-snippet-completions-with-company ()
626 "Test simple snippet completion in a python LSP." 636 "Test simple snippet completion in a clangd LSP."
627 (skip-unless (and (executable-find "pylsp") 637 (skip-unless (and (executable-find "clangd")
628 (functionp 'yas-minor-mode) 638 (functionp 'yas-minor-mode)
629 (functionp 'company-complete))) 639 (functionp 'company-complete)))
630 (eglot--with-fixture 640 (eglot--with-fixture
631 `(("project" . (("something.py" . ,eglot--test-python-buffer)))) 641 `(("project" . (("coiso.c" . ,eglot--test-c-buffer))))
632 (with-current-buffer 642 (with-current-buffer
633 (eglot--find-file-noselect "project/something.py") 643 (eglot--find-file-noselect "project/coiso.c")
634 (yas-minor-mode 1) 644 (yas-minor-mode 1)
635 (let ((eglot-workspace-configuration 645 (eglot--wait-for-clangd)
636 `((:pylsp . (:plugins (:jedi_completion (:include_params t)))))))
637 (should (eglot--tests-connect)))
638 (goto-char (point-max)) 646 (goto-char (point-max))
639 (insert "foo") 647 (insert "foo")
640 (company-mode) 648 (company-mode)
@@ -642,98 +650,63 @@ def foobazquuz(d, e, f): pass
642 (should (looking-back "fooba")) 650 (should (looking-back "fooba"))
643 (should (= 2 (length company-candidates))) 651 (should (= 2 (length company-candidates)))
644 ;; this last one is brittle, since there it is possible that 652 ;; this last one is brittle, since there it is possible that
645 ;; pylsp will change the representation of this candidate 653 ;; clangd will change the representation of this candidate
646 (should (member "foobazquuz(d, e, f)" company-candidates))))) 654 (should (member "foobazquuz(int a, int b, int f)" company-candidates)))))
647 655
648(ert-deftest eglot-test-eldoc-after-completions () 656(ert-deftest eglot-test-eldoc-after-completions ()
649 "Test documentation echo in a python LSP." 657 "Test documentation echo in a clangd LSP."
650 (skip-unless (executable-find "pylsp")) 658 (skip-unless (executable-find "clangd"))
651 (eglot--with-fixture 659 (eglot--with-fixture
652 `(("project" . (("something.py" . "import sys\nsys.exi")))) 660 `(("project" . (("coiso.c" . "#include <stdio.h>\nint main () {fprin"))))
653 (with-current-buffer 661 (with-current-buffer
654 (eglot--find-file-noselect "project/something.py") 662 (eglot--find-file-noselect "project/coiso.c")
655 (should (eglot--tests-connect)) 663 (eglot--wait-for-clangd)
656 (goto-char (point-max)) 664 (goto-char (point-max))
657 (completion-at-point) 665 (completion-at-point)
658 (should (looking-back "sys.exit")) 666 (message (buffer-string))
659 (should (string-match "^exit" (eglot--tests-force-full-eldoc)))))) 667 (should (looking-back "fprintf(?"))
668 (unless (= (char-before) ?\()) (insert "()") (backward-char)
669 (eglot--signal-textDocument/didChange)
670 (should (string-match "^fprintf" (eglot--tests-force-full-eldoc))))))
660 671
661(ert-deftest eglot-test-multiline-eldoc () 672(ert-deftest eglot-test-multiline-eldoc ()
662 "Test if suitable amount of lines of hover info are shown." 673 "Test Eldoc documentation from multiple osurces."
663 (skip-unless (executable-find "pylsp")) 674 (skip-unless (executable-find "clangd"))
664 (eglot--with-fixture 675 (eglot--with-fixture
665 `(("project" . (("hover-first.py" . "from datetime import datetime")))) 676 `(("project" . (("coiso.c" .
677 "#include <stdio.h>\nint main () {fprintf(blergh);}"))))
666 (with-current-buffer 678 (with-current-buffer
667 (eglot--find-file-noselect "project/hover-first.py") 679 (eglot--find-file-noselect "project/coiso.c")
668 (should (eglot--tests-connect)) 680 (search-forward "fprintf(ble")
669 (goto-char (point-max)) 681 (eglot--wait-for-clangd)
670 ;; one-line 682 (flymake-start nil t) ;; thing brings in the "unknown identifier blergh"
671 (let* ((eldoc-echo-area-use-multiline-p t) 683 (let* ((captured-message (eglot--tests-force-full-eldoc)))
672 (captured-message (eglot--tests-force-full-eldoc))) 684 ;; check for signature and error message in the result
673 (should (string-match "datetim" captured-message)) 685 (should (string-match "fprintf" captured-message))
686 (should (string-match "blergh" captured-message))
674 (should (cl-find ?\n captured-message)))))) 687 (should (cl-find ?\n captured-message))))))
675 688
676(ert-deftest eglot-test-single-line-eldoc () 689(ert-deftest eglot-test-formatting ()
677 "Test if suitable amount of lines of hover info are shown." 690 "Test formatting in the clangd server."
678 (skip-unless (executable-find "pylsp"))
679 (eglot--with-fixture
680 `(("project" . (("hover-first.py" . "from datetime import datetime"))))
681 (with-current-buffer
682 (eglot--find-file-noselect "project/hover-first.py")
683 (should (eglot--tests-connect))
684 (goto-char (point-max))
685 ;; one-line
686 (let* ((eldoc-echo-area-use-multiline-p nil)
687 (captured-message (eglot--tests-force-full-eldoc)))
688 (should (string-match "datetim" captured-message))
689 (should (not (cl-find ?\n eldoc-last-message)))))))
690
691(ert-deftest eglot-test-python-autopep-formatting ()
692 "Test formatting in the pylsp python LSP.
693pylsp prefers autopep over yafp, despite its README stating the contrary."
694 ;; Beware, default autopep rules can change over time, which may 691 ;; Beware, default autopep rules can change over time, which may
695 ;; affect this test. 692 ;; affect this test.
696 (skip-unless (and (executable-find "pylsp") 693 (skip-unless (executable-find "clangd"))
697 (executable-find "autopep8")))
698 (eglot--with-fixture
699 `(("project" . (("something.py" . "def a():pass\n\ndef b():pass"))))
700 (with-current-buffer
701 (eglot--find-file-noselect "project/something.py")
702 (should (eglot--tests-connect))
703 ;; Try to format just the second line
704 (search-forward "b():pa")
705 (eglot-format (line-beginning-position) (line-end-position))
706 (should (looking-at "ss"))
707 (should
708 (or (string= (buffer-string) "def a():pass\n\n\ndef b(): pass\n")
709 ;; autopep8 2.0.0 (pycodestyle: 2.9.1)
710 (string= (buffer-string) "def a():pass\n\ndef b(): pass")))
711 ;; now format the whole buffer
712 (eglot-format-buffer)
713 (should
714 (string= (buffer-string) "def a(): pass\n\n\ndef b(): pass\n")))))
715
716(ert-deftest eglot-test-python-yapf-formatting ()
717 "Test formatting in the pylsp python LSP."
718 (skip-unless (and (executable-find "pylsp")
719 (not (executable-find "autopep8"))
720 (or (executable-find "yapf")
721 (executable-find "yapf3"))))
722 (eglot--with-fixture 694 (eglot--with-fixture
723 `(("project" . (("something.py" . "def a():pass\ndef b():pass")))) 695 `(("project" . (("coiso.c" . ,(concat "#include <stdio.h>\n"
696 "int main(){fprintf(blergh);}"
697 "int ble{\n\nreturn 0;}")))))
724 (with-current-buffer 698 (with-current-buffer
725 (eglot--find-file-noselect "project/something.py") 699 (eglot--find-file-noselect "project/coiso.c")
726 (should (eglot--tests-connect)) 700 (eglot--wait-for-clangd)
701 (forward-line)
727 ;; Try to format just the second line 702 ;; Try to format just the second line
728 (search-forward "b():pa")
729 (eglot-format (line-beginning-position) (line-end-position)) 703 (eglot-format (line-beginning-position) (line-end-position))
730 (should (looking-at "ss")) 704 (should (looking-at "int main() { fprintf(blergh); }"))
731 (should 705 ;; ;; now format the whole buffer
732 (string= (buffer-string) "def a():pass\n\n\ndef b():\n pass\n"))
733 ;; now format the whole buffer
734 (eglot-format-buffer) 706 (eglot-format-buffer)
735 (should 707 (should
736 (string= (buffer-string) "def a():\n pass\n\n\ndef b():\n pass\n"))))) 708 (string= (buffer-string)
709 "#include <stdio.h>\nint main() { fprintf(blergh); }\nint ble { return 0; }")))))
737 710
738(ert-deftest eglot-test-rust-on-type-formatting () 711(ert-deftest eglot-test-rust-on-type-formatting ()
739 "Test textDocument/onTypeFormatting against rust-analyzer." 712 "Test textDocument/onTypeFormatting against rust-analyzer."