Patch 8.2.2311

3 views
Skip to first unread message

Bram Moolenaar

unread,
Jan 7, 2021, 4:04:40 PM1/7/21
to vim...@googlegroups.com

Patch 8.2.2311
Problem: Vim9: cannot assign to a variable that shadows a command modifier.
Solution: Check for assignment after possible command modifier.
(closes #7632)
Files: src/vim9compile.c, src/ex_docmd.c,
src/testdir/test_vim9_assign.vim


*** ../vim-8.2.2310/src/vim9compile.c 2021-01-07 19:23:04.966566919 +0100
--- src/vim9compile.c 2021-01-07 22:02:33.588205264 +0100
***************
*** 6217,6222 ****
--- 6217,6293 ----
}

/*
+ * Check for an assignment at "eap->cmd", compile it if found.
+ * Return NOTDONE if there is none, FAIL for failure, OK if done.
+ */
+ static int
+ may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx)
+ {
+ char_u *pskip;
+ char_u *p;
+
+ // Assuming the command starts with a variable or function name,
+ // find what follows.
+ // Skip over "var.member", "var[idx]" and the like.
+ // Also "&opt = val", "$ENV = val" and "@r = val".
+ pskip = (*eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@')
+ ? eap->cmd + 1 : eap->cmd;
+ p = to_name_end(pskip, TRUE);
+ if (p > eap->cmd && *p != NUL)
+ {
+ char_u *var_end;
+ int oplen;
+ int heredoc;
+
+ if (eap->cmd[0] == '@')
+ var_end = eap->cmd + 2;
+ else
+ var_end = find_name_end(pskip, NULL, NULL,
+ FNE_CHECK_START | FNE_INCL_BR);
+ oplen = assignment_len(skipwhite(var_end), &heredoc);
+ if (oplen > 0)
+ {
+ size_t len = p - eap->cmd;
+
+ // Recognize an assignment if we recognize the variable
+ // name:
+ // "g:var = expr"
+ // "local = expr" where "local" is a local var.
+ // "script = expr" where "script" is a script-local var.
+ // "import = expr" where "import" is an imported var
+ // "&opt = expr"
+ // "$ENV = expr"
+ // "@r = expr"
+ if (*eap->cmd == '&'
+ || *eap->cmd == '$'
+ || *eap->cmd == '@'
+ || ((len) > 2 && eap->cmd[1] == ':')
+ || lookup_local(eap->cmd, len, NULL, cctx) == OK
+ || arg_exists(eap->cmd, len, NULL, NULL, NULL, cctx) == OK
+ || script_var_exists(eap->cmd, len, FALSE, cctx) == OK
+ || find_imported(eap->cmd, len, cctx) != NULL)
+ {
+ *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
+ if (*line == NULL || *line == eap->cmd)
+ return FAIL;
+ return OK;
+ }
+ }
+ }
+
+ if (*eap->cmd == '[')
+ {
+ // [var, var] = expr
+ *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
+ if (*line == NULL)
+ return FAIL;
+ if (*line != eap->cmd)
+ return OK;
+ }
+ return NOTDONE;
+ }
+
+ /*
* Check if "name" can be "unlet".
*/
int
***************
*** 7838,7905 ****

if (!starts_with_colon)
{
! char_u *pskip;

! // Assuming the command starts with a variable or function name,
! // find what follows.
! // Skip over "var.member", "var[idx]" and the like.
! // Also "&opt = val", "$ENV = val" and "@r = val".
! pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
! ? ea.cmd + 1 : ea.cmd;
! p = to_name_end(pskip, TRUE);
! if (p > ea.cmd && *p != NUL)
! {
! char_u *var_end;
! int oplen;
! int heredoc;
!
! if (ea.cmd[0] == '@')
! var_end = ea.cmd + 2;
! else
! var_end = find_name_end(pskip, NULL, NULL,
! FNE_CHECK_START | FNE_INCL_BR);
! oplen = assignment_len(skipwhite(var_end), &heredoc);
! if (oplen > 0)
! {
! size_t len = p - ea.cmd;
!
! // Recognize an assignment if we recognize the variable
! // name:
! // "g:var = expr"
! // "local = expr" where "local" is a local var.
! // "script = expr" where "script" is a script-local var.
! // "import = expr" where "import" is an imported var
! // "&opt = expr"
! // "$ENV = expr"
! // "@r = expr"
! if (*ea.cmd == '&'
! || *ea.cmd == '$'
! || *ea.cmd == '@'
! || ((len) > 2 && ea.cmd[1] == ':')
! || lookup_local(ea.cmd, len, NULL, &cctx) == OK
! || arg_exists(ea.cmd, len, NULL, NULL,
! NULL, &cctx) == OK
! || script_var_exists(ea.cmd, len,
! FALSE, &cctx) == OK
! || find_imported(ea.cmd, len, &cctx) != NULL)
! {
! line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
! if (line == NULL || line == ea.cmd)
! goto erret;
! goto nextline;
! }
! }
! }
!
! if (*ea.cmd == '[')
! {
! // [var, var] = expr
! line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
! if (line == NULL)
! goto erret;
! if (line != ea.cmd)
! goto nextline;
! }
}

/*
--- 7909,7922 ----

if (!starts_with_colon)
{
! int assign;

! // Check for assignment after command modifiers.
! assign = may_compile_assignment(&ea, &line, &cctx);
! if (assign == OK)
! goto nextline;
! if (assign == FAIL)
! goto erret;
}

/*
*** ../vim-8.2.2310/src/ex_docmd.c 2021-01-04 16:15:55.066084896 +0100
--- src/ex_docmd.c 2021-01-07 21:56:15.173041913 +0100
***************
*** 2738,2743 ****
--- 2738,2762 ----
}

p = skip_range(eap->cmd, TRUE, NULL);
+
+ // In Vim9 script a variable can shadow a command modifier:
+ // verbose = 123
+ // verbose += 123
+ // silent! verbose = func()
+ // verbose.member = 2
+ // verbose[expr] = 2
+ if (in_vim9script())
+ {
+ char_u *s;
+
+ for (s = p; ASCII_ISALPHA(*s); ++s)
+ ;
+ s = skipwhite(s);
+ if (vim_strchr((char_u *)".[=", *s) != NULL
+ || (*s != NUL && s[1] == '='))
+ break;
+ }
+
switch (*p)
{
// When adding an entry, also modify cmd_exists().
*** ../vim-8.2.2310/src/testdir/test_vim9_assign.vim 2021-01-07 19:23:04.966566919 +0100
--- src/testdir/test_vim9_assign.vim 2021-01-07 21:56:35.244998244 +0100
***************
*** 1464,1468 ****
--- 1464,1489 ----
assert_equal('', $ENVVAR)
enddef

+ def Test_assign_command_modifier()
+ var lines =<< trim END
+ var verbose = 0
+ verbose = 1
+ assert_equal(1, verbose)
+ silent verbose = 2
+ assert_equal(2, verbose)
+ silent verbose += 2
+ assert_equal(4, verbose)
+ silent verbose -= 1
+ assert_equal(3, verbose)
+
+ var topleft = {one: 1}
+ sandbox topleft.one = 3
+ assert_equal({one: 3}, topleft)
+ leftabove topleft[' '] = 4
+ assert_equal({one: 3, ' ': 4}, topleft)
+ END
+ CheckDefAndScriptSuccess(lines)
+ enddef
+

" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.2310/src/version.c 2021-01-07 20:23:29.846515289 +0100
--- src/version.c 2021-01-07 21:38:38.395022245 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2311,
/**/

--
hundred-and-one symptoms of being an internet addict:
104. When people ask about the Presidential Election you ask "Which country?"

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages