Mercurial > vim
comparison src/channel.c @ 28511:d7ca583e5772 v8.2.4780
patch 8.2.4780: parsing an LSP message fails when it is split
Commit: https://github.com/vim/vim/commit/03cca297df5210f94be2246cfdb1ee9a30454bea
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Mon Apr 18 14:07:46 2022 +0100
patch 8.2.4780: parsing an LSP message fails when it is split
Problem: Parsing an LSP message fails when it is split.
Solution: Collapse the received data before parsing. (Yegappan Lakshmanan,
closes #10215)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 18 Apr 2022 15:15:04 +0200 |
parents | 9f8563d05629 |
children | 6b1da12297e5 |
comparison
equal
deleted
inserted
replaced
28510:3f4bd5516667 | 28511:d7ca583e5772 |
---|---|
2033 * When "want_nl" is TRUE collapse more buffers until a NL is found. | 2033 * When "want_nl" is TRUE collapse more buffers until a NL is found. |
2034 */ | 2034 */ |
2035 int | 2035 int |
2036 channel_collapse(channel_T *channel, ch_part_T part, int want_nl) | 2036 channel_collapse(channel_T *channel, ch_part_T part, int want_nl) |
2037 { | 2037 { |
2038 readq_T *head = &channel->ch_part[part].ch_head; | 2038 ch_mode_T mode = channel->ch_part[part].ch_mode; |
2039 readq_T *node = head->rq_next; | 2039 readq_T *head = &channel->ch_part[part].ch_head; |
2040 readq_T *last_node; | 2040 readq_T *node = head->rq_next; |
2041 readq_T *n; | 2041 readq_T *last_node; |
2042 char_u *newbuf; | 2042 readq_T *n; |
2043 char_u *p; | 2043 char_u *newbuf; |
2044 long_u len; | 2044 char_u *p; |
2045 long_u len; | |
2045 | 2046 |
2046 if (node == NULL || node->rq_next == NULL) | 2047 if (node == NULL || node->rq_next == NULL) |
2047 return FAIL; | 2048 return FAIL; |
2048 | 2049 |
2049 last_node = node->rq_next; | 2050 last_node = node->rq_next; |
2050 len = node->rq_buflen + last_node->rq_buflen; | 2051 len = node->rq_buflen + last_node->rq_buflen; |
2051 if (want_nl) | 2052 if (want_nl || mode == MODE_LSP) |
2052 while (last_node->rq_next != NULL | 2053 while (last_node->rq_next != NULL |
2053 && channel_first_nl(last_node) == NULL) | 2054 && (mode == MODE_LSP |
2055 || channel_first_nl(last_node) == NULL)) | |
2054 { | 2056 { |
2055 last_node = last_node->rq_next; | 2057 last_node = last_node->rq_next; |
2056 len += last_node->rq_buflen; | 2058 len += last_node->rq_buflen; |
2057 } | 2059 } |
2058 | 2060 |
3004 int argc = 0; | 3006 int argc = 0; |
3005 | 3007 |
3006 // Get any json message in the queue. | 3008 // Get any json message in the queue. |
3007 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) | 3009 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) |
3008 { | 3010 { |
3011 if (ch_mode == MODE_LSP) | |
3012 // In the "lsp" mode, the http header and the json payload may | |
3013 // be received in multiple messages. So concatenate all the | |
3014 // received messages. | |
3015 (void)channel_collapse(channel, part, FALSE); | |
3016 | |
3009 // Parse readahead, return when there is still no message. | 3017 // Parse readahead, return when there is still no message. |
3010 channel_parse_json(channel, part); | 3018 channel_parse_json(channel, part); |
3011 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) | 3019 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) |
3012 return FALSE; | 3020 return FALSE; |
3013 } | 3021 } |
3972 { | 3980 { |
3973 int more; | 3981 int more; |
3974 sock_T fd; | 3982 sock_T fd; |
3975 int timeout; | 3983 int timeout; |
3976 chanpart_T *chanpart = &channel->ch_part[part]; | 3984 chanpart_T *chanpart = &channel->ch_part[part]; |
3985 ch_mode_T mode = channel->ch_part[part].ch_mode; | |
3977 int retval = FAIL; | 3986 int retval = FAIL; |
3978 | 3987 |
3979 ch_log(channel, "Blocking read JSON for id %d", id); | 3988 ch_log(channel, "Blocking read JSON for id %d", id); |
3980 ++channel_blocking_wait; | 3989 ++channel_blocking_wait; |
3981 | 3990 |
3982 if (id >= 0) | 3991 if (id >= 0) |
3983 channel_add_block_id(chanpart, id); | 3992 channel_add_block_id(chanpart, id); |
3984 | 3993 |
3985 for (;;) | 3994 for (;;) |
3986 { | 3995 { |
3996 if (mode == MODE_LSP) | |
3997 // In the "lsp" mode, the http header and the json payload may be | |
3998 // received in multiple messages. So concatenate all the received | |
3999 // messages. | |
4000 (void)channel_collapse(channel, part, FALSE); | |
4001 | |
3987 more = channel_parse_json(channel, part); | 4002 more = channel_parse_json(channel, part); |
3988 | 4003 |
3989 // search for message "id" | 4004 // search for message "id" |
3990 if (channel_get_json(channel, part, id, TRUE, rettv) == OK) | 4005 if (channel_get_json(channel, part, id, TRUE, rettv) == OK) |
3991 { | 4006 { |