Patch 8.1.1625
Problem: Script line numbers are not exactly right.
Solution: Handle heredoc and continuation lines better. (Ozaki Kiichi,
closes #4611, closes #4511)
Files: src/ex_cmds2.c, src/proto/
ex_cmds2.pro,
src/testdir/test_vimscript.vim, src/userfunc.c
*** ../vim-8.1.1624/src/ex_cmds2.c 2019-06-25 06:27:57.537385321 +0200
--- src/ex_cmds2.c 2019-07-04 14:44:06.668255705 +0200
***************
*** 3269,3288 ****
*/
struct source_cookie
{
! FILE *fp; /* opened file for sourcing */
! char_u *nextline; /* if not NULL: line that was read ahead */
! int finished; /* ":finish" used */
#ifdef USE_CRNL
! int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
! int error; /* TRUE if LF found after CR-LF */
#endif
#ifdef FEAT_EVAL
! linenr_T breakpoint; /* next line with breakpoint or zero */
! char_u *fname; /* name of sourced file */
! int dbg_tick; /* debug_tick when breakpoint was set */
! int level; /* top nesting level of sourced file */
#endif
! vimconv_T conv; /* type of conversion */
};
#ifdef FEAT_EVAL
--- 3269,3289 ----
*/
struct source_cookie
{
! FILE *fp; // opened file for sourcing
! char_u *nextline; // if not NULL: line that was read ahead
! linenr_T sourcing_lnum; // line number of the source file
! int finished; // ":finish" used
#ifdef USE_CRNL
! int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS
! int error; // TRUE if LF found after CR-LF
#endif
#ifdef FEAT_EVAL
! linenr_T breakpoint; // next line with breakpoint or zero
! char_u *fname; // name of sourced file
! int dbg_tick; // debug_tick when breakpoint was set
! int level; // top nesting level of sourced file
#endif
! vimconv_T conv; // type of conversion
};
#ifdef FEAT_EVAL
***************
*** 3346,3352 ****
}
#endif
-
/*
* do_source: Read the file "fname" and execute its lines as EX commands.
*
--- 3347,3352 ----
***************
*** 3495,3500 ****
--- 3495,3501 ----
#endif
cookie.nextline = NULL;
+ cookie.sourcing_lnum = 0;
cookie.finished = FALSE;
#ifdef FEAT_EVAL
***************
*** 3790,3795 ****
--- 3791,3804 ----
#endif
+ linenr_T
+ get_sourced_lnum(char_u *(*fgetline)(int, void *, int, int), void *cookie)
+ {
+ return fgetline == getsourceline
+ ? ((struct source_cookie *)cookie)->sourcing_lnum
+ : sourcing_lnum;
+ }
+
/*
* Get one full line from a sourced file.
* Called by do_cmdline() when it's called from do_source().
***************
*** 3816,3821 ****
--- 3825,3834 ----
script_line_end();
# endif
#endif
+
+ // Set the current sourcing line number.
+ sourcing_lnum = sp->sourcing_lnum + 1;
+
/*
* Get current line. If there is a read-ahead line, use it, otherwise get
* one now.
***************
*** 3828,3834 ****
{
line = sp->nextline;
sp->nextline = NULL;
! ++sourcing_lnum;
}
#ifdef FEAT_PROFILE
if (line != NULL && do_profiling == PROF_YES)
--- 3841,3847 ----
{
line = sp->nextline;
sp->nextline = NULL;
! ++sp->sourcing_lnum;
}
#ifdef FEAT_PROFILE
if (line != NULL && do_profiling == PROF_YES)
***************
*** 3840,3846 ****
if (line != NULL && do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL)
{
/* compensate for the one line read-ahead */
! --sourcing_lnum;
// Get the next line and concatenate it when it starts with a
// backslash. We always need to read the next line, keep it in
--- 3853,3859 ----
if (line != NULL && do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL)
{
/* compensate for the one line read-ahead */
! --sp->sourcing_lnum;
// Get the next line and concatenate it when it starts with a
// backslash. We always need to read the next line, keep it in
***************
*** 3931,3937 ****
/*
* Loop until there is a finished line (or end-of-file).
*/
! sourcing_lnum++;
for (;;)
{
/* make room to read at least 120 (more) characters */
--- 3944,3950 ----
/*
* Loop until there is a finished line (or end-of-file).
*/
! ++sp->sourcing_lnum;
for (;;)
{
/* make room to read at least 120 (more) characters */
***************
*** 4001,4007 ****
;
if ((len & 1) != (c & 1)) /* escaped NL, read more */
{
! sourcing_lnum++;
continue;
}
--- 4014,4020 ----
;
if ((len & 1) != (c & 1)) /* escaped NL, read more */
{
! ++sp->sourcing_lnum;
continue;
}
*** ../vim-8.1.1624/src/proto/
ex_cmds2.pro 2019-06-25 04:12:12.312665250 +0200
--- src/proto/
ex_cmds2.pro 2019-07-04 14:44:22.440165162 +0200
***************
*** 81,86 ****
--- 81,87 ----
void scriptnames_slash_adjust(void);
char_u *get_scriptname(scid_T id);
void free_scriptnames(void);
+ linenr_T get_sourced_lnum(char_u *(*fgetline)(int, void *, int, int), void *cookie);
char_u *getsourceline(int c, void *cookie, int indent, int do_concat);
void script_line_start(void);
void script_line_exec(void);
*** ../vim-8.1.1624/src/testdir/test_vimscript.vim 2019-06-25 06:27:57.537385321 +0200
--- src/testdir/test_vimscript.vim 2019-07-04 14:40:09.613616459 +0200
***************
*** 1676,1681 ****
--- 1676,1751 ----
delfunc Func
endfunc
+ func Test_function_defined_line()
+ if has('gui_running')
+ " Can't catch the output of gvim.
+ return
+ endif
+
+ let lines =<< trim [CODE]
+ " F1
+ func F1()
+ " F2
+ func F2()
+ "
+ "
+ "
+ return
+ endfunc
+ " F3
+ execute "func F3()\n\n\n\nreturn\nendfunc"
+ " F4
+ execute "func F4()\n
+ \\n
+ \\n
+ \\n
+ \return\n
+ \endfunc"
+ endfunc
+ " F5
+ execute "func F5()\n\n\n\nreturn\nendfunc"
+ " F6
+ execute "func F6()\n
+ \\n
+ \\n
+ \\n
+ \return\n
+ \endfunc"
+ call F1()
+ verbose func F1
+ verbose func F2
+ verbose func F3
+ verbose func F4
+ verbose func F5
+ verbose func F6
+ qall!
+ [CODE]
+
+ call writefile(lines, 'Xtest.vim')
+ let res = system(v:progpath .. ' --clean -es -X -S Xtest.vim')
+ call assert_equal(0, v:shell_error)
+
+ let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 2$', m)
+
+ let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 4$', m)
+
+ let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 11$', m)
+
+ let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 13$', m)
+
+ let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 21$', m)
+
+ let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
+ call assert_match(' line 23$', m)
+
+ call delete('Xtest.vim')
+ endfunc
+
"-------------------------------------------------------------------------------
" Modelines {{{1
" vim: ts=8 sw=4 tw=80 fdm=marker
*** ../vim-8.1.1624/src/userfunc.c 2019-06-25 04:12:12.312665250 +0200
--- src/userfunc.c 2019-07-04 14:40:09.613616459 +0200
***************
*** 2008,2014 ****
int todo;
hashitem_T *hi;
int do_concat = TRUE;
! int sourcing_lnum_off;
/*
* ":function" without argument: list functions.
--- 2008,2015 ----
int todo;
hashitem_T *hi;
int do_concat = TRUE;
! linenr_T sourcing_lnum_off;
! linenr_T sourcing_lnum_top;
/*
* ":function" without argument: list functions.
***************
*** 2275,2280 ****
--- 2276,2284 ----
cmdline_row = msg_row;
}
+ // Save the starting line number.
+ sourcing_lnum_top = sourcing_lnum;
+
indent = 2;
nesting = 0;
for (;;)
***************
*** 2285,2291 ****
saved_wait_return = FALSE;
}
need_wait_return = FALSE;
- sourcing_lnum_off = sourcing_lnum;
if (line_arg != NULL)
{
--- 2289,2294 ----
***************
*** 2318,2325 ****
}
/* Detect line continuation: sourcing_lnum increased more than one. */
! if (sourcing_lnum > sourcing_lnum_off + 1)
! sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1;
else
sourcing_lnum_off = 0;
--- 2321,2329 ----
}
/* Detect line continuation: sourcing_lnum increased more than one. */
! sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie);
! if (sourcing_lnum < sourcing_lnum_off)
! sourcing_lnum_off -= sourcing_lnum;
else
sourcing_lnum_off = 0;
***************
*** 2670,2676 ****
fp->uf_flags = flags;
fp->uf_calls = 0;
fp->uf_script_ctx = current_sctx;
! fp->uf_script_ctx.sc_lnum += sourcing_lnum - newlines.ga_len - 1;
goto ret_free;
erret:
--- 2674,2680 ----
fp->uf_flags = flags;
fp->uf_calls = 0;
fp->uf_script_ctx = current_sctx;
! fp->uf_script_ctx.sc_lnum += sourcing_lnum_top;
goto ret_free;
erret:
*** ../vim-8.1.1624/src/version.c 2019-07-04 14:20:38.180325318 +0200
--- src/version.c 2019-07-04 14:41:39.325101527 +0200
***************
*** 779,780 ****
--- 779,782 ----
{ /* Add new patch number below this line */
+ /**/
+ 1625,
/**/
--
Q: Why do ducks have flat feet?
A: To stamp out forest fires.
Q: Why do elephants have flat feet?
A: To stamp out flaming ducks.
/// Bram Moolenaar -- Br...@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 ///