mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.1.1539: not easy to define a variable and lock it
Problem: Not easy to define a variable and lock it.
Solution: Add ":const".
9937a05543
This commit is contained in:
parent
de2e51439e
commit
1c90c19f62
@ -9629,8 +9629,31 @@ This does NOT work: >
|
||||
No error message is given for a non-existing
|
||||
variable, also without !.
|
||||
If the system does not support deleting an environment
|
||||
variable, it is made emtpy.
|
||||
variable, it is made empty.
|
||||
|
||||
*:cons* *:const* *E996*
|
||||
:cons[t] {var-name} = {expr1}
|
||||
:cons[t] [{name1}, {name2}, ...] = {expr1}
|
||||
:cons[t] [{name1}, {name2}, ...] .= {expr1}
|
||||
:cons[t] [{name}, ..., ; {lastname}] = {expr1}
|
||||
:cons[t] {var-name} =<< [trim] {marker}
|
||||
text...
|
||||
text...
|
||||
{marker}
|
||||
Similar to |:let|, but additionally lock the variable
|
||||
after setting the value. This is the same as locking
|
||||
the variable with |:lockvar| just after |:let|, thus: >
|
||||
:const x = 1
|
||||
< is equivalent to: >
|
||||
:let x = 1
|
||||
:lockvar 1 x
|
||||
< This is useful if you want to make sure the variable
|
||||
is not modified.
|
||||
*E995*
|
||||
|:const| does not allow to for changing a variable. >
|
||||
:let x = 1
|
||||
:const x = 2 " Error!
|
||||
<
|
||||
:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv*
|
||||
Lock the internal variable {name}. Locking means that
|
||||
it can no longer be changed (until it is unlocked).
|
||||
|
107
src/nvim/eval.c
107
src/nvim/eval.c
@ -176,6 +176,7 @@ static char *e_funcref = N_("E718: Funcref required");
|
||||
static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
|
||||
static char *e_nofunc = N_("E130: Unknown function: %s");
|
||||
static char *e_illvar = N_("E461: Illegal variable name: %s");
|
||||
static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
|
||||
static const char *e_readonlyvar = N_(
|
||||
"E46: Cannot change read-only variable \"%.*s\"");
|
||||
|
||||
@ -777,9 +778,9 @@ var_redir_start(
|
||||
tv.v_type = VAR_STRING;
|
||||
tv.vval.v_string = (char_u *)"";
|
||||
if (append)
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, false, (char_u *)".");
|
||||
else
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, false, (char_u *)"=");
|
||||
clear_lval(redir_lval);
|
||||
err = did_emsg;
|
||||
did_emsg |= save_emsg;
|
||||
@ -837,7 +838,7 @@ void var_redir_stop(void)
|
||||
redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval,
|
||||
false, false, 0, FNE_CHECK_START);
|
||||
if (redir_endp != NULL && redir_lval->ll_name != NULL) {
|
||||
set_var_lval(redir_lval, redir_endp, &tv, false, (char_u *)".");
|
||||
set_var_lval(redir_lval, redir_endp, &tv, false, false, (char_u *)".");
|
||||
}
|
||||
clear_lval(redir_lval);
|
||||
}
|
||||
@ -1436,6 +1437,16 @@ int eval_foldexpr(char_u *arg, int *cp)
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* :cons[t] var = expr1 define constant
|
||||
* :cons[t] [name1, name2, ...] = expr1 define constnats unpacking list
|
||||
* :cons[t] [name, ..., ; lastname] = expr1 define constnats unpacking list
|
||||
*/
|
||||
void ex_const(exarg_T *eap)
|
||||
{
|
||||
ex_let_const(eap, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* ":let" list all variable values
|
||||
* ":let var1 var2" list variable values
|
||||
@ -1448,8 +1459,14 @@ int eval_foldexpr(char_u *arg, int *cp)
|
||||
* ":let var .= expr" assignment command.
|
||||
* ":let var ..= expr" assignment command.
|
||||
* ":let [var1, var2] = expr" unpack list.
|
||||
* ":cons[t] [name, ..., ; lastname] = expr1" unpack list.
|
||||
*/
|
||||
void ex_let(exarg_T *eap)
|
||||
{
|
||||
ex_let_const(eap, false);
|
||||
}
|
||||
|
||||
static void ex_let_const(exarg_T *eap, const bool is_const)
|
||||
{
|
||||
char_u *arg = eap->arg;
|
||||
char_u *expr = NULL;
|
||||
@ -1512,7 +1529,7 @@ void ex_let(exarg_T *eap)
|
||||
}
|
||||
emsg_skip--;
|
||||
} else if (i != FAIL) {
|
||||
(void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, op);
|
||||
(void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
|
||||
tv_clear(&rettv);
|
||||
}
|
||||
}
|
||||
@ -1533,6 +1550,7 @@ ex_let_vars(
|
||||
int copy, /* copy values from "tv", don't move */
|
||||
int semicolon, /* from skip_var_list() */
|
||||
int var_count, /* from skip_var_list() */
|
||||
int is_const, /* lock variables for :const */
|
||||
char_u *nextchars
|
||||
)
|
||||
{
|
||||
@ -1543,7 +1561,7 @@ ex_let_vars(
|
||||
/*
|
||||
* ":let var = expr" or ":for var in list"
|
||||
*/
|
||||
if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
|
||||
if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL)
|
||||
return FAIL;
|
||||
return OK;
|
||||
}
|
||||
@ -1572,7 +1590,7 @@ ex_let_vars(
|
||||
size_t rest_len = tv_list_len(l);
|
||||
while (*arg != ']') {
|
||||
arg = skipwhite(arg + 1);
|
||||
arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, (const char_u *)",;]",
|
||||
arg = ex_let_one(arg, TV_LIST_ITEM_TV(item), true, is_const, (const char_u *)",;]",
|
||||
nextchars);
|
||||
if (arg == NULL) {
|
||||
return FAIL;
|
||||
@ -1595,8 +1613,7 @@ ex_let_vars(
|
||||
ltv.vval.v_list = rest_list;
|
||||
tv_list_ref(rest_list);
|
||||
|
||||
arg = ex_let_one(skipwhite(arg + 1), <v, false,
|
||||
(char_u *)"]", nextchars);
|
||||
arg = ex_let_one(skipwhite(arg + 1), <v, false, is_const, (char_u *)"]", nextchars);
|
||||
tv_clear(<v);
|
||||
if (arg == NULL) {
|
||||
return FAIL;
|
||||
@ -1851,7 +1868,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
|
||||
/// @return a pointer to the char just after the var name or NULL in case of
|
||||
/// error.
|
||||
static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
const bool copy, const char_u *const endchars,
|
||||
const bool copy, const bool is_const, const char_u *const endchars,
|
||||
const char_u *const op)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
@ -1864,6 +1881,11 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
* ":let $VAR = expr": Set environment variable.
|
||||
*/
|
||||
if (*arg == '$') {
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_("E996: Cannot lock an environment variable"));
|
||||
return NULL;
|
||||
}
|
||||
// Find the end of the name.
|
||||
arg++;
|
||||
char *name = (char *)arg;
|
||||
@ -1909,6 +1931,11 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
// ":let &l:option = expr": Set local option value.
|
||||
// ":let &g:option = expr": Set global option value.
|
||||
} else if (*arg == '&') {
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_("E996: Cannot lock an option"));
|
||||
return NULL;
|
||||
}
|
||||
// Find the end of the name.
|
||||
char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
|
||||
if (p == NULL
|
||||
@ -1959,6 +1986,11 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
}
|
||||
// ":let @r = expr": Set register contents.
|
||||
} else if (*arg == '@') {
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_("E996: Cannot lock a register"));
|
||||
return NULL;
|
||||
}
|
||||
arg++;
|
||||
if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) {
|
||||
emsgf(_(e_letwrong), op);
|
||||
@ -1998,7 +2030,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) {
|
||||
EMSG(_(e_letunexp));
|
||||
} else {
|
||||
set_var_lval(&lv, p, tv, copy, op);
|
||||
set_var_lval(&lv, p, tv, copy, is_const, op);
|
||||
arg_end = p;
|
||||
}
|
||||
}
|
||||
@ -2363,7 +2395,7 @@ static void clear_lval(lval_T *lp)
|
||||
* "%" for "%=", "." for ".=" or "=" for "=".
|
||||
*/
|
||||
static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
int copy, const char_u *op)
|
||||
int copy, const bool is_const, const char_u *op)
|
||||
{
|
||||
int cc;
|
||||
listitem_T *ri;
|
||||
@ -2375,6 +2407,13 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
if (op != NULL && *op != '=') {
|
||||
typval_T tv;
|
||||
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_(e_cannot_mod));
|
||||
*endp = cc;
|
||||
return;
|
||||
}
|
||||
|
||||
// handle +=, -=, *=, /=, %= and .=
|
||||
di = NULL;
|
||||
if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
|
||||
@ -2390,7 +2429,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
tv_clear(&tv);
|
||||
}
|
||||
} else {
|
||||
set_var(lp->ll_name, lp->ll_name_len, rettv, copy);
|
||||
set_var_const(lp->ll_name, lp->ll_name_len, rettv, copy, is_const);
|
||||
}
|
||||
*endp = cc;
|
||||
} else if (tv_check_lock(lp->ll_newkey == NULL
|
||||
@ -2401,6 +2440,12 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
listitem_T *ll_li = lp->ll_li;
|
||||
int ll_n1 = lp->ll_n1;
|
||||
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_("E996: Cannot lock a range"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether any of the list items is locked
|
||||
for (ri = tv_list_first(rettv->vval.v_list);
|
||||
ri != NULL && ll_li != NULL; ) {
|
||||
@ -2456,6 +2501,12 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
dict_T *dict = lp->ll_dict;
|
||||
bool watched = tv_dict_is_watched(dict);
|
||||
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_("E996: Cannot lock a list or dict"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign to a List or Dictionary item.
|
||||
if (lp->ll_newkey != NULL) {
|
||||
if (op != NULL && *op != '=') {
|
||||
@ -2579,7 +2630,7 @@ bool next_for_item(void *fi_void, char_u *arg)
|
||||
} else {
|
||||
fi->fi_lw.lw_item = TV_LIST_ITEM_NEXT(fi->fi_list, item);
|
||||
return (ex_let_vars(arg, TV_LIST_ITEM_TV(item), true,
|
||||
fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
|
||||
fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20043,6 +20094,23 @@ static void list_one_var_a(const char *prefix, const char *name,
|
||||
static void set_var(const char *name, const size_t name_len, typval_T *const tv,
|
||||
const bool copy)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
set_var_const(name, name_len, tv, copy, false);
|
||||
}
|
||||
|
||||
/// Set variable to the given value
|
||||
///
|
||||
/// If the variable already exists, the value is updated. Otherwise the variable
|
||||
/// is created.
|
||||
///
|
||||
/// @param[in] name Variable name to set.
|
||||
/// @param[in] name_len Length of the variable name.
|
||||
/// @param tv Variable value.
|
||||
/// @param[in] copy True if value in tv is to be copied.
|
||||
/// @param[in] is_const True if value in tv is to be locked.
|
||||
static void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
|
||||
const bool copy, const bool is_const)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
dictitem_T *v;
|
||||
hashtab_T *ht;
|
||||
@ -20069,6 +20137,12 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
|
||||
|
||||
typval_T oldtv = TV_INITIAL_VALUE;
|
||||
if (v != NULL) {
|
||||
if (is_const)
|
||||
{
|
||||
EMSG(_(e_cannot_mod));
|
||||
return;
|
||||
}
|
||||
|
||||
// existing variable, need to clear the value
|
||||
if (var_check_ro(v->di_flags, name, name_len)
|
||||
|| tv_check_lock(v->di_tv.v_lock, name, name_len)) {
|
||||
@ -20135,6 +20209,9 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
|
||||
return;
|
||||
}
|
||||
v->di_flags = DI_FLAGS_ALLOC;
|
||||
if (is_const) {
|
||||
v->di_flags |= DI_FLAGS_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) {
|
||||
@ -20153,6 +20230,10 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
|
||||
tv_clear(&oldtv);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_const) {
|
||||
v->di_tv.v_lock |= VAR_LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether variable is read-only (DI_FLAGS_RO, DI_FLAGS_RO_SBX)
|
||||
|
@ -600,6 +600,12 @@ return {
|
||||
addr_type=ADDR_LINES,
|
||||
func='ex_wrongmodifier',
|
||||
},
|
||||
{
|
||||
command='const',
|
||||
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
|
||||
addr_type=ADDR_LINES,
|
||||
func='ex_const',
|
||||
},
|
||||
{
|
||||
command='copen',
|
||||
flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
|
||||
|
211
src/nvim/testdir/test_const.vim
Normal file
211
src/nvim/testdir/test_const.vim
Normal file
@ -0,0 +1,211 @@
|
||||
|
||||
" Test for :const
|
||||
|
||||
func s:noop()
|
||||
endfunc
|
||||
|
||||
func Test_define_var_with_lock()
|
||||
const i = 1
|
||||
const f = 1.1
|
||||
const s = 'vim'
|
||||
const F = funcref('s:noop')
|
||||
const l = [1, 2, 3]
|
||||
const d = {'foo': 10}
|
||||
if has('channel')
|
||||
const j = test_null_job()
|
||||
const c = test_null_channel()
|
||||
endif
|
||||
const b = v:true
|
||||
const n = v:null
|
||||
|
||||
call assert_fails('let i = 1', 'E741:')
|
||||
call assert_fails('let f = 1.1', 'E741:')
|
||||
call assert_fails('let s = "vim"', 'E741:')
|
||||
call assert_fails('let F = funcref("s:noop")', 'E741:')
|
||||
call assert_fails('let l = [1, 2, 3]', 'E741:')
|
||||
call assert_fails('let d = {"foo": 10}', 'E741:')
|
||||
if has('channel')
|
||||
call assert_fails('let j = test_null_job()', 'E741:')
|
||||
call assert_fails('let c = test_null_channel()', 'E741:')
|
||||
endif
|
||||
call assert_fails('let b = v:true', 'E741:')
|
||||
call assert_fails('let n = v:null', 'E741:')
|
||||
|
||||
" Unlet
|
||||
unlet i
|
||||
unlet f
|
||||
unlet s
|
||||
unlet F
|
||||
unlet l
|
||||
unlet d
|
||||
unlet j
|
||||
unlet c
|
||||
unlet b
|
||||
unlet n
|
||||
endfunc
|
||||
|
||||
func Test_define_l_var_with_lock()
|
||||
" With l: prefix
|
||||
const l:i = 1
|
||||
const l:f = 1.1
|
||||
const l:s = 'vim'
|
||||
const l:F = funcref('s:noop')
|
||||
const l:l = [1, 2, 3]
|
||||
const l:d = {'foo': 10}
|
||||
if has('channel')
|
||||
const l:j = test_null_job()
|
||||
const l:c = test_null_channel()
|
||||
endif
|
||||
const l:b = v:true
|
||||
const l:n = v:null
|
||||
|
||||
call assert_fails('let l:i = 1', 'E741:')
|
||||
call assert_fails('let l:f = 1.1', 'E741:')
|
||||
call assert_fails('let l:s = "vim"', 'E741:')
|
||||
call assert_fails('let l:F = funcref("s:noop")', 'E741:')
|
||||
call assert_fails('let l:l = [1, 2, 3]', 'E741:')
|
||||
call assert_fails('let l:d = {"foo": 10}', 'E741:')
|
||||
if has('channel')
|
||||
call assert_fails('let l:j = test_null_job()', 'E741:')
|
||||
call assert_fails('let l:c = test_null_channel()', 'E741:')
|
||||
endif
|
||||
call assert_fails('let l:b = v:true', 'E741:')
|
||||
call assert_fails('let l:n = v:null', 'E741:')
|
||||
|
||||
" Unlet
|
||||
unlet l:i
|
||||
unlet l:f
|
||||
unlet l:s
|
||||
unlet l:F
|
||||
unlet l:l
|
||||
unlet l:d
|
||||
if has('channel')
|
||||
unlet l:j
|
||||
unlet l:c
|
||||
endif
|
||||
unlet l:b
|
||||
unlet l:n
|
||||
endfunc
|
||||
|
||||
func Test_define_script_var_with_lock()
|
||||
const s:x = 0
|
||||
call assert_fails('let s:x = 1', 'E741:')
|
||||
unlet s:x
|
||||
endfunc
|
||||
|
||||
func Test_descructuring_with_lock()
|
||||
const [a, b, c] = [1, 1.1, 'vim']
|
||||
|
||||
call assert_fails('let a = 1', 'E741:')
|
||||
call assert_fails('let b = 1.1', 'E741:')
|
||||
call assert_fails('let c = "vim"', 'E741:')
|
||||
|
||||
const [d; e] = [1, 1.1, 'vim']
|
||||
call assert_fails('let d = 1', 'E741:')
|
||||
call assert_fails('let e = [2.2, "a"]', 'E741:')
|
||||
endfunc
|
||||
|
||||
func Test_cannot_modify_existing_variable()
|
||||
let i = 1
|
||||
let f = 1.1
|
||||
let s = 'vim'
|
||||
let F = funcref('s:noop')
|
||||
let l = [1, 2, 3]
|
||||
let d = {'foo': 10}
|
||||
if has('channel')
|
||||
let j = test_null_job()
|
||||
let c = test_null_channel()
|
||||
endif
|
||||
let b = v:true
|
||||
let n = v:null
|
||||
|
||||
call assert_fails('const i = 1', 'E995:')
|
||||
call assert_fails('const f = 1.1', 'E995:')
|
||||
call assert_fails('const s = "vim"', 'E995:')
|
||||
call assert_fails('const F = funcref("s:noop")', 'E995:')
|
||||
call assert_fails('const l = [1, 2, 3]', 'E995:')
|
||||
call assert_fails('const d = {"foo": 10}', 'E995:')
|
||||
if has('channel')
|
||||
call assert_fails('const j = test_null_job()', 'E995:')
|
||||
call assert_fails('const c = test_null_channel()', 'E995:')
|
||||
endif
|
||||
call assert_fails('const b = v:true', 'E995:')
|
||||
call assert_fails('const n = v:null', 'E995:')
|
||||
call assert_fails('const [i, f, s] = [1, 1.1, "vim"]', 'E995:')
|
||||
|
||||
const i2 = 1
|
||||
const f2 = 1.1
|
||||
const s2 = 'vim'
|
||||
const F2 = funcref('s:noop')
|
||||
const l2 = [1, 2, 3]
|
||||
const d2 = {'foo': 10}
|
||||
if has('channel')
|
||||
const j2 = test_null_job()
|
||||
const c2 = test_null_channel()
|
||||
endif
|
||||
const b2 = v:true
|
||||
const n2 = v:null
|
||||
|
||||
call assert_fails('const i2 = 1', 'E995:')
|
||||
call assert_fails('const f2 = 1.1', 'E995:')
|
||||
call assert_fails('const s2 = "vim"', 'E995:')
|
||||
call assert_fails('const F2 = funcref("s:noop")', 'E995:')
|
||||
call assert_fails('const l2 = [1, 2, 3]', 'E995:')
|
||||
call assert_fails('const d2 = {"foo": 10}', 'E995:')
|
||||
if has('channel')
|
||||
call assert_fails('const j2 = test_null_job()', 'E995:')
|
||||
call assert_fails('const c2 = test_null_channel()', 'E995:')
|
||||
endif
|
||||
call assert_fails('const b2 = v:true', 'E995:')
|
||||
call assert_fails('const n2 = v:null', 'E995:')
|
||||
call assert_fails('const [i2, f2, s2] = [1, 1.1, "vim"]', 'E995:')
|
||||
endfunc
|
||||
|
||||
func Test_const_with_index_access()
|
||||
let l = [1, 2, 3]
|
||||
call assert_fails('const l[0] = 4', 'E996:')
|
||||
call assert_fails('const l[0:1] = [1, 2]', 'E996:')
|
||||
|
||||
let d = {'aaa': 0}
|
||||
call assert_fails("const d['aaa'] = 4", 'E996:')
|
||||
call assert_fails("const d.aaa = 4", 'E996:')
|
||||
endfunc
|
||||
|
||||
func Test_const_with_compound_assign()
|
||||
let i = 0
|
||||
call assert_fails('const i += 4', 'E995:')
|
||||
call assert_fails('const i -= 4', 'E995:')
|
||||
call assert_fails('const i *= 4', 'E995:')
|
||||
call assert_fails('const i /= 4', 'E995:')
|
||||
call assert_fails('const i %= 4', 'E995:')
|
||||
|
||||
let s = 'a'
|
||||
call assert_fails('const s .= "b"', 'E995:')
|
||||
|
||||
let [a, b, c] = [1, 2, 3]
|
||||
call assert_fails('const [a, b, c] += [4, 5, 6]', 'E995:')
|
||||
|
||||
let [d; e] = [1, 2, 3]
|
||||
call assert_fails('const [d; e] += [4, 5, 6]', 'E995:')
|
||||
endfunc
|
||||
|
||||
func Test_const_with_special_variables()
|
||||
call assert_fails('const $FOO = "hello"', 'E996:')
|
||||
call assert_fails('const @a = "hello"', 'E996:')
|
||||
call assert_fails('const &filetype = "vim"', 'E996:')
|
||||
call assert_fails('const &l:filetype = "vim"', 'E996:')
|
||||
call assert_fails('const &g:encoding = "utf-8"', 'E996:')
|
||||
endfunc
|
||||
|
||||
func Test_lock_depth_is_1()
|
||||
const l = [1, 2, 3]
|
||||
const d = {'foo': 10}
|
||||
|
||||
" Modify list
|
||||
call add(l, 4)
|
||||
let l[0] = 42
|
||||
|
||||
" Modify dict
|
||||
let d['bar'] = 'hello'
|
||||
let d.foo = 44
|
||||
endfunc
|
Loading…
Reference in New Issue
Block a user