-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix more bugs in eglot--apply-text-edits #64
Conversation
OK I finally understand the problem. By the way a simpler way to reproduce (tried installing Eclipse but failed miserably) is to dogfood Erase your
Now, I think the current implementation is confusing. There are three alternatives:
|
BTW I'm on the fence between 2 and 3, because 3 is the easiest. But FTR here's an implementation of 2. diff --git a/eglot.el b/eglot.el
index d29bef5..7e34113 100644
--- a/eglot.el
+++ b/eglot.el
@@ -608,16 +608,15 @@ CONNECT-ARGS are passed as additional arguments to
:character (- (goto-char (or pos (point)))
(line-beginning-position)))))
-(defun eglot--lsp-position-to-point (pos-plist &optional marker)
- "Convert LSP position POS-PLIST to Emacs point.
-If optional MARKER, return a marker instead"
+(defun eglot--lsp-position-to-point (pos-plist)
+ "Convert LSP position POS-PLIST to Emacs point."
(save-excursion (goto-char (point-min))
(forward-line (min most-positive-fixnum
(plist-get pos-plist :line)))
(forward-char (min (plist-get pos-plist :character)
(- (line-end-position)
(line-beginning-position))))
- (if marker (copy-marker (point-marker)) (point))))
+ (point)))
(defun eglot--path-to-uri (path)
"URIfy PATH."
@@ -673,9 +672,14 @@ under cursor."
(defun eglot--range-region (range &optional markers)
"Return region (BEG . END) that represents LSP RANGE.
If optional MARKERS, make markers."
- (let* ((st (plist-get range :start))
- (beg (eglot--lsp-position-to-point st markers))
- (end (eglot--lsp-position-to-point (plist-get range :end) markers)))
+ (let* ((beg (set-marker (make-marker)
+ (eglot--lsp-position-to-point
+ (plist-get range :start))))
+ (end (set-marker (make-marker)
+ (eglot--lsp-position-to-point
+ (plist-get range :end)))))
+ (set-marker-insertion-type beg t)
+ (if (= beg end) (setq end beg))
(cons beg end)))
@@ -1477,7 +1481,9 @@ If SKIP-SIGNATURE, don't try to send textDocument/signatureHelp."
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32237
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32278
(let ((inhibit-modification-hooks t)
- (length (- end beg)))
+ (length (- end beg))
+ (beg (marker-position beg))
+ (end (marker-position end)))
(run-hook-with-args 'before-change-functions
beg end)
(replace-buffer-contents temp) |
I chose this option, is it OK? |
* eglot.el (eglot--apply-text-edits): Pass to change hooks only marker positions, not the markers themselves. Apply the edits in reverse order to ensure that inserted text appears in the same order as the edits.
Yeah, I was going to choose that too. Give it bit of testing if you can though. |
Alright, I tested it a bit and so far I haven't seen any problems. |
Good, then go ahead and do the change. |
I already did. I see you already committed, but one more thing that is missing is calling change functions with marker positions instead of markers. I remember them signaling errors if the arguments are not integers, but I can't really reproduce it. |
Sorry, I missed your commit somehow.
They shouldn't signal errors just because the are passed markers. But indeed, if you make the markers push, then you must pass positions otherwise the arguments you pass to the before and after change functions aren't the ones that are supposed to. |
…ct 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 joaotavora/eglot#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..
…ct 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 joaotavora/eglot#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..
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 joaotavora/eglot#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.. #64: joaotavora/eglot#64
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 joaotavora/eglot#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 joaotavora/eglot#64
This fixes bugs which I found when using the eclipse.jdt.ls server. If there are multiple insertions in the same place, the inserted text must be in the same order as the TextEdit[] array itself. https://microsoft.github.io/language-server-protocol/specification#textedit-1
To reproduce it, simply run the eclipse.jdt.ls server without this fix and try some code actions.