]> granicus.if.org Git - vim/commitdiff
patch 8.2.3019: location list only has the start position. v8.2.3019
authorthinca <thinca@gmail.com>
Sat, 19 Jun 2021 18:45:20 +0000 (20:45 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 19 Jun 2021 18:45:20 +0000 (20:45 +0200)
Problem:    Location list only has the start position.
Solution:   Make it possible to add an end position. (Shane-XB-Qian,
            closes #8393)

runtime/doc/eval.txt
src/quickfix.c
src/testdir/dumps/Test_quickfix_cwindow_1.dump
src/testdir/dumps/Test_quickfix_cwindow_2.dump
src/testdir/test_quickfix.vim
src/testdir/test_tagjump.vim
src/testdir/test_vim9_expr.vim
src/version.c

index fdc63eaa3dd2525a0e92886979c3fe165f7178c7..dd2d24232a94514b9e71739163ff04ee0923cc1d 100644 (file)
@@ -5841,7 +5841,10 @@ getqflist([{what}])                                      *getqflist()*
                                bufname() to get the name
                        module  module name
                        lnum    line number in the buffer (first line is 1)
+                       end_lnum
+                               end of line number if the item is multiline
                        col     column number (first column is 1)
+                       end_col end of column number if the item has range
                        vcol    |TRUE|: "col" is visual column
                                |FALSE|: "col" is byte index
                        nr      error number
index 4974cb47907bacdf379f4a6415acfdbb2feab948..36574b80f792a15d0588d462f0c2c36aeb01ef0b 100644 (file)
@@ -30,13 +30,16 @@ struct qfline_S
     qfline_T   *qf_next;       // pointer to next error in the list
     qfline_T   *qf_prev;       // pointer to previous error in the list
     linenr_T   qf_lnum;        // line number where the error occurred
+    linenr_T   qf_end_lnum;    // line number when the error has range or zero
     int                qf_fnum;        // file number for the line
     int                qf_col;         // column where the error occurred
+    int                qf_end_col;     // column when the error has range or zero
     int                qf_nr;          // error number
     char_u     *qf_module;     // module name for this error
     char_u     *qf_pattern;    // search pattern for the error
     char_u     *qf_text;       // description of the error
-    char_u     qf_viscol;      // set to TRUE if qf_col is screen column
+    char_u     qf_viscol;      // set to TRUE if qf_col and qf_end_col is
+                               // screen column
     char_u     qf_cleared;     // set to TRUE if line has been deleted
     char_u     qf_type;        // type of the error (mostly 'E'); 1 for
                                // :helpgrep
@@ -165,7 +168,7 @@ static efm_T        *fmt_start = NULL; // cached across qf_parse_line() calls
 static callback_T qftf_cb;
 
 static void    qf_new_list(qf_info_T *qi, char_u *qf_title);
-static int     qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
+static int     qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, long end_lnum, int col, int end_col, int vis_col, char_u *pattern, int nr, int type, int valid);
 static void    qf_free(qf_list_T *qfl);
 static char_u  *qf_types(int, int);
 static int     qf_get_fnum(qf_list_T *qfl, char_u *, char_u *);
@@ -174,6 +177,7 @@ static char_u       *qf_pop_dir(struct dir_stack_T **);
 static char_u  *qf_guess_filepath(qf_list_T *qfl, char_u *);
 static void    qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, int newwin);
 static void    qf_fmt_text(char_u *text, char_u *buf, int bufsize);
+static void    qf_range_text(qfline_T *qfp, char_u *buf, int bufsize);
 static int     qf_win_pos_update(qf_info_T *qi, int old_qf_index);
 static win_T   *qf_find_win(qf_info_T *qi);
 static buf_T   *qf_find_buf(qf_info_T *qi);
@@ -899,7 +903,9 @@ typedef struct {
     char_u     *errmsg;
     int                errmsglen;
     long       lnum;
+    long       end_lnum;
     int                col;
+    int                end_col;
     char_u     use_viscol;
     char_u     *pattern;
     int                enr;
@@ -1235,7 +1241,9 @@ qf_parse_get_fields(
     if (!qf_multiscan)
        fields->errmsg[0] = NUL;
     fields->lnum = 0;
+    fields->end_lnum = 0;
     fields->col = 0;
+    fields->end_col = 0;
     fields->use_viscol = FALSE;
     fields->enr = -1;
     fields->type = 0;
@@ -1630,7 +1638,9 @@ qf_init_process_nextline(
                0,
                fields->errmsg,
                fields->lnum,
+               fields->end_lnum,
                fields->col,
+               fields->end_col,
                fields->use_viscol,
                fields->pattern,
                fields->enr,
@@ -2053,7 +2063,9 @@ qf_add_entry(
     int                bufnum,         // buffer number or zero
     char_u     *mesg,          // message
     long       lnum,           // line number
+    long       end_lnum,       // line number for end
     int                col,            // column
+    int                end_col,        // column for end
     int                vis_col,        // using visual column
     char_u     *pattern,       // search pattern
     int                nr,             // error number
@@ -2082,7 +2094,9 @@ qf_add_entry(
        return QF_FAIL;
     }
     qfp->qf_lnum = lnum;
+    qfp->qf_end_lnum = end_lnum;
     qfp->qf_col = col;
+    qfp->qf_end_col = end_col;
     qfp->qf_viscol = vis_col;
     if (pattern == NULL || *pattern == NUL)
        qfp->qf_pattern = NULL;
@@ -2239,7 +2253,9 @@ copy_loclist_entries(qf_list_T *from_qfl, qf_list_T *to_qfl)
                    0,
                    from_qfp->qf_text,
                    from_qfp->qf_lnum,
+                   from_qfp->qf_end_lnum,
                    from_qfp->qf_col,
+                   from_qfp->qf_end_col,
                    from_qfp->qf_viscol,
                    from_qfp->qf_pattern,
                    from_qfp->qf_nr,
@@ -3555,11 +3571,8 @@ qf_list_entry(qfline_T *qfp, int qf_idx, int cursel)
        msg_puts_attr(":", qfSepAttr);
     if (qfp->qf_lnum == 0)
        IObuff[0] = NUL;
-    else if (qfp->qf_col == 0)
-       sprintf((char *)IObuff, "%ld", qfp->qf_lnum);
     else
-       sprintf((char *)IObuff, "%ld col %d",
-               qfp->qf_lnum, qfp->qf_col);
+       qf_range_text(qfp, IObuff, IOSIZE);
     sprintf((char *)IObuff + STRLEN(IObuff), "%s",
            (char *)qf_types(qfp->qf_type, qfp->qf_nr));
     msg_puts_attr((char *)IObuff, qfLineAttr);
@@ -3685,6 +3698,37 @@ qf_fmt_text(char_u *text, char_u *buf, int bufsize)
     buf[i] = NUL;
 }
 
+/*
+ * Range information from lnum, col, end_lnum, and end_col.
+ * Put the result in "buf[bufsize]".
+ */
+    static void
+qf_range_text(qfline_T *qfp, char_u *buf, int bufsize)
+{
+    int len;
+    vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum);
+    len = (int)STRLEN(buf);
+
+    if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum)
+    {
+       vim_snprintf((char *)buf + len, bufsize - len,
+               "-%ld", qfp->qf_end_lnum);
+       len += (int)STRLEN(buf + len);
+    }
+    if (qfp->qf_col > 0)
+    {
+       vim_snprintf((char *)buf + len, bufsize - len, " col %d", qfp->qf_col);
+       len += (int)STRLEN(buf + len);
+       if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col)
+       {
+           vim_snprintf((char *)buf + len, bufsize - len,
+                   "-%d", qfp->qf_end_col);
+           len += (int)STRLEN(buf + len);
+       }
+    }
+    buf[len] = NUL;
+}
+
 /*
  * Display information (list number, list size and the title) about a
  * quickfix/location list.
@@ -4565,17 +4609,9 @@ qf_buf_add_line(
 
        if (qfp->qf_lnum > 0)
        {
-           vim_snprintf((char *)IObuff + len, IOSIZE - len, "%ld",
-                   qfp->qf_lnum);
+           qf_range_text(qfp, IObuff + len, IOSIZE - len);
            len += (int)STRLEN(IObuff + len);
 
-           if (qfp->qf_col > 0)
-           {
-               vim_snprintf((char *)IObuff + len, IOSIZE - len,
-                       " col %d", qfp->qf_col);
-               len += (int)STRLEN(IObuff + len);
-           }
-
            vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s",
                    (char *)qf_types(qfp->qf_type, qfp->qf_nr));
            len += (int)STRLEN(IObuff + len);
@@ -5953,7 +5989,9 @@ vgr_match_buflines(
                            ml_get_buf(buf,
                                regmatch->startpos[0].lnum + lnum, FALSE),
                            regmatch->startpos[0].lnum + lnum,
+                           regmatch->endpos[0].lnum + lnum,
                            regmatch->startpos[0].col + 1,
+                           regmatch->endpos[0].col + 1,
                            FALSE,      // vis_col
                            NULL,       // search pattern
                            0,          // nr
@@ -5996,7 +6034,9 @@ vgr_match_buflines(
                            duplicate_name ? 0 : buf->b_fnum,
                            str,
                            lnum,
+                           0,
                            matches[0] + col + 1,
+                           0,
                            FALSE,      // vis_col
                            NULL,       // search pattern
                            0,          // nr
@@ -6626,10 +6666,12 @@ get_qfline_items(qfline_T *qfp, list_T *list)
     buf[0] = qfp->qf_type;
     buf[1] = NUL;
     if (dict_add_number(dict, "bufnr", (long)bufnum) == FAIL
-           || dict_add_number(dict, "lnum",  (long)qfp->qf_lnum) == FAIL
-           || dict_add_number(dict, "col",   (long)qfp->qf_col) == FAIL
-           || dict_add_number(dict, "vcol",  (long)qfp->qf_viscol) == FAIL
-           || dict_add_number(dict, "nr",    (long)qfp->qf_nr) == FAIL
+           || dict_add_number(dict, "lnum",     (long)qfp->qf_lnum) == FAIL
+           || dict_add_number(dict, "end_lnum", (long)qfp->qf_end_lnum) == FAIL
+           || dict_add_number(dict, "col",      (long)qfp->qf_col) == FAIL
+           || dict_add_number(dict, "end_col",  (long)qfp->qf_end_col) == FAIL
+           || dict_add_number(dict, "vcol",     (long)qfp->qf_viscol) == FAIL
+           || dict_add_number(dict, "nr",       (long)qfp->qf_nr) == FAIL
            || dict_add_string(dict, "module", qfp->qf_module) == FAIL
            || dict_add_string(dict, "pattern", qfp->qf_pattern) == FAIL
            || dict_add_string(dict, "text", qfp->qf_text) == FAIL
@@ -7143,8 +7185,8 @@ qf_add_entry_from_dict(
 {
     static int did_bufnr_emsg;
     char_u     *filename, *module, *pattern, *text, *type;
-    int                bufnum, valid, status, col, vcol, nr;
-    long       lnum;
+    int                bufnum, valid, status, col, end_col, vcol, nr;
+    long       lnum, end_lnum;
 
     if (first_entry)
        did_bufnr_emsg = FALSE;
@@ -7153,7 +7195,9 @@ qf_add_entry_from_dict(
     module = dict_get_string(d, (char_u *)"module", TRUE);
     bufnum = (int)dict_get_number(d, (char_u *)"bufnr");
     lnum = (int)dict_get_number(d, (char_u *)"lnum");
+    end_lnum = (int)dict_get_number(d, (char_u *)"end_lnum");
     col = (int)dict_get_number(d, (char_u *)"col");
+    end_col = (int)dict_get_number(d, (char_u *)"end_col");
     vcol = (int)dict_get_number(d, (char_u *)"vcol");
     nr = (int)dict_get_number(d, (char_u *)"nr");
     type = dict_get_string(d, (char_u *)"type", TRUE);
@@ -7190,7 +7234,9 @@ qf_add_entry_from_dict(
                        bufnum,
                        text,
                        lnum,
+                       end_lnum,
                        col,
+                       end_col,
                        vcol,           // vis_col
                        pattern,        // search pattern
                        nr,
@@ -8058,8 +8104,11 @@ hgr_search_file(
                        0,
                        line,
                        lnum,
+                       0,
                        (int)(p_regmatch->startp[0] - line)
                        + 1,    // col
+                       (int)(p_regmatch->endp[0] - line)
+                       + 1,    // end_col
                        FALSE,  // vis_col
                        NULL,   // search pattern
                        0,      // nr
index ef153f9089fc3d222d35236e5b3cbcc4caabac06..c2b487232efe8c33b7b9b176851d38ed9ba67aa1 100644 (file)
@@ -4,9 +4,9 @@
 |m|a|t|c|h|e|s| @67
 |~+0#4040ff13&| @73
 |X+1#0000000&|C|w|i|n|d|o|w| @48|1|,|4| @11|A|l@1
->X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4||+0#0000000&| |s|o|m|e| @52
-|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2||+0#0000000&| |t|e|x|t| @52
-|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6||+0#0000000&| |m|a|t|c|h|e|s| @49
+>X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4|-|5||+0#0000000&| |s|o|m|e| @50
+|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2|-|3||+0#0000000&| |t|e|x|t| @50
+|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6|-|7||+0#0000000&| |m|a|t|c|h|e|s| @47
 |~+0#4040ff13&| @73
 |[+3#0000000&|Q|u|i|c|k|f|i|x| |L|i|s|t|]| |:|v|i|m|g|r|e|p| |e| |X|C|w|i|n|d|o|w| @20|1|,|1| @12|A|l@1
 | +0&&@74
index 4c87ca053f4ac25856481fc2a5ad23273fe9c45e..0e7fa3c9ee9f46af3ff05baf76c3a080ea9c94b3 100644 (file)
@@ -4,9 +4,9 @@
 |m|a|t|c|h|e|s| @67
 |~+0#4040ff13&| @73
 |X+3#0000000&|C|w|i|n|d|o|w| @48|2|,|2| @11|A|l@1
-|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4||+0#0000000&| |s|o|m|e| @52
-|X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2||+0#0000000&| |t|e|x|t| @52
-|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6||+0#0000000&| |m|a|t|c|h|e|s| @49
+|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4|-|5||+0#0000000&| |s|o|m|e| @50
+|X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2|-|3||+0#0000000&| |t|e|x|t| @50
+|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6|-|7||+0#0000000&| |m|a|t|c|h|e|s| @47
 |~+0#4040ff13&| @73
 |[+1#0000000&|Q|u|i|c|k|f|i|x| |L|i|s|t|]| |:|v|i|m|g|r|e|p| |e| |X|C|w|i|n|d|o|w| @20|2|,|1| @12|A|l@1
 |:+0&&|c|n|e|x|t| @68
index 263dbbd6e242482a1c56ed836f646607fe9fbe0f..e82ce683eceb156d38e4524fc92d568b520626df 100644 (file)
@@ -134,6 +134,21 @@ func XlistTests(cchar)
   call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
                   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
 
+  " Ranged entries
+  call g:Xsetlist([{'lnum':10,'text':'Line1'},
+             \ {'lnum':20,'col':10,'text':'Line2'},
+             \ {'lnum':30,'col':15,'end_col':20,'text':'Line3'},
+             \ {'lnum':40,'end_lnum':45,'text':'Line4'},
+             \ {'lnum':50,'end_lnum':55,'col':15,'text':'Line5'},
+             \ {'lnum':60,'end_lnum':65,'col':25,'end_col':35,'text':'Line6'}])
+  let l = split(execute('Xlist', ""), "\n")
+  call assert_equal([' 1:10: Line1',
+             \ ' 2:20 col 10: Line2',
+             \ ' 3:30 col 15-20: Line3',
+             \ ' 4:40-45: Line4',
+             \ ' 5:50-55 col 15: Line5',
+             \ ' 6:60-65 col 25-35: Line6'], l)
+
   " Different types of errors
   call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
              \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
@@ -644,6 +659,7 @@ func s:test_xhelpgrep(cchar)
   call assert_true(&buftype == 'help')
   call assert_true(winnr() == 1)
   call assert_true(winnr('$') == 2)
+  call assert_match('|\d\+ col \d\+-\d\+|', getbufline(winbufnr(2), 1)[0])
 
   " This wipes out the buffer, make sure that doesn't cause trouble.
   Xclose
@@ -1514,10 +1530,13 @@ func SetXlistTests(cchar, bnum)
   call s:setup_commands(a:cchar)
 
   call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
-             \  {'bufnr': a:bnum, 'lnum': 2}])
+             \  {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5}])
   let l = g:Xgetlist()
   call assert_equal(2, len(l))
   call assert_equal(2, l[1].lnum)
+  call assert_equal(3, l[1].end_lnum)
+  call assert_equal(4, l[1].col)
+  call assert_equal(5, l[1].end_col)
 
   Xnext
   call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
@@ -2852,7 +2871,9 @@ func XvimgrepTests(cchar)
   let l = g:Xgetlist()
   call assert_equal(2, len(l))
   call assert_equal(8, l[0].col)
+  call assert_equal(11, l[0].end_col)
   call assert_equal(12, l[1].col)
+  call assert_equal(15, l[1].end_col)
 
   1Xvimgrep ?Editor? Xtestfile*
   let l = g:Xgetlist()
@@ -5098,15 +5119,21 @@ func Xtest_qftextfunc(cchar)
   call assert_equal('Tqfexpr', &quickfixtextfunc)
   call assert_equal('',
         \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
-  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
+  call g:Xsetlist([
+        \ { 'filename': 'F1', 'lnum': 10, 'col': 2,
+        \   'end_col': 7, 'text': 'green'},
+        \ { 'filename': 'F1', 'lnum': 20, 'end_lnum': 25, 'col': 4,
+        \   'end_col': 8, 'text': 'blue'},
+        \ ])
+
   Xwindow
   call assert_equal('F1-L10C2-green', getline(1))
   call assert_equal('F1-L20C4-blue', getline(2))
   Xclose
   set quickfixtextfunc&vim
   Xwindow
-  call assert_equal('F1|10 col 2| green', getline(1))
-  call assert_equal('F1|20 col 4| blue', getline(2))
+  call assert_equal('F1|10 col 2-7| green', getline(1))
+  call assert_equal('F1|20-25 col 4-8| blue', getline(2))
   Xclose
   set efm&
   set quickfixtextfunc&
@@ -5339,7 +5366,7 @@ func Test_add_invalid_entry_with_qf_window()
   call setqflist(['bb'], 'a')
   call assert_equal(1, line('$'))
   call assert_equal(['Xfile1|10| aa'], getline(1, '$'))
-  call assert_equal([{'lnum': 10, 'bufnr': bufnr('Xfile1'), 'col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'aa'}], getqflist())
+  call assert_equal([{'lnum': 10, 'end_lnum': 0, 'bufnr': bufnr('Xfile1'), 'col': 0, 'end_col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'aa'}], getqflist())
   cclose
 endfunc
 
index c789dc9615a794ba1caba8774cb5a84749aadbfb..92af0d0b0fbbd1ed8d425a5f64d52c3ab5b74168 100644 (file)
@@ -837,15 +837,16 @@ func Test_ltag()
   ltag third
   call assert_equal('Xfoo', bufname(''))
   call assert_equal(3, line('.'))
-  call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0,
-        \ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '',
-        \ 'module': '', 'text': 'third'}], getloclist(0))
+  call assert_equal([{'lnum': 3, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'),
+        \ 'col': 0, 'end_col': 0, 'pattern': '', 'valid': 1, 'vcol': 0,
+        \ 'nr': 0, 'type': '', 'module': '', 'text': 'third'}], getloclist(0))
 
   ltag second
   call assert_equal(2, line('.'))
-  call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0,
-        \ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0,
-        \ 'type': '', 'module': '', 'text': 'second'}], getloclist(0))
+  call assert_equal([{'lnum': 0, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'),
+        \ 'col': 0, 'end_col': 0, 'pattern': '^\Vint second() {}\$',
+        \ 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'module': '',
+        \ 'text': 'second'}], getloclist(0))
 
   call delete('Xtags')
   call delete('Xfoo')
index 974ca8548b78c3841c3644d5ef0ba3b842de2c23..9170cc9563e823a7b93f44ba4ced99416705e289 100644 (file)
@@ -2943,7 +2943,9 @@ def Test_expr7_method_call()
       loclist->setloclist(0)
       assert_equal([{bufnr: bufnr,
                     lnum: 42,
+                    end_lnum: 0,
                     col: 17,
+                    end_col: 0,
                     text: 'wrong',
                     pattern: '',
                     valid: 1,
index 347074a1f5668ebd29d1e35a715c51e38f87a79a..adde02e851a6ea202ba10363f138173d24fedbfe 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3019,
 /**/
     3018,
 /**/