]> granicus.if.org Git - vim/commitdiff
patch 8.2.4989: cannot specify a function name for :defcompile v8.2.4989
authorBram Moolenaar <Bram@vim.org>
Sat, 21 May 2022 14:39:02 +0000 (15:39 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 21 May 2022 14:39:02 +0000 (15:39 +0100)
Problem:    Cannot specify a function name for :defcompile.
Solution:   Implement a function name argument for :defcompile.

runtime/doc/vim9.txt
src/ex_cmds.h
src/proto/userfunc.pro
src/testdir/test_vim9_cmd.vim
src/testdir/test_vim9_disassemble.vim
src/userfunc.c
src/version.c
src/vim9execute.c

index 5a0e5bf88029ca5f448b5c35d1bed14a7490b472..479edc57c5c1467c11f8ccc9f5b2bbf6a1e2ce28 100644 (file)
@@ -1210,7 +1210,14 @@ prefix if they do not exist at the time of compiling.
                                                *: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}.
index e4f9bb05db5daae5021247bfffb301dd1d7f30da..b8cf41d44cac49cb9cb5ce10487c8599042737a8 100644 (file)
@@ -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,
index 7bedac07bf45c75672b3365ba3693655bbbdff01..537276013a57e8e2e9dfe44d1c3b4f3478699e52 100644 (file)
@@ -45,6 +45,7 @@ char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, f
 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);
index 77e1d8a0696483f691bf18d769626da88497b82f..7db8e50c8e6b22a36d1e1ecafb32ef27099ea3ad 100644 (file)
@@ -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
index c99c8b4fa4b7c5a52bf0fc7ecfcfcb51d8fb7985..78604950b94322ddde065c87ebcc6e1036587300 100644 (file)
@@ -43,6 +43,9 @@ def Test_disassemble_load()
   assert_fails('disass [', 'E475:')
   assert_fails('disass 234', 'E129:')
   assert_fails('disass <XX>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('<SNR>\d*_ScriptFuncLoad.*' ..
index 42e285fca1765e3dc5ae72cbf5a7d1be8a7b8407..6eabd8b77fa01088ce9c433b8a579360a7895d24 100644 (file)
@@ -4996,37 +4996,116 @@ ex_function(exarg_T *eap)
     ga_clear_strings(&lines_to_free);
 }
 
+/*
+ * Find a function by name, including "<lambda>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, "<lambda>", 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 (*eap->arg != NUL)
     {
-       if (!HASHITEM_EMPTY(hi))
+       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)
-           {
-               (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
+           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;
 
-               if (func_hashtab.ht_changed != changed)
+       for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
+       {
+           if (!HASHITEM_EMPTY(hi))
+           {
+               --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;
+                   }
                }
            }
        }
index ec25334d3f0fe875fb22e573d257bab9a83ee739..c6e6a391f38a2c650921973d007a7f447f16357a 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4989,
 /**/
     4988,
 /**/
index a64ae5cbbd8ce6de5011e7c99dc5826521960923..d89f442367a484cfbdd2c9c9e8184a324d93b807 100644 (file)
@@ -6277,55 +6277,15 @@ get_disassemble_argument(expand_T *xp, int idx)
 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, "<lambda>", 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);
-       return;
-    }
-
-    ufunc = find_func(fname, is_global);
-    if (ufunc == NULL)
-    {
-       char_u *p = untrans_function_name(fname);
+    compiletype_T compile_type;
 
-       if (p != NULL)
-           // Try again without making it script-local.
-           ufunc = find_func(p, FALSE);
-    }
-    vim_free(fname);
+    ufunc = find_func_by_name(arg, &compile_type);
     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;