]> granicus.if.org Git - vim/commitdiff
patch 8.1.1625: script line numbers are not exactly right v8.1.1625
authorBram Moolenaar <Bram@vim.org>
Thu, 4 Jul 2019 12:57:12 +0000 (14:57 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 4 Jul 2019 12:57:12 +0000 (14:57 +0200)
Problem:    Script line numbers are not exactly right.
Solution:   Handle heredoc and continuation lines better. (Ozaki Kiichi,
            closes #4611, closes #4511)

src/ex_cmds2.c
src/proto/ex_cmds2.pro
src/testdir/test_vimscript.vim
src/userfunc.c
src/version.c

index 036a2a73523e163d61529885dd4d1420c61f2a6d..fb26b2aa4fe9d74af240fd629fcb1a2e614349cd 100644 (file)
@@ -3269,20 +3269,21 @@ cmd_source(char_u *fname, exarg_T *eap)
  */
 struct source_cookie
 {
-    FILE       *fp;            /* opened file for sourcing */
-    char_u      *nextline;      /* if not NULL: line that was read ahead */
-    int                finished;       /* ":finish" used */
+    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 */
+    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 */
+    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 */
+    vimconv_T  conv;           // type of conversion
 };
 
 #ifdef FEAT_EVAL
@@ -3346,7 +3347,6 @@ fopen_noinh_readbin(char *filename)
 }
 #endif
 
-
 /*
  * do_source: Read the file "fname" and execute its lines as EX commands.
  *
@@ -3495,6 +3495,7 @@ do_source(
 #endif
 
     cookie.nextline = NULL;
+    cookie.sourcing_lnum = 0;
     cookie.finished = FALSE;
 
 #ifdef FEAT_EVAL
@@ -3790,6 +3791,14 @@ free_scriptnames(void)
 
 #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,6 +3825,10 @@ getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat)
        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,7 +3841,7 @@ getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat)
     {
        line = sp->nextline;
        sp->nextline = NULL;
-       ++sourcing_lnum;
+       ++sp->sourcing_lnum;
     }
 #ifdef FEAT_PROFILE
     if (line != NULL && do_profiling == PROF_YES)
@@ -3840,7 +3853,7 @@ getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat)
     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
@@ -3931,7 +3944,7 @@ get_one_sourceline(struct source_cookie *sp)
     /*
      * 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 */
@@ -4001,7 +4014,7 @@ get_one_sourceline(struct source_cookie *sp)
                ;
            if ((len & 1) != (c & 1))   /* escaped NL, read more */
            {
-               sourcing_lnum++;
+               ++sp->sourcing_lnum;
                continue;
            }
 
index 0d249cb9a70f77db6bda03a46df1f26a6d67801e..c12e0d7308f0110dd51393968e820a55cd70cd0a 100644 (file)
@@ -81,6 +81,7 @@ void ex_scriptnames(exarg_T *eap);
 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);
index bf3e052ec950b77cb7d31b06ef7d0c6e43808cde..501a57ba1257a12593667030b8a0fafda3067119 100644 (file)
@@ -1676,6 +1676,76 @@ func Test_funccall_garbage_collect()
     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
index 864c816f24ecece623d0473b5af89e069e2462f0..6bfe534a9e4161d41bbf721b98c06fb2d9dcc485 100644 (file)
@@ -2008,7 +2008,8 @@ ex_function(exarg_T *eap)
     int                todo;
     hashitem_T *hi;
     int                do_concat = TRUE;
-    int                sourcing_lnum_off;
+    linenr_T   sourcing_lnum_off;
+    linenr_T   sourcing_lnum_top;
 
     /*
      * ":function" without argument: list functions.
@@ -2275,6 +2276,9 @@ ex_function(exarg_T *eap)
        cmdline_row = msg_row;
     }
 
+    // Save the starting line number.
+    sourcing_lnum_top = sourcing_lnum;
+
     indent = 2;
     nesting = 0;
     for (;;)
@@ -2285,7 +2289,6 @@ ex_function(exarg_T *eap)
            saved_wait_return = FALSE;
        }
        need_wait_return = FALSE;
-       sourcing_lnum_off = sourcing_lnum;
 
        if (line_arg != NULL)
        {
@@ -2318,8 +2321,9 @@ ex_function(exarg_T *eap)
        }
 
        /* 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;
+       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,7 +2674,7 @@ 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:
index 50c333c5bff663989ff92abec49e16f641ba55d2..157e9ece256eb9b967efa0ef71094a333a76afe0 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1625,
 /**/
     1624,
 /**/