diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2024-04-04 21:42:07 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-04-04 21:42:07 +0200 |
commit | 3fa8f7728a47822e4efd106ab30c83c28f198b3c (patch) | |
tree | f5f4721859b71c1ccc6709fcbb3e896e6b77f6ca | |
parent | 4a65391ca273f2eca84f5ec7bd846693232dfacc (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.c | 3 | ||||
-rw-r--r-- | src/testdir/test_vim9_class.vim | 30 | ||||
-rw-r--r-- | src/testdir/test_vim9_enum.vim | 31 | ||||
-rw-r--r-- | src/testdir/test_vim9_import.vim | 26 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 10 | ||||
-rw-r--r-- | src/userfunc.c | 16 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |