mirror of
https://github.com/vim/vim.git
synced 2025-07-25 10:54:51 -04:00
patch 8.2.1297: when a test fails it's often not easy to see where
Problem: When a test fails it's often not easy to see what the call stack is. Solution: Add more entries from the call stack in the exception message.
This commit is contained in:
parent
d66cdcd43a
commit
a5d0423fa1
@ -876,7 +876,7 @@ Also see |`=|.
|
|||||||
*:<cword>* *<cword>* *:<cWORD>* *<cWORD>*
|
*:<cword>* *<cword>* *:<cWORD>* *<cWORD>*
|
||||||
*:<cexpr>* *<cexpr>* *:<cfile>* *<cfile>*
|
*:<cexpr>* *<cexpr>* *:<cfile>* *<cfile>*
|
||||||
*:<afile>* *<afile>* *:<abuf>* *<abuf>*
|
*:<afile>* *<afile>* *:<abuf>* *<abuf>*
|
||||||
*:<amatch>* *<amatch>*
|
*:<amatch>* *<amatch>* *:<stack>* *<stack>*
|
||||||
*:<sfile>* *<sfile>* *:<slnum>* *<slnum>*
|
*:<sfile>* *<sfile>* *:<slnum>* *<slnum>*
|
||||||
*:<sflnum>* *<sflnum>* *E499* *E500*
|
*:<sflnum>* *<sflnum>* *E499* *E500*
|
||||||
Note: these are typed literally, they are not special keys!
|
Note: these are typed literally, they are not special keys!
|
||||||
@ -903,12 +903,16 @@ Note: these are typed literally, they are not special keys!
|
|||||||
events).
|
events).
|
||||||
<sfile> When executing a ":source" command, is replaced with the
|
<sfile> When executing a ":source" command, is replaced with the
|
||||||
file name of the sourced file. *E498*
|
file name of the sourced file. *E498*
|
||||||
When executing a function, is replaced with:
|
When executing a function, is replaced with the call stack,
|
||||||
"function {function-name}[{lnum}]"
|
as with <stack> (this is for backwards compatibility, using
|
||||||
function call nesting is indicated like this:
|
<stack> is preferred).
|
||||||
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
|
|
||||||
Note that filename-modifiers are useless when <sfile> is
|
Note that filename-modifiers are useless when <sfile> is
|
||||||
used inside a function.
|
not used inside a script.
|
||||||
|
<stack> is replaced with the call stack, using
|
||||||
|
"function {function-name}[{lnum}]" for a function line
|
||||||
|
and "script {file-name}[{lnum}]" for a script line, and
|
||||||
|
".." in between items. E.g.:
|
||||||
|
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
|
||||||
<slnum> When executing a ":source" command, is replaced with the
|
<slnum> When executing a ":source" command, is replaced with the
|
||||||
line number. *E842*
|
line number. *E842*
|
||||||
When executing a function it's the line number relative to
|
When executing a function it's the line number relative to
|
||||||
|
@ -105,7 +105,7 @@ do_debug(char_u *cmd)
|
|||||||
vim_free(debug_newval);
|
vim_free(debug_newval);
|
||||||
debug_newval = NULL;
|
debug_newval = NULL;
|
||||||
}
|
}
|
||||||
sname = estack_sfile();
|
sname = estack_sfile(FALSE);
|
||||||
if (sname != NULL)
|
if (sname != NULL)
|
||||||
msg((char *)sname);
|
msg((char *)sname);
|
||||||
vim_free(sname);
|
vim_free(sname);
|
||||||
@ -344,7 +344,7 @@ do_checkbacktracelevel(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char_u *sname = estack_sfile();
|
char_u *sname = estack_sfile(FALSE);
|
||||||
int max = get_maxbacktrace_level(sname);
|
int max = get_maxbacktrace_level(sname);
|
||||||
|
|
||||||
if (debug_backtrace_level > max)
|
if (debug_backtrace_level > max)
|
||||||
@ -365,7 +365,7 @@ do_showbacktrace(char_u *cmd)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
int max;
|
int max;
|
||||||
|
|
||||||
sname = estack_sfile();
|
sname = estack_sfile(FALSE);
|
||||||
max = get_maxbacktrace_level(sname);
|
max = get_maxbacktrace_level(sname);
|
||||||
if (sname != NULL)
|
if (sname != NULL)
|
||||||
{
|
{
|
||||||
|
@ -8268,8 +8268,10 @@ find_cmdline_var(char_u *src, int *usedlen)
|
|||||||
#define SPEC_SFILE (SPEC_CFILE + 1)
|
#define SPEC_SFILE (SPEC_CFILE + 1)
|
||||||
"<slnum>", // ":so" file line number
|
"<slnum>", // ":so" file line number
|
||||||
#define SPEC_SLNUM (SPEC_SFILE + 1)
|
#define SPEC_SLNUM (SPEC_SFILE + 1)
|
||||||
|
"<stack>", // call stack
|
||||||
|
#define SPEC_STACK (SPEC_SLNUM + 1)
|
||||||
"<afile>", // autocommand file name
|
"<afile>", // autocommand file name
|
||||||
#define SPEC_AFILE (SPEC_SLNUM + 1)
|
#define SPEC_AFILE (SPEC_STACK + 1)
|
||||||
"<abuf>", // autocommand buffer number
|
"<abuf>", // autocommand buffer number
|
||||||
#define SPEC_ABUF (SPEC_AFILE + 1)
|
#define SPEC_ABUF (SPEC_AFILE + 1)
|
||||||
"<amatch>", // autocommand match name
|
"<amatch>", // autocommand match name
|
||||||
@ -8520,10 +8522,13 @@ eval_vars(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SPEC_SFILE: // file name for ":so" command
|
case SPEC_SFILE: // file name for ":so" command
|
||||||
result = estack_sfile();
|
case SPEC_STACK: // call stack
|
||||||
|
result = estack_sfile(spec_idx == SPEC_SFILE);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
{
|
{
|
||||||
*errormsg = _("E498: no :source file name to substitute for \"<sfile>\"");
|
*errormsg = spec_idx == SPEC_SFILE
|
||||||
|
? _("E498: no :source file name to substitute for \"<sfile>\"")
|
||||||
|
: _("E489: no call stack to substitute for \"<stack>\"");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
resultbuf = result; // remember allocated string
|
resultbuf = result; // remember allocated string
|
||||||
|
@ -290,7 +290,7 @@ cause_errthrow(
|
|||||||
|
|
||||||
// Get the source name and lnum now, it may change before
|
// Get the source name and lnum now, it may change before
|
||||||
// reaching do_errthrow().
|
// reaching do_errthrow().
|
||||||
elem->sfile = estack_sfile();
|
elem->sfile = estack_sfile(FALSE);
|
||||||
elem->slnum = SOURCING_LNUM;
|
elem->slnum = SOURCING_LNUM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ throw_exception(void *value, except_type_T type, char_u *cmdname)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
excp->throw_name = estack_sfile();
|
excp->throw_name = estack_sfile(FALSE);
|
||||||
if (excp->throw_name == NULL)
|
if (excp->throw_name == NULL)
|
||||||
excp->throw_name = vim_strsave((char_u *)"");
|
excp->throw_name = vim_strsave((char_u *)"");
|
||||||
if (excp->throw_name == NULL)
|
if (excp->throw_name == NULL)
|
||||||
|
@ -461,7 +461,7 @@ get_emsg_source(void)
|
|||||||
|
|
||||||
if (SOURCING_NAME != NULL && other_sourcing_name())
|
if (SOURCING_NAME != NULL && other_sourcing_name())
|
||||||
{
|
{
|
||||||
char_u *sname = estack_sfile();
|
char_u *sname = estack_sfile(FALSE);
|
||||||
char_u *tofree = sname;
|
char_u *tofree = sname;
|
||||||
|
|
||||||
if (sname == NULL)
|
if (sname == NULL)
|
||||||
|
@ -4,7 +4,7 @@ estack_T *estack_push(etype_T type, char_u *name, long lnum);
|
|||||||
estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum);
|
estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum);
|
||||||
int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
|
int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
|
||||||
estack_T *estack_pop(void);
|
estack_T *estack_pop(void);
|
||||||
char_u *estack_sfile(void);
|
char_u *estack_sfile(int is_sfile);
|
||||||
void ex_runtime(exarg_T *eap);
|
void ex_runtime(exarg_T *eap);
|
||||||
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
||||||
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
||||||
|
@ -111,58 +111,68 @@ estack_pop(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the current value for <sfile> in allocated memory.
|
* Get the current value for <sfile> in allocated memory.
|
||||||
|
* "is_sfile" is TRUE for <sfile> itself.
|
||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
estack_sfile(void)
|
estack_sfile(int is_sfile)
|
||||||
{
|
{
|
||||||
estack_T *entry;
|
estack_T *entry;
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
|
garray_T ga;
|
||||||
size_t len;
|
size_t len;
|
||||||
int idx;
|
int idx;
|
||||||
char *res;
|
etype_T last_type = ETYPE_SCRIPT;
|
||||||
size_t done;
|
char *type_name;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
|
entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
|
||||||
if (entry->es_name == NULL)
|
|
||||||
return NULL;
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
if (entry->es_info.ufunc == NULL)
|
if (is_sfile && entry->es_type != ETYPE_UFUNC)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
if (entry->es_name == NULL)
|
||||||
|
return NULL;
|
||||||
return vim_strsave(entry->es_name);
|
return vim_strsave(entry->es_name);
|
||||||
|
}
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
|
// Give information about each stack entry up to the root.
|
||||||
// For a function we compose the call stack, as it was done in the past:
|
// For a function we compose the call stack, as it was done in the past:
|
||||||
// "function One[123]..Two[456]..Three"
|
// "function One[123]..Two[456]..Three"
|
||||||
len = STRLEN(entry->es_name) + 10;
|
ga_init2(&ga, sizeof(char), 100);
|
||||||
for (idx = exestack.ga_len - 2; idx >= 0; --idx)
|
for (idx = 0; idx < exestack.ga_len; ++idx)
|
||||||
{
|
{
|
||||||
entry = ((estack_T *)exestack.ga_data) + idx;
|
entry = ((estack_T *)exestack.ga_data) + idx;
|
||||||
if (entry->es_name == NULL || entry->es_info.ufunc == NULL)
|
if (entry->es_name != NULL)
|
||||||
{
|
{
|
||||||
++idx;
|
len = STRLEN(entry->es_name) + 15;
|
||||||
break;
|
type_name = "";
|
||||||
|
if (entry->es_type != last_type)
|
||||||
|
{
|
||||||
|
switch (entry->es_type)
|
||||||
|
{
|
||||||
|
case ETYPE_SCRIPT: type_name = "script "; break;
|
||||||
|
case ETYPE_UFUNC: type_name = "function "; break;
|
||||||
|
default: type_name = ""; break;
|
||||||
|
}
|
||||||
|
last_type = entry->es_type;
|
||||||
|
}
|
||||||
|
len += STRLEN(type_name);
|
||||||
|
if (ga_grow(&ga, len) == FAIL)
|
||||||
|
break;
|
||||||
|
if (idx == exestack.ga_len - 1 || entry->es_lnum == 0)
|
||||||
|
// For the bottom entry: do not add the line number, it is used
|
||||||
|
// in <slnum>. Also leave it out when the number is not set.
|
||||||
|
vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s%s",
|
||||||
|
type_name, entry->es_name,
|
||||||
|
idx == exestack.ga_len - 1 ? "" : "..");
|
||||||
|
else
|
||||||
|
vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s[%ld]..",
|
||||||
|
type_name, entry->es_name, entry->es_lnum);
|
||||||
|
ga.ga_len += STRLEN(ga.ga_data + ga.ga_len);
|
||||||
}
|
}
|
||||||
len += STRLEN(entry->es_name) + 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = (char *)alloc((int)len);
|
return (char_u *)ga.ga_data;
|
||||||
if (res != NULL)
|
|
||||||
{
|
|
||||||
STRCPY(res, "function ");
|
|
||||||
while (idx < exestack.ga_len - 1)
|
|
||||||
{
|
|
||||||
done = STRLEN(res);
|
|
||||||
entry = ((estack_T *)exestack.ga_data) + idx;
|
|
||||||
vim_snprintf(res + done, len - done, "%s[%ld]..",
|
|
||||||
entry->es_name, entry->es_lnum);
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
done = STRLEN(res);
|
|
||||||
entry = ((estack_T *)exestack.ga_data) + idx;
|
|
||||||
vim_snprintf(res + done, len - done, "%s", entry->es_name);
|
|
||||||
}
|
|
||||||
return (char_u *)res;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,17 +16,47 @@ func s:expand_sflnum()
|
|||||||
return str2nr(expand('<sflnum>'))
|
return str2nr(expand('<sflnum>'))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_expand_sfile()
|
" This test depends on the location in the test file, put it first.
|
||||||
call assert_match('test_expand_func\.vim$', s:sfile)
|
func Test_expand_sflnum()
|
||||||
call assert_match('^function .*\.\.Test_expand_sfile$', expand('<sfile>'))
|
call assert_equal(5, s:sflnum)
|
||||||
|
call assert_equal(22, str2nr(expand('<sflnum>')))
|
||||||
|
|
||||||
|
" Line-continuation
|
||||||
|
call assert_equal(
|
||||||
|
\ 25,
|
||||||
|
\ str2nr(expand('<sflnum>')))
|
||||||
|
|
||||||
" Call in script-local function
|
" Call in script-local function
|
||||||
call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile())
|
call assert_equal(16, s:expand_sflnum())
|
||||||
|
|
||||||
|
" Call in command
|
||||||
|
command Flnum echo expand('<sflnum>')
|
||||||
|
call assert_equal(34, str2nr(trim(execute('Flnum'))))
|
||||||
|
delcommand Flnum
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_expand_sfile_and_stack()
|
||||||
|
call assert_match('test_expand_func\.vim$', s:sfile)
|
||||||
|
let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$'
|
||||||
|
call assert_match(expected , expand('<sfile>'))
|
||||||
|
call assert_match(expected , expand('<stack>'))
|
||||||
|
|
||||||
|
" Call in script-local function
|
||||||
|
call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile())
|
||||||
|
|
||||||
" Call in command
|
" Call in command
|
||||||
command Sfile echo expand('<sfile>')
|
command Sfile echo expand('<sfile>')
|
||||||
call assert_match('^function .*\.\.Test_expand_sfile$', trim(execute('Sfile')))
|
call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$', trim(execute('Sfile')))
|
||||||
delcommand Sfile
|
delcommand Sfile
|
||||||
|
|
||||||
|
" Use <stack> from sourced script.
|
||||||
|
let lines =<< trim END
|
||||||
|
let g:stack_value = expand('<stack>')
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xstack')
|
||||||
|
source Xstack
|
||||||
|
call assert_match('\<Xstack$', g:stack_value)
|
||||||
|
call delete('Xstack')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_expand_slnum()
|
func Test_expand_slnum()
|
||||||
@ -47,24 +77,6 @@ func Test_expand_slnum()
|
|||||||
delcommand Slnum
|
delcommand Slnum
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_expand_sflnum()
|
|
||||||
call assert_equal(5, s:sflnum)
|
|
||||||
call assert_equal(52, str2nr(expand('<sflnum>')))
|
|
||||||
|
|
||||||
" Line-continuation
|
|
||||||
call assert_equal(
|
|
||||||
\ 55,
|
|
||||||
\ str2nr(expand('<sflnum>')))
|
|
||||||
|
|
||||||
" Call in script-local function
|
|
||||||
call assert_equal(16, s:expand_sflnum())
|
|
||||||
|
|
||||||
" Call in command
|
|
||||||
command Flnum echo expand('<sflnum>')
|
|
||||||
call assert_equal(64, str2nr(trim(execute('Flnum'))))
|
|
||||||
delcommand Flnum
|
|
||||||
endfunc
|
|
||||||
|
|
||||||
func Test_expand()
|
func Test_expand()
|
||||||
new
|
new
|
||||||
call assert_equal("", expand('%:S'))
|
call assert_equal("", expand('%:S'))
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
prepare_assert_error(garray_T *gap)
|
prepare_assert_error(garray_T *gap)
|
||||||
{
|
{
|
||||||
char buf[NUMBUFLEN];
|
char buf[NUMBUFLEN];
|
||||||
char_u *sname = estack_sfile();
|
char_u *sname = estack_sfile(FALSE);
|
||||||
|
|
||||||
ga_init2(gap, 1, 100);
|
ga_init2(gap, 1, 100);
|
||||||
if (sname != NULL)
|
if (sname != NULL)
|
||||||
|
@ -754,6 +754,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 */
|
||||||
|
/**/
|
||||||
|
1297,
|
||||||
/**/
|
/**/
|
||||||
1296,
|
1296,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user