0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

patch 8.2.2268: Vim9: list unpack seen as declaration

Problem:    Vim9: list unpack seen as declaration.
Solution:   Check for "var". (closes #7594)
This commit is contained in:
Bram Moolenaar
2021-01-01 21:05:55 +01:00
parent c368957b19
commit 3862ea3f62
7 changed files with 54 additions and 15 deletions

View File

@@ -1748,7 +1748,7 @@ next_for_item(void *fi_void, char_u *arg)
{ {
forinfo_T *fi = (forinfo_T *)fi_void; forinfo_T *fi = (forinfo_T *)fi_void;
int result; int result;
int flag = in_vim9script() ? ASSIGN_NO_DECL : 0; int flag = in_vim9script() ? ASSIGN_DECL : 0;
listitem_T *item; listitem_T *item;
if (fi->fi_blob != NULL) if (fi->fi_blob != NULL)

View File

@@ -912,7 +912,7 @@ ex_let_vars(
int copy, // copy values from "tv", don't move int copy, // copy values from "tv", don't move
int semicolon, // from skip_var_list() int semicolon, // from skip_var_list()
int var_count, // from skip_var_list() int var_count, // from skip_var_list()
int flags, // ASSIGN_FINAL, ASSIGN_CONST, ASSIGN_NO_DECL int flags, // ASSIGN_FINAL, ASSIGN_CONST, etc.
char_u *op) char_u *op)
{ {
char_u *arg = arg_start; char_u *arg = arg_start;
@@ -1267,7 +1267,7 @@ ex_let_one(
char_u *arg, // points to variable name char_u *arg, // points to variable name
typval_T *tv, // value to assign to variable typval_T *tv, // value to assign to variable
int copy, // copy value from "tv" int copy, // copy value from "tv"
int flags, // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
char_u *endchars, // valid chars after variable name or NULL char_u *endchars, // valid chars after variable name or NULL
char_u *op) // "+", "-", "." or NULL char_u *op) // "+", "-", "." or NULL
{ {
@@ -1279,7 +1279,7 @@ ex_let_one(
int opt_flags; int opt_flags;
char_u *tofree = NULL; char_u *tofree = NULL;
if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0 if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0 && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
&& vim_strchr((char_u *)"$@&", *arg) != NULL) && vim_strchr((char_u *)"$@&", *arg) != NULL)
{ {
@@ -1476,7 +1476,8 @@ ex_let_one(
lval_T lv; lval_T lv;
p = get_lval(arg, tv, &lv, FALSE, FALSE, p = get_lval(arg, tv, &lv, FALSE, FALSE,
(flags & ASSIGN_NO_DECL) ? GLV_NO_DECL : 0, FNE_CHECK_START); (flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
? GLV_NO_DECL : 0, FNE_CHECK_START);
if (p != NULL && lv.ll_name != NULL) if (p != NULL && lv.ll_name != NULL)
{ {
if (endchars != NULL && vim_strchr(endchars, if (endchars != NULL && vim_strchr(endchars,
@@ -3053,7 +3054,7 @@ set_var(
typval_T *tv, typval_T *tv,
int copy) // make copy of value in "tv" int copy) // make copy of value in "tv"
{ {
set_var_const(name, NULL, tv, copy, ASSIGN_NO_DECL); set_var_const(name, NULL, tv, copy, ASSIGN_DECL);
} }
/* /*
@@ -3067,7 +3068,7 @@ set_var_const(
type_T *type, type_T *type,
typval_T *tv_arg, typval_T *tv_arg,
int copy, // make copy of value in "tv" int copy, // make copy of value in "tv"
int flags) // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL int flags) // ASSIGN_CONST, ASSIGN_FINAL, etc.
{ {
typval_T *tv = tv_arg; typval_T *tv = tv_arg;
typval_T bool_tv; typval_T bool_tv;
@@ -3087,7 +3088,7 @@ set_var_const(
if (vim9script if (vim9script
&& !is_script_local && !is_script_local
&& (flags & ASSIGN_NO_DECL) == 0 && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0 && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
&& name[1] == ':') && name[1] == ':')
{ {
@@ -3126,7 +3127,7 @@ set_var_const(
if (is_script_local && vim9script) if (is_script_local && vim9script)
{ {
if ((flags & ASSIGN_NO_DECL) == 0) if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
{ {
semsg(_(e_redefining_script_item_str), name); semsg(_(e_redefining_script_item_str), name);
goto failed; goto failed;
@@ -3200,8 +3201,15 @@ set_var_const(
clear_tv(&di->di_tv); clear_tv(&di->di_tv);
} }
else // add a new variable else
{ {
// add a new variable
if (vim9script && is_script_local && (flags & ASSIGN_NO_DECL))
{
semsg(_(e_unknown_variable_str), name);
goto failed;
}
// Can't add "v:" or "a:" variable. // Can't add "v:" or "a:" variable.
if (ht == &vimvarht || ht == get_funccal_args_ht()) if (ht == &vimvarht || ht == get_funccal_args_ht())
{ {

View File

@@ -261,6 +261,12 @@ def Test_assign_unpack()
END END
CheckDefFailure(lines, 'E1031:', 3) CheckDefFailure(lines, 'E1031:', 3)
lines =<< trim END
[v1, v2] = [1, 2]
END
CheckDefFailure(lines, 'E1089', 1)
CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
lines =<< trim END lines =<< trim END
var v1: number var v1: number
var v2: number var v2: number
@@ -759,6 +765,8 @@ def Test_assignment_default()
assert_equal(5678, nr) assert_equal(5678, nr)
enddef enddef
let scriptvar = 'init'
def Test_assignment_var_list() def Test_assignment_var_list()
var lines =<< trim END var lines =<< trim END
var v1: string var v1: string
@@ -794,10 +802,9 @@ def Test_assignment_var_list()
assert_equal('some', $SOME_VAR) assert_equal('some', $SOME_VAR)
assert_equal('other', $OTHER_VAR) assert_equal('other', $OTHER_VAR)
[g:globalvar, s:scriptvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] = [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
['global', 'script', 'buf', 'win', 'tab', 'error'] ['global', 'buf', 'win', 'tab', 'error']
assert_equal('global', g:globalvar) assert_equal('global', g:globalvar)
assert_equal('script', s:scriptvar)
assert_equal('buf', b:bufvar) assert_equal('buf', b:bufvar)
assert_equal('win', w:winvar) assert_equal('win', w:winvar)
assert_equal('tab', t:tabvar) assert_equal('tab', t:tabvar)
@@ -805,6 +812,21 @@ def Test_assignment_var_list()
unlet g:globalvar unlet g:globalvar
END END
CheckDefAndScriptSuccess(lines) CheckDefAndScriptSuccess(lines)
[g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
assert_equal('global', g:globalvar)
assert_equal('script', s:scriptvar)
assert_equal('buf', b:bufvar)
lines =<< trim END
vim9script
var s:scriptvar = 'init'
[g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
assert_equal('global', g:globalvar)
assert_equal('script', s:scriptvar)
assert_equal('win', w:winvar)
END
CheckScriptSuccess(lines)
enddef enddef
def Test_assignment_vim9script() def Test_assignment_vim9script()
@@ -1182,7 +1204,7 @@ def Test_var_declaration()
g:other_var = other g:other_var = other
# type is inferred # type is inferred
s:dict = {['a']: 222} var s:dict = {['a']: 222}
def GetDictVal(key: any) def GetDictVal(key: any)
g:dict_val = s:dict[key] g:dict_val = s:dict[key]
enddef enddef

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2268,
/**/ /**/
2267, 2267,
/**/ /**/

View File

@@ -2146,6 +2146,7 @@ typedef enum {
#define ASSIGN_FINAL 1 // ":final" #define ASSIGN_FINAL 1 // ":final"
#define ASSIGN_CONST 2 // ":const" #define ASSIGN_CONST 2 // ":const"
#define ASSIGN_NO_DECL 4 // "name = expr" without ":let"/":const"/":final" #define ASSIGN_NO_DECL 4 // "name = expr" without ":let"/":const"/":final"
#define ASSIGN_DECL 8 // may declare variable if it does not exist
#include "ex_cmds.h" // Ex command defines #include "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff #include "spell.h" // spell checking stuff

View File

@@ -5634,6 +5634,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
semsg(_(e_cannot_use_operator_on_new_variable), name); semsg(_(e_cannot_use_operator_on_new_variable), name);
goto theend; goto theend;
} }
if (!is_decl)
{
semsg(_(e_unknown_variable_str), name);
goto theend;
}
// new local variable // new local variable
if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL) if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
@@ -6140,6 +6145,7 @@ compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
return NULL; return NULL;
} }
// TODO: this doesn't work for local variables
ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx); ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd; return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
} }

View File

@@ -806,7 +806,7 @@ store_var(char_u *name, typval_T *tv)
funccal_entry_T entry; funccal_entry_T entry;
save_funccal(&entry); save_funccal(&entry);
set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL); set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL);
restore_funccal(); restore_funccal();
} }