Patch 8.2.1479
Problem:    Vim9: error for list index uses wrong line number.
Solution:   Set source line number. (closes #6724)  Add a way to assert the
            line number of the error with assert_fails().
Files:      runtime/doc/testing.txt, src/vim9execute.c, src/testing.c,
            src/evalfunc.c, src/message.c, src/globals.h, src/testdir/vim9.vim,
            src/testdir/test_vim9_expr.vim


*** ../vim-8.2.1478/runtime/doc/testing.txt     2020-08-13 18:57:56.558214754 
+0200
--- runtime/doc/testing.txt     2020-08-17 23:25:55.100930876 +0200
***************
*** 291,298 ****
                        catch
                          call assert_exception('E492:')
                        endtry
! 
! assert_fails({cmd} [, {error} [, {msg}]])                     *assert_fails()*
                Run {cmd} and add an error message to |v:errors| if it does
                NOT produce an error or when {error} is not found in the
                error message.  Also see |assert-return|.
--- 291,299 ----
                        catch
                          call assert_exception('E492:')
                        endtry
! <
!                                                       *assert_fails()*
! assert_fails({cmd} [, {error} [, {msg} [, {lnum}]]])
                Run {cmd} and add an error message to |v:errors| if it does
                NOT produce an error or when {error} is not found in the
                error message.  Also see |assert-return|.
***************
*** 311,323 ****
                string for the first error: >
                        assert_fails('cmd', ['', 'E987:'])
  <
                Note that beeping is not considered an error, and some failing
                commands only beep.  Use |assert_beeps()| for those.
  
                Can also be used as a |method|: >
                        GetCmd()->assert_fails('E99:')
  
! assert_false({actual} [, {msg}])                              *assert_false()*
                When {actual} is not false an error message is added to
                |v:errors|, like with |assert_equal()|.
                Also see |assert-return|.
--- 312,332 ----
                string for the first error: >
                        assert_fails('cmd', ['', 'E987:'])
  <
+               If {msg} is empty then it is not used.  Do this to get the
+               default message when passing the {lnum} argument.
+ 
+               When {lnum} is present and not negative, and the {error}
+               argument is present and matches, then this is compared with
+               the line number at which the error was reported. That can be
+               the line number in a function or in a script.
+ 
                Note that beeping is not considered an error, and some failing
                commands only beep.  Use |assert_beeps()| for those.
  
                Can also be used as a |method|: >
                        GetCmd()->assert_fails('E99:')
  
! assert_false({actual} [, {msg}])                      *assert_false()*
                When {actual} is not false an error message is added to
                |v:errors|, like with |assert_equal()|.
                Also see |assert-return|.
*** ../vim-8.2.1478/src/vim9execute.c   2020-08-16 18:29:31.480642573 +0200
--- src/vim9execute.c   2020-08-17 23:21:53.814668709 +0200
***************
*** 2299,2304 ****
--- 2299,2305 ----
  
                    ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
                    tv = STACK_TV_BOT(-1);
+                   SOURCING_LNUM = iptr->isn_lnum;
                    if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE)
                                                                       == FAIL)
                        goto on_error;
*** ../vim-8.2.1478/src/testing.c       2020-07-26 15:36:12.963172976 +0200
--- src/testing.c       2020-08-17 23:19:27.939712176 +0200
***************
*** 142,148 ****
      int               did_copy = FALSE;
      int               omitted = 0;
  
!     if (opt_msg_tv->v_type != VAR_UNKNOWN)
      {
        ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0));
        vim_free(tofree);
--- 142,151 ----
      int               did_copy = FALSE;
      int               omitted = 0;
  
!     if (opt_msg_tv->v_type != VAR_UNKNOWN
!           && !(opt_msg_tv->v_type == VAR_STRING
!               && (opt_msg_tv->vval.v_string == NULL
!                   || *opt_msg_tv->vval.v_string == NUL)))
      {
        ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0));
        vim_free(tofree);
***************
*** 570,575 ****
--- 573,579 ----
        char_u  buf[NUMBUFLEN];
        char_u  *expected;
        int     error_found = FALSE;
+       int     lnum_error_found = FALSE;
        char_u  *actual = emsg_assert_fails_msg == NULL ? (char_u *)"[unknown]"
                                                       : emsg_assert_fails_msg;
  
***************
*** 611,624 ****
            goto theend;
        }
  
        if (error_found)
        {
            typval_T actual_tv;
  
            prepare_assert_error(&ga);
!           actual_tv.v_type = VAR_STRING;
!           actual_tv.vval.v_string = actual;
!           fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
                                                     &actual_tv, ASSERT_OTHER);
            ga_concat(&ga, (char_u *)": ");
            assert_append_cmd_or_arg(&ga, argvars, cmd);
--- 615,645 ----
            goto theend;
        }
  
+       if (!error_found && argvars[3].v_type == VAR_NUMBER
+               && argvars[3].vval.v_number >= 0
+               && argvars[3].vval.v_number != emsg_assert_fails_lnum)
+       {
+           error_found = TRUE;
+           lnum_error_found = TRUE;
+       }
+ 
        if (error_found)
        {
            typval_T actual_tv;
  
            prepare_assert_error(&ga);
!           if (lnum_error_found)
!           {
!               actual_tv.v_type = VAR_NUMBER;
!               actual_tv.vval.v_number = emsg_assert_fails_lnum;
!           }
!           else
!           {
!               actual_tv.v_type = VAR_STRING;
!               actual_tv.vval.v_string = actual;
!           }
!           fill_assert_error(&ga, &argvars[2], NULL,
!                   &argvars[lnum_error_found ? 3 : 1],
                                                     &actual_tv, ASSERT_OTHER);
            ga_concat(&ga, (char_u *)": ");
            assert_append_cmd_or_arg(&ga, argvars, cmd);
*** ../vim-8.2.1478/src/evalfunc.c      2020-08-14 18:56:41.740716995 +0200
--- src/evalfunc.c      2020-08-17 22:50:36.489055690 +0200
***************
*** 494,500 ****
      {"assert_equal",  2, 3, FEARG_2,    ret_number,   f_assert_equal},
      {"assert_equalfile", 2, 3, FEARG_1,         ret_number,   
f_assert_equalfile},
      {"assert_exception", 1, 2, 0,       ret_number,   f_assert_exception},
!     {"assert_fails",  1, 3, FEARG_1,    ret_number,   f_assert_fails},
      {"assert_false",  1, 2, FEARG_1,    ret_number,   f_assert_false},
      {"assert_inrange",        3, 4, FEARG_3,    ret_number,   
f_assert_inrange},
      {"assert_match",  2, 3, FEARG_2,    ret_number,   f_assert_match},
--- 494,500 ----
      {"assert_equal",  2, 3, FEARG_2,    ret_number,   f_assert_equal},
      {"assert_equalfile", 2, 3, FEARG_1,         ret_number,   
f_assert_equalfile},
      {"assert_exception", 1, 2, 0,       ret_number,   f_assert_exception},
!     {"assert_fails",  1, 4, FEARG_1,    ret_number,   f_assert_fails},
      {"assert_false",  1, 2, FEARG_1,    ret_number,   f_assert_false},
      {"assert_inrange",        3, 4, FEARG_3,    ret_number,   
f_assert_inrange},
      {"assert_match",  2, 3, FEARG_2,    ret_number,   f_assert_match},
*** ../vim-8.2.1478/src/message.c       2020-07-26 15:36:12.963172976 +0200
--- src/message.c       2020-08-17 22:58:13.149209965 +0200
***************
*** 655,661 ****
--- 655,664 ----
        }
  
        if (emsg_assert_fails_used && emsg_assert_fails_msg == NULL)
+       {
            emsg_assert_fails_msg = vim_strsave(s);
+           emsg_assert_fails_lnum = SOURCING_LNUM;
+       }
  
        // set "v:errmsg", also when using ":silent! cmd"
        set_vim_var_string(VV_ERRMSG, s, -1);
*** ../vim-8.2.1478/src/globals.h       2020-08-15 16:33:24.493747355 +0200
--- src/globals.h       2020-08-17 23:00:25.232160843 +0200
***************
*** 223,228 ****
--- 223,229 ----
  // used by assert_fails()
  EXTERN int    emsg_assert_fails_used INIT(= FALSE);
  EXTERN char_u *emsg_assert_fails_msg INIT(= NULL);
+ EXTERN long   emsg_assert_fails_lnum INIT(= 0);
  
  EXTERN int    did_endif INIT(= FALSE);    // just had ":endif"
  #endif
*** ../vim-8.2.1478/src/testdir/vim9.vim        2020-08-10 21:57:49.039237480 
+0200
--- src/testdir/vim9.vim        2020-08-18 13:39:10.164499846 +0200
***************
*** 9,25 ****
  endfunc
  
  " Check that "lines" inside ":def" results in an "error" message.
! func CheckDefFailure(lines, error)
    call writefile(['def Func()'] + a:lines + ['enddef', 'defcompile'], 'Xdef')
!   call assert_fails('so Xdef', a:error, a:lines)
    call delete('Xdef')
  endfunc
  
  " Check that "lines" inside ":def" results in an "error" message when 
executed.
! func CheckDefExecFailure(lines, error)
    call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
    so Xdef
!   call assert_fails('call Func()', a:error, a:lines)
    call delete('Xdef')
  endfunc
  
--- 9,27 ----
  endfunc
  
  " Check that "lines" inside ":def" results in an "error" message.
! " If "lnum" is given check that the error is reported for this line.
! func CheckDefFailure(lines, error, lnum = -1)
    call writefile(['def Func()'] + a:lines + ['enddef', 'defcompile'], 'Xdef')
!   call assert_fails('so Xdef', a:error, a:lines, a:lnum)
    call delete('Xdef')
  endfunc
  
  " Check that "lines" inside ":def" results in an "error" message when 
executed.
! " If "lnum" is given check that the error is reported for this line.
! func CheckDefExecFailure(lines, error, lnum = -1)
    call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
    so Xdef
!   call assert_fails('call Func()', a:error, a:lines, a:lnum)
    call delete('Xdef')
  endfunc
  
*** ../vim-8.2.1478/src/testdir/test_vim9_expr.vim      2020-08-16 
18:42:50.678811797 +0200
--- src/testdir/test_vim9_expr.vim      2020-08-18 13:39:47.436223625 +0200
***************
*** 1464,1479 ****
                4]
  
    call CheckDefFailure(["let x = 1234[3]"], 'E1107:')
!   call CheckDefExecFailure(["let x = g:anint[3]"], 'E1062:')
  
    call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:')
  
    call CheckDefFailure(["let x = [1,2,3]"], 'E1069:')
    call CheckDefFailure(["let x = [1 ,2, 3]"], 'E1068:')
  
!   call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:')
    call CheckDefFailure(["let x = g:list_mixed["], 'E1097:')
!   call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:')
    call CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:')
    call CheckDefFailure(["let l: list<number> = [234, 'x']"], 'E1012:')
    call CheckDefFailure(["let l: list<number> = ['x', 234]"], 'E1012:')
--- 1464,1481 ----
                4]
  
    call CheckDefFailure(["let x = 1234[3]"], 'E1107:')
!   call CheckDefExecFailure(["let x = g:anint[3]"], 'E1062:', 1)
  
    call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:')
  
    call CheckDefFailure(["let x = [1,2,3]"], 'E1069:')
    call CheckDefFailure(["let x = [1 ,2, 3]"], 'E1068:')
  
!   call CheckDefExecFailure(["echo 1", "let x = [][0]", "echo 3"], 'E684:', 2)
! 
!   call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:', 1)
    call CheckDefFailure(["let x = g:list_mixed["], 'E1097:')
!   call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:', 1)
    call CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:')
    call CheckDefFailure(["let l: list<number> = [234, 'x']"], 'E1012:')
    call CheckDefFailure(["let l: list<number> = ['x', 234]"], 'E1012:')
*** ../vim-8.2.1478/src/version.c       2020-08-18 13:04:10.795215214 +0200
--- src/version.c       2020-08-18 13:40:06.516083107 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1479,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
233. You start dreaming about web pages...in html.

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202008181211.07ICBSvT1111559%40masaka.moolenaar.net.

Raspunde prin e-mail lui