mirror of
https://github.com/neovim/neovim.git
synced 2025-10-07 10:26:31 +00:00
Merge branch 'master' into luaviml'/lua
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
@@ -26,6 +29,7 @@
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/misc1.h"
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/os/input.h"
|
||||
|
||||
#define CHANNEL_BUFFER_SIZE 0xffff
|
||||
|
||||
@@ -86,6 +90,7 @@ static msgpack_sbuffer out_buffer;
|
||||
/// Initializes the module
|
||||
void channel_init(void)
|
||||
{
|
||||
ch_before_blocking_events = multiqueue_new_child(main_loop.events);
|
||||
channels = pmap_new(uint64_t)();
|
||||
event_strings = pmap_new(cstr_t)();
|
||||
msgpack_sbuffer_init(&out_buffer);
|
||||
@@ -189,7 +194,7 @@ Object channel_send_call(uint64_t id,
|
||||
Channel *channel = NULL;
|
||||
|
||||
if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) {
|
||||
api_set_error(err, Exception, _("Invalid channel \"%" PRIu64 "\""), id);
|
||||
api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id);
|
||||
api_free_array(args);
|
||||
return NIL;
|
||||
}
|
||||
@@ -209,7 +214,8 @@ Object channel_send_call(uint64_t id,
|
||||
|
||||
if (frame.errored) {
|
||||
if (frame.result.type == kObjectTypeString) {
|
||||
api_set_error(err, Exception, "%s", frame.result.data.string.data);
|
||||
api_set_error(err, kErrorTypeException, "%s",
|
||||
frame.result.data.string.data);
|
||||
} else if (frame.result.type == kObjectTypeArray) {
|
||||
// Should be an error in the form [type, message]
|
||||
Array array = frame.result.data.array;
|
||||
@@ -217,14 +223,13 @@ Object channel_send_call(uint64_t id,
|
||||
&& (array.items[0].data.integer == kErrorTypeException
|
||||
|| array.items[0].data.integer == kErrorTypeValidation)
|
||||
&& array.items[1].type == kObjectTypeString) {
|
||||
err->type = (ErrorType) array.items[0].data.integer;
|
||||
xstrlcpy(err->msg, array.items[1].data.string.data, sizeof(err->msg));
|
||||
err->set = true;
|
||||
api_set_error(err, (ErrorType)array.items[0].data.integer, "%s",
|
||||
array.items[1].data.string.data);
|
||||
} else {
|
||||
api_set_error(err, Exception, "%s", "unknown error");
|
||||
api_set_error(err, kErrorTypeException, "%s", "unknown error");
|
||||
}
|
||||
} else {
|
||||
api_set_error(err, Exception, "%s", "unknown error");
|
||||
api_set_error(err, kErrorTypeException, "%s", "unknown error");
|
||||
}
|
||||
|
||||
api_free_object(frame.result);
|
||||
@@ -395,7 +400,7 @@ static void handle_request(Channel *channel, msgpack_object *request)
|
||||
Error error = ERROR_INIT;
|
||||
msgpack_rpc_validate(&request_id, request, &error);
|
||||
|
||||
if (error.set) {
|
||||
if (ERROR_SET(&error)) {
|
||||
// Validation failed, send response with error
|
||||
if (channel_write(channel,
|
||||
serialize_response(channel->id,
|
||||
@@ -409,9 +414,9 @@ static void handle_request(Channel *channel, msgpack_object *request)
|
||||
channel->id);
|
||||
call_set_error(channel, buf);
|
||||
}
|
||||
api_clear_error(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the request handler
|
||||
MsgpackRpcRequestHandler handler;
|
||||
msgpack_object *method = msgpack_rpc_method(request);
|
||||
@@ -430,16 +435,24 @@ static void handle_request(Channel *channel, msgpack_object *request)
|
||||
handler.async = true;
|
||||
}
|
||||
|
||||
RequestEvent *event_data = xmalloc(sizeof(RequestEvent));
|
||||
event_data->channel = channel;
|
||||
event_data->handler = handler;
|
||||
event_data->args = args;
|
||||
event_data->request_id = request_id;
|
||||
RequestEvent *evdata = xmalloc(sizeof(RequestEvent));
|
||||
evdata->channel = channel;
|
||||
evdata->handler = handler;
|
||||
evdata->args = args;
|
||||
evdata->request_id = request_id;
|
||||
incref(channel);
|
||||
if (handler.async) {
|
||||
on_request_event((void **)&event_data);
|
||||
bool is_get_mode = handler.fn == handle_nvim_get_mode;
|
||||
|
||||
if (is_get_mode && !input_blocking()) {
|
||||
// Defer the event to a special queue used by os/input.c. #6247
|
||||
multiqueue_put(ch_before_blocking_events, on_request_event, 1, evdata);
|
||||
} else {
|
||||
// Invoke immediately.
|
||||
on_request_event((void **)&evdata);
|
||||
}
|
||||
} else {
|
||||
multiqueue_put(channel->events, on_request_event, 1, event_data);
|
||||
multiqueue_put(channel->events, on_request_event, 1, evdata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,6 +480,7 @@ static void on_request_event(void **argv)
|
||||
api_free_array(args);
|
||||
decref(channel);
|
||||
xfree(e);
|
||||
api_clear_error(&error);
|
||||
}
|
||||
|
||||
static bool channel_write(Channel *channel, WBuffer *buffer)
|
||||
@@ -509,12 +523,13 @@ static bool channel_write(Channel *channel, WBuffer *buffer)
|
||||
static void send_error(Channel *channel, uint64_t id, char *err)
|
||||
{
|
||||
Error e = ERROR_INIT;
|
||||
api_set_error(&e, Exception, "%s", err);
|
||||
api_set_error(&e, kErrorTypeException, "%s", err);
|
||||
channel_write(channel, serialize_response(channel->id,
|
||||
id,
|
||||
&e,
|
||||
NIL,
|
||||
&out_buffer));
|
||||
api_clear_error(&e);
|
||||
}
|
||||
|
||||
static void send_request(Channel *channel,
|
||||
|
@@ -11,6 +11,11 @@
|
||||
|
||||
#define METHOD_MAXLEN 512
|
||||
|
||||
/// HACK: os/input.c drains this queue immediately before blocking for input.
|
||||
/// Events on this queue are async-safe, but they need the resolved state
|
||||
/// of os_inchar(), so they are processed "just-in-time".
|
||||
MultiQueue *ch_before_blocking_events;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "msgpack_rpc/channel.h.generated.h"
|
||||
#endif
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
@@ -74,7 +77,7 @@ typedef struct {
|
||||
size_t idx;
|
||||
} MPToAPIObjectStackItem;
|
||||
|
||||
/// Convert type used by msgpack parser to Neovim own API type
|
||||
/// Convert type used by msgpack parser to Nvim API type.
|
||||
///
|
||||
/// @param[in] obj Msgpack value to convert.
|
||||
/// @param[out] arg Location where result of conversion will be saved.
|
||||
@@ -485,8 +488,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id,
|
||||
Array args,
|
||||
Error *error)
|
||||
{
|
||||
snprintf(error->msg, sizeof(error->msg), "Invalid method name");
|
||||
error->set = true;
|
||||
api_set_error(error, kErrorTypeException, "Invalid method name");
|
||||
return NIL;
|
||||
}
|
||||
|
||||
@@ -495,8 +497,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id,
|
||||
Array args,
|
||||
Error *error)
|
||||
{
|
||||
snprintf(error->msg, sizeof(error->msg), "Invalid method arguments");
|
||||
error->set = true;
|
||||
api_set_error(error, kErrorTypeException, "Invalid method arguments");
|
||||
return NIL;
|
||||
}
|
||||
|
||||
@@ -529,7 +530,7 @@ void msgpack_rpc_serialize_response(uint64_t response_id,
|
||||
msgpack_pack_int(pac, 1);
|
||||
msgpack_pack_uint64(pac, response_id);
|
||||
|
||||
if (err->set) {
|
||||
if (ERROR_SET(err)) {
|
||||
// error represented by a [type, message] array
|
||||
msgpack_pack_array(pac, 2);
|
||||
msgpack_rpc_from_integer(err->type, pac);
|
||||
@@ -582,49 +583,49 @@ void msgpack_rpc_validate(uint64_t *response_id,
|
||||
*response_id = NO_RESPONSE;
|
||||
// Validate the basic structure of the msgpack-rpc payload
|
||||
if (req->type != MSGPACK_OBJECT_ARRAY) {
|
||||
api_set_error(err, Validation, _("Message is not an array"));
|
||||
api_set_error(err, kErrorTypeValidation, "Message is not an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->via.array.size == 0) {
|
||||
api_set_error(err, Validation, _("Message is empty"));
|
||||
api_set_error(err, kErrorTypeValidation, "Message is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
|
||||
api_set_error(err, Validation, _("Message type must be an integer"));
|
||||
api_set_error(err, kErrorTypeValidation, "Message type must be an integer");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t type = req->via.array.ptr[0].via.u64;
|
||||
if (type != kMessageTypeRequest && type != kMessageTypeNotification) {
|
||||
api_set_error(err, Validation, _("Unknown message type"));
|
||||
api_set_error(err, kErrorTypeValidation, "Unknown message type");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((type == kMessageTypeRequest && req->via.array.size != 4)
|
||||
|| (type == kMessageTypeNotification && req->via.array.size != 3)) {
|
||||
api_set_error(err, Validation, _("Request array size should be 4 (request) "
|
||||
"or 3 (notification)"));
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Request array size must be 4 (request) or 3 (notification)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == kMessageTypeRequest) {
|
||||
msgpack_object *id_obj = msgpack_rpc_msg_id(req);
|
||||
if (!id_obj) {
|
||||
api_set_error(err, Validation, _("ID must be a positive integer"));
|
||||
api_set_error(err, kErrorTypeValidation, "ID must be a positive integer");
|
||||
return;
|
||||
}
|
||||
*response_id = id_obj->via.u64;
|
||||
}
|
||||
|
||||
if (!msgpack_rpc_method(req)) {
|
||||
api_set_error(err, Validation, _("Method must be a string"));
|
||||
api_set_error(err, kErrorTypeValidation, "Method must be a string");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!msgpack_rpc_args(req)) {
|
||||
api_set_error(err, Validation, _("Parameters must be an array"));
|
||||
api_set_error(err, kErrorTypeValidation, "Parameters must be an array");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
Reference in New Issue
Block a user