Skip to content

Commit

Permalink
patch 9.1.0263: Vim9: Problem with lambda blocks in enums and classes
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
  • Loading branch information
yegappan authored and chrisbra committed Apr 4, 2024
1 parent 4a65391 commit 3fa8f77
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand Down
30 changes: 30 additions & 0 deletions src/testdir/test_vim9_class.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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
31 changes: 31 additions & 0 deletions src/testdir/test_vim9_enum.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 26 additions & 0 deletions src/testdir/test_vim9_import.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions src/testdir/test_vim9_script.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions src/userfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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;
Expand All @@ -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;

Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
263,
/**/
262,
/**/
Expand Down

0 comments on commit 3fa8f77

Please sign in to comment.