diff options
| -rw-r--r-- | src/nvim/buffer.c | 5 | ||||
| -rw-r--r-- | src/nvim/quickfix.c | 12 | ||||
| -rw-r--r-- | src/nvim/tag.c | 46 | ||||
| -rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
| -rw-r--r-- | src/nvim/testdir/test_alot.vim | 1 | ||||
| -rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 45 | ||||
| -rw-r--r-- | src/nvim/testdir/test_join.vim | 35 | ||||
| -rw-r--r-- | src/nvim/testdir/test_tagjump.vim | 28 | ||||
| -rw-r--r-- | src/nvim/testdir/test_taglist.vim | 7 | ||||
| -rw-r--r-- | src/nvim/testdir/test_user_func.vim | 96 | ||||
| -rw-r--r-- | test/functional/legacy/packadd_spec.lua | 2 | 
11 files changed, 254 insertions, 24 deletions
| diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 3fadcc75bf..00d472b4c8 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -296,6 +296,11 @@ open_buffer (    }    save_file_ff(curbuf);                 // keep this fileformat +  // Set last_changedtick to avoid triggering a TextChanged autocommand right +  // after it was added. +  curbuf->b_last_changedtick = buf_get_changedtick(curbuf); +  curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); +    /* require "!" to overwrite the file, because it wasn't read completely */    if (aborting())      curbuf->b_flags |= BF_READERR; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 4308c4e87e..a19e98725a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4541,11 +4541,6 @@ void ex_cbuffer(exarg_T *eap)    qf_info_T *qi = &ql_info;    const char *au_name = NULL; -  if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer -      || eap->cmdidx == CMD_laddbuffer) { -    qi = ll_get_or_alloc_list(curwin); -  } -    switch (eap->cmdidx) {      case CMD_cbuffer:        au_name = "cbuffer"; @@ -4576,6 +4571,13 @@ void ex_cbuffer(exarg_T *eap)      }    } +  // Must come after autocommands. +  if (eap->cmdidx == CMD_lbuffer +      || eap->cmdidx == CMD_lgetbuffer +      || eap->cmdidx == CMD_laddbuffer) { +    qi = ll_get_or_alloc_list(curwin); +  } +    if (*eap->arg == NUL)      buf = curbuf;    else if (*skipwhite(skipdigits(eap->arg)) == NUL) diff --git a/src/nvim/tag.c b/src/nvim/tag.c index c09a13edb1..2a980af2a2 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -952,12 +952,12 @@ void do_tags(exarg_T *eap)          continue;        msg_putchar('\n'); -      sprintf((char *)IObuff, "%c%2d %2d %-15s %5ld  ", -          i == tagstackidx ? '>' : ' ', -          i + 1, -          tagstack[i].cur_match + 1, -          tagstack[i].tagname, -          tagstack[i].fmark.mark.lnum); +      vim_snprintf((char *)IObuff, IOSIZE, "%c%2d %2d %-15s %5ld  ", +                   i == tagstackidx ? '>' : ' ', +                   i + 1, +                   tagstack[i].cur_match + 1, +                   tagstack[i].tagname, +                   tagstack[i].fmark.mark.lnum);        msg_outtrans(IObuff);        msg_outtrans_attr(name, tagstack[i].fmark.fnum == curbuf->b_fnum                          ? HL_ATTR(HLF_D) : 0); @@ -2217,6 +2217,16 @@ static bool test_for_static(tagptrs_T *tagp)    return FALSE;  } +// Returns the length of a matching tag line. +static size_t matching_line_len(const char_u *const lbuf) +{ +  const char_u *p = lbuf + 1; + +  // does the same thing as parse_match() +  p += STRLEN(p) + 1; +  return (p - lbuf) + STRLEN(p); +} +  /*   * Parse a line from a matching tag.  Does not change the line itself.   * @@ -2300,11 +2310,10 @@ static char_u *tag_full_fname(tagptrs_T *tagp)   *   * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.   */ -static int  -jumpto_tag ( -    char_u *lbuf,              /* line from the tags file for this tag */ -    int forceit,                    /* :ta with ! */ -    int keep_help                  /* keep help flag (FALSE for cscope) */ +static int jumpto_tag( +    const char_u *lbuf_arg,   // line from the tags file for this tag +    int forceit,              // :ta with ! +    int keep_help             // keep help flag (FALSE for cscope)  )  {    int save_secure; @@ -2312,7 +2321,6 @@ jumpto_tag (    bool save_p_ws;    int save_p_scs, save_p_ic;    linenr_T save_lnum; -  int csave = 0;    char_u      *str;    char_u      *pbuf;                    /* search pattern buffer */    char_u      *pbuf_end; @@ -2327,6 +2335,9 @@ jumpto_tag (    char_u      *full_fname = NULL;    int old_KeyTyped = KeyTyped;              /* getting the file may reset it */    const int l_g_do_tagpreview = g_do_tagpreview; +  const size_t len = matching_line_len(lbuf_arg) + 1; +  char_u *lbuf = xmalloc(len); +  memmove(lbuf, lbuf_arg, len);    pbuf = xmalloc(LSIZE); @@ -2336,8 +2347,7 @@ jumpto_tag (      goto erret;    } -  /* truncate the file name, so it can be used as a string */ -  csave = *tagp.fname_end; +  // truncate the file name, so it can be used as a string    *tagp.fname_end = NUL;    fname = tagp.fname; @@ -2447,7 +2457,10 @@ jumpto_tag (      else        keep_help_flag = curbuf->b_help;    } +    if (getfile_result == GETFILE_UNUSED) { +    // Careful: getfile() may trigger autocommands and call jumpto_tag() +    // recursively.      getfile_result = getfile(0, fname, NULL, true, (linenr_T)0, forceit);    }    keep_help_flag = false; @@ -2605,9 +2618,8 @@ jumpto_tag (    }  erret: -  g_do_tagpreview = 0;   /* For next time */ -  if (tagp.fname_end != NULL) -    *tagp.fname_end = csave; +  g_do_tagpreview = 0;  // For next time +  xfree(lbuf);    xfree(pbuf);    xfree(tofree_fname);    xfree(full_fname); diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 361db47fc7..1e3dc04049 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -114,6 +114,7 @@ NEW_TESTS ?= \  	    test_timers.res \  	    test_undo.res \  	    test_usercommands.res \ +	    test_user_func.res \  	    test_vimscript.res \  	    test_visual.res \  	    test_winbuf_close.res \ diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 238dbe8d90..ace4b377cb 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -19,6 +19,7 @@ source test_functions.vim  source test_ga.vim  source test_global.vim  source test_goto.vim +source test_join.vim  source test_jumps.vim  source test_fileformat.vim  source test_filetype.vim diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index e4ab3ccea8..b1502eff89 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1,5 +1,7 @@  " Tests for autocommands +source shared.vim +  func! s:cleanup_buffers() abort    for bnr in range(1, bufnr('$'))      if bufloaded(bnr) && bufnr('%') != bnr @@ -248,6 +250,23 @@ func Test_augroup_warning()    au! VimEnter  endfunc +func Test_BufReadCmdHelp() +  " This used to cause access to free memory +  au BufReadCmd * e +h +  help + +  au! BufReadCmd +endfunc + +func Test_BufReadCmdHelpJump() +  " This used to cause access to free memory +  au BufReadCmd * e +h{ +  " } to fix highlighting +  call assert_fails('help', 'E434:') + +  au! BufReadCmd +endfunc +  func Test_augroup_deleted()    " This caused a crash before E936 was introduced    augroup x @@ -1165,6 +1184,13 @@ func Test_nocatch_wipe_dummy_buffer()    au!  endfunc +func Test_wipe_cbuffer() +  sv x +  au * * bw +  lb +  au! +endfunc +  " Test TextChangedI and TextChangedP  func Test_ChangedP()    " Nvim does not support test_override(). @@ -1245,3 +1271,22 @@ func Test_TextChangedI_with_setline()    call test_override('starting', 0)    bwipe!  endfunc + +func Test_Changed_FirstTime() +  if !has('terminal') || has('gui_running') +    return +  endif +  " Prepare file for TextChanged event. +  call writefile([''], 'Xchanged.txt') +  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) +  call assert_equal('running', term_getstatus(buf)) +  " It's only adding autocmd, so that no event occurs. +  call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>") +  call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>") +  call WaitFor({-> term_getstatus(buf) == 'finished'}) +  call assert_equal([''], readfile('Xchanged.txt')) + +  " clean up +  call delete('Xchanged.txt') +  bwipe! +endfunc diff --git a/src/nvim/testdir/test_join.vim b/src/nvim/testdir/test_join.vim new file mode 100644 index 0000000000..1c97414164 --- /dev/null +++ b/src/nvim/testdir/test_join.vim @@ -0,0 +1,35 @@ +" Test for joining lines. + +func Test_join_with_count() +  new +  call setline(1, ['one', 'two', 'three', 'four']) +  normal J +  call assert_equal('one two', getline(1)) +  %del +  call setline(1, ['one', 'two', 'three', 'four']) +  normal 10J +  call assert_equal('one two three four', getline(1)) +  quit! +endfunc + +" Tests for setting the '[,'] marks when joining lines. +func Test_join_marks() +  enew +  call append(0, [ +	      \ "\t\tO sodales, ludite, vos qui", +	      \ "attamen consulite per voster honur. Tua pulchra " . +	      \ "facies me fay planszer milies", +	      \ "", +	      \ "This line.", +	      \ "Should be joined with the next line", +	      \ "and with this line"]) + +  normal gg0gqj +  call assert_equal([0, 1, 1, 0], getpos("'[")) +  call assert_equal([0, 2, 1, 0], getpos("']")) + +  /^This line/;'}-join +  call assert_equal([0, 4, 11, 0], getpos("'[")) +  call assert_equal([0, 4, 67, 0], getpos("']")) +  enew! +endfunc diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index 268a153077..f9bd8b5246 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -230,4 +230,32 @@ func Test_tag_file_encoding()    call delete('Xtags1')  endfunc +func Test_tagjump_etags() +  if !has('emacs_tags') +    return +  endif +  call writefile([ +        \ "void foo() {}", +        \ "int main(int argc, char **argv)", +        \ "{", +        \ "\tfoo();", +        \ "\treturn 0;", +        \ "}", +        \ ], 'Xmain.c') + +  call writefile([ +	\ "\x0c", +        \ "Xmain.c,64", +        \ "void foo() {}\x7ffoo\x011,0", +        \ "int main(int argc, char **argv)\x7fmain\x012,14", +	\ ], 'Xtags') +  set tags=Xtags +  ta foo +  call assert_equal('void foo() {}', getline('.')) + +  call delete('Xtags') +  call delete('Xmain.c') +  bwipe! +endfunc +  " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim index 2d1557ebd9..3ad2025915 100644 --- a/src/nvim/testdir/test_taglist.vim +++ b/src/nvim/testdir/test_taglist.vim @@ -1,4 +1,4 @@ -" test 'taglist' function +" test 'taglist' function and :tags command  func Test_taglist()    call writefile([ @@ -56,3 +56,8 @@ func Test_taglist_ctags_etags()    call delete('Xtags')  endfunc + +func Test_tags_too_long() +  call assert_fails('tag ' . repeat('x', 1020), 'E426') +  tags +endfunc diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim new file mode 100644 index 0000000000..e7a3701386 --- /dev/null +++ b/src/nvim/testdir/test_user_func.vim @@ -0,0 +1,96 @@ +" Test for user functions. +" Also test an <expr> mapping calling a function. +" Also test that a builtin function cannot be replaced. +" Also test for regression when calling arbitrary expression. + +func Table(title, ...) +  let ret = a:title +  let idx = 1 +  while idx <= a:0 +    exe "let ret = ret . a:" . idx +    let idx = idx + 1 +  endwhile +  return ret +endfunc + +func Compute(n1, n2, divname) +  if a:n2 == 0 +    return "fail" +  endif +  exe "let g:" . a:divname . " = ". a:n1 / a:n2 +  return "ok" +endfunc + +func Expr1() +  silent! normal! v +  return "111" +endfunc + +func Expr2() +  call search('XX', 'b') +  return "222" +endfunc + +func ListItem() +  let g:counter += 1 +  return g:counter . '. ' +endfunc + +func ListReset() +  let g:counter = 0 +  return '' +endfunc + +func FuncWithRef(a) +  unlet g:FuncRef +  return a:a +endfunc + +func Test_user_func() +  let g:FuncRef=function("FuncWithRef") +  let g:counter = 0 +  inoremap <expr> ( ListItem() +  inoremap <expr> [ ListReset() +  imap <expr> + Expr1() +  imap <expr> * Expr2() +  let g:retval = "nop" + +  call assert_equal('xxx4asdf', Table("xxx", 4, "asdf")) +  call assert_equal('fail', Compute(45, 0, "retval")) +  call assert_equal('nop', g:retval) +  call assert_equal('ok', Compute(45, 5, "retval")) +  call assert_equal(9, g:retval) +  call assert_equal(333, g:FuncRef(333)) + +  enew + +  normal oXX+-XX +  call assert_equal('XX111-XX', getline('.')) +  normal o---*--- +  call assert_equal('---222---', getline('.')) +  normal o(one +  call assert_equal('1. one', getline('.')) +  normal o(two +  call assert_equal('2. two', getline('.')) +  normal o[(one again +  call assert_equal('1. one again', getline('.')) + +  call assert_equal(3, max([1, 2, 3])) +  call assert_fails("call extend(g:, {'max': function('min')})", 'E704') +  call assert_equal(3, max([1, 2, 3])) + +  " Regression: the first line below used to throw ?E110: Missing ')'? +  " Second is here just to prove that this line is correct when not skipping +  " rhs of &&. +  call assert_equal(0, (0 && (function('tr'))(1, 2, 3))) +  call assert_equal(1, (1 && (function('tr'))(1, 2, 3))) + +  delfunc Table +  delfunc Compute +  delfunc Expr1 +  delfunc Expr2 +  delfunc ListItem +  delfunc ListReset +  unlet g:retval g:counter +  enew! +endfunc diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua index 67f6006d1d..7c3d48317b 100644 --- a/test/functional/legacy/packadd_spec.lua +++ b/test/functional/legacy/packadd_spec.lua @@ -15,7 +15,7 @@ describe('packadd', function()      source([=[        func SetUp() -        let s:topdir = expand(expand('%:p:h') . '/Xdir') +        let s:topdir = expand(getcwd() . '/Xdir')          exe 'set packpath=' . s:topdir          let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest')        endfunc | 
