[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot cef3c29 22/69: Heroically merge master into jsonr
From: |
João Távora |
Subject: |
[elpa] externals/eglot cef3c29 22/69: Heroically merge master into jsonrpc-refactor (using imerge) |
Date: |
Fri, 22 Jun 2018 11:54:57 -0400 (EDT) |
branch: externals/eglot
commit cef3c29a4a2bfbb87d3fa0518626a4e0fdcb95dc
Merge: bb60c0c 24877ae
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Heroically merge master into jsonrpc-refactor (using imerge)
---
.travis.yml | 4 +
eglot-tests.el | 93 +++++++++++++------
eglot.el | 286 ++++++++++++++++++++++++++++-----------------------------
jsonrpc.el | 67 +++++++-------
4 files changed, 242 insertions(+), 208 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 2f0db4c..9b0a6d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,6 +18,10 @@ install:
# Install RLS
- rustup update
- rustup component add rls-preview rust-analysis rust-src
+ # Install https://github.com/palantir/python-language-server
+ - virtualenv .
+ - . ./bin/activate
+ - pip install 'python-language-server[all]'
script:
- make check
diff --git a/eglot-tests.el b/eglot-tests.el
index 9359a78..a19f121 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -26,11 +26,12 @@
(require 'eglot)
(require 'cl-lib)
(require 'ert)
+(require 'edebug)
;; Helpers
(defmacro eglot--with-dirs-and-files (dirs &rest body)
- (declare (indent defun) (debug t))
+ (declare (indent 1) (debug t))
`(eglot--call-with-dirs-and-files
,dirs #'(lambda () ,@body)))
@@ -51,24 +52,24 @@
(defun eglot--call-with-dirs-and-files (dirs fn)
(let* ((default-directory (make-temp-file "eglot--fixture" t))
new-buffers new-processes)
- (with-temp-message ""
- (unwind-protect
- (let ((find-file-hook
- (cons (lambda () (push (current-buffer) new-buffers))
- find-file-hook))
- (eglot-connect-hook
- (lambda (proc) (push proc new-processes))))
- (mapc #'eglot--make-file-or-dirs dirs)
- (funcall fn))
- (eglot--message "Killing buffers %s, deleting %s, killing %s"
- (mapconcat #'buffer-name new-buffers ", ")
- default-directory
- new-processes)
- (delete-directory default-directory 'recursive)
- (let ((eglot-autoreconnect nil))
- (mapc #'eglot-shutdown
- (cl-remove-if-not #'process-live-p new-processes)))
- (mapc #'kill-buffer new-buffers)))))
+ (unwind-protect
+ (let ((find-file-hook
+ (cons (lambda () (push (current-buffer) new-buffers))
+ find-file-hook))
+ (eglot-connect-hook
+ (lambda (proc) (push proc new-processes))))
+ (mapc #'eglot--make-file-or-dirs dirs)
+ (funcall fn))
+ (eglot--message "Killing buffers %s, deleting %s, killing %s"
+ (mapconcat #'buffer-name new-buffers ", ")
+ default-directory
+ new-processes)
+ (let ((eglot-autoreconnect nil))
+ (mapc #'eglot-shutdown
+ (cl-remove-if-not #'process-live-p new-processes)))
+ (dolist (buf new-buffers) ;; have to save otherwise will get prompted
+ (with-current-buffer buf (save-buffer) (kill-buffer)))
+ (delete-directory default-directory 'recursive))))
(cl-defmacro eglot--with-test-timeout (timeout &body body)
(declare (indent 1) (debug t))
@@ -85,8 +86,9 @@
(catch tag
(setq timer
(run-with-timer timeout nil
- (lambda () ;; (throw tag timed-out)
- )))
+ (lambda ()
+ (unless edebug-active
+ (throw tag timed-out)))))
(funcall fn)))
(cancel-timer timer)
(when (eq retval timed-out)
@@ -109,12 +111,13 @@
(ert-deftest auto-detect-running-server ()
"Visit a file and M-x eglot, then visit a neighbour. "
+ (skip-unless (executable-find "rls"))
(let (proc)
- (eglot--with-test-timeout 2
- (eglot--with-dirs-and-files
- '(("project" . (("coiso.rs" . "bla")
- ("merdix.rs" . "bla")))
- ("anotherproject" . (("cena.rs" . "bla"))))
+ (eglot--with-dirs-and-files
+ '(("project" . (("coiso.rs" . "bla")
+ ("merdix.rs" . "bla")))
+ ("anotherproject" . (("cena.rs" . "bla"))))
+ (eglot--with-test-timeout 2
(with-current-buffer
(eglot--find-file-noselect "project/coiso.rs")
(setq proc
@@ -131,12 +134,13 @@
(ert-deftest auto-reconnect ()
"Start a server. Kill it. Watch it reconnect."
+ (skip-unless (executable-find "rls"))
(let (proc
(eglot-autoreconnect 1))
- (eglot--with-test-timeout 3
- (eglot--with-dirs-and-files
- '(("project" . (("coiso.rs" . "bla")
- ("merdix.rs" . "bla"))))
+ (eglot--with-dirs-and-files
+ '(("project" . (("coiso.rs" . "bla")
+ ("merdix.rs" . "bla"))))
+ (eglot--with-test-timeout 3
(with-current-buffer
(eglot--find-file-noselect "project/coiso.rs")
(setq proc
@@ -153,6 +157,35 @@
(while (process-live-p proc) (accept-process-output nil 0.5))
(should (not (jsonrpc-current-process))))))))
+(ert-deftest basic-completions ()
+ "Test basic autocompletion in a python LSP"
+ (skip-unless (executable-find "pyls"))
+ (eglot--with-dirs-and-files
+ '(("project" . (("something.py" . "import sys\nsys.exi"))))
+ (eglot--with-test-timeout 4
+ (with-current-buffer
+ (eglot--find-file-noselect "project/something.py")
+ (eglot 'python-mode `(transient . ,default-directory) '("pyls"))
+ (goto-char (point-max))
+ (completion-at-point)
+ (should (looking-back "sys.exit"))))))
+
+(ert-deftest hover-after-completions ()
+ "Test basic autocompletion in a python LSP"
+ (skip-unless (executable-find "pyls"))
+ (eglot--with-dirs-and-files
+ '(("project" . (("something.py" . "import sys\nsys.exi"))))
+ (eglot--with-test-timeout 4
+ (with-current-buffer
+ (eglot--find-file-noselect "project/something.py")
+ (eglot 'python-mode `(transient . ,default-directory) '("pyls"))
+ (goto-char (point-max))
+ (setq eldoc-last-message nil)
+ (completion-at-point)
+ (should (looking-back "sys.exit"))
+ (while (not eldoc-last-message) (accept-process-output nil 0.1))
+ (should (string-match "^exit" eldoc-last-message))))))
+
(provide 'eglot-tests)
;;; eglot-tests.el ends here
diff --git a/eglot.el b/eglot.el
index 907c98b..41e57b4 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2018 Free Software Foundation, Inc.
-;; Version: 0.3
+;; Version: 0.4
;; Author: João Távora <address@hidden>
;; Maintainer: João Távora <address@hidden>
;; URL: https://github.com/joaotavora/eglot
@@ -121,11 +121,10 @@ A list (ID WHAT DONE-P).")
"File system watches for the didChangeWatchedfiles thingy.")
(defun eglot--on-shutdown (proc)
+ "Called by jsonrpc.el when PROC is already dead."
;; Turn off `eglot--managed-mode' where appropriate.
- (dolist (buffer (buffer-list))
- (with-current-buffer buffer
- (when (eglot--buffer-managed-p proc)
- (eglot--managed-mode -1))))
+ (dolist (buffer (eglot--managed-buffers proc))
+ (with-current-buffer buffer (eglot--managed-mode-onoff proc -1)))
;; Kill any expensive watches
(maphash (lambda (_id watches)
(mapcar #'file-notify-rm-watch watches))
@@ -141,21 +140,24 @@ A list (ID WHAT DONE-P).")
((timerp (eglot--inhibit-autoreconnect proc))
(eglot--warn "Not auto-reconnecting, last one didn't last long."))))
-(defun eglot-shutdown (proc &optional interactive)
+(defun eglot-shutdown (proc &optional _interactive)
"Politely ask the server PROC to quit.
Forcefully quit it if it doesn't respond. Don't leave this
function with the server still running. INTERACTIVE is t if
called interactively."
(interactive (list (jsonrpc-current-process-or-lose) t))
- (when interactive (eglot--message "Asking %s politely to terminate" proc))
+ (eglot--message "Asking %s politely to terminate" proc)
(unwind-protect
(let ((jsonrpc-request-timeout 3))
(setf (eglot--moribund proc) t)
(jsonrpc-request proc :shutdown nil)
- ;; this one should always fail under normal conditions
+ ;; this one should always fail, hence ignore-errors
(ignore-errors (jsonrpc-request proc :exit nil)))
+ ;; Turn off `eglot--managed-mode' where appropriate.
+ (dolist (buffer (eglot--managed-buffers proc))
+ (with-current-buffer buffer (eglot--managed-mode-onoff proc -1)))
(when (process-live-p proc)
- (eglot--warn "Brutally deleting existing process %s" proc)
+ (eglot--warn "Brutally deleting non-compliant %s" proc)
(delete-process proc))))
(defun eglot--find-current-process ()
@@ -164,6 +166,9 @@ called interactively."
(cl-find major-mode (gethash probe eglot--processes-by-project)
:key #'eglot--major-mode)))
+(jsonrpc-define-process-var eglot--managed-buffers nil
+ "Buffers managed by the server.")
+
(defun eglot--project-short-name (project)
"Give PROJECT a short name."
(file-name-base (directory-file-name (car (project-roots project)))))
@@ -216,35 +221,30 @@ called interactively."
(symbol-name guessed-mode) nil (symbol-name guessed-mode) nil)))
(t guessed-mode)))
(project (or (project-current) `(transient . ,default-directory)))
- (guessed-command (cdr (assoc managed-mode eglot-server-programs)))
+ (guessed (cdr (assoc managed-mode eglot-server-programs)))
+ (program (and (listp guessed) (stringp (car guessed)) (car guessed)))
(base-prompt "[eglot] Enter program to execute (or <host>:<port>): ")
(prompt
(cond (current-prefix-arg base-prompt)
- ((null guessed-command)
- (concat (format "[eglot] Sorry, couldn't guess for `%s'!"
- managed-mode)
- "\n" base-prompt))
- ((and (listp guessed-command)
- (not (integerp (cadr guessed-command)))
- (not (executable-find (car guessed-command))))
+ ((null guessed)
+ (format "[eglot] Sorry, couldn't guess for `%s'\n%s!"
+ managed-mode base-prompt))
+ ((and program (not (executable-find program)))
(concat (format "[eglot] I guess you want to run `%s'"
- (combine-and-quote-strings guessed-command))
- (format ", but I can't find `%s' in PATH!"
- (car guessed-command))
+ (combine-and-quote-strings guessed))
+ (format ", but I can't find `%s' in PATH!" program)
"\n" base-prompt))))
(contact
- (cond ((not prompt) guessed-command)
- (t
- (let ((string (read-shell-command
- prompt
- (if (listp guessed-command)
- (combine-and-quote-strings
guessed-command))
- 'eglot-command-history)))
- (if (and string (string-match
- "^\\([^\s\t]+\\):\\([[:digit:]]+\\)$"
- (string-trim string)))
- (list (match-string 1 string) (match-string 2 string))
- (split-string-and-unquote string)))))))
+ (if prompt
+ (let ((s (read-shell-command
+ prompt
+ (if program (combine-and-quote-strings guessed))
+ 'eglot-command-history)))
+ (if (string-match "^\\([^\s\t]+\\):\\([[:digit:]]+\\)$"
+ (string-trim s))
+ (list (match-string 1 s) (string-to-number (match-string 2
s)))
+ (split-string-and-unquote s)))
+ guessed)))
(list managed-mode project contact t)))
;;;###autoload
@@ -341,7 +341,8 @@ Builds a function from METHOD, passes it PROC, ID and
PARAMS."
(jsonrpc-obj :processId (unless (eq (process-type proc)
'network)
(emacs-pid))
- :rootPath (car (project-roots project))
+ :rootPath (expand-file-name
+ (car (project-roots project)))
:rootUri (eglot--path-to-uri
(car (project-roots project)))
:initializationOptions []
@@ -383,29 +384,24 @@ Builds a function from METHOD, passes it PROC, ID and
PARAMS."
"Warning message with FORMAT and ARGS."
(apply #'eglot--message (concat "(warning) " format) args)
(let ((warning-minimum-level :error))
- (display-warning 'eglot
- (apply #'format format args)
- :warning)))
+ (display-warning 'eglot (apply #'format format args) :warning)))
(defun eglot--pos-to-lsp-position (&optional pos)
"Convert point POS to LSP position."
(save-excursion
- (jsonrpc-obj :line
- ;; F!@(#*&#$)CKING OFF-BY-ONE
- (1- (line-number-at-pos pos t))
- :character
- (- (goto-char (or pos (point)))
- (line-beginning-position)))))
-
-(defun eglot--lsp-position-to-point (pos-plist)
- "Convert LSP position POS-PLIST to Emacs point."
+ (jsonrpc-obj :line (1- (line-number-at-pos pos t)) ; F!@&#$CKING OFF-BY-ONE
+ :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"
(save-excursion (goto-char (point-min))
(forward-line (plist-get pos-plist :line))
- (forward-char
- (min (plist-get pos-plist :character)
- (- (line-end-position)
- (line-beginning-position))))
- (point)))
+ (forward-char (min (plist-get pos-plist :character)
+ (- (line-end-position)
+ (line-beginning-position))))
+ (if marker (copy-marker (point-marker)) (point))))
(defun eglot--path-to-uri (path)
"URIfy PATH."
@@ -428,29 +424,31 @@ Builds a function from METHOD, passes it PROC, ID and
PARAMS."
(defun eglot--format-markup (markup)
"Format MARKUP according to LSP's spec."
- (cond ((stringp markup)
- (with-temp-buffer
- (ignore-errors (funcall (intern "markdown-mode"))) ;escape bytecomp
- (font-lock-ensure)
- (insert markup)
- (string-trim (buffer-string))))
- (t
- (with-temp-buffer
- (ignore-errors (funcall (intern (concat
- (plist-get markup :language)
- "-mode" ))))
- (insert (plist-get markup :value))
- (font-lock-ensure)
- (buffer-string)))))
-
-(defun eglot--server-capable (feat)
- "Determine if current server is capable of FEAT."
- (plist-get (eglot--capabilities (jsonrpc-current-process-or-lose)) feat))
-
-(defun eglot--range-region (range)
- "Return region (BEG . END) that represents LSP RANGE."
- (cons (eglot--lsp-position-to-point (plist-get range :start))
- (eglot--lsp-position-to-point (plist-get range :end))))
+ (pcase-let ((`(,string ,mode)
+ (if (stringp markup) (list (string-trim markup)
+ (intern "markdown-mode"))
+ (list (plist-get markup :value)
+ (intern (concat (plist-get markup :language) "-mode"
))))))
+ (with-temp-buffer
+ (ignore-errors (funcall mode))
+ (insert string) (font-lock-ensure) (buffer-string))))
+
+(defun eglot--server-capable (&rest feats)
+ "Determine if current server is capable of FEATS."
+ (cl-loop for caps = (eglot--capabilities (jsonrpc-current-process-or-lose))
+ then (cadr probe)
+ for feat in feats
+ for probe = (plist-member caps feat)
+ if (not probe) do (cl-return nil)
+ if (eq (cadr probe) t) do (cl-return t)
+ if (eq (cadr probe) :json-false) do (cl-return nil)
+ finally (cl-return (or probe t))))
+
+(defun eglot--range-region (range &optional markers)
+ "Return region (BEG END) that represents LSP RANGE.
+If optional MARKERS, make markers."
+ (list (eglot--lsp-position-to-point (plist-get range :start) markers)
+ (eglot--lsp-position-to-point (plist-get range :end) markers)))
;;; Minor modes
@@ -490,20 +488,20 @@ Builds a function from METHOD, passes it PROC, ID and
PARAMS."
(remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
(remove-function (local 'eldoc-documentation-function)
#'eglot-eldoc-function)
- (remove-function (local imenu-create-index-function) #'eglot-imenu)
- (let ((proc (eglot--find-current-process)))
- (when (and (process-live-p proc) (y-or-n-p "[eglot] Kill server too? "))
- (eglot-shutdown proc t))))))
+ (remove-function (local imenu-create-index-function) #'eglot-imenu))))
+
+(defun eglot--managed-mode-onoff (proc arg)
+ "Proxy for function `eglot--managed-mode' with ARG and PROC."
+ (eglot--managed-mode arg)
+ (let ((buf (current-buffer)))
+ (if eglot--managed-mode
+ (cl-pushnew buf (eglot--managed-buffers proc))
+ (setf (eglot--managed-buffers proc)
+ (delq buf (eglot--managed-buffers proc))))))
(add-hook 'eglot--managed-mode-hook 'flymake-mode)
(add-hook 'eglot--managed-mode-hook 'eldoc-mode)
-(defun eglot--buffer-managed-p (&optional proc)
- "Tell if current buffer can be managed by PROC."
- (and buffer-file-name (let ((cur (eglot--find-current-process)))
- (or (and (null proc) cur)
- (and proc (eq proc cur))))))
-
(defvar-local eglot--current-flymake-report-fn nil
"Current flymake report function for this buffer")
@@ -512,11 +510,13 @@ Builds a function from METHOD, passes it PROC, ID and
PARAMS."
If PROC is supplied, do it only if BUFFER is managed by it. In
that case, also signal textDocument/didOpen."
;; Called even when revert-buffer-in-progress-p
- (when (eglot--buffer-managed-p proc)
- (eglot--managed-mode 1)
- (eglot--signal-textDocument/didOpen)
- (flymake-start)
- (funcall (or eglot--current-flymake-report-fn #'ignore) nil)))
+ (let* ((cur (and buffer-file-name (eglot--find-current-process)))
+ (proc (or (and (null proc) cur) (and proc (eq proc cur) cur))))
+ (when proc
+ (eglot--managed-mode-onoff proc 1)
+ (eglot--signal-textDocument/didOpen)
+ (flymake-start)
+ (funcall (or eglot--current-flymake-report-fn #'ignore) nil))))
(add-hook 'find-file-hook 'eglot--maybe-activate-editing-mode)
@@ -532,7 +532,8 @@ that case, also signal textDocument/didOpen."
(lambda (event)
(interactive "e")
(with-selected-window (posn-window (event-start event))
- (call-interactively what))))
+ (call-interactively what)
+ (force-mode-line-update t))))
(defun eglot--mode-line-props (thing face defs &optional prepend)
"Helper for function `eglot--mode-line-format'.
@@ -567,7 +568,7 @@ Uses THING, FACE, DEFS and PREPEND."
`("/" ,(eglot--mode-line-props
"error" 'compilation-mode-line-fail
'((mouse-1 eglot-events-buffer "go to events buffer")
- (mouse-3 eglot-clear-status "clear this status"))
+ (mouse-3 jrpc-clear-status "clear this status"))
(format "An error occured: %s\n" status))))
,@(when (and doing (not done-p))
`("/" ,(eglot--mode-line-props
@@ -577,9 +578,10 @@ Uses THING, FACE, DEFS and PREPEND."
'((mouse-1 eglot-events-buffer "go to events buffer")))))
,@(when (cl-plusp pending)
`("/" ,(eglot--mode-line-props
- (format "%d" pending) 'warning
+ (format "%d oustanding requests" pending) 'warning
'((mouse-1 eglot-events-buffer "go to events buffer")
- (mouse-3 eglot-clear-status "clear this status"))
+ (mouse-3 jrpc-forget-pending-continuations
+ "fahgettaboudit"))
(format "%d pending requests\n" pending)))))))))
(add-to-list 'mode-line-misc-info
@@ -625,7 +627,7 @@ Uses THING, FACE, DEFS and PREPEND."
"Unreported diagnostics for this buffer.")
(cl-defun eglot--server-textDocument/publishDiagnostics
- (_process &key uri diagnostics)
+ (_proc &key uri diagnostics)
"Handle notification publishDiagnostics"
(if-let ((buffer (find-buffer-visiting (eglot--uri-to-path uri))))
(with-current-buffer buffer
@@ -634,7 +636,7 @@ Uses THING, FACE, DEFS and PREPEND."
collect (cl-destructuring-bind (&key range severity _group
_code source message)
diag-spec
- (pcase-let ((`(,beg . ,end) (eglot--range-region range)))
+ (pcase-let ((`(,beg ,end) (eglot--range-region range)))
(flymake-make-diagnostic (current-buffer)
beg end
(cond ((<= severity 1) :error)
@@ -679,15 +681,12 @@ THINGS are either registrations or unregisterations."
(proc &key id _label edit)
"Handle server request workspace/applyEdit"
(condition-case err
- (progn
- (eglot--apply-workspace-edit edit 'confirm)
- (jsonrpc-reply proc id :result `(:applied )))
- (error
- (jsonrpc-reply proc id
- :result `(:applied :json-false)
- :error
- (jsonrpc-obj :code -32001
- :message (format "%s" err))))))
+ (progn (eglot--apply-workspace-edit edit 'confirm)
+ (jsonrpc-reply proc id :result `(:applied )))
+ (error (jsonrpc-reply proc id
+ :result `(:applied :json-false)
+ :error (jsonrpc-obj :code -32001
+ :message (format "%s" err))))))
(defun eglot--TextDocumentIdentifier ()
"Compute TextDocumentIdentifier object for current buffer."
@@ -752,7 +751,8 @@ Records START, END and PRE-CHANGE-LENGTH locally."
(advice-add #'jsonrpc-request :before
(cl-function (lambda (_proc _method _params &key deferred)
(when (and eglot--managed-mode deferred)
- (eglot--signal-textDocument/didChange)))))
+ (eglot--signal-textDocument/didChange))))
+ '((name . eglot--signal-textDocument/didChange)))
(defun eglot--signal-textDocument/didChange ()
"Send textDocument/didChange to server."
@@ -945,15 +945,19 @@ DUMMY is ignored"
:deferred :textDocument/completion))
(items (if (vectorp resp) resp (plist-get resp :items))))
(mapcar
- (jsonrpc-lambda (&rest all &key label &allow-other-keys)
- (add-text-properties 0 1 all label) label)
+ (jsonrpc-lambda (&rest all &key label insertText
&allow-other-keys)
+ (let ((insert (or insertText label)))
+ (add-text-properties 0 1 all insert) insert))
items))))
:annotation-function
(lambda (obj)
- (propertize (concat " " (or (get-text-property 0 :detail obj)
- (cdr (assoc (get-text-property 0 :kind
obj)
- eglot--kind-names))))
- 'face 'font-lock-function-name-face))
+ (cl-destructuring-bind (&key detail documentation kind
&allow-other-keys)
+ (text-properties-at 0 obj)
+ (concat " " (propertize
+ (or (and documentation
+ (replace-regexp-in-string "\n.*" ""
documentation))
+ detail (cdr (assoc kind eglot--kind-names)))
+ 'face 'font-lock-function-name-face))))
:display-sort-function
(lambda (items)
(sort items (lambda (a b)
@@ -964,31 +968,27 @@ DUMMY is ignored"
(lambda (obj)
(let ((documentation
(or (get-text-property 0 :documentation obj)
- (plist-get (jsonrpc-request proc :completionItem/resolve
- (text-properties-at 0 obj))
- :documentation))))
+ (and (eglot--server-capable :completionProvider
+ :resolveProvider)
+ (plist-get (jsonrpc-request proc
:completionItem/resolve
+ (text-properties-at 0
obj))
+ :documentation)))))
(when documentation
(with-current-buffer (get-buffer-create " *eglot doc*")
- (erase-buffer)
- (ignore-errors (funcall (intern "markdown-mode")))
- (font-lock-ensure)
- (insert documentation)
+ (insert (eglot--format-markup documentation))
(current-buffer)))))
- :exit-function
- (lambda (_string _status) (eglot-eldoc-function))))))
+ :exit-function (lambda (_string _status)
+ (eglot--signal-textDocument/didChange)
+ (eglot-eldoc-function))))))
(defvar eglot--highlights nil "Overlays for textDocument/documentHighlight.")
(defun eglot--hover-info (contents &optional range)
- (concat (and range
- (pcase-let ((`(,beg . ,end) (eglot--range-region range)))
- (concat (buffer-substring beg end) ": ")))
+ (concat (and range (pcase-let ((`(,beg ,end) (eglot--range-region range)))
+ (concat (buffer-substring beg end) ": ")))
(mapconcat #'eglot--format-markup
- (append
- (cond ((vectorp contents)
- contents)
- (contents
- (list contents)))) "\n")))
+ (append (cond ((vectorp contents) contents)
+ (contents (list contents)))) "\n")))
(defun eglot--sig-info (sigs active-sig active-param)
(cl-loop
@@ -1051,9 +1051,10 @@ If SKIP-SIGNATURE, don't try to send
textDocument/signatureHelp."
proc :textDocument/hover position-params
:success-fn (jsonrpc-lambda (&key contents range)
(unless sig-showing
- (when-buffer-window
- (eldoc-message
- (eglot--hover-info contents range)))))
+ ;; for eglot-tests.el's sake, set this unconditionally
+ (setq eldoc-last-message
+ (eglot--hover-info contents range))
+ (when-buffer-window (eldoc-message
eldoc-last-message))))
:deferred :textDocument/hover))
(when (eglot--server-capable :documentHighlightProvider)
(jsonrpc-async-request
@@ -1065,7 +1066,7 @@ If SKIP-SIGNATURE, don't try to send
textDocument/signatureHelp."
(when-buffer-window
(mapcar
(jsonrpc-lambda (&key range _kind)
- (pcase-let ((`(,beg . ,end)
+ (pcase-let ((`(,beg ,end)
(eglot--range-region range)))
(let ((ov (make-overlay beg end)))
(overlay-put ov 'face 'highlight)
@@ -1100,14 +1101,14 @@ If SKIP-SIGNATURE, don't try to send
textDocument/signatureHelp."
(unless (or (not version) (equal version eglot--versioned-identifier))
(eglot--error "Edits on `%s' require version %d, you have %d"
(current-buffer) version eglot--versioned-identifier))
- (mapc (jsonrpc-lambda
- (&key range newText)
- (save-restriction
- (widen)
- (save-excursion
- (pcase-let ((`(,beg . ,end) (eglot--range-region range)))
- (goto-char beg) (delete-region beg end) (insert newText)))))
- edits)
+ (save-restriction
+ (widen)
+ (save-excursion
+ (mapc (jsonrpc-lambda (newText beg end)
+ (goto-char beg) (delete-region beg end) (insert newText))
+ (mapcar (jsonrpc-lambda (&key range newText)
+ (cons newText (eglot--range-region range 'markers)))
+ edits))))
(eglot--message "%s: Performed %s edits" (current-buffer) (length edits)))
(defun eglot--apply-workspace-edit (wedit &optional confirm)
@@ -1223,11 +1224,10 @@ Proceed? "
"Handle notification window/progress"
(setf (eglot--spinner process) (list id title done message))
(when (and (equal "Indexing" title) done)
- (dolist (buffer (buffer-list))
+ (dolist (buffer (eglot--managed-buffers process))
(with-current-buffer buffer
- (when (eglot--buffer-managed-p process)
- (funcall (or eglot--current-flymake-report-fn #'ignore)
- eglot--unreported-diagnostics))))))
+ (funcall (or eglot--current-flymake-report-fn #'ignore)
+ eglot--unreported-diagnostics)))))
(provide 'eglot)
;;; eglot.el ends here
diff --git a/jsonrpc.el b/jsonrpc.el
index 251ebf4..d5f7745 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -168,17 +168,13 @@ FORMAT as the message."
(var-sym initval &optional doc)
"Define VAR-SYM as a generalized process-local variable.
INITVAL is the default value. DOC is the documentation."
- (declare (indent 2))
+ (declare (indent 2) (doc-string 3))
`(progn
- (put ',var-sym 'function-documentation ,doc)
- (defun ,var-sym (proc)
+ (defun ,var-sym (proc) ,doc
(let* ((plist (process-plist proc))
(probe (plist-member plist ',var-sym)))
- (if probe
- (cadr probe)
- (let ((def ,initval))
- (process-put proc ',var-sym def)
- def))))
+ (if probe (cadr probe)
+ (let ((def ,initval)) (process-put proc ',var-sym def) def))))
(gv-define-setter ,var-sym (to-store process)
`(let ((once ,to-store)) (process-put ,process ',',var-sym once)
once))))
@@ -551,7 +547,7 @@ TIMEOUT is nil)"
(funcall (or timeout-fn
(lambda ()
(jsonrpc-log-event
- proc `(:timed-out ,method :id id
+ proc `(:timed-out ,method :id ,id
:params
,params))))))))))))
(when deferred
(let* ((buf (current-buffer))
@@ -583,14 +579,14 @@ TIMEOUT is nil)"
(puthash id
(list (or success-fn
(jsonrpc-lambda (&rest _ignored)
- (jsonrpc-log-event
- proc (jsonrpc-obj :message "success
ignored" :id id))))
+ (jsonrpc-log-event
+ proc (jsonrpc-obj :message "success ignored" :id
id))))
(or error-fn
(jsonrpc-lambda (&key code message &allow-other-keys)
- (setf (jsonrpc-status proc) `(,message
t))
- (jsonrpc-log-event
- proc (jsonrpc-obj :message "error
ignored, status set"
- :id id :error
code))))
+ (setf (jsonrpc-status proc) `(,message t))
+ (jsonrpc-log-event
+ proc (jsonrpc-obj :message "error ignored, status
set"
+ :id id :error code))))
(setq timer (funcall make-timer)))
(jsonrpc--request-continuations proc))
(list id timer)))
@@ -604,33 +600,34 @@ only exit locally (and return the JSONRPC result object)
if the
request is successful, otherwise exit non-locally with an error.
DEFERRED is passed to `jsonrpc-async-request', which see."
- (let* ((tag (cl-gensym "jsonrpc-request-catch-tag"))
- req-id req-timer
+ (let* ((tag (cl-gensym "jsonrpc-request-catch-tag")) id-and-timer
(retval
(unwind-protect ; protect against user-quit, for example
(catch tag
- (pcase-let
- ((`(,id ,timer)
- (jsonrpc-async-request
- proc method params
- :success-fn (lambda (result) (throw tag `(done
,result)))
- :error-fn
- (jsonrpc-lambda
- (&key code message data)
- (throw tag `(error (jsonrpc-error-code . ,code)
- (jsonrpc-error-message . ,message)
- (jsonrpc-error-data . ,data))))
- :timeout-fn
- (lambda ()
- (throw tag '(error (jsonrpc-error-message . "Timed
out"))))
- :deferred deferred)))
- (setq req-id (or id 'deferred) req-timer timer))
+ (setq
+ id-and-timer
+ (jsonrpc-async-request
+ proc method params
+ :success-fn (lambda (result) (throw tag `(done ,result)))
+ :error-fn
+ (jsonrpc-lambda
+ (&key code message data)
+ (throw tag `(error (jsonrpc-error-code . ,code)
+ (jsonrpc-error-message . ,message)
+ (jsonrpc-error-data . ,data))))
+ :timeout-fn
+ (lambda ()
+ (throw tag '(error (jsonrpc-error-message . "Timed out"))))
+ :deferred deferred))
(while t (accept-process-output nil 30)))
- (when req-timer (cancel-timer req-timer)))))
+ (pcase-let ((`(,id ,timer) id-and-timer))
+ (when id (remhash id (jsonrpc--request-continuations proc)))
+ (when timer (cancel-timer timer))))))
(when (eq 'error (car retval))
(signal 'error
(cons
- (format "[jsonrpc] jsonrpc-request (%s) failed:" req-id) (cdr
retval))))
+ (format "[jsonrpc] jsonrpc-request (%s) failed:" (car
id-and-timer))
+ (cdr retval))))
(cadr retval)))
(cl-defun jsonrpc-notify (proc method params)
- [elpa] externals/eglot a65d3f4 53/69: Make message and warning helpers private, (continued)
- [elpa] externals/eglot a65d3f4 53/69: Make message and warning helpers private, João Távora, 2018/06/22
- [elpa] externals/eglot 9e9dc57 30/69: Merge branch 'master' into jsonrpc-refactor (using regular merge), João Távora, 2018/06/22
- [elpa] externals/eglot 6c9d41e 38/69: Add reasonably sophisticated deferred action tests, João Távora, 2018/06/22
- [elpa] externals/eglot 2da7d92 50/69: Simplify JSONRPC status setting, João Távora, 2018/06/22
- [elpa] externals/eglot 69a622a 64/69: Fix some typos, João Távora, 2018/06/22
- [elpa] externals/eglot 7371f68 57/69: * jsonrpc.el: Rewrite commentary., João Távora, 2018/06/22
- [elpa] externals/eglot 6531c8b 58/69: Merge branch 'master' into jsonrpc-refactor, João Távora, 2018/06/22
- [elpa] externals/eglot 59cc3fb 61/69: jsonrpc-connection-receive is now a public convenience function, João Távora, 2018/06/22
- [elpa] externals/eglot d371f05 49/69: Request dispatcher's return value determines response, João Távora, 2018/06/22
- [elpa] externals/eglot 0f20fdf 68/69: Tiny README.md change, João Távora, 2018/06/22
- [elpa] externals/eglot cef3c29 22/69: Heroically merge master into jsonrpc-refactor (using imerge),
João Távora <=
- [elpa] externals/eglot a4441c6 37/69: Merge master into jsonrpc-refactor (using imerge), João Távora, 2018/06/22
- [elpa] externals/eglot 0e44b27 27/69: jsonrpc.el uses classes and generic functions, João Távora, 2018/06/22
- [elpa] externals/eglot 856a224 62/69: Simplify jsonrpc-connection-send, João Távora, 2018/06/22
- [elpa] externals/eglot 1f09fd3 59/69: Review commentary section before another review cycle, João Távora, 2018/06/22
- [elpa] externals/eglot 8fda30c 67/69: Merge master into jsonrpc-refactor (using imerge), João Távora, 2018/06/22
- [elpa] externals/eglot 7f4e273 31/69: Merge master into jsonrpc-refactor (using imerge), João Távora, 2018/06/22
- [elpa] externals/eglot 4525eca 43/69: Support json.c. API purely based on classes, João Távora, 2018/06/22
- [elpa] externals/eglot bb60c0c 21/69: Rename jrpc.el to jsonrpc.el, João Távora, 2018/06/22
- [elpa] externals/eglot 46e6107 54/69: Reshuffle definitions inside jsonrpc.el, João Távora, 2018/06/22
- [elpa] externals/eglot 6f1ecc6 28/69: Merge branch use-eieio-server-defclass into jsonrpc-refactor, João Távora, 2018/06/22