From 983d83ff1cd796ff321074335fa53fbe7ac45a46 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 12:12:43 +0100 Subject: [PATCH 01/11] patch 8.2.2476: using freed memory when splitting window while closing buffer Problem: Using freed memory when using an autocommand to split a window while a buffer is being closed. Solution: Disallow splitting when the buffer has b_locked_split set. --- src/buffer.c | 10 ++++++++-- src/errors.h | 2 ++ src/popupwin.c | 2 +- src/structs.h | 2 ++ src/testdir/test_autocmd.vim | 9 +++------ src/version.c | 2 ++ src/window.c | 10 ++++++++-- 7 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index f9bffbf3d8..ca1fd36efe 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -595,6 +595,7 @@ close_buffer( if (buf->b_nwindows == 1) { ++buf->b_locked; + ++buf->b_locked_split; if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf) && !bufref_valid(&bufref)) @@ -605,6 +606,7 @@ aucmd_abort: return FALSE; } --buf->b_locked; + --buf->b_locked_split; if (abort_if_last && one_window()) // Autocommands made this the only window. goto aucmd_abort; @@ -614,12 +616,14 @@ aucmd_abort: if (!unload_buf) { ++buf->b_locked; + ++buf->b_locked_split; if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, FALSE, buf) && !bufref_valid(&bufref)) // Autocommands deleted the buffer. goto aucmd_abort; --buf->b_locked; + --buf->b_locked_split; if (abort_if_last && one_window()) // Autocommands made this the only window. goto aucmd_abort; @@ -800,6 +804,7 @@ buf_freeall(buf_T *buf, int flags) // Make sure the buffer isn't closed by autocommands. ++buf->b_locked; + ++buf->b_locked_split; set_bufref(&bufref, buf); if (buf->b_ml.ml_mfp != NULL) { @@ -826,6 +831,7 @@ buf_freeall(buf_T *buf, int flags) return; } --buf->b_locked; + --buf->b_locked_split; // If the buffer was in curwin and the window has changed, go back to that // window, if it still exists. This avoids that ":edit x" triggering a @@ -1718,8 +1724,8 @@ set_curbuf(buf_T *buf, int action) set_bufref(&prevbufref, prevbuf); set_bufref(&newbufref, buf); - // Autocommands may delete the current buffer and/or the buffer we want to go - // to. In those cases don't close the buffer. + // Autocommands may delete the current buffer and/or the buffer we want to + // go to. In those cases don't close the buffer. if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) || (bufref_valid(&prevbufref) && bufref_valid(&newbufref) diff --git a/src/errors.h b/src/errors.h index e6d7ab26c8..ec038ec24e 100644 --- a/src/errors.h +++ b/src/errors.h @@ -353,3 +353,5 @@ EXTERN char e_missing_return_type[] INIT(= N_("E1157: Missing return type")); EXTERN char e_cannot_use_flatten_in_vim9_script[] INIT(= N_("E1158: Cannot use flatten() in Vim9 script")); +EXTERN char e_cannot_split_window_when_closing_buffer[] + INIT(= N_("E1159: Cannot split a window when closing the buffer")); diff --git a/src/popupwin.c b/src/popupwin.c index 436238f9ba..47e7338b74 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1941,7 +1941,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) buf->b_p_ul = -1; // no undo buf->b_p_swf = FALSE; // no swap file buf->b_p_bl = FALSE; // unlisted buffer - buf->b_locked = TRUE; + buf->b_locked = TRUE; // prevent deleting the buffer // Avoid that 'buftype' is reset when this buffer is entered. buf->b_p_initialized = TRUE; diff --git a/src/structs.h b/src/structs.h index 6cdfb4fc5c..8d86d11b18 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2633,6 +2633,8 @@ struct file_buffer int b_flags; // various BF_ flags int b_locked; // Buffer is being closed or referenced, don't // let autocommands wipe it out. + int b_locked_split; // Buffer is being closed, don't allow opening + // a new window with it. /* * b_ffname has the full path of the file (NULL for no name). diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index c1d3639538..3109f88bbd 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2761,15 +2761,12 @@ endfunc " Fuzzer found some strange combination that caused a crash. func Test_autocmd_normal_mess() - " TODO: why does this hang on Windows? - CheckNotMSWindows - augroup aucmd_normal_test au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc augroup END - o4 + call assert_fails('o4', 'E1159') silent! H - e xx + call assert_fails('e xx', 'E1159') normal G augroup aucmd_normal_test @@ -2791,7 +2788,7 @@ func Test_autocmd_vimgrep() au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9 augroup END - " TODO: if this is executed directly valgrind reports errors + %bwipe! call assert_fails('lv?a?', 'E926:') augroup aucmd_vimgrep diff --git a/src/version.c b/src/version.c index 01c9efb0ac..c21856080f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2476, /**/ 2475, /**/ diff --git a/src/window.c b/src/window.c index bea4f391a8..58a216daf7 100644 --- a/src/window.c +++ b/src/window.c @@ -769,6 +769,11 @@ check_split_disallowed() emsg(_("E242: Can't split a window while closing another")); return FAIL; } + if (curwin->w_buffer->b_locked_split) + { + emsg(_(e_cannot_split_window_when_closing_buffer)); + return FAIL; + } return OK; } @@ -793,6 +798,9 @@ win_split(int size, int flags) if (ERROR_IF_ANY_POPUP_WINDOW) return FAIL; + if (check_split_disallowed() == FAIL) + return FAIL; + // When the ":tab" modifier was used open a new tab page instead. if (may_open_tabpage() == OK) return OK; @@ -804,8 +812,6 @@ win_split(int size, int flags) emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; } - if (check_split_disallowed() == FAIL) - return FAIL; // When creating the help window make a snapshot of the window layout. // Otherwise clear the snapshot, it's now invalid. From dd07c02232e91ee963b91a4477179d4b9548b862 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 13:32:46 +0100 Subject: [PATCH 02/11] patch 8.2.2477: autocommand tests hang on MS-Windows Problem: Autocommand tests hang on MS-Windows. Solution: Skip a couple of tests. Fix file name. --- src/testdir/test_autocmd.vim | 8 +++++++- src/version.c | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 3109f88bbd..e4f67f4fc6 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2761,6 +2761,9 @@ endfunc " Fuzzer found some strange combination that caused a crash. func Test_autocmd_normal_mess() + " For unknown reason this hangs on MS-Windows + CheckNotMSWindows + augroup aucmd_normal_test au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc augroup END @@ -2775,6 +2778,9 @@ func Test_autocmd_normal_mess() endfunc func Test_autocmd_closing_cmdwin() + " For unknown reason this hangs on MS-Windows + CheckNotMSWindows + au BufWinLeave * nested q call assert_fails("norm 7q?\n", 'E855:') @@ -2789,7 +2795,7 @@ func Test_autocmd_vimgrep() au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9 augroup END %bwipe! - call assert_fails('lv?a?', 'E926:') + call assert_fails('lv ?a? foo', 'E926:') augroup aucmd_vimgrep au! diff --git a/src/version.c b/src/version.c index c21856080f..7a91c9bae8 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2477, /**/ 2476, /**/ From 0dc5f603e9b86da9fe5798c231d8d6170501516e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 14:01:35 +0100 Subject: [PATCH 03/11] patch 8.2.2478: MS-Windows: backup files for plugins are loaded Problem: MS-Windows: backup files for plugins are loaded. Solution: Do not use the alternate file name for files ending in "~". --- src/filepath.c | 5 ++++- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/filepath.c b/src/filepath.c index 81fe74924b..8e54e5bcf8 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -3360,7 +3360,10 @@ dos_expandpath( if (p == NULL) break; // out of memory - if (*wfb.cAlternateFileName == NUL) + // Do not use the alternate filename when the file name ends in '~', + // because it picks up backup files: short name for "foo.vim~" is + // "foo~1.vim", which matches "*.vim". + if (*wfb.cAlternateFileName == NUL || p[STRLEN(p) - 1] == '~') p_alt = NULL; else p_alt = utf16_to_enc(wfb.cAlternateFileName, NULL); diff --git a/src/version.c b/src/version.c index 7a91c9bae8..ae61a32c86 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2478, /**/ 2477, /**/ From 00385114dbd6a3d59516baa02e1ea86a1e7ee70e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 14:31:06 +0100 Subject: [PATCH 04/11] patch 8.2.2479: set/getbufline test fails without the job feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: set/getbufline test fails without the job feature. Solution: Check whether the job feature is supported. (Dominique Pellé, closes #7790) --- src/testdir/test_bufline.vim | 12 +++++++----- src/testdir/test_vim9_builtin.vim | 12 +++++++----- src/version.c | 2 ++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim index b2de198ef0..5df5288184 100644 --- a/src/testdir/test_bufline.vim +++ b/src/testdir/test_bufline.vim @@ -40,11 +40,13 @@ func Test_setbufline_getbufline() call assert_equal([], getbufline(b, 6)) call assert_equal([], getbufline(b, 2, 1)) - call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()]) - call assert_equal(["function('eval')", - \ "{'key': 123}", - \ "no process"], - \ getbufline(b, 2, 4)) + if has('job') + call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()]) + call assert_equal(["function('eval')", + \ "{'key': 123}", + \ "no process"], + \ getbufline(b, 2, 4)) + endif exe "bwipe! " . b endfunc diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 06839c0c51..eb36bd77a1 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -824,11 +824,13 @@ def Test_set_get_bufline() assert_equal([], getbufline(b, 6)) assert_equal([], getbufline(b, 2, 1)) - setbufline(b, 2, [function('eval'), {key: 123}, test_null_job()]) - assert_equal(["function('eval')", - "{'key': 123}", - "no process"], - getbufline(b, 2, 4)) + if has('job') + setbufline(b, 2, [function('eval'), {key: 123}, test_null_job()]) + assert_equal(["function('eval')", + "{'key': 123}", + "no process"], + getbufline(b, 2, 4)) + endif exe 'bwipe! ' .. b END diff --git a/src/version.c b/src/version.c index ae61a32c86..383e15a187 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2479, /**/ 2478, /**/ From c3fc75db023f2acd0b82b7eebffd7ed89e8001ed Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 15:28:09 +0100 Subject: [PATCH 05/11] patch 8.2.2480: Vim9: some errors for white space do not show context Problem: Vim9: some errors for white space do not show context. Solution: Include the text at the error. --- src/dict.c | 4 ++-- src/errors.h | 4 ++-- src/list.c | 2 +- src/userfunc.c | 8 ++++---- src/version.c | 2 ++ src/vim9compile.c | 12 ++++++------ src/vim9script.c | 2 +- src/vim9type.c | 6 ++++-- 8 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/dict.c b/src/dict.c index 260f229850..b40aaef0da 100644 --- a/src/dict.c +++ b/src/dict.c @@ -970,7 +970,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) } if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1])) { - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", *arg); clear_tv(&tvkey); goto failret; } @@ -1012,7 +1012,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) { if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1])) { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", *arg); goto failret; } *arg = skipwhite(*arg + 1); diff --git a/src/errors.h b/src/errors.h index ec038ec24e..ed267fd398 100644 --- a/src/errors.h +++ b/src/errors.h @@ -175,8 +175,8 @@ EXTERN char e_separator_mismatch_str[] INIT(= N_("E1067: Separator mismatch: %s")); EXTERN char e_no_white_space_allowed_before_str[] INIT(= N_("E1068: No white space allowed before '%s'")); -EXTERN char e_white_space_required_after_str[] - INIT(= N_("E1069: White space required after '%s'")); +EXTERN char e_white_space_required_after_str_str[] + INIT(= N_("E1069: White space required after '%s': %s")); EXTERN char e_missing_from[] INIT(= N_("E1070: Missing \"from\"")); EXTERN char e_invalid_string_after_from[] diff --git a/src/list.c b/src/list.c index c51c99bc90..c93a66d81b 100644 --- a/src/list.c +++ b/src/list.c @@ -1311,7 +1311,7 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) { if (vim9script && !IS_WHITE_OR_NUL((*arg)[1]) && (*arg)[1] != ']') { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", *arg); goto failret; } *arg = skipwhite(*arg + 1); diff --git a/src/userfunc.c b/src/userfunc.c index bdf4064263..e220781b1f 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -126,7 +126,7 @@ one_function_arg( ++p; if (!skip && !VIM_ISWHITE(*p)) { - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", p - 1); return arg; } type = skipwhite(p); @@ -297,7 +297,7 @@ get_function_args( if (!skip && in_vim9script() && !IS_WHITE_OR_NUL(*p) && *p != endchar) { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", p - 1); goto err_ret; } } @@ -487,7 +487,7 @@ skip_arrow( if (white_error != NULL && !VIM_ISWHITE(s[1])) { *white_error = TRUE; - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", s); return NULL; } s = skipwhite(s + 1); @@ -884,7 +884,7 @@ get_func_tv( break; if (vim9script && !IS_WHITE_OR_NUL(argp[1])) { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", argp); ret = FAIL; break; } diff --git a/src/version.c b/src/version.c index 383e15a187..871e04892c 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2480, /**/ 2479, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 6a1d8d9e78..3c24fdb06c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2807,7 +2807,7 @@ compile_arguments(char_u **arg, cctx_T *cctx, int *argcount) { ++p; if (*p != NUL && !VIM_ISWHITE(*p)) - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", p - 1); } else must_end = TRUE; @@ -3073,7 +3073,7 @@ compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) ++p; if (*p != ']' && !IS_WHITE_OR_NUL(*p)) { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", p - 1); return FAIL; } } @@ -3242,7 +3242,7 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) whitep = *arg + 1; if (!IS_WHITE_OR_NUL(*whitep)) { - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", *arg); return FAIL; } @@ -3279,10 +3279,10 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) whitep = *arg + 1; if (!IS_WHITE_OR_NUL(*whitep)) { - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), ",", *arg); return FAIL; } - *arg = skipwhite(*arg + 1); + *arg = skipwhite(whitep); } *arg = *arg + 1; @@ -5711,7 +5711,7 @@ compile_lhs( // parse optional type: "let var: type = expr" if (!VIM_ISWHITE(var_end[1])) { - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", var_end); return FAIL; } p = skipwhite(var_end + 1); diff --git a/src/vim9script.c b/src/vim9script.c index 010b4bfdb3..387c9bedc4 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -629,7 +629,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg) } if (!VIM_ISWHITE(p[1])) { - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), ":", p); return arg + STRLEN(arg); } name = vim_strnsave(arg, p - arg); diff --git a/src/vim9type.c b/src/vim9type.c index 1374cee1b1..dbe7db92cf 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -788,7 +788,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error) if (!VIM_ISWHITE(*p)) { if (give_error) - semsg(_(e_white_space_required_after_str), ","); + semsg(_(e_white_space_required_after_str_str), + ",", p - 1); return NULL; } } @@ -815,7 +816,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error) // parse return type ++*arg; if (!VIM_ISWHITE(**arg) && give_error) - semsg(_(e_white_space_required_after_str), ":"); + semsg(_(e_white_space_required_after_str_str), + ":", *arg - 1); *arg = skipwhite(*arg); ret_type = parse_type(arg, type_gap, give_error); if (ret_type == NULL) From 4f53b79bf5f8b0de7c6933fd157894ba7a53f35e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 15:59:49 +0100 Subject: [PATCH 06/11] patch 8.2.2481: Vim9: confusing error when variable arguments have default Problem: Vim9: confusing error when variable arguments have a default value. Solution: Give a specific error message. (closes #7793) --- src/testdir/test_vim9_func.vim | 10 ++++++++++ src/userfunc.c | 5 +++++ src/version.c | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 73ff693fa9..cdaba5af74 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -781,6 +781,16 @@ def Test_call_def_varargs() Func(1, 'a') END CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch') + + lines =<< trim END + vim9script + def Func( # some comment + ...l = [] + ) + echo l + enddef + END + CheckScriptFailure(lines, 'E1160:') enddef let s:value = '' diff --git a/src/userfunc.c b/src/userfunc.c index e220781b1f..82df0bb960 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -241,6 +241,11 @@ get_function_args( skip); if (p == arg) break; + if (*skipwhite(p) == '=') + { + emsg(_(e_cannot_use_default_for_variable_arguments)); + break; + } } } else diff --git a/src/version.c b/src/version.c index 871e04892c..c6f44a401f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2481, /**/ 2480, /**/ From a5a1ec1826c0e43d0282ba4d35c155a97bab3e27 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 16:05:47 +0100 Subject: [PATCH 07/11] patch 8.2.2482: build error Problem: Build error. Solution: Add new error message. --- src/errors.h | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/errors.h b/src/errors.h index ed267fd398..921b9df5cc 100644 --- a/src/errors.h +++ b/src/errors.h @@ -355,3 +355,5 @@ EXTERN char e_cannot_use_flatten_in_vim9_script[] INIT(= N_("E1158: Cannot use flatten() in Vim9 script")); EXTERN char e_cannot_split_window_when_closing_buffer[] INIT(= N_("E1159: Cannot split a window when closing the buffer")); +EXTERN char e_cannot_use_default_for_variable_arguments[] + INIT(= N_("E1160: Cannot use a default for variable arguments")); diff --git a/src/version.c b/src/version.c index c6f44a401f..17ab64a912 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2482, /**/ 2481, /**/ From 6628b7ebff1cfcb476ce96852a7d2b095872826c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 16:33:35 +0100 Subject: [PATCH 08/11] patch 8.2.2483: Vim9: type error for misformed expression Problem: Vim9: type error for misformed expression. Solution: Check for end of command before checking type. (closes #7795) --- src/testdir/test_vim9_script.vim | 22 ++++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 15 +++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index d25bb47aaa..72e12740ad 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1743,6 +1743,21 @@ def Test_if_elseif_else_fails() CheckDefFailure(['endif'], 'E580:') CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:') CheckDefFailure(['if true', 'echo 1'], 'E171:') + + var lines =<< trim END + var s = '' + if s = '' + endif + END + CheckDefFailure(lines, 'E488:') + + lines =<< trim END + var s = '' + if s == '' + elseif s = '' + endif + END + CheckDefFailure(lines, 'E488:') enddef let g:bool_true = v:true @@ -2200,6 +2215,13 @@ def Test_while_loop_fails() CheckDefFailure(['break'], 'E587:') CheckDefFailure(['if true', 'break'], 'E587:') CheckDefFailure(['while 1', 'echo 3'], 'E170:') + + var lines =<< trim END + var s = '' + while s = '' + endwhile + END + CheckDefFailure(lines, 'E488:') enddef def Test_interrupt_loop() diff --git a/src/version.c b/src/version.c index 17ab64a912..4c53107001 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2483, /**/ 2482, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 3c24fdb06c..7a220a851f 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6701,6 +6701,11 @@ compile_if(char_u *arg, cctx_T *cctx) clear_ppconst(&ppconst); return NULL; } + if (!ends_excmd2(arg, skipwhite(p))) + { + semsg(_(e_trailing_arg), p); + return NULL; + } if (cctx->ctx_skip == SKIP_YES) clear_ppconst(&ppconst); else if (instr->ga_len == instr_count && ppconst.pp_used == 1) @@ -6825,6 +6830,11 @@ compile_elseif(char_u *arg, cctx_T *cctx) return NULL; } cctx->ctx_skip = save_skip; + if (!ends_excmd2(arg, skipwhite(p))) + { + semsg(_(e_trailing_arg), p); + return NULL; + } if (scope->se_skip_save == SKIP_YES) clear_ppconst(&ppconst); else if (instr->ga_len == instr_count && ppconst.pp_used == 1) @@ -7237,6 +7247,11 @@ compile_while(char_u *arg, cctx_T *cctx) // compile "expr" if (compile_expr0(&p, cctx) == FAIL) return NULL; + if (!ends_excmd2(arg, skipwhite(p))) + { + semsg(_(e_trailing_arg), p); + return NULL; + } if (bool_on_stack(cctx) == FAIL) return FAIL; From dee37dc733df444df1950eb922a35560e4b113d6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 16:40:05 +0100 Subject: [PATCH 09/11] patch 8.2.2484: Vim9: Cannot use a comment starting with #{ Problem: Vim9: Cannot use a comment starting with #{ after an expression. Solution: Remove the check for "{" since #{ dictionaries are not supported. --- src/ex_docmd.c | 3 +-- src/testdir/test_vim9_script.vim | 4 ++++ src/version.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index a2e53ad349..9409d7c5e0 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5212,8 +5212,7 @@ ends_excmd2(char_u *cmd_start UNUSED, char_u *cmd) return TRUE; #ifdef FEAT_EVAL if (in_vim9script()) - return c == '#' && cmd[1] != '{' - && (cmd == cmd_start || VIM_ISWHITE(cmd[-1])); + return c == '#' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1])); #endif return c == '"'; } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 72e12740ad..7f1e71dc68 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2205,6 +2205,10 @@ def Test_while_loop() result ..= cnt .. '_' endwhile assert_equal('1_3_', result) + + var s = '' + while s == 'x' #{comment + endwhile enddef def Test_while_loop_fails() diff --git a/src/version.c b/src/version.c index 4c53107001..cbef3daf67 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2484, /**/ 2483, /**/ From 0123cc1e1422003704cc6941916dd75e61fb7976 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 17:17:58 +0100 Subject: [PATCH 10/11] patch 8.2.2485: when sourcing a script again the script version isn't reset Problem: When sourcing a script again the script version isn't reset. Solution: Set sn_version to one when sourcing a script again. Clear sn_save_cpo properly. (closes #7608) --- src/scriptfile.c | 5 ++++- src/testdir/test_vim9_script.vim | 15 ++++++++++++++- src/version.c | 2 ++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index c8a23d55a3..82ae42a1a6 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1319,6 +1319,9 @@ do_source( } // imports can be redefined once mark_imports_for_reload(sid); + + // reset version, "vim9script" may have been added or removed. + si->sn_version = 1; } else { @@ -1457,7 +1460,7 @@ almosttheend: if (si->sn_save_cpo != NULL) { set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, 0); - CLEAR_POINTER(si->sn_save_cpo); + VIM_CLEAR(si->sn_save_cpo); } restore_funccal(); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 7f1e71dc68..42a0d61dd0 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2207,7 +2207,7 @@ def Test_while_loop() assert_equal('1_3_', result) var s = '' - while s == 'x' #{comment + while s == 'x' #{comment} endwhile enddef @@ -3155,6 +3155,19 @@ def Test_restoring_cpo() delete('Xsourced') delete('Xclose') delete('Xdone') + + writefile(['vim9script'], 'XanotherScript') + set cpo=aABceFsMny> + edit XanotherScript + so % + assert_equal('aABceFsMny>', &cpo) + :1del + w + so % + assert_equal('aABceFsMny>', &cpo) + + delete('XanotherScript') + set cpo&vim enddef diff --git a/src/version.c b/src/version.c index cbef3daf67..ca79c64dd8 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2485, /**/ 2484, /**/ From ba98fb54aefada4c36390add4c7dd90b93e7e5bb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Feb 2021 18:06:29 +0100 Subject: [PATCH 11/11] patch 8.2.2486: Vim9: some errors for white space do not show context Problem: Vim9: some errors for white space do not show context. Solution: Include the text at the error. --- src/dict.c | 4 ++-- src/errors.h | 4 ++-- src/list.c | 3 ++- src/userfunc.c | 4 ++-- src/version.c | 2 ++ src/vim9compile.c | 10 +++++----- src/vim9type.c | 5 +++-- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/dict.c b/src/dict.c index b40aaef0da..b36b2bf6dd 100644 --- a/src/dict.c +++ b/src/dict.c @@ -945,7 +945,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) if (**arg != ':') { if (*skipwhite(*arg) == ':') - semsg(_(e_no_white_space_allowed_before_str), ":"); + semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg); else semsg(_(e_missing_dict_colon), *arg); clear_tv(&tvkey); @@ -1025,7 +1025,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) if (!had_comma) { if (**arg == ',') - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), ",", *arg); else semsg(_(e_missing_dict_comma), *arg); goto failret; diff --git a/src/errors.h b/src/errors.h index 921b9df5cc..9b9a782753 100644 --- a/src/errors.h +++ b/src/errors.h @@ -173,8 +173,8 @@ EXTERN char e_cannot_declare_a_register_str[] INIT(= N_("E1066: Cannot declare a register: %s")); EXTERN char e_separator_mismatch_str[] INIT(= N_("E1067: Separator mismatch: %s")); -EXTERN char e_no_white_space_allowed_before_str[] - INIT(= N_("E1068: No white space allowed before '%s'")); +EXTERN char e_no_white_space_allowed_before_str_str[] + INIT(= N_("E1068: No white space allowed before '%s': %s")); EXTERN char e_white_space_required_after_str_str[] INIT(= N_("E1069: White space required after '%s': %s")); EXTERN char e_missing_from[] diff --git a/src/list.c b/src/list.c index c93a66d81b..4d33aa6e08 100644 --- a/src/list.c +++ b/src/list.c @@ -1328,7 +1328,8 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) if (do_error) { if (**arg == ',') - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), + ",", *arg); else semsg(_("E696: Missing comma in List: %s"), *arg); } diff --git a/src/userfunc.c b/src/userfunc.c index 82df0bb960..c9b15fd638 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -878,7 +878,7 @@ get_func_tv( { if (*argp != ',' && *skipwhite(argp) == ',') { - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), ",", argp); ret = FAIL; break; } @@ -3214,7 +3214,7 @@ define_function(exarg_T *eap, char_u *name_arg) if ((vim9script || eap->cmdidx == CMD_def) && VIM_ISWHITE(p[-1])) { - semsg(_(e_no_white_space_allowed_before_str), "("); + semsg(_(e_no_white_space_allowed_before_str_str), "(", p - 1); goto ret_free; } diff --git a/src/version.c b/src/version.c index ca79c64dd8..e203038df7 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2486, /**/ 2485, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 7a220a851f..512f7246c2 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2800,7 +2800,7 @@ compile_arguments(char_u **arg, cctx_T *cctx, int *argcount) if (*p != ',' && *skipwhite(p) == ',') { - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), ",", p); p = skipwhite(p); } if (*p == ',') @@ -3055,7 +3055,7 @@ compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) } if (*p == ',') { - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), ",", p); return FAIL; } if (*p == ']') @@ -3234,7 +3234,7 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (**arg != ':') { if (*skipwhite(*arg) == ':') - semsg(_(e_no_white_space_allowed_before_str), ":"); + semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg); else semsg(_(e_missing_dict_colon), *arg); return FAIL; @@ -3273,7 +3273,7 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) } if (IS_WHITE_OR_NUL(*whitep)) { - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep); return FAIL; } whitep = *arg + 1; @@ -4270,7 +4270,7 @@ compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (**arg != '>') { if (*skipwhite(*arg) == '>') - semsg(_(e_no_white_space_allowed_before_str), ">"); + semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg); else emsg(_(e_missing_gt)); return FAIL; diff --git a/src/vim9type.c b/src/vim9type.c index dbe7db92cf..1a20ef5796 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -638,7 +638,7 @@ parse_type_member( if (give_error) { if (*skipwhite(*arg) == '<') - semsg(_(e_no_white_space_allowed_before_str), "<"); + semsg(_(e_no_white_space_allowed_before_str_str), "<", *arg); else emsg(_(e_missing_type)); } @@ -779,7 +779,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error) if (*p != ',' && *skipwhite(p) == ',') { if (give_error) - semsg(_(e_no_white_space_allowed_before_str), ","); + semsg(_(e_no_white_space_allowed_before_str_str), + ",", p); return NULL; } if (*p == ',')