To: vim_dev@googlegroups.com Subject: Patch 8.2.0619 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0619 Problem: Null dict is not handled like an empty dict. Solution: Fix the code and add tests. (Yegappan Lakshmanan, closes #5968) Files: src/dict.c, src/eval.c, src/testdir/test_blob.vim, src/testdir/test_expr.vim, src/testdir/test_filter_map.vim, src/testdir/test_let.vim, src/testdir/test_listdict.vim, src/testdir/test_search.vim, src/testdir/test_unlet.vim, src/testdir/test_usercommands.vim, src/testdir/test_vimscript.vim *** ../vim-8.2.0618/src/dict.c 2020-03-28 19:41:29.595765241 +0100 --- src/dict.c 2020-04-23 13:01:08.432900291 +0200 *************** *** 977,990 **** dictitem_T *item2; int todo; - if (d1 == NULL && d2 == NULL) - return TRUE; - if (d1 == NULL || d2 == NULL) - return FALSE; if (d1 == d2) return TRUE; if (dict_len(d1) != dict_len(d2)) return FALSE; todo = (int)d1->dv_hashtab.ht_used; for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) --- 977,991 ---- dictitem_T *item2; int todo; if (d1 == d2) return TRUE; if (dict_len(d1) != dict_len(d2)) return FALSE; + if (dict_len(d1) == 0) + // empty and NULL dicts are considered equal + return TRUE; + if (d1 == NULL || d2 == NULL) + return FALSE; todo = (int)d1->dv_hashtab.ht_used; for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) *** ../vim-8.2.0618/src/eval.c 2020-04-22 19:13:16.043410511 +0200 --- src/eval.c 2020-04-23 13:15:55.054069438 +0200 *************** *** 871,877 **** --- 871,880 ---- if (len != -1) key[len] = prevval; if (wrong) + { + clear_tv(&var1); return NULL; + } } if (lp->ll_di == NULL) *************** *** 4553,4560 **** case VAR_DICT: if (tv->vval.v_dict == NULL) { *tofree = NULL; ! r = NULL; } else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID && tv->vval.v_dict->dv_hashtab.ht_used != 0) --- 4556,4564 ---- case VAR_DICT: if (tv->vval.v_dict == NULL) { + // NULL dict is equivalent to empty dict. *tofree = NULL; ! r = (char_u *)"{}"; } else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID && tv->vval.v_dict->dv_hashtab.ht_used != 0) *************** *** 4565,4570 **** --- 4569,4575 ---- else { int old_copyID = tv->vval.v_dict->dv_copyID; + tv->vval.v_dict->dv_copyID = copyID; *tofree = dict2string(tv, copyID, restore_copyID); if (restore_copyID) *** ../vim-8.2.0618/src/testdir/test_blob.vim 2020-04-21 22:19:26.055486850 +0200 --- src/testdir/test_blob.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 207,212 **** --- 207,213 ---- call assert_equal(0z001122, b) call add(b, '51') call assert_equal(0z00112233, b) + call assert_equal(1, add(test_null_blob(), 0x22)) call assert_fails('call add(b, [9])', 'E745:') call assert_fails('call add("", 0x01)', 'E897:') *** ../vim-8.2.0618/src/testdir/test_expr.vim 2020-04-20 16:49:56.705830066 +0200 --- src/testdir/test_expr.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 96,108 **** endfor endfunc - func Test_compare_null_dict() - call assert_fails('let x = test_null_dict()[10]') - call assert_equal({}, {}) - call assert_equal(test_null_dict(), test_null_dict()) - call assert_notequal({}, test_null_dict()) - endfunc - func Test_set_reg_null_list() call setreg('x', test_null_list()) endfunc --- 96,101 ---- *** ../vim-8.2.0618/src/testdir/test_filter_map.vim 2020-04-20 16:49:56.705830066 +0200 --- src/testdir/test_filter_map.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 96,101 **** --- 96,102 ---- call assert_fails("let l = filter('abc', '\"> \" . v:val')", 'E712:') call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:') call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:') + call assert_fails("let l = filter([1, 2], {})", 'E731:') call assert_equal(0, map(test_null_list(), '"> " .. v:val')) call assert_equal(0, map(test_null_dict(), '"> " .. v:val')) endfunc *** ../vim-8.2.0618/src/testdir/test_let.vim 2020-03-20 18:20:47.080975621 +0100 --- src/testdir/test_let.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 274,279 **** --- 274,280 ---- call assert_fails('let &buftype[1] = "nofile"', 'E18:') let s = "var" let var = 1 + call assert_fails('let var += [1,2]', 'E734:') call assert_fails('let {s}.1 = 2', 'E18:') call assert_fails('let a[1] = 5', 'E121:') let l = [[1,2]] *************** *** 286,291 **** --- 287,294 ---- call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:') call assert_fails('let l[-2:-3] = [3, 4]', 'E684:') call assert_fails('let l[0:4] = [5, 6]', 'E711:') + call assert_fails('let g:["a;b"] = 10', 'E461:') + call assert_fails('let g:.min = function("max")', 'E704:') " This test works only when the language is English if v:lang == "C" || v:lang =~ '^[Ee]n' *** ../vim-8.2.0618/src/testdir/test_listdict.vim 2020-04-20 16:49:56.705830066 +0200 --- src/testdir/test_listdict.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 32,38 **** call assert_equal([1, 'as''d', [1, 2, function('strlen')], {'a': 1}], l[0:8]) call assert_equal([], l[8:-1]) call assert_equal([], l[0:-10]) ! call assert_equal([], test_null_list()[:2]) endfunc " List identity --- 32,42 ---- call assert_equal([1, 'as''d', [1, 2, function('strlen')], {'a': 1}], l[0:8]) call assert_equal([], l[8:-1]) call assert_equal([], l[0:-10]) ! " perform an operation on a list slice ! let l = [1, 2, 3] ! let l[:1] += [1, 2] ! let l[2:] -= [1] ! call assert_equal([2, 4, 2], l) endfunc " List identity *************** *** 147,152 **** --- 151,170 ---- call assert_fails("call remove(l, l)", 'E745:') endfunc + " List add() function + func Test_list_add() + let l = [] + call add(l, 1) + call add(l, [2, 3]) + call add(l, []) + call add(l, test_null_list()) + call add(l, {'k' : 3}) + call add(l, {}) + call add(l, test_null_dict()) + call assert_equal([1, [2, 3], [], [], {'k' : 3}, {}, {}], l) + call assert_equal(1, add(test_null_list(), 4)) + endfunc + " Tests for Dictionary type func Test_dict() *************** *** 529,534 **** --- 547,561 ---- call assert_equal({'a': 99, 'b': 100}, d) endfunc + " Cannot use += with a locked dick + func Test_dict_lock_operator() + unlet! d + let d = {} + lockvar d + call assert_fails("let d += {'k' : 10}", 'E741:') + unlockvar d + endfunc + " No remove() of write-protected scope-level variable func Tfunc1(this_is_a_long_parameter_name) call assert_fails("call remove(a:, 'this_is_a_long_parameter_name')", 'E742') *************** *** 651,658 **** call assert_fails("call sort([1, 2], function('min'), 1)", "E715:") call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:") call assert_fails("call sort([1, 2], function('min'))", "E702:") - call assert_equal(0, sort(test_null_list())) - call assert_equal(0, uniq(test_null_list())) endfunc " splitting a string to a List using split() --- 678,683 ---- *************** *** 896,918 **** call assert_fails("let l = insert([1,2,3], 4, 10)", 'E684:') call assert_fails("let l = insert([1,2,3], 4, -10)", 'E684:') call assert_fails("let l = insert([1,2,3], 4, [])", 'E745:') endfunc " Test for a null list func Test_null_list() ! call assert_equal(0, join(test_null_list())) call assert_fails('let s = join([1, 2], [])', 'E730:') call assert_equal([], split(test_null_string())) endfunc " Test for a null dict func Test_null_dict() ! call assert_equal(0, items(test_null_dict())) ! call assert_equal(0, keys(test_null_dict())) ! call assert_equal(0, values(test_null_dict())) ! call assert_false(has_key(test_null_dict(), 'k')) ! call assert_fails("let l = [] + test_null_list()", 'E15:') ! call assert_fails("let l = test_null_list() + []", 'E15:') endfunc " vim: shiftwidth=2 sts=2 expandtab --- 921,964 ---- call assert_fails("let l = insert([1,2,3], 4, 10)", 'E684:') call assert_fails("let l = insert([1,2,3], 4, -10)", 'E684:') call assert_fails("let l = insert([1,2,3], 4, [])", 'E745:') + let l = [1, 2, 3] + call assert_fails("let l[i] = 3", 'E121:') + call assert_fails("let l[1.1] = 4", 'E806:') + call assert_fails("let l[:i] = [4, 5]", 'E121:') + call assert_fails("let l[:3.2] = [4, 5]", 'E806:') endfunc " Test for a null list func Test_null_list() ! let l = test_null_list() ! call assert_equal(0, join(l)) ! call assert_equal(0, len(l)) ! call assert_equal(1, empty(l)) call assert_fails('let s = join([1, 2], [])', 'E730:') call assert_equal([], split(test_null_string())) + call assert_equal([], l[:2]) + call assert_true([] == l) + call assert_equal('[]', string(l)) + call assert_equal(0, sort(l)) + call assert_equal(0, uniq(l)) + call assert_fails("let k = [] + l", 'E15:') + call assert_fails("let k = l + []", 'E15:') endfunc " Test for a null dict func Test_null_dict() ! call assert_equal(test_null_dict(), test_null_dict()) ! let d = test_null_dict() ! call assert_equal({}, d) ! call assert_equal(0, len(d)) ! call assert_equal(1, empty(d)) ! call assert_equal(0, items(d)) ! call assert_equal(0, keys(d)) ! call assert_equal(0, values(d)) ! call assert_false(has_key(d, 'k')) ! call assert_equal('{}', string(d)) ! call assert_fails('let x = test_null_dict()[10]') ! call assert_equal({}, {}) endfunc " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0618/src/testdir/test_search.vim 2020-04-11 18:36:35.047150850 +0200 --- src/testdir/test_search.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 1617,1620 **** --- 1617,1651 ---- close! endfunc + " Test for searching with 'smartcase' and 'ignorecase' + func Test_search_smartcase() + new + call setline(1, ['', 'Hello']) + set noignorecase nosmartcase + call assert_fails('exe "normal /\\a\\_.\\(.*\\)O\"', 'E486:') + + set ignorecase nosmartcase + exe "normal /\\a\\_.\\(.*\\)O\" + call assert_equal([2, 1], [line('.'), col('.')]) + + call cursor(1, 1) + set ignorecase smartcase + call assert_fails('exe "normal /\\a\\_.\\(.*\\)O\"', 'E486:') + + exe "normal /\\a\\_.\\(.*\\)o\" + call assert_equal([2, 1], [line('.'), col('.')]) + + set ignorecase& smartcase& + close! + endfunc + + " Test searching past the end of a file + func Test_search_past_eof() + new + call setline(1, ['Line']) + exe "normal /\\n\\zs\" + call assert_equal([1, 4], [line('.'), col('.')]) + close! + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0618/src/testdir/test_unlet.vim 2020-03-20 18:20:47.080975621 +0100 --- src/testdir/test_unlet.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 27,32 **** --- 27,33 ---- call assert_fails("unlet l['k'", 'E111:') let d = {'k' : 1} call assert_fails("unlet d.k2", 'E716:') + call assert_fails("unlet {a};", 'E488:') endfunc func Test_unlet_env() *** ../vim-8.2.0618/src/testdir/test_usercommands.vim 2020-04-13 21:16:18.039292270 +0200 --- src/testdir/test_usercommands.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 587,603 **** return "a\nb\n" endfunc command -nargs=* -complete=customlist,T1 TCmd1 ! call feedkeys(":T1 \\\"\", 'xt') ! call assert_equal('"T1 ', @:) delcommand TCmd1 delfunc T1 func T2(a, c, p) ! return ['a', 'b', 'c'] endfunc command -nargs=* -complete=customlist,T2 TCmd2 ! call feedkeys(":T2 \\\"\", 'xt') ! call assert_equal('"T2 ', @:) delcommand TCmd2 delfunc T2 endfunc --- 587,603 ---- return "a\nb\n" endfunc command -nargs=* -complete=customlist,T1 TCmd1 ! call feedkeys(":TCmd1 \\\"\", 'xt') ! call assert_equal('"TCmd1 ', @:) delcommand TCmd1 delfunc T1 func T2(a, c, p) ! return {} endfunc command -nargs=* -complete=customlist,T2 TCmd2 ! call feedkeys(":TCmd2 \\\"\", 'xt') ! call assert_equal('"TCmd2 ', @:) delcommand TCmd2 delfunc T2 endfunc *** ../vim-8.2.0618/src/testdir/test_vimscript.vim 2020-04-20 16:49:56.705830066 +0200 --- src/testdir/test_vimscript.vim 2020-04-23 13:01:08.432900291 +0200 *************** *** 1671,1676 **** --- 1671,1690 ---- call assert_fails('let x .= "f"', 'E734') let x = !3.14 call assert_equal(0.0, x) + + " integer and float operations + let x = 1 + let x *= 2.1 + call assert_equal(2.1, x) + let x = 1 + let x /= 0.25 + call assert_equal(4.0, x) + let x = 1 + call assert_fails('let x %= 0.25', 'E734:') + let x = 1 + call assert_fails('let x .= 0.25', 'E734:') + let x = 1.0 + call assert_fails('let x += [1.1]', 'E734:') endif " Test for environment variable *************** *** 1871,1876 **** --- 1885,1893 ---- " Missing 'in' in a :for statement call assert_fails('for i range(1) | endfor', 'E690:') + + " Incorrect number of variables in for + call assert_fails('for [i,] in range(3) | endfor', 'E475:') endfunc " Test for deep nesting of if/for/while/try statements {{{1 *** ../vim-8.2.0618/src/version.c 2020-04-22 19:13:16.047410502 +0200 --- src/version.c 2020-04-23 13:17:07.645870595 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 619, /**/ -- Contrary to popular belief, it's often your clothing that gets promoted, not you. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///