changeset 25265:1d6ff96306fc v8.2.3169

patch 8.2.3169: Vim9: cannot handle nested inline function Commit: https://github.com/vim/vim/commit/5245beb37cb52991a745644c20d7ca1b0138ef2c Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jul 15 22:03:50 2021 +0200 patch 8.2.3169: Vim9: cannot handle nested inline function Problem: Vim9: cannot handle nested inline function. Solution: Check for nested inline function. (closes https://github.com/vim/vim/issues/8575)
author Bram Moolenaar <Bram@vim.org>
date Thu, 15 Jul 2021 22:15:03 +0200
parents 19bc0f4c9379
children 535c3b8a9d34
files src/testdir/test_vim9_expr.vim src/testdir/test_vim9_func.vim src/userfunc.c src/version.c
diffstat 4 files changed, 47 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -2082,7 +2082,8 @@ def Test_expr7_lambda_block()
       var Func = (nr: number): int => {
               return nr
   END
-  CheckDefAndScriptFailure(lines, 'E1171', 1)  # line nr is function start
+  CheckDefFailure(lines, 'E1171', 0)  # line nr is function start
+  CheckScriptFailure(['vim9script'] + lines, 'E1171', 2)
 
   lines =<< trim END
       var Func = (nr: number): int => {
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -2255,6 +2255,16 @@ def Test_nested_inline_lambda()
       assert_equal('--there', F('unused')('there')('--'))
   END
   CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      vim9script
+      echo range(4)->mapnew((_, v) => {
+        return range(v) ->mapnew((_, s) => {
+          return string(s)
+          })
+        })
+  END
+  CheckScriptSuccess(lines)
 enddef
 
 def Shadowed(): list<number>
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -634,6 +634,7 @@ get_function_body(
 						   || eap->cmdidx == CMD_block;
 #define MAX_FUNC_NESTING 50
     char	nesting_def[MAX_FUNC_NESTING];
+    char	nesting_inline[MAX_FUNC_NESTING];
     int		nesting = 0;
     getline_opt_T getline_options;
     int		indent = 2;
@@ -658,7 +659,8 @@ get_function_body(
 	    ((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL;
     }
 
-    nesting_def[nesting] = vim9_function;
+    nesting_def[0] = vim9_function;
+    nesting_inline[0] = eap->cmdidx == CMD_block;
     getline_options = vim9_function
 				? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT;
     for (;;)
@@ -705,10 +707,10 @@ get_function_body(
 	    SOURCING_LNUM = sourcing_lnum_top;
 	    if (skip_until != NULL)
 		semsg(_(e_missing_heredoc_end_marker_str), skip_until);
+	    else if (nesting_inline[nesting])
+		emsg(_(e_missing_end_block));
 	    else if (eap->cmdidx == CMD_def)
 		emsg(_(e_missing_enddef));
-	    else if (eap->cmdidx == CMD_block)
-		emsg(_(e_missing_end_block));
 	    else
 		emsg(_("E126: Missing :endfunction"));
 	    goto theend;
@@ -765,7 +767,8 @@ get_function_body(
 	}
 	else
 	{
-	    int c;
+	    int	    c;
+	    char_u  *end;
 
 	    // skip ':' and blanks
 	    for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p)
@@ -773,7 +776,7 @@ get_function_body(
 
 	    // Check for "endfunction", "enddef" or "}".
 	    // When a ":" follows it must be a dict key; "enddef: value,"
-	    if ((nesting == 0 && eap->cmdidx == CMD_block)
+	    if (nesting_inline[nesting]
 		    ? *p == '}'
 		    : (checkforcmd(&p, nesting_def[nesting]
 						? "enddef" : "endfunction", 4)
@@ -857,6 +860,31 @@ get_function_body(
 		    {
 			++nesting;
 			nesting_def[nesting] = (c == 'd');
+			nesting_inline[nesting] = FALSE;
+			indent += 2;
+		    }
+		}
+	    }
+
+	    // Check for nested inline function.
+	    end = p + STRLEN(p) - 1;
+	    while (end > p && VIM_ISWHITE(*end))
+		--end;
+	    if (*end == '{')
+	    {
+		--end;
+		while (end > p && VIM_ISWHITE(*end))
+		    --end;
+		if (end > p - 2 && end[-1] == '=' && end[0] == '>')
+		{
+		    // found trailing "=> {", start of an inline function
+		    if (nesting == MAX_FUNC_NESTING - 1)
+			emsg(_(e_function_nesting_too_deep));
+		    else
+		    {
+			++nesting;
+			nesting_def[nesting] = TRUE;
+			nesting_inline[nesting] = TRUE;
 			indent += 2;
 		    }
 		}
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3169,
+/**/
     3168,
 /**/
     3167,