changeset 24254:0868ac82ef18 v8.2.2668

patch 8.2.2668: Vim9: omitting "call" for "confirm()" does not give an error Commit: https://github.com/vim/vim/commit/f49a1fcdb952ca270f108fcc27bb8ad6922e0807 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 27 22:20:21 2021 +0100 patch 8.2.2668: Vim9: omitting "call" for "confirm()" does not give an error Problem: Vim9: omitting "call" for "confirm()" does not give an error. Solution: Do not recognize a modifier followed by "(".
author Bram Moolenaar <Bram@vim.org>
date Sat, 27 Mar 2021 22:30:02 +0100
parents 5fdc41e253e7
children 811f6574df57
files src/ex_docmd.c src/testdir/test_vim9_builtin.vim src/version.c
diffstat 3 files changed, 84 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2685,6 +2685,58 @@ ex_errmsg(char *msg, char_u *arg)
 }
 
 /*
+ * Check for an Ex command with optional tail.
+ * If there is a match advance "pp" to the argument and return TRUE.
+ * If "noparen" is TRUE do not recognize the command followed by "(".
+ */
+    static int
+checkforcmd_opt(
+    char_u	**pp,		// start of command
+    char	*cmd,		// name of command
+    int		len,		// required length
+    int		noparen)
+{
+    int		i;
+
+    for (i = 0; cmd[i] != NUL; ++i)
+	if (((char_u *)cmd)[i] != (*pp)[i])
+	    break;
+    if (i >= len && !isalpha((*pp)[i])
+			   && (*pp)[i] != '_' && (!noparen || (*pp)[i] != '('))
+    {
+	*pp = skipwhite(*pp + i);
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * Check for an Ex command with optional tail.
+ * If there is a match advance "pp" to the argument and return TRUE.
+ */
+    int
+checkforcmd(
+    char_u	**pp,		// start of command
+    char	*cmd,		// name of command
+    int		len)		// required length
+{
+    return checkforcmd_opt(pp, cmd, len, FALSE);
+}
+
+/*
+ * Check for an Ex command with optional tail, not followed by "(".
+ * If there is a match advance "pp" to the argument and return TRUE.
+ */
+    static int
+checkforcmd_noparen(
+    char_u	**pp,		// start of command
+    char	*cmd,		// name of command
+    int		len)		// required length
+{
+    return checkforcmd_opt(pp, cmd, len, TRUE);
+}
+
+/*
  * Parse and skip over command modifiers:
  * - update eap->cmd
  * - store flags in "cmod".
@@ -2770,51 +2822,51 @@ parse_command_modifiers(
 	switch (*p)
 	{
 	    // When adding an entry, also modify cmd_exists().
-	    case 'a':	if (!checkforcmd(&eap->cmd, "aboveleft", 3))
+	    case 'a':	if (!checkforcmd_noparen(&eap->cmd, "aboveleft", 3))
 			    break;
 			cmod->cmod_split |= WSP_ABOVE;
 			continue;
 
-	    case 'b':	if (checkforcmd(&eap->cmd, "belowright", 3))
+	    case 'b':	if (checkforcmd_noparen(&eap->cmd, "belowright", 3))
 			{
 			    cmod->cmod_split |= WSP_BELOW;
 			    continue;
 			}
-			if (checkforcmd(&eap->cmd, "browse", 3))
+			if (checkforcmd_opt(&eap->cmd, "browse", 3, TRUE))
 			{
 #ifdef FEAT_BROWSE_CMD
 			    cmod->cmod_flags |= CMOD_BROWSE;
 #endif
 			    continue;
 			}
-			if (!checkforcmd(&eap->cmd, "botright", 2))
+			if (!checkforcmd_noparen(&eap->cmd, "botright", 2))
 			    break;
 			cmod->cmod_split |= WSP_BOT;
 			continue;
 
-	    case 'c':	if (!checkforcmd(&eap->cmd, "confirm", 4))
+	    case 'c':	if (!checkforcmd_opt(&eap->cmd, "confirm", 4, TRUE))
 			    break;
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
 			cmod->cmod_flags |= CMOD_CONFIRM;
 #endif
 			continue;
 
-	    case 'k':	if (checkforcmd(&eap->cmd, "keepmarks", 3))
+	    case 'k':	if (checkforcmd_noparen(&eap->cmd, "keepmarks", 3))
 			{
 			    cmod->cmod_flags |= CMOD_KEEPMARKS;
 			    continue;
 			}
-			if (checkforcmd(&eap->cmd, "keepalt", 5))
+			if (checkforcmd_noparen(&eap->cmd, "keepalt", 5))
 			{
 			    cmod->cmod_flags |= CMOD_KEEPALT;
 			    continue;
 			}
-			if (checkforcmd(&eap->cmd, "keeppatterns", 5))
+			if (checkforcmd_noparen(&eap->cmd, "keeppatterns", 5))
 			{
 			    cmod->cmod_flags |= CMOD_KEEPPATTERNS;
 			    continue;
 			}
-			if (!checkforcmd(&eap->cmd, "keepjumps", 5))
+			if (!checkforcmd_noparen(&eap->cmd, "keepjumps", 5))
 			    break;
 			cmod->cmod_flags |= CMOD_KEEPJUMPS;
 			continue;
@@ -2823,7 +2875,7 @@ parse_command_modifiers(
 			{
 			    char_u *reg_pat;
 
-			    if (!checkforcmd(&p, "filter", 4)
+			    if (!checkforcmd_noparen(&p, "filter", 4)
 						|| *p == NUL || ends_excmd(*p))
 				break;
 			    if (*p == '!')
@@ -2857,45 +2909,45 @@ parse_command_modifiers(
 			}
 
 			// ":hide" and ":hide | cmd" are not modifiers
-	    case 'h':	if (p != eap->cmd || !checkforcmd(&p, "hide", 3)
+	    case 'h':	if (p != eap->cmd || !checkforcmd_noparen(&p, "hide", 3)
 					       || *p == NUL || ends_excmd(*p))
 			    break;
 			eap->cmd = p;
 			cmod->cmod_flags |= CMOD_HIDE;
 			continue;
 
-	    case 'l':	if (checkforcmd(&eap->cmd, "lockmarks", 3))
+	    case 'l':	if (checkforcmd_noparen(&eap->cmd, "lockmarks", 3))
 			{
 			    cmod->cmod_flags |= CMOD_LOCKMARKS;
 			    continue;
 			}
 
-			if (!checkforcmd(&eap->cmd, "leftabove", 5))
+			if (!checkforcmd_noparen(&eap->cmd, "leftabove", 5))
 			    break;
 			cmod->cmod_split |= WSP_ABOVE;
 			continue;
 
-	    case 'n':	if (checkforcmd(&eap->cmd, "noautocmd", 3))
+	    case 'n':	if (checkforcmd_noparen(&eap->cmd, "noautocmd", 3))
 			{
 			    cmod->cmod_flags |= CMOD_NOAUTOCMD;
 			    continue;
 			}
-			if (!checkforcmd(&eap->cmd, "noswapfile", 3))
+			if (!checkforcmd_noparen(&eap->cmd, "noswapfile", 3))
 			    break;
 			cmod->cmod_flags |= CMOD_NOSWAPFILE;
 			continue;
 
-	    case 'r':	if (!checkforcmd(&eap->cmd, "rightbelow", 6))
+	    case 'r':	if (!checkforcmd_noparen(&eap->cmd, "rightbelow", 6))
 			    break;
 			cmod->cmod_split |= WSP_BELOW;
 			continue;
 
-	    case 's':	if (checkforcmd(&eap->cmd, "sandbox", 3))
+	    case 's':	if (checkforcmd_noparen(&eap->cmd, "sandbox", 3))
 			{
 			    cmod->cmod_flags |= CMOD_SANDBOX;
 			    continue;
 			}
-			if (!checkforcmd(&eap->cmd, "silent", 3))
+			if (!checkforcmd_noparen(&eap->cmd, "silent", 3))
 			    break;
 			cmod->cmod_flags |= CMOD_SILENT;
 			if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
@@ -2906,7 +2958,7 @@ parse_command_modifiers(
 			}
 			continue;
 
-	    case 't':	if (checkforcmd(&p, "tab", 3))
+	    case 't':	if (checkforcmd_noparen(&p, "tab", 3))
 			{
 			    if (!skip_only)
 			    {
@@ -2928,22 +2980,22 @@ parse_command_modifiers(
 			    eap->cmd = p;
 			    continue;
 			}
-			if (!checkforcmd(&eap->cmd, "topleft", 2))
+			if (!checkforcmd_noparen(&eap->cmd, "topleft", 2))
 			    break;
 			cmod->cmod_split |= WSP_TOP;
 			continue;
 
-	    case 'u':	if (!checkforcmd(&eap->cmd, "unsilent", 3))
+	    case 'u':	if (!checkforcmd_noparen(&eap->cmd, "unsilent", 3))
 			    break;
 			cmod->cmod_flags |= CMOD_UNSILENT;
 			continue;
 
-	    case 'v':	if (checkforcmd(&eap->cmd, "vertical", 4))
+	    case 'v':	if (checkforcmd_noparen(&eap->cmd, "vertical", 4))
 			{
 			    cmod->cmod_split |= WSP_VERT;
 			    continue;
 			}
-			if (checkforcmd(&eap->cmd, "vim9cmd", 4))
+			if (checkforcmd_noparen(&eap->cmd, "vim9cmd", 4))
 			{
 			    if (ends_excmd2(p, eap->cmd))
 			    {
@@ -2954,7 +3006,7 @@ parse_command_modifiers(
 			    cmod->cmod_flags |= CMOD_VIM9CMD;
 			    continue;
 			}
-			if (!checkforcmd(&p, "verbose", 4))
+			if (!checkforcmd_noparen(&p, "verbose", 4))
 			    break;
 			if (vim_isdigit(*eap->cmd))
 			    cmod->cmod_verbose = atoi((char *)eap->cmd);
@@ -3252,29 +3304,6 @@ parse_cmd_address(exarg_T *eap, char **e
 }
 
 /*
- * Check for an Ex command with optional tail.
- * If there is a match advance "pp" to the argument and return TRUE.
- */
-    int
-checkforcmd(
-    char_u	**pp,		// start of command
-    char	*cmd,		// name of command
-    int		len)		// required length
-{
-    int		i;
-
-    for (i = 0; cmd[i] != NUL; ++i)
-	if (((char_u *)cmd)[i] != (*pp)[i])
-	    break;
-    if (i >= len && !isalpha((*pp)[i]) && (*pp)[i] != '_')
-    {
-	*pp = skipwhite(*pp + i);
-	return TRUE;
-    }
-    return FALSE;
-}
-
-/*
  * Append "cmd" to the error message in IObuff.
  * Takes care of limiting the length and handling 0xa0, which would be
  * invisible otherwise.
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -142,15 +142,15 @@ def Test_browse()
   CheckFeature browse
 
   var lines =<< trim END
-      call browse(1, 2, 3, 4)
+      browse(1, 2, 3, 4)
   END
   CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 2')
   lines =<< trim END
-      call browse(1, 'title', 3, 4)
+      browse(1, 'title', 3, 4)
   END
   CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 3')
   lines =<< trim END
-      call browse(1, 'title', 'dir', 4)
+      browse(1, 'title', 'dir', 4)
   END
   CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 4')
 enddef
@@ -236,9 +236,9 @@ def Test_confirm()
     CheckFeature dialog_con
   endif
 
-  assert_fails('call confirm(true)', 'E1174')
-  assert_fails('call confirm("yes", true)', 'E1174')
-  assert_fails('call confirm("yes", "maybe", 2, true)', 'E1174')
+  assert_fails('confirm(true)', 'E1174')
+  assert_fails('confirm("yes", true)', 'E1174')
+  assert_fails('confirm("yes", "maybe", 2, true)', 'E1174')
 enddef
 
 def Test_copy_return_type()
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2668,
+/**/
     2667,
 /**/
     2666,