@@ -7150,69 +7150,52 @@ server. WORKSPACE is the active workspace."
7150
7150
('request (lsp--on-request workspace json-data)))))))
7151
7151
7152
7152
(defun lsp--create-filter-function (workspace)
7153
- "Make filter for the workspace."
7154
- (let ((body-received 0)
7155
- leftovers body-length body chunk)
7156
- (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))))))
7153
+ "Efficient, low-latency filter for the workspace."
7154
+ (let ((header-done nil)
7155
+ (body-length nil)
7156
+ (body-buffer (generate-new-buffer " *lsp-body*")))
7157
+ (lambda (_proc input)
7158
+ (with-current-buffer body-buffer
7159
+ (goto-char (point-max))
7160
+ ;; Always insert input directly; avoid string concat.
7161
+ (insert (encode-coding-string input 'utf-8-unix t))
7162
+ (goto-char (point-min))
7163
+ ;; Loop for as long as there's a full message in the buffer.
7164
+ (cl-loop
7165
+ ;; Stop only if at buffer end or incomplete message.
7166
+ while (< (point) (point-max))
7167
+ do
7168
+ (unless header-done
7169
+ (let ((header-end (search-forward "\r\n\r\n" nil t)))
7170
+ (unless header-end
7171
+ ;; Incomplete header, wait for more input
7172
+ (cl-return))
7173
+ (let* ((headers (buffer-substring-no-properties (point-min) (- header-end 4)))
7174
+ (parsed (mapcar #'lsp--parse-header (split-string headers "\r\n"))))
7175
+ (setq body-length (lsp--get-body-length parsed))
7176
+ (setq header-done t)
7177
+ (delete-region (point-min) header-end)
7178
+ (goto-char (point-min)))))
7179
+ (when (and header-done body-length)
7180
+ (let ((bytes-available (- (point-max) (point))))
7181
+ (if (>= bytes-available body-length)
7182
+ (let ((json-start (point))
7183
+ (json-end (+ (point) body-length)))
7184
+ (decode-coding-region json-start json-end 'utf-8)
7185
+ (goto-char json-start)
7186
+ (condition-case err
7187
+ (let ((msg (lsp-json-read-buffer)))
7188
+ ;; IMMEDIATELY dispatch as soon as we get one full message:
7189
+ (lsp--parser-on-message msg workspace))
7190
+ (error
7191
+ (lsp-warn "Failed to parse chunk with message %s" err)))
7192
+ (delete-region (point-min) json-end)
7193
+ ;; Reset for next message
7194
+ (setq header-done nil)
7195
+ (setq body-length nil)
7196
+ (goto-char (point-min))) ; Start parsing next message (if any)
7197
+ ;; Not enough body yet; wait for more data
7198
+ (cl-return)))))))))
7216
7199
7217
7200
(defvar-local lsp--line-col-to-point-hash-table nil
7218
7201
"Hash table with keys (line . col) and values that are either point positions
0 commit comments