mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
vim-patch:9.2.0265: unnecessary restrictions for defining dictionary function names (#38524)
Problem: unnecessary restrictions for defining dictionary function
names
Solution: Allow defining dict function with bracket key that is not a
valid identifier (thinca)
In Vim script, "function obj.func()" and "function obj['func']()" both
define a dictionary function. However, the bracket form required the
key to match function naming rules (eval_isnamec), so
"function obj['foo-bar']()" failed with E475.
Assigning and calling already work: "let obj['foo-bar'] = obj.func"
and "call obj['foo-bar']()" are valid. Only the definition was
incorrectly restricted.
Skip the identifier check when the name comes from fd_newkey (i.e. the
key was given in bracket notation). Dictionary keys may be any string.
Supported by AI
closes: vim/vim#19833
f89662722d
Co-authored-by: thinca <thinca@gmail.com>
This commit is contained in:
@@ -2737,21 +2737,27 @@ void ex_function(exarg_T *eap)
|
||||
}
|
||||
if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) {
|
||||
char *name_base = arg;
|
||||
if ((uint8_t)(*arg) == K_SPECIAL) {
|
||||
name_base = vim_strchr(arg, '_');
|
||||
if (name_base == NULL) {
|
||||
name_base = arg + 3;
|
||||
} else {
|
||||
name_base++;
|
||||
// When defining a dictionary function with bracket notation
|
||||
// (e.g. obj['foo-bar']()), the key is a dictionary key and is not
|
||||
// required to follow function naming rules. Skip the identifier
|
||||
// check in that case.
|
||||
if (arg != fudi.fd_newkey) {
|
||||
if ((uint8_t)(*arg) == K_SPECIAL) {
|
||||
name_base = vim_strchr(arg, '_');
|
||||
if (name_base == NULL) {
|
||||
name_base = arg + 3;
|
||||
} else {
|
||||
name_base++;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; name_base[i] != NUL && (i == 0
|
||||
? eval_isnamec1(name_base[i])
|
||||
: eval_isnamec(name_base[i])); i++) {}
|
||||
if (name_base[i] != NUL) {
|
||||
emsg_funcname(e_invarg2, arg);
|
||||
goto ret_free;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; name_base[i] != NUL && (i == 0
|
||||
? eval_isnamec1(name_base[i])
|
||||
: eval_isnamec(name_base[i])); i++) {}
|
||||
if (name_base[i] != NUL) {
|
||||
emsg_funcname(e_invarg2, arg);
|
||||
goto ret_free;
|
||||
}
|
||||
}
|
||||
// Disallow using the g: dict.
|
||||
|
||||
@@ -540,6 +540,18 @@ func Test_func_dict()
|
||||
call assert_fails('call mydict.nonexist()', 'E716:')
|
||||
endfunc
|
||||
|
||||
func Test_func_dict_bracket_key()
|
||||
" Dictionary function can be defined with bracket notation using a key
|
||||
" that does not follow function naming rules (e.g. containing a hyphen).
|
||||
let obj = {}
|
||||
function obj['foo-bar']() dict
|
||||
return self.value
|
||||
endfunction
|
||||
let obj.value = 42
|
||||
call assert_equal(42, obj['foo-bar']())
|
||||
call assert_equal(42, call(obj['foo-bar'], []))
|
||||
endfunc
|
||||
|
||||
func Test_func_range()
|
||||
new
|
||||
call setline(1, range(1, 8))
|
||||
|
||||
Reference in New Issue
Block a user