summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-04-02 19:43:57 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-02 19:43:57 +0100
commit97f8c1081ec6d6d158bb51e18fa23a36d3ed5623 (patch)
treebff2837d32937a9edf15ed39b770e8b5c34c92de
parenteabddc425ea23fb91b3b0058ff01e9e4ede53351 (diff)
downloadvim-git-97f8c1081ec6d6d158bb51e18fa23a36d3ed5623.tar.gz
patch 8.2.4666: Vim9: assignment not recognized in skipped blockv8.2.4666
Problem: Vim9: assignment not recognized in skipped block. Solution: When skipping assume identifier exists. (closes #10059)
-rw-r--r--src/proto/vim9compile.pro6
-rw-r--r--src/testdir/test_vim9_cmd.vim12
-rw-r--r--src/testdir/test_vim9_script.vim13
-rw-r--r--src/version.c2
-rw-r--r--src/vim9cmds.c4
-rw-r--r--src/vim9compile.c62
6 files changed, 63 insertions, 36 deletions
diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro
index 94ef8277e..0f3094f8c 100644
--- a/src/proto/vim9compile.pro
+++ b/src/proto/vim9compile.pro
@@ -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);
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 38ee7f23f..56d3bf231 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -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()
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 71cef1ee9..54864587f 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 753eef303..b6fd0474e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4666,
+/**/
4665,
/**/
4664,
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index 483b1f34b..a853d9b0b 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -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)
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 4e3a1bfb1..205d9a9a6 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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;
}