aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJurica Bradaric <jbradaric@gmail.com>2019-10-12 22:49:21 +0200
committerJurica Bradaric <jbradaric@gmail.com>2019-10-13 11:54:54 +0200
commitfcc24d0df3b1a6bde82c0e5b90f1392639f3fa5b (patch)
tree13c3617776f09c6e1fa8f6dc74c18925d1a0c6e3
parent6c012b0624935b93e92a0b12d86d49ef695210ba (diff)
downloadrneovim-fcc24d0df3b1a6bde82c0e5b90f1392639f3fa5b.tar.gz
rneovim-fcc24d0df3b1a6bde82c0e5b90f1392639f3fa5b.tar.bz2
rneovim-fcc24d0df3b1a6bde82c0e5b90f1392639f3fa5b.zip
vim-patch:8.1.1625: script line numbers are not exactly right
Problem: Script line numbers are not exactly right. Solution: Handle heredoc and continuation lines better. (Ozaki Kiichi, closes vim/vim#4611, closes vim/vim#4511) https://github.com/vim/vim/commit/bc2cfe4672d370330b8698d4d025697a9a6ec569
-rw-r--r--src/nvim/eval.c26
-rw-r--r--src/nvim/ex_cmds2.c21
-rw-r--r--src/nvim/testdir/test_vimscript.vim70
3 files changed, 102 insertions, 15 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index bedfe2d6d0..d314e3a732 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -21301,7 +21301,8 @@ void ex_function(exarg_T *eap)
hashtab_T *ht;
int todo;
hashitem_T *hi;
- int sourcing_lnum_off;
+ linenr_T sourcing_lnum_off;
+ linenr_T sourcing_lnum_top;
bool show_block = false;
bool do_concat = true;
@@ -21550,15 +21551,17 @@ void ex_function(exarg_T *eap)
cmdline_row = msg_row;
}
+ // Save the starting line number.
+ sourcing_lnum_top = sourcing_lnum;
+
indent = 2;
nesting = 0;
for (;; ) {
if (KeyTyped) {
- msg_scroll = TRUE;
- saved_wait_return = FALSE;
+ msg_scroll = true;
+ saved_wait_return = false;
}
- need_wait_return = FALSE;
- sourcing_lnum_off = sourcing_lnum;
+ need_wait_return = false;
if (line_arg != NULL) {
/* Use eap->arg, split up in parts by line breaks. */
@@ -21591,11 +21594,13 @@ void ex_function(exarg_T *eap)
ui_ext_cmdline_block_append((size_t)indent, (const char *)theline);
}
- /* 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
+ // 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;
+ }
if (skip_until != NULL) {
// Between ":append" and "." and between ":python <<EOF" and "EOF"
@@ -21896,7 +21901,8 @@ void ex_function(exarg_T *eap)
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;
+ fp->uf_script_ctx.sc_lnum += sourcing_lnum_top;
+
goto ret_free;
erret:
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 272c81e29b..84291b3637 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -97,10 +97,11 @@ typedef struct sn_prl_S {
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
#if defined(USE_CRNL)
int fileformat; ///< EOL_UNKNOWN, EOL_UNIX or EOL_DOS
- bool error; ///< true if LF found after CR-LF
+ bool error; ///< true if LF found after CR-LF
#endif
linenr_T breakpoint; ///< next line with breakpoint or zero
char_u *fname; ///< name of sourced file
@@ -3124,6 +3125,7 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
#endif
cookie.nextline = NULL;
+ cookie.sourcing_lnum = 0;
cookie.finished = false;
// Check if this script has a breakpoint.
@@ -3375,6 +3377,13 @@ void free_scriptnames(void)
}
# endif
+linenr_T get_sourced_lnum(LineGetter fgetline, 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().
@@ -3395,6 +3404,8 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat)
if (do_profiling == PROF_YES) {
script_line_end();
}
+ // 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.
if (sp->finished) {
@@ -3404,7 +3415,7 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat)
} else {
line = sp->nextline;
sp->nextline = NULL;
- sourcing_lnum++;
+ sp->sourcing_lnum++;
}
if (line != NULL && do_profiling == PROF_YES) {
script_line_start();
@@ -3414,7 +3425,7 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat)
// contain the 'C' flag.
if (line != NULL && do_concat && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) {
// compensate for the one line read-ahead
- sourcing_lnum--;
+ 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
@@ -3492,7 +3503,7 @@ static char_u *get_one_sourceline(struct source_cookie *sp)
ga_init(&ga, 1, 250);
// Loop until there is a finished line (or end-of-file).
- sourcing_lnum++;
+ sp->sourcing_lnum++;
for (;; ) {
// make room to read at least 120 (more) characters
ga_grow(&ga, 120);
@@ -3559,7 +3570,7 @@ retry:
// len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo
for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) {}
if ((len & 1) != (c & 1)) { // escaped NL, read more
- sourcing_lnum++;
+ sp->sourcing_lnum++;
continue;
}
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index f39e53d6dd..3fcba4134e 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1409,6 +1409,76 @@ func Test_compound_assignment_operators()
let @/ = ''
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