To: vim_dev@googlegroups.com Subject: Patch 8.2.1297 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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. Files: runtime/doc/cmdline.txt, src/scriptfile.c, src/proto/scriptfile.pro, src/debugger.c, src/ex_docmd.c, src/ex_eval.c, src/message.c, src/testing.c, src/testdir/test_expand_func.vim *** ../vim-8.2.1296/runtime/doc/cmdline.txt 2020-02-04 22:22:43.060586069 +0100 --- runtime/doc/cmdline.txt 2020-07-26 15:22:46.958707750 +0200 *************** *** 476,481 **** --- 476,485 ---- This will find the longest match with the first 'wildchar', then list all matching files with the next. + *complete-script-local-functions* + When completing user function names, prepend "s:" to find script-local + functions. + *suffixes* For file name completion you can use the 'suffixes' option to set a priority between files with almost the same name. If there are multiple matches, *************** *** 586,591 **** --- 590,596 ---- :command :cscope :debug + :eval :folddoopen :folddoclosed :function *************** *** 610,615 **** --- 615,621 ---- :tcl :tcldo :tclfile + :terminal :vglobal :windo :write ! *************** *** 870,876 **** *:* ** *:* ** *:* ** *:* ** *:* ** *:* ** ! *:* ** *:* ** *:* ** *:* ** *E499* *E500* Note: these are typed literally, they are not special keys! --- 876,882 ---- *:* ** *:* ** *:* ** *:* ** *:* ** *:* ** ! *:* ** *:* ** *:* ** *:* ** *:* ** *E499* *E500* Note: these are typed literally, they are not special keys! *************** *** 897,908 **** events). 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}]" Note that filename-modifiers are useless when is ! used inside a function. When executing a ":source" command, is replaced with the line number. *E842* When executing a function it's the line number relative to --- 903,918 ---- events). When executing a ":source" command, is replaced with the file name of the sourced file. *E498* ! When executing a function, is replaced with the call stack, ! as with (this is for backwards compatibility, using ! is preferred). Note that filename-modifiers are useless when is ! not used inside a script. ! 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}]" When executing a ":source" command, is replaced with the line number. *E842* When executing a function it's the line number relative to *** ../vim-8.2.1296/src/scriptfile.c 2020-07-19 16:32:06.085674254 +0200 --- src/scriptfile.c 2020-07-26 15:05:08.942203746 +0200 *************** *** 111,168 **** /* * Get the current value for in allocated memory. */ char_u * ! estack_sfile(void) { estack_T *entry; #ifdef FEAT_EVAL size_t len; int idx; ! char *res; ! size_t done; #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) #endif return vim_strsave(entry->es_name); ! #ifdef FEAT_EVAL // 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) { entry = ((estack_T *)exestack.ga_data) + idx; ! if (entry->es_name == NULL || entry->es_info.ufunc == NULL) { ! ++idx; ! break; } - 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; #endif } --- 111,178 ---- /* * Get the current value for in allocated memory. + * "is_sfile" is TRUE for itself. */ char_u * ! estack_sfile(int is_sfile) { estack_T *entry; #ifdef FEAT_EVAL + garray_T ga; size_t len; int idx; ! etype_T last_type = ETYPE_SCRIPT; ! char *type_name; #endif entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; #ifdef FEAT_EVAL ! 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" ! 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) { ! 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 . 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); } } ! return (char_u *)ga.ga_data; #endif } *** ../vim-8.2.1296/src/proto/scriptfile.pro 2020-07-08 15:16:15.534128895 +0200 --- src/proto/scriptfile.pro 2020-07-26 14:46:57.419632549 +0200 *************** *** 4,10 **** 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); 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); --- 4,10 ---- 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(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); *** ../vim-8.2.1296/src/debugger.c 2019-12-31 22:36:14.561918852 +0100 --- src/debugger.c 2020-07-26 14:50:36.590426249 +0200 *************** *** 105,111 **** vim_free(debug_newval); debug_newval = NULL; } ! sname = estack_sfile(); if (sname != NULL) msg((char *)sname); vim_free(sname); --- 105,111 ---- vim_free(debug_newval); debug_newval = NULL; } ! sname = estack_sfile(FALSE); if (sname != NULL) msg((char *)sname); vim_free(sname); *************** *** 344,350 **** } else { ! char_u *sname = estack_sfile(); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) --- 344,350 ---- } else { ! char_u *sname = estack_sfile(FALSE); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) *************** *** 365,371 **** int i = 0; int max; ! sname = estack_sfile(); max = get_maxbacktrace_level(sname); if (sname != NULL) { --- 365,371 ---- int i = 0; int max; ! sname = estack_sfile(FALSE); max = get_maxbacktrace_level(sname); if (sname != NULL) { *** ../vim-8.2.1296/src/ex_docmd.c 2020-07-25 19:38:13.329572365 +0200 --- src/ex_docmd.c 2020-07-26 15:26:50.397667316 +0200 *************** *** 8268,8275 **** #define SPEC_SFILE (SPEC_CFILE + 1) "", // ":so" file line number #define SPEC_SLNUM (SPEC_SFILE + 1) "", // autocommand file name ! #define SPEC_AFILE (SPEC_SLNUM + 1) "", // autocommand buffer number #define SPEC_ABUF (SPEC_AFILE + 1) "", // autocommand match name --- 8268,8277 ---- #define SPEC_SFILE (SPEC_CFILE + 1) "", // ":so" file line number #define SPEC_SLNUM (SPEC_SFILE + 1) + "", // call stack + #define SPEC_STACK (SPEC_SLNUM + 1) "", // autocommand file name ! #define SPEC_AFILE (SPEC_STACK + 1) "", // autocommand buffer number #define SPEC_ABUF (SPEC_AFILE + 1) "", // autocommand match name *************** *** 8520,8529 **** break; case SPEC_SFILE: // file name for ":so" command ! result = estack_sfile(); if (result == NULL) { ! *errormsg = _("E498: no :source file name to substitute for \"\""); return NULL; } resultbuf = result; // remember allocated string --- 8522,8534 ---- break; case SPEC_SFILE: // file name for ":so" command ! case SPEC_STACK: // call stack ! result = estack_sfile(spec_idx == SPEC_SFILE); if (result == NULL) { ! *errormsg = spec_idx == SPEC_SFILE ! ? _("E498: no :source file name to substitute for \"\"") ! : _("E489: no call stack to substitute for \"\""); return NULL; } resultbuf = result; // remember allocated string *** ../vim-8.2.1296/src/ex_eval.c 2020-07-23 17:16:15.050100601 +0200 --- src/ex_eval.c 2020-07-26 14:50:50.530350934 +0200 *************** *** 290,296 **** // Get the source name and lnum now, it may change before // reaching do_errthrow(). ! elem->sfile = estack_sfile(); elem->slnum = SOURCING_LNUM; } } --- 290,296 ---- // Get the source name and lnum now, it may change before // reaching do_errthrow(). ! elem->sfile = estack_sfile(FALSE); elem->slnum = SOURCING_LNUM; } } *************** *** 549,555 **** } else { ! excp->throw_name = estack_sfile(); if (excp->throw_name == NULL) excp->throw_name = vim_strsave((char_u *)""); if (excp->throw_name == NULL) --- 549,555 ---- } else { ! excp->throw_name = estack_sfile(FALSE); if (excp->throw_name == NULL) excp->throw_name = vim_strsave((char_u *)""); if (excp->throw_name == NULL) *** ../vim-8.2.1296/src/message.c 2020-07-11 22:14:54.310422225 +0200 --- src/message.c 2020-07-26 14:50:53.722333708 +0200 *************** *** 461,467 **** if (SOURCING_NAME != NULL && other_sourcing_name()) { ! char_u *sname = estack_sfile(); char_u *tofree = sname; if (sname == NULL) --- 461,467 ---- if (SOURCING_NAME != NULL && other_sourcing_name()) { ! char_u *sname = estack_sfile(FALSE); char_u *tofree = sname; if (sname == NULL) *** ../vim-8.2.1296/src/testing.c 2020-07-12 23:09:15.450213545 +0200 --- src/testing.c 2020-07-26 14:51:00.166298950 +0200 *************** *** 22,28 **** prepare_assert_error(garray_T *gap) { char buf[NUMBUFLEN]; ! char_u *sname = estack_sfile(); ga_init2(gap, 1, 100); if (sname != NULL) --- 22,28 ---- prepare_assert_error(garray_T *gap) { char buf[NUMBUFLEN]; ! char_u *sname = estack_sfile(FALSE); ga_init2(gap, 1, 100); if (sname != NULL) *** ../vim-8.2.1296/src/testdir/test_expand_func.vim 2020-03-25 22:23:41.898363595 +0100 --- src/testdir/test_expand_func.vim 2020-07-26 15:34:35.143612408 +0200 *************** *** 16,32 **** return str2nr(expand('')) endfunc ! func Test_expand_sfile() call assert_match('test_expand_func\.vim$', s:sfile) ! call assert_match('^function .*\.\.Test_expand_sfile$', expand('')) " Call in script-local function ! call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.\d\+_expand_sfile$', s:expand_sfile()) " Call in command command Sfile echo expand('') ! call assert_match('^function .*\.\.Test_expand_sfile$', trim(execute('Sfile'))) delcommand Sfile endfunc func Test_expand_slnum() --- 16,62 ---- return str2nr(expand('')) endfunc ! " 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(''))) ! ! " Line-continuation ! call assert_equal( ! \ 25, ! \ str2nr(expand(''))) ! ! " Call in script-local function ! call assert_equal(16, s:expand_sflnum()) ! ! " Call in command ! command Flnum echo expand('') ! 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('')) ! call assert_match(expected , expand('')) " Call in script-local function ! call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.\d\+_expand_sfile$', s:expand_sfile()) " Call in command command Sfile echo expand('') ! call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$', trim(execute('Sfile'))) delcommand Sfile + + " Use from sourced script. + let lines =<< trim END + let g:stack_value = expand('') + END + call writefile(lines, 'Xstack') + source Xstack + call assert_match('\'))) - - " Line-continuation - call assert_equal( - \ 55, - \ str2nr(expand(''))) - - " Call in script-local function - call assert_equal(16, s:expand_sflnum()) - - " Call in command - command Flnum echo expand('') - call assert_equal(64, str2nr(trim(execute('Flnum')))) - delcommand Flnum - endfunc - func Test_expand() new call assert_equal("", expand('%:S')) --- 77,82 ---- *** ../vim-8.2.1296/src/version.c 2020-07-26 13:27:12.417186380 +0200 --- src/version.c 2020-07-26 15:34:56.231517835 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1297, /**/ -- From "know your smileys": :~) A man with a tape recorder up his nose /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///