mirror of
https://github.com/zoriya/vim.git
synced 2025-12-21 06:35:17 +00:00
patch 8.2.2846: Vim9: "echo Func()" does not give an error for using void
Problem: Vim9: "echo Func()" does not give an error for a function without
a return value.
Solution: Give an error. Be more specific about why a value is invalid.
This commit is contained in:
@@ -31,6 +31,8 @@ EXTERN char e_cannot_slice_dictionary[]
|
|||||||
INIT(= N_("E719: Cannot slice a Dictionary"));
|
INIT(= N_("E719: Cannot slice a Dictionary"));
|
||||||
EXTERN char e_assert_fails_second_arg[]
|
EXTERN char e_assert_fails_second_arg[]
|
||||||
INIT(= N_("E856: \"assert_fails()\" second argument must be a string or a list with one or two strings"));
|
INIT(= N_("E856: \"assert_fails()\" second argument must be a string or a list with one or two strings"));
|
||||||
|
EXTERN char e_using_invalid_value_as_string_str[]
|
||||||
|
INIT(= N_("E908: using an invalid value as a String: %s"));
|
||||||
EXTERN char e_cannot_index_special_variable[]
|
EXTERN char e_cannot_index_special_variable[]
|
||||||
INIT(= N_("E909: Cannot index a special variable"));
|
INIT(= N_("E909: Cannot index a special variable"));
|
||||||
#endif
|
#endif
|
||||||
@@ -409,3 +411,5 @@ EXTERN char e_cannot_nest_redir[]
|
|||||||
INIT(= N_("E1185: Cannot nest :redir"));
|
INIT(= N_("E1185: Cannot nest :redir"));
|
||||||
EXTERN char e_missing_redir_end[]
|
EXTERN char e_missing_redir_end[]
|
||||||
INIT(= N_("E1185: Missing :redir END"));
|
INIT(= N_("E1185: Missing :redir END"));
|
||||||
|
EXTERN char e_expression_does_not_result_in_value_str[]
|
||||||
|
INIT(= N_("E1186: Expression does not result in a value: %s"));
|
||||||
|
|||||||
19
src/eval.c
19
src/eval.c
@@ -2951,7 +2951,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
if (vim9script && (var2.v_type == VAR_VOID
|
if (vim9script && (var2.v_type == VAR_VOID
|
||||||
|| var2.v_type == VAR_CHANNEL
|
|| var2.v_type == VAR_CHANNEL
|
||||||
|| var2.v_type == VAR_JOB))
|
|| var2.v_type == VAR_JOB))
|
||||||
emsg(_(e_inval_string));
|
semsg(_(e_using_invalid_value_as_string_str),
|
||||||
|
vartype_name(var2.v_type));
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
else if (vim9script && var2.v_type == VAR_FLOAT)
|
else if (vim9script && var2.v_type == VAR_FLOAT)
|
||||||
{
|
{
|
||||||
@@ -6110,7 +6111,7 @@ ex_echo(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
char_u *arg = eap->arg;
|
char_u *arg = eap->arg;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
char_u *p;
|
char_u *arg_start;
|
||||||
int needclr = TRUE;
|
int needclr = TRUE;
|
||||||
int atstart = TRUE;
|
int atstart = TRUE;
|
||||||
int did_emsg_before = did_emsg;
|
int did_emsg_before = did_emsg;
|
||||||
@@ -6127,7 +6128,7 @@ ex_echo(exarg_T *eap)
|
|||||||
// still need to be cleared. E.g., "echo 22,44".
|
// still need to be cleared. E.g., "echo 22,44".
|
||||||
need_clr_eos = needclr;
|
need_clr_eos = needclr;
|
||||||
|
|
||||||
p = arg;
|
arg_start = arg;
|
||||||
if (eval1(&arg, &rettv, &evalarg) == FAIL)
|
if (eval1(&arg, &rettv, &evalarg) == FAIL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -6137,14 +6138,21 @@ ex_echo(exarg_T *eap)
|
|||||||
*/
|
*/
|
||||||
if (!aborting() && did_emsg == did_emsg_before
|
if (!aborting() && did_emsg == did_emsg_before
|
||||||
&& called_emsg == called_emsg_before)
|
&& called_emsg == called_emsg_before)
|
||||||
semsg(_(e_invexpr2), p);
|
semsg(_(e_invexpr2), arg_start);
|
||||||
need_clr_eos = FALSE;
|
need_clr_eos = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
need_clr_eos = FALSE;
|
need_clr_eos = FALSE;
|
||||||
|
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
|
{
|
||||||
|
if (rettv.v_type == VAR_VOID)
|
||||||
|
{
|
||||||
|
semsg(_(e_expression_does_not_result_in_value_str), arg_start);
|
||||||
|
break;
|
||||||
|
}
|
||||||
echo_one(&rettv, eap->cmdidx == CMD_echo, &atstart, &needclr);
|
echo_one(&rettv, eap->cmdidx == CMD_echo, &atstart, &needclr);
|
||||||
|
}
|
||||||
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
arg = skipwhite(arg);
|
arg = skipwhite(arg);
|
||||||
@@ -6218,7 +6226,8 @@ ex_execute(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
if (rettv.v_type == VAR_CHANNEL || rettv.v_type == VAR_JOB)
|
if (rettv.v_type == VAR_CHANNEL || rettv.v_type == VAR_JOB)
|
||||||
{
|
{
|
||||||
emsg(_(e_inval_string));
|
semsg(_(e_using_invalid_value_as_string_str),
|
||||||
|
vartype_name(rettv.v_type));
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -3175,7 +3175,8 @@ execute_common(typval_T *argvars, typval_T *rettv, int arg_off)
|
|||||||
else if (argvars[arg_off].v_type == VAR_JOB
|
else if (argvars[arg_off].v_type == VAR_JOB
|
||||||
|| argvars[arg_off].v_type == VAR_CHANNEL)
|
|| argvars[arg_off].v_type == VAR_CHANNEL)
|
||||||
{
|
{
|
||||||
emsg(_(e_inval_string));
|
semsg(_(e_using_invalid_value_as_string_str),
|
||||||
|
vartype_name(argvars[arg_off].v_type));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1728,7 +1728,6 @@ EXTERN char e_list_end[] INIT(= N_("E697: Missing end of List ']': %s"));
|
|||||||
EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary"));
|
EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary"));
|
||||||
EXTERN char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob"));
|
EXTERN char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob"));
|
||||||
EXTERN char e_modulus[] INIT(= N_("E804: Cannot use '%' with Float"));
|
EXTERN char e_modulus[] INIT(= N_("E804: Cannot use '%' with Float"));
|
||||||
EXTERN char e_inval_string[] INIT(= N_("E908: using an invalid value as a String"));
|
|
||||||
EXTERN char e_const_option[] INIT(= N_("E996: Cannot lock an option"));
|
EXTERN char e_const_option[] INIT(= N_("E996: Cannot lock an option"));
|
||||||
EXTERN char e_unknown_option[] INIT(= N_("E113: Unknown option: %s"));
|
EXTERN char e_unknown_option[] INIT(= N_("E113: Unknown option: %s"));
|
||||||
EXTERN char e_letunexp[] INIT(= N_("E18: Unexpected characters in :let"));
|
EXTERN char e_letunexp[] INIT(= N_("E18: Unexpected characters in :let"));
|
||||||
|
|||||||
@@ -1282,5 +1282,28 @@ def Test_redir_to_var()
|
|||||||
CheckDefFailure(lines, 'E1141:')
|
CheckDefFailure(lines, 'E1141:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_echo_void()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def NoReturn()
|
||||||
|
echo 'nothing'
|
||||||
|
enddef
|
||||||
|
echo NoReturn()
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E1186:', 5)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def NoReturn()
|
||||||
|
echo 'nothing'
|
||||||
|
enddef
|
||||||
|
def Try()
|
||||||
|
echo NoReturn()
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E1186:', 1)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
|||||||
@@ -522,7 +522,8 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
|
|||||||
case VAR_ANY:
|
case VAR_ANY:
|
||||||
case VAR_VOID:
|
case VAR_VOID:
|
||||||
case VAR_INSTR:
|
case VAR_INSTR:
|
||||||
emsg(_(e_inval_string));
|
semsg(_(e_using_invalid_value_as_string_str),
|
||||||
|
vartype_name(varp->v_type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
2846,
|
||||||
/**/
|
/**/
|
||||||
2845,
|
2845,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@@ -8375,15 +8375,31 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
char_u *p = arg;
|
char_u *p = arg;
|
||||||
char_u *prev = arg;
|
char_u *prev = arg;
|
||||||
|
char_u *expr_start;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int start_ctx_lnum = cctx->ctx_lnum;
|
int start_ctx_lnum = cctx->ctx_lnum;
|
||||||
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
|
type_T *type;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (ends_excmd2(prev, p))
|
if (ends_excmd2(prev, p))
|
||||||
break;
|
break;
|
||||||
|
expr_start = p;
|
||||||
if (compile_expr0(&p, cctx) == FAIL)
|
if (compile_expr0(&p, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (cctx->ctx_skip != SKIP_YES)
|
||||||
|
{
|
||||||
|
// check for non-void type
|
||||||
|
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
|
if (type->tt_type == VAR_VOID)
|
||||||
|
{
|
||||||
|
semsg(_(e_expression_does_not_result_in_value_str), expr_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
prev = p;
|
prev = p;
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
|
|||||||
@@ -1578,7 +1578,8 @@ exec_instructions(ectx_T *ectx)
|
|||||||
|| tv->v_type == VAR_JOB)
|
|| tv->v_type == VAR_JOB)
|
||||||
{
|
{
|
||||||
SOURCING_LNUM = iptr->isn_lnum;
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
emsg(_(e_inval_string));
|
semsg(_(e_using_invalid_value_as_string_str),
|
||||||
|
vartype_name(tv->v_type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user