diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-03-09 13:47:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-09 13:47:01 +0800 |
commit | 3ad845882413944a8d6ed3bd9da68c6b4cee0afb (patch) | |
tree | 56f889cfd0efd2106b57cfd2dfa171edf0666150 | |
parent | 89a525de9f2551e460cc91d40fd7afbb7e07622f (diff) | |
download | rneovim-3ad845882413944a8d6ed3bd9da68c6b4cee0afb.tar.gz rneovim-3ad845882413944a8d6ed3bd9da68c6b4cee0afb.tar.bz2 rneovim-3ad845882413944a8d6ed3bd9da68c6b4cee0afb.zip |
vim-patch:8.2.1067: expression "!expr->func()" does not work (#22585)
Problem: Expression "!expr->func()" does not work.
Solution: Apply plus and minus earlier. (closes vim/vim#6348)
https://github.com/vim/vim/commit/0b1cd52ff6bf690388f892be686a91721a082e55
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/eval.c | 29 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 3 | ||||
-rw-r--r-- | src/nvim/eval/vars.c | 4 | ||||
-rw-r--r-- | test/old/testdir/test_expr.vim | 7 |
4 files changed, 27 insertions, 16 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index cbad5d04ff..9b42375120 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2906,6 +2906,12 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string) case '8': case '9': ret = get_number_tv(arg, rettv, evaluate, want_string); + + // Apply prefixed "-" and "+" now. Matters especially when + // "->" follows. + if (ret == OK && evaluate && end_leader > start_leader) { + ret = eval7_leader(rettv, true, start_leader, &end_leader); + } break; // String constant: "string". @@ -3011,13 +3017,12 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string) // Handle following '[', '(' and '.' for expr[expr], expr.name, // expr(expr), expr->name(expr) if (ret == OK) { - ret = handle_subscript((const char **)arg, rettv, evaluate, true, - (char *)start_leader, &end_leader); + ret = handle_subscript((const char **)arg, rettv, evaluate, true); } // Apply logical NOT and unary '-', from right to left, ignore '+'. if (ret == OK && evaluate && end_leader > start_leader) { - ret = eval7_leader(rettv, (char *)start_leader, &end_leader); + ret = eval7_leader(rettv, false, start_leader, &end_leader); } recurse--; @@ -3027,9 +3032,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string) /// Apply the leading "!" and "-" before an eval7 expression to "rettv". /// Adjusts "end_leaderp" until it is at "start_leader". /// +/// @param numeric_only if true only handle "+" and "-". +/// /// @return OK on success, FAIL on failure. -static int eval7_leader(typval_T *const rettv, const char *const start_leader, - const char **const end_leaderp) +static int eval7_leader(typval_T *const rettv, const bool numeric_only, + const char *const start_leader, const char **const end_leaderp) FUNC_ATTR_NONNULL_ALL { const char *end_leader = (char *)(*end_leaderp); @@ -3050,6 +3057,10 @@ static int eval7_leader(typval_T *const rettv, const char *const start_leader, while (end_leader > start_leader) { end_leader--; if (*end_leader == '!') { + if (numeric_only) { + end_leader++; + break; + } if (rettv->v_type == VAR_FLOAT) { f = !(bool)f; } else { @@ -6899,8 +6910,7 @@ int check_luafunc_name(const char *const str, const bool paren) /// @param verbose give error messages /// @param start_leader start of '!' and '-' prefixes /// @param end_leaderp end of '!' and '-' prefixes -int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int verbose, - const char *const start_leader, const char **const end_leaderp) +int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int verbose) { int ret = OK; dict_T *selfdict = NULL; @@ -6944,11 +6954,6 @@ int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int tv_dict_unref(selfdict); selfdict = NULL; } else if (**arg == '-') { - // Expression "-1.0->method()" applies the leader "-" before - // applying ->. - if (evaluate && *end_leaderp > start_leader) { - ret = eval7_leader(rettv, (char *)start_leader, end_leaderp); - } if (ret == OK) { if ((*arg)[2] == '{') { // expr->{lambda}() diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 3c4cc34464..13779f4173 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3075,8 +3075,7 @@ void ex_call(exarg_T *eap) } // Handle a function returning a Funcref, Dictionary or List. - if (handle_subscript((const char **)&arg, &rettv, true, true, - (const char *)name, (const char **)&name) + if (handle_subscript((const char **)&arg, &rettv, true, true) == FAIL) { failed = true; break; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index d80bdc70f6..ed2453bd59 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -508,7 +508,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) } else { // handle d.key, l[idx], f(expr) const char *const arg_subsc = arg; - if (handle_subscript(&arg, &tv, true, true, name, &name) == FAIL) { + if (handle_subscript(&arg, &tv, true, true) == FAIL) { error = true; } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { @@ -1715,7 +1715,7 @@ bool var_exists(const char *var) n = get_var_tv(name, len, &tv, NULL, false, true) == OK; if (n) { // Handle d.key, l[idx], f(expr). - n = handle_subscript(&var, &tv, true, false, name, &name) == OK; + n = handle_subscript(&var, &tv, true, false) == OK; if (n) { tv_clear(&tv); } diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim index 47f7f5eb0e..292a504df9 100644 --- a/test/old/testdir/test_expr.vim +++ b/test/old/testdir/test_expr.vim @@ -111,6 +111,13 @@ func Test_special_char() call assert_fails('echo "\<C-">') endfunc +func Test_method_with_prefix() + call assert_equal(1, !range(5)->empty()) + call assert_equal([0, 1, 2], --3->range()) + call assert_equal(0, !-3) + call assert_equal(1, !+-+0) +endfunc + func Test_option_value() " boolean set bri |