]> granicus.if.org Git - vim/commitdiff
patch 7.4.1589 v7.4.1589
authorBram Moolenaar <Bram@vim.org>
Thu, 17 Mar 2016 22:13:28 +0000 (23:13 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 17 Mar 2016 22:13:28 +0000 (23:13 +0100)
Problem:    Combining dict and args with partial doesn't always work.
Solution:   Use the arguments from the partial.

src/eval.c
src/testdir/test_partial.vim
src/version.c

index cc23de490c14d6cfde666454d6bc55be8676cb45..3db58f8d805f4f6bc90854fc4ef1f1cbef1fe09a 100644 (file)
@@ -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
        {
index 71d1837caec803286c6acb6a147ce175f8ac31be..fa07866a17c709aefc3467fa5133227b81376a05 100644 (file)
@@ -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'))
index 405c9d689d9af4ec425671a5cc492e7dddf11a8b..6e448f2d0ffdd7bf8a048132f27a840e15b6035c 100644 (file)
@@ -748,6 +748,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1589,
 /**/
     1588,
 /**/