diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 3e03723b70..842abee93c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -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. diff --git a/test/old/testdir/test_user_func.vim b/test/old/testdir/test_user_func.vim index d1ed4cb499..7e540ac5b9 100644 --- a/test/old/testdir/test_user_func.vim +++ b/test/old/testdir/test_user_func.vim @@ -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))