Replies: 2 comments
-
As far as I know, Eglot does not send any resourceOperations among its client capabilities, so it is a mistake from the server to send a rename workspace edit (e.g.: |
Beta Was this translation helpful? Give feedback.
0 replies
-
This is indeed because eglot doesn't support file rename yet. I've hit the same issue on clojure-lsp, and the below patch resolves it for me. Let me know if it helps @adonovan diff -u /var/folders/wk/_mbcwk1x7gn6bxqx97__h2c80000gp/T/buffer-content-gGFDOp /var/folders/wk/_mbcwk1x7gn6bxqx97__h2c80000gp/T/buffer-content-RYgFdZ
--- /var/folders/wk/_mbcwk1x7gn6bxqx97__h2c80000gp/T/buffer-content-gGFDOp 2024-12-27 13:35:01
+++ /var/folders/wk/_mbcwk1x7gn6bxqx97__h2c80000gp/T/buffer-content-RYgFdZ 2024-12-27 13:35:01
@@ -635,7 +635,9 @@
(ParameterInformation (:label) (:documentation))
(Position (:line :character))
(Range (:start :end))
+ (RenameFile (:oldUri) (:newUri) nil)
(Registration (:id :method) (:registerOptions))
+ (ResourceOperation (:kind))
(ResponseError (:code :message) (:data))
(ShowMessageParams (:type :message))
(ShowMessageRequestParams (:type :message) (:actions))
@@ -3662,36 +3664,56 @@
ORIGIN is a symbol designating the command that originated this
edit proposed by the server."
(eglot--dbind ((WorkspaceEdit) changes documentChanges) wedit
- (let ((prepared
- (mapcar (eglot--lambda ((TextDocumentEdit) textDocument edits)
- (eglot--dbind ((VersionedTextDocumentIdentifier) uri version)
- textDocument
- (list (eglot-uri-to-path uri) edits version)))
- documentChanges)))
- (unless (and changes documentChanges)
- ;; We don't want double edits, and some servers send both
- ;; changes and documentChanges. This unless ensures that we
- ;; prefer documentChanges over changes.
+ (let ((prepared-text-edits '())
+ (prepared-resource-ops '()))
+ ;; Handle documentChanges for file rename
+ (when (and documentChanges
+ (vectorp documentChanges)
+ (= (length documentChanges) 1)
+ (string= (plist-get (aref documentChanges 0) :kind) "rename"))
+ (let* ((rename-op (aref documentChanges 0))
+ (old-path (eglot-uri-to-path (plist-get rename-op :oldUri)))
+ (new-path (eglot-uri-to-path (plist-get rename-op :newUri))))
+ (push (list 'rename old-path new-path) prepared-resource-ops)))
+
+ ;; Handle changes for symbol updates
+ (when changes
(cl-loop for (uri edits) on changes by #'cddr
- do (push (list (eglot-uri-to-path uri) edits) prepared)))
+ do (push (list (eglot-uri-to-path uri) edits)
+ prepared-text-edits)))
+
(cl-flet ((notevery-visited-p ()
(cl-notevery #'find-buffer-visiting
- (mapcar #'car prepared)))
+ (mapcar #'car prepared-text-edits)))
(accept-p ()
(y-or-n-p
- (format "[eglot] Server wants to edit:\n%sProceed? "
- (cl-loop
- for (f eds _) in prepared
- concat (format
- " %s (%d change%s)\n"
- f (length eds)
- (if (> (length eds) 1) "s" ""))))))
+ (format "[eglot] Server wants to make the following changes:\n%s%sProceed? "
+ (cl-loop for (f eds) in prepared-text-edits
+ concat (format " %s (%d text change%s)\n"
+ f (length eds)
+ (if (> (length eds) 1) "s" "")))
+ (cl-loop for (op old new) in prepared-resource-ops
+ concat (format " %s: %s -> %s\n"
+ op old new)))))
(apply ()
- (cl-loop for edit in prepared
- for (path edits version) = edit
- do (with-current-buffer (find-file-noselect path)
- (eglot--apply-text-edits edits version))
- finally (eldoc) (eglot--message "Edit successful!"))))
- (let ((decision (eglot--confirm-server-edits origin prepared)))
+ ;; First apply text edits
+ (dolist (edit prepared-text-edits)
+ (let ((path (car edit))
+ (edits (cadr edit)))
+ (with-current-buffer (find-file-noselect path)
+ (eglot--apply-text-edits edits nil))))
+ ;; Then apply resource operations
+ (dolist (op prepared-resource-ops)
+ (pcase op
+ (`(rename ,old-path ,new-path)
+ (let ((buf (find-buffer-visiting old-path)))
+ (when buf
+ (with-current-buffer buf
+ (set-visited-file-name new-path)
+ (save-buffer)))
+ (rename-file old-path new-path t)))))
+ (eldoc)
+ (eglot--message "Edit successful!")))
+ (let ((decision (eglot--confirm-server-edits origin prepared-text-edits)))
(cond
((or (eq decision 'diff)
(and (eq decision 'maybe-diff) (notevery-visited-p)))
- (eglot--propose-changes-as-diff prepared))
+ (eglot--propose-changes-as-diff prepared-text-edits))
((or (memq decision '(t summary))
(and (eq decision 'maybe-summary) (notevery-visited-p)))
(when (accept-p) (apply)))
@@ -3712,11 +3734,28 @@
nil nil nil nil
(symbol-name (symbol-at-point)))))
(eglot-server-capable-or-lose :renameProvider)
- (eglot--apply-workspace-edit
- (eglot--request (eglot--current-server-or-lose)
- :textDocument/rename `(,@(eglot--TextDocumentPositionParams)
- :newName ,newname))
- this-command))
+ (let* ((old-name (symbol-name (symbol-at-point)))
+ (locations (eglot--request (eglot--current-server-or-lose)
+ :textDocument/references
+ `(:context (:includeDeclaration t)
+ ,@(eglot--TextDocumentPositionParams))))
+ (changes nil)
+ (rename-response (eglot--request (eglot--current-server-or-lose)
+ :textDocument/rename
+ `(,@(eglot--TextDocumentPositionParams)
+ :newName ,newname))))
+ ;; Process references for symbol updates
+ (dotimes (i (length locations))
+ (let* ((loc (aref locations i))
+ (uri (plist-get loc :uri))
+ (range (plist-get loc :range)))
+ (push `(:range ,range :newText ,newname) (plist-get changes uri))
+ (setq changes (plist-put changes uri (plist-get changes uri)))))
+ ;; Apply both the file rename and symbol updates
+ (eglot--apply-workspace-edit
+ `(:documentChanges ,(plist-get rename-response :documentChanges)
+ :changes ,changes)
+ this-command)))
(defun eglot--code-action-bounds ()
"Calculate appropriate bounds depending on region and point." |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
In Go's LSP server, an
eglot-rename
operation on a package name causes the server to respond with a directory rename. In other words, the workspace-edit's document-change's old and new URIs both refer to directories. This causes eglot--apply-workspace-edit to fail.Beta Was this translation helpful? Give feedback.
All reactions