# HG changeset patch # User Bram Moolenaar # Date 1640714405 -3600 # Node ID 30d8377ea1b199e66239b97ce373b2ac0bda986e # Parent 43989ce10dd1bc2f53f3073b30ef94f2fcee3ae8 patch 8.2.3924: Vim9: no error if something follows :enddef Commit: https://github.com/vim/vim/commit/7473a84cf935f64ddd4ea7fe7eee0f9c51c50b60 Author: Bram Moolenaar Date: Tue Dec 28 17:55:26 2021 +0000 patch 8.2.3924: Vim9: no error if something follows :enddef Problem: Vim9: no error if something follows :enddef in a nested function. Solution: Give an error. Move common code to a function. diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -717,8 +717,8 @@ EXTERN char e_missing_end_block[] INIT(= N_("E1171: Missing } after inline function")); EXTERN char e_cannot_use_default_values_in_lambda[] INIT(= N_("E1172: Cannot use default values in a lambda")); -EXTERN char e_text_found_after_enddef_str[] - INIT(= N_("E1173: Text found after enddef: %s")); +EXTERN char e_text_found_after_str_str[] + INIT(= N_("E1173: Text found after %s: %s")); EXTERN char e_string_required_for_argument_nr[] INIT(= N_("E1174: String required for argument %d")); EXTERN char e_non_empty_string_required_for_argument_nr[] diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1686,7 +1686,7 @@ def Test_nested_function_with_nextcmd() # Compile all functions defcompile END - CheckScriptFailure(lines, 'E476: Invalid command: AAAAA') + CheckScriptFailure(lines, 'E1173: Text found after enddef: BBBB') enddef def Test_nested_function_with_args_split() @@ -1703,8 +1703,17 @@ def Test_nested_function_with_args_split # Compile all functions defcompile END - # FIXME: this should fail on the BBBB - CheckScriptSuccess(lines) + CheckScriptFailure(lines, 'E1173: Text found after enddef: BBBB') + + lines =<< trim END + vim9script + def FirstFunction() + func SecondFunction() + endfunc|BBBB + enddef + defcompile + END + CheckScriptFailure(lines, 'E1173: Text found after endfunction: BBBB') enddef def Test_return_type_wrong() diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -166,6 +166,35 @@ one_function_arg( } /* + * Handle line continuation in function arguments or body. + * Get a next line, store it in "eap" if appropriate and use "line_to_free" to + * handle freeing the line later. + */ + static char_u * +get_function_line( + exarg_T *eap, + char_u **line_to_free, + getline_opt_T getline_options, + int indent) +{ + char_u *theline; + + if (eap->getline == NULL) + theline = getcmdline(':', 0L, indent, getline_options); + else + theline = eap->getline(':', eap->cookie, indent, getline_options); + if (theline != NULL) + { + if (*eap->cmdlinep == *line_to_free) + *eap->cmdlinep = theline; + vim_free(*line_to_free); + *line_to_free = theline; + } + + return theline; +} + +/* * Get function arguments. * "argp" should point to just after the "(", possibly to white space. * "argp" is advanced just after "endchar". @@ -212,16 +241,11 @@ get_function_args( while (eap != NULL && eap->getline != NULL && (*p == NUL || (VIM_ISWHITE(*whitep) && *p == '#'))) { - char_u *theline; - // End of the line, get the next one. - theline = eap->getline(':', eap->cookie, 0, TRUE); + char_u *theline = get_function_line(eap, line_to_free, 0, TRUE); + if (theline == NULL) break; - vim_free(*line_to_free); - if (*eap->cmdlinep == *line_to_free) - *eap->cmdlinep = theline; - *line_to_free = theline; whitep = (char_u *)" "; p = skipwhite(theline); } @@ -720,15 +744,8 @@ get_function_body( } else { - if (eap->getline == NULL) - theline = getcmdline(':', 0L, indent, getline_options); - else - theline = eap->getline(':', eap->cookie, indent, + theline = get_function_line(eap, line_to_free, indent, getline_options); - if (*eap->cmdlinep == *line_to_free) - *eap->cmdlinep = theline; - vim_free(*line_to_free); - *line_to_free = theline; } if (KeyTyped) lines_left = Rows - 1; @@ -827,7 +844,7 @@ get_function_body( SOURCING_LNUM = sourcing_lnum_top + newlines->ga_len + 1; if (eap->cmdidx == CMD_def) - semsg(_(e_text_found_after_enddef_str), p); + semsg(_(e_text_found_after_str_str), "enddef", p); else give_warning2((char_u *) _("W22: Text found after :endfunction: %s"), diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3924, +/**/ 3923, /**/ 3922, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -879,12 +879,18 @@ compile_nested_function(exarg_T *eap, cc } ufunc = define_function(eap, lambda_name, line_to_free); - if (ufunc == NULL) { r = eap->skip ? OK : FAIL; goto theend; } + if (eap->nextcmd != NULL) + { + semsg(_(e_text_found_after_str_str), + eap->cmdidx == CMD_def ? "enddef" : "endfunction", eap->nextcmd); + r = FAIL; + goto theend; + } // copy over the block scope IDs before compiling if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0)