@@ -7150,69 +7150,43 @@ server. WORKSPACE is the active workspace."
71507150 ('request (lsp--on-request workspace json-data)))))))
71517151
71527152(defun lsp--create-filter-function (workspace)
7153- "Make filter for the workspace."
7154- (let ((body-received 0)
7155- leftovers body-length body chunk)
7153+ "Efficiently filter/process LSP messages for WORKSPACE.
7154+ Accumulates incoming LSP data in a buffer, parses headers to find
7155+ Content-Length, then extracts and decodes complete JSON messages for processing."
7156+ (let ((input-buffer (generate-new-buffer " *lsp-input*"))
7157+ (json-body-buffer (generate-new-buffer " *lsp-json-body*")))
71567158 (lambda (_proc input)
7157- (setf chunk (if (s-blank? leftovers)
7158- (encode-coding-string input 'utf-8-unix t)
7159- (concat leftovers (encode-coding-string input 'utf-8-unix t))))
7160-
7161- (let (messages)
7162- (while (not (s-blank? chunk))
7163- (if (not body-length)
7164- ;; Read headers
7165- (if-let* ((body-sep-pos (string-match-p "\r\n\r\n" chunk)))
7166- ;; We've got all the headers, handle them all at once:
7167- (setf body-length (lsp--get-body-length
7168- (mapcar #'lsp--parse-header
7169- (split-string
7170- (substring-no-properties chunk
7171- (or (string-match-p "Content-Length" chunk)
7172- (error "Unable to find Content-Length header."))
7173- body-sep-pos)
7174- "\r\n")))
7175- body-received 0
7176- leftovers nil
7177- chunk (substring-no-properties chunk (+ body-sep-pos 4)))
7178-
7179- ;; Haven't found the end of the headers yet. Save everything
7180- ;; for when the next chunk arrives and await further input.
7181- (setf leftovers chunk
7182- chunk nil))
7183- (let* ((chunk-length (string-bytes chunk))
7184- (left-to-receive (- body-length body-received))
7185- (this-body (if (< left-to-receive chunk-length)
7186- (prog1 (substring-no-properties chunk 0 left-to-receive)
7187- (setf chunk (substring-no-properties chunk left-to-receive)))
7188- (prog1 chunk
7189- (setf chunk nil))))
7190- (body-bytes (string-bytes this-body)))
7191- (push this-body body)
7192- (setf body-received (+ body-received body-bytes))
7193- (when (>= chunk-length left-to-receive)
7194- (condition-case err
7195- (with-temp-buffer
7196- (apply #'insert
7197- (nreverse
7198- (prog1 body
7199- (setf leftovers nil
7200- body-length nil
7201- body-received nil
7202- body nil))))
7203- (decode-coding-region (point-min)
7204- (point-max)
7205- 'utf-8)
7206- (goto-char (point-min))
7207- (push (lsp-json-read-buffer) messages))
7208-
7209- (error
7210- (lsp-warn "Failed to parse the following chunk:\n'''\n%s\n'''\nwith message %s"
7211- (concat leftovers input)
7212- err)))))))
7213- (mapc (lambda (msg)
7214- (lsp--parser-on-message msg workspace))
7215- (nreverse messages))))))
7159+ (with-current-buffer input-buffer
7160+ ;; Insert raw input at the end as UTF-8 (no decode yet)
7161+ (goto-char (point-max))
7162+ (insert (encode-coding-string input 'utf-8-unix t))
7163+ (goto-char (point-min))
7164+ (cl-loop
7165+ ;; Try to parse messages as long as possible
7166+ while (let ((header-end (search-forward "\r\n\r\n" nil t)))
7167+ (when header-end
7168+ (let* ((headers (buffer-substring (point-min) (- header-end 4)))
7169+ (header-lines (split-string headers "\r\n" t))
7170+ (parsed-headers (mapcar #'lsp--parse-header header-lines))
7171+ (body-length (lsp--get-body-length parsed-headers))
7172+ (body-start header-end)
7173+ (body-end (+ header-end body-length)))
7174+ (when (<= body-end (point-max))
7175+ ;; Copy and decode body
7176+ (with-current-buffer json-body-buffer
7177+ (erase-buffer)
7178+ (insert-buffer-substring input-buffer body-start body-end)
7179+ (decode-coding-region (point-min) (point-max) 'utf-8)
7180+ (goto-char (point-min))
7181+ (condition-case err
7182+ (let ((msg (lsp-json-read-buffer)))
7183+ (lsp--parser-on-message msg workspace))
7184+ (error
7185+ (message "LSP JSON parse error: %S" err))))
7186+ ;; Remove processed data
7187+ (delete-region (point-min) body-end)
7188+ (goto-char (point-min))
7189+ t)))))))))
72167190
72177191(defvar-local lsp--line-col-to-point-hash-table nil
72187192 "Hash table with keys (line . col) and values that are either point positions
0 commit comments