Merge pull request #20954 from zeertzjq/vim-8.2.2918

vim-patch:8.2.{1274,1306,2722,2723,3016}: eval error message improvements
This commit is contained in:
zeertzjq 2022-11-06 08:53:24 +08:00 committed by GitHub
commit be90bfbb00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 12 deletions

View File

@ -1757,7 +1757,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
// Assign to a List or Dictionary item. // Assign to a List or Dictionary item.
if (lp->ll_newkey != NULL) { if (lp->ll_newkey != NULL) {
if (op != NULL && *op != '=') { if (op != NULL && *op != '=') {
semsg(_(e_letwrong), op); semsg(_(e_dictkey), lp->ll_newkey);
return; return;
} }
@ -2277,10 +2277,15 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, int evaluate)
char *p; char *p;
const int did_emsg_before = did_emsg; const int did_emsg_before = did_emsg;
const int called_emsg_before = called_emsg; const int called_emsg_before = called_emsg;
bool end_error = false;
p = skipwhite(arg); p = skipwhite(arg);
ret = eval1(&p, rettv, evaluate); ret = eval1(&p, rettv, evaluate);
if (ret == FAIL || !ends_excmd(*p)) {
if (ret != FAIL) {
end_error = !ends_excmd(*p);
}
if (ret == FAIL || end_error) {
if (ret != FAIL) { if (ret != FAIL) {
tv_clear(rettv); tv_clear(rettv);
} }
@ -2290,7 +2295,11 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, int evaluate)
// Also check called_emsg for when using assert_fails(). // Also check called_emsg for when using assert_fails().
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), arg); if (end_error) {
semsg(_(e_trailing_arg), p);
} else {
semsg(_(e_invexpr2), arg);
}
} }
ret = FAIL; ret = FAIL;
} }
@ -3418,7 +3427,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
if (**arg == '.') { if (**arg == '.') {
// dict.name // dict.name
key = *arg + 1; key = *arg + 1;
for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; len++) {} for (len = 0; eval_isdictc(key[len]); len++) {}
if (len == 0) { if (len == 0) {
return FAIL; return FAIL;
} }
@ -6694,7 +6703,8 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
for (p = arg; *p != NUL for (p = arg; *p != NUL
&& (eval_isnamec(*p) && (eval_isnamec(*p)
|| *p == '{' || *p == '{'
|| ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.')) || ((flags & FNE_INCL_BR) && (*p == '['
|| (*p == '.' && eval_isdictc(p[1]))))
|| mb_nest != 0 || mb_nest != 0
|| br_nest != 0); MB_PTR_ADV(p)) { || br_nest != 0); MB_PTR_ADV(p)) {
if (*p == '\'') { if (*p == '\'') {
@ -6807,18 +6817,25 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex
/// @return true if character "c" can be used in a variable or function name. /// @return true if character "c" can be used in a variable or function name.
/// Does not include '{' or '}' for magic braces. /// Does not include '{' or '}' for magic braces.
int eval_isnamec(int c) bool eval_isnamec(int c)
{ {
return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR; return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
} }
/// @return true if character "c" can be used as the first character in a /// @return true if character "c" can be used as the first character in a
/// variable or function name (excluding '{' and '}'). /// variable or function name (excluding '{' and '}').
int eval_isnamec1(int c) bool eval_isnamec1(int c)
{ {
return ASCII_ISALPHA(c) || c == '_'; return ASCII_ISALPHA(c) || c == '_';
} }
/// @return true if character "c" can be used as the first character of a
/// dictionary key.
bool eval_isdictc(int c)
{
return ASCII_ISALNUM(c) || c == '_';
}
/// Get typval_T v: variable value. /// Get typval_T v: variable value.
typval_T *get_vim_var_tv(int idx) typval_T *get_vim_var_tv(int idx)
{ {

View File

@ -231,11 +231,13 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
expr++; expr++;
} }
} }
expr = skipwhite(expr + 2); expr += 2;
} else { } else {
expr = skipwhite(expr + 1); expr += 1;
} }
expr = skipwhite(expr);
if (eap->skip) { if (eap->skip) {
emsg_skip++; emsg_skip++;
} }

View File

@ -281,15 +281,23 @@ func Test_let_errors()
let l = [[1,2]] let l = [[1,2]]
call assert_fails('let l[:][0] = [5]', 'E708:') call assert_fails('let l[:][0] = [5]', 'E708:')
let d = {'k' : 4} let d = {'k' : 4}
call assert_fails('let d.# = 5', 'E713:') call assert_fails('let d.# = 5', 'E488:')
call assert_fails('let d.m += 5', 'E734:') call assert_fails('let d.m += 5', 'E716:')
call assert_fails('let m = d[{]', 'E15:')
let l = [1, 2] let l = [1, 2]
call assert_fails('let l[2] = 0', 'E684:') call assert_fails('let l[2] = 0', 'E684:')
call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:') call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:')
call assert_fails('let l[-2:-3] = [3, 4]', 'E684:') call assert_fails('let l[-2:-3] = [3, 4]', 'E684:')
call assert_fails('let l[0:4] = [5, 6]', 'E711:') call assert_fails('let l[0:4] = [5, 6]', 'E711:')
call assert_fails('let l -= 2', 'E734:')
call assert_fails('let l += 2', 'E734:')
call assert_fails('let g:["a;b"] = 10', 'E461:') call assert_fails('let g:["a;b"] = 10', 'E461:')
call assert_fails('let g:.min = function("max")', 'E704:') call assert_fails('let g:.min = function("max")', 'E704:')
if has('channel')
let ch = test_null_channel()
call assert_fails('let ch += 1', 'E734:')
endif
call assert_fails('let name = "a" .. "b",', 'E488: Trailing characters: ,')
" This test works only when the language is English " This test works only when the language is English
if v:lang == "C" || v:lang =~ '^[Ee]n' if v:lang == "C" || v:lang =~ '^[Ee]n'

View File

@ -289,6 +289,13 @@ func Test_dict_func()
call assert_equal('xxx3', Fn('xxx')) call assert_equal('xxx3', Fn('xxx'))
endfunc endfunc
func Test_dict_assign()
let d = {}
let d.1 = 1
let d._ = 2
call assert_equal({'1': 1, '_': 2}, d)
endfunc
" Function in script-local List or Dict " Function in script-local List or Dict
func Test_script_local_dict_func() func Test_script_local_dict_func()
let g:dict = {} let g:dict = {}

View File

@ -5569,7 +5569,7 @@ func Test_expr_eval_error_msg()
call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression") call T(22, '1 2 + CONT(22)', 'E488', "Trailing characters: 2 +")
call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")