Compare commits

...

7 Commits

Author SHA1 Message Date
Bram Moolenaar
ffcfddc759 patch 8.2.3151: Vim9: profiling fails if nested function is also profiled
Problem:    Vim9: profiling fails if nested function is also profiled.
Solution:   Use the compile type from the outer function. (closes #8543)
2021-07-11 20:22:30 +02:00
Yegappan Lakshmanan
c72bdd28ac patch 8.2.3150: Vim9: argument types are not checked at compile time
Problem:    Vim9: argument types are not checked at compile time.
Solution:   Add more type checks. (Yegappan Lakshmanan, closes #8545)
2021-07-11 19:44:18 +02:00
Bram Moolenaar
cc7eb2aa7a patch 8.2.3149: some plugins have a problem with the error check
Problem:    Some plugins have a problem with the error check for using
            :command with -complete but without -nargs.
Solution:   In legacy script only give a warning message.
2021-07-11 19:12:04 +02:00
Bram Moolenaar
5231224e11 patch 8.2.3148: Vim9: function arg type check does not handle base offset
Problem:    Vim9: function arg type check does not handle base offset.
Solution:   Take the base offset into account when checking builtin function
            argument types.
2021-07-11 18:23:19 +02:00
Bram Moolenaar
648594eaf7 patch 8.2.3147: Vim9: profiling does not work with a nested function
Problem:    Vim9: profiling does not work with a nested function.
Solution:   Also compile a nested function without profiling. (closes #8543)
            Handle that compiling may cause the table of compiled functions to
            change.
2021-07-11 17:55:01 +02:00
Bram Moolenaar
c03fe66ade patch 8.2.3146: Vim9: line number wrong for :execute argument
Problem:    Vim9: line number wrong for :execute argument.
Solution:   Use the line number of the :execute command itself. (closes #8537)
2021-07-11 16:52:45 +02:00
Bram Moolenaar
4ece152ad6 patch 8.2.3145: Vim9: profile test fails without profile feature
Problem:    Vim9: profile test fails without profile feature.
Solution:   Check the profile feature is present.
2021-07-11 16:31:51 +02:00
12 changed files with 268 additions and 43 deletions

View File

@@ -6191,6 +6191,7 @@ ex_execute(exarg_T *eap)
char_u *p;
garray_T ga;
int len;
long start_lnum = SOURCING_LNUM;
ga_init2(&ga, 1, 80);
@@ -6244,6 +6245,9 @@ ex_execute(exarg_T *eap)
if (ret != FAIL && ga.ga_data != NULL)
{
// use the first line of continuation lines for messages
SOURCING_LNUM = start_lnum;
if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr)
{
// Mark the already saved text as finishing the line, so that what

View File

@@ -322,7 +322,7 @@ arg_string_or_nr(type_T *type, argcontext_T *context)
* Check "type" is a string or a list of strings.
*/
static int
arg_string_or_list(type_T *type, argcontext_T *context)
arg_string_or_list_string(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING)
return OK;
@@ -339,6 +339,19 @@ arg_string_or_list(type_T *type, argcontext_T *context)
return FAIL;
}
/*
* Check "type" is a string or a list of 'any'
*/
static int
arg_string_or_list_any(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_STRING || type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
}
/*
* Check "type" is a list or a dict.
*/
@@ -412,6 +425,20 @@ arg_item_of_prev(type_T *type, argcontext_T *context)
return check_arg_type(expected, type, context);
}
/*
* Check "type" is a string or a number or a list
*/
static int
arg_str_or_nr_or_list(type_T *type, argcontext_T *context)
{
if (type->tt_type == VAR_STRING
|| type->tt_type == VAR_NUMBER
|| type->tt_type == VAR_LIST)
return OK;
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
return FAIL;
}
/*
* Check "type" which is the third argument of extend().
*/
@@ -438,7 +465,8 @@ argcheck_T arg1_list_nr[] = {arg_list_number};
argcheck_T arg1_list_string[] = {arg_list_string};
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
argcheck_T arg1_string_or_nr[] = {arg_string_or_nr};
argcheck_T arg1_string_or_list[] = {arg_string_or_list};
argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any};
argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string};
argcheck_T arg1_list_or_blob[] = {arg_list_or_blob};
argcheck_T arg1_chan_or_job[] = {arg_chan_or_job};
argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
@@ -449,13 +477,18 @@ argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr};
argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any};
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
argcheck_T arg2_execute[] = {arg_string_or_list, arg_string};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any};
argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any};
argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number};
argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string};
argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string};
argcheck_T arg2_setline[] = {arg_string_or_nr, arg_string_or_list_any};
argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_string_or_list_any};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
/*
@@ -764,7 +797,7 @@ static funcentry_T global_functions[] =
ret_number_bool, f_assert_notequal},
{"assert_notmatch", 2, 3, FEARG_2, arg3_string,
ret_number_bool, f_assert_notmatch},
{"assert_report", 1, 1, FEARG_1, NULL,
{"assert_report", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_assert_report},
{"assert_true", 1, 2, FEARG_1, NULL,
ret_number_bool, f_assert_true},
@@ -780,7 +813,7 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"balloon_show", 1, 1, FEARG_1, arg1_string_or_list,
{"balloon_show", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_void,
#ifdef FEAT_BEVAL
f_balloon_show
@@ -876,7 +909,7 @@ static funcentry_T global_functions[] =
ret_number, f_char2nr},
{"charclass", 1, 1, FEARG_1, arg1_string,
ret_number, f_charclass},
{"charcol", 1, 1, FEARG_1, arg1_string_or_list,
{"charcol", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_charcol},
{"charidx", 2, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_charidx},
@@ -886,7 +919,7 @@ static funcentry_T global_functions[] =
ret_number, f_cindent},
{"clearmatches", 0, 1, FEARG_1, arg1_number,
ret_void, f_clearmatches},
{"col", 1, 1, FEARG_1, arg1_string_or_list,
{"col", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_col},
{"complete", 2, 2, FEARG_2, NULL,
ret_void, f_complete},
@@ -1300,17 +1333,17 @@ static funcentry_T global_functions[] =
NULL
#endif
},
{"popup_atcursor", 2, 2, FEARG_1, NULL,
{"popup_atcursor", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_atcursor)},
{"popup_beval", 2, 2, FEARG_1, NULL,
{"popup_beval", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_beval)},
{"popup_clear", 0, 1, 0, NULL,
ret_void, PROP_FUNC(f_popup_clear)},
{"popup_close", 1, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_close)},
{"popup_create", 2, 2, FEARG_1, NULL,
{"popup_create", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_create)},
{"popup_dialog", 2, 2, FEARG_1, NULL,
{"popup_dialog", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_dialog)},
{"popup_filter_menu", 2, 2, 0, NULL,
ret_bool, PROP_FUNC(f_popup_filter_menu)},
@@ -1330,11 +1363,11 @@ static funcentry_T global_functions[] =
ret_list_number, PROP_FUNC(f_popup_list)},
{"popup_locate", 2, 2, 0, arg2_number,
ret_number, PROP_FUNC(f_popup_locate)},
{"popup_menu", 2, 2, FEARG_1, NULL,
{"popup_menu", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_menu)},
{"popup_move", 2, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_move)},
{"popup_notification", 2, 2, FEARG_1, NULL,
{"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict,
ret_number, PROP_FUNC(f_popup_notification)},
{"popup_setoptions", 2, 2, FEARG_1, NULL,
ret_void, PROP_FUNC(f_popup_setoptions)},
@@ -1540,7 +1573,7 @@ static funcentry_T global_functions[] =
ret_string, f_shellescape},
{"shiftwidth", 0, 1, FEARG_1, arg1_number,
ret_number, f_shiftwidth},
{"sign_define", 1, 2, FEARG_1, arg2_string_dict,
{"sign_define", 1, 2, FEARG_1, arg2_string_or_list_dict,
ret_any, SIGN_FUNC(f_sign_define)},
{"sign_getdefined", 0, 1, FEARG_1, NULL,
ret_list_dict_any, SIGN_FUNC(f_sign_getdefined)},
@@ -1552,7 +1585,7 @@ static funcentry_T global_functions[] =
ret_number, SIGN_FUNC(f_sign_place)},
{"sign_placelist", 1, 1, FEARG_1, NULL,
ret_list_number, SIGN_FUNC(f_sign_placelist)},
{"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list,
{"sign_undefine", 0, 1, FEARG_1, arg1_string_or_list_string,
ret_number_bool, SIGN_FUNC(f_sign_undefine)},
{"sign_unplace", 1, 2, FEARG_1, arg2_string_dict,
ret_number_bool, SIGN_FUNC(f_sign_unplace)},
@@ -1826,13 +1859,13 @@ static funcentry_T global_functions[] =
ret_list_any, f_uniq},
{"values", 1, 1, FEARG_1, arg1_dict,
ret_list_any, f_values},
{"virtcol", 1, 1, FEARG_1, arg1_string_or_list,
{"virtcol", 1, 1, FEARG_1, arg1_string_or_list_any,
ret_number, f_virtcol},
{"visualmode", 0, 1, 0, NULL,
ret_string, f_visualmode},
{"wildmenumode", 0, 0, 0, NULL,
ret_number, f_wildmenumode},
{"win_execute", 2, 3, FEARG_2, NULL,
{"win_execute", 2, 3, FEARG_2, arg23_win_execute,
ret_string, f_win_execute},
{"win_findbuf", 1, 1, FEARG_1, arg1_number,
ret_list_number, f_win_findbuf},

View File

@@ -3613,6 +3613,12 @@ verbose_open(void)
*/
void
give_warning(char_u *message, int hl)
{
give_warning_with_source(message, hl, FALSE);
}
void
give_warning_with_source(char_u *message, int hl, int with_source)
{
// Don't do this for ":silent".
if (msg_silent != 0)
@@ -3629,8 +3635,21 @@ give_warning(char_u *message, int hl)
keep_msg_attr = HL_ATTR(HLF_W);
else
keep_msg_attr = 0;
if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0)
if (with_source)
{
// Do what msg() does, but with a column offset if the warning should
// be after the mode message.
msg_start();
msg_source(HL_ATTR(HLF_W));
msg_puts(" ");
msg_puts_attr((char *)message, HL_ATTR(HLF_W) | MSG_HIST);
msg_clr_eos();
(void)msg_end();
}
else if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0)
set_keep_msg(message, keep_msg_attr);
msg_didout = FALSE; // overwrite this message
msg_nowait = TRUE; // don't wait for this message
msg_col = 0;

View File

@@ -69,6 +69,7 @@ void verbose_leave_scroll(void);
void verbose_stop(void);
int verbose_open(void);
void give_warning(char_u *message, int hl);
void give_warning_with_source(char_u *message, int hl, int with_source);
void give_warning2(char_u *message, char_u *a1, int hl);
void msg_advance(int col);
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd);

View File

@@ -1,5 +1,7 @@
" Tests for user defined commands
source vim9.vim
" Test for <mods> in user defined commands
function Test_cmdmods()
let g:mods = ''
@@ -270,13 +272,29 @@ func Test_CmdErrors()
call assert_fails('com! -complete=custom DoCmd :', 'E467:')
call assert_fails('com! -complete=customlist DoCmd :', 'E467:')
call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:')
call assert_fails('com! -complete=file DoCmd :', 'E1208:')
call assert_fails('com! -nargs=0 -complete=file DoCmd :', 'E1208:')
call assert_fails('com! -nargs=x DoCmd :', 'E176:')
call assert_fails('com! -count=1 -count=2 DoCmd :', 'E177:')
call assert_fails('com! -count=x DoCmd :', 'E178:')
call assert_fails('com! -range=x DoCmd :', 'E178:')
com! -complete=file DoCmd :
call assert_match('E1208:', v:warningmsg)
let v:warningmsg = ''
com! -nargs=0 -complete=file DoCmd :
call assert_match('E1208:', v:warningmsg)
let lines =<< trim END
vim9script
com! -complete=file DoCmd :
END
call CheckScriptFailure(lines, 'E1208', 2)
let lines =<< trim END
vim9script
com! -nargs=0 -complete=file DoCmd :
END
call CheckScriptFailure(lines, 'E1208', 2)
com! -nargs=0 DoCmd :
call assert_fails('DoCmd x', 'E488:')

View File

@@ -213,12 +213,19 @@ def Test_assert_notmatch()
CheckDefFailure(['assert_notmatch("a", "b", null)'], 'E1013: Argument 3: type mismatch, expected string but got special')
enddef
def Test_assert_report()
CheckDefAndScriptFailure2(['assert_report([1, 2])'], 'E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1')
enddef
def Test_balloon_show()
CheckGui
CheckFeature balloon_eval
assert_fails('balloon_show(10)', 'E1174:')
assert_fails('balloon_show(true)', 'E1174:')
CheckDefAndScriptFailure2(['balloon_show(1.2)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['balloon_show({"a": 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1')
enddef
def Test_balloon_split()
@@ -387,6 +394,13 @@ enddef
def Test_charcol()
CheckDefFailure(['charcol(10)'], 'E1013: Argument 1: type mismatch, expected string but got number')
CheckDefFailure(['charcol({a: 10})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>')
new
setline(1, ['abcdefgh'])
cursor(1, 4)
assert_equal(4, charcol('.'))
assert_equal(9, charcol([1, '$']))
assert_equal(0, charcol([10, '$']))
bw!
enddef
def Test_charidx()
@@ -412,8 +426,11 @@ enddef
def Test_col()
new
setline(1, 'asdf')
col([1, '$'])->assert_equal(5)
setline(1, 'abcdefgh')
cursor(1, 4)
assert_equal(4, col('.'))
col([1, '$'])->assert_equal(9)
assert_equal(0, col([10, '$']))
assert_fails('col(true)', 'E1174:')
@@ -1503,11 +1520,36 @@ def Test_or()
CheckDefFailure(['or(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
enddef
def Test_popup_atcursor()
CheckDefAndScriptFailure2(['popup_atcursor({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer number, text or a list required')
CheckDefAndScriptFailure2(['popup_atcursor("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary required')
enddef
def Test_popup_beval()
CheckDefAndScriptFailure2(['popup_beval({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer number, text or a list required')
CheckDefAndScriptFailure2(['popup_beval("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary required')
enddef
def Test_popup_dialog()
CheckDefAndScriptFailure2(['popup_dialog({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer number, text or a list required')
CheckDefAndScriptFailure2(['popup_dialog("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary required')
enddef
def Test_popup_locate()
CheckDefAndScriptFailure2(['popup_locate("a", 20)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1030: Using a String as a Number')
CheckDefAndScriptFailure2(['popup_locate(10, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number')
enddef
def Test_popup_menu()
CheckDefAndScriptFailure2(['popup_menu({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer number, text or a list required')
CheckDefAndScriptFailure2(['popup_menu("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary required')
enddef
def Test_popup_notification()
CheckDefAndScriptFailure2(['popup_notification({"a": 10}, {})'], 'E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E450: buffer number, text or a list required')
CheckDefAndScriptFailure2(['popup_notification("a", [1, 2])'], 'E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E715: Dictionary required')
enddef
def Test_prevnonblank()
CheckDefFailure(['prevnonblank(null)'], 'E1013: Argument 1: type mismatch, expected string but got special')
assert_equal(0, prevnonblank(1))
@@ -1887,6 +1929,17 @@ def Test_setfperm()
CheckDefFailure(['setfperm("a", 0z10)'], 'E1013: Argument 2: type mismatch, expected string but got blob')
enddef
def Test_setline()
new
setline(1, range(1, 4))
assert_equal(['1', '2', '3', '4'], getline(1, '$'))
setline(1, ['a', 'b', 'c', 'd'])
assert_equal(['a', 'b', 'c', 'd'], getline(1, '$'))
setline(1, 'one')
assert_equal(['one', 'b', 'c', 'd'], getline(1, '$'))
bw!
enddef
def Test_setloclist()
var items = [{filename: '/tmp/file', lnum: 1, valid: true}]
var what = {items: items}
@@ -2301,10 +2354,19 @@ enddef
def Test_virtcol()
CheckDefAndScriptFailure2(['virtcol(1.1)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1')
new
setline(1, ['abcdefgh'])
cursor(1, 4)
assert_equal(4, virtcol('.'))
assert_equal(9, virtcol([1, '$']))
assert_equal(0, virtcol([10, '$']))
bw!
enddef
def Test_win_execute()
assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()'))
assert_equal("\n" .. winnr(), 'echo winnr()'->win_execute(win_getid()))
assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()', 'silent'))
assert_equal('', win_execute(342343, 'echo winnr()'))
enddef

View File

@@ -4167,17 +4167,56 @@ def Test_option_modifier()
set hlsearch&
enddef
def ProfiledFunc()
" This must be called last, it may cause following :def functions to fail
def Test_xxx_echoerr_line_number()
var lines =<< trim END
echoerr 'some'
.. ' error'
.. ' continued'
END
CheckDefExecAndScriptFailure(lines, 'some error continued', 1)
enddef
def ProfiledWithLambda()
var n = 3
echo [[1, 2], [3, 4]]->filter((_, l) => l[0] == n)
enddef
def ProfiledNested()
var x = 0
def Nested(): any
return x
enddef
Nested()
enddef
def ProfiledNestedProfiled()
var x = 0
def Nested(): any
return x
enddef
Nested()
enddef
" Execute this near the end, profiling doesn't stop until Vim exists.
" This only tests that it works, not the profiling output.
def Test_xx_profile_with_lambda()
CheckFeature profile
profile start Xprofile.log
profile func ProfiledFunc
ProfiledFunc()
profile func ProfiledWithLambda
ProfiledWithLambda()
profile func ProfiledNested
ProfiledNested()
# Also profile the nested function. Use a different function, although the
# contents is the same, to make sure it was not already compiled.
profile func *
ProfiledNestedProfiled()
profdel func *
profile pause
enddef
" Keep this last, it messes up highlighting.

View File

@@ -824,6 +824,9 @@ f_assert_report(typval_T *argvars, typval_T *rettv)
{
garray_T ga;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
prepare_assert_error(&ga);
ga_concat(&ga, tv_get_string(&argvars[0]));
assert_error(&ga);

View File

@@ -1027,7 +1027,15 @@ ex_command(exarg_T *eap)
&& STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0))
emsg(_("E841: Reserved name, cannot be used for user defined command"));
else if (compl > 0 && (argt & EX_EXTRA) == 0)
emsg(_(e_complete_used_without_nargs));
{
// Some plugins rely on silently ignoring the mistake, only make this
// an error in Vim9 script.
if (in_vim9script())
emsg(_(e_complete_used_without_nargs));
else
give_warning_with_source(
(char_u *)_(e_complete_used_without_nargs), TRUE, TRUE);
}
else
uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
addr_type_arg, eap->forceit);

View File

@@ -755,6 +755,20 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3151,
/**/
3150,
/**/
3149,
/**/
3148,
/**/
3147,
/**/
3146,
/**/
3145,
/**/
3144,
/**/

View File

@@ -1781,6 +1781,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
garray_T *stack = &cctx->ctx_type_stack;
int argoff;
type_T **argtypes = NULL;
type_T *shuffled_argtypes[MAX_FUNC_ARGS];
type_T *maptype = NULL;
RETURN_OK_IF_SKIP(cctx);
@@ -1800,6 +1801,16 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
{
// Check the types of the arguments.
argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
if (method_call && argoff > 1)
{
int i;
for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = (i < argoff - 1)
? argtypes[i + 1]
: (i == argoff - 1) ? argtypes[0] : argtypes[i];
argtypes = shuffled_argtypes;
}
if (internal_func_check_arg_types(argtypes, func_idx, argcount,
cctx) == FAIL)
return FAIL;
@@ -3624,10 +3635,12 @@ compile_lambda(char_u **arg, cctx_T *cctx)
ufunc->uf_ret_type = &t_unknown;
compile_def_function(ufunc, FALSE, cctx->ctx_compile_type, cctx);
#ifdef FEAT_PROFILE
// When the outer function is compiled for profiling, the lambda may be
// called without profiling. Compile it here in the right context.
if (cctx->ctx_compile_type == CT_PROFILE)
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
// evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
// points into it. Point to the original line to avoid a dangling pointer.
@@ -5557,6 +5570,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
char_u *lambda_name;
ufunc_T *ufunc;
int r = FAIL;
compiletype_T compile_type;
if (eap->forceit)
{
@@ -5623,14 +5637,27 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
}
}
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, TRUE, COMPILE_TYPE(ufunc), cctx)
== FAIL)
compile_type = COMPILE_TYPE(ufunc);
#ifdef FEAT_PROFILE
// If the outer function is profiled, also compile the nested function for
// profiling.
if (cctx->ctx_compile_type == CT_PROFILE)
compile_type = CT_PROFILE;
#endif
if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, TRUE, compile_type, cctx) == FAIL)
{
func_ptr_unref(ufunc);
goto theend;
}
#ifdef FEAT_PROFILE
// When the outer function is compiled for profiling, the nested function
// may be called without profiling. Compile it here in the right context.
if (compile_type == CT_PROFILE && func_needs_compiling(ufunc, CT_NONE))
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
if (is_global)
{
char_u *func_name = vim_strnsave(name_start + 2,

View File

@@ -197,6 +197,7 @@ call_dfunc(
int idx;
estack_T *entry;
funclocal_T *floc = NULL;
int res = OK;
if (dfunc->df_deleted)
{
@@ -219,14 +220,6 @@ call_dfunc(
(((dfunc_T *)def_functions.ga_data)
+ ectx->ec_dfunc_idx)->df_ufunc);
}
// Profiling might be enabled/disabled along the way. This should not
// fail, since the function was compiled before and toggling profiling
// doesn't change any errors.
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL)
return FAIL;
}
#endif
@@ -235,10 +228,14 @@ call_dfunc(
// When debugging and using "cont" switches to the not-debugged
// instructions, may need to still compile them.
if ((func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL)
|| INSTRUCTIONS(dfunc) == NULL)
if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc)))
{
res = compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL);
// compile_def_function() may cause def_functions.ga_data to change
dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
}
if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
{
if (did_emsg_cumul + did_emsg == did_emsg_before)
semsg(_(e_function_is_not_compiled_str),