1
0
forked from aniani/vim

patch 8.2.1365: Vim9: no error for missing white space around operator

Problem:    Vim9: no error for missing white space around operator.
Solution:   Check for white space. (closes #6618)
This commit is contained in:
Bram Moolenaar
2020-08-05 10:53:21 +02:00
parent 282f9c64e5
commit bb1b5e24ec
7 changed files with 80 additions and 26 deletions

View File

@@ -2574,6 +2574,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
int getnext; int getnext;
char_u *p; char_u *p;
int op; int op;
int oplen;
int concat; int concat;
typval_T var2; typval_T var2;
@@ -2584,11 +2585,19 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
if (op != '+' && op != '-' && !concat) if (op != '+' && op != '-' && !concat)
break; break;
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
if (getnext) if (getnext)
*arg = eval_next_line(evalarg); *arg = eval_next_line(evalarg);
else else
{
if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg))
{
error_white_both(p, 1);
clear_tv(rettv);
return FAIL;
}
*arg = p; *arg = p;
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); }
if ((op != '+' || (rettv->v_type != VAR_LIST if ((op != '+' || (rettv->v_type != VAR_LIST
&& rettv->v_type != VAR_BLOB)) && rettv->v_type != VAR_BLOB))
#ifdef FEAT_FLOAT #ifdef FEAT_FLOAT
@@ -2613,9 +2622,14 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
/* /*
* Get the second variable. * Get the second variable.
*/ */
if (op == '.' && *(*arg + 1) == '.') // .. string concatenation oplen = (op == '.' && *(*arg + 1) == '.') ? 2 : 1;
++*arg; if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[oplen]))
*arg = skipwhite_and_linebreak(*arg + 1, evalarg); {
error_white_both(p, oplen);
clear_tv(rettv);
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
if (eval6(arg, &var2, evalarg, op == '.') == FAIL) if (eval6(arg, &var2, evalarg, op == '.') == FAIL)
{ {
clear_tv(rettv); clear_tv(rettv);
@@ -3358,6 +3372,7 @@ eval_method(
} }
else else
{ {
*arg = skipwhite(*arg);
if (**arg != '(') if (**arg != '(')
{ {
if (verbose) if (verbose)
@@ -4841,7 +4856,7 @@ get_env_len(char_u **arg)
/* /*
* Get the length of the name of a function or internal variable. * Get the length of the name of a function or internal variable.
* "arg" is advanced to the first non-white character after the name. * "arg" is advanced to after the name.
* Return 0 if something is wrong. * Return 0 if something is wrong.
*/ */
int int
@@ -4867,7 +4882,7 @@ get_id_len(char_u **arg)
return 0; return 0;
len = (int)(p - *arg); len = (int)(p - *arg);
*arg = skipwhite(p); *arg = p;
return len; return len;
} }

View File

@@ -1137,6 +1137,7 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first)
} }
else else
{ {
arg = skipwhite(arg);
if (tofree != NULL) if (tofree != NULL)
name = tofree; name = tofree;
if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL) if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
@@ -3358,6 +3359,7 @@ assert_error(garray_T *gap)
int int
var_exists(char_u *var) var_exists(char_u *var)
{ {
char_u *arg = var;
char_u *name; char_u *name;
char_u *tofree; char_u *tofree;
typval_T tv; typval_T tv;
@@ -3366,7 +3368,7 @@ var_exists(char_u *var)
// get_name_len() takes care of expanding curly braces // get_name_len() takes care of expanding curly braces
name = var; name = var;
len = get_name_len(&var, &tofree, TRUE, FALSE); len = get_name_len(&arg, &tofree, TRUE, FALSE);
if (len > 0) if (len > 0)
{ {
if (tofree != NULL) if (tofree != NULL)
@@ -3375,12 +3377,13 @@ var_exists(char_u *var)
if (n) if (n)
{ {
// handle d.key, l[idx], f(expr) // handle d.key, l[idx], f(expr)
n = (handle_subscript(&var, &tv, &EVALARG_EVALUATE, FALSE) == OK); arg = skipwhite(arg);
n = (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, FALSE) == OK);
if (n) if (n)
clear_tv(&tv); clear_tv(&tv);
} }
} }
if (*var != NUL) if (*arg != NUL)
n = FALSE; n = FALSE;
vim_free(tofree); vim_free(tofree);

View File

@@ -17,6 +17,7 @@ char_u *peek_next_line_from_context(cctx_T *cctx);
char_u *next_line_from_context(cctx_T *cctx, int skip_comment); char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
char_u *to_name_const_end(char_u *arg); char_u *to_name_const_end(char_u *arg);
exptype_T get_compare_type(char_u *p, int *len, int *type_is); exptype_T get_compare_type(char_u *p, int *len, int *type_is);
void error_white_both(char_u *op, int len);
int assignment_len(char_u *p, int *heredoc); int assignment_len(char_u *p, int *heredoc);
void vim9_declare_error(char_u *name); void vim9_declare_error(char_u *name);
int check_vim9_unlet(char_u *name); int check_vim9_unlet(char_u *name);

View File

@@ -872,6 +872,39 @@ def Test_expr5_vim9script()
echo 'abc' isnot? 'abc' echo 'abc' isnot? 'abc'
END END
CheckScriptFailure(lines, 'E15:') CheckScriptFailure(lines, 'E15:')
# check white space
lines =<< trim END
vim9script
echo 5+6
END
CheckScriptFailure(lines, 'E1004:')
lines =<< trim END
vim9script
echo 5 +6
END
CheckScriptFailure(lines, 'E1004:')
lines =<< trim END
vim9script
echo 5+ 6
END
CheckScriptFailure(lines, 'E1004:')
lines =<< trim END
vim9script
echo 'a'..'b'
END
CheckScriptFailure(lines, 'E1004:')
lines =<< trim END
vim9script
echo 'a' ..'b'
END
CheckScriptFailure(lines, 'E1004:')
lines =<< trim END
vim9script
echo 'a'.. 'b'
END
CheckScriptFailure(lines, 'E1004:')
enddef enddef
def Test_expr5_float() def Test_expr5_float()

View File

@@ -1270,7 +1270,7 @@ enddef
def TreeWalk(dir: string): list<any> def TreeWalk(dir: string): list<any>
return readdir(dir)->map({_, val -> return readdir(dir)->map({_, val ->
fnamemodify(dir .. '/' .. val, ':p')->isdirectory() fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
? {val : TreeWalk(dir .. '/' .. val)} ? {val: TreeWalk(dir .. '/' .. val)}
: val : val
}) })
enddef enddef

View File

@@ -754,6 +754,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 */
/**/
1365,
/**/ /**/
1364, 1364,
/**/ /**/

View File

@@ -4243,6 +4243,18 @@ compile_expr7(
return OK; return OK;
} }
/*
* Give the "white on both sides" error, taking the operator from "p[len]".
*/
void
error_white_both(char_u *op, int len)
{
char_u buf[10];
vim_strncpy(buf, op, len);
semsg(_(e_white_both), buf);
}
/* /*
* * number multiplication * * number multiplication
* / number division * / number division
@@ -4275,10 +4287,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1])) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
{ {
char_u buf[3]; error_white_both(op, 1);
vim_strncpy(buf, op, 1);
semsg(_(e_white_both), buf);
return FAIL; return FAIL;
} }
*arg = skipwhite(op + 1); *arg = skipwhite(op + 1);
@@ -4354,10 +4363,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen])) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
{ {
char_u buf[3]; error_white_both(op, oplen);
vim_strncpy(buf, op, oplen);
semsg(_(e_white_both), buf);
return FAIL; return FAIL;
} }
@@ -4486,10 +4492,7 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len])) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
{ {
char_u buf[7]; error_white_both(p, len);
vim_strncpy(buf, p, len);
semsg(_(e_white_both), buf);
return FAIL; return FAIL;
} }
@@ -5132,10 +5135,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen]))) if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
{ {
char_u buf[4]; error_white_both(op, oplen);
vim_strncpy(buf, op, oplen);
semsg(_(e_white_both), buf);
return NULL; return NULL;
} }