27
27
(headers '()) ; ; alist of headers
28
28
(body nil ) ; ; message body
29
29
(reading-body nil ) ; ; If non-nil, reading body
30
- (leftovers " " ) ; ; Leftover data from previous chunk; to be processed
30
+ (body-length nil ) ; ; length of current message body
31
+ (body-received 0 ) ; ; amount of current message body currently stored in 'body'
32
+ (leftovers nil ) ; ; Leftover data from previous chunk; to be processed
31
33
32
34
(queued-notifications nil )
33
35
(queued-requests nil )
@@ -116,8 +118,8 @@ Else it is queued (unless DONT-QUEUE is non-nil)"
116
118
message
117
119
(or (car (alist-get code lsp--errors)) " Unknown error" ))))
118
120
119
- (defun lsp--parser-length-header ( p )
120
- (string-to-number (cdr (assoc " Content-Length" (lsp--parser- headers p) ))))
121
+ (defun lsp--get-body-length ( headers )
122
+ (string-to-number (cdr (assoc " Content-Length" headers))))
121
123
122
124
(defun lsp--parse-header (s )
123
125
" Parse string S as a LSP (KEY . VAL) header."
@@ -135,10 +137,13 @@ Else it is queued (unless DONT-QUEUE is non-nil)"
135
137
(cons key val)))
136
138
137
139
(defun lsp--parser-reset (p )
138
- (setf (lsp--parser-leftovers p) " "
139
- (lsp--parser-headers p) '()
140
- (lsp--parser-body p) nil
141
- (lsp--parser-reading-body p) nil ))
140
+ (setf
141
+ (lsp--parser-leftovers p) " "
142
+ (lsp--parser-body-length p) nil
143
+ (lsp--parser-body-received p) nil
144
+ (lsp--parser-headers p) '()
145
+ (lsp--parser-body p) nil
146
+ (lsp--parser-reading-body p) nil ))
142
147
143
148
(defun lsp--parser-on-message (p )
144
149
" Called when the parser reads a complete message from the server."
@@ -159,50 +164,53 @@ Else it is queued (unless DONT-QUEUE is non-nil)"
159
164
('request (lsp--on-request p json-data))))
160
165
(lsp--parser-reset p))
161
166
162
- (defun lsp--parser-read (p chunk- )
167
+ (defun lsp--parser-read (p chunk )
163
168
(cl-assert (lsp--parser-workspace p) nil " Parser workspace cannot be nil." )
164
- (let* ((leftovers (lsp--parser-leftovers p))
165
- (chunk (if (> (length leftovers) 0 )
166
- (concat leftovers chunk-)
167
- chunk-)))
168
-
169
- ; ; Read headers
170
- (when (not (lsp--parser-reading-body p))
171
- (let ((body-sep-pos (string-match-p " \r\n\r\n " chunk)))
169
+
170
+ (while (not (string-empty-p chunk))
171
+ (if (not (lsp--parser-reading-body p))
172
+ (let* ((full-chunk (concat (lsp--parser-leftovers p) chunk))
173
+ (body-sep-pos (string-match-p " \r\n\r\n " chunk)))
172
174
(if body-sep-pos
173
175
; ; We've got all the headers, handle them all at once:
174
176
(let* ((header-raw (substring chunk 0 body-sep-pos))
175
- (content (substring chunk (+ body-sep-pos 4 )))
176
- (headers
177
- (mapcar 'lsp--parse-header
178
- (split-string header-raw " \r\n " ))))
179
- (setf (lsp--parser-headers p) headers)
180
- (setf (lsp--parser-reading-body p) t )
177
+ (content (substring chunk (+ body-sep-pos 4 )))
178
+ (headers
179
+ (mapcar 'lsp--parse-header
180
+ (split-string header-raw " \r\n " )))
181
+ (body-length (lsp--get-body-length headers)))
182
+ (setf
183
+ (lsp--parser-headers p) headers
184
+ (lsp--parser-reading-body p) t
185
+ (lsp--parser-body-length p) body-length
186
+ (lsp--parser-body-received p) 0
187
+ (lsp--parser-body p) (make-string body-length ?\0 )
188
+ (lsp--parser-leftovers p) nil )
181
189
(setq chunk content))
182
190
183
191
; ; Haven't found the end of the headers yet, save everything
184
- ; ; for later :
185
- (setf (lsp--parser-leftovers p) chunk))) )
186
-
187
- ; ; Read body
188
- ( when (lsp--parser-reading-body p)
189
- (let ((body-length (lsp--parser-length-header p) ))
190
- ( if ( >= ( length chunk) body-length)
191
- ; ; Have a full body (and maybe a bit of the next one )
192
- ( let ((full-body ( substring chunk 0 body-length))
193
- (bit-of-next-message ( substring chunk body -length)))
194
- ( setf (lsp--parser-body p) full -body)
195
- ( when lsp-print-io
196
- ( message " Output from language server: %s " full -body) )
197
- (lsp--parser-on-message p)
198
-
199
- ( unless ( string-empty-p bit-of-next-message)
200
- ; ; We've got a bit of the next message. Hopefully we
201
- ; ; don't do this _too_ much
202
- (lsp--parser-read p bit-of-next-message )))
203
-
204
- ; ; else, still waiting for the rest of the current body
205
- ( setf (lsp--parser-leftovers p) chunk) )))))
192
+ ; ; for when the next chunk arrives :
193
+ (setf (lsp--parser-leftovers p) full- chunk)
194
+ ( setq chunk " " )))
195
+
196
+ ; ; Read body
197
+ (let* ((total- body-length (lsp--parser-body-length p ))
198
+ (received- body-length (lsp--parser-body-received p) )
199
+ (chunk-length ( length chunk) )
200
+ (left-to-receive ( - total-body-length received- body-length))
201
+ (this-body ( substring chunk 0 ( min left-to-receive chunk-length)))
202
+ (leftovers ( substring chunk ( length this -body))) )
203
+
204
+ ( store-substring (lsp--parser-body p) received-body-length this -body)
205
+ ( setf (lsp--parser-body-received p) ( + (lsp--parser-body-received p)
206
+ ( length this-body)))
207
+
208
+ ( when ( >= chunk-length left-to-receive)
209
+ ( when lsp-print-io
210
+ ( message " Output from language server: %s " (lsp--parser-body p )))
211
+ (lsp--parser-on-message p))
212
+
213
+ ( setq chunk leftovers )))))
206
214
207
215
(defun lsp--parser-make-filter (p ignore-regexps )
208
216
#' (lambda (proc output )
0 commit comments