]> granicus.if.org Git - vim/commitdiff
patch 8.1.1489: sign order wrong when priority was changed v8.1.1489
authorBram Moolenaar <Bram@vim.org>
Fri, 7 Jun 2019 19:37:13 +0000 (21:37 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 7 Jun 2019 19:37:13 +0000 (21:37 +0200)
Problem:    Sign order wrong when priority was changed.
Solution:   Reorder signs when priority is changed. (Yegappan Lakshmanan,
            closes #4502)

src/quickfix.c
src/sign.c
src/testdir/test_signs.vim
src/version.c

index e237df0fa63b04281b9b145f8ed6b18a0fa7732c..290f6bcccc416184f1c10b08874a7652eaa1f44d 100644 (file)
@@ -5320,7 +5320,7 @@ qf_find_closest_entry(
  * the list. If linewise is TRUE, then treat multiple entries on a single line
  * as one.
  */
-    static qfline_T *
+    static void
 qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
 {
     while (n-- > 0 && !got_int)
@@ -5348,8 +5348,6 @@ qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
        entry = entry->qf_next;
        ++*errornr;
     }
-
-    return entry;
 }
 
 /*
@@ -5357,7 +5355,7 @@ qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
  * the list. If linewise is TRUE, then treat multiple entries on a single line
  * as one.
  */
-    static qfline_T *
+    static void
 qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
 {
     while (n-- > 0 && !got_int)
@@ -5373,8 +5371,6 @@ qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
        if (linewise)
            entry = qf_find_first_entry_on_line(entry, errornr);
     }
-
-    return entry;
 }
 
 /*
@@ -5403,11 +5399,9 @@ qf_find_nth_adj_entry(
     {
        // Go to the n'th entry in the current buffer
        if (dir == FORWARD)
-           adj_entry = qf_get_nth_below_entry(adj_entry, n, linewise,
-                   &errornr);
+           qf_get_nth_below_entry(adj_entry, n, linewise, &errornr);
        else
-           adj_entry = qf_get_nth_above_entry(adj_entry, n, linewise,
-                   &errornr);
+           qf_get_nth_above_entry(adj_entry, n, linewise, &errornr);
     }
 
     return errornr;
index 8f1de4af170590ad740fbfd5b80f0e855ec56730..e8288d628348f504e7be9d1cdb5226aacfe75634 100644 (file)
@@ -307,6 +307,78 @@ sign_get_info(signlist_T *sign)
     return d;
 }
 
+/*
+ * Sort the signs placed on the same line as "sign" by priority.  Invoked after
+ * changing the priority of an already placed sign.  Assumes the signs in the
+ * buffer are sorted by line number and priority.
+ */
+    static void
+sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign)
+{
+    signlist_T *p = NULL;
+
+    // If there is only one sign in the buffer or only one sign on the line or
+    // the sign is already sorted by priority, then return.
+    if ((sign->prev == NULL
+               || sign->prev->lnum != sign->lnum
+               || sign->prev->priority > sign->priority)
+           && (sign->next == NULL
+               || sign->next->lnum != sign->lnum
+               || sign->next->priority < sign->priority))
+       return;
+
+    // One or more signs on the same line as 'sign'
+    // Find a sign after which 'sign' should be inserted
+
+    // First search backward for a sign with higher priority on the same line
+    p = sign;
+    while (p->prev != NULL && p->prev->lnum == sign->lnum
+                                       && p->prev->priority <= sign->priority)
+       p = p->prev;
+
+    if (p == sign)
+    {
+       // Sign not found. Search forward for a sign with priority just before
+       // 'sign'.
+       p = sign->next;
+       while (p->next != NULL && p->next->lnum == sign->lnum
+                                        && p->next->priority > sign->priority)
+           p = p->next;
+    }
+
+    // Remove 'sign' from the list
+    if (buf->b_signlist == sign)
+       buf->b_signlist = sign->next;
+    if (sign->prev != NULL)
+       sign->prev->next = sign->next;
+    if (sign->next != NULL)
+       sign->next->prev = sign->prev;
+    sign->prev = NULL;
+    sign->next = NULL;
+
+    // Re-insert 'sign' at the right place
+    if (p->priority <= sign->priority)
+    {
+       // 'sign' has a higher priority and should be inserted before 'p'
+       sign->prev = p->prev;
+       sign->next = p;
+       p->prev = sign;
+       if (sign->prev != NULL)
+           sign->prev->next = sign;
+       if (buf->b_signlist == p)
+           buf->b_signlist = sign;
+    }
+    else
+    {
+       // 'sign' has a lower priority and should be inserted after 'p'
+       sign->prev = p;
+       sign->next = p->next;
+       p->next = sign;
+       if (sign->next != NULL)
+           sign->next->prev = sign;
+    }
+}
+
 /*
  * Add the sign into the signlist. Find the right spot to do it though.
  */
@@ -331,6 +403,7 @@ buf_addsign(
            // Update an existing sign
            sign->typenr = typenr;
            sign->priority = prio;
+           sign_sort_by_prio_on_line(buf, sign);
            return;
        }
        else if (lnum < sign->lnum)
index a986e122ddd3ff970700bcab332bafcecc24989c..8a6731cc410b478f64c8a2c1a2bf7e6d955b0352 100644 (file)
@@ -1183,6 +1183,301 @@ func Test_sign_priority()
              \ 'priority' : 10}],
              \ s[0].signs)
 
+  call sign_unplace('*')
+
+  " Three signs on different lines with changing priorities
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 11, 'priority' : 50})
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 12, 'priority' : 60})
+  call sign_place(3, '', 'sign3', 'Xsign',
+             \ {'lnum' : 13, 'priority' : 70})
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 12, 'priority' : 40})
+  call sign_place(3, '', 'sign3', 'Xsign',
+             \ {'lnum' : 13, 'priority' : 30})
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 11, 'priority' : 50})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '',
+             \ 'priority' : 50},
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '',
+             \ 'priority' : 40},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '',
+             \ 'priority' : 30}],
+             \ s[0].signs)
+
+  call sign_unplace('*')
+
+  " Two signs on the same line with changing priorities
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 20})
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 30})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20}],
+             \ s[0].signs)
+  " Change the priority of the last sign to highest
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 40})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 40},
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30}],
+             \ s[0].signs)
+  " Change the priority of the first sign to lowest
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 25})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 25}],
+             \ s[0].signs)
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 45})
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 55})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 55},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 45}],
+             \ s[0].signs)
+
+  call sign_unplace('*')
+
+  " Three signs on the same line with changing priorities
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 40})
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 30})
+  call sign_place(3, '', 'sign3', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 20})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 40},
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20}],
+             \ s[0].signs)
+
+  " Change the priority of the middle sign to the highest
+  call sign_place(2, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 50})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 50},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 40},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20}],
+             \ s[0].signs)
+
+  " Change the priority of the middle sign to the lowest
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 15})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 50},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 15}],
+             \ s[0].signs)
+
+  " Change the priority of the last sign to the highest
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 55})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 55},
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 50},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20}],
+             \ s[0].signs)
+
+  " Change the priority of the first sign to the lowest
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 15})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 50},
+             \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 15}],
+             \ s[0].signs)
+
+  call sign_unplace('*')
+
+  " Three signs on the same line with changing priorities along with other
+  " signs
+  call sign_place(1, '', 'sign1', 'Xsign',
+             \ {'lnum' : 2, 'priority' : 10})
+  call sign_place(2, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 30})
+  call sign_place(3, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 20})
+  call sign_place(4, '', 'sign3', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 25})
+  call sign_place(5, '', 'sign2', 'Xsign',
+             \ {'lnum' : 6, 'priority' : 80})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
+             \ 'priority' : 10},
+             \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 25},
+             \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
+             \ 'priority' : 80}],
+             \ s[0].signs)
+
+  " Change the priority of the first sign to lowest
+  call sign_place(2, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 15})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
+             \ 'priority' : 10},
+             \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 25},
+             \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 15},
+             \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
+             \ 'priority' : 80}],
+             \ s[0].signs)
+
+  " Change the priority of the last sign to highest
+  call sign_place(2, '', 'sign1', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 30})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
+             \ 'priority' : 10},
+             \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 25},
+             \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
+             \ 'priority' : 80}],
+             \ s[0].signs)
+
+  " Change the priority of the middle sign to lowest
+  call sign_place(4, '', 'sign3', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 15})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
+             \ 'priority' : 10},
+             \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 20},
+             \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 15},
+             \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
+             \ 'priority' : 80}],
+             \ s[0].signs)
+
+  " Change the priority of the middle sign to highest
+  call sign_place(3, '', 'sign2', 'Xsign',
+             \ {'lnum' : 4, 'priority' : 35})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+             \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
+             \ 'priority' : 10},
+             \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 35},
+             \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 30},
+             \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+             \ 'priority' : 15},
+             \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
+             \ 'priority' : 80}],
+             \ s[0].signs)
+
+  call sign_unplace('*')
+
+  " Multiple signs with the same priority on the same line
+  call sign_place(1, '', 'sign1', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  call sign_place(2, '', 'sign2', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  call sign_place(3, '', 'sign3', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20}],
+              \ s[0].signs)
+  " Place the last sign again with the same priority
+  call sign_place(1, '', 'sign1', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20}],
+              \ s[0].signs)
+  " Place the first sign again with the same priority
+  call sign_place(1, '', 'sign1', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20}],
+              \ s[0].signs)
+  " Place the middle sign again with the same priority
+  call sign_place(3, '', 'sign3', 'Xsign',
+              \ {'lnum' : 4, 'priority' : 20})
+  let s = sign_getplaced('Xsign', {'group' : '*'})
+  call assert_equal([
+              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20},
+              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
+              \ 'priority' : 20}],
+              \ s[0].signs)
+
+  call sign_unplace('*')
+
   " Place multiple signs with same id on a line with different priority
   call sign_place(1, '', 'sign1', 'Xsign',
              \ {'lnum' : 5, 'priority' : 20})
index 90ee2476a265d808c17f071e179133f1051c470f..f63c5f37fa9b76288c6bc06ccd078f818b743e04 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1489,
 /**/
     1488,
 /**/