bug#81514: 32.0.50; Eglot messages progress reporter shows errors
Stéphane Marks <[email protected]> Thu, 30 Jul 2026 01:54:04 +0200
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <CAN+1Hbo4getfT4FF0g3t55e9jennDgok8+Et58yfHNY8X9OR0g@mail.gmail.com> |
On Wed, Jul 29, 2026 at 7:25 PM João Távora <[email protected]> wrote: > Haven't read it, but see lots of + and only one - which makes me frown. > What was so wrong in Eglot's use of this facility, which worked fine afaict > until your changes? > Two issues with it. First is that the LSP progress messages are percentages growing from 0-100 and the pulsing reporter was incorrect for that use. It shows visibly when one uses the Emacs 31 system-taskbar progress reporters that display graphical bars representing % completion. Second is that those stateful progress bars need to be cleared when the progress reporter is considered "done." So we changed from a pulsing reporter to a "numeric" reporter and correctly called progress-reporter-done at the end. We amended the Tramp progress reporter similarly recently. > João > > João Távora > > On Wed, Jul 29, 2026, 21:28 Stéphane Marks <[email protected]> wrote: > >> On Wed, Jul 29, 2026 at 3:59 PM João Távora <[email protected]> wrote: >> >>> Hi! >>> >>> If there are confirmed failings in Eglot's usage of progress reporters, >>> fixes are welcome. >>> >>> That said, please tread carefully: said fixes must not endanger (or >>> worsen in any way) the backward compatibility of eglot.el all the way to at >>> least Emacs 27, where these progress reporters didn't exist or were more >>> primitive. I'd also appreciate if said fixes are succinct in nature, and >>> not architecture-changing... >>> >>> Thanks! >>> João >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> On Wed, Jul 29, 2026, 20:33 Stéphane Marks <[email protected]> wrote: >>> >>>> On Wed, Jul 29, 2026 at 2:47 PM Stéphane Marks <[email protected]> >>>> wrote: >>>> >>>>> On Wed, Jul 29, 2026 at 11:17 AM Jacek Świerk <[email protected]> >>>>> wrote: >>>>> >>>>>> I can reproduce it with clangd on the following C++ repository: >>>>>> https://github.com/rui314/mold. It doesn't happen every time but >>>>>> often enough: >>>>>> >>>>>> Debugger entered--Lisp error: (wrong-type-argument sequencep 100) >>>>>> ((20 . [1785337541.907988 nil nil "[eglot] mold >>>>>> backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 20 100) >>>>>> progress-reporter-do-update((20 . [1785337541.907988 nil nil >>>>>> "[eglot] mold backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 100 nil) >>>>>> eglot--reporter-update((20 . [1785337541.907988 nil nil "[eglot] >>>>>> mold backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 100 nil) >>>>>> #f(compiled-function (arg1 arg2 arg3 arg4 &rest rest) #<bytecode >>>>>> 0xa1216d65848076a>)(#<eglot-lsp-server 1022b7360904> >>>>>> "backgroundIndexProgress" 100 nil) >>>>>> #f(compiled-function (arg1 arg2 &rest rest) "Handle $/progress >>>>>> notification identified by TOKEN from SERVER." #<bytecode >>>>>> -0xf68beacb9f43862>)(#<eglot-lsp-server 1022b7360904> $/progress :token >>>>>> "backgroundIndexProgress" :value (:kind "end")) >>>>>> apply(#f(compiled-function (arg1 arg2 &rest rest) "Handle >>>>>> $/progress notification identified by TOKEN from SERVER." #<bytecode >>>>>> -0xf68beacb9f43862>) #<eglot-lsp-server 1022b7360904> $/progress (:token >>>>>> "backgroundIndexProgress" :value (:kind "end"))) >>>>>> eglot-handle-notification(#<eglot-lsp-server 1022b7360904> >>>>>> $/progress :token "backgroundIndexProgress" :value (:kind "end")) >>>>>> apply(eglot-handle-notification #<eglot-lsp-server 1022b7360904> >>>>>> $/progress (:token "backgroundIndexProgress" :value (:kind "end"))) >>>>>> #f(compiled-function (server method params) #<bytecode >>>>>> 0x1f1b657efb0838aa>)(#<eglot-lsp-server 1022b7360904> $/progress (:token >>>>>> "backgroundIndexProgress" :value (:kind "end"))) >>>>>> jsonrpc-connection-receive(#<eglot-lsp-server 1022b7360904> >>>>>> (:jsonrpc "2.0" :method "$/progress" :params (:token >>>>>> "backgroundIndexProgress" :value (:kind "end")))) >>>>>> #f(compiled-function (conn msg) #<bytecode >>>>>> 0x4e6153735258fd3>)(#<eglot-lsp-server 1022b7360904> (:jsonrpc "2.0" >>>>>> :method "$/progress" :params (:token "backgroundIndexProgress" :value >>>>>> (:kind "end")))) >>>>>> apply(#f(compiled-function (conn msg) #<bytecode >>>>>> 0x4e6153735258fd3>) (#<eglot-lsp-server 1022b7360904> (:jsonrpc "2.0" >>>>>> :method "$/progress" :params (:token "backgroundIndexProgress" :value >>>>>> (:kind "end"))))) >>>>>> timer-event-handler([t 27242 5829 902968 nil #f(compiled-function >>>>>> (conn msg) #<bytecode 0x4e6153735258fd3>) (#<eglot-lsp-server 1022b7360904> >>>>>> (:jsonrpc "2.0" :method "$/progress" :params (:token >>>>>> "backgroundIndexProgress" :value (:kind "end")))) nil 894000 nil]) >>>>>> >>>>>> The LSP message that causes it looks like this from the >>>>>> (eglot-events-buffer): >>>>>> <-- $/progress >>>>>> {"jsonrpc":"2.0","method":"$/progress","params":{"token":"backgroundIndexProgress","value":{"kind":"end"}}} >>>>>> >>>>>> Based on my understanding of Eglot code, Eglot creates a non-numeric >>>>>> progress >>>>>> reporter because MIN-VALUE and MAX-VALUE arguments are not provided. >>>>>> However, it >>>>>> looks like Eglot updates the created progress reporter as it were >>>>>> numeric: >>>>>> (eglot--reporter-update pr pcnt msg) >>>>>> >>>>>> For the {"kind": "end"} notification, pcnt is set to 100 and msg is >>>>>> nil. After >>>>>> commit b6849229003, the pulsing reporter forwards (or update-text >>>>>> value) as >>>>>> UPDATE-TEXT. That evaluates to 100. Then progress-reporter-echo-area >>>>>> tries >>>>>> (concat (if update-text " " "") update-text) which triggers the shown >>>>>> error. >>>>>> >>>>> I was able to reproduce the issue without eglot and will take a look. >>>>> >>>>> Coincidentally, and independent of the issue, eglot seems to want a >>>>> numeric reporter but instead creates a non-numeric reporter. eglot-handle-notification >>>>> method seems to also be missing the call to progress-reporter-done >>>>> that would clear any stateful reporters it's created such as those in >>>>> system-taskbar for which a relevant change was made in Tramp recently. I >>>>> can take a stab at those. >>>>> >>>> >>>> Here's a patch for progress-reporter. I can look into eglot separately >>>> if agreed. >>>> >>> >> Something like this patch should work and it is backward compatible to >> Emacs 27. I added a comment about the LSP protocol value range for >> percentage and it says we can ignore values outside that range and/or >> integer type. Should we? >> >> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el >> index f701a38ab8b..173a0b87f68 100644 >> --- a/lisp/progmodes/eglot.el >> +++ b/lisp/progmodes/eglot.el >> @@ -2870,9 +2870,17 @@ eglot-handle-notification >> (cl-flet ((fmt (&rest args) (mapconcat #'identity args " ")) >> (mkpr (title) >> (if (eq eglot-report-progress 'messages) >> + ;; >> https://github.com/microsoft/language-server-protocol/blob/b7f5132c95261c0898ae5124e7a91707abc48fcd/_specifications/specification-3-16.md?plain=1#L1455 >> + ;; >> + ;; The value range is [0, 100]. >> + ;; >> + ;; The value should be steadily rising. Clients are >> + ;; free to ignore values that are not following this >> + ;; rule. >> (make-progress-reporter >> (format "[eglot] %s %s: %s" >> - (eglot-project-nickname server) token >> title)) >> + (eglot-project-nickname server) token title) >> + 0 100) >> (list 'eglot--mode-line-reporter token title))) >> (upd (pcnt msg &optional >> (pr (gethash token (eglot--progress-reporters >> server)))) >> @@ -2880,7 +2888,14 @@ eglot-handle-notification >> ((eq (car pr) 'eglot--mode-line-reporter) >> (setcdr (cddr pr) (list msg pcnt)) >> (force-mode-line-update t)) >> - (pr (eglot--reporter-update pr pcnt msg))))) >> + (pr (eglot--reporter-update pr pcnt msg)))) >> + (done (&optional >> + (pr (gethash token (eglot--progress-reporters >> server)))) >> + (cond >> + ((eq (car pr) 'eglot--mode-line-reporter) >> + (setcdr (cddr pr) (list "" 100)) >> + (force-mode-line-update t)) >> + (pr (progress-reporter-done pr))))) >> (eglot--dbind ((WorkDoneProgress) kind title percentage message) >> value >> (pcase kind >> ("begin" >> @@ -2889,6 +2904,7 @@ eglot-handle-notification >> (eglot--progress-reporters server)))) >> ("report" (upd percentage message)) >> ("end" (upd (or percentage 100) message) >> + (done) >> (run-at-time 2 nil >> (lambda () >> (remhash token (eglot--progress-reporters >> server)))))))))) >> >