[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot e28b396 25/69: Fix #259: work around a bug in Ema
From: |
João Távora |
Subject: |
[elpa] externals/eglot e28b396 25/69: Fix #259: work around a bug in Emacs's change detection |
Date: |
Sun, 20 Oct 2019 08:21:46 -0400 (EDT) |
branch: externals/eglot
commit e28b396a320e17a44a6d09bb870da1355b9f7310
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Fix #259: work around a bug in Emacs's change detection
When using capitalize-word, or any case-fiddling function,
before-change-functions will record e.g. the whole word's start and
end, even though only the first character has changed. Not only is
this longer than needed but also conflicts with what we get in
after-change-functions, which records just the one-char-long change.
Also, if the word didn't need any fiddling at all then
before-change-function will run but after-change-functions won't: an
"orphan" before-change will erroneously be sent to the server.
* eglot.el (eglot--after-change): Detect problematic case and fix
change description.
(eglot--before-change): Store markers of changed region.
(eglot--signal-textDocument/didChange): Weed out orphan changes.
---
eglot.el | 52 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 37 insertions(+), 15 deletions(-)
diff --git a/eglot.el b/eglot.el
index b9fc25c..0c2f4e9 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1530,26 +1530,42 @@ THINGS are either registrations or unregisterations
(sic)."
(defvar-local eglot--change-idle-timer nil "Idle timer for didChange signals.")
-(defun eglot--before-change (start end)
- "Hook onto `before-change-functions' with START and END."
- ;; Records START and END, crucially convert them into LSP
- ;; (line/char) positions before that information is lost (because
- ;; the after-change thingy doesn't know if newlines were
- ;; deleted/added)
+(defun eglot--before-change (beg end)
+ "Hook onto `before-change-functions' with BEG and END."
(when (listp eglot--recent-changes)
- (push `(,(eglot--pos-to-lsp-position start)
- ,(eglot--pos-to-lsp-position end))
+ ;; Records BEG and END, crucially convert them into LSP
+ ;; (line/char) positions before that information is lost (because
+ ;; the after-change thingy doesn't know if newlines were
+ ;; deleted/added). Also record markers of BEG and END
+ ;; (github#259)
+ (push `(,(eglot--pos-to-lsp-position beg)
+ ,(eglot--pos-to-lsp-position end)
+ (,beg . ,(copy-marker beg))
+ (,end . ,(copy-marker end)))
eglot--recent-changes)))
-(defun eglot--after-change (start end pre-change-length)
+(defun eglot--after-change (beg end pre-change-length)
"Hook onto `after-change-functions'.
-Records START, END and PRE-CHANGE-LENGTH locally."
+Records BEG, END and PRE-CHANGE-LENGTH locally."
(cl-incf eglot--versioned-identifier)
- (if (and (listp eglot--recent-changes)
- (null (cddr (car eglot--recent-changes))))
- (setf (cddr (car eglot--recent-changes))
- `(,pre-change-length ,(buffer-substring-no-properties start end)))
- (setf eglot--recent-changes :emacs-messup))
+ (pcase (and (listp eglot--recent-changes)
+ (car eglot--recent-changes))
+ (`(,lsp-beg ,lsp-end
+ (,b-beg . ,b-beg-marker)
+ (,b-end . ,b-end-marker))
+ ;; github#259: With `upcase-word' or somesuch,
+ ;; `before-change-functions' always records the whole word's
+ ;; `beg' and `end'. Not only is this longer than needed but
+ ;; conflicts with the args received here. Detect this using
+ ;; markers recorded earlier and `pre-change-len', then fix it.
+ (when (and (= b-end b-end-marker) (= b-beg b-beg-marker)
+ (not (zerop pre-change-length)))
+ (setq lsp-end (eglot--pos-to-lsp-position end)
+ lsp-beg (eglot--pos-to-lsp-position beg)))
+ (setcar eglot--recent-changes
+ `(,lsp-beg ,lsp-end ,pre-change-length
+ ,(buffer-substring-no-properties beg end))))
+ (_ (setf eglot--recent-changes :emacs-messup)))
(when eglot--change-idle-timer (cancel-timer eglot--change-idle-timer))
(let ((buf (current-buffer)))
(setq eglot--change-idle-timer
@@ -1609,6 +1625,12 @@ When called interactively, use the currently active
server"
(buffer-substring-no-properties (point-min)
(point-max)))))
(cl-loop for (beg end len text) in (reverse eglot--recent-changes)
+ ;; github#259: `capitalize-word' and commands based
+ ;; on `casify_region' will cause multiple duplicate
+ ;; empty entries in `eglot--before-change' calls
+ ;; without an `eglot--after-change' reciprocal.
+ ;; Weed them out here.
+ when (numberp len)
vconcat `[,(list :range `(:start ,beg :end ,end)
:rangeLength len :text text)]))))
(setq eglot--recent-changes nil)
- [elpa] externals/eglot d65d139 15/69: Don't teardown company if started via trigger chars, (continued)
- [elpa] externals/eglot d65d139 15/69: Don't teardown company if started via trigger chars, João Távora, 2019/10/20
- [elpa] externals/eglot 7d6e3cf 21/69: Per #220: unbreak build, João Távora, 2019/10/20
- [elpa] externals/eglot b868ee1 23/69: Fix #260: Only consider Eglot's own diagnostics in eglot-code-actions, João Távora, 2019/10/20
- [elpa] externals/eglot 5f629eb 26/69: Add built-in support for Elixir's elixir-ls (#264), João Távora, 2019/10/20
- [elpa] externals/eglot 356100a 19/69: Fix #220: don't sort xref's by default, João Távora, 2019/10/20
- [elpa] externals/eglot 195c311 22/69: Fix local function call in directory watcher (#255), João Távora, 2019/10/20
- [elpa] externals/eglot 2df3991 13/69: Fix #206: Update README.md, João Távora, 2019/10/20
- [elpa] externals/eglot 8d0c8de 05/69: Add NEWS.md file and rework README.md, João Távora, 2019/10/20
- [elpa] externals/eglot b4f3028 18/69: Fix #223: use a less buggy Flymake, João Távora, 2019/10/20
- [elpa] externals/eglot 6c884c4 24/69: Fix #263: fix case when eglot-put-doc-in-help-buffer is nil, João Távora, 2019/10/20
- [elpa] externals/eglot e28b396 25/69: Fix #259: work around a bug in Emacs's change detection,
João Távora <=
- [elpa] externals/eglot 2372bc8 30/69: Fixed extra ) in python example snippet (#287), João Távora, 2019/10/20
- [elpa] externals/eglot 6d87de1 35/69: Treat null/nil server capabilities as false, João Távora, 2019/10/20
- [elpa] externals/eglot 7f31f29 36/69: Use gopls server as the default for Go (#304), João Távora, 2019/10/20
- [elpa] externals/eglot 4548202 28/69: Simplify eldoc usage (#269), João Távora, 2019/10/20
- [elpa] externals/eglot 36b7cf32 38/69: Fix #272: also use signature label offsets for parameter info, João Távora, 2019/10/20
- [elpa] externals/eglot 059ea59 43/69: Optionally shutdown after killing last buffer of managed project (#309), João Távora, 2019/10/20
- [elpa] externals/eglot 59ba0b1 39/69: New README section on how to best report bugs to Eglot, João Távora, 2019/10/20
- [elpa] externals/eglot ce983d1 47/69: Revert "Treat null/nil server capabilities as false", João Távora, 2019/10/20
- [elpa] externals/eglot 4693abf 50/69: Fix #258: Allow user to set idle time to wait before processing changes, João Távora, 2019/10/20
- [elpa] externals/eglot 14ab804 54/69: Fix #318: unbreak xref-find-definitions, João Távora, 2019/10/20