forked from aniani/vim
patch 7.4.1589
Problem: Combining dict and args with partial doesn't always work. Solution: Use the arguments from the partial.
This commit is contained in:
46
src/eval.c
46
src/eval.c
@@ -3461,7 +3461,7 @@ ex_call(exarg_T *eap)
|
|||||||
int doesrange;
|
int doesrange;
|
||||||
int failed = FALSE;
|
int failed = FALSE;
|
||||||
funcdict_T fudi;
|
funcdict_T fudi;
|
||||||
partial_T *partial;
|
partial_T *partial = NULL;
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
{
|
{
|
||||||
@@ -3497,12 +3497,6 @@ ex_call(exarg_T *eap)
|
|||||||
name = deref_func_name(tofree, &len,
|
name = deref_func_name(tofree, &len,
|
||||||
partial != NULL ? NULL : &partial, FALSE);
|
partial != NULL ? NULL : &partial, FALSE);
|
||||||
|
|
||||||
/* When calling fdict.func(), where "func" is a partial, use "fdict"
|
|
||||||
* instead of the dict in the partial, for backwards compatibility.
|
|
||||||
* TODO: Do use the arguments in the partial? */
|
|
||||||
if (fudi.fd_dict != NULL)
|
|
||||||
partial = NULL;
|
|
||||||
|
|
||||||
/* Skip white space to allow ":call func ()". Not good, but required for
|
/* Skip white space to allow ":call func ()". Not good, but required for
|
||||||
* backward compatibility. */
|
* backward compatibility. */
|
||||||
startarg = skipwhite(arg);
|
startarg = skipwhite(arg);
|
||||||
@@ -21734,17 +21728,18 @@ handle_subscript(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rettv->v_type == VAR_FUNC && selfdict != NULL)
|
if ((rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL)
|
||||||
|
&& selfdict != NULL)
|
||||||
{
|
{
|
||||||
char_u *fname;
|
char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
|
||||||
|
: rettv->vval.v_partial->pt_name;
|
||||||
char_u *tofree = NULL;
|
char_u *tofree = NULL;
|
||||||
ufunc_T *fp;
|
ufunc_T *fp;
|
||||||
char_u fname_buf[FLEN_FIXED + 1];
|
char_u fname_buf[FLEN_FIXED + 1];
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Translate "s:func" to the stored function name. */
|
/* Translate "s:func" to the stored function name. */
|
||||||
fname = fname_trans_sid(rettv->vval.v_string, fname_buf,
|
fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
|
||||||
&tofree, &error);
|
|
||||||
fp = find_func(fname);
|
fp = find_func(fname);
|
||||||
vim_free(tofree);
|
vim_free(tofree);
|
||||||
|
|
||||||
@@ -21758,7 +21753,34 @@ handle_subscript(
|
|||||||
pt->pt_refcount = 1;
|
pt->pt_refcount = 1;
|
||||||
pt->pt_dict = selfdict;
|
pt->pt_dict = selfdict;
|
||||||
selfdict = NULL;
|
selfdict = NULL;
|
||||||
|
if (rettv->v_type == VAR_FUNC)
|
||||||
|
{
|
||||||
|
/* just a function: use selfdict */
|
||||||
pt->pt_name = rettv->vval.v_string;
|
pt->pt_name = rettv->vval.v_string;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
partial_T *ret_pt = rettv->vval.v_partial;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* partial: use selfdict and copy args */
|
||||||
|
pt->pt_name = vim_strsave(ret_pt->pt_name);
|
||||||
|
if (ret_pt->pt_argc > 0)
|
||||||
|
{
|
||||||
|
pt->pt_argv = (typval_T *)alloc(
|
||||||
|
sizeof(typval_T) * ret_pt->pt_argc);
|
||||||
|
if (pt->pt_argv == NULL)
|
||||||
|
/* out of memory: drop the arguments */
|
||||||
|
pt->pt_argc = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pt->pt_argc = ret_pt->pt_argc;
|
||||||
|
for (i = 0; i < pt->pt_argc; i++)
|
||||||
|
copy_tv(&ret_pt->pt_argv[i], &pt->pt_argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
partial_unref(ret_pt);
|
||||||
|
}
|
||||||
func_ref(pt->pt_name);
|
func_ref(pt->pt_name);
|
||||||
rettv->v_type = VAR_PARTIAL;
|
rettv->v_type = VAR_PARTIAL;
|
||||||
rettv->vval.v_partial = pt;
|
rettv->vval.v_partial = pt;
|
||||||
@@ -23915,6 +23937,8 @@ trans_function_name(
|
|||||||
{
|
{
|
||||||
name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name);
|
name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name);
|
||||||
*pp = end;
|
*pp = end;
|
||||||
|
if (partial != NULL)
|
||||||
|
*partial = lv.ll_tv->vval.v_partial;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,6 +115,36 @@ func Test_script_function_in_dict()
|
|||||||
call assert_equal('bar', B())
|
call assert_equal('bar', B())
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
function! s:cache_arg(arg) dict
|
||||||
|
let s:result = self.name . '/' . a:arg
|
||||||
|
return s:result
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
func Test_script_function_in_dict_arg()
|
||||||
|
let s:obj = {'name': 'foo'}
|
||||||
|
let s:obj['clear'] = function('s:cache_arg')
|
||||||
|
|
||||||
|
call assert_equal('foo/bar', s:obj.clear('bar'))
|
||||||
|
let F = s:obj.clear
|
||||||
|
let s:result = ''
|
||||||
|
call assert_equal('foo/bar', F('bar'))
|
||||||
|
call assert_equal('foo/bar', s:result)
|
||||||
|
|
||||||
|
let s:obj['clear'] = function('s:cache_arg', ['bar'])
|
||||||
|
call assert_equal('foo/bar', s:obj.clear())
|
||||||
|
let s:result = ''
|
||||||
|
call s:obj.clear()
|
||||||
|
call assert_equal('foo/bar', s:result)
|
||||||
|
|
||||||
|
let F = s:obj.clear
|
||||||
|
call assert_equal('foo/bar', F())
|
||||||
|
let s:result = ''
|
||||||
|
call F()
|
||||||
|
call assert_equal('foo/bar', s:result)
|
||||||
|
|
||||||
|
call assert_equal('foo/bar', call(s:obj.clear, [], s:obj))
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_partial_exists()
|
func Test_partial_exists()
|
||||||
let F = function('MyFunc')
|
let F = function('MyFunc')
|
||||||
call assert_true(exists('*F'))
|
call assert_true(exists('*F'))
|
||||||
|
|||||||
@@ -748,6 +748,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 */
|
||||||
|
/**/
|
||||||
|
1589,
|
||||||
/**/
|
/**/
|
||||||
1588,
|
1588,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user