]> granicus.if.org Git - vim/commitdiff
patch 8.2.1373: Vim9: no error for assigning to non-existing script var v8.2.1373
authorBram Moolenaar <Bram@vim.org>
Wed, 5 Aug 2020 12:34:14 +0000 (14:34 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 5 Aug 2020 12:34:14 +0000 (14:34 +0200)
Problem:    Vim9: no error for assigning to non-existing script var.
Solution:   Check that in Vim9 script the variable was defined. (closes #6630)

src/structs.h
src/testdir/test_vim9_script.vim
src/userfunc.c
src/version.c
src/vim9compile.c

index 7e34d809981bde7577e51b0af743d80a701668d7..a80de6a71f92e5dafd5d707e75f8c9846c7f8ef8 100644 (file)
@@ -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
index 64ac3bbd925c1bdb5fd27808720ee58b71404061..f99333c0cbb4fd9627953ac664460b2eeaf2e12f 100644 (file)
@@ -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)
 
index 43aa146a9827bd5a801336fd77d4af70679af43d..684a805d8abaf0197451719e285f6bbc3b64de4f 100644 (file)
@@ -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)
     {
index 1e23a08ad609dd16b6d3bff6e1fd04a7a4c4ee0e..7b1b8d8c2199ab8dd1d0f8c6852790afbb1638fe 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1373,
 /**/
     1372,
 /**/
index f8381d7837d3bc39d85e2b25a1436731999a8181..dc10b4851b8b5caca7930e5877956f10a5d9f6bd 100644 (file)
@@ -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;
+                   }
                }
            }