# HG changeset patch # User Bram Moolenaar # Date 1653144303 -7200 # Node ID a712ea47539039c78859fb8c9cd88793a69af22e # Parent 57c9377b9c62338359a9347778f7b060a3398829 patch 8.2.4989: cannot specify a function name for :defcompile Commit: https://github.com/vim/vim/commit/f79d9dd43f6fe05711d7e2616ab4b8bde2ccb089 Author: Bram Moolenaar Date: Sat May 21 15:39:02 2022 +0100 patch 8.2.4989: cannot specify a function name for :defcompile Problem: Cannot specify a function name for :defcompile. Solution: Implement a function name argument for :defcompile. diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1210,7 +1210,14 @@ prefix if they do not exist at the time *:defc* *:defcompile* :defc[ompile] Compile functions defined in the current script that were not compiled yet. - This will report errors found during the compilation. + This will report any errors found during compilation. + +:defc[ompile] {func} +:defc[ompile] debug {func} +:defc[ompile] profile {func} + Compile function {func}, if needed. Use "debug" and + "profile" to specify the compilation mode. + This will report any errors found during compilation. *:disa* *:disassemble* :disa[ssemble] {func} Show the instructions generated for {func}. diff --git a/src/ex_cmds.h b/src/ex_cmds.h --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -465,7 +465,7 @@ EXCMD(CMD_def, "def", ex_function, EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_defcompile, "defcompile", ex_defcompile, - EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR, + EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA, ADDR_NONE), EXCMD(CMD_delcommand, "delcommand", ex_delcommand, EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -45,6 +45,7 @@ char_u *save_function_name(char_u **name void list_functions(regmatch_T *regmatch); ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free); void ex_function(exarg_T *eap); +ufunc_T *find_func_by_name(char_u *name, compiletype_T *compile_type); void ex_defcompile(exarg_T *eap); int eval_fname_script(char_u *p); int translated_function_exists(char_u *name, int is_global); diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -83,6 +83,16 @@ def Test_vim9cmd() v9.CheckScriptSuccess(lines) enddef +def Test_defcompile_fails() + assert_fails('defcompile NotExists', 'E1061:') + assert_fails('defcompile debug debug Test_defcompile_fails', 'E488:') + assert_fails('defcompile profile profile Test_defcompile_fails', 'E488:') +enddef + +defcompile Test_defcompile_fails +defcompile debug Test_defcompile_fails +defcompile profile Test_defcompile_fails + def Test_cmdmod_execute() # "legacy" applies not only to the "exe" argument but also to the commands var lines =<< trim END diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -43,6 +43,9 @@ def Test_disassemble_load() assert_fails('disass [', 'E475:') assert_fails('disass 234', 'E129:') assert_fails('disass foo', 'E129:') + assert_fails('disass Test_disassemble_load burp', 'E488:') + assert_fails('disass debug debug Test_disassemble_load', 'E488:') + assert_fails('disass profile profile Test_disassemble_load', 'E488:') var res = execute('disass s:ScriptFuncLoad') assert_match('\d*_ScriptFuncLoad.*' .. diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -4997,36 +4997,115 @@ ex_function(exarg_T *eap) } /* + * Find a function by name, including "123". + * Check for "profile" and "debug" arguments and set"compile_type". + * Return NULL if not found. + */ + ufunc_T * +find_func_by_name(char_u *name, compiletype_T *compile_type) +{ + char_u *arg = name; + char_u *fname; + ufunc_T *ufunc; + int is_global = FALSE; + + *compile_type = CT_NONE; + if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7])) + { + *compile_type = CT_PROFILE; + arg = skipwhite(arg + 7); + } + else if (STRNCMP(arg, "debug", 5) == 0 && VIM_ISWHITE(arg[5])) + { + *compile_type = CT_DEBUG; + arg = skipwhite(arg + 5); + } + + if (STRNCMP(arg, "", 8) == 0) + { + arg += 8; + (void)getdigits(&arg); + fname = vim_strnsave(name, arg - name); + } + else + fname = trans_function_name(&arg, &is_global, FALSE, + TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL); + if (fname == NULL) + { + semsg(_(e_invalid_argument_str), name); + return NULL; + } + if (!ends_excmd2(name, arg)) + { + emsg(ex_errmsg(e_trailing_characters_str, arg)); + return NULL; + } + + ufunc = find_func(fname, is_global); + if (ufunc == NULL) + { + char_u *p = untrans_function_name(fname); + + if (p != NULL) + // Try again without making it script-local. + ufunc = find_func(p, FALSE); + } + vim_free(fname); + if (ufunc == NULL) + semsg(_(e_cannot_find_function_str), name); + return ufunc; +} + +/* * :defcompile - compile all :def functions in the current script that need to - * be compiled. Except dead functions. Doesn't do profiling. + * be compiled or the one specified by the argument. + * Skips dead functions. Doesn't do profiling. */ void -ex_defcompile(exarg_T *eap UNUSED) +ex_defcompile(exarg_T *eap) { - long todo = (long)func_hashtab.ht_used; - int changed = func_hashtab.ht_changed; - hashitem_T *hi; ufunc_T *ufunc; - for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) - { - if (!HASHITEM_EMPTY(hi)) + if (*eap->arg != NUL) + { + compiletype_T compile_type; + + ufunc = find_func_by_name(eap->arg, &compile_type); + if (ufunc != NULL) { - --todo; - ufunc = HI2UF(hi); - if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid - && ufunc->uf_def_status == UF_TO_BE_COMPILED - && (ufunc->uf_flags & FC_DEAD) == 0) + if (func_needs_compiling(ufunc, compile_type)) + (void)compile_def_function(ufunc, FALSE, compile_type, NULL); + else + smsg(_("Function %s does not need compiling"), eap->arg); + } + } + else + { + long todo = (long)func_hashtab.ht_used; + int changed = func_hashtab.ht_changed; + hashitem_T *hi; + + for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) + { + if (!HASHITEM_EMPTY(hi)) { - (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL); - - if (func_hashtab.ht_changed != changed) + --todo; + ufunc = HI2UF(hi); + if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid + && ufunc->uf_def_status == UF_TO_BE_COMPILED + && (ufunc->uf_flags & FC_DEAD) == 0) { - // a function has been added or removed, need to start over - todo = (long)func_hashtab.ht_used; - changed = func_hashtab.ht_changed; - hi = func_hashtab.ht_array; - --hi; + (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL); + + if (func_hashtab.ht_changed != changed) + { + // a function has been added or removed, need to start + // over + todo = (long)func_hashtab.ht_used; + changed = func_hashtab.ht_changed; + hi = func_hashtab.ht_array; + --hi; + } } } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4989, +/**/ 4988, /**/ 4987, diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -6277,55 +6277,15 @@ get_disassemble_argument(expand_T *xp, i ex_disassemble(exarg_T *eap) { char_u *arg = eap->arg; - char_u *fname; ufunc_T *ufunc; dfunc_T *dfunc; isn_T *instr; int instr_count; - int is_global = FALSE; - compiletype_T compile_type = CT_NONE; - - if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7])) - { - compile_type = CT_PROFILE; - arg = skipwhite(arg + 7); - } - else if (STRNCMP(arg, "debug", 5) == 0 && VIM_ISWHITE(arg[5])) - { - compile_type = CT_DEBUG; - arg = skipwhite(arg + 5); - } - - if (STRNCMP(arg, "", 8) == 0) - { - arg += 8; - (void)getdigits(&arg); - fname = vim_strnsave(eap->arg, arg - eap->arg); - } - else - fname = trans_function_name(&arg, &is_global, FALSE, - TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL); - if (fname == NULL) - { - semsg(_(e_invalid_argument_str), eap->arg); + compiletype_T compile_type; + + ufunc = find_func_by_name(arg, &compile_type); + if (ufunc == NULL) return; - } - - ufunc = find_func(fname, is_global); - if (ufunc == NULL) - { - char_u *p = untrans_function_name(fname); - - if (p != NULL) - // Try again without making it script-local. - ufunc = find_func(p, FALSE); - } - vim_free(fname); - if (ufunc == NULL) - { - semsg(_(e_cannot_find_function_str), eap->arg); - return; - } if (func_needs_compiling(ufunc, compile_type) && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL) return;