João Távora [Tue, 27 Nov 2018 13:49:30 +0000 (13:49 +0000)]
Improve performance of xref summary line collection
* eglot.el (eglot--temp-location-buffers): New variable.
(eglot--handling-xrefs): New macro.
(eglot--xref-make): Use eglot--temp-location-buffers.
(xref-backend-definitions, xref-backend-references)
(xref-backend-apropos): Use eglot--handling-xrefs.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/52
GitHub-reference: per https://github.com/joaotavora/eglot/issues/127
João Távora [Fri, 23 Nov 2018 12:31:15 +0000 (12:31 +0000)]
Control strictness towards incoming lsp messages
A new variable, eglot-strict-mode controls whether Eglot is strict or
lax with regard to incoming LSP messages.
1. Bug reports should be tested with eglot-strict-mode set to
'(disallow-non-standard-keys enforce-required-keys)
2. Users struggling to get non-standard servers working set this
variable to '(), nil. For now, by popular demand, this is the
default value.
Note that this commit in particular introduces a new infrastructure,
but does not yet alter any code in Eglot to use it. Neither is the
variable eglot--lsp-interface-alist populated.
* eglot-tests.el (eglot-strict-interfaces): New test.
* eglot.el (eglot--lsp-interface-alist): New variable.
(eglot-strict-mode): New variable.
(eglot--call-with-interface): New helper.
(eglot--dbind): New macro.
(eglot--lambda): New macro.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/144
GitHub-reference: per https://github.com/joaotavora/eglot/issues/156
João Távora [Mon, 19 Nov 2018 23:16:33 +0000 (23:16 +0000)]
Fix potential security issue fontifying lsp doc
Previously, a server could mistankely or maliciously call *-mode
functions by in the response to a completion or hover request,
specifically in the :documentation field of the response.
Although there are plenty of similar avenues of attack in Emacs, it's
probably a good idea not to let LSP servers decide which functions to
call in an Emacs session running Eglot.
* eglot.el (eglot--format-markup): Call major-mode to fontify
buffer, not some dynamically constructed function name.
(eglot-completion-at-point): Ensure eglot--format-markup runs in
source buffer.
* eglot.el (eglot--pos-to-lsp-position): Call
eglot-current-column-function with tab-width bound to 1.
(eglot--lsp-position-to-point): Call eglot-move-to-column-function
with tab-width bound to 1.
João Távora [Tue, 13 Nov 2018 22:08:16 +0000 (22:08 +0000)]
Add ability to report lsp-compliant columns
* eglot.el (eglot-current-column-function): New variable.
(eglot-lsp-abiding-column): New helper.
(eglot--pos-to-lsp-position): Use eglot-current-column-function.
(eglot-move-to-column-function): Tweak docstring.
João Távora [Mon, 12 Nov 2018 22:29:38 +0000 (22:29 +0000)]
Add ability to move to lsp-precise columns
Also close https://github.com/joaotavora/eglot/issues/125.
Idea and much of design contributed by Michał Krzywkowski
<k.michal@zoho.com>
This introduces the variable eglot-move-to-column-function.
According to the standard, LSP column/character offsets are based
on a count of UTF-16 code units, not actual visual columns. So
when LSP says position 3 of a line containing just \"aXbc\",
where X is a multi-byte character, it actually means `b', not
`c'. This is what the function
`eglot-move-to-lsp-abiding-column' does.
However, many servers don't follow the spec this closely, and
thus this variable should be set to `move-to-column' in buffers
managed by those servers.
* eglot.el (eglot-move-to-column-function): New variable.
(eglot-move-to-lsp-abiding-column): New function.
(eglot--lsp-position-to-point): Use eglot-move-to-column-function.
* eglot.el (eglot-server-programs): Mention that the function must
accept one argument.
(eglot--guess-contact): Pass to functional contacts the interactive
value.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/63
* eglot.el (eglot--sig-info): Don't lose existing information.
Attempt to highlight the active parameter by searching for it's
:label in signature's :label. Append to the result first sentence
of signature's :documentation, if present.
João Távora [Fri, 10 Aug 2018 01:29:26 +0000 (02:29 +0100)]
Support snippet completions
* eglot.el (eglot-client-capabilities): Declare support for
snippet-based completions.
(eglot-completion-at-point): Expand snippet completions with
YASnippet if that is found.
(eglot-note, eglot-warning, eglot-error): Diagnostic
overlay priorities have to be slightly lower than yasnippet's,
which must be reasonably high.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/50
João Távora [Mon, 13 Aug 2018 00:45:40 +0000 (01:45 +0100)]
Handle edits to same position in the correct order
In eglot--apply-text-edits, the markers returned by
eglot--lsp-position-to-point are of the "stay" type, i.e. have an
insertion-type of nil. This causes multiple insertion edits to the
same location to happen in the reverse order in which they appear in
the LSP message, which is a violation of the spec and a bug.
There are more ways to solve this (see related discuttion in
https://github.com/joaotavora/eglot/pull/64), but the easiest way is
to revert the order in which the edits are processed. This is because
the spec tells us that the order is only relevant in precisely this
"same position" case. So if we reverse the order we fix this bug and
don't break anything else.
* eglot.el (eglot--apply-text-edits): Apply edits in reverse..
GitHub-reference: close https://github.com/joaotavora/eglot/issues/64
João Távora [Sat, 11 Aug 2018 13:52:33 +0000 (14:52 +0100)]
Implement asynchronous server connection
A new defcustom eglot-sync-connect controls this feature. If it is t,
eglot should behave like previously, waiting synchronously for a
connection to be established, with the exception that there is now a
non-nil timeout set to eglot-connect-timeout, which defaults to 30
seconds.
eglot-connect is now considerably more complicated as it replicates
most of the work that jsonrpc-request does vis-a-vis handling errors,
timeouts and user quits..
Kill server's output and events buffers from eglot-shutdown ()
* eglot.el
(Package-Requires): Require jsonrpc 1.0.5
(eglot-shutdown): Kill events and stderr buffers of the
server, unless new PRESERVE-BUFFERS argument is non-nil.
eglot-reconnect): Preserve buffers on shutdown.
* eglot-tests.el (eglot--call-with-dirs-and-files): Call
eglot-shutdown with non-nil PRESERVE-BUFFERS arg.
João Távora [Mon, 6 Aug 2018 16:53:09 +0000 (17:53 +0100)]
Accept functions as entries in eglot-server-programs
CONTACT in the (MAJOR-MODE . CONTACT) association in
eglot-server-programs can now be a function of no arguments producing
any value previously valid for contact. The function is called at
time of `M-x eglot` or `eglot-ensure`. This is useful for servers
requiring command-line invocations that depend on the specific
momentary environment.
* eglot.el (eglot-server-programs): CONTACT can be a fucntion of no
arguments.
(eglot--guess-contact, eglot--connect): Accept function
CONTACTs.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/63
Fix placement of diagnostics with same start and end positions
Some servers such as cquery and clangd publish diagnostic with
identical start and end positions.
* eglot.el (eglot-handle-notification
:textDocument/publishDiagnostics): Add 1 to :line since LSP lines
are 0-based. Don't subtract 1 from :character, since both emacs and
LSP have 0-based columns.
* eglot.el (eglot-format): New command.
(eglot-format-buffer): Use it as implementation.
(eglot-client-capabilities): Add :rangeFormatting.
* eglot-tests.el (formatting): Also test range formatting.
* README.md (Commands and keybindings): Mention eglot-format.
(Language features): Tick textDocument/rangeFormatting.
João Távora [Sun, 22 Jul 2018 18:07:43 +0000 (19:07 +0100)]
Don't turn on flymake-mode any more than is needed
If flymake-mode is in eglot--managed-mode-hook, it will be called even
if eglot--managed-mode is being turned off, which could be problematic
because it triggers a check if flymake-start-on-flymake-mode is t.
* eglot.el (eglot--managed-mode): Turn on flymake-mode and
eldoc-mode here.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/44
João Távora [Fri, 20 Jul 2018 16:45:47 +0000 (17:45 +0100)]
Robustify in the face of manual mode changes
When manually changing the major-mode of a managed buffer, this sends
a didClose and tears down Eglot-related stuff like if were killing the
buffer. After changing the mode, we have to recheck that we are now
not managed by another server (or by the same server, in case we
changed the mode to be the same mode).
* eglot.el (eglot-shutdown): Use eglot--with-live-buffer
(eglot--on-shutdown): Use eglot--with-live-buffer
(eglot--managed-mode): Use change-major-mode-hook.
(eglot--managed-mode-onoff): Change protocol. Turn off when called
with no arguments.
(eglot--maybe-activate-editing-mode): Don't do anything if mode is
already active. Suitable for calling from
after-change-major-mode-hook.
(after-change-major-mode-hook): Add
eglot--maybe-activate-editing-mode.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/44
João Távora [Wed, 11 Jul 2018 23:30:32 +0000 (00:30 +0100)]
Implement workspace/didchangeconfiguration ()
* README.md (Supported Protocol Features, Commands and
keybindings): mention workspace/didChangeConfiguration.
* eglot.el (eglot-server-initialized-hook): New hook.
(eglot--connect): Run it.
(eglot-workspace-configuration): New variable.
(eglot-signal-didChangeConfiguration): New command.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/29
GitHub-reference: close https://github.com/joaotavora/eglot/issues/40
Fixes an issue with the latest RLS, where the server returns a plist
instead of a plain string as documentation for completion candidates,
which broke the `annotation-function`. This change was introduced by
https://github.com/rust-lang-nursery/rls/commit/206a9fb41e837333d0e67187a6a9fe24868b77a4
Copyright-paperwork-exempt: yes
* eglot.el (eglot-completion-at-point): Use eglot--format-markup
João Távora [Mon, 25 Jun 2018 16:37:43 +0000 (17:37 +0100)]
Cache buffer's managing server
* eglot.el (eglot--cached-current-server): New variable.
(eglot--managed-mode-onoff): Set it.
(eglot--current-server): Read it.
(eglot--maybe-activate-editing-mode): Add assertion.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/32