When a response to a semtok request is received, it's important
to remember which regions to flush. Font-lock logic will then
do its magic and coalesce those regions into one before invoking
eglot--semtok-font-lock, and eglot--semtok-font-lock-1 will have
up-to-date data to work with.
* lisp/progmodes/eglot.el (eglot--semtok-request): Rework.
(eglot--semtok-inflight): Adjust docstring.
Don't have evidence for the usefulness of this optimization yet.
* lisp/progmodes/eglot.el (eglot--semtok-idle-timer): Delete.
(eglot--semtok-request): Simplify.
Many back-to-back calls for 'eglot--semtok-request' and small
regions occur even on trivial fast edits. Even though it's
cheap and harmless to send many delta rquests, it's nicer to
just send just one. The debouncing from jsonrpc-async-request
almost suffices, but sometimes two requests creep in because
didChange is sent in between. Use this simple flag to avoid.
* lisp/progmodes/eglot.el (eglot--semtok-inflight): New variable.
(eglot--semtok-request): Use it.
Stefan's idea to use ONLY font-lock instead of jit-lock seems
more promising and less buggy. I did have to add this slightly
odd eglot--semtok-font-lock-2 kludge, though, but other than
that, it seems fine.
* lisp/progmodes/eglot.el (eglot-semantic-tokens-mode): Now use
ONLY font-lock.
(eglot--semtok-request): Rework, don't call painting function
here.
(eglot--semtok-font-lock): Rename from eglot--semtok-jit-lock and
use a single arg. Maybe call eglot--semtok-font-lock-2. Return
nil or risk crashing Emacs.
(eglot--semtok-font-lock-1): Rework slightly.
(eglot--semtok-font-lock-2): New helper.
Simplify many things. Instead of font-lock-add-keywords, use
jit-lock-register exclusively. Works, but slightly problematic,
since when editing the buffer the existing enriched face
information is first removed, then readded. Will try other
approaches.
* lisp/progmodes/eglot.el (eglot-connect-hook): Don't put
eglot--semtok-initialize here.
(eglot--connect): Ratther here.
(eglot--semtok-token-faces): New helper.
(eglot--semtok-font-lock): Delete.
(eglot--semtok-initialize): Rework.
(eglot-semantic-tokens-mode): Simplify.
(eglot--semtok-jit-lock): Simplify.
(eglot--semtok-jit-lock-1): Simplify.
Kept the general structure but clarified the code paths.
Less lines of code, remove some variables. Probably fixed some
bugs and introduced others.
* lisp/progmodes/eglot.el (eglot-lsp-server): Tweak doc.
(eglot--semtok-request-full-on-idle): Delete. Integrated into caller.
(eglot--semtok-jit-lock): Rename from eglot--semtok-propertize. Rework.
(eglot--semtok-jit-lock-1): Extract from old eglot--semtok-propertize.
(eglot-semantic-tokens-mode): Use new eglot--semtok-jit-lock name.
(eglot--semtok-put-cache)
(eglot--semtok-ingest-range-response)
(eglot--semtok-ingest-delta-response)
(eglot--semtok-ingest-full-response): Delete helpers.
(eglot--semtok-apply-delta-edits): Rework with more cl-loopy idioms.
(eglot--semtok-flush-region): Delete.
(eglot--semtok-request): Now takes a region as argument. Rework extensively.
* lisp/progmodes/eglot.el
(eglot-handle-request): Don't bump eglot--versioned-identifier,
since that confuses semtok bootstrap in a new file with clangd.
* lisp/progmodes/eglot.el (eglot--semtok-font-lock): Rename from
eglot--semtok-fontify-tokens.
(eglot-semantic-tokens-mode): Use eglot--semtok-font-lock.
(eglot--semtok-ingest-delta-response): Rename from
eglot--semtok-ingest-full/delta-response
(eglot--semtok-request): Use new function.
Since we keep the invisible characters of all the
server-supplied markdown, we risk that the first lines are
entirely invisible. This defeats the :echo calculation in
eglot-hover-eldoc-function.
Fallout of bug#79552.
* lisp/progmodes/eglot.el (eglot-hover-eldoc-function): Fix.
Co-authored-by: João Távora <joaotavora@gmail.com>
We use gfm-view-mode to render Markdown before we hand over the string
to ElDoc (which usually put it in a 'special' mode "*eldoc*" buffer).
'gfm-view-mode' adds keymap text properties to make links clickable. It
also makes some of the markup invisible with a special 'invisible'
property value which is specific to 'gfm-view-mode'. We used to delete
the latter, therefore breaking the link-clicking. Simply resetting the
regions with non-nil 'invisible' to 't' instead of deleting them fixes
this. See also https://github.com/joaotavora/eglot/discussions/1238
* lisp/progmodes/eglot.el: Make invisible markup invisible
instead of deleting it.
* etc/EGLOT-NEWS: Mention bugfix.
Co-authored-by: João Távora <joaotavora@gmail.com>
The previous change actually introduced a bug in a closely
related but distinct place. We need to address the off-by-one
in the 'substring' call, not the 'add-face-text-property'.
* lisp/progmodes/eglot.el (eglot--sig-info): Fixup.
This feature was tweaked and last tested with a 2019 edition of
the 'ccls' LSP. The spec does not clearly specify this number
to be 0-indexed, but it would make sense that it would be so.
So there's not need to 1+ - correct the numbers at all before
using them in substring. This would fix the Haskell server use
of this feature (which is bug#79259)
* lisp/progmodes/eglot.el (eglot--sig-info): Fix likely off-by-1.
Escape literal % characters in Eglot URIs
Otherwise, a literal % in a file-name will be interpreted (by the
language server) as if it were a part of a percent-encoded sequence.
See Bug#78984 for context on why `url-path-allowed-chars' cannot be
changed to escape literal % characters.
* lisp/progmodes/eglot.el (eglot--uri-path-allowed-chars): Escape %,
remove the redundant variable definition.
* test/lisp/progmodes/eglot-tests.el (eglot-test-path-to-uri-escape):
test it.
* lisp/progmodes/eglot.el (eglot--managed-mode): Use
revert-buffer-in-progress instead of
revert-buffer-in-progress-p.
* lisp/vc/vc-hooks.el (vc-dir-resynch-file): Declare some
functions.
Some minor modes adds their own eldoc display function to
'eldoc-display-functions' hook buffer-locally. So when eldoc
uses 'eldoc-display-functions' to display docs, it should use
the buffer-local value of the hook.
But that's not always the case. In 'eldoc--invoke-strategy', the
code that runs 'eldoc-display-functions' hook is wrapped in a
callback function that eventually gets passed to each
documentation function in 'eldoc-documentation-functions'. So
now it's the documentation functions' responsibility to call the
eldoc callback in the original buffer.
All the eglot documentation functions indeed do that, using
'eglot--when-buffer-window' to switch to the original buffer
when calling the eldoc callback. But
'eglot-code-action-suggestion' is the exception, the callback is
called outside of the 'eglot--when-buffer-window' form.
This patch fixes that.
This bug was originally reported on eldoc-box [1]. The user
found that eldoc-box's display function are rarely called, even
though the minor mode is turned on. This patch fixes the issue.
[1] https://github.com/casouri/eldoc-box/issues/126#issuecomment-2896611278
* lisp/progmodes/eglot.el (eglot-code-action-suggestion): Move
the funcall form into the eglot--when-buffer-window form.
* lisp/progmodes/eglot.el (eglot-uri-to-path): Remove the leading
slash in MS-Windows file names only if they begin with a slash.
This adjusts the function to the recent fix for bug#76982 in
'url-generic-parse-url', which previously would produce file names
that begin with an extra slash. (Bug#78392)
When we don't have anything to give to Flymake, we still want to
signal we're alive so the mode-line doesn't show a confusing
'Wait'.
* lisp/progmodes/eglot.el (eglot--report-to-flymake): Clear 'Wait'
state.
After a change in the buffer has occured, it is often the case
that Flymake is quicker to ask for diagnostics than the server
is to supply them to us. If we're still stuck with old outdated
diagnostics, don't forward them to Flymake, even if it eagerly
asks us for them.
* etc/EGLOT-NEWS (Changes in upcoming Eglot): Announce changes.
* lisp/progmodes/eglot.el
(eglot--diagnostics): Rework.
(eglot--report-to-flymake): Also take version.
(eglot-handle-notification textDocument/publishDiagnostics)
(eglot--managed-mode)
(eglot-flymake-backend): Tweak call to eglot--report-to-flymake.
In certain situations, Eglot has to report to the server parts
of the diagnostics that it itself sent us. The server may use
this as context to compute code actions, for example. Eglot
selects diagnostics by asking Flymake, looking for the ones that
contain Eglot-specific cookies.
But when doing so, it is important to also be aware of the LSP
document version these each of these diagnostics pertain to,
since if a diagonstic in the buffer pertains to an older version
of the LSP document (because Flymake fired or the server hasn't
pushed a new set), that diagnostics 'eglot-lsp-data' cookie is
invalid and possibly harmful.
An example is when a diagnostic extends all the way to the end
of the buffer. If we attempt to fix by shortening the buffer,
an Eldoc-started code actions request may be sent to the server
considering the soon-to-be-deleted Flymake diagnostic as
context. But that diagnostic's 'eglot-lsp-data' cookie is no
longer valid and when processing that context we try to go past
point-max and burp an annoying error.
Best to check the version of the diagnostic (if we have it) and
ignore the ones that don't match the document version.
* lisp/progmodes/eglot.el (eglot--versioned-identifier): Move up.
(eglot--flymake-diagnostics, eglot--diag-to-lsp-diag): New helpers.
(eglot-handle-notification): Record LSP doc version in diagnostics.
(eglot--code-action-bounds)
(eglot--code-action-params): Use eglot--flymake-diagnostics.
* lisp/emacs-lisp/cl-macs.el (cl-gensym): Declare function
obsolete in favor of gensym, added in Emacs 26.1. The only reason
for its existence is that it allows an integer argument, but
that's not really useful, so it's better to remove this complexity.
Ref: https://lists.gnu.org/r/emacs-devel/2017-09/msg00313.html
* doc/misc/cl.texi (Symbols, Creating Symbols, Efficiency Concerns)
(Obsolete Setf Customization): Don't document above obsolete function.
* lisp/emacs-lisp/cl-macs.el (cl--parse-loop-clause):
* lisp/emacs-lisp/edebug.el (edebug-make-form-wrapper):
* lisp/obsolete/cl.el (cl--function-convert, lexical-let):
* lisp/obsolete/thumbs.el (thumbs-temp-file):
* lisp/progmodes/eglot.el (eglot--lambda)
(eglot--when-live-buffer, eglot--when-buffer-window)
(eglot--collecting-xrefs, eglot--glob-parse):
* lisp/progmodes/flymake.el (flymake--run-backend):
* test/lisp/emacs-lisp/package-tests.el (with-package-test):
* test/lisp/progmodes/eglot-tests.el (eglot--guessing-contact):
* test/lisp/progmodes/elisp-mode-tests.el
(elisp-shorthand-read-buffer, elisp-shorthand-read-from-string): Prefer
plain gensym to cl-gensym in files that can depend on Emacs 26.1.
* lisp/jsonrpc.el (jsonrpc-lambda, jsonrpc-request): Prefer gensym to
cl-gensym only when defined, as this file supports Emacs 25.1
* test/lisp/emacs-lisp/cl-macs-tests.el (cl-lib-test-gensym): Simplify
test as 'should' no longer uses cl-gensym.
The async requests frequently issued by ElDoc are a significant
source of request pile-up on the server side (for some servers).
With this change, Eglot will issue additional LSP
$/cancelRequest notifications for in-flight requests of certain
kinds in the pre-command hook.
This required a small change to the 'jsonrpc-async-request'
entrypoint.
This feature is experimental.
* lisp/jsonrpc.el (jsonrpc-async-request): No longer returns nil.
* lisp/progmodes/eglot.el (eglot--inflight-async-requests): New variable.
(eglot--cancel-inflight-async-requests): New function.
(eglot--async-request): New function.
(eglot--pre-command-hook): Call eglot--cancel-inflight-async-requests.
(eglot-signature-eldoc-function, eglot-hover-eldoc-function)
(eglot-highlight-eldoc-function, eglot-code-action-suggestion):
Use eglot--async-request.