Compare commits

...

3 Commits

Author SHA1 Message Date
Bram Moolenaar
e32e516dfa patch 8.2.2387: runtime type check does not mention argument index
Problem:    Runtime type check does not mention argument index.
Solution:   Add ct_arg_idx. (closes #7720)
2021-01-21 20:21:29 +01:00
Bram Moolenaar
f904133e1a patch 8.2.2386: Vim9: crash when using ":silent! put"
Problem:    Vim9: crash when using ":silent! put".
Solution:   When ignoring an error for ":silent!" rewind the stack and skip
            ahead to restoring the cmdmod. (closes #7717)
2021-01-21 19:41:16 +01:00
Bram Moolenaar
e71996bd08 patch 8.2.2385: "gj" and "gk" do not work correctly when inside a fold
Problem:    "gj" and "gk" do not work correctly when inside a fold.
Solution:   Move check for folding. (closes #7724, closes #4095)
2021-01-21 17:03:07 +01:00
9 changed files with 126 additions and 32 deletions

View File

@@ -2570,12 +2570,6 @@ nv_screengo(oparg_T *oap, int dir, long dist)
else
{
// to previous line
if (curwin->w_cursor.lnum == 1)
{
retval = FAIL;
break;
}
--curwin->w_cursor.lnum;
#ifdef FEAT_FOLDING
// Move to the start of a closed fold. Don't do that when
// 'foldopen' contains "all": it will open in a moment.
@@ -2583,6 +2577,13 @@ nv_screengo(oparg_T *oap, int dir, long dist)
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
#endif
if (curwin->w_cursor.lnum == 1)
{
retval = FAIL;
break;
}
--curwin->w_cursor.lnum;
linelen = linetabsize(ml_get_curline());
if (linelen > width1)
curwin->w_curswant += (((linelen - width1 - 1) / width2)
@@ -5957,13 +5958,8 @@ nv_g_cmd(cmdarg_T *cap)
*/
case 'j':
case K_DOWN:
// with 'nowrap' it works just like the normal "j" command; also when
// in a closed fold
if (!curwin->w_p_wrap
#ifdef FEAT_FOLDING
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
#endif
)
// with 'nowrap' it works just like the normal "j" command.
if (!curwin->w_p_wrap)
{
oap->motion_type = MLINE;
i = cursor_down(cap->count1, oap->op_type == OP_NOP);
@@ -5976,13 +5972,8 @@ nv_g_cmd(cmdarg_T *cap)
case 'k':
case K_UP:
// with 'nowrap' it works just like the normal "k" command; also when
// in a closed fold
if (!curwin->w_p_wrap
#ifdef FEAT_FOLDING
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
#endif
)
// with 'nowrap' it works just like the normal "k" command.
if (!curwin->w_p_wrap)
{
oap->motion_type = MLINE;
i = cursor_up(cap->count1, oap->op_type == OP_NOP);

View File

@@ -859,4 +859,39 @@ func Test_fold_create_delete()
bwipe!
endfunc
func Test_fold_relative_move()
enew!
set fdm=indent sw=2 wrap tw=80
let content = [ ' foo', ' bar', ' baz',
\ repeat('x', 100),
\ ' foo', ' bar', ' baz'
\ ]
call append(0, content)
normal zM
call cursor(3, 1)
call assert_true(foldclosed(line('.')))
normal gj
call assert_equal(2, winline())
call cursor(2, 1)
call assert_true(foldclosed(line('.')))
normal 2gj
call assert_equal(3, winline())
call cursor(5, 1)
call assert_true(foldclosed(line('.')))
normal gk
call assert_equal(3, winline())
call cursor(6, 1)
call assert_true(foldclosed(line('.')))
normal 2gk
call assert_equal(2, winline())
set fdm& sw& wrap& tw&
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -263,7 +263,7 @@ def Test_extend_arg_types()
CheckDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number')
CheckDefFailure(['extend([1], ["b"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1012: Type mismatch; expected list<number> but got list<any>')
CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<any>')
enddef
def Test_extendnew()

View File

@@ -934,7 +934,7 @@ def Test_disassemble_lambda_with_type()
'return Ref(g:value)\_s*' ..
'\d LOADG g:value\_s*' ..
'\d LOAD $0\_s*' ..
'\d CHECKTYPE number stack\[-2\]\_s*' ..
'\d CHECKTYPE number stack\[-2\] arg 1\_s*' ..
'\d PCALL (argc 1)\_s*' ..
'\d RETURN',
instr)

View File

@@ -144,6 +144,22 @@ def Test_return_something()
assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
enddef
def Test_check_argument_type()
var lines =<< trim END
vim9script
def Val(a: number, b: number): number
return 0
enddef
def Func()
var x: any = true
Val(0, x)
enddef
disass Func
Func()
END
CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2)
enddef
def Test_missing_return()
CheckDefFailure(['def Missing(): number',
' if g:cond',
@@ -2184,6 +2200,24 @@ def Test_dict_member_with_silent()
CheckScriptSuccess(lines)
enddef
def Test_skip_cmds_with_silent()
var lines =<< trim END
vim9script
def Func(b: bool)
Crash()
enddef
def Crash()
sil! :/not found/d _
sil! :/not found/put _
enddef
Func(true)
END
CheckScriptSuccess(lines)
enddef
def Test_opfunc()
nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@
def g:Opfunc(_: any): string

View File

@@ -750,6 +750,12 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2387,
/**/
2386,
/**/
2385,
/**/
2384,
/**/

View File

@@ -224,7 +224,8 @@ typedef struct {
// arguments to ISN_CHECKTYPE
typedef struct {
type_T *ct_type;
int ct_off; // offset in stack, -1 is bottom
char ct_off; // offset in stack, -1 is bottom
char ct_arg_idx; // argument index or zero
} checktype_T;
// arguments to ISN_STORENR

View File

@@ -816,7 +816,8 @@ generate_COND2BOOL(cctx_T *cctx)
generate_TYPECHECK(
cctx_T *cctx,
type_T *expected,
int offset)
int offset,
int argidx)
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
@@ -826,6 +827,7 @@ generate_TYPECHECK(
return FAIL;
isn->isn_arg.type.ct_type = alloc_type(expected);
isn->isn_arg.type.ct_off = offset;
isn->isn_arg.type.ct_arg_idx = argidx;
// type becomes expected
((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
@@ -904,7 +906,7 @@ need_type(
// If it's a constant a runtime check makes no sense.
if (!actual_is_const && use_typecheck(actual, expected))
{
generate_TYPECHECK(cctx, expected, offset);
generate_TYPECHECK(cctx, expected, offset, arg_idx);
return OK;
}
@@ -1637,7 +1639,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
if (maptype != NULL && maptype->tt_member != NULL
&& maptype->tt_member != &t_any)
// Check that map() didn't change the item types.
generate_TYPECHECK(cctx, maptype, -1);
generate_TYPECHECK(cctx, maptype, -1, 1);
return OK;
}
@@ -1735,7 +1737,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
else
expected = ufunc->uf_va_type->tt_member;
actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
if (need_type(actual, expected, -argcount + i, 0, cctx,
if (need_type(actual, expected, -argcount + i, i + 1, cctx,
TRUE, FALSE) == FAIL)
{
arg_type_mismatch(expected, actual, i + 1);
@@ -1852,7 +1854,7 @@ generate_PCALL(
type->tt_argcount - 1]->tt_member;
else
expected = type->tt_args[i];
if (need_type(actual, expected, offset, 0,
if (need_type(actual, expected, offset, i + 1,
cctx, TRUE, FALSE) == FAIL)
{
arg_type_mismatch(expected, actual, i + 1);

View File

@@ -1124,6 +1124,7 @@ call_def_function(
msglist_T *private_msg_list = NULL;
cmdmod_T save_cmdmod;
int restore_cmdmod = FALSE;
int restore_cmdmod_stacklen = 0;
int save_emsg_silent_def = emsg_silent_def;
int save_did_emsg_def = did_emsg_def;
int trylevel_at_start = trylevel;
@@ -3241,7 +3242,8 @@ call_def_function(
tv = STACK_TV_BOT(ct->ct_off);
SOURCING_LNUM = iptr->isn_lnum;
if (check_typval_type(ct->ct_type, tv, 0) == FAIL)
if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx)
== FAIL)
goto on_error;
// number 0 is FALSE, number 1 is TRUE
@@ -3398,6 +3400,7 @@ call_def_function(
case ISN_CMDMOD:
save_cmdmod = cmdmod;
restore_cmdmod = TRUE;
restore_cmdmod_stacklen = ectx.ec_stack.ga_len;
cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
apply_cmdmod(&cmdmod);
break;
@@ -3523,7 +3526,22 @@ on_error:
// when calling the function.
if (did_emsg_cumul + did_emsg == did_emsg_before
&& emsg_silent && did_emsg_def == 0)
{
// If a sequence of instructions causes an error while ":silent!"
// was used, restore the stack length and jump ahead to restoring
// the cmdmod.
if (restore_cmdmod)
{
while (ectx.ec_stack.ga_len > restore_cmdmod_stacklen)
{
--ectx.ec_stack.ga_len;
clear_tv(STACK_TV_BOT(0));
}
while (ectx.ec_instr[ectx.ec_iidx].isn_type != ISN_CMDMOD_REV)
++ectx.ec_iidx;
}
continue;
}
on_fatal_error:
// Jump here for an error that messes up the stack.
// If we are not inside a try-catch started here, abort execution.
@@ -4218,11 +4236,18 @@ ex_disassemble(exarg_T *eap)
case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
case ISN_CHECKTYPE:
{
checktype_T *ct = &iptr->isn_arg.type;
char *tofree;
smsg("%4d CHECKTYPE %s stack[%d]", current,
type_name(iptr->isn_arg.type.ct_type, &tofree),
iptr->isn_arg.type.ct_off);
if (ct->ct_arg_idx == 0)
smsg("%4d CHECKTYPE %s stack[%d]", current,
type_name(ct->ct_type, &tofree),
(int)ct->ct_off);
else
smsg("%4d CHECKTYPE %s stack[%d] arg %d", current,
type_name(ct->ct_type, &tofree),
(int)ct->ct_off,
(int)ct->ct_arg_idx);
vim_free(tofree);
break;
}