summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-07-26 15:37:02 +0200
committerBram Moolenaar <Bram@vim.org>2020-07-26 15:37:02 +0200
commita5d0423fa16f18b4576a2a07e50034e489587a7d (patch)
tree67bfe997079bb1a9f17db6a829b29d6369a922a3 /src
parentd66cdcd43a598825add743bc95642cd8ed705252 (diff)
patch 8.2.1297: when a test fails it's often not easy to see wherev8.2.1297
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.
Diffstat (limited to 'src')
-rw-r--r--src/debugger.c6
-rw-r--r--src/ex_docmd.c11
-rw-r--r--src/ex_eval.c4
-rw-r--r--src/message.c2
-rw-r--r--src/proto/scriptfile.pro2
-rw-r--r--src/scriptfile.c70
-rw-r--r--src/testdir/test_expand_func.vim56
-rw-r--r--src/testing.c2
-rw-r--r--src/version.c2
9 files changed, 92 insertions, 63 deletions
diff --git a/src/debugger.c b/src/debugger.c
index 91ab5ee1fa..00fb9c8f8b 100644
--- a/src/debugger.c
+++ b/src/debugger.c
@@ -105,7 +105,7 @@ do_debug(char_u *cmd)
vim_free(debug_newval);
debug_newval = NULL;
}
- sname = estack_sfile();
+ sname = estack_sfile(FALSE);
if (sname != NULL)
msg((char *)sname);
vim_free(sname);
@@ -344,7 +344,7 @@ do_checkbacktracelevel(void)
}
else
{
- char_u *sname = estack_sfile();
+ char_u *sname = estack_sfile(FALSE);
int max = get_maxbacktrace_level(sname);
if (debug_backtrace_level > max)
@@ -365,7 +365,7 @@ do_showbacktrace(char_u *cmd)
int i = 0;
int max;
- sname = estack_sfile();
+ sname = estack_sfile(FALSE);
max = get_maxbacktrace_level(sname);
if (sname != NULL)
{
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 04c3b465a7..987e92dea9 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8268,8 +8268,10 @@ find_cmdline_var(char_u *src, int *usedlen)
#define SPEC_SFILE (SPEC_CFILE + 1)
"<slnum>", // ":so" file line number
#define SPEC_SLNUM (SPEC_SFILE + 1)
+ "<stack>", // call stack
+#define SPEC_STACK (SPEC_SLNUM + 1)
"<afile>", // autocommand file name
-#define SPEC_AFILE (SPEC_SLNUM + 1)
+#define SPEC_AFILE (SPEC_STACK + 1)
"<abuf>", // autocommand buffer number
#define SPEC_ABUF (SPEC_AFILE + 1)
"<amatch>", // autocommand match name
@@ -8520,10 +8522,13 @@ eval_vars(
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
diff --git a/src/ex_eval.c b/src/ex_eval.c
index f0ffaffdde..58088a0706 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -290,7 +290,7 @@ cause_errthrow(
// 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;
}
}
@@ -549,7 +549,7 @@ throw_exception(void *value, except_type_T type, char_u *cmdname)
}
else
{
- excp->throw_name = estack_sfile();
+ excp->throw_name = estack_sfile(FALSE);
if (excp->throw_name == NULL)
excp->throw_name = vim_strsave((char_u *)"");
if (excp->throw_name == NULL)
diff --git a/src/message.c b/src/message.c
index 76ec456795..91b2fe2372 100644
--- a/src/message.c
+++ b/src/message.c
@@ -461,7 +461,7 @@ get_emsg_source(void)
if (SOURCING_NAME != NULL && other_sourcing_name())
{
- char_u *sname = estack_sfile();
+ char_u *sname = estack_sfile(FALSE);
char_u *tofree = sname;
if (sname == NULL)
diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro
index fd4c104738..00f1301eee 100644
--- a/src/proto/scriptfile.pro
+++ b/src/proto/scriptfile.pro
@@ -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);
int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
estack_T *estack_pop(void);
-char_u *estack_sfile(void);
+char_u *estack_sfile(int is_sfile);
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_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
diff --git a/src/scriptfile.c b/src/scriptfile.c
index ce269a1cd2..ce9c15d31b 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -111,58 +111,68 @@ estack_pop(void)
/*
* Get the current value for <sfile> in allocated memory.
+ * "is_sfile" is TRUE for <sfile> itself.
*/
char_u *
-estack_sfile(void)
+estack_sfile(int is_sfile)
{
estack_T *entry;
#ifdef FEAT_EVAL
+ garray_T ga;
size_t len;
int idx;
- char *res;
- size_t done;
+ etype_T last_type = ETYPE_SCRIPT;
+ char *type_name;
#endif
entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
- if (entry->es_name == NULL)
- return NULL;
#ifdef FEAT_EVAL
- if (entry->es_info.ufunc == NULL)
+ if (is_sfile && entry->es_type != ETYPE_UFUNC)
#endif
+ {
+ if (entry->es_name == NULL)
+ return NULL;
return vim_strsave(entry->es_name);
-
+ }
#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:
// "function One[123]..Two[456]..Three"
- len = STRLEN(entry->es_name) + 10;
- for (idx = exestack.ga_len - 2; idx >= 0; --idx)
+ ga_init2(&ga, sizeof(char), 100);
+ for (idx = 0; idx < exestack.ga_len; ++idx)
{
entry = ((estack_T *)exestack.ga_data) + idx;
- if (entry->es_name == NULL || entry->es_info.ufunc == NULL)
+ if (entry->es_name != NULL)
{
- ++idx;
- break;
+ len = STRLEN(entry->es_name) + 15;
+ 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);
- 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;
+ return (char_u *)ga.ga_data;
#endif
}
diff --git a/src/testdir/test_expand_func.vim b/src/testdir/test_expand_func.vim
index 18437b7588..41673e50af 100644
--- a/src/testdir/test_expand_func.vim
+++ b/src/testdir/test_expand_func.vim
@@ -16,17 +16,47 @@ func s:expand_sflnum()
return str2nr(expand('<sflnum>'))
endfunc
-func Test_expand_sfile()
+" This test depends on the location in the test file, put it first.
+func Test_expand_sflnum()
+ 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 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)
- 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()
@@ -47,24 +77,6 @@ func Test_expand_slnum()
delcommand Slnum
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()
new
call assert_equal("", expand('%:S'))
diff --git a/src/testing.c b/src/testing.c
index de89bd9fd7..137d5fe9f7 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -22,7 +22,7 @@
prepare_assert_error(garray_T *gap)
{
char buf[NUMBUFLEN];
- char_u *sname = estack_sfile();
+ char_u *sname = estack_sfile(FALSE);
ga_init2(gap, 1, 100);
if (sname != NULL)
diff --git a/src/version.c b/src/version.c
index 6a5f19951e..c45c15519c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1297,
+/**/
1296,
/**/
1295,