mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 8.2.3889: duplicate code for translating script-local function name
Problem: Duplicate code for translating script-local function name. Solution: Move the code to get_scriptlocal_funcname(). (Yegappan Lakshmanan, closes #9393)
This commit is contained in:
committed by
Bram Moolenaar
parent
73a024209c
commit
e7f4abd38b
@@ -4050,22 +4050,11 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
list_T *list = NULL;
|
list_T *list = NULL;
|
||||||
|
|
||||||
if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
|
if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
|
||||||
{
|
|
||||||
char sid_buf[25];
|
|
||||||
int off = *s == 's' ? 2 : 5;
|
|
||||||
|
|
||||||
// Expand s: and <SID> into <SNR>nr_, so that the function can
|
// Expand s: and <SID> into <SNR>nr_, so that the function can
|
||||||
// also be called from another script. Using trans_function_name()
|
// also be called from another script. Using trans_function_name()
|
||||||
// would also work, but some plugins depend on the name being
|
// would also work, but some plugins depend on the name being
|
||||||
// printable text.
|
// printable text.
|
||||||
sprintf(sid_buf, "<SNR>%ld_", (long)current_sctx.sc_sid);
|
name = get_scriptlocal_funcname(s);
|
||||||
name = alloc(STRLEN(sid_buf) + STRLEN(s + off) + 1);
|
|
||||||
if (name != NULL)
|
|
||||||
{
|
|
||||||
STRCPY(name, sid_buf);
|
|
||||||
STRCAT(name, s + off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
name = vim_strsave(s);
|
name = vim_strsave(s);
|
||||||
|
|
||||||
|
@@ -4450,7 +4450,18 @@ get_callback(typval_T *arg)
|
|||||||
r = FAIL;
|
r = FAIL;
|
||||||
else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
|
else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
|
||||||
{
|
{
|
||||||
// Note that we don't make a copy of the string.
|
if (arg->v_type == VAR_STRING)
|
||||||
|
{
|
||||||
|
char_u *name;
|
||||||
|
|
||||||
|
name = get_scriptlocal_funcname(arg->vval.v_string);
|
||||||
|
if (name != NULL)
|
||||||
|
{
|
||||||
|
vim_free(arg->vval.v_string);
|
||||||
|
arg->vval.v_string = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res.cb_name = arg->vval.v_string;
|
res.cb_name = arg->vval.v_string;
|
||||||
func_ref(res.cb_name);
|
func_ref(res.cb_name);
|
||||||
}
|
}
|
||||||
|
25
src/option.c
25
src/option.c
@@ -7205,33 +7205,8 @@ option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED)
|
|||||||
// Lambda expression or a funcref
|
// Lambda expression or a funcref
|
||||||
tv = eval_expr(optval, NULL);
|
tv = eval_expr(optval, NULL);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// treat everything else as a function name string
|
// treat everything else as a function name string
|
||||||
|
|
||||||
// Function name starting with "s:" are supported only in a vimscript
|
|
||||||
// context.
|
|
||||||
if (STRNCMP(optval, "s:", 2) == 0)
|
|
||||||
{
|
|
||||||
char sid_buf[25];
|
|
||||||
char_u *funcname;
|
|
||||||
|
|
||||||
if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
|
|
||||||
{
|
|
||||||
emsg(_(e_using_sid_not_in_script_context));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
// Expand s: prefix into <SNR>nr_<name>
|
|
||||||
sprintf(sid_buf, "<SNR>%ld_", (long)current_sctx.sc_sid);
|
|
||||||
funcname = alloc(STRLEN(sid_buf) + STRLEN(optval + 2) + 1);
|
|
||||||
if (funcname == NULL)
|
|
||||||
return FAIL;
|
|
||||||
STRCPY(funcname, sid_buf);
|
|
||||||
STRCAT(funcname, optval + 2);
|
|
||||||
tv = alloc_string_tv(funcname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tv = alloc_string_tv(vim_strsave(optval));
|
tv = alloc_string_tv(vim_strsave(optval));
|
||||||
}
|
|
||||||
if (tv == NULL)
|
if (tv == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typva
|
|||||||
char_u *printable_func_name(ufunc_T *fp);
|
char_u *printable_func_name(ufunc_T *fp);
|
||||||
char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial, type_T **type);
|
char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial, type_T **type);
|
||||||
char_u *untrans_function_name(char_u *name);
|
char_u *untrans_function_name(char_u *name);
|
||||||
|
char_u *get_scriptlocal_funcname(char_u *funcname);
|
||||||
char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, funcdict_T *fudi);
|
char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, funcdict_T *fudi);
|
||||||
void list_functions(regmatch_T *regmatch);
|
void list_functions(regmatch_T *regmatch);
|
||||||
ufunc_T *define_function(exarg_T *eap, char_u *name_arg);
|
ufunc_T *define_function(exarg_T *eap, char_u *name_arg);
|
||||||
|
@@ -639,6 +639,21 @@ func Test_funcref()
|
|||||||
call assert_fails('echo test_null_function()->funcref()', 'E475: Invalid argument: NULL')
|
call assert_fails('echo test_null_function()->funcref()', 'E475: Invalid argument: NULL')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for calling function() and funcref() outside of a Vim script context.
|
||||||
|
func Test_function_outside_script()
|
||||||
|
let cleanup =<< trim END
|
||||||
|
call writefile([execute('messages')], 'Xtest.out')
|
||||||
|
qall
|
||||||
|
END
|
||||||
|
call writefile(cleanup, 'Xverify.vim')
|
||||||
|
call RunVim([], [], "-c \"echo function('s:abc')\" -S Xverify.vim")
|
||||||
|
call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0])
|
||||||
|
call RunVim([], [], "-c \"echo funcref('s:abc')\" -S Xverify.vim")
|
||||||
|
call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0])
|
||||||
|
call delete('Xtest.out')
|
||||||
|
call delete('Xverify.vim')
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_setmatches()
|
func Test_setmatches()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
hi def link 1 Comment
|
hi def link 1 Comment
|
||||||
|
@@ -642,6 +642,18 @@ func Test_opfunc_callback()
|
|||||||
END
|
END
|
||||||
call CheckScriptSuccess(lines)
|
call CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
" setting 'opfunc' to a script local function outside of a script context
|
||||||
|
" should fail
|
||||||
|
let cleanup =<< trim END
|
||||||
|
call writefile([execute('messages')], 'Xtest.out')
|
||||||
|
qall
|
||||||
|
END
|
||||||
|
call writefile(cleanup, 'Xverify.vim')
|
||||||
|
call RunVim([], [], "-c \"set opfunc=s:abc\" -S Xverify.vim")
|
||||||
|
call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0])
|
||||||
|
call delete('Xtest.out')
|
||||||
|
call delete('Xverify.vim')
|
||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
set opfunc&
|
set opfunc&
|
||||||
delfunc OpFunc1
|
delfunc OpFunc1
|
||||||
|
@@ -3875,6 +3875,46 @@ untrans_function_name(char_u *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the 'funcname' starts with "s:" or "<SID>", then expands it to the
|
||||||
|
* current script ID and returns the expanded function name. The caller should
|
||||||
|
* free the returned name. If not called from a script context or the function
|
||||||
|
* name doesn't start with these prefixes, then returns NULL.
|
||||||
|
* This doesn't check whether the script-local function exists or not.
|
||||||
|
*/
|
||||||
|
char_u *
|
||||||
|
get_scriptlocal_funcname(char_u *funcname)
|
||||||
|
{
|
||||||
|
char sid_buf[25];
|
||||||
|
int off;
|
||||||
|
char_u *newname;
|
||||||
|
|
||||||
|
if (funcname == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (STRNCMP(funcname, "s:", 2) != 0
|
||||||
|
&& STRNCMP(funcname, "<SID>", 5) != 0)
|
||||||
|
// The function name is not a script-local function name
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
|
||||||
|
{
|
||||||
|
emsg(_(e_using_sid_not_in_script_context));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Expand s: prefix into <SNR>nr_<name>
|
||||||
|
vim_snprintf(sid_buf, sizeof(sid_buf), "<SNR>%ld_",
|
||||||
|
(long)current_sctx.sc_sid);
|
||||||
|
off = *funcname == 's' ? 2 : 5;
|
||||||
|
newname = alloc(STRLEN(sid_buf) + STRLEN(funcname + off) + 1);
|
||||||
|
if (newname == NULL)
|
||||||
|
return NULL;
|
||||||
|
STRCPY(newname, sid_buf);
|
||||||
|
STRCAT(newname, funcname + off);
|
||||||
|
|
||||||
|
return newname;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call trans_function_name(), except that a lambda is returned as-is.
|
* Call trans_function_name(), except that a lambda is returned as-is.
|
||||||
* Returns the name in allocated memory.
|
* Returns the name in allocated memory.
|
||||||
|
@@ -749,6 +749,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 */
|
||||||
|
/**/
|
||||||
|
3889,
|
||||||
/**/
|
/**/
|
||||||
3888,
|
3888,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user