aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c29
-rw-r--r--src/nvim/eval/userfunc.c3
-rw-r--r--src/nvim/eval/vars.c4
-rw-r--r--test/old/testdir/test_expr.vim7
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