mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	Merge pull request #3943 from ZyX-I/better-fref-error
eval: Use better error messages when failing to dump values
This commit is contained in:
		@@ -4712,7 +4712,7 @@ msgpackdump({list})				   {Nvim} *msgpackdump()*
 | 
				
			|||||||
		(dictionary with zero items is represented by 0x80 byte in
 | 
							(dictionary with zero items is represented by 0x80 byte in
 | 
				
			||||||
		messagepack).
 | 
							messagepack).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Limitations:
 | 
							Limitations:					*E951* *E952*
 | 
				
			||||||
		1. |Funcref|s cannot be dumped.
 | 
							1. |Funcref|s cannot be dumped.
 | 
				
			||||||
		2. Containers that reference themselves cannot be dumped.
 | 
							2. Containers that reference themselves cannot be dumped.
 | 
				
			||||||
		3. Dictionary keys are always dumped as STR strings.
 | 
							3. Dictionary keys are always dumped as STR strings.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										114
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							@@ -6479,7 +6479,8 @@ failret:
 | 
				
			|||||||
static int name##_convert_one_value(firstargtype firstargname, \
 | 
					static int name##_convert_one_value(firstargtype firstargname, \
 | 
				
			||||||
                                    MPConvStack *const mpstack, \
 | 
					                                    MPConvStack *const mpstack, \
 | 
				
			||||||
                                    typval_T *const tv, \
 | 
					                                    typval_T *const tv, \
 | 
				
			||||||
                                    const int copyID) \
 | 
					                                    const int copyID, \
 | 
				
			||||||
 | 
					                                    const char *const objname) \
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
 | 
					  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
 | 
				
			||||||
{ \
 | 
					{ \
 | 
				
			||||||
  switch (tv->v_type) { \
 | 
					  switch (tv->v_type) { \
 | 
				
			||||||
@@ -6713,14 +6714,16 @@ name##_convert_one_value_regular_dict: \
 | 
				
			|||||||
  return OK; \
 | 
					  return OK; \
 | 
				
			||||||
} \
 | 
					} \
 | 
				
			||||||
\
 | 
					\
 | 
				
			||||||
scope int vim_to_##name(firstargtype firstargname, typval_T *const tv) \
 | 
					scope int vim_to_##name(firstargtype firstargname, typval_T *const tv, \
 | 
				
			||||||
 | 
					                        const char *const objname) \
 | 
				
			||||||
  FUNC_ATTR_WARN_UNUSED_RESULT \
 | 
					  FUNC_ATTR_WARN_UNUSED_RESULT \
 | 
				
			||||||
{ \
 | 
					{ \
 | 
				
			||||||
  current_copyID += COPYID_INC; \
 | 
					  current_copyID += COPYID_INC; \
 | 
				
			||||||
  const int copyID = current_copyID; \
 | 
					  const int copyID = current_copyID; \
 | 
				
			||||||
  MPConvStack mpstack; \
 | 
					  MPConvStack mpstack; \
 | 
				
			||||||
  kv_init(mpstack); \
 | 
					  kv_init(mpstack); \
 | 
				
			||||||
  if (name##_convert_one_value(firstargname, &mpstack, tv, copyID) == FAIL) { \
 | 
					  if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \
 | 
				
			||||||
 | 
					      == FAIL) { \
 | 
				
			||||||
    goto vim_to_msgpack_error_ret; \
 | 
					    goto vim_to_msgpack_error_ret; \
 | 
				
			||||||
  } \
 | 
					  } \
 | 
				
			||||||
  while (kv_size(mpstack)) { \
 | 
					  while (kv_size(mpstack)) { \
 | 
				
			||||||
@@ -6769,8 +6772,8 @@ scope int vim_to_##name(firstargtype firstargname, typval_T *const tv) \
 | 
				
			|||||||
        } \
 | 
					        } \
 | 
				
			||||||
        const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \
 | 
					        const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \
 | 
				
			||||||
        if (name##_convert_one_value(firstargname, &mpstack, \
 | 
					        if (name##_convert_one_value(firstargname, &mpstack, \
 | 
				
			||||||
                                     &kv_pair->lv_first->li_tv, copyID) \
 | 
					                                     &kv_pair->lv_first->li_tv, copyID, \
 | 
				
			||||||
            == FAIL) { \
 | 
					                                     objname) == FAIL) { \
 | 
				
			||||||
          goto vim_to_msgpack_error_ret; \
 | 
					          goto vim_to_msgpack_error_ret; \
 | 
				
			||||||
        } \
 | 
					        } \
 | 
				
			||||||
        cur_tv = &kv_pair->lv_last->li_tv; \
 | 
					        cur_tv = &kv_pair->lv_last->li_tv; \
 | 
				
			||||||
@@ -6778,8 +6781,8 @@ scope int vim_to_##name(firstargtype firstargname, typval_T *const tv) \
 | 
				
			|||||||
        break; \
 | 
					        break; \
 | 
				
			||||||
      } \
 | 
					      } \
 | 
				
			||||||
    } \
 | 
					    } \
 | 
				
			||||||
    if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID) \
 | 
					    if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \
 | 
				
			||||||
        == FAIL) { \
 | 
					                                 objname) == FAIL) { \
 | 
				
			||||||
      goto vim_to_msgpack_error_ret; \
 | 
					      goto vim_to_msgpack_error_ret; \
 | 
				
			||||||
    } \
 | 
					    } \
 | 
				
			||||||
  } \
 | 
					  } \
 | 
				
			||||||
@@ -6975,7 +6978,7 @@ static char *tv2string(typval_T *tv, size_t *len)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  garray_T ga;
 | 
					  garray_T ga;
 | 
				
			||||||
  ga_init(&ga, (int)sizeof(char), 80);
 | 
					  ga_init(&ga, (int)sizeof(char), 80);
 | 
				
			||||||
  vim_to_string(&ga, tv);
 | 
					  vim_to_string(&ga, tv, "tv2string() argument");
 | 
				
			||||||
  did_echo_string_emsg = false;
 | 
					  did_echo_string_emsg = false;
 | 
				
			||||||
  if (len != NULL) {
 | 
					  if (len != NULL) {
 | 
				
			||||||
    *len = (size_t) ga.ga_len;
 | 
					    *len = (size_t) ga.ga_len;
 | 
				
			||||||
@@ -7001,7 +7004,7 @@ static char *echo_string(typval_T *tv, size_t *len)
 | 
				
			|||||||
      ga_concat(&ga, tv->vval.v_string);
 | 
					      ga_concat(&ga, tv->vval.v_string);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    vim_to_echo(&ga, tv);
 | 
					    vim_to_echo(&ga, tv, ":echo argument");
 | 
				
			||||||
    did_echo_string_emsg = false;
 | 
					    did_echo_string_emsg = false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (len != NULL) {
 | 
					  if (len != NULL) {
 | 
				
			||||||
@@ -12686,6 +12689,77 @@ static inline bool vim_list_to_buf(const list_T *const list,
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Show a error message when converting to msgpack value
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @param[in]  msg  Error message to dump. Must contain exactly two %s that
 | 
				
			||||||
 | 
					///                  will be replaced with what was being dumped: first with
 | 
				
			||||||
 | 
					///                  something like “F” or “function argument”, second with path
 | 
				
			||||||
 | 
					///                  to the failed value.
 | 
				
			||||||
 | 
					/// @param[in]  mpstack  Path to the failed value.
 | 
				
			||||||
 | 
					/// @param[in]  objname  Dumped object name.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @return FAIL.
 | 
				
			||||||
 | 
					static int conv_error(const char *const msg, const MPConvStack *const mpstack,
 | 
				
			||||||
 | 
					                      const char *const objname)
 | 
				
			||||||
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  garray_T msg_ga;
 | 
				
			||||||
 | 
					  ga_init(&msg_ga, (int)sizeof(char), 80);
 | 
				
			||||||
 | 
					  char *const key_msg = _("key %s");
 | 
				
			||||||
 | 
					  char *const key_pair_msg = _("key %s at index %i from special map");
 | 
				
			||||||
 | 
					  char *const idx_msg = _("index %i");
 | 
				
			||||||
 | 
					  for (size_t i = 0; i < kv_size(*mpstack); i++) {
 | 
				
			||||||
 | 
					    if (i != 0) {
 | 
				
			||||||
 | 
					      ga_concat(&msg_ga, (char_u *) ", ");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    MPConvStackVal v = kv_A(*mpstack, i);
 | 
				
			||||||
 | 
					    switch (v.type) {
 | 
				
			||||||
 | 
					      case kMPConvDict: {
 | 
				
			||||||
 | 
					        typval_T key_tv = {
 | 
				
			||||||
 | 
					            .v_type = VAR_STRING,
 | 
				
			||||||
 | 
					            .vval = { .v_string = (v.data.d.hi == NULL
 | 
				
			||||||
 | 
					                                   ? v.data.d.dict->dv_hashtab.ht_array
 | 
				
			||||||
 | 
					                                   : (v.data.d.hi - 1))->hi_key },
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        char *const key = tv2string(&key_tv, NULL);
 | 
				
			||||||
 | 
					        vim_snprintf((char *) IObuff, IOSIZE, key_msg, key);
 | 
				
			||||||
 | 
					        xfree(key);
 | 
				
			||||||
 | 
					        ga_concat(&msg_ga, IObuff);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      case kMPConvPairs:
 | 
				
			||||||
 | 
					      case kMPConvList: {
 | 
				
			||||||
 | 
					        int idx = 0;
 | 
				
			||||||
 | 
					        const listitem_T *li;
 | 
				
			||||||
 | 
					        for (li = v.data.l.list->lv_first;
 | 
				
			||||||
 | 
					             li != NULL && li->li_next != v.data.l.li;
 | 
				
			||||||
 | 
					             li = li->li_next) {
 | 
				
			||||||
 | 
					          idx++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (v.type == kMPConvList
 | 
				
			||||||
 | 
					            || li == NULL
 | 
				
			||||||
 | 
					            || (li->li_tv.v_type != VAR_LIST
 | 
				
			||||||
 | 
					                && li->li_tv.vval.v_list->lv_len <= 0)) {
 | 
				
			||||||
 | 
					          vim_snprintf((char *) IObuff, IOSIZE, idx_msg, idx);
 | 
				
			||||||
 | 
					          ga_concat(&msg_ga, IObuff);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          typval_T key_tv = li->li_tv.vval.v_list->lv_first->li_tv;
 | 
				
			||||||
 | 
					          char *const key = echo_string(&key_tv, NULL);
 | 
				
			||||||
 | 
					          vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx);
 | 
				
			||||||
 | 
					          xfree(key);
 | 
				
			||||||
 | 
					          ga_concat(&msg_ga, IObuff);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  EMSG3(msg, objname, (kv_size(*mpstack) == 0
 | 
				
			||||||
 | 
					                       ? _("itself")
 | 
				
			||||||
 | 
					                       : (char *) msg_ga.ga_data));
 | 
				
			||||||
 | 
					  ga_clear(&msg_ga);
 | 
				
			||||||
 | 
					  return FAIL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONV_STRING(buf, len) \
 | 
					#define CONV_STRING(buf, len) \
 | 
				
			||||||
    do { \
 | 
					    do { \
 | 
				
			||||||
      if (buf == NULL) { \
 | 
					      if (buf == NULL) { \
 | 
				
			||||||
@@ -12726,10 +12800,9 @@ static inline bool vim_list_to_buf(const list_T *const list,
 | 
				
			|||||||
    msgpack_pack_double(packer, (double) (flt))
 | 
					    msgpack_pack_double(packer, (double) (flt))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONV_FUNC(fun) \
 | 
					#define CONV_FUNC(fun) \
 | 
				
			||||||
    do { \
 | 
					    return conv_error(_("E951: Error while dumping %s, %s: " \
 | 
				
			||||||
      EMSG2(_(e_invarg2), "attempt to dump function reference"); \
 | 
					                        "attempt to dump function reference"), \
 | 
				
			||||||
      return FAIL; \
 | 
					                      mpstack, objname)
 | 
				
			||||||
    } while (0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONV_EMPTY_LIST() \
 | 
					#define CONV_EMPTY_LIST() \
 | 
				
			||||||
    msgpack_pack_array(packer, 0)
 | 
					    msgpack_pack_array(packer, 0)
 | 
				
			||||||
@@ -12772,10 +12845,9 @@ static inline bool vim_list_to_buf(const list_T *const list,
 | 
				
			|||||||
#define CONV_LIST_BETWEEN_ITEMS(lst)
 | 
					#define CONV_LIST_BETWEEN_ITEMS(lst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONV_RECURSE(val, conv_type) \
 | 
					#define CONV_RECURSE(val, conv_type) \
 | 
				
			||||||
    do { \
 | 
					    return conv_error(_("E952: Unable to dump %s: " \
 | 
				
			||||||
      EMSG2(_(e_invarg2), "container references itself"); \
 | 
					                        "container references itself in %s"), \
 | 
				
			||||||
      return FAIL; \
 | 
					                      mpstack, objname)
 | 
				
			||||||
    } while (0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONV_ALLOW_SPECIAL true
 | 
					#define CONV_ALLOW_SPECIAL true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12817,8 +12889,14 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv)
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  msgpack_packer *lpacker = msgpack_packer_new(ret_list, &msgpack_list_write);
 | 
					  msgpack_packer *lpacker = msgpack_packer_new(ret_list, &msgpack_list_write);
 | 
				
			||||||
 | 
					  const char *const msg = _("msgpackdump() argument, index %i");
 | 
				
			||||||
 | 
					  // Assume that translation will not take more then 4 times more space
 | 
				
			||||||
 | 
					  char msgbuf[sizeof("msgpackdump() argument, index ") * 4 + NUMBUFLEN];
 | 
				
			||||||
 | 
					  int idx = 0;
 | 
				
			||||||
  for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) {
 | 
					  for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) {
 | 
				
			||||||
    if (vim_to_msgpack(lpacker, &li->li_tv) == FAIL) {
 | 
					    vim_snprintf(msgbuf, sizeof(msgbuf), (char *) msg, idx);
 | 
				
			||||||
 | 
					    idx++;
 | 
				
			||||||
 | 
					    if (vim_to_msgpack(lpacker, &li->li_tv, msgbuf) == FAIL) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,7 +118,8 @@ enum {
 | 
				
			|||||||
/// Maximum number of function arguments
 | 
					/// Maximum number of function arguments
 | 
				
			||||||
#define MAX_FUNC_ARGS   20
 | 
					#define MAX_FUNC_ARGS   20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int vim_to_msgpack(msgpack_packer *const, typval_T *const);
 | 
					int vim_to_msgpack(msgpack_packer *const, typval_T *const,
 | 
				
			||||||
 | 
					                   const char *const objname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "eval.h.generated.h"
 | 
					# include "eval.h.generated.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1684,17 +1684,18 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
  msgpack_sbuffer sbuf;
 | 
					  msgpack_sbuffer sbuf;
 | 
				
			||||||
  msgpack_sbuffer_init(&sbuf);
 | 
					  msgpack_sbuffer_init(&sbuf);
 | 
				
			||||||
  msgpack_packer *spacker = msgpack_packer_new(&sbuf, &msgpack_sbuffer_write);
 | 
					  msgpack_packer *spacker = msgpack_packer_new(&sbuf, &msgpack_sbuffer_write);
 | 
				
			||||||
#define DUMP_ADDITIONAL_ELEMENTS(src) \
 | 
					#define DUMP_ADDITIONAL_ELEMENTS(src, what) \
 | 
				
			||||||
  do { \
 | 
					  do { \
 | 
				
			||||||
    if ((src) != NULL) { \
 | 
					    if ((src) != NULL) { \
 | 
				
			||||||
      for (listitem_T *li = (src)->lv_first; li != NULL; li = li->li_next) { \
 | 
					      for (listitem_T *li = (src)->lv_first; li != NULL; li = li->li_next) { \
 | 
				
			||||||
        if (vim_to_msgpack(spacker, &li->li_tv) == FAIL) { \
 | 
					        if (vim_to_msgpack(spacker, &li->li_tv, \
 | 
				
			||||||
 | 
					                           _("additional elements of ShaDa " what)) == FAIL) { \
 | 
				
			||||||
          goto shada_pack_entry_error; \
 | 
					          goto shada_pack_entry_error; \
 | 
				
			||||||
        } \
 | 
					        } \
 | 
				
			||||||
      } \
 | 
					      } \
 | 
				
			||||||
    } \
 | 
					    } \
 | 
				
			||||||
  } while (0)
 | 
					  } while (0)
 | 
				
			||||||
#define DUMP_ADDITIONAL_DATA(src) \
 | 
					#define DUMP_ADDITIONAL_DATA(src, what) \
 | 
				
			||||||
  do { \
 | 
					  do { \
 | 
				
			||||||
    dict_T *const d = (src); \
 | 
					    dict_T *const d = (src); \
 | 
				
			||||||
    if (d != NULL) { \
 | 
					    if (d != NULL) { \
 | 
				
			||||||
@@ -1706,7 +1707,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
          const size_t key_len = strlen((const char *) hi->hi_key); \
 | 
					          const size_t key_len = strlen((const char *) hi->hi_key); \
 | 
				
			||||||
          msgpack_pack_str(spacker, key_len); \
 | 
					          msgpack_pack_str(spacker, key_len); \
 | 
				
			||||||
          msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \
 | 
					          msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \
 | 
				
			||||||
          if (vim_to_msgpack(spacker, &di->di_tv) == FAIL) { \
 | 
					          if (vim_to_msgpack(spacker, &di->di_tv, \
 | 
				
			||||||
 | 
					                             _("additional data of ShaDa " what)) == FAIL) { \
 | 
				
			||||||
            goto shada_pack_entry_error; \
 | 
					            goto shada_pack_entry_error; \
 | 
				
			||||||
          } \
 | 
					          } \
 | 
				
			||||||
        } \
 | 
					        } \
 | 
				
			||||||
@@ -1741,7 +1743,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
      if (is_hist_search) {
 | 
					      if (is_hist_search) {
 | 
				
			||||||
        msgpack_pack_uint8(spacker, (uint8_t) entry.data.history_item.sep);
 | 
					        msgpack_pack_uint8(spacker, (uint8_t) entry.data.history_item.sep);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements);
 | 
					      DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements,
 | 
				
			||||||
 | 
					                               "history entry item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemVariable: {
 | 
					    case kSDItemVariable: {
 | 
				
			||||||
@@ -1750,14 +1753,20 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
          ? 0
 | 
					          ? 0
 | 
				
			||||||
          : entry.data.global_var.additional_elements->lv_len);
 | 
					          : entry.data.global_var.additional_elements->lv_len);
 | 
				
			||||||
      msgpack_pack_array(spacker, arr_size);
 | 
					      msgpack_pack_array(spacker, arr_size);
 | 
				
			||||||
      PACK_BIN(cstr_as_string(entry.data.global_var.name));
 | 
					      const String varname = cstr_as_string(entry.data.global_var.name);
 | 
				
			||||||
      if (vim_to_msgpack(spacker, &entry.data.global_var.value) == FAIL) {
 | 
					      PACK_BIN(varname);
 | 
				
			||||||
 | 
					      char vardesc[256] = "variable g:";
 | 
				
			||||||
 | 
					      memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
 | 
				
			||||||
 | 
					             varname.size + 1);
 | 
				
			||||||
 | 
					      if (vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc)
 | 
				
			||||||
 | 
					          == FAIL) {
 | 
				
			||||||
        ret = kSDWriteIgnError;
 | 
					        ret = kSDWriteIgnError;
 | 
				
			||||||
        EMSG2(_(WERR "Failed to write variable %s"),
 | 
					        EMSG2(_(WERR "Failed to write variable %s"),
 | 
				
			||||||
              entry.data.global_var.name);
 | 
					              entry.data.global_var.name);
 | 
				
			||||||
        goto shada_pack_entry_error;
 | 
					        goto shada_pack_entry_error;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements);
 | 
					      DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements,
 | 
				
			||||||
 | 
					                               "variable item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemSubString: {
 | 
					    case kSDItemSubString: {
 | 
				
			||||||
@@ -1767,7 +1776,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
          : entry.data.sub_string.additional_elements->lv_len);
 | 
					          : entry.data.sub_string.additional_elements->lv_len);
 | 
				
			||||||
      msgpack_pack_array(spacker, arr_size);
 | 
					      msgpack_pack_array(spacker, arr_size);
 | 
				
			||||||
      PACK_BIN(cstr_as_string(entry.data.sub_string.sub));
 | 
					      PACK_BIN(cstr_as_string(entry.data.sub_string.sub));
 | 
				
			||||||
      DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements);
 | 
					      DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements,
 | 
				
			||||||
 | 
					                               "sub string item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemSearchPattern: {
 | 
					    case kSDItemSearchPattern: {
 | 
				
			||||||
@@ -1814,7 +1824,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
        msgpack_pack_int64(spacker, entry.data.search_pattern.offset);
 | 
					        msgpack_pack_int64(spacker, entry.data.search_pattern.offset);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
#undef PACK_BOOL
 | 
					#undef PACK_BOOL
 | 
				
			||||||
      DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data);
 | 
					      DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data,
 | 
				
			||||||
 | 
					                           "search pattern item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemChange:
 | 
					    case kSDItemChange:
 | 
				
			||||||
@@ -1849,7 +1860,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
        PACK_STATIC_STR(KEY_NAME_CHAR);
 | 
					        PACK_STATIC_STR(KEY_NAME_CHAR);
 | 
				
			||||||
        msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name);
 | 
					        msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data);
 | 
					      DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data,
 | 
				
			||||||
 | 
					                           "mark (change, jump, global or local) item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemRegister: {
 | 
					    case kSDItemRegister: {
 | 
				
			||||||
@@ -1877,7 +1889,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
        PACK_STATIC_STR(REG_KEY_WIDTH);
 | 
					        PACK_STATIC_STR(REG_KEY_WIDTH);
 | 
				
			||||||
        msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width);
 | 
					        msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data);
 | 
					      DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item");
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case kSDItemBufferList: {
 | 
					    case kSDItemBufferList: {
 | 
				
			||||||
@@ -1908,7 +1920,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
 | 
				
			|||||||
          msgpack_pack_uint64(
 | 
					          msgpack_pack_uint64(
 | 
				
			||||||
              spacker, (uint64_t) entry.data.buffer_list.buffers[i].pos.col);
 | 
					              spacker, (uint64_t) entry.data.buffer_list.buffers[i].pos.col);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data);
 | 
					        DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data,
 | 
				
			||||||
 | 
					                             "buffer list subitem");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -541,27 +541,27 @@ describe('msgpackdump() function', function()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a function reference', function()
 | 
					  it('fails to dump a function reference', function()
 | 
				
			||||||
    execute('let Todump = function("tr")')
 | 
					    execute('let Todump = function("tr")')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: attempt to dump function reference',
 | 
					    eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
 | 
				
			||||||
       exc_exec('call msgpackdump([Todump])'))
 | 
					       exc_exec('call msgpackdump([Todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a function reference in a list', function()
 | 
					  it('fails to dump a function reference in a list', function()
 | 
				
			||||||
    execute('let todump = [function("tr")]')
 | 
					    execute('let todump = [function("tr")]')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: attempt to dump function reference',
 | 
					    eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a recursive list', function()
 | 
					  it('fails to dump a recursive list', function()
 | 
				
			||||||
    execute('let todump = [[[]]]')
 | 
					    execute('let todump = [[[]]]')
 | 
				
			||||||
    execute('call add(todump[0][0], todump)')
 | 
					    execute('call add(todump[0][0], todump)')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0, index 0',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a recursive dict', function()
 | 
					  it('fails to dump a recursive dict', function()
 | 
				
			||||||
    execute('let todump = {"d": {"d": {}}}')
 | 
					    execute('let todump = {"d": {"d": {}}}')
 | 
				
			||||||
    execute('call extend(todump.d.d, {"d": todump})')
 | 
					    execute('call extend(todump.d.d, {"d": todump})')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key \'d\', key \'d\', key \'d\'',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -580,21 +580,35 @@ describe('msgpackdump() function', function()
 | 
				
			|||||||
  it('fails to dump a recursive list in a special dict', function()
 | 
					  it('fails to dump a recursive list in a special dict', function()
 | 
				
			||||||
    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
				
			||||||
    execute('call add(todump._VAL, todump)')
 | 
					    execute('call add(todump._VAL, todump)')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a recursive (key) map in a special dict', function()
 | 
					  it('fails to dump a recursive (key) map in a special dict', function()
 | 
				
			||||||
    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
 | 
				
			||||||
    execute('call add(todump._VAL, [todump, 0])')
 | 
					    execute('call add(todump._VAL, [todump, 0])')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in index 1',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('fails to dump a recursive (val) map in a special dict', function()
 | 
					  it('fails to dump a recursive (val) map in a special dict', function()
 | 
				
			||||||
    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
 | 
				
			||||||
    execute('call add(todump._VAL, [0, todump])')
 | 
					    execute('call add(todump._VAL, [0, todump])')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key 0 at index 0 from special map',
 | 
				
			||||||
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('fails to dump a recursive (key) map in a special dict, _VAL reference', function()
 | 
				
			||||||
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
 | 
				
			||||||
 | 
					    execute('call add(todump._VAL[0][0], todump._VAL)')
 | 
				
			||||||
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key [[[[...@0], []]]] at index 0 from special map, index 0',
 | 
				
			||||||
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('fails to dump a recursive (val) map in a special dict, _VAL reference', function()
 | 
				
			||||||
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
 | 
				
			||||||
 | 
					    execute('call add(todump._VAL[0][1], todump._VAL)')
 | 
				
			||||||
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key [] at index 0 from special map, index 0',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -602,7 +616,7 @@ describe('msgpackdump() function', function()
 | 
				
			|||||||
  function()
 | 
					  function()
 | 
				
			||||||
    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
					    execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
 | 
				
			||||||
    execute('call add(todump._VAL, [0, todump._VAL])')
 | 
					    execute('call add(todump._VAL, [0, todump._VAL])')
 | 
				
			||||||
    eq('Vim(call):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 1',
 | 
				
			||||||
       exc_exec('call msgpackdump([todump])'))
 | 
					       exc_exec('call msgpackdump([todump])'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -497,7 +497,7 @@ $
 | 
				
			|||||||
  it('errors when a funcref is stored in a variable', function()
 | 
					  it('errors when a funcref is stored in a variable', function()
 | 
				
			||||||
    nvim_command('let F = function("tr")')
 | 
					    nvim_command('let F = function("tr")')
 | 
				
			||||||
    nvim_command('set shada+=!')
 | 
					    nvim_command('set shada+=!')
 | 
				
			||||||
    eq('\nE475: Invalid argument: attempt to dump function reference'
 | 
					    eq('\nE951: Error while dumping variable g:F, itself: attempt to dump function reference'
 | 
				
			||||||
       .. '\nE574: Failed to write variable F',
 | 
					       .. '\nE574: Failed to write variable F',
 | 
				
			||||||
       redir_exec('wshada'))
 | 
					       redir_exec('wshada'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
@@ -506,7 +506,7 @@ $
 | 
				
			|||||||
    nvim_command('let L = []')
 | 
					    nvim_command('let L = []')
 | 
				
			||||||
    nvim_command('call add(L, L)')
 | 
					    nvim_command('call add(L, L)')
 | 
				
			||||||
    nvim_command('set shada+=!')
 | 
					    nvim_command('set shada+=!')
 | 
				
			||||||
    eq('\nE475: Invalid argument: container references itself'
 | 
					    eq('\nE952: Unable to dump variable g:L: container references itself in index 0'
 | 
				
			||||||
       .. '\nE574: Failed to write variable L',
 | 
					       .. '\nE574: Failed to write variable L',
 | 
				
			||||||
       redir_exec('wshada'))
 | 
					       redir_exec('wshada'))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,7 +143,7 @@ describe('ShaDa support code', function()
 | 
				
			|||||||
    meths.set_var('U', '10')
 | 
					    meths.set_var('U', '10')
 | 
				
			||||||
    nvim_command('set shada+=!')
 | 
					    nvim_command('set shada+=!')
 | 
				
			||||||
    set_additional_cmd('set shada+=!')
 | 
					    set_additional_cmd('set shada+=!')
 | 
				
			||||||
    eq('Vim(wshada):E475: Invalid argument: attempt to dump function reference',
 | 
					    eq('Vim(wshada):E951: Error while dumping variable g:F, itself: attempt to dump function reference',
 | 
				
			||||||
       exc_exec('wshada'))
 | 
					       exc_exec('wshada'))
 | 
				
			||||||
    meths.set_option('shada', '')
 | 
					    meths.set_option('shada', '')
 | 
				
			||||||
    reset()
 | 
					    reset()
 | 
				
			||||||
@@ -156,7 +156,7 @@ describe('ShaDa support code', function()
 | 
				
			|||||||
    nvim_command('call add(L, L)')
 | 
					    nvim_command('call add(L, L)')
 | 
				
			||||||
    meths.set_var('U', '10')
 | 
					    meths.set_var('U', '10')
 | 
				
			||||||
    nvim_command('set shada+=!')
 | 
					    nvim_command('set shada+=!')
 | 
				
			||||||
    eq('Vim(wshada):E475: Invalid argument: container references itself',
 | 
					    eq('Vim(wshada):E952: Unable to dump variable g:L: container references itself in index 0',
 | 
				
			||||||
       exc_exec('wshada'))
 | 
					       exc_exec('wshada'))
 | 
				
			||||||
    meths.set_option('shada', '')
 | 
					    meths.set_option('shada', '')
 | 
				
			||||||
    set_additional_cmd('set shada+=!')
 | 
					    set_additional_cmd('set shada+=!')
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user