[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot 1add335 078/139: Workaround two suspected Emacs b
From: |
João Távora |
Subject: |
[elpa] externals/eglot 1add335 078/139: Workaround two suspected Emacs bugs |
Date: |
Mon, 14 May 2018 09:54:57 -0400 (EDT) |
branch: externals/eglot
commit 1add3354d5c46bae530565b77636b8f11207f40f
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Workaround two suspected Emacs bugs
* eglot.el (eglot--process-filter): Use a proper unique tag. Use
unwind-protect.
(eglot--sync-request): Rework.
(eglot--server-client/registerCapability): Use a proper done tag.
---
eglot.el | 135 ++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 72 insertions(+), 63 deletions(-)
diff --git a/eglot.el b/eglot.el
index 321307d..1d72b4c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -415,7 +415,8 @@ INTERACTIVE is t if called interactively."
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(let ((inhibit-read-only t)
- (expected-bytes (eglot--expected-bytes proc)))
+ (expected-bytes (eglot--expected-bytes proc))
+ (done (make-symbol "eglot--process-filter-done-tag")))
;; Insert the text, advancing the process marker.
;;
(save-excursion
@@ -424,51 +425,52 @@ INTERACTIVE is t if called interactively."
(set-marker (process-mark proc) (point)))
;; Loop (more than one message might have arrived)
;;
- (catch 'done
- (while t
- (cond ((not expected-bytes)
- ;; Starting a new message
- ;;
- (setq expected-bytes
- (and (search-forward-regexp
- "\\(?:.*: .*\r\n\\)*Content-Length: \
+ (unwind-protect
+ (catch done
+ (while t
+ (cond ((not expected-bytes)
+ ;; Starting a new message
+ ;;
+ (setq expected-bytes
+ (and (search-forward-regexp
+ "\\(?:.*: .*\r\n\\)*Content-Length: \
*\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
- (+ (point) 100)
- t)
- (string-to-number (match-string 1))))
- (unless expected-bytes
- (throw 'done :waiting-for-new-message)))
- (t
- ;; Attempt to complete a message body
- ;;
- (let ((available-bytes (- (position-bytes (process-mark
proc))
- (position-bytes (point)))))
- (cond
- ((>= available-bytes
- expected-bytes)
- (let* ((message-end (byte-to-position
- (+ (position-bytes (point))
- expected-bytes))))
- (unwind-protect
- (save-restriction
- (narrow-to-region (point) message-end)
- (let* ((json-object-type 'plist)
- (json-message (json-read)))
- ;; Process content in another buffer,
- ;; shielding buffer from tamper
- ;;
- (with-temp-buffer
- (eglot--process-receive proc
json-message))))
- (goto-char message-end)
- (delete-region (point-min) (point))
- (setq expected-bytes nil))))
+ (+ (point) 100)
+ t)
+ (string-to-number (match-string 1))))
+ (unless expected-bytes
+ (throw done :waiting-for-new-message)))
(t
- ;; Message is still incomplete
+ ;; Attempt to complete a message body
;;
- (throw 'done
:waiting-for-more-bytes-in-this-message))))))))
- ;; Saved parsing state for next visit to this filter
- ;;
- (setf (eglot--expected-bytes proc) expected-bytes)))))
+ (let ((available-bytes (- (position-bytes (process-mark
proc))
+ (position-bytes (point)))))
+ (cond
+ ((>= available-bytes
+ expected-bytes)
+ (let* ((message-end (byte-to-position
+ (+ (position-bytes (point))
+ expected-bytes))))
+ (unwind-protect
+ (save-restriction
+ (narrow-to-region (point) message-end)
+ (let* ((json-object-type 'plist)
+ (json-message (json-read)))
+ ;; Process content in another buffer,
+ ;; shielding buffer from tamper
+ ;;
+ (with-temp-buffer
+ (eglot--process-receive proc
json-message))))
+ (goto-char message-end)
+ (delete-region (point-min) (point))
+ (setq expected-bytes nil))))
+ (t
+ ;; Message is still incomplete
+ ;;
+ (throw done
:waiting-for-more-bytes-in-this-message))))))))
+ ;; Saved parsing state for next visit to this filter
+ ;;
+ (setf (eglot--expected-bytes proc) expected-bytes))))))
(defun eglot-events-buffer (process &optional interactive)
"Display events buffer for current LSP connection PROCESS.
@@ -654,18 +656,25 @@ is a symbol saying if this is a client or server
originated."
(defun eglot--sync-request (proc method params)
"Like `eglot--request' for PROC, METHOD and PARAMS, but synchronous.
Meaning only return locally if successful, otherwise exit non-locally."
- (eglot--request proc method params
- :success-fn (lambda (&rest args)
- (if (vectorp (car args))
- (car args)
- args))
- :error-fn (cl-function
- (lambda (&key code message &allow-other-keys)
- (eglot--error "Oops: %s: %s" code message)))
- :timeout-fn (lambda ()
- (eglot--error
- "Tired of waiting for reply to sync request"))
- :async-p nil))
+ (let* ((timeout-error-sym (cl-gensym))
+ (retval (eglot--request proc method params
+ :success-fn (lambda (&rest args)
+ (if (vectorp (car args))
+ (car args)
+ args))
+ :error-fn (cl-function
+ (lambda (&key code message
&allow-other-keys)
+ (eglot--error "Oops: %s: %s"
code message)))
+ :timeout-fn (lambda () timeout-error-sym)
+ :async-p nil)))
+ ;; FIXME: There's maybe an emacs bug here. Because timeout-fn runs
+ ;; in a timer, the better and obvious choice of throwing the erro
+ ;; in the lambda is not quitting the `accept-process-output'
+ ;; infinite loop up there. So use this contorted strategy with
+ ;; `cl-gensym'.
+ (if (eq retval timeout-error-sym)
+ (eglot--error "Tired of waiting for reply to sync request")
+ retval)))
(cl-defun eglot--notify (process method params)
"Notify PROCESS of something, don't expect a reply.e"
@@ -1045,8 +1054,9 @@ running. INTERACTIVE is t if called interactively."
(cl-defun eglot--server-client/registerCapability
(proc &key id registrations)
"Handle notification client/registerCapability"
- (let ((jsonrpc-id id))
- (catch 'done
+ (let ((jsonrpc-id id)
+ (done (make-symbol "done")))
+ (catch done
(mapc
(lambda (reg)
(apply
@@ -1059,12 +1069,11 @@ running. INTERACTIVE is t if called interactively."
(and (functionp handler-sym)
(apply handler-sym proc :id id registerOptions))))
(unless ok
- (throw
- 'done
- (eglot--reply proc jsonrpc-id
- :error (eglot--obj
- :code -32601
- :message (or message "sorry
:-("))))))))
+ (throw done
+ (eglot--reply proc jsonrpc-id
+ :error (eglot--obj
+ :code -32601
+ :message (or message "sorry
:-("))))))))
reg))
registrations)
(eglot--reply proc id :result (eglot--obj :message "OK")))))
- [elpa] externals/eglot 79a2a1e 069/139: Be quite explicit about our lack of capabilities right now, (continued)
- [elpa] externals/eglot 79a2a1e 069/139: Be quite explicit about our lack of capabilities right now, João Távora, 2018/05/14
- [elpa] externals/eglot 95187cf 058/139: Connect to LSP server via TCP, João Távora, 2018/05/14
- [elpa] externals/eglot f76f04e 057/139: More correctly keep track of didOpen/didClose per buffer, João Távora, 2018/05/14
- [elpa] externals/eglot 46bb1c0 049/139: Reorganize file, João Távora, 2018/05/14
- [elpa] externals/eglot ff5a03d 074/139: Very basic xref support, João Távora, 2018/05/14
- [elpa] externals/eglot e9b5e54 077/139: ETOOMANYLAMBDAS, João Távora, 2018/05/14
- [elpa] externals/eglot dda11dd 095/139: Try to fix some textDocument/completion bugs, João Távora, 2018/05/14
- [elpa] externals/eglot ea918ab 066/139: Include source info in diagnostics, João Távora, 2018/05/14
- [elpa] externals/eglot a199c8e 070/139: Honour textDocumentSync, João Távora, 2018/05/14
- [elpa] externals/eglot e86f9b4 073/139: New helper eglot--sync-request, João Távora, 2018/05/14
- [elpa] externals/eglot 1add335 078/139: Workaround two suspected Emacs bugs,
João Távora <=
- [elpa] externals/eglot 889ef20 085/139: Tweak the async request engine., João Távora, 2018/05/14
- [elpa] externals/eglot 193c57d 075/139: Half-decent xref support, João Távora, 2018/05/14
- [elpa] externals/eglot fc6879f 084/139: Explain why didOpen on after-revert-hook is a bad idea, João Távora, 2018/05/14
- [elpa] externals/eglot 24466a9 096/139: When killing server, always wait 3 seconds, João Távora, 2018/05/14
- [elpa] externals/eglot fceb6bb 090/139: Get rid of eglot--special-buffer-process, João Távora, 2018/05/14
- [elpa] externals/eglot d254f97 082/139: Solve another textDocument/didChange bug, João Távora, 2018/05/14
- [elpa] externals/eglot f257d63 089/139: * eglot.el: Reformat to shave off some lines., João Távora, 2018/05/14
- [elpa] externals/eglot c7bd095 118/139: Improve eglot-eldoc-function, João Távora, 2018/05/14
- [elpa] externals/eglot 3e0f1c3 122/139: Misc little adjustments for readability, João Távora, 2018/05/14
- [elpa] externals/eglot 3dcbc30 109/139: Add minimal headers, commentary and autoloads, João Távora, 2018/05/14