diff options
-rw-r--r-- | src/nvim/eval/vars.c | 56 | ||||
-rw-r--r-- | test/old/testdir/test_listdict.vim | 8 |
2 files changed, 29 insertions, 35 deletions
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index f988a49e6c..7ba751490b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1056,36 +1056,31 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { - if (list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_name, lp->ll_name_len, - lp->ll_n1, !lp->ll_empty2, lp->ll_n2) == FAIL) { - return FAIL; - } + tv_list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_n1, !lp->ll_empty2, lp->ll_n2); + } else if (lp->ll_list != NULL) { + // unlet a List item. + tv_list_item_remove(lp->ll_list, lp->ll_li); } else { - if (lp->ll_list != NULL) { - // unlet a List item. - tv_list_item_remove(lp->ll_list, lp->ll_li); - } else { - // unlet a Dictionary item. - dict_T *d = lp->ll_dict; - assert(d != NULL); - dictitem_T *di = lp->ll_di; - bool watched = tv_dict_is_watched(d); - char *key = NULL; - typval_T oldtv; + // unlet a Dictionary item. + dict_T *d = lp->ll_dict; + assert(d != NULL); + dictitem_T *di = lp->ll_di; + bool watched = tv_dict_is_watched(d); + char *key = NULL; + typval_T oldtv; - if (watched) { - tv_copy(&di->di_tv, &oldtv); - // need to save key because dictitem_remove will free it - key = xstrdup(di->di_key); - } + if (watched) { + tv_copy(&di->di_tv, &oldtv); + // need to save key because dictitem_remove will free it + key = xstrdup(di->di_key); + } - tv_dict_item_remove(d, di); + tv_dict_item_remove(d, di); - if (watched) { - tv_dict_watcher_notify(d, key, NULL, &oldtv); - tv_clear(&oldtv); - xfree(key); - } + if (watched) { + tv_dict_watcher_notify(d, key, NULL, &oldtv); + tv_clear(&oldtv); + xfree(key); } } @@ -1094,18 +1089,14 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ /// Unlet one item or a range of items from a list. /// Return OK or FAIL. -static int list_unlet_range(list_T *const l, listitem_T *const li_first, const char *const name, - const size_t name_len, const long n1_arg, const bool has_n2, - const long n2) +static void tv_list_unlet_range(list_T *const l, listitem_T *const li_first, const long n1_arg, + const bool has_n2, const long n2) { assert(l != NULL); // Delete a range of List items. listitem_T *li_last = li_first; long n1 = n1_arg; while (true) { - if (value_check_lock(TV_LIST_ITEM_TV(li_last)->v_lock, name, name_len)) { - return FAIL; - } listitem_T *const li = TV_LIST_ITEM_NEXT(l, li_last); n1++; if (li == NULL || (has_n2 && n2 < n1)) { @@ -1114,7 +1105,6 @@ static int list_unlet_range(list_T *const l, listitem_T *const li_first, const c li_last = li; } tv_list_remove_items(l, li_first, li_last); - return OK; } /// unlet a variable diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim index 1fc0c1e7d4..a33725cf5c 100644 --- a/test/old/testdir/test_listdict.vim +++ b/test/old/testdir/test_listdict.vim @@ -666,10 +666,14 @@ func Test_list_locked_var_unlet() call assert_equal(expected[depth][u][1], ps) endfor endfor - " Deleting a list range should fail if the range is locked + + " Deleting a list range with locked items works, but changing the items + " fails. let l = [1, 2, 3, 4] lockvar l[1:2] - call assert_fails('unlet l[1:2]', 'E741:') + call assert_fails('let l[1:2] = [8, 9]', 'E741:') + unlet l[1:2] + call assert_equal([1, 4], l) unlet l endfunc |