branch: externals/elpa
commit b511b7d2da0e48a460bbcf4e7e9380a7253aa5d1
Author: João Távora <joaotav...@gmail.com>
Commit: João Távora <joaotav...@gmail.com>

    Redesign and simplify parser
    
    Fix horrible bugs. This is the correct way.
    
    * eglot.el (eglot--process-filter): Redesign.
---
 eglot.el | 106 ++++++++++++++++++++++++++++-----------------------------------
 1 file changed, 47 insertions(+), 59 deletions(-)

diff --git a/eglot.el b/eglot.el
index 71dab80..b9aa94c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -234,71 +234,59 @@ INTERACTIVE is t if called interactively."
   (when (buffer-live-p (process-buffer proc))
     (with-current-buffer (process-buffer proc)
       (let ((inhibit-read-only t)
-            (pre-insertion-mark (copy-marker (process-mark proc)))
             (expected-bytes (eglot--expected-bytes proc)))
         ;; Insert the text, advancing the process marker.
-        (goto-char (process-mark proc))
-        (insert string)
-        (set-marker (process-mark proc) (point))
-
-        ;; goto point just before insertion
         ;;
-        (goto-char pre-insertion-mark)
-
-        ;; loop for each message (more than one might have arrived)
+        (save-excursion
+          (goto-char (process-mark proc))
+          (insert string)
+          (set-marker (process-mark proc) (point)))
+        ;; Loop (more than one message might have arrived)
         ;;
         (catch 'done
           (while t
-            (let* ((match (search-forward-regexp
-                           "\\(?:.*: .*\r\n\\)*Content-Length: 
\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
-                           (+ (point) 100)
-                           t))
-                   (new-expected-bytes (and match
-                                            (string-to-number (match-string 
1)))))
-              (when new-expected-bytes
-                (when expected-bytes
-                  (eglot--warn
-                   (concat "Unexpectedly starting new message but %s bytes "
-                           "reportedly remaining from previous one")
-                   expected-bytes))
-                (setf (eglot--expected-bytes proc) new-expected-bytes)
-                (setq expected-bytes new-expected-bytes)))
-
-            ;; check for message body
-            ;;
-            (let ((available-bytes (- (position-bytes (process-mark proc))
-                                      (position-bytes (point)))))
-              (cond ((not expected-bytes) ; previous search didn't match
-                     (eglot--warn
-                      "Skipping %s bytes of unexpected garbage from process %s"
-                      available-bytes
-                      proc)
-                     (goto-char (process-mark proc))
-                     (throw 'done :skipping-garbage))
-                    ((>= 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 in another buffer, shielding
-                               ;; buffer from tamper
-                               (with-temp-buffer
-                                 (eglot--process-receive proc json-message))))
-                         (goto-char message-end)
-                         (setf (eglot--expected-bytes proc) nil
-                               expected-bytes nil)))
-                     (when (= (point) (process-mark proc))
-                       (throw 'done :clean-done)))
-                    (t
-                     ;; just adding some stuff to the end that doesn't yet
-                     ;; complete the message
-                     (throw 'done :waiting-for-more-bytes))))))))))
+            (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))))
+                      (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)))))
 
 (defmacro eglot--obj (&rest what)
   "Make WHAT a suitable argument for `json-encode'."

Reply via email to