mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
vim-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.
a5d0423fa1
Use docs from latest Vim.
This commit is contained in:
parent
1c164689a4
commit
98ab0bb5f7
@ -2010,6 +2010,7 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
|
||||
a function
|
||||
<SID> "<SNR>123_" where "123" is the
|
||||
current script ID |<SID>|
|
||||
<stack> call stack
|
||||
<cword> word under the cursor
|
||||
<cWORD> WORD under the cursor
|
||||
<client> the {clientid} of the last received
|
||||
|
@ -879,12 +879,18 @@ Note: these are typed literally, they are not special keys!
|
||||
*:<sfile>* *<sfile>*
|
||||
<sfile> When executing a `:source` command, is replaced with the
|
||||
file name of the sourced file. *E498*
|
||||
When executing a function, is replaced with:
|
||||
"function {function-name}[{lnum}]"
|
||||
function call nesting is indicated like this:
|
||||
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
|
||||
When executing a function, is replaced with the call stack,
|
||||
as with <stack> (this is for backwards compatibility, using
|
||||
<stack> is preferred).
|
||||
Note that filename-modifiers are useless when <sfile> is
|
||||
used inside a function.
|
||||
not used inside a script.
|
||||
*:<stack>* *<stack>*
|
||||
<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}]"
|
||||
If there is no call stack you get error *E489* .
|
||||
*:<slnum>* *<slnum>*
|
||||
<slnum> When executing a `:source` command, is replaced with the
|
||||
line number. *E842*
|
||||
|
@ -99,7 +99,7 @@ void do_debug(char_u *cmd)
|
||||
xfree(debug_newval);
|
||||
debug_newval = NULL;
|
||||
}
|
||||
char *sname = estack_sfile();
|
||||
char *sname = estack_sfile(false);
|
||||
if (sname != NULL) {
|
||||
msg(sname);
|
||||
}
|
||||
@ -324,7 +324,7 @@ static void do_checkbacktracelevel(void)
|
||||
debug_backtrace_level = 0;
|
||||
msg(_("frame is zero"));
|
||||
} else {
|
||||
char *sname = estack_sfile();
|
||||
char *sname = estack_sfile(false);
|
||||
int max = get_maxbacktrace_level(sname);
|
||||
|
||||
if (debug_backtrace_level > max) {
|
||||
@ -337,7 +337,7 @@ static void do_checkbacktracelevel(void)
|
||||
|
||||
static void do_showbacktrace(char_u *cmd)
|
||||
{
|
||||
char *sname = estack_sfile();
|
||||
char *sname = estack_sfile(false);
|
||||
int max = get_maxbacktrace_level(sname);
|
||||
if (sname != NULL) {
|
||||
int i = 0;
|
||||
|
@ -7912,9 +7912,12 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
|
||||
break;
|
||||
|
||||
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) {
|
||||
*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;
|
||||
}
|
||||
resultbuf = result; // remember allocated string
|
||||
|
@ -278,7 +278,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
|
||||
|
||||
// Get the source name and lnum now, it may change before
|
||||
// reaching do_errthrow().
|
||||
elem->sfile = estack_sfile();
|
||||
elem->sfile = estack_sfile(false);
|
||||
elem->slnum = SOURCING_LNUM;
|
||||
}
|
||||
return true;
|
||||
@ -490,7 +490,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
|
||||
entry->sfile = NULL;
|
||||
excp->throw_lnum = entry->slnum;
|
||||
} else {
|
||||
excp->throw_name = estack_sfile();
|
||||
excp->throw_name = estack_sfile(false);
|
||||
if (excp->throw_name == NULL) {
|
||||
excp->throw_name = xstrdup("");
|
||||
}
|
||||
|
@ -555,7 +555,7 @@ static char *get_emsg_source(void)
|
||||
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (SOURCING_NAME != NULL && other_sourcing_name()) {
|
||||
char *sname = estack_sfile();
|
||||
char *sname = estack_sfile(false);
|
||||
char *tofree = sname;
|
||||
|
||||
if (sname == NULL) {
|
||||
|
@ -100,42 +100,55 @@ void estack_pop(void)
|
||||
}
|
||||
|
||||
/// Get the current value for <sfile> in allocated memory.
|
||||
char *estack_sfile(void)
|
||||
/// @param is_sfile true for <sfile> itself.
|
||||
char *estack_sfile(bool is_sfile)
|
||||
{
|
||||
estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
|
||||
if (entry->es_name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (entry->es_info.ufunc == NULL) {
|
||||
if (is_sfile && entry->es_type != ETYPE_UFUNC) {
|
||||
if (entry->es_name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return xstrdup(entry->es_name);
|
||||
}
|
||||
|
||||
// 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:
|
||||
// "function One[123]..Two[456]..Three"
|
||||
size_t len = STRLEN(entry->es_name) + 10;
|
||||
int idx;
|
||||
for (idx = exestack.ga_len - 2; idx >= 0; idx--) {
|
||||
garray_T ga;
|
||||
ga_init(&ga, sizeof(char), 100);
|
||||
etype_T last_type = ETYPE_SCRIPT;
|
||||
for (int idx = 0; idx < exestack.ga_len; idx++) {
|
||||
entry = ((estack_T *)exestack.ga_data) + idx;
|
||||
if (entry->es_name == NULL || entry->es_info.ufunc == NULL) {
|
||||
idx++;
|
||||
break;
|
||||
if (entry->es_name != NULL) {
|
||||
size_t len = strlen(entry->es_name) + 15;
|
||||
char *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);
|
||||
ga_grow(&ga, (int)len);
|
||||
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((char *)ga.ga_data + ga.ga_len, len, "%s%s%s",
|
||||
type_name, entry->es_name, idx == exestack.ga_len - 1 ? "" : "..");
|
||||
} else {
|
||||
vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%" PRIdLINENR "]..",
|
||||
type_name, entry->es_name, entry->es_lnum);
|
||||
}
|
||||
ga.ga_len += (int)strlen((char *)ga.ga_data + ga.ga_len);
|
||||
}
|
||||
len += STRLEN(entry->es_name) + 15;
|
||||
}
|
||||
|
||||
char *res = (char *)xmalloc(len);
|
||||
STRCPY(res, "function ");
|
||||
size_t done;
|
||||
while (idx < exestack.ga_len - 1) {
|
||||
done = STRLEN(res);
|
||||
entry = ((estack_T *)exestack.ga_data) + idx;
|
||||
vim_snprintf(res + done, len - done, "%s[%" PRIdLINENR "]..", 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 res;
|
||||
return (char *)ga.ga_data;
|
||||
}
|
||||
|
||||
static bool runtime_search_path_valid = false;
|
||||
|
@ -37,17 +37,28 @@ func Test_expand_sflnum()
|
||||
delcommand Flnum
|
||||
endfunc
|
||||
|
||||
func Test_expand_sfile()
|
||||
func Test_expand_sfile_and_stack()
|
||||
call assert_match('test_expand_func\.vim$', s:sfile)
|
||||
call assert_match('^function .*\.\.Test_expand_sfile$', expand('<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('^function .*\.\.Test_expand_sfile\[5\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile())
|
||||
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
|
||||
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
|
||||
|
||||
" 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
|
||||
|
||||
func Test_expand_slnum()
|
||||
|
@ -18,7 +18,7 @@
|
||||
static void prepare_assert_error(garray_T *gap)
|
||||
{
|
||||
char buf[NUMBUFLEN];
|
||||
char *sname = estack_sfile();
|
||||
char *sname = estack_sfile(false);
|
||||
|
||||
ga_init(gap, 1, 100);
|
||||
if (sname != NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user