João Távora [Thu, 6 Dec 2018 18:26:17 +0000 (18:26 +0000)]
Warn about suspicious interface usage at compile-time
For fun, set eglot-strict-mode to '(disallow-non-standard-keys
enforce-required-keys enforce-optional-keys) when compiling, or just
use flymake-mode in eglot.el.
* eglot.el (eglot--lsp-interface-alist): Use in compile-time.
Order alphabetically. Fix a few bugs.
(eglot-strict-mode): Disallow non-standard-keys when compiling.
Update docstring.
(eglot--keywordize-vars, eglot--check-interface): New
compile-time-helpers.
(eglot--dbind, eglot--dcase): Use new helpers.
João Távora [Mon, 3 Dec 2018 12:24:26 +0000 (12:24 +0000)]
Robustify previous fix against non-standard insertion bindings
* eglot.el (eglot--managed-mode): Manage post-self-insert-hook.
(eglot--last-inserted-char): New variable.
(eglot--post-self-insert-hook): Set it.
(eglot--before-change): Reset it.
(eglot--CompletionParams): Use it.
GitHub-reference: per https://github.com/joaotavora/eglot/issues/173
João Távora [Sun, 2 Dec 2018 10:54:09 +0000 (10:54 +0000)]
Support completioncontext to help servers like ccls
* eglot.el (eglot-client-capabilities): Annouce
textDocument/completion/contextSupport.
(eglot--CompletionParams): New helper.
(eglot-completion-at-point): Use it.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/173
João Távora [Sat, 1 Dec 2018 22:47:56 +0000 (22:47 +0000)]
Don't break in indirect buffers
Indirect buffers, such as the ones created by ediff-regions-wordwise,
have eglot enabled but not buffer-file-name. Resort to the finding
the file-name of the original buffer for these.
* eglot.el (eglot--TextDocumentIdentifier): Work in indirect
buffers.
* eglot.el (eglot--lsp-interface-alist): Add CodeAction,
FileSystemWatcher, Registration, TextDocumentEdit, WorkspaceEdit.
(eglot-handle-notification): Use eglot--dbind.
(eglot--apply-workspace-edit): Use eglot--dbind and eglot--lambda.
(eglot-code-actions): Use eglot--lambda.
(eglot--register-workspace/didChangeWatchedFiles): Use eglot--lambda.
João Távora [Wed, 28 Nov 2018 20:26:37 +0000 (20:26 +0000)]
Simplify interface of eglot--dbind macro
* eglot.el (eglot--dbind): Use new interface.
(eglot--lambda): Use new eglot--dbind interface.
(eglot--lsp-interface-alist): Fix docstring.
(eglot--call-with-interface): Simplify.
(eglot--plist-keys): New helper.
* eglot-tests.el (eglot-strict-interfaces):
Add a new test clause.
* eglot.el (eglot-current-column): Rename from eglot--current-column.
(eglot-current-column-function): Use it as value and mention in docstring.
(eglot--xref-make): Use eglot-current-column.
(eglot-current-column-function): Set to eglot--current-column.
(eglot--pos-to-lsp-position): Don't bind tab-width anymore.
(eglot--xref-make): Use eglot--current-column.
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.