summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2024-04-04 21:42:07 +0200
committerChristian Brabandt <cb@256bit.org>2024-04-04 21:42:07 +0200
commit3fa8f7728a47822e4efd106ab30c83c28f198b3c (patch)
treef5f4721859b71c1ccc6709fcbb3e896e6b77f6ca
parent4a65391ca273f2eca84f5ec7bd846693232dfacc (diff)
patch 9.1.0263: Vim9: Problem with lambda blocks in enums and classesv9.1.0263
Problem: Vim9: Problem with lambda blocks in enums and classes (Aliaksei Budavei) Solution: Support evaluating lambda blocks from a string, skip over comments (Yegappan Lakshmanan) fixes: #14350 closes: #14405 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/eval.c3
-rw-r--r--src/testdir/test_vim9_class.vim30
-rw-r--r--src/testdir/test_vim9_enum.vim31
-rw-r--r--src/testdir/test_vim9_import.vim26
-rw-r--r--src/testdir/test_vim9_script.vim10
-rw-r--r--src/userfunc.c16
-rw-r--r--src/version.c2
7 files changed, 115 insertions, 3 deletions
diff --git a/src/eval.c b/src/eval.c
index a4fde0ef29..187b4d4d87 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -549,6 +549,7 @@ skip_expr_concatenate(
((char_u **)gap->ga_data)[gap->ga_len - 1];
((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL;
ga_clear_strings(gap);
+ ga_clear(freegap);
}
else
{
@@ -1203,7 +1204,7 @@ get_lval_imported(
dictitem_T *di = find_var_in_ht(ht, 0, lp->ll_name, TRUE);
if (di == NULL)
- // variable is not found
+ // script is autoloaded. So variable will be found later
goto success;
*dip = di;
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 6eafe00373..77a2102c2d 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -10553,4 +10553,34 @@ def Test_protected_funcref()
v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
enddef
+" Test for using lambda block in classes
+def Test_lambda_block_in_class()
+ # This used to crash Vim
+ var lines =<< trim END
+ vim9script
+ class IdClass1
+ const Id: func(number): number = (num: number): number => {
+ # Return a ID
+ return num * 10
+ }
+ endclass
+ var id = IdClass1.new()
+ assert_equal(20, id.Id(2))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # This used to crash Vim
+ lines =<< trim END
+ vim9script
+ class IdClass2
+ static const Id: func(number): number = (num: number): number => {
+ # Return a ID
+ return num * 2
+ }
+ endclass
+ assert_equal(16, IdClass2.Id(8))
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_enum.vim b/src/testdir/test_vim9_enum.vim
index 5f9fbff6d3..274b556b77 100644
--- a/src/testdir/test_vim9_enum.vim
+++ b/src/testdir/test_vim9_enum.vim
@@ -1503,4 +1503,35 @@ def Test_use_enum_values_in_class_variable()
v9.CheckSourceSuccess(lines)
enddef
+" Test for using lambda block in enums
+def Test_lambda_block_in_enum()
+ # This used to crash Vim
+ var lines =<< trim END
+ vim9script
+ enum IdEnum1
+ ID1
+ const Id: func(number): number = (num: number): number => {
+ # Return a ID
+ return num / 2
+ }
+ endenum
+ assert_equal(5, IdEnum1.ID1.Id(10))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # This used to crash Vim
+ lines =<< trim END
+ vim9script
+ enum IdEnum2
+ ID1
+ static const Id: func(number): number = (num: number): number => {
+ # Return a ID
+ return num + 2
+ }
+ endenum
+ assert_equal(12, IdEnum2.Id(10))
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index 8d68f1e47e..67b67595f5 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -2993,4 +2993,30 @@ def Test_import_autloaded_script()
&rtp = save_rtp
enddef
+" Test for autoloading an imported dict func
+def Test_autoload_import_dict_func()
+ mkdir('Xdir/autoload', 'pR')
+ var lines =<< trim END
+ vim9script
+ export var al_exported_nr: number = 33
+ def Al_AddNum(n: number)
+ al_exported_nr += n
+ enddef
+ export var al_exportedDict: dict<func> = {Fn: Al_AddNum}
+ END
+ writefile(lines, 'Xdir/autoload/Xdictfunc.vim')
+
+ var save_rtp = &rtp
+ exe 'set rtp^=' .. getcwd() .. '/Xdir'
+ lines =<< trim END
+ import './Xdir/autoload/Xdictfunc.vim'
+ call Xdictfunc#al_exportedDict.Fn(5)
+ call assert_equal(38, Xdictfunc#al_exported_nr)
+ call call(Xdictfunc#al_exportedDict.Fn, [3])
+ call assert_equal(41, Xdictfunc#al_exported_nr)
+ END
+ v9.CheckScriptSuccess(lines)
+ &rtp = save_rtp
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 0e21334927..cd693e5993 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -4931,6 +4931,16 @@ def Test_for_empty_line_after_lambda()
v9.CheckSourceSuccess(lines)
enddef
+" Test for evaluating a lambda block from a string
+def Test_eval_lambda_block()
+ var lines =<< trim END
+ vim9script
+ var Fn = eval("(x: number): number => {\nreturn x * 2\n}")
+ assert_equal(6, Fn(3))
+ END
+ v9.CheckSourceSuccess(lines)
+enddef
+
" Keep this last, it messes up highlighting.
def Test_substitute_cmd()
new
diff --git a/src/userfunc.c b/src/userfunc.c
index 9a307966b7..b023c3a966 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1335,6 +1335,7 @@ lambda_function_body(
char_u *name;
int lnum_save = -1;
linenr_T sourcing_lnum_top = SOURCING_LNUM;
+ char_u *line_arg = NULL;
*arg = skipwhite(*arg + 1);
if (**arg == '|' || !ends_excmd2(start, *arg))
@@ -1343,6 +1344,12 @@ lambda_function_body(
return FAIL;
}
+ // When there is a line break use what follows for the lambda body.
+ // Makes lambda body initializers work for object and enum member
+ // variables.
+ if (**arg == '\n')
+ line_arg = *arg + 1;
+
CLEAR_FIELD(eap);
eap.cmdidx = CMD_block;
eap.forceit = FALSE;
@@ -1357,7 +1364,7 @@ lambda_function_body(
}
ga_init2(&newlines, sizeof(char_u *), 10);
- if (get_function_body(&eap, &newlines, NULL,
+ if (get_function_body(&eap, &newlines, line_arg,
&evalarg->eval_tofree_ga) == FAIL)
goto erret;
@@ -1372,7 +1379,12 @@ lambda_function_body(
for (idx = 0; idx < newlines.ga_len; ++idx)
{
- char_u *p = skipwhite(((char_u **)newlines.ga_data)[idx]);
+ char_u *p = ((char_u **)newlines.ga_data)[idx];
+ if (p == NULL)
+ // comment line in the lambda body
+ continue;
+
+ p = skipwhite(p);
if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
goto erret;
diff --git a/src/version.c b/src/version.c
index d31484a4e9..1a82d9b3ab 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 263,
+/**/
262,
/**/
261,