mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.3395: Vim9: expression breakpoint not checked in :def function
Problem: Vim9: expression breakpoint not checked in :def function. Solution: Always compile a function for debugging if there is an expression breakpoint. (closes #8803)
This commit is contained in:
@@ -518,6 +518,7 @@ static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
|
||||
#define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
|
||||
#define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx])
|
||||
static int last_breakp = 0; // nr of last defined breakpoint
|
||||
static int has_expr_breakpoint = FALSE;
|
||||
|
||||
#ifdef FEAT_PROFILE
|
||||
// Profiling uses file and func names similar to breakpoints.
|
||||
@@ -691,6 +692,8 @@ ex_breakadd(exarg_T *eap)
|
||||
// DBG_EXPR
|
||||
DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp;
|
||||
++debug_tick;
|
||||
if (gap == &dbg_breakp)
|
||||
has_expr_breakpoint = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,6 +710,29 @@ ex_debuggreedy(exarg_T *eap)
|
||||
debug_greedy = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_has_expr_breakpoint()
|
||||
{
|
||||
int i;
|
||||
|
||||
has_expr_breakpoint = FALSE;
|
||||
for (i = 0; i < dbg_breakp.ga_len; ++i)
|
||||
if (BREAKP(i).dbg_type == DBG_EXPR)
|
||||
{
|
||||
has_expr_breakpoint = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if there is any expression breakpoint.
|
||||
*/
|
||||
int
|
||||
debug_has_expr_breakpoint()
|
||||
{
|
||||
return has_expr_breakpoint;
|
||||
}
|
||||
|
||||
/*
|
||||
* ":breakdel" and ":profdel".
|
||||
*/
|
||||
@@ -799,6 +825,8 @@ ex_breakdel(exarg_T *eap)
|
||||
// If all breakpoints were removed clear the array.
|
||||
if (gap->ga_len == 0)
|
||||
ga_clear(gap);
|
||||
if (gap == &dbg_breakp)
|
||||
update_has_expr_breakpoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ void dbg_check_breakpoint(exarg_T *eap);
|
||||
int dbg_check_skipped(exarg_T *eap);
|
||||
void ex_breakadd(exarg_T *eap);
|
||||
void ex_debuggreedy(exarg_T *eap);
|
||||
int debug_has_expr_breakpoint(void);
|
||||
void ex_breakdel(exarg_T *eap);
|
||||
void ex_breaklist(exarg_T *eap);
|
||||
linenr_T dbg_find_breakpoint(int file, char_u *fname, linenr_T after);
|
||||
|
@@ -5,6 +5,7 @@ char_u *char_from_string(char_u *str, varnumber_T index);
|
||||
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
|
||||
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
|
||||
typval_T *lookup_debug_var(char_u *name);
|
||||
int may_break_in_function(ufunc_T *ufunc);
|
||||
int exe_typval_instr(typval_T *tv, typval_T *rettv);
|
||||
char_u *exe_substitute_instr(void);
|
||||
int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv);
|
||||
|
@@ -932,6 +932,27 @@ func Test_Backtrace_DefFunction()
|
||||
call delete('Xtest2.vim')
|
||||
endfunc
|
||||
|
||||
func Test_DefFunction_expr()
|
||||
CheckCWD
|
||||
let file3 =<< trim END
|
||||
vim9script
|
||||
g:someVar = "foo"
|
||||
def g:ChangeVar()
|
||||
g:someVar = "bar"
|
||||
echo "changed"
|
||||
enddef
|
||||
defcompile
|
||||
END
|
||||
call writefile(file3, 'Xtest3.vim')
|
||||
let buf = RunVimInTerminal('-S Xtest3.vim', {})
|
||||
|
||||
call RunDbgCmd(buf, ':breakadd expr g:someVar')
|
||||
call RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest3.vim')
|
||||
endfunc
|
||||
|
||||
func Test_debug_def_and_legacy_function()
|
||||
CheckCWD
|
||||
let file =<< trim END
|
||||
|
@@ -755,6 +755,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
3395,
|
||||
/**/
|
||||
3394,
|
||||
/**/
|
||||
|
11
src/vim.h
11
src/vim.h
@@ -1808,9 +1808,16 @@ typedef enum {
|
||||
|
||||
// Keep in sync with INSTRUCTIONS().
|
||||
#ifdef FEAT_PROFILE
|
||||
# define COMPILE_TYPE(ufunc) (debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
|
||||
# define COMPILE_TYPE(ufunc) (debug_break_level > 0 \
|
||||
|| may_break_in_function(ufunc) \
|
||||
? CT_DEBUG \
|
||||
: do_profiling == PROF_YES && (ufunc)->uf_profiling \
|
||||
? CT_PROFILE : CT_NONE)
|
||||
#else
|
||||
# define COMPILE_TYPE(ufunc) debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : CT_NONE
|
||||
# define COMPILE_TYPE(ufunc) debug_break_level > 0 \
|
||||
|| may_break_in_function(ufunc) \
|
||||
? CT_DEBUG \
|
||||
: CT_NONE
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -513,14 +513,14 @@ extern garray_T def_functions;
|
||||
// Keep in sync with COMPILE_TYPE()
|
||||
#ifdef FEAT_PROFILE
|
||||
# define INSTRUCTIONS(dfunc) \
|
||||
(debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
|
||||
(debug_break_level > 0 || may_break_in_function(dfunc->df_ufunc) \
|
||||
? (dfunc)->df_instr_debug \
|
||||
: ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \
|
||||
? (dfunc)->df_instr_prof \
|
||||
: (dfunc)->df_instr))
|
||||
#else
|
||||
# define INSTRUCTIONS(dfunc) \
|
||||
(debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
|
||||
(debug_break_level > 0 || may_break_in_function(dfunc->df_ufunc) \
|
||||
? (dfunc)->df_instr_debug \
|
||||
: (dfunc)->df_instr)
|
||||
#endif
|
||||
|
@@ -1483,6 +1483,16 @@ lookup_debug_var(char_u *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if there might be a breakpoint in "ufunc", which is when a
|
||||
* breakpoint was set in that function or when there is any expression.
|
||||
*/
|
||||
int
|
||||
may_break_in_function(ufunc_T *ufunc)
|
||||
{
|
||||
return ufunc->uf_has_breakpoint || debug_has_expr_breakpoint();
|
||||
}
|
||||
|
||||
static void
|
||||
handle_debug(isn_T *iptr, ectx_T *ectx)
|
||||
{
|
||||
@@ -1498,7 +1508,7 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
|
||||
{
|
||||
linenr_T breakpoint;
|
||||
|
||||
if (!ufunc->uf_has_breakpoint)
|
||||
if (!may_break_in_function(ufunc))
|
||||
return;
|
||||
|
||||
// check for the next breakpoint if needed
|
||||
|
Reference in New Issue
Block a user