summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-03-17 23:13:28 +0100
committerBram Moolenaar <Bram@vim.org>2016-03-17 23:13:28 +0100
commit9e63f61cb01c70fd71652f54b2d01ee27b2a3534 (patch)
treed4f7622cefb7e5776fa55d6f44f8dbe38b8a0390
parent1ff2b64b11e7d263c6853745d5e594bd8f94b91e (diff)
downloadvim-git-9e63f61cb01c70fd71652f54b2d01ee27b2a3534.tar.gz
patch 7.4.1589v7.4.1589
Problem: Combining dict and args with partial doesn't always work. Solution: Use the arguments from the partial.
-rw-r--r--src/eval.c48
-rw-r--r--src/testdir/test_partial.vim30
-rw-r--r--src/version.c2
3 files changed, 68 insertions, 12 deletions
diff --git a/src/eval.c b/src/eval.c
index cc23de490..3db58f8d8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3461,7 +3461,7 @@ ex_call(exarg_T *eap)
int doesrange;
int failed = FALSE;
funcdict_T fudi;
- partial_T *partial;
+ partial_T *partial = NULL;
if (eap->skip)
{
@@ -3497,12 +3497,6 @@ ex_call(exarg_T *eap)
name = deref_func_name(tofree, &len,
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
* backward compatibility. */
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;
ufunc_T *fp;
char_u fname_buf[FLEN_FIXED + 1];
int error;
/* Translate "s:func" to the stored function name. */
- fname = fname_trans_sid(rettv->vval.v_string, fname_buf,
- &tofree, &error);
+ fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
fp = find_func(fname);
vim_free(tofree);
@@ -21758,7 +21753,34 @@ handle_subscript(
pt->pt_refcount = 1;
pt->pt_dict = selfdict;
selfdict = NULL;
- pt->pt_name = rettv->vval.v_string;
+ if (rettv->v_type == VAR_FUNC)
+ {
+ /* just a function: use selfdict */
+ 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);
rettv->v_type = VAR_PARTIAL;
rettv->vval.v_partial = pt;
@@ -23915,6 +23937,8 @@ trans_function_name(
{
name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name);
*pp = end;
+ if (partial != NULL)
+ *partial = lv.ll_tv->vval.v_partial;
}
else
{
diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim
index 71d1837ca..fa07866a1 100644
--- a/src/testdir/test_partial.vim
+++ b/src/testdir/test_partial.vim
@@ -115,6 +115,36 @@ func Test_script_function_in_dict()
call assert_equal('bar', B())
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()
let F = function('MyFunc')
call assert_true(exists('*F'))
diff --git a/src/version.c b/src/version.c
index 405c9d689..6e448f2d0 100644
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1589,
+/**/
1588,
/**/
1587,