diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-08-05 14:34:14 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-08-05 14:34:14 +0200 |
commit | f9b2b49663226235f94f08230fe9023caf80a6e9 (patch) | |
tree | f34be82de9372deb871b09a572157d7dcfefed6e | |
parent | fdac71c5075062f97f77044e9619fa5c907e0327 (diff) |
patch 8.2.1373: Vim9: no error for assigning to non-existing script varv8.2.1373
Problem: Vim9: no error for assigning to non-existing script var.
Solution: Check that in Vim9 script the variable was defined. (closes #6630)
-rw-r--r-- | src/structs.h | 4 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 9 | ||||
-rw-r--r-- | src/userfunc.c | 1 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 88 |
5 files changed, 68 insertions, 36 deletions
diff --git a/src/structs.h b/src/structs.h index 7e34d80998..a80de6a71f 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1594,7 +1594,9 @@ typedef struct int uf_tml_execed; // line being timed was executed # endif sctx_T uf_script_ctx; // SCTX where function was defined, - // used for s: variables + // used for s: variables; sc_version changed + // for :function + int uf_script_ctx_version; // original sc_version of SCTX int uf_refcount; // reference count, see func_name_refcount() funccall_T *uf_scoped; // l: local variables for closure diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 64ac3bbd92..f99333c0cb 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -112,6 +112,15 @@ def Test_assignment() call CheckDefFailure(['let s:var = 123'], 'E1101:') call CheckDefFailure(['let s:var: number'], 'E1101:') + lines =<< trim END + vim9script + def SomeFunc() + s:var = 123 + enddef + defcompile + END + call CheckScriptFailure(lines, 'E1089:') + g:inc_counter += 1 assert_equal(2, g:inc_counter) diff --git a/src/userfunc.c b/src/userfunc.c index 43aa146a98..684a805d8a 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3508,6 +3508,7 @@ def_function(exarg_T *eap, char_u *name_arg) fp->uf_calls = 0; fp->uf_cleared = FALSE; fp->uf_script_ctx = current_sctx; + fp->uf_script_ctx_version = current_sctx.sc_version; fp->uf_script_ctx.sc_lnum += sourcing_lnum_top; if (is_export) { diff --git a/src/version.c b/src/version.c index 1e23a08ad6..7b1b8d8c21 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1373, +/**/ 1372, /**/ 1371, diff --git a/src/vim9compile.c b/src/vim9compile.c index f8381d7837..dc10b4851b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -148,6 +148,7 @@ static char e_syntax_at[] = N_("E1002: Syntax error at %s"); static char e_used_as_arg[] = N_("E1006: %s is used as an argument"); static char e_cannot_use_void[] = N_("E1031: Cannot use void value"); static char e_namespace[] = N_("E1075: Namespace not supported: %s"); +static char e_unknown_var[] = N_("E1089: unknown variable: %s"); static void delete_def_function_contents(dfunc_T *dfunc); static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); @@ -5335,7 +5336,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) else { int idx; - imported_T *import = NULL; for (idx = 0; reserved[idx] != NULL; ++idx) if (STRCMP(reserved[idx], name) == 0) @@ -5374,49 +5374,67 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0) - || lookup_script(var_start, varlen) == OK - || (import = find_imported(var_start, varlen, cctx)) - != NULL) + else { - char_u *rawname = name + (name[1] == ':' ? 2 : 0); - - if (is_decl) + int script_namespace = varlen > 1 + && STRNCMP(var_start, "s:", 2) == 0; + int script_var = (script_namespace + ? lookup_script(var_start + 2, varlen - 2) + : lookup_script(var_start, varlen)) == OK; + imported_T *import = + find_imported(var_start, varlen, cctx); + + if (script_namespace || script_var || import != NULL) { - if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)) - semsg(_("E1101: Cannot declare a script variable in a function: %s"), + char_u *rawname = name + (name[1] == ':' ? 2 : 0); + + if (is_decl) + { + if (script_namespace) + semsg(_("E1101: Cannot declare a script variable in a function: %s"), name); - else - semsg(_("E1054: Variable already declared in the script: %s"), + else + semsg(_("E1054: Variable already declared in the script: %s"), name); - goto theend; - } - dest = dest_script; + goto theend; + } + else if (cctx->ctx_ufunc->uf_script_ctx_version + == SCRIPT_VERSION_VIM9 + && script_namespace + && !script_var && import == NULL) + { + semsg(_(e_unknown_var), name); + goto theend; + } + + dest = dest_script; - // existing script-local variables should have a type - scriptvar_sid = current_sctx.sc_sid; - if (import != NULL) - scriptvar_sid = import->imp_sid; - scriptvar_idx = get_script_item_idx(scriptvar_sid, + // existing script-local variables should have a type + scriptvar_sid = current_sctx.sc_sid; + if (import != NULL) + scriptvar_sid = import->imp_sid; + scriptvar_idx = get_script_item_idx(scriptvar_sid, rawname, TRUE); - if (scriptvar_idx >= 0) - { - scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid); - svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + if (scriptvar_idx >= 0) + { + scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid); + svar_T *sv = + ((svar_T *)si->sn_var_vals.ga_data) + scriptvar_idx; - type = sv->sv_type; + type = sv->sv_type; + } } - } - else if (name[1] == ':' && name[2] != NUL) - { - semsg(_("E1082: Cannot use a namespaced variable: %s"), + else if (name[1] == ':' && name[2] != NUL) + { + semsg(_("E1082: Cannot use a namespaced variable: %s"), name); - goto theend; - } - else if (!is_decl) - { - semsg(_("E1089: unknown variable: %s"), name); - goto theend; + goto theend; + } + else if (!is_decl) + { + semsg(_(e_unknown_var), name); + goto theend; + } } } |