# HG changeset patch # User Bram Moolenaar # Date 1585769403 -7200 # Node ID 8a7bede7b138c76289d9f400c6c9a2769fd9450e # Parent 7f8a267721e43818006faf3abc498e7e0af57e9d patch 8.2.0492: Vim9: some error messages not tested Commit: https://github.com/vim/vim/commit/a8c1770469504ae66c80bbdb03b6b31641215848 Author: Bram Moolenaar Date: Wed Apr 1 21:17:24 2020 +0200 patch 8.2.0492: Vim9: some error messages not tested Problem: Vim9: some error messages not tested. Solution: Add more tests. Remove dead code. Fix uncovered bugs. diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -106,6 +106,8 @@ func Test_expr2_fails() call CheckDefFailure("let x = 1||2", msg) call CheckDefFailure("let x = 1 ||2", msg) call CheckDefFailure("let x = 1|| 2", msg) + + call CheckDefFailure("let x = 1 || xxx", 'E1001:') endfunc " test && @@ -877,7 +879,7 @@ func Test_expr7_fails() call CheckDefFailure("let x = 123->{x -> x + 5) }", "E451:") call CheckDefFailure("let x = ¬exist", 'E113:') - call CheckDefExecFailure("&grepprg = [343]", 'E1051:') + call CheckDefFailure("&grepprg = [343]", 'E1013:') call CheckDefExecFailure("echo s:doesnt_exist", 'E121:') call CheckDefExecFailure("echo g:doesnt_exist", 'E121:') diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -31,6 +31,8 @@ endfunc let s:appendToMe = 'xxx' let s:addToMe = 111 let g:existing = 'yes' +let g:inc_counter = 1 +let $SOME_ENV_VAR = 'some' def Test_assignment() let bool1: bool = true @@ -94,6 +96,27 @@ def Test_assignment() assert_equal(333, s:addToMe) s:newVar = 'new' assert_equal('new', s:newVar) + + set ts=7 + &ts += 1 + assert_equal(8, &ts) + call CheckDefFailure(['¬ex += 3'], 'E113:') + call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:') + call CheckDefFailure(['&path += 3'], 'E1013:') + + g:inc_counter += 1 + assert_equal(2, g:inc_counter) + + $SOME_ENV_VAR ..= 'more' + assert_equal('somemore', $SOME_ENV_VAR) + call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:') + call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:') + + @a = 'areg' + @a ..= 'add' + assert_equal('aregadd', @a) + call CheckDefFailure(['@a += "more"'], 'E1013:') + call CheckDefFailure(['@a += 123'], 'E1013:') enddef func Test_assignment_failure() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 492, +/**/ 491, /**/ 490, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -277,6 +277,25 @@ get_dict_type(type_T *member_type, garra return type; } +/* + * Return the type_T for a typval. Only for primitive types. + */ + static type_T * +typval2type(typval_T *tv) +{ + if (tv->v_type == VAR_NUMBER) + return &t_number; + if (tv->v_type == VAR_BOOL) + return &t_bool; + if (tv->v_type == VAR_STRING) + return &t_string; + if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles + return &t_list_string; + if (tv->v_type == VAR_DICT) // e.g. for v:completed_item + return &t_dict_any; + return &t_any; +} + ///////////////////////////////////////////////////////////////////// // Following generate_ functions expect the caller to call ga_grow(). @@ -1402,7 +1421,7 @@ parse_type_member(char_u **arg, type_T * /* * Parse a type at "arg" and advance over it. - * Return NULL for failure. + * Return &t_any for failure. */ type_T * parse_type(char_u **arg, garray_T *type_list) @@ -3462,7 +3481,7 @@ compile_assignment(char_u *arg, exarg_T int vimvaridx = -1; int oplen = 0; int heredoc = FALSE; - type_T *type; + type_T *type = &t_any; lvar_T *lvar; char_u *name; char_u *sp; @@ -3532,6 +3551,7 @@ compile_assignment(char_u *arg, exarg_T else if (*arg == '$') { dest = dest_env; + type = &t_string; if (is_decl) { semsg(_("E1065: Cannot declare an environment variable: %s"), name); @@ -3546,6 +3566,7 @@ compile_assignment(char_u *arg, exarg_T goto theend; } dest = dest_reg; + type = &t_string; if (is_decl) { semsg(_("E1066: Cannot declare a register: %s"), name); @@ -3563,6 +3584,8 @@ compile_assignment(char_u *arg, exarg_T } else if (STRNCMP(arg, "v:", 2) == 0) { + typval_T *vtv; + vimvaridx = find_vim_var(name + 2); if (vimvaridx < 0) { @@ -3570,6 +3593,8 @@ compile_assignment(char_u *arg, exarg_T goto theend; } dest = dest_vimvar; + vtv = get_vim_var_tv(vimvaridx); + type = typval2type(vtv); if (is_decl) { semsg(_("E1064: Cannot declare a v: variable: %s"), name); @@ -3625,16 +3650,9 @@ compile_assignment(char_u *arg, exarg_T // parse optional type: "let var: type = expr" p = skipwhite(p + 1); type = parse_type(&p, cctx->ctx_type_list); - if (type == NULL) - goto theend; has_type = TRUE; } - else if (idx < 0) - { - // global and new local default to "any" type - type = &t_any; - } - else + else if (idx >= 0) { lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; type = lvar->lv_type; @@ -3700,7 +3718,9 @@ compile_assignment(char_u *arg, exarg_T } else if (oplen > 0) { - int r; + int r; + type_T *stacktype; + garray_T *stack; // for "+=", "*=", "..=" etc. first load the current value if (*op != '=') @@ -3709,7 +3729,7 @@ compile_assignment(char_u *arg, exarg_T { case dest_option: // TODO: check the option exists - generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type); + generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); break; case dest_global: generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type); @@ -3746,12 +3766,10 @@ compile_assignment(char_u *arg, exarg_T if (r == FAIL) goto theend; + stack = &cctx->ctx_type_stack; + stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; if (idx >= 0 && (is_decl || !has_type)) { - garray_T *stack = &cctx->ctx_type_stack; - type_T *stacktype = - ((type_T **)stack->ga_data)[stack->ga_len - 1]; - lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; if (!has_type) { @@ -3767,6 +3785,8 @@ compile_assignment(char_u *arg, exarg_T if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL) goto theend; } + else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) + goto theend; } else if (cmdidx == CMD_const) { diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -684,6 +684,8 @@ call_def_function( typval_T optval; char_u *name = iptr->isn_arg.string; + // This is not expected to fail, name is checked during + // compilation: don't set SOURCING_LNUM. if (ga_grow(&ectx.ec_stack, 1) == FAIL) goto failed; if (get_option_tv(&name, &optval, TRUE) == FAIL)