diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-03-17 23:13:28 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-03-17 23:13:28 +0100 |
commit | 9e63f61cb01c70fd71652f54b2d01ee27b2a3534 (patch) | |
tree | d4f7622cefb7e5776fa55d6f44f8dbe38b8a0390 | |
parent | 1ff2b64b11e7d263c6853745d5e594bd8f94b91e (diff) | |
download | vim-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.c | 48 | ||||
-rw-r--r-- | src/testdir/test_partial.vim | 30 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |