mirror of
https://github.com/zoriya/vim.git
synced 2025-12-19 13:45:18 +00:00
patch 8.1.0515: reloading a script gives errors for existing functions
Problem: Reloading a script gives errors for existing functions. Solution: Allow redefining a function once when reloading a script.
This commit is contained in:
@@ -9673,9 +9673,13 @@ See |:verbose-cmd| for more information.
|
|||||||
deleted if there are no more references to it.
|
deleted if there are no more references to it.
|
||||||
*E127* *E122*
|
*E127* *E122*
|
||||||
When a function by this name already exists and [!] is
|
When a function by this name already exists and [!] is
|
||||||
not used an error message is given. When [!] is used,
|
not used an error message is given. There is one
|
||||||
an existing function is silently replaced. Unless it
|
exception: When sourcing a script again, a function
|
||||||
is currently being executed, that is an error.
|
that was previously defined in that script will be
|
||||||
|
silently replaced.
|
||||||
|
When [!] is used, an existing function is silently
|
||||||
|
replaced. Unless it is currently being executed, that
|
||||||
|
is an error.
|
||||||
NOTE: Use ! wisely. If used without care it can cause
|
NOTE: Use ! wisely. If used without care it can cause
|
||||||
an existing function to be replaced unexpectedly,
|
an existing function to be replaced unexpectedly,
|
||||||
which is hard to debug.
|
which is hard to debug.
|
||||||
|
|||||||
@@ -5519,6 +5519,7 @@ chk_modeline(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
save_current_sctx = current_sctx;
|
save_current_sctx = current_sctx;
|
||||||
current_sctx.sc_sid = SID_MODELINE;
|
current_sctx.sc_sid = SID_MODELINE;
|
||||||
|
current_sctx.sc_seq = 0;
|
||||||
current_sctx.sc_lnum = 0;
|
current_sctx.sc_lnum = 0;
|
||||||
#endif
|
#endif
|
||||||
retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags);
|
retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags);
|
||||||
|
|||||||
@@ -4344,6 +4344,7 @@ do_source(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
sctx_T save_current_sctx;
|
sctx_T save_current_sctx;
|
||||||
static scid_T last_current_SID = 0;
|
static scid_T last_current_SID = 0;
|
||||||
|
static int last_current_SID_seq = 0;
|
||||||
funccal_entry_T funccalp_entry;
|
funccal_entry_T funccalp_entry;
|
||||||
int save_debug_break_level = debug_break_level;
|
int save_debug_break_level = debug_break_level;
|
||||||
scriptitem_T *si = NULL;
|
scriptitem_T *si = NULL;
|
||||||
@@ -4508,11 +4509,11 @@ do_source(
|
|||||||
* Also starts profiling timer for nested script. */
|
* Also starts profiling timer for nested script. */
|
||||||
save_funccal(&funccalp_entry);
|
save_funccal(&funccalp_entry);
|
||||||
|
|
||||||
/*
|
// Check if this script was sourced before to finds its SID.
|
||||||
* Check if this script was sourced before to finds its SID.
|
// If it's new, generate a new SID.
|
||||||
* If it's new, generate a new SID.
|
// Always use a new sequence number.
|
||||||
*/
|
|
||||||
save_current_sctx = current_sctx;
|
save_current_sctx = current_sctx;
|
||||||
|
current_sctx.sc_seq = ++last_current_SID_seq;
|
||||||
current_sctx.sc_lnum = 0;
|
current_sctx.sc_lnum = 0;
|
||||||
# ifdef UNIX
|
# ifdef UNIX
|
||||||
stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
|
stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ EXTERN int want_garbage_collect INIT(= FALSE);
|
|||||||
EXTERN int garbage_collect_at_exit INIT(= FALSE);
|
EXTERN int garbage_collect_at_exit INIT(= FALSE);
|
||||||
|
|
||||||
// Script CTX being sourced or was sourced to define the current function.
|
// Script CTX being sourced or was sourced to define the current function.
|
||||||
EXTERN sctx_T current_sctx INIT(= {0 COMMA 0});
|
EXTERN sctx_T current_sctx INIT(= {0 COMMA 0 COMMA 0});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN int did_source_packages INIT(= FALSE);
|
EXTERN int did_source_packages INIT(= FALSE);
|
||||||
|
|||||||
@@ -2953,6 +2953,7 @@ exe_commands(mparm_T *parmp)
|
|||||||
sourcing_name = (char_u *)"command line";
|
sourcing_name = (char_u *)"command line";
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
current_sctx.sc_sid = SID_CARG;
|
current_sctx.sc_sid = SID_CARG;
|
||||||
|
current_sctx.sc_seq = 0;
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < parmp->n_commands; ++i)
|
for (i = 0; i < parmp->n_commands; ++i)
|
||||||
{
|
{
|
||||||
@@ -3183,6 +3184,7 @@ process_env(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
save_current_sctx = current_sctx;
|
save_current_sctx = current_sctx;
|
||||||
current_sctx.sc_sid = SID_ENV;
|
current_sctx.sc_sid = SID_ENV;
|
||||||
|
current_sctx.sc_seq = 0;
|
||||||
current_sctx.sc_lnum = 0;
|
current_sctx.sc_lnum = 0;
|
||||||
#endif
|
#endif
|
||||||
do_cmdline_cmd(initstr);
|
do_cmdline_cmd(initstr);
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ struct vimoption
|
|||||||
char_u *def_val[2]; // default values for variable (vi and vim)
|
char_u *def_val[2]; // default values for variable (vi and vim)
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
sctx_T script_ctx; // script context where the option was last set
|
sctx_T script_ctx; // script context where the option was last set
|
||||||
# define SCTX_INIT , {0, 0}
|
# define SCTX_INIT , {0, 0, 0}
|
||||||
#else
|
#else
|
||||||
# define SCTX_INIT
|
# define SCTX_INIT
|
||||||
#endif
|
#endif
|
||||||
@@ -5959,6 +5959,7 @@ set_string_option_direct(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
script_ctx.sc_sid = set_sid;
|
script_ctx.sc_sid = set_sid;
|
||||||
|
script_ctx.sc_seq = 0;
|
||||||
script_ctx.sc_lnum = 0;
|
script_ctx.sc_lnum = 0;
|
||||||
}
|
}
|
||||||
set_option_sctx_idx(idx, opt_flags, script_ctx);
|
set_option_sctx_idx(idx, opt_flags, script_ctx);
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ typedef struct VimMenu vimmenu_T;
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scid_T sc_sid; // script ID
|
scid_T sc_sid; // script ID
|
||||||
|
int sc_seq; // sourcing sequence number
|
||||||
linenr_T sc_lnum; // line number
|
linenr_T sc_lnum; // line number
|
||||||
} sctx_T;
|
} sctx_T;
|
||||||
|
|
||||||
|
|||||||
@@ -1138,3 +1138,30 @@ func Test_func_range_with_edit()
|
|||||||
call delete('Xfuncrange2')
|
call delete('Xfuncrange2')
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_func_exists_on_reload()
|
||||||
|
call writefile(['func ExistingFunction()', 'echo "yes"', 'endfunc'], 'Xfuncexists')
|
||||||
|
call assert_equal(0, exists('*ExistingFunction'))
|
||||||
|
source Xfuncexists
|
||||||
|
call assert_equal(1, exists('*ExistingFunction'))
|
||||||
|
" Redefining a function when reloading a script is OK.
|
||||||
|
source Xfuncexists
|
||||||
|
call assert_equal(1, exists('*ExistingFunction'))
|
||||||
|
|
||||||
|
" But redefining in another script is not OK.
|
||||||
|
call writefile(['func ExistingFunction()', 'echo "yes"', 'endfunc'], 'Xfuncexists2')
|
||||||
|
call assert_fails('source Xfuncexists2', 'E122:')
|
||||||
|
|
||||||
|
delfunc ExistingFunction
|
||||||
|
call assert_equal(0, exists('*ExistingFunction'))
|
||||||
|
call writefile([
|
||||||
|
\ 'func ExistingFunction()', 'echo "yes"', 'endfunc',
|
||||||
|
\ 'func ExistingFunction()', 'echo "no"', 'endfunc',
|
||||||
|
\ ], 'Xfuncexists')
|
||||||
|
call assert_fails('source Xfuncexists', 'E122:')
|
||||||
|
call assert_equal(1, exists('*ExistingFunction'))
|
||||||
|
|
||||||
|
call delete('Xfuncexists2')
|
||||||
|
call delete('Xfuncexists')
|
||||||
|
delfunc ExistingFunction
|
||||||
|
endfunc
|
||||||
|
|||||||
@@ -2330,14 +2330,19 @@ ex_function(exarg_T *eap)
|
|||||||
fp = find_func(name);
|
fp = find_func(name);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
if (!eap->forceit)
|
// Function can be replaced with "function!" and when sourcing the
|
||||||
|
// same script again, but only once.
|
||||||
|
if (!eap->forceit
|
||||||
|
&& (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid
|
||||||
|
|| fp->uf_script_ctx.sc_seq == current_sctx.sc_seq))
|
||||||
{
|
{
|
||||||
emsg_funcname(e_funcexts, name);
|
emsg_funcname(e_funcexts, name);
|
||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
if (fp->uf_calls > 0)
|
if (fp->uf_calls > 0)
|
||||||
{
|
{
|
||||||
emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
|
emsg_funcname(
|
||||||
|
N_("E127: Cannot redefine function %s: It is in use"),
|
||||||
name);
|
name);
|
||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -792,6 +792,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 */
|
||||||
|
/**/
|
||||||
|
515,
|
||||||
/**/
|
/**/
|
||||||
514,
|
514,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user