Skip to content

Commit f896627

Browse files
thincachrisbra
authored andcommitted
patch 9.2.0265: unnecessary restrictions for defining dictionary function names
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: #19833 Signed-off-by: thinca <[email protected]> Signed-off-by: Yegappan Lakshmanan <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent d13f135 commit f896627

3 files changed

Lines changed: 45 additions & 24 deletions

File tree

src/testdir/test_user_func.vim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,18 @@ func Test_func_dict()
584584
call assert_fails('call mydict.nonexist()', 'E716:')
585585
endfunc
586586

587+
func Test_func_dict_bracket_key()
588+
" Dictionary function can be defined with bracket notation using a key
589+
" that does not follow function naming rules (e.g. containing a hyphen).
590+
let obj = {}
591+
function obj['foo-bar']() dict
592+
return self.value
593+
endfunction
594+
let obj.value = 42
595+
call assert_equal(42, obj['foo-bar']())
596+
call assert_equal(42, call(obj['foo-bar'], []))
597+
endfunc
598+
587599
func Test_func_range()
588600
new
589601
call setline(1, range(1, 8))

src/userfunc.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5253,33 +5253,40 @@ define_function(
52535253
char_u *name_base = arg;
52545254
int i;
52555255

5256-
if (*arg == K_SPECIAL)
5256+
// When defining a dictionary function with bracket notation
5257+
// (e.g. obj['foo-bar']()), the key is a dictionary key and is not
5258+
// required to follow function naming rules. Skip the identifier
5259+
// check in that case.
5260+
if (arg != fudi.fd_newkey)
52575261
{
5258-
name_base = vim_strchr(arg, '_');
5259-
if (name_base == NULL)
5260-
name_base = arg + 3;
5261-
else
5262-
++name_base;
5263-
}
5264-
for (i = 0; name_base[i] != NUL && (i == 0
5265-
? eval_isnamec1(name_base[i])
5266-
: eval_isnamec(name_base[i])); ++i)
5267-
;
5268-
if (name_base[i] != NUL)
5269-
{
5270-
emsg_funcname(e_invalid_argument_str, arg);
5271-
goto ret_free;
5272-
}
5262+
if (*arg == K_SPECIAL)
5263+
{
5264+
name_base = vim_strchr(arg, '_');
5265+
if (name_base == NULL)
5266+
name_base = arg + 3;
5267+
else
5268+
++name_base;
5269+
}
5270+
for (i = 0; name_base[i] != NUL && (i == 0
5271+
? eval_isnamec1(name_base[i])
5272+
: eval_isnamec(name_base[i])); ++i)
5273+
;
5274+
if (name_base[i] != NUL)
5275+
{
5276+
emsg_funcname(e_invalid_argument_str, arg);
5277+
goto ret_free;
5278+
}
52735279

5274-
// In Vim9 script a function cannot have the same name as a
5275-
// variable.
5276-
if (vim9script && *arg == K_SPECIAL
5277-
&& eval_variable(name_base, i, 0, NULL,
5278-
NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT
5280+
// In Vim9 script a function cannot have the same name as a
5281+
// variable.
5282+
if (vim9script && *arg == K_SPECIAL
5283+
&& eval_variable(name_base, i, 0, NULL,
5284+
NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT
52795285
+ EVAL_VAR_NO_FUNC) == OK)
5280-
{
5281-
semsg(_(e_redefining_script_item_str), name_base);
5282-
goto ret_free;
5286+
{
5287+
semsg(_(e_redefining_script_item_str), name_base);
5288+
goto ret_free;
5289+
}
52835290
}
52845291
}
52855292
// Disallow using the g: dict.

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
265,
737739
/**/
738740
264,
739741
/**/

0 commit comments

Comments
 (0)