diff options
| author | João Távora | 2023-03-15 10:27:24 +0000 |
|---|---|---|
| committer | João Távora | 2023-03-15 11:03:16 +0000 |
| commit | 0fdc953edf7cfd0fe236b6b6e5726e4e58d9a94f (patch) | |
| tree | d3e7857ef75b54269cd0c37a05c48c904e244cdd | |
| parent | fe58837bbec5181013b178684860f74e0379d965 (diff) | |
| download | emacs-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-NEWS | 13 | ||||
| -rw-r--r-- | lisp/progmodes/eglot.el | 14 | ||||
| -rw-r--r-- | test/lisp/progmodes/eglot-tests.el | 49 |
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 |
| 13 | version 29.1 and with GNU ELPA since 2018. | 13 | version 29.1 and with GNU ELPA since 2018. |
| 14 | 14 | ||
| 15 | Note: references to Eglot issues are presented as "github#nnnn". | 15 | Note: references to some Eglot issues are presented as "github#nnnn". |
| 16 | This refers to https://github.com/joaotavora/eglot/issues/. | 16 | This refers to https://github.com/joaotavora/eglot/issues/. That is, |
| 17 | That is, to look up issue github#1234, go to | 17 | to look up issue github#1234, go to |
| 18 | https://github.com/joaotavora/eglot/issues/1234. | 18 | https://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. |
| 332 | Among other things, consider LSP's "filterText" cookies, which enable | 337 | Among other things, consider LSP's "filterText" cookies, which enable |
| 333 | a kind of poor-man's flex-matching for some backends. | 338 | a 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 () |