0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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.
This commit is contained in:
Bram Moolenaar
2022-05-21 15:39:02 +01:00
parent 2d8ed0203a
commit f79d9dd43f
8 changed files with 127 additions and 65 deletions

View File

@@ -1210,7 +1210,14 @@ prefix if they do not exist at the time of compiling.
*:defc* *:defcompile* *:defc* *:defcompile*
:defc[ompile] Compile functions defined in the current script that :defc[ompile] Compile functions defined in the current script that
were not compiled yet. 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* *:disassemble*
:disa[ssemble] {func} Show the instructions generated for {func}. :disa[ssemble] {func} Show the instructions generated for {func}.

View File

@@ -465,7 +465,7 @@ EXCMD(CMD_def, "def", ex_function,
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE), ADDR_NONE),
EXCMD(CMD_defcompile, "defcompile", ex_defcompile, 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), ADDR_NONE),
EXCMD(CMD_delcommand, "delcommand", ex_delcommand, EXCMD(CMD_delcommand, "delcommand", ex_delcommand,
EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,

View 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); void list_functions(regmatch_T *regmatch);
ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free); ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free);
void ex_function(exarg_T *eap); 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); void ex_defcompile(exarg_T *eap);
int eval_fname_script(char_u *p); int eval_fname_script(char_u *p);
int translated_function_exists(char_u *name, int is_global); int translated_function_exists(char_u *name, int is_global);

View File

@@ -83,6 +83,16 @@ def Test_vim9cmd()
v9.CheckScriptSuccess(lines) v9.CheckScriptSuccess(lines)
enddef 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() def Test_cmdmod_execute()
# "legacy" applies not only to the "exe" argument but also to the commands # "legacy" applies not only to the "exe" argument but also to the commands
var lines =<< trim END var lines =<< trim END

View File

@@ -43,6 +43,9 @@ def Test_disassemble_load()
assert_fails('disass [', 'E475:') assert_fails('disass [', 'E475:')
assert_fails('disass 234', 'E129:') assert_fails('disass 234', 'E129:')
assert_fails('disass <XX>foo', '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') var res = execute('disass s:ScriptFuncLoad')
assert_match('<SNR>\d*_ScriptFuncLoad.*' .. assert_match('<SNR>\d*_ScriptFuncLoad.*' ..

View File

@@ -4996,17 +4996,94 @@ ex_function(exarg_T *eap)
ga_clear_strings(&lines_to_free); 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 * :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 void
ex_defcompile(exarg_T *eap UNUSED) ex_defcompile(exarg_T *eap)
{
ufunc_T *ufunc;
if (*eap->arg != NUL)
{
compiletype_T compile_type;
ufunc = find_func_by_name(eap->arg, &compile_type);
if (ufunc != 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; long todo = (long)func_hashtab.ht_used;
int changed = func_hashtab.ht_changed; int changed = func_hashtab.ht_changed;
hashitem_T *hi; hashitem_T *hi;
ufunc_T *ufunc;
for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
{ {
@@ -5022,7 +5099,8 @@ ex_defcompile(exarg_T *eap UNUSED)
if (func_hashtab.ht_changed != changed) if (func_hashtab.ht_changed != changed)
{ {
// a function has been added or removed, need to start over // a function has been added or removed, need to start
// over
todo = (long)func_hashtab.ht_used; todo = (long)func_hashtab.ht_used;
changed = func_hashtab.ht_changed; changed = func_hashtab.ht_changed;
hi = func_hashtab.ht_array; hi = func_hashtab.ht_array;
@@ -5032,6 +5110,7 @@ ex_defcompile(exarg_T *eap UNUSED)
} }
} }
} }
}
/* /*
* Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
4989,
/**/ /**/
4988, 4988,
/**/ /**/

View File

@@ -6277,55 +6277,15 @@ get_disassemble_argument(expand_T *xp, int idx)
ex_disassemble(exarg_T *eap) ex_disassemble(exarg_T *eap)
{ {
char_u *arg = eap->arg; char_u *arg = eap->arg;
char_u *fname;
ufunc_T *ufunc; ufunc_T *ufunc;
dfunc_T *dfunc; dfunc_T *dfunc;
isn_T *instr; isn_T *instr;
int instr_count; int instr_count;
int is_global = FALSE; compiletype_T compile_type;
compiletype_T compile_type = CT_NONE;
if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7])) ufunc = find_func_by_name(arg, &compile_type);
{
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) 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; return;
}
if (func_needs_compiling(ufunc, compile_type) if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL) && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
return; return;