]> granicus.if.org Git - vim/commitdiff
patch 8.2.0502: Vim9: some code is not tested v8.2.0502
authorBram Moolenaar <Bram@vim.org>
Thu, 2 Apr 2020 19:13:25 +0000 (21:13 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 2 Apr 2020 19:13:25 +0000 (21:13 +0200)
Problem:    Vim9: some code is not tested.
Solution:   Add more tests.  Fix uncovered problems.

16 files changed:
src/cmdexpand.c
src/ex_cmds.c
src/ex_docmd.c
src/ex_eval.c
src/ex_getln.c
src/highlight.c
src/proto/regexp.pro
src/regexp.c
src/search.c
src/syntax.c
src/tag.c
src/testdir/test_vim9_disassemble.vim
src/testdir/test_vim9_script.vim
src/userfunc.c
src/version.c
src/vim9compile.c

index 4f9b3cad0c825500fea3443c149da8edc5e10fff..3a2b10c5a78526065562e3b7039a638fdb8f2b9c 100644 (file)
@@ -1389,7 +1389,7 @@ set_one_cmd_context(
                if (*arg != NUL)
                {
                    xp->xp_context = EXPAND_NOTHING;
-                   arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
+                   arg = skip_regexp(arg + 1, *arg, p_magic);
                }
            }
            return find_nextcmd(arg);
@@ -1427,7 +1427,7 @@ set_one_cmd_context(
            {
                // skip "from" part
                ++arg;
-               arg = skip_regexp(arg, delim, p_magic, NULL);
+               arg = skip_regexp(arg, delim, p_magic);
            }
            // skip "to" part
            while (arg[0] != NUL && arg[0] != delim)
index ce5db88604582dcab7269ddc301a3aeed59fd6b2..bd114631bbd0147e24d745ad3b489191b0e13714 100644 (file)
@@ -451,7 +451,7 @@ ex_sort(exarg_T *eap)
        }
        else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL)
        {
-           s = skip_regexp(p + 1, *p, TRUE, NULL);
+           s = skip_regexp(p + 1, *p, TRUE);
            if (*s != *p)
            {
                emsg(_(e_invalpat));
@@ -3626,7 +3626,7 @@ do_sub(exarg_T *eap)
            which_pat = RE_LAST;            // use last used regexp
            delimiter = *cmd++;             // remember delimiter character
            pat = cmd;                      // remember start of search pat
-           cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
+           cmd = skip_regexp_ex(cmd, delimiter, p_magic, &eap->arg, NULL);
            if (cmd[0] == delimiter)        // end delimiter found
                *cmd++ = NUL;               // replace it with a NUL
        }
@@ -4801,7 +4801,7 @@ ex_global(exarg_T *eap)
        if (delim)
            ++cmd;              // skip delimiter if there is one
        pat = cmd;              // remember start of pattern
-       cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
+       cmd = skip_regexp_ex(cmd, delim, p_magic, &eap->arg, NULL);
        if (cmd[0] == delim)                // end delimiter found
            *cmd++ = NUL;                   // replace it with a NUL
     }
@@ -6441,7 +6441,7 @@ skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
        if (s != NULL)
            *s = p + 1;
        c = *p;
-       p = skip_regexp(p + 1, c, TRUE, NULL);
+       p = skip_regexp(p + 1, c, TRUE);
        if (*p != c)
            return NULL;
 
index fb084d32d56891490cf3607089b0bbcf62899ac1..b04e2832a7738099c2c3516e9feba1bbd6fad244 100644 (file)
@@ -3663,7 +3663,7 @@ get_address(
                }
                if (skip)       // skip "/pat/"
                {
-                   cmd = skip_regexp(cmd, c, (int)p_magic, NULL);
+                   cmd = skip_regexp(cmd, c, (int)p_magic);
                    if (*cmd == c)
                        ++cmd;
                }
@@ -6123,7 +6123,7 @@ ex_open(exarg_T *eap)
     {
        // ":open /pattern/": put cursor in column found with pattern
        ++eap->arg;
-       p = skip_regexp(eap->arg, '/', p_magic, NULL);
+       p = skip_regexp(eap->arg, '/', p_magic);
        *p = NUL;
        regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0);
        if (regmatch.regprog != NULL)
@@ -7857,7 +7857,7 @@ ex_findpat(exarg_T *eap)
     {
        whole = FALSE;
        ++eap->arg;
-       p = skip_regexp(eap->arg, '/', p_magic, NULL);
+       p = skip_regexp(eap->arg, '/', p_magic);
        if (*p)
        {
            *p++ = NUL;
index 70b52a3699e62182fd52bcf8341ee5d2b41e42f6..72da2f252d4da04ebda5ec76031905667ff154f9 100644 (file)
@@ -1527,7 +1527,7 @@ ex_catch(exarg_T *eap)
     else
     {
        pat = eap->arg + 1;
-       end = skip_regexp(pat, *eap->arg, TRUE, NULL);
+       end = skip_regexp(pat, *eap->arg, TRUE);
     }
 
     if (!give_up)
index bc3cccc632a8d7f4de57b4a47c2c4fd129fa71ef..4b0645a504a77a87a6ab97034cfc8caa33f8855e 100644 (file)
@@ -277,7 +277,7 @@ do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *is_s
     p = skipwhite(p);
     delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
     *search_delim = delim;
-    end = skip_regexp(p, delim, p_magic, NULL);
+    end = skip_regexp(p, delim, p_magic);
 
     use_last_pat = end == p && *end == delim;
 
index 5d90e696aa146342ab600156023e67f8283c7d0c..9f8bfbc7f26998e5bafaf327fa34a86cb7bfae43 100644 (file)
@@ -4964,7 +4964,7 @@ ex_match(exarg_T *eap)
            semsg(_(e_invarg2), eap->arg);
            return;
        }
-       end = skip_regexp(p + 1, *p, TRUE, NULL);
+       end = skip_regexp(p + 1, *p, TRUE);
        if (!eap->skip)
        {
            if (*end != NUL && !ends_excmd(*skipwhite(end + 1)))
index 01f1fff0d7e8430182e2f94350c672b58f9d50ee..27ba8e59a080b450d69bfee9f66e9b5113321c42 100644 (file)
@@ -1,6 +1,7 @@
 /* regexp.c */
 int re_multiline(regprog_T *prog);
-char_u *skip_regexp(char_u *startp, int dirc, int magic, char_u **newp);
+char_u *skip_regexp(char_u *startp, int dirc, int magic);
+char_u *skip_regexp_ex(char_u *startp, int dirc, int magic, char_u **newp, int *dropped);
 reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
 void unref_extmatch(reg_extmatch_T *em);
 char_u *regtilde(char_u *source, int magic);
index 4e21d44ccf061a2be1465dd6a5967bec4b593f4e..b4fb59598907c4b34bd6e1f531a923a98b32b0b0 100644 (file)
@@ -537,16 +537,30 @@ skip_anyof(char_u *p)
  * Stop at end of "startp" or where "dirc" is found ('/', '?', etc).
  * Take care of characters with a backslash in front of it.
  * Skip strings inside [ and ].
+ */
+    char_u *
+skip_regexp(
+    char_u     *startp,
+    int                dirc,
+    int                magic)
+{
+    return skip_regexp_ex(startp, dirc, magic, NULL, NULL);
+}
+
+/*
+ * skip_regexp() with extra arguments:
  * When "newp" is not NULL and "dirc" is '?', make an allocated copy of the
  * expression and change "\?" to "?".  If "*newp" is not NULL the expression
  * is changed in-place.
+ * If a "\?" is changed to "?" then "dropped" is incremented, unless NULL.
  */
     char_u *
-skip_regexp(
+skip_regexp_ex(
     char_u     *startp,
     int                dirc,
     int                magic,
-    char_u     **newp)
+    char_u     **newp,
+    int                *dropped)
 {
     int                mymagic;
     char_u     *p = startp;
@@ -579,6 +593,8 @@ skip_regexp(
                    if (*newp != NULL)
                        p = *newp + (p - startp);
                }
+               if (dropped != NULL)
+                   ++*dropped;
                if (*newp != NULL)
                    STRMOVE(p, p + 1);
                else
index 2005b79019c3d3e0c5cef7fd24bb3096c0bd09d4..95a27f8675da95993af99230ccd2038a09c15731 100644 (file)
@@ -1312,7 +1312,7 @@ do_search(
             * If there is a matching '/' or '?', toss it.
             */
            ps = strcopy;
-           p = skip_regexp(pat, search_delim, (int)p_magic, &strcopy);
+           p = skip_regexp_ex(pat, search_delim, (int)p_magic, &strcopy, NULL);
            if (strcopy != ps)
            {
                // made a copy of "pat" to change "\?" to "?"
index d16c22010477cf04f4a45b2b266579ce68ddffd3..c1d1b856bf16cfdc5db8c102b2077b65dec91efc 100644 (file)
@@ -5598,7 +5598,7 @@ get_syn_pattern(char_u *arg, synpat_T *ci)
     if (arg == NULL || arg[0] == NUL || arg[1] == NUL || arg[2] == NUL)
        return NULL;
 
-    end = skip_regexp(arg + 1, *arg, TRUE, NULL);
+    end = skip_regexp(arg + 1, *arg, TRUE);
     if (*end != *arg)                      // end delimiter not found
     {
        semsg(_("E401: Pattern delimiter not found: %s"), arg);
@@ -5775,7 +5775,7 @@ syn_cmd_sync(exarg_T *eap, int syncing UNUSED)
                finished = TRUE;
                break;
            }
-           arg_end = skip_regexp(next_arg + 1, *next_arg, TRUE, NULL);
+           arg_end = skip_regexp(next_arg + 1, *next_arg, TRUE);
            if (*arg_end != *next_arg)      // end delimiter not found
            {
                illegal = TRUE;
index dc4b9a57124b674a378d9d9fb571da7170e30740..1cb5c445a4693c6e82f5d72a57189c2f8bba0ae7 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -3530,7 +3530,7 @@ jumpto_tag(
         */
        str = pbuf;
        if (pbuf[0] == '/' || pbuf[0] == '?')
-           str = skip_regexp(pbuf + 1, pbuf[0], FALSE, NULL) + 1;
+           str = skip_regexp(pbuf + 1, pbuf[0], FALSE) + 1;
        if (str > pbuf_end - 1) // search command with nothing following
        {
            save_p_ws = p_ws;
@@ -3820,7 +3820,7 @@ find_extra(char_u **pp)
            str = skipdigits(str);
        else if (*str == '/' || *str == '?')
        {
-           str = skip_regexp(str + 1, *str, FALSE, NULL);
+           str = skip_regexp(str + 1, *str, FALSE);
            if (*str != first_char)
                str = NULL;
            else
index 95cd2894fe20ef80b6d0a39c3d7e027c22014750..36c098c7e97d605617055a488c38b4df2d15a7bd 100644 (file)
@@ -809,6 +809,8 @@ def Test_disassemble_compare_const()
   let cases = [
         \ ['"xx" == "yy"', false],
         \ ['"aa" == "aa"', true],
+        \ ['has("eval") ? true : false', true],
+        \ ['has("asdf") ? true : false', false],
         \ ]
 
   let nr = 1
index 8d36c81ad7054957fb5f892207dfb086b8e0504f..d93ea6a06c28a79c355982a6066b53db52f05917 100644 (file)
@@ -468,12 +468,20 @@ def Test_try_catch_match()
     seq ..= 'b'
   catch /asdf/
     seq ..= 'x'
+  catch ?a\?sdf?
+    seq ..= 'y'
   finally
     seq ..= 'c'
   endtry
   assert_equal('abc', seq)
 enddef
 
+def Test_try_catch_fails()
+  call CheckDefFailure(['catch'], 'E603:')
+  call CheckDefFailure(['try', 'echo 0', 'catch','catch'], 'E1033:')
+  call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
+enddef
+
 let s:export_script_lines =<< trim END
   vim9script
   let name: string = 'bob'
@@ -926,6 +934,13 @@ def Test_if_elseif_else()
   assert_equal('three', IfElse(3))
 enddef
 
+def Test_if_elseif_else_fails()
+  call CheckDefFailure(['elseif true'], 'E582:')
+  call CheckDefFailure(['else'], 'E581:')
+  call CheckDefFailure(['endif'], 'E580:')
+  call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
+enddef
+
 let g:bool_true = v:true
 let g:bool_false = v:false
 
@@ -972,6 +987,12 @@ def Test_if_const_expr()
   endif
   assert_equal(false, res)
 
+  res = false
+  if has('xyz') ? true : false
+    res = true
+  endif
+  assert_equal(false, res)
+
   res = false
   if true && true
     res = true
@@ -1030,6 +1051,8 @@ enddef
 def Test_if_const_expr_fails()
   call CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
   call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
+  call CheckDefFailure(["if has('aaa'"], 'E110:')
+  call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
 enddef
 
 def Test_delfunc()
@@ -1096,6 +1119,30 @@ def Test_for_outside_of_function()
   delete('Xvim9for.vim')
 enddef
 
+def Test_for_loop()
+  let result = ''
+  for cnt in range(7)
+    if cnt == 4
+      break
+    endif
+    if cnt == 2
+      continue
+    endif
+    result ..= cnt .. '_'
+  endfor
+  assert_equal('0_1_3_', result)
+enddef
+
+def Test_for_loop_fails()
+  call CheckDefFailure(['for # in range(5)'], 'E690:')
+  call CheckDefFailure(['for i In range(5)'], 'E690:')
+  call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
+  call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 'E1006:')
+  call CheckDefFailure(['for i in "text"'], 'E1024:')
+  call CheckDefFailure(['for i in xxx'], 'E1001:')
+  call CheckDefFailure(['endfor'], 'E588:')
+enddef
+
 def Test_while_loop()
   let result = ''
   let cnt = 0
@@ -1112,12 +1159,13 @@ def Test_while_loop()
   assert_equal('1_3_', result)
 enddef
 
-def Test_for_loop_fails()
-  call CheckDefFailure(['for # in range(5)'], 'E690:')
-  call CheckDefFailure(['for i In range(5)'], 'E690:')
-  call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
-  call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 'E1006:')
-  call CheckDefFailure(['for i in "text"'], 'E1024:')
+def Test_while_loop_fails()
+  call CheckDefFailure(['while xxx'], 'E1001:')
+  call CheckDefFailure(['endwhile'], 'E588:')
+  call CheckDefFailure(['continue'], 'E586:')
+  call CheckDefFailure(['if true', 'continue'], 'E586:')
+  call CheckDefFailure(['break'], 'E587:')
+  call CheckDefFailure(['if true', 'break'], 'E587:')
 enddef
 
 def Test_interrupt_loop()
index 62003a83a39df7a88d8339c5aed0de8d91828445..12d582a25009ed78eddc3cafbcde09ba6a724e95 100644 (file)
@@ -2330,7 +2330,7 @@ ex_function(exarg_T *eap)
      */
     if (*eap->arg == '/')
     {
-       p = skip_regexp(eap->arg + 1, '/', TRUE, NULL);
+       p = skip_regexp(eap->arg + 1, '/', TRUE);
        if (!eap->skip)
        {
            regmatch_T  regmatch;
index b1a10aaebd25635ec6dfe0c79823771fcb3a3f40..ddc5295c89400112ca5d66965d11bf9a4623fc08 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    502,
 /**/
     501,
 /**/
index bf87b6f96d836d7346abea06e18f8c527ad6f199..dec7587a8421141338f06ec7d26c89826b477eb6 100644 (file)
@@ -4095,7 +4095,7 @@ evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
        *arg = skipwhite(*arg);
        if (**arg != ')')
            return FAIL;
-       *arg = skipwhite(*arg + 1);
+       *arg = *arg + 1;
 
        argvars[0] = *tv;
        argvars[1].v_type = VAR_UNKNOWN;
@@ -4269,6 +4269,7 @@ evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
        int             val = tv2bool(tv);
        typval_T        tv2;
 
+       // require space before and after the ?
        if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
            return FAIL;
 
@@ -4553,6 +4554,7 @@ compile_for(char_u *arg, cctx_T *cctx)
     loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
     if (loop_idx < 0)
     {
+       // only happens when out of memory
        drop_scope(cctx);
        return NULL;
     }
@@ -4899,12 +4901,13 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
        char_u *end;
        char_u *pat;
        char_u *tofree = NULL;
+       int     dropped = 0;
        int     len;
 
        // Push v:exception, push {expr} and MATCH
        generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
 
-       end = skip_regexp(p + 1, *p, TRUE, &tofree);
+       end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
        if (*end != *p)
        {
            semsg(_("E1067: Separator mismatch: %s"), p);
@@ -4914,10 +4917,10 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
        if (tofree == NULL)
            len = (int)(end - (p + 1));
        else
-           len = (int)(end - (tofree + 1));
-       pat = vim_strnsave(p + 1, len);
+           len = (int)(end - tofree);
+       pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
        vim_free(tofree);
-       p += len + 2;
+       p += len + 2 + dropped;
        if (pat == NULL)
            return FAIL;
        if (generate_PUSHS(cctx, pat) == FAIL)