0
0
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:
Bram Moolenaar
2021-09-02 18:49:06 +02:00
parent 04626c243c
commit 26a4484da2
8 changed files with 75 additions and 5 deletions

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

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

View File

@@ -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
/*

View File

@@ -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

View File

@@ -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