[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot 9e9dc57 30/69: Merge branch 'master' into jsonrpc
From: |
João Távora |
Subject: |
[elpa] externals/eglot 9e9dc57 30/69: Merge branch 'master' into jsonrpc-refactor (using regular merge) |
Date: |
Fri, 22 Jun 2018 11:54:59 -0400 (EDT) |
branch: externals/eglot
commit 9e9dc573b6ed17f4c0fe00d7d4888e81b79108b8
Merge: 05ff697 0462130
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Merge branch 'master' into jsonrpc-refactor (using regular merge)
This increases the test coverage in the jsonrpc-branch
---
.travis.yml | 2 +-
eglot-tests.el | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 186 insertions(+), 22 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9b0a6d8..60a97fc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ rust:
env:
global:
- - EGLOT_TESTING=t # For kicks, so I don't forget this syntax
+ - TRAVIS_TESTING=t
matrix:
- EMACS_VERSION=26-prerelease
diff --git a/eglot-tests.el b/eglot-tests.el
index 777d2da..bdb8b21 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -64,22 +64,28 @@
(mapconcat #'buffer-name new-buffers ", ")
default-directory
(mapcar #'jsonrpc-name new-servers))
- (let ((eglot-autoreconnect nil))
- (mapc #'eglot-shutdown
- (cl-remove-if-not
- (lambda (server) (process-live-p (eglot--process server)))
- new-servers)))
- (dolist (buf new-buffers) ;; have to save otherwise will get prompted
- (with-current-buffer buf (save-buffer) (kill-buffer)))
- (delete-directory default-directory 'recursive))))
-
-(cl-defmacro eglot--with-test-timeout (timeout &body body)
+ (unwind-protect
+ (let ((eglot-autoreconnect nil))
+ (mapc #'eglot-shutdown
+ (cl-remove-if-not (lambda (server) (process-live-p
(eglot--process server)))
+ new-servers)))
+ (mapc #'kill-buffer (mapcar #'jsonrpc--events-buffer new-servers))
+ (dolist (buf new-buffers) ;; have to save otherwise will get prompted
+ (with-current-buffer buf (save-buffer) (kill-buffer)))
+ (delete-directory default-directory 'recursive)))))
+
+(cl-defmacro eglot--with-timeout (timeout &body body)
(declare (indent 1) (debug t))
- `(eglot--call-with-test-timeout ,timeout (lambda () ,@body)))
+ `(eglot--call-with-timeout ',timeout (lambda () ,@body)))
-(defun eglot--call-with-test-timeout (timeout fn)
- (let* ((tag (make-symbol "tag"))
+(defun eglot--call-with-timeout (timeout fn)
+ (let* ((tag (gensym "eglot-test-timeout"))
(timed-out (make-symbol "timeout"))
+ (timeout-and-message
+ (if (listp timeout) timeout
+ (list timeout "waiting for test to finish")))
+ (timeout (car timeout-and-message))
+ (message (cadr timeout-and-message))
(timer)
(retval))
(unwind-protect
@@ -93,13 +99,81 @@
(funcall fn)))
(cancel-timer timer)
(when (eq retval timed-out)
- (error "Test timeout!")))))
+ (error "%s" (concat "Timed out " message))))))
(defun eglot--find-file-noselect (file &optional noerror)
(unless (or noerror
(file-readable-p file)) (error "%s does not exist" file))
(find-file-noselect file))
+(cl-defmacro eglot--sniffing ((&key server-requests
+ server-notifications
+ server-replies
+ client-requests
+ client-notifications
+ client-replies)
+ &rest body)
+ "Run BODY saving LSP JSON messages in variables, most recent first."
+ (declare (indent 1) (debug (sexp &rest form)))
+ (let ((log-event-ad-sym (make-symbol "eglot--event-sniff")))
+ `(unwind-protect
+ (let ,(delq nil (list server-requests
+ server-notifications
+ server-replies
+ client-requests
+ client-notifications
+ client-replies))
+ (advice-add
+ #'jsonrpc-log-event :before
+ (lambda (_proc message &optional type)
+ (cl-destructuring-bind (&key method id _error &allow-other-keys)
+ message
+ (let ((req-p (and method id))
+ (notif-p method)
+ (reply-p id))
+ (cond
+ ((eq type 'server)
+ (cond (req-p ,(when server-requests
+ `(push message ,server-requests)))
+ (notif-p ,(when server-notifications
+ `(push message ,server-notifications)))
+ (reply-p ,(when server-replies
+ `(push message ,server-replies)))))
+ ((eq type 'client)
+ (cond (req-p ,(when client-requests
+ `(push message ,client-requests)))
+ (notif-p ,(when client-notifications
+ `(push message ,client-notifications)))
+ (reply-p ,(when client-replies
+ `(push message ,client-replies)))))))))
+ '((name . ,log-event-ad-sym)))
+ ,@body)
+ (advice-remove #'jsonrpc-log-event ',log-event-ad-sym))))
+
+(cl-defmacro eglot--wait-for ((events-sym &optional (timeout 1) message) args
&body body)
+ "Spin until FN match in EVENTS-SYM, flush events after it.
+Pass TIMEOUT to `eglot--with-timeout'."
+ (declare (indent 2) (debug (sexp sexp sexp &rest form)))
+ `(eglot--with-timeout (,timeout ,(or message
+ (format "waiting for:\n%s"
(pp-to-string body))))
+ (let ((event
+ (cl-loop thereis (cl-loop for json in ,events-sym
+ when (funcall
+ (jsonrpc-lambda ,args ,@body) json)
+ return (cons json before)
+ collect json into before)
+ for i from 0
+ when (zerop (mod i 5))
+ ;; do (eglot--message "still struggling to find in %s"
+ ;; ,events-sym)
+ do
+ ;; `read-event' is essential to have the file
+ ;; watchers come through.
+ (read-event "[eglot] Waiting a bit..." nil 0.1)
+ (accept-process-output nil 0.1))))
+ (setq ,events-sym (cdr event))
+ (eglot--message "Event detected:\n%s"
+ (pp-to-string (car event))))))
;; `rust-mode' is not a part of emacs. So define these two shims which
;; should be more than enough for testing
@@ -107,9 +181,6 @@
(define-derived-mode rust-mode prog-mode "Rust"))
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
-
-(ert-deftest dummy () "A dummy test" (should t))
-
(ert-deftest auto-detect-running-server ()
"Visit a file and M-x eglot, then visit a neighbour. "
(skip-unless (executable-find "rls"))
@@ -118,7 +189,7 @@
'(("project" . (("coiso.rs" . "bla")
("merdix.rs" . "bla")))
("anotherproject" . (("cena.rs" . "bla"))))
- (eglot--with-test-timeout 2
+ (eglot--with-timeout 2
(with-current-buffer
(eglot--find-file-noselect "project/coiso.rs")
(should (setq server (apply #'eglot (eglot--interactive))))
@@ -138,7 +209,7 @@
(eglot--with-dirs-and-files
'(("project" . (("coiso.rs" . "bla")
("merdix.rs" . "bla"))))
- (eglot--with-test-timeout 3
+ (eglot--with-timeout 3
(with-current-buffer
(eglot--find-file-noselect "project/coiso.rs")
(should (setq server (apply #'eglot (eglot--interactive))))
@@ -156,12 +227,105 @@
(while (process-live-p proc) (accept-process-output nil 0.5)))
(should (not (jsonrpc-current-connection))))))))
+(ert-deftest rls-watches-files ()
+ "Start RLS server. Notify it when a critical file changes."
+ (skip-unless (executable-find "rls"))
+ (skip-unless (executable-find "cargo"))
+ (skip-unless (null (getenv "TRAVIS_TESTING")))
+ (let ((eglot-autoreconnect 1))
+ (eglot--with-dirs-and-files
+ '(("project" . (("coiso.rs" . "bla")
+ ("merdix.rs" . "bla"))))
+ (eglot--with-timeout 10
+ (with-current-buffer
+ (eglot--find-file-noselect "project/coiso.rs")
+ (should (zerop (shell-command "cargo init")))
+ (eglot--sniffing (
+ :server-requests s-requests
+ :client-notifications c-notifs
+ :client-replies c-replies
+ )
+ (should (apply #'eglot (eglot--interactive)))
+ (let (register-id)
+ (eglot--wait-for (s-requests 1)
+ (&key id method &allow-other-keys)
+ (setq register-id id)
+ (string= method "client/registerCapability"))
+ (eglot--wait-for (c-replies 1)
+ (&key id error &allow-other-keys)
+ (and (eq id register-id) (null error))))
+ (delete-file "Cargo.toml")
+ (eglot--wait-for
+ (c-notifs 3 "waiting for didChangeWatchedFiles notification")
+ (&key method params &allow-other-keys)
+ (and (eq method :workspace/didChangeWatchedFiles)
+ (cl-destructuring-bind (&key uri type)
+ (elt (plist-get params :changes) 0)
+ (and (string= (eglot--path-to-uri "Cargo.toml") uri)
+ (= type 3)))))))))))
+
+(ert-deftest rls-basic-diagnostics ()
+ "Hover and highlightChanges are tricky in RLS."
+ (skip-unless (executable-find "rls"))
+ (skip-unless (executable-find "cargo"))
+ (eglot--with-dirs-and-files
+ '(("project" . (("main.rs" . "bla"))))
+ (eglot--with-timeout 3
+ (with-current-buffer
+ (eglot--find-file-noselect "project/main.rs")
+ (should (zerop (shell-command "cargo init")))
+ (eglot--sniffing (:server-notifications s-notifs)
+ (insert "fn main() {\nprintfoo!(\"Hello, world!\");\n}")
+ (apply #'eglot (eglot--interactive))
+ (eglot--wait-for (s-notifs 1)
+ (&key _id method &allow-other-keys)
+ (string= method "textDocument/publishDiagnostics"))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point))))))))
+
+(ert-deftest rls-hover-after-edit ()
+ "Hover and highlightChanges are tricky in RLS."
+ (skip-unless (executable-find "rls"))
+ (skip-unless (executable-find "cargo"))
+ (eglot--with-dirs-and-files
+ '(("project" . (("main.rs" . "bla"))))
+ (eglot--with-timeout 3
+ (with-current-buffer
+ (eglot--find-file-noselect "project/main.rs")
+ (should (zerop (shell-command "cargo init")))
+ (eglot--sniffing (
+ :server-notifications s-notifs
+ :server-requests s-requests
+ :server-replies s-replies
+ :client-notifications c-notifs
+ :client-replies c-replies
+ :client-requests c-reqs
+ )
+ (insert "fn test() -> i32 { let test=3; return te; }")
+ (apply #'eglot (eglot--interactive))
+ (goto-char (point-min))
+ (search-forward "return te")
+ (insert "st")
+ (progn
+ ;; simulate these two which don't happen when buffer isn't
+ ;; visible in a window.
+ (eglot--signal-textDocument/didChange)
+ (eglot-eldoc-function))
+ (let (pending-id)
+ (eglot--wait-for (c-reqs)
+ (&key id method &allow-other-keys)
+ (setq pending-id id)
+ (string= method :textDocument/documentHighlight))
+ (eglot--wait-for (s-replies)
+ (&key id &allow-other-keys)
+ (eq id pending-id))))))))
+
(ert-deftest basic-completions ()
"Test basic autocompletion in a python LSP"
(skip-unless (executable-find "pyls"))
(eglot--with-dirs-and-files
'(("project" . (("something.py" . "import sys\nsys.exi"))))
- (eglot--with-test-timeout 4
+ (eglot--with-timeout 4
(with-current-buffer
(eglot--find-file-noselect "project/something.py")
(should (apply #'eglot (eglot--interactive)))
@@ -174,7 +338,7 @@
(skip-unless (executable-find "pyls"))
(eglot--with-dirs-and-files
'(("project" . (("something.py" . "import sys\nsys.exi"))))
- (eglot--with-test-timeout 4
+ (eglot--with-timeout 4
(with-current-buffer
(eglot--find-file-noselect "project/something.py")
(should (apply #'eglot (eglot--interactive)))
- [elpa] externals/eglot bf9c850 52/69: Get rid of jsonrpc-obj, (continued)
- [elpa] externals/eglot bf9c850 52/69: Get rid of jsonrpc-obj, João Távora, 2018/06/22
- [elpa] externals/eglot 0b474ec 63/69: Fix use of jsonrpc-message in tests, João Távora, 2018/06/22
- [elpa] externals/eglot 44e9647 46/69: Simplify JSONRPC connection shutdown, João Távora, 2018/06/22
- [elpa] externals/eglot 47b957d 65/69: Let's not send Content-type for now., João Távora, 2018/06/22
- [elpa] externals/eglot 61d1276 66/69: Fix another bug in jsonrpc-connection-send, João Távora, 2018/06/22
- [elpa] externals/eglot 2917214 47/69: Merge master into jsonrpc-refactor, João Távora, 2018/06/22
- [elpa] externals/eglot f730fff 48/69: Merge branch 'master' into jsonrpc-refactor, João Távora, 2018/06/22
- [elpa] externals/eglot aaca7de 60/69: Fix ridiculous bug, João Távora, 2018/06/22
- [elpa] externals/eglot d87f4bf 55/69: jsonrpc--log-event should also be private, João Távora, 2018/06/22
- [elpa] externals/eglot a65d3f4 53/69: Make message and warning helpers private, João Távora, 2018/06/22
- [elpa] externals/eglot 9e9dc57 30/69: Merge branch 'master' into jsonrpc-refactor (using regular merge),
João Távora <=
- [elpa] externals/eglot 6c9d41e 38/69: Add reasonably sophisticated deferred action tests, João Távora, 2018/06/22
- [elpa] externals/eglot 2da7d92 50/69: Simplify JSONRPC status setting, João Távora, 2018/06/22
- [elpa] externals/eglot 69a622a 64/69: Fix some typos, João Távora, 2018/06/22
- [elpa] externals/eglot 7371f68 57/69: * jsonrpc.el: Rewrite commentary., João Távora, 2018/06/22
- [elpa] externals/eglot 6531c8b 58/69: Merge branch 'master' into jsonrpc-refactor, João Távora, 2018/06/22
- [elpa] externals/eglot 59cc3fb 61/69: jsonrpc-connection-receive is now a public convenience function, João Távora, 2018/06/22
- [elpa] externals/eglot d371f05 49/69: Request dispatcher's return value determines response, João Távora, 2018/06/22
- [elpa] externals/eglot 0f20fdf 68/69: Tiny README.md change, João Távora, 2018/06/22
- [elpa] externals/eglot cef3c29 22/69: Heroically merge master into jsonrpc-refactor (using imerge), João Távora, 2018/06/22
- [elpa] externals/eglot a4441c6 37/69: Merge master into jsonrpc-refactor (using imerge), João Távora, 2018/06/22