mirror of
https://github.com/vim/vim
synced 2025-07-16 09:12:00 +00:00
patch 8.1.1816: cannot use a user defined function as a method
Problem: Cannot use a user defined function as a method. Solution: Pass the base as the first argument to the user defined function after "->". (partly by FUJIWARA Takuya)
This commit is contained in:
@ -4734,7 +4734,7 @@ eval7(
|
|||||||
*arg = skipwhite(*arg);
|
*arg = skipwhite(*arg);
|
||||||
|
|
||||||
/* Handle following '[', '(' and '.' for expr[expr], expr.name,
|
/* Handle following '[', '(' and '.' for expr[expr], expr.name,
|
||||||
* expr(expr). */
|
* expr(expr), expr->name(expr) */
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
ret = handle_subscript(arg, rettv, evaluate, TRUE);
|
ret = handle_subscript(arg, rettv, evaluate, TRUE);
|
||||||
|
|
||||||
@ -4824,7 +4824,7 @@ eval_method(
|
|||||||
|
|
||||||
// Locate the method name.
|
// Locate the method name.
|
||||||
name = *arg;
|
name = *arg;
|
||||||
for (len = 0; ASCII_ISALNUM(name[len]) || name[len] == '_'; ++len)
|
for (len = 0; eval_isnamec(name[len]); ++len)
|
||||||
;
|
;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
{
|
||||||
@ -4842,6 +4842,8 @@ eval_method(
|
|||||||
}
|
}
|
||||||
*arg += len;
|
*arg += len;
|
||||||
|
|
||||||
|
// TODO: if "name" is a function reference, resolve it.
|
||||||
|
|
||||||
vim_memset(&funcexe, 0, sizeof(funcexe));
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
funcexe.evaluate = evaluate;
|
funcexe.evaluate = evaluate;
|
||||||
funcexe.basetv = &base;
|
funcexe.basetv = &base;
|
||||||
|
@ -5,3 +5,7 @@ let foo#bar = {}
|
|||||||
func foo#bar.echo()
|
func foo#bar.echo()
|
||||||
let g:called_foo_bar_echo += 1
|
let g:called_foo_bar_echo += 1
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func foo#addFoo(head)
|
||||||
|
return a:head .. 'foo'
|
||||||
|
endfunc
|
||||||
|
@ -8,6 +8,8 @@ func Test_autoload_dict_func()
|
|||||||
call g:foo#bar.echo()
|
call g:foo#bar.echo()
|
||||||
call assert_equal(1, g:loaded_foo_vim)
|
call assert_equal(1, g:loaded_foo_vim)
|
||||||
call assert_equal(1, g:called_foo_bar_echo)
|
call assert_equal(1, g:called_foo_bar_echo)
|
||||||
|
|
||||||
|
eval 'bar'->g:foo#addFoo()->assert_equal('barfoo')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_source_autoload()
|
func Test_source_autoload()
|
||||||
|
@ -47,7 +47,7 @@ func FuncWithRef(a)
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_user_func()
|
func Test_user_func()
|
||||||
let g:FuncRef=function("FuncWithRef")
|
let g:FuncRef = function("FuncWithRef")
|
||||||
let g:counter = 0
|
let g:counter = 0
|
||||||
inoremap <expr> ( ListItem()
|
inoremap <expr> ( ListItem()
|
||||||
inoremap <expr> [ ListReset()
|
inoremap <expr> [ ListReset()
|
||||||
@ -62,6 +62,14 @@ func Test_user_func()
|
|||||||
call assert_equal(9, g:retval)
|
call assert_equal(9, g:retval)
|
||||||
call assert_equal(333, g:FuncRef(333))
|
call assert_equal(333, g:FuncRef(333))
|
||||||
|
|
||||||
|
let g:retval = "nop"
|
||||||
|
call assert_equal('xxx4asdf', "xxx"->Table(4, "asdf"))
|
||||||
|
call assert_equal('fail', 45->Compute(0, "retval"))
|
||||||
|
call assert_equal('nop', g:retval)
|
||||||
|
call assert_equal('ok', 45->Compute(5, "retval"))
|
||||||
|
call assert_equal(9, g:retval)
|
||||||
|
" call assert_equal(333, 333->g:FuncRef())
|
||||||
|
|
||||||
enew
|
enew
|
||||||
|
|
||||||
normal oXX+-XX
|
normal oXX+-XX
|
||||||
@ -144,3 +152,11 @@ func Test_default_arg()
|
|||||||
\ .. " endfunction",
|
\ .. " endfunction",
|
||||||
\ execute('func Args2'))
|
\ execute('func Args2'))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func s:addFoo(lead)
|
||||||
|
return a:lead .. 'foo'
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_user_method()
|
||||||
|
eval 'bar'->s:addFoo()->assert_equal('barfoo')
|
||||||
|
endfunc
|
||||||
|
@ -1495,7 +1495,8 @@ call_func(
|
|||||||
int argcount = argcount_in;
|
int argcount = argcount_in;
|
||||||
typval_T *argvars = argvars_in;
|
typval_T *argvars = argvars_in;
|
||||||
dict_T *selfdict = funcexe->selfdict;
|
dict_T *selfdict = funcexe->selfdict;
|
||||||
typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */
|
typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" or
|
||||||
|
// "funcexe->basetv" is not NULL
|
||||||
int argv_clear = 0;
|
int argv_clear = 0;
|
||||||
partial_T *partial = funcexe->partial;
|
partial_T *partial = funcexe->partial;
|
||||||
|
|
||||||
@ -1554,10 +1555,7 @@ call_func(
|
|||||||
/*
|
/*
|
||||||
* User defined function.
|
* User defined function.
|
||||||
*/
|
*/
|
||||||
if (funcexe->basetv != NULL)
|
if (partial != NULL && partial->pt_func != NULL)
|
||||||
// TODO: support User function: base->Method()
|
|
||||||
fp = NULL;
|
|
||||||
else if (partial != NULL && partial->pt_func != NULL)
|
|
||||||
fp = partial->pt_func;
|
fp = partial->pt_func;
|
||||||
else
|
else
|
||||||
fp = find_func(rfname);
|
fp = find_func(rfname);
|
||||||
@ -1586,6 +1584,16 @@ call_func(
|
|||||||
argcount = funcexe->argv_func(argcount, argvars,
|
argcount = funcexe->argv_func(argcount, argvars,
|
||||||
fp->uf_args.ga_len);
|
fp->uf_args.ga_len);
|
||||||
|
|
||||||
|
if (funcexe->basetv != NULL)
|
||||||
|
{
|
||||||
|
// Method call: base->Method()
|
||||||
|
mch_memmove(&argv[1], argvars, sizeof(typval_T) * argcount);
|
||||||
|
argv[0] = *funcexe->basetv;
|
||||||
|
argcount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(argv, argvars, sizeof(typval_T) * argcount);
|
||||||
|
|
||||||
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
|
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
|
||||||
*funcexe->doesrange = TRUE;
|
*funcexe->doesrange = TRUE;
|
||||||
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
|
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
|
||||||
@ -1613,7 +1621,7 @@ call_func(
|
|||||||
did_save_redo = TRUE;
|
did_save_redo = TRUE;
|
||||||
}
|
}
|
||||||
++fp->uf_calls;
|
++fp->uf_calls;
|
||||||
call_user_func(fp, argcount, argvars, rettv,
|
call_user_func(fp, argcount, argv, rettv,
|
||||||
funcexe->firstline, funcexe->lastline,
|
funcexe->firstline, funcexe->lastline,
|
||||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||||
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
||||||
@ -1630,7 +1638,8 @@ call_func(
|
|||||||
else if (funcexe->basetv != NULL)
|
else if (funcexe->basetv != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Find the method name in the table, call its implementation.
|
* expr->method(): Find the method name in the table, call its
|
||||||
|
* implementation with the base as one of the arguments.
|
||||||
*/
|
*/
|
||||||
error = call_internal_method(fname, argcount, argvars, rettv,
|
error = call_internal_method(fname, argcount, argvars, rettv,
|
||||||
funcexe->basetv);
|
funcexe->basetv);
|
||||||
|
@ -773,6 +773,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 */
|
||||||
|
/**/
|
||||||
|
1816,
|
||||||
/**/
|
/**/
|
||||||
1815,
|
1815,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user