]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.2264: Vim9: no error for mismatched :endfunc or :enddef v8.2.2264
authorBram Moolenaar <Bram@vim.org>
Fri, 1 Jan 2021 17:43:51 +0000 (18:43 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 1 Jan 2021 17:43:51 +0000 (18:43 +0100)
Problem:    Vim9: no error for mismatched :endfunc or :enddef.
Solution:   Check for the mismatch. (issue #7582)

src/errors.h
src/testdir/test_vim9_func.vim
src/userfunc.c
src/version.c

index 4b4245a1bdb62ca7219c2066227756374c71b15d..6f4ac0e1a7c8c9cbaf8dc016dd1576bcf29dd304 100644 (file)
@@ -335,3 +335,7 @@ EXTERN char e_script_variable_invalid_after_reload_in_function_str[]
        INIT(= N_("E1149: Script variable is invalid after reload in function %s"));
 EXTERN char e_script_variable_type_changed[]
        INIT(= N_("E1150: Script variable type changed"));
+EXTERN char e_mismatched_endfunction[]
+       INIT(= N_("E1151: Mismatched endfunction"));
+EXTERN char e_mismatched_enddef[]
+       INIT(= N_("E1152: Mismatched enddef"));
index a2d1ed3e2915fd9fddd6d32f99f81c9ee2d8c925..223b2fbda7703a1d50345847c1632218df413184 100644 (file)
@@ -79,6 +79,25 @@ def Test_funcdepth_error()
   set maxfuncdepth&
 enddef
 
+def Test_endfunc_enddef()
+  var lines =<< trim END
+    def Test()
+      echo 'test'
+      endfunc
+    enddef
+  END
+  CheckScriptFailure(lines, 'E1151:', 3)
+
+  lines =<< trim END
+    def Test()
+      func Nested()
+        echo 'test'
+      enddef
+    enddef
+  END
+  CheckScriptFailure(lines, 'E1152:', 4)
+enddef
+
 def ReturnString(): string
   return 'string'
 enddef
index bc3dd0e9ae383d735465119db5026ddfc9662ad4..f0877e1c3bd468cbc50f01e1f3dbc9cc059b2094 100644 (file)
@@ -3404,35 +3404,51 @@ define_function(exarg_T *eap, char_u *name_arg)
 
            // Check for "endfunction" or "enddef".
            if (checkforcmd(&p, nesting_def[nesting]
-                            ? "enddef" : "endfunction", 4) && nesting-- == 0)
+                                               ? "enddef" : "endfunction", 4))
            {
-               char_u *nextcmd = NULL;
-
-               if (*p == '|')
-                   nextcmd = p + 1;
-               else if (line_arg != NULL && *skipwhite(line_arg) != NUL)
-                   nextcmd = line_arg;
-               else if (*p != NUL && *p != '"' && p_verbose > 0)
-                   give_warning2(eap->cmdidx == CMD_def
-                       ? (char_u *)_("W1001: Text found after :enddef: %s")
-                       : (char_u *)_("W22: Text found after :endfunction: %s"),
-                        p, TRUE);
-               if (nextcmd != NULL)
+               if (nesting-- == 0)
                {
-                   // Another command follows. If the line came from "eap" we
-                   // can simply point into it, otherwise we need to change
-                   // "eap->cmdlinep".
-                   eap->nextcmd = nextcmd;
-                   if (line_to_free != NULL)
+                   char_u *nextcmd = NULL;
+
+                   if (*p == '|')
+                       nextcmd = p + 1;
+                   else if (line_arg != NULL && *skipwhite(line_arg) != NUL)
+                       nextcmd = line_arg;
+                   else if (*p != NUL && *p != '"' && p_verbose > 0)
+                       give_warning2(eap->cmdidx == CMD_def
+                           ? (char_u *)_("W1001: Text found after :enddef: %s")
+                           : (char_u *)_("W22: Text found after :endfunction: %s"),
+                            p, TRUE);
+                   if (nextcmd != NULL)
                    {
-                       vim_free(*eap->cmdlinep);
-                       *eap->cmdlinep = line_to_free;
-                       line_to_free = NULL;
+                       // Another command follows. If the line came from "eap"
+                       // we can simply point into it, otherwise we need to
+                       // change "eap->cmdlinep".
+                       eap->nextcmd = nextcmd;
+                       if (line_to_free != NULL)
+                       {
+                           vim_free(*eap->cmdlinep);
+                           *eap->cmdlinep = line_to_free;
+                           line_to_free = NULL;
+                       }
                    }
+                   break;
                }
-               break;
            }
 
+           // Check for mismatched "endfunc" or "enddef".
+           // We don't check for "def" inside "func" thus we also can't check
+           // for "enddef".
+           // We continue to find the end of the function, although we might
+           // not find it.
+           else if (nesting_def[nesting])
+           {
+               if (checkforcmd(&p, "endfunction", 4))
+                   emsg(_(e_mismatched_endfunction));
+           }
+           else if (eap->cmdidx == CMD_def && checkforcmd(&p, "enddef", 4))
+               emsg(_(e_mismatched_enddef));
+
            // Increase indent inside "if", "while", "for" and "try", decrease
            // at "end".
            if (indent > 2 && (*p == '}' || STRNCMP(p, "end", 3) == 0))
index 26c9d8bf8dbcc197277b31f7f8d1552666b9fe0d..3fc3c01e1d23e28920534b6d34397c2a19fe9beb 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2264,
 /**/
     2263,
 /**/