Eglot: add support for insertReplaceEdit (bug#73857)
* lisp/progmodes/eglot.el (eglot-server-programs): Mention zig-ts-mode. (eglot--lsp-interface-alist): Describe 'InsertReplaceEdit'. (eglot-client-capabilities): Advertise 'insertReplaceSupport'. (eglot-completion-at-point): Consider 'InsertReplaceEdit'. (eglot--apply-text-edits): Consider 'InsertReplaceEdit'. * test/lisp/progmodes/eglot-tests.el (eglot-test-zig-insert-replace-completion): New test. Special thanks to kcbanner@gmail.com
This commit is contained in:
parent
a1ce633ca9
commit
1143cf09a3
2 changed files with 39 additions and 12 deletions
|
@ -314,7 +314,7 @@ automatically)."
|
|||
((lua-mode lua-ts-mode) . ,(eglot-alternatives
|
||||
'("lua-language-server" "lua-lsp")))
|
||||
(yang-mode . ("yang-language-server"))
|
||||
(zig-mode . ("zls"))
|
||||
((zig-mode zig-ts-mode) . ("zls"))
|
||||
((css-mode css-ts-mode)
|
||||
. ,(eglot-alternatives '(("vscode-css-language-server" "--stdio")
|
||||
("css-languageserver" "--stdio"))))
|
||||
|
@ -658,6 +658,7 @@ This can be useful when using docker to run a language server.")
|
|||
(:detail :deprecated :children))
|
||||
(TextDocumentEdit (:textDocument :edits) ())
|
||||
(TextEdit (:range :newText))
|
||||
(InsertReplaceEdit (:newText :insert :replace))
|
||||
(VersionedTextDocumentIdentifier (:uri :version) ())
|
||||
(WorkDoneProgress (:kind) (:title :message :percentage :cancellable))
|
||||
(WorkspaceEdit () (:changes :documentChanges))
|
||||
|
@ -970,7 +971,8 @@ object."
|
|||
["documentation"
|
||||
"details"
|
||||
"additionalTextEdits"])
|
||||
:tagSupport (:valueSet [1]))
|
||||
:tagSupport (:valueSet [1])
|
||||
:insertReplaceSupport t)
|
||||
:contextSupport t)
|
||||
:hover (list :dynamicRegistration :json-false
|
||||
:contentFormat (eglot--accepted-formats))
|
||||
|
@ -3367,8 +3369,15 @@ for which LSP on-type-formatting should be requested."
|
|||
;; insertion to potentially cancel an essential
|
||||
;; resolution request (github#1474).
|
||||
'dont-cancel-on-input)
|
||||
(let ((snippet-fn (and (eql insertTextFormat 2)
|
||||
(eglot--snippet-expansion-fn))))
|
||||
(let* ((snippet-fn (and (eql insertTextFormat 2)
|
||||
(eglot--snippet-expansion-fn)))
|
||||
(apply-edit
|
||||
(lambda (range text)
|
||||
(pcase-let ((`(,beg . ,end)
|
||||
(eglot-range-region range)))
|
||||
(delete-region beg end)
|
||||
(goto-char beg)
|
||||
(funcall (or snippet-fn #'insert) text)))))
|
||||
(cond (textEdit
|
||||
;; Revert buffer back to state when the edit
|
||||
;; was obtained from server. If a `proxy'
|
||||
|
@ -3377,12 +3386,11 @@ for which LSP on-type-formatting should be requested."
|
|||
;; state, _not_ the current "foo.bar".
|
||||
(delete-region orig-pos (point))
|
||||
(insert (substring bounds-string (- orig-pos (car bounds))))
|
||||
(eglot--dbind ((TextEdit) range newText) textEdit
|
||||
(pcase-let ((`(,beg . ,end)
|
||||
(eglot-range-region range)))
|
||||
(delete-region beg end)
|
||||
(goto-char beg)
|
||||
(funcall (or snippet-fn #'insert) newText))))
|
||||
(eglot--dcase textEdit
|
||||
(((TextEdit) range newText)
|
||||
(funcall apply-edit range newText))
|
||||
(((InsertReplaceEdit) newText replace)
|
||||
(funcall apply-edit replace newText))))
|
||||
(snippet-fn
|
||||
;; A snippet should be inserted, but using plain
|
||||
;; `insertText'. This requires us to delete the
|
||||
|
@ -3611,8 +3619,12 @@ If SILENT, don't echo progress in mode-line."
|
|||
(replace-buffer-contents temp)))
|
||||
(when reporter
|
||||
(eglot--reporter-update reporter (cl-incf done))))))))
|
||||
(mapcar (eglot--lambda ((TextEdit) range newText)
|
||||
(cons newText (eglot-range-region range 'markers)))
|
||||
(mapcar (lambda (edit)
|
||||
(eglot--dcase edit
|
||||
(((TextEdit) range newText)
|
||||
(cons newText (eglot-range-region range 'markers)))
|
||||
(((InsertReplaceEdit) newText replace)
|
||||
(cons newText (eglot-range-region replace 'markers)))))
|
||||
(reverse edits)))
|
||||
(undo-amalgamate-change-group change-group)
|
||||
(when reporter
|
||||
|
|
|
@ -725,6 +725,21 @@ directory hierarchy."
|
|||
"fn test() -> i32 { let v: usize = 1; v.count_ones.1234567890;")
|
||||
(buffer-string))))))
|
||||
|
||||
(ert-deftest eglot-test-zig-insert-replace-completion ()
|
||||
"Test zls's use of 'InsertReplaceEdit'."
|
||||
(skip-unless (functionp 'zig-ts-mode))
|
||||
(eglot--with-fixture
|
||||
`(("project" .
|
||||
(("main.zig" .
|
||||
,(concat "const Foo = struct {correct_name: u32,\n};\n"
|
||||
"fn example(foo: Foo) u32 {return foo.correc_name; }")))))
|
||||
(with-current-buffer
|
||||
(eglot--find-file-noselect "project/main.zig")
|
||||
(should (eglot--tests-connect))
|
||||
(search-forward "foo.correc")
|
||||
(completion-at-point)
|
||||
(should (looking-back "correct_name")))))
|
||||
|
||||
(ert-deftest eglot-test-basic-xref ()
|
||||
"Test basic xref functionality in a clangd LSP."
|
||||
(skip-unless (executable-find "clangd"))
|
||||
|
|
Loading…
Add table
Reference in a new issue