aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2023-03-15 10:27:24 +0000
committerJoão Távora2023-03-15 11:03:16 +0000
commit0fdc953edf7cfd0fe236b6b6e5726e4e58d9a94f (patch)
treed3e7857ef75b54269cd0c37a05c48c904e244cdd
parentfe58837bbec5181013b178684860f74e0379d965 (diff)
downloademacs-0fdc953edf7cfd0fe236b6b6e5726e4e58d9a94f.tar.gz
emacs-0fdc953edf7cfd0fe236b6b6e5726e4e58d9a94f.zip
Unbreak Eglot (as a :core ELPA package) on Emacs 26.3
Because of the lack of regular automated testing on a CI system, many recent developments in and outside Eglot had wrecked this compatibility. The GitHub CI available at https://github.com/joaotavora/eglot/actions can be used to run this combination of eglot.el + eglot-tests.el on 26.3, 27.2 and 28.2. * etc/EGLOT-NEWS: Mention new version. * lisp/progmodes/eglot.el (eglot--reporter-update): New compatibility shim. (eglot-handle-notification $/progress): Use it. (eglot-handle-notification textDocument/publishDiagnostics): Use two-arg assoc-delete-all. (Version): Bump to 1.13. * test/lisp/progmodes/eglot-tests.el (Commentary): Tweak. (tramp): Tweak require; (eglot-test-diagnostic-tags-unnecessary-code): Use jsonrpc--encode. (eglot--call-with-tramp-test): Adjust dependency on ert-remote-temporary-file-directory. (eglot-test-rust-on-type-formatting) (eglot-test-project-wide-diagnostics-rust-analyzer): Wait longer.
-rw-r--r--etc/EGLOT-NEWS13
-rw-r--r--lisp/progmodes/eglot.el14
-rw-r--r--test/lisp/progmodes/eglot-tests.el49
3 files changed, 46 insertions, 30 deletions
diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS
index dc77e4fe624..dd04e677285 100644
--- a/etc/EGLOT-NEWS
+++ b/etc/EGLOT-NEWS
@@ -12,12 +12,17 @@ This file is about changes in Eglot, the Emacs client for LSP
12(Language Server Protocol) distributed with GNU Emacs since Emacs 12(Language Server Protocol) distributed with GNU Emacs since Emacs
13version 29.1 and with GNU ELPA since 2018. 13version 29.1 and with GNU ELPA since 2018.
14 14
15Note: references to Eglot issues are presented as "github#nnnn". 15Note: references to some Eglot issues are presented as "github#nnnn".
16This refers to https://github.com/joaotavora/eglot/issues/. 16This refers to https://github.com/joaotavora/eglot/issues/. That is,
17That is, to look up issue github#1234, go to 17to look up issue github#1234, go to
18https://github.com/joaotavora/eglot/issues/1234. 18https://github.com/joaotavora/eglot/issues/1234.
19 19
20 20
21* Changes in Eglot 1.13 (15/03/2023)
22
23** ELPA installations on Emacs 26.3 are supported again.
24
25
21* Changes in Eglot 1.12 (13/03/2023) 26* Changes in Eglot 1.12 (13/03/2023)
22 27
23** LSP inlay hints are now supported. 28** LSP inlay hints are now supported.
@@ -328,7 +333,7 @@ This disconnects the server after last managed buffer is killed.
328 333
329(github#217, github#270) 334(github#217, github#270)
330 335
331** Completion support support has been fixed. 336** Completion support has been fixed.
332Among other things, consider LSP's "filterText" cookies, which enable 337Among other things, consider LSP's "filterText" cookies, which enable
333a kind of poor-man's flex-matching for some backends. 338a kind of poor-man's flex-matching for some backends.
334 339
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 037cc87148f..6c1b9eafe43 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2,7 +2,7 @@
2 2
3;; Copyright (C) 2018-2023 Free Software Foundation, Inc. 3;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
4 4
5;; Version: 1.12 5;; Version: 1.13
6;; Author: João Távora <joaotavora@gmail.com> 6;; Author: João Távora <joaotavora@gmail.com>
7;; Maintainer: João Távora <joaotavora@gmail.com> 7;; Maintainer: João Távora <joaotavora@gmail.com>
8;; URL: https://github.com/joaotavora/eglot 8;; URL: https://github.com/joaotavora/eglot
@@ -2147,6 +2147,10 @@ COMMAND is a symbol naming the command."
2147 (_server (_method (eql telemetry/event)) &rest _any) 2147 (_server (_method (eql telemetry/event)) &rest _any)
2148 "Handle notification telemetry/event.") ;; noop, use events buffer 2148 "Handle notification telemetry/event.") ;; noop, use events buffer
2149 2149
2150(defalias 'eglot--reporter-update
2151 (if (> emacs-major-version 26) #'progress-reporter-update
2152 (lambda (a b &optional _c) (progress-reporter-update a b))))
2153
2150(cl-defmethod eglot-handle-notification 2154(cl-defmethod eglot-handle-notification
2151 (server (_method (eql $/progress)) &key token value) 2155 (server (_method (eql $/progress)) &key token value)
2152 "Handle $/progress notification identified by TOKEN from SERVER." 2156 "Handle $/progress notification identified by TOKEN from SERVER."
@@ -2162,10 +2166,10 @@ COMMAND is a symbol naming the command."
2162 (make-progress-reporter prefix 0 100 percentage 1 0) 2166 (make-progress-reporter prefix 0 100 percentage 1 0)
2163 (make-progress-reporter prefix nil nil nil 1 0)) 2167 (make-progress-reporter prefix nil nil nil 1 0))
2164 (eglot--progress-reporters server)))) 2168 (eglot--progress-reporters server))))
2165 (progress-reporter-update pr percentage (fmt title message)))) 2169 (eglot--reporter-update pr percentage (fmt title message))))
2166 ("report" 2170 ("report"
2167 (when-let ((pr (gethash token (eglot--progress-reporters server)))) 2171 (when-let ((pr (gethash token (eglot--progress-reporters server))))
2168 (progress-reporter-update pr percentage (fmt title message)))) 2172 (eglot--reporter-update pr percentage (fmt title message))))
2169 ("end" (remhash token (eglot--progress-reporters server)))))))) 2173 ("end" (remhash token (eglot--progress-reporters server))))))))
2170 2174
2171(cl-defmethod eglot-handle-notification 2175(cl-defmethod eglot-handle-notification
@@ -2183,7 +2187,7 @@ COMMAND is a symbol naming the command."
2183 (buffer (find-buffer-visiting path))) 2187 (buffer (find-buffer-visiting path)))
2184 (with-current-buffer buffer 2188 (with-current-buffer buffer
2185 (cl-loop 2189 (cl-loop
2186 initially (assoc-delete-all path flymake-list-only-diagnostics #'string=) 2190 initially (assoc-delete-all path flymake-list-only-diagnostics)
2187 for diag-spec across diagnostics 2191 for diag-spec across diagnostics
2188 collect (eglot--dbind ((Diagnostic) range code message severity source tags) 2192 collect (eglot--dbind ((Diagnostic) range code message severity source tags)
2189 diag-spec 2193 diag-spec
@@ -2237,7 +2241,7 @@ COMMAND is a symbol naming the command."
2237 into diags 2241 into diags
2238 finally 2242 finally
2239 (setq flymake-list-only-diagnostics 2243 (setq flymake-list-only-diagnostics
2240 (assoc-delete-all path flymake-list-only-diagnostics #'string=)) 2244 (assoc-delete-all path flymake-list-only-diagnostics))
2241 (push (cons path diags) flymake-list-only-diagnostics))))) 2245 (push (cons path diags) flymake-list-only-diagnostics)))))
2242 2246
2243(cl-defun eglot--register-unregister (server things how) 2247(cl-defun eglot--register-unregister (server things how)
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el
index b95e527c510..7ac26732737 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -31,23 +31,20 @@
31;; Some of these tests rely on the GNU ELPA package company.el and 31;; Some of these tests rely on the GNU ELPA package company.el and
32;; yasnippet.el being available. 32;; yasnippet.el being available.
33 33
34;; Some of the tests require access to a remote host files. Since 34;; Some of the tests require access to a remote host files, which is
35;; this could be problematic, a mock-up connection method "mock" is 35;; mocked in the simplest case. If you want to test a real Tramp
36;; used. Emulating a remote connection, it simply calls "sh -i". 36;; connection, override $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable
37;; Tramp's file name handlers still run, so this test is sufficient 37;; value (FIXME: like what?) in order to overwrite the default value.
38;; except for connection establishing. 38;;
39 39;; IMPORTANT: Since Eglot is a :core ELPA package, these tests are
40;; If you want to test a real Tramp connection, set 40 ;;supposed to run on Emacsen down to 26.3. Do not use bleeding-edge
41;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to 41 ;;functionality not compatible with that Emacs version.
42;; overwrite the default value. If you want to skip tests accessing a
43;; remote host, set this environment variable to "/dev/null" or
44;; whatever is appropriate on your system.
45 42
46;;; Code: 43;;; Code:
47(require 'eglot) 44(require 'eglot)
48(require 'cl-lib) 45(require 'cl-lib)
49(require 'ert) 46(require 'ert)
50(require 'tramp) ; must be prior ert-x 47(require 'tramp)
51(require 'ert-x) ; ert-simulate-command 48(require 'ert-x) ; ert-simulate-command
52(require 'edebug) 49(require 'edebug)
53(require 'python) ; some tests use pylsp 50(require 'python) ; some tests use pylsp
@@ -463,7 +460,7 @@ then restored."
463 (eglot--make-file-or-dir '(".git")) 460 (eglot--make-file-or-dir '(".git"))
464 (eglot--make-file-or-dir 461 (eglot--make-file-or-dir
465 `("compile_commands.json" . 462 `("compile_commands.json" .
466 ,(json-serialize 463 ,(jsonrpc--json-encode
467 `[(:directory ,default-directory :command "/usr/bin/c++ -Wall -c main.cpp" 464 `[(:directory ,default-directory :command "/usr/bin/c++ -Wall -c main.cpp"
468 :file ,(expand-file-name "main.cpp"))]))) 465 :file ,(expand-file-name "main.cpp"))])))
469 (let ((eglot-server-programs '((c++-mode . ("clangd"))))) 466 (let ((eglot-server-programs '((c++-mode . ("clangd")))))
@@ -744,7 +741,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary."
744 (should (zerop (shell-command "cargo init"))) 741 (should (zerop (shell-command "cargo init")))
745 (eglot--sniffing (:server-notifications s-notifs) 742 (eglot--sniffing (:server-notifications s-notifs)
746 (should (eglot--tests-connect)) 743 (should (eglot--tests-connect))
747 (eglot--wait-for (s-notifs 10) (&key method &allow-other-keys) 744 (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
748 (string= method "textDocument/publishDiagnostics"))) 745 (string= method "textDocument/publishDiagnostics")))
749 (goto-char (point-max)) 746 (goto-char (point-max))
750 (eglot--simulate-key-event ?.) 747 (eglot--simulate-key-event ?.)
@@ -810,7 +807,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary."
810 (should (= 4 (length (flymake--project-diagnostics)))))))))) 807 (should (= 4 (length (flymake--project-diagnostics))))))))))
811 808
812(ert-deftest eglot-test-project-wide-diagnostics-rust-analyzer () 809(ert-deftest eglot-test-project-wide-diagnostics-rust-analyzer ()
813 "Test diagnostics through multiple files in a TypeScript LSP." 810 "Test diagnostics through multiple files in rust-analyzer."
814 (skip-unless (executable-find "rust-analyzer")) 811 (skip-unless (executable-find "rust-analyzer"))
815 (skip-unless (executable-find "cargo")) 812 (skip-unless (executable-find "cargo"))
816 (skip-unless (executable-find "git")) 813 (skip-unless (executable-find "git"))
@@ -829,7 +826,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary."
829 (eglot--sniffing (:server-notifications s-notifs) 826 (eglot--sniffing (:server-notifications s-notifs)
830 (eglot--tests-connect) 827 (eglot--tests-connect)
831 (flymake-start) 828 (flymake-start)
832 (eglot--wait-for (s-notifs 15) 829 (eglot--wait-for (s-notifs 20)
833 (&key _id method params &allow-other-keys) 830 (&key _id method params &allow-other-keys)
834 (and (string= method "textDocument/publishDiagnostics") 831 (and (string= method "textDocument/publishDiagnostics")
835 (string-suffix-p "main.rs" (plist-get params :uri)))) 832 (string-suffix-p "main.rs" (plist-get params :uri))))
@@ -1272,18 +1269,28 @@ macro will assume it exists."
1272 1269
1273(defvar tramp-histfile-override) 1270(defvar tramp-histfile-override)
1274(defun eglot--call-with-tramp-test (fn) 1271(defun eglot--call-with-tramp-test (fn)
1272 (unless (>= emacs-major-version 27)
1273 (ert-skip "Eglot Tramp support only on Emacs >= 27"))
1275 ;; Set up a Tramp method that’s just a shell so the remote host is 1274 ;; Set up a Tramp method that’s just a shell so the remote host is
1276 ;; really just the local host. 1275 ;; really just the local host.
1277 (let* ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path)) 1276 (let* ((tramp-remote-path (cons 'tramp-own-remote-path
1277 tramp-remote-path))
1278 (tramp-histfile-override t) 1278 (tramp-histfile-override t)
1279 (tramp-verbose 1) 1279 (tramp-verbose 1)
1280 (temporary-file-directory 1280 (temporary-file-directory
1281 (or (bound-and-true-p ert-remote-temporary-file-directory) 1281 (or (bound-and-true-p ert-remote-temporary-file-directory)
1282 temporary-file-directory)) 1282 (prog1 (format "/mock::%s" temporary-file-directory)
1283 (add-to-list
1284 'tramp-methods
1285 '("mock"
1286 (tramp-login-program "sh") (tramp-login-args (("-i")))
1287 (tramp-direct-async ("-c")) (tramp-remote-shell "/bin/sh")
1288 (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10)))
1289 (add-to-list 'tramp-default-host-alist
1290 `("\\`mock\\'" nil ,(system-name)))
1291 (when (and noninteractive (not (file-directory-p "~/")))
1292 (setenv "HOME" temporary-file-directory)))))
1283 (default-directory temporary-file-directory)) 1293 (default-directory temporary-file-directory))
1284 ;; We must check the remote LSP server. So far, just "clangd" is used.
1285 (unless (executable-find "clangd" 'remote)
1286 (ert-skip "Remote clangd not found"))
1287 (funcall fn))) 1294 (funcall fn)))
1288 1295
1289(ert-deftest eglot-test-tramp-test () 1296(ert-deftest eglot-test-tramp-test ()