From d26b01d4bd42c7cf6fc455406b3cfd696465f652 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 4 Jan 2016 17:20:16 +0300 Subject: eval: Use better error messages when failing to dump values Examples: let g:SR = [[]] call add(g:SR[0], g:SR) wshada " E952: Unable to dump variable g:SR: container references itself in index 0, index 0 let g:F = {'_TYPE': v:msgpack_types.map, '_VAL': [[{'abc': 1}, function("tr")]]} wshada " E951: Error while dumping variable g:F, key {'abc': 1} at index 0 from special map, key '': attempt to dump function reference " (no msgpack#string available) " E951: Error while dumping variable g:F, key {="abc": 1} at index 0 from special map, key '': attempt to dump function reference " (msgpack#string available) let g:F = {'_TYPE': v:msgpack_types.map, '_VAL': [[g:SR, function("tr")]]} wshada " E951: Error while dumping variable g:F, key [[[[{E724@0}]]]] at index 0 from special map, index 1: attempt to dump function reference call msgpackdump([g:SR]) " E952: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0 Not tested yet. --- src/nvim/eval.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/nvim/eval.h | 3 +- src/nvim/shada.c | 39 ++++++++++------ 3 files changed, 147 insertions(+), 32 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b60886704e..5a8fe4076e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6479,7 +6479,8 @@ failret: static int name##_convert_one_value(firstargtype firstargname, \ MPConvStack *const mpstack, \ typval_T *const tv, \ - const int copyID) \ + const int copyID, \ + const char *const objname) \ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ { \ switch (tv->v_type) { \ @@ -6713,14 +6714,16 @@ name##_convert_one_value_regular_dict: \ 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 \ { \ current_copyID += COPYID_INC; \ const int copyID = current_copyID; \ MPConvStack 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; \ } \ 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; \ if (name##_convert_one_value(firstargname, &mpstack, \ - &kv_pair->lv_first->li_tv, copyID) \ - == FAIL) { \ + &kv_pair->lv_first->li_tv, copyID, \ + objname) == FAIL) { \ goto vim_to_msgpack_error_ret; \ } \ cur_tv = &kv_pair->lv_last->li_tv; \ @@ -6778,8 +6781,8 @@ scope int vim_to_##name(firstargtype firstargname, typval_T *const tv) \ break; \ } \ } \ - if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID) \ - == FAIL) { \ + if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \ + objname) == FAIL) { \ goto vim_to_msgpack_error_ret; \ } \ } \ @@ -6975,7 +6978,7 @@ static char *tv2string(typval_T *tv, size_t *len) { garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - vim_to_string(&ga, tv); + vim_to_string(&ga, tv, "tv2string() argument"); did_echo_string_emsg = false; if (len != NULL) { *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); } } else { - vim_to_echo(&ga, tv); + vim_to_echo(&ga, tv, ":echo argument"); did_echo_string_emsg = false; } if (len != NULL) { @@ -12686,6 +12689,100 @@ static inline bool vim_list_to_buf(const list_T *const list, 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; + trylevel++; + typval_T rettv; + int doesrange; + char *key; + bool free_key = false; + if (call_func((char_u *) "msgpack#string", + sizeof("msgpack#string") - 1, + &rettv, 1, &key_tv, 0L, 0L, &doesrange, true, + NULL) == FAIL + || ((key = (char *) get_tv_string(&rettv)) == NULL) + || did_throw + || (msg_list != NULL && *msg_list != NULL)) { + key = tv2string(&key_tv, NULL); + free_key = true; + } + did_emsg = false; + discard_current_exception(); + if (msg_list != NULL && *msg_list != NULL) { + free_global_msglist(); + } + trylevel--; + vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx); + clear_tv(&rettv); + if (free_key) { + 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) \ do { \ if (buf == NULL) { \ @@ -12726,10 +12823,9 @@ static inline bool vim_list_to_buf(const list_T *const list, msgpack_pack_double(packer, (double) (flt)) #define CONV_FUNC(fun) \ - do { \ - EMSG2(_(e_invarg2), "attempt to dump function reference"); \ - return FAIL; \ - } while (0) + return conv_error(_("E951: Error while dumping %s, %s: " \ + "attempt to dump function reference"), \ + mpstack, objname) #define CONV_EMPTY_LIST() \ msgpack_pack_array(packer, 0) @@ -12772,10 +12868,9 @@ static inline bool vim_list_to_buf(const list_T *const list, #define CONV_LIST_BETWEEN_ITEMS(lst) #define CONV_RECURSE(val, conv_type) \ - do { \ - EMSG2(_(e_invarg2), "container references itself"); \ - return FAIL; \ - } while (0) + return conv_error(_("E952: Unable to dump %s: " \ + "container references itself in %s"), \ + mpstack, objname) #define CONV_ALLOW_SPECIAL true @@ -12817,8 +12912,14 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv) return; } 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) { - 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; } } diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 19a1bbb083..ea8b5bc253 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -118,7 +118,8 @@ enum { /// Maximum number of function arguments #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 # include "eval.h.generated.h" diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 6a30472a7c..347bd8664c 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1684,17 +1684,18 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, msgpack_sbuffer sbuf; msgpack_sbuffer_init(&sbuf); msgpack_packer *spacker = msgpack_packer_new(&sbuf, &msgpack_sbuffer_write); -#define DUMP_ADDITIONAL_ELEMENTS(src) \ +#define DUMP_ADDITIONAL_ELEMENTS(src, what) \ do { \ if ((src) != NULL) { \ 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; \ } \ } \ } \ } while (0) -#define DUMP_ADDITIONAL_DATA(src) \ +#define DUMP_ADDITIONAL_DATA(src, what) \ do { \ dict_T *const d = (src); \ 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); \ msgpack_pack_str(spacker, 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; \ } \ } \ @@ -1741,7 +1743,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, if (is_hist_search) { 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; } case kSDItemVariable: { @@ -1750,14 +1753,20 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ? 0 : entry.data.global_var.additional_elements->lv_len); msgpack_pack_array(spacker, arr_size); - PACK_BIN(cstr_as_string(entry.data.global_var.name)); - if (vim_to_msgpack(spacker, &entry.data.global_var.value) == FAIL) { + const String varname = cstr_as_string(entry.data.global_var.name); + 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; EMSG2(_(WERR "Failed to write variable %s"), entry.data.global_var.name); 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; } case kSDItemSubString: { @@ -1767,7 +1776,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, : entry.data.sub_string.additional_elements->lv_len); msgpack_pack_array(spacker, arr_size); 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; } case kSDItemSearchPattern: { @@ -1814,7 +1824,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, msgpack_pack_int64(spacker, entry.data.search_pattern.offset); } #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; } case kSDItemChange: @@ -1849,7 +1860,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, PACK_STATIC_STR(KEY_NAME_CHAR); 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; } case kSDItemRegister: { @@ -1877,7 +1889,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, PACK_STATIC_STR(REG_KEY_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; } case kSDItemBufferList: { @@ -1908,7 +1920,8 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, msgpack_pack_uint64( 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; } -- cgit From efaf76e6238c7b109676575b41f637374f896cb8 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 6 Jan 2016 22:33:56 +0300 Subject: functests: Update tests --- test/functional/eval/msgpack_functions_spec.lua | 34 +++++++++++++++++-------- test/functional/plugin/msgpack_spec.lua | 24 +++++++++++++++++ test/functional/shada/errors_spec.lua | 4 +-- test/functional/shada/variables_spec.lua | 4 +-- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index da42fc9d26..4f2533f49d 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -541,27 +541,27 @@ describe('msgpackdump() function', function() it('fails to dump a function reference', function() 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])')) end) it('fails to dump a function reference in a list', function() 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])')) end) it('fails to dump a recursive list', function() execute('let 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])')) end) it('fails to dump a recursive dict', function() execute('let todump = {"d": {"d": {}}}') 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])')) end) @@ -580,21 +580,35 @@ describe('msgpackdump() function', function() it('fails to dump a recursive list in a special dict', function() execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') 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])')) end) 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])') - 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])')) end) 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])') - 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 [[[{E724@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])')) end) @@ -602,7 +616,7 @@ describe('msgpackdump() function', function() function() execute('let todump = {"_TYPE": v:msgpack_types.array, "_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])')) end) diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index 18ff0f5156..9cbfacd936 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -697,3 +697,27 @@ describe('In autoload/msgpack.vim', function() end) end) end) + +describe('msgpackdump() function', function() + before_each(reset) + + it('uses msgpack#string for dumping fref error messages for special map keys', function() + nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[{"_TYPE": v:msgpack_types.string, "_VAL": ["abc"]}, [function("tr")]]]}') + eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, key ="abc" at index 0 from special map, index 0: attempt to dump function reference', + exc_exec('call msgpackdump([todump])')) + end) + + it('falls back to using string() in case of error (fref)', function() + nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[function("tr")], []]]}') + nvim_command('call add(todump._VAL[0][0], todump._VAL[0][0])') + eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, key [function(\'tr\'), {E724@0}] at index 0 from special map, index 0: attempt to dump function reference', + exc_exec('call msgpackdump([todump])')) + end) + + it('falls back to using string() in case of error (recurse)', function() + nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') + nvim_command('call add(todump._VAL[0][0], todump._VAL[0][0])') + eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key [{E724@0}] at index 0 from special map, index 0', + exc_exec('call msgpackdump([todump])')) + end) +end) diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua index f6265bf24b..e7951ee74c 100644 --- a/test/functional/shada/errors_spec.lua +++ b/test/functional/shada/errors_spec.lua @@ -497,7 +497,7 @@ $ it('errors when a funcref is stored in a variable', function() nvim_command('let F = function("tr")') 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', redir_exec('wshada')) end) @@ -506,7 +506,7 @@ $ nvim_command('let L = []') nvim_command('call add(L, L)') 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', redir_exec('wshada')) end) diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua index 22054db353..3becf1bc32 100644 --- a/test/functional/shada/variables_spec.lua +++ b/test/functional/shada/variables_spec.lua @@ -143,7 +143,7 @@ describe('ShaDa support code', function() meths.set_var('U', '10') nvim_command('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')) meths.set_option('shada', '') reset() @@ -156,7 +156,7 @@ describe('ShaDa support code', function() nvim_command('call add(L, L)') meths.set_var('U', '10') 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')) meths.set_option('shada', '') set_additional_cmd('set shada+=!') -- cgit From bd4ca22cf06f832ccda432733498f00e0af77eaa Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 6 Jan 2016 22:40:23 +0300 Subject: documentation: Update documentation --- runtime/doc/eval.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 8864909e71..f70968de01 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4712,13 +4712,17 @@ msgpackdump({list}) {Nvim} *msgpackdump()* (dictionary with zero items is represented by 0x80 byte in messagepack). - Limitations: + Limitations: *E951* *E952* 1. |Funcref|s cannot be dumped. 2. Containers that reference themselves cannot be dumped. 3. Dictionary keys are always dumped as STR strings. 4. Other strings are always dumped as BIN strings. 5. Points 3. and 4. do not apply to |msgpack-special-dict|s. + Note: error messages may use |msgpack#string()| function for + showing where error occurred. In case it is not + available it falls back to |string()|. + msgpackparse({list}) {Nvim} *msgpackparse()* Convert a |readfile()|-style list to a list of VimL objects. Example: > -- cgit From c6f6033482015723742f97aeba95d0e65f694943 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 6 Jan 2016 22:47:39 +0300 Subject: eval: Do not use msgpack#string for error messages --- runtime/doc/eval.txt | 4 ---- src/nvim/eval.c | 27 ++----------------------- test/functional/eval/msgpack_functions_spec.lua | 2 +- test/functional/plugin/msgpack_spec.lua | 24 ---------------------- 4 files changed, 3 insertions(+), 54 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f70968de01..49afa15601 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4719,10 +4719,6 @@ msgpackdump({list}) {Nvim} *msgpackdump()* 4. Other strings are always dumped as BIN strings. 5. Points 3. and 4. do not apply to |msgpack-special-dict|s. - Note: error messages may use |msgpack#string()| function for - showing where error occurred. In case it is not - available it falls back to |string()|. - msgpackparse({list}) {Nvim} *msgpackparse()* Convert a |readfile()|-style list to a list of VimL objects. Example: > diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5a8fe4076e..57d7002739 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12744,32 +12744,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, ga_concat(&msg_ga, IObuff); } else { typval_T key_tv = li->li_tv.vval.v_list->lv_first->li_tv; - trylevel++; - typval_T rettv; - int doesrange; - char *key; - bool free_key = false; - if (call_func((char_u *) "msgpack#string", - sizeof("msgpack#string") - 1, - &rettv, 1, &key_tv, 0L, 0L, &doesrange, true, - NULL) == FAIL - || ((key = (char *) get_tv_string(&rettv)) == NULL) - || did_throw - || (msg_list != NULL && *msg_list != NULL)) { - key = tv2string(&key_tv, NULL); - free_key = true; - } - did_emsg = false; - discard_current_exception(); - if (msg_list != NULL && *msg_list != NULL) { - free_global_msglist(); - } - trylevel--; + char *const key = echo_string(&key_tv, NULL); vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx); - clear_tv(&rettv); - if (free_key) { - xfree(key); - } + xfree(key); ga_concat(&msg_ga, IObuff); } break; diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index 4f2533f49d..41b0faf76c 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -601,7 +601,7 @@ describe('msgpackdump() function', function() 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 [[[{E724@0}, []]]] at index 0 from special map, index 0', + 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) diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index 9cbfacd936..18ff0f5156 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -697,27 +697,3 @@ describe('In autoload/msgpack.vim', function() end) end) end) - -describe('msgpackdump() function', function() - before_each(reset) - - it('uses msgpack#string for dumping fref error messages for special map keys', function() - nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[{"_TYPE": v:msgpack_types.string, "_VAL": ["abc"]}, [function("tr")]]]}') - eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, key ="abc" at index 0 from special map, index 0: attempt to dump function reference', - exc_exec('call msgpackdump([todump])')) - end) - - it('falls back to using string() in case of error (fref)', function() - nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[function("tr")], []]]}') - nvim_command('call add(todump._VAL[0][0], todump._VAL[0][0])') - eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, key [function(\'tr\'), {E724@0}] at index 0 from special map, index 0: attempt to dump function reference', - exc_exec('call msgpackdump([todump])')) - end) - - it('falls back to using string() in case of error (recurse)', function() - nvim_command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') - nvim_command('call add(todump._VAL[0][0], todump._VAL[0][0])') - eq('Vim(call):E952: Unable to dump msgpackdump() argument, index 0: container references itself in key [{E724@0}] at index 0 from special map, index 0', - exc_exec('call msgpackdump([todump])')) - end) -end) -- cgit