vim-patch:9.2.1288: E110 "missing ')'" error does not say where the problem is (#42698)

Problem:  An invalid nested expression such as "echo (0!)" gives
          "E110: Missing ')'" although the ")" is there, and does not say
          where the expression is not valid.
Solution: When text follows the expression, add it to the E110 message, as
          E697 does for a List (zuloloxi).

Without parentheses "echo 0!" already gives E15 with the text "!".  When
nothing follows the expression the ")" is really missing and the message
is as before.

related: vim/vim#17602
closes:  vim/vim#21607

https://github.com/vim/vim/commit/d06691450ab0dc2ea72a997f8426002f66da2ac2

Co-authored-by: zuloloxi <10588750+zuloloxi@users.noreply.github.com>
This commit is contained in:
zeertzjqandzuloloxi authored and GitHub committed 2026-11-05 08:51:27 +08:00
1 parent 2da580649e
commit 1332ed9027
5 files changed
+34 -2

No files matched your search

+8
View File
@@ -1566,9 +1566,17 @@ When using the '=' register you get the expression itself, not what it
evaluates to. Use |eval()| to evaluate it.
------------------------------------------------------------------------------
nesting *expr-nesting* *E110*
(expr1) nested expression
If text follows the expression, E110 includes it, to show where the expression
should end: >
echo (0!)
< E110: Missing ')': !) ~
Vim expects the ")" where the "!" is.
------------------------------------------------------------------------------
environment variable *expr-env*
+1 -1
View File
@@ -10,7 +10,7 @@
local dup_allowed = {
E109 = 2,
E1098 = 2,
E110 = 2,
E110 = 3,
E112 = 2,
E114 = 2,
E115 = 2,
+2
View File
@@ -130,6 +130,8 @@ EXTERN const char e_write[] INIT(= N_("E80: Error while writing"));
EXTERN const char e_zerocount[] INIT(= N_("E939: Positive count required"));
EXTERN const char e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context"));
EXTERN const char e_missingparen[] INIT(= N_("E107: Missing parentheses: %s"));
EXTERN const char e_missing_closing_paren[] INIT(= N_("E110: Missing ')'"));
EXTERN const char e_missing_closing_paren_str[] INIT(= N_("E110: Missing ')': %s"));
EXTERN const char e_empty_buffer[] INIT(= N_("E749: Empty buffer"));
EXTERN const char e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist"));
+6 -1
View File
@@ -2755,7 +2755,12 @@ static int eval7(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan
if (**arg == ')') {
(*arg)++;
} else if (ret == OK) {
emsg(_("E110: Missing ')'"));
// Show where the expression stopped, unless at the end.
if (**arg == NUL) {
emsg(_(e_missing_closing_paren));
} else {
semsg(_(e_missing_closing_paren_str), *arg);
}
tv_clear(rettv);
ret = FAIL;
}
+17
View File
@@ -209,6 +209,23 @@ func Test_special_char()
call CheckLegacyAndVim9Failure(['echo "\<C-">'], ['E15:', 'E1004:', 'E1004:'])
endfunc
" When something else than ")" follows a nested expression, E110 shows where
" the expression ended; when nothing follows, the ")" is really missing.
func Test_missing_closing_paren()
call CheckLegacyAndVim9Failure(['echo (0!)'], "E110: Missing ')': !)")
call CheckLegacyAndVim9Failure(['echo (1 2)'], "E110: Missing ')': 2)")
call CheckLegacyAndVim9Failure(['echo (1 + 2 ]'], "E110: Missing ')': ]")
call CheckLegacyAndVim9Failure(['echo ("a" "b")'], "E110: Missing ')': \"b\")")
" in a :def function the expression may continue on the next line
call CheckLegacyAndVim9Failure(['VAR x = ((1)'], ["E110: Missing ')'", 'E1097:', "E110: Missing ')'"])
try
echo ((1)
call assert_report('should not get here')
catch
call assert_equal("Vim(echo):E110: Missing ')'", v:exception)
endtry
endfunc
func Test_method_with_prefix()
let lines =<< trim END
call assert_equal(TRUE, !range(5)->empty())