]> granicus.if.org Git - vim/commitdiff
patch 8.2.4666: Vim9: assignment not recognized in skipped block v8.2.4666
authorBram Moolenaar <Bram@vim.org>
Sat, 2 Apr 2022 18:43:57 +0000 (19:43 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 2 Apr 2022 18:43:57 +0000 (19:43 +0100)
Problem:    Vim9: assignment not recognized in skipped block.
Solution:   When skipping assume identifier exists. (closes #10059)

src/proto/vim9compile.pro
src/testdir/test_vim9_cmd.vim
src/testdir/test_vim9_script.vim
src/version.c
src/vim9cmds.c
src/vim9compile.c

index 94ef8277e8314e96388a1b84e6aad04ad6092b0d..0f3094f8cf64fec6efa75c11d2504a4c234ebac0 100644 (file)
@@ -18,9 +18,9 @@ void fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx);
 int func_needs_compiling(ufunc_T *ufunc, compiletype_T compile_type);
 int assignment_len(char_u *p, int *heredoc);
 void vim9_declare_error(char_u *name);
-int get_var_dest(char_u *name, assign_dest_T *dest, int cmdidx, int *option_scope, int *vimvaridx, type_T **type, cctx_T *cctx);
-int compile_lhs(char_u *var_start, lhs_T *lhs, int cmdidx, int heredoc, int oplen, cctx_T *cctx);
-int compile_assign_lhs(char_u *var_start, lhs_T *lhs, int cmdidx, int is_decl, int heredoc, int oplen, cctx_T *cctx);
+int get_var_dest(char_u *name, assign_dest_T *dest, cmdidx_T cmdidx, int *option_scope, int *vimvaridx, type_T **type, cctx_T *cctx);
+int compile_lhs(char_u *var_start, lhs_T *lhs, cmdidx_T cmdidx, int heredoc, int has_cmd, int oplen, cctx_T *cctx);
+int compile_assign_lhs(char_u *var_start, lhs_T *lhs, cmdidx_T cmdidx, int is_decl, int heredoc, int has_cmd, int oplen, cctx_T *cctx);
 int compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx);
 int compile_assign_unlet(char_u *var_start, lhs_T *lhs, int is_assign, type_T *rhs_type, cctx_T *cctx);
 compiletype_T get_compile_type(ufunc_T *ufunc);
index 38ee7f23feb868cceeff391d13810cc2b4164c9b..56d3bf231b79eca662812db8f1cc8494f25bc62e 100644 (file)
@@ -1363,7 +1363,12 @@ def Test_command_not_recognized()
   var lines =<< trim END
     d.key = 'asdf'
   END
-  v9.CheckDefFailure(lines, 'E1146:', 1)
+  v9.CheckDefFailure(lines, 'E1089: Unknown variable: d', 1)
+
+  lines =<< trim END
+    d['key'] = 'asdf'
+  END
+  v9.CheckDefFailure(lines, 'E1089: Unknown variable: d', 1)
 
   lines =<< trim END
     if 0
@@ -1371,11 +1376,6 @@ def Test_command_not_recognized()
     endif
   END
   v9.CheckDefSuccess(lines)
-
-  lines =<< trim END
-    d['key'] = 'asdf'
-  END
-  v9.CheckDefFailure(lines, 'E1146:', 1)
 enddef
 
 def Test_magic_not_used()
index 71cef1ee9e6016ac4b7769938521990bc8d801a1..54864587fe87884fc650a5819008e71ba90664d2 100644 (file)
@@ -2003,6 +2003,19 @@ def Test_for_skipped_block()
       assert_equal([3, 4], result)
     enddef
     DefFalse()
+
+    def BuildDiagrams()
+      var diagrams: list<any>
+      if false
+        var max = 0
+        for v in diagrams
+          var l = 3
+          if max < l | max = l | endif
+          v->add(l)
+        endfor
+      endif
+    enddef
+    BuildDiagrams()
   END
   v9.CheckDefAndScriptSuccess(lines)
 enddef
index 753eef3036b33adea8f0fd887bc4843ddcf3edf0..b6fd0474eebf173c81c98ecf1edda29dd1cdac06 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4666,
 /**/
     4665,
 /**/
index 483b1f34b28bd0bd77be30e2a8d37b09dcc6a07e..a853d9b0be33dd0d55a9c08e15a6671392bf3965 100644 (file)
@@ -139,7 +139,7 @@ compile_unlet(
        //
        // Figure out the LHS type and other properties.
        //
-       ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, 0, cctx);
+       ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
 
        // Use the info in "lhs" to unlet the item at the index in the
        // list or dict.
@@ -2160,7 +2160,7 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
        arg = skipwhite(arg);
 
        if (compile_assign_lhs(arg, lhs, CMD_redir,
-                                               FALSE, FALSE, 1, cctx) == FAIL)
+                                        FALSE, FALSE, FALSE, 1, cctx) == FAIL)
            return NULL;
        if (need_type(&t_string, lhs->lhs_member_type,
                                            -1, 0, cctx, FALSE, FALSE) == FAIL)
index 4e3a1bfb1f556a41613e2f3b8251b001bef253d9..205d9a9a63a008ddf90c6cf2026e5d85b046a736 100644 (file)
@@ -279,7 +279,8 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
 
 /*
  * Return TRUE if "name" is a local variable, argument, script variable,
- * imported or function.
+ * imported or function.  Or commands are being skipped, a declaration may have
+ * been skipped then.
  */
     static int
 item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx)
@@ -1109,7 +1110,7 @@ vim9_declare_error(char_u *name)
 get_var_dest(
        char_u          *name,
        assign_dest_T   *dest,
-       int             cmdidx,
+       cmdidx_T        cmdidx,
        int             *option_scope,
        int             *vimvaridx,
        type_T          **type,
@@ -1225,7 +1226,7 @@ get_var_dest(
 }
 
     static int
-is_decl_command(int cmdidx)
+is_decl_command(cmdidx_T cmdidx)
 {
     return cmdidx == CMD_let || cmdidx == CMD_var
                                 || cmdidx == CMD_final || cmdidx == CMD_const;
@@ -1238,12 +1239,13 @@ is_decl_command(int cmdidx)
  */
     int
 compile_lhs(
-       char_u  *var_start,
-       lhs_T   *lhs,
-       int     cmdidx,
-       int     heredoc,
-       int     oplen,
-       cctx_T  *cctx)
+       char_u      *var_start,
+       lhs_T       *lhs,
+       cmdidx_T    cmdidx,
+       int         heredoc,
+       int         has_cmd,        // "var" before "var_start"
+       int         oplen,
+       cctx_T      *cctx)
 {
     char_u     *var_end;
     int                is_decl = is_decl_command(cmdidx);
@@ -1493,7 +1495,8 @@ compile_lhs(
            semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name);
            return FAIL;
        }
-       if (!is_decl)
+       if (!is_decl || (lhs->lhs_has_index && !has_cmd
+                                               && cctx->ctx_skip != SKIP_YES))
        {
            semsg(_(e_unknown_variable_str), lhs->lhs_name);
            return FAIL;
@@ -1520,9 +1523,12 @@ compile_lhs(
        char_u  *p;
 
        // Something follows after the variable: "var[idx]" or "var.key".
-       if (is_decl)
+       if (is_decl && cctx->ctx_skip != SKIP_YES)
        {
-           emsg(_(e_cannot_use_index_when_declaring_variable));
+           if (has_cmd)
+               emsg(_(e_cannot_use_index_when_declaring_variable));
+           else
+               semsg(_(e_unknown_variable_str), lhs->lhs_name);
            return FAIL;
        }
 
@@ -1562,15 +1568,17 @@ compile_lhs(
  */
     int
 compile_assign_lhs(
-       char_u  *var_start,
-       lhs_T   *lhs,
-       int     cmdidx,
-       int     is_decl,
-       int     heredoc,
-       int     oplen,
-       cctx_T  *cctx)
+       char_u      *var_start,
+       lhs_T       *lhs,
+       cmdidx_T    cmdidx,
+       int         is_decl,
+       int         heredoc,
+       int         has_cmd,        // "var" before "var_start"
+       int         oplen,
+       cctx_T      *cctx)
 {
-    if (compile_lhs(var_start, lhs, cmdidx, heredoc, oplen, cctx) == FAIL)
+    if (compile_lhs(var_start, lhs, cmdidx, heredoc, has_cmd, oplen, cctx)
+                                                                      == FAIL)
        return FAIL;
 
     if (!lhs->lhs_has_index && lhs->lhs_lvar == &lhs->lhs_arg_lvar)
@@ -2049,7 +2057,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
         * Figure out the LHS type and other properties.
         */
        if (compile_assign_lhs(var_start, &lhs, cmdidx,
-                                       is_decl, heredoc, oplen, cctx) == FAIL)
+                               is_decl, heredoc, var_start > eap->cmd,
+                               oplen, cctx) == FAIL)
            goto theend;
        if (heredoc)
        {
@@ -2769,6 +2778,7 @@ compile_def_function(
        CLEAR_FIELD(ea);
        ea.cmdlinep = &line;
        ea.cmd = skipwhite(line);
+       ea.skip = cctx.ctx_skip == SKIP_YES;
 
        if (*ea.cmd == '#')
        {
@@ -2957,15 +2967,17 @@ compile_def_function(
 
        if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
        {
-           if (cctx.ctx_skip == SKIP_YES && ea.cmdidx != CMD_eval)
+           // "eval" is used for "val->func()" and "var" for "var = val", then
+           // "p" is equal to "ea.cmd" for a valid command.
+           if (ea.cmdidx == CMD_eval || ea.cmdidx == CMD_var)
+               ;
+           else if (cctx.ctx_skip == SKIP_YES)
            {
                line += STRLEN(line);
                goto nextline;
            }
-           else if (ea.cmdidx != CMD_eval)
+           else
            {
-               // CMD_var cannot happen, compile_assignment() above would be
-               // used.  Most likely an assignment to a non-existing variable.
                semsg(_(e_command_not_recognized_str), ea.cmd);
                goto erret;
            }