Patch 8.0.0393 (after 8.0.0190)
Problem:    When the same tag appears more than once, the order is
            unpredictable. (Charles Campbell)
Solution:   Besides using a dict for finding duplicates, use a grow array for
            keeping the tags in sequence.
Files:      src/tag.c, src/testdir/test_tagjump.vim


*** ../vim-8.0.0392/src/tag.c   2017-01-23 20:47:09.037078522 +0100
--- src/tag.c   2017-03-01 15:38:25.293498562 +0100
***************
*** 35,43 ****
  } tagptrs_T;
  
  /*
!  * The matching tags are first stored in one of the ht_match[] hash tables.  
In
   * which one depends on the priority of the match.
!  * At the end, all the matches from ht_match[] are concatenated, to make a 
list
   * sorted on priority.
   */
  #define MT_ST_CUR     0               /* static match in current file */
--- 35,44 ----
  } tagptrs_T;
  
  /*
!  * The matching tags are first stored in one of the hash tables.  In
   * which one depends on the priority of the match.
!  * ht_match[] is used to find duplicates, ga_match[] to keep them in sequence.
!  * At the end, all the matches from ga_match[] are concatenated, to make a 
list
   * sorted on priority.
   */
  #define MT_ST_CUR     0               /* static match in current file */
***************
*** 1339,1345 ****
  #endif
  
      char_u    *mfp;
!     hashtab_T ht_match[MT_COUNT];
      hash_T    hash = 0;
      int               match_count = 0;                /* number of matches 
found */
      char_u    **matches;
--- 1340,1347 ----
  #endif
  
      char_u    *mfp;
!     garray_T  ga_match[MT_COUNT];     /* stores matches in sequence */
!     hashtab_T ht_match[MT_COUNT];     /* stores matches by key */
      hash_T    hash = 0;
      int               match_count = 0;                /* number of matches 
found */
      char_u    **matches;
***************
*** 1405,1411 ****
--- 1407,1416 ----
      ebuf = alloc(LSIZE);
  #endif
      for (mtt = 0; mtt < MT_COUNT; ++mtt)
+     {
+       ga_init2(&ga_match[mtt], (int)sizeof(char_u *), 100);
        hash_init(&ht_match[mtt]);
+     }
  
      /* check for out of memory situation */
      if (lbuf == NULL || tag_fname == NULL
***************
*** 2213,2219 ****
            }
  
            /*
!            * If a match is found, add it to ht_match[].
             */
            if (match)
            {
--- 2218,2224 ----
            }
  
            /*
!            * If a match is found, add it to ht_match[] and ga_match[].
             */
            if (match)
            {
***************
*** 2271,2277 ****
                }
  
                /*
!                * Add the found match in ht_match[mtt].
                 * Store the info we need later, which depends on the kind of
                 * tags we are dealing with.
                 */
--- 2276,2282 ----
                }
  
                /*
!                * Add the found match in ht_match[mtt] and ga_match[mtt].
                 * Store the info we need later, which depends on the kind of
                 * tags we are dealing with.
                 */
***************
*** 2423,2429 ****
                    if (HASHITEM_EMPTY(hi))
                    {
                        if (hash_add_item(&ht_match[mtt], hi, mfp, hash)
!                                                                      == FAIL)
                        {
                            /* Out of memory! Just forget about the rest. */
                            retval = OK;
--- 2428,2435 ----
                    if (HASHITEM_EMPTY(hi))
                    {
                        if (hash_add_item(&ht_match[mtt], hi, mfp, hash)
!                                                                      == FAIL
!                                      || ga_grow(&ga_match[mtt], 1) != OK)
                        {
                            /* Out of memory! Just forget about the rest. */
                            retval = OK;
***************
*** 2431,2437 ****
--- 2437,2447 ----
                            break;
                        }
                        else
+                       {
+                           ((char_u **)(ga_match[mtt].ga_data))
+                                               [ga_match[mtt].ga_len++] = mfp;
                            ++match_count;
+                       }
                    }
                    else
                        /* duplicate tag, drop it */
***************
*** 2533,2539 ****
  #endif
  
      /*
!      * Move the matches from the ht_match[] arrays into one list of
       * matches.  When retval == FAIL, free the matches.
       */
      if (retval == FAIL)
--- 2543,2549 ----
  #endif
  
      /*
!      * Move the matches from the ga_match[] arrays into one list of
       * matches.  When retval == FAIL, free the matches.
       */
      if (retval == FAIL)
***************
*** 2547,2580 ****
      match_count = 0;
      for (mtt = 0; mtt < MT_COUNT; ++mtt)
      {
!       hashitem_T      *hi;
!       long_u          todo;
! 
!       todo = (long)ht_match[mtt].ht_used;
!       for (hi = ht_match[mtt].ht_array; todo > 0; ++hi)
        {
!           if (!HASHITEM_EMPTY(hi))
            {
!               mfp = hi->hi_key;
!               if (matches == NULL)
!                   vim_free(mfp);
!               else
                {
!                   if (!name_only)
!                   {
!                       /* Change mtt back to zero-based. */
!                       *mfp = *mfp - 1;
  
!                       /* change the TAG_SEP back to NUL */
!                       for (p = mfp + 1; *p != NUL; ++p)
!                           if (*p == TAG_SEP)
!                               *p = NUL;
!                   }
!                   matches[match_count++] = (char_u *)mfp;
                }
!               todo--;
            }
        }
        hash_clear(&ht_match[mtt]);
      }
  
--- 2557,2584 ----
      match_count = 0;
      for (mtt = 0; mtt < MT_COUNT; ++mtt)
      {
!       for (i = 0; i < ga_match[mtt].ga_len; ++i)
        {
!           mfp = ((char_u **)(ga_match[mtt].ga_data))[i];
!           if (matches == NULL)
!               vim_free(mfp);
!           else
            {
!               if (!name_only)
                {
!                   /* Change mtt back to zero-based. */
!                   *mfp = *mfp - 1;
  
!                   /* change the TAG_SEP back to NUL */
!                   for (p = mfp + 1; *p != NUL; ++p)
!                       if (*p == TAG_SEP)
!                           *p = NUL;
                }
!               matches[match_count++] = (char_u *)mfp;
            }
        }
+ 
+       ga_clear(&ga_match[mtt]);
        hash_clear(&ht_match[mtt]);
      }
  
*** ../vim-8.0.0392/src/testdir/test_tagjump.vim        2017-01-16 
20:53:31.154599637 +0100
--- src/testdir/test_tagjump.vim        2017-03-01 15:25:28.362478203 +0100
***************
*** 35,44 ****
--- 35,68 ----
    tag one
    call assert_equal(2, line('.'))
  
+   bwipe!
    set tags&
    call delete('Xtags')
    call delete('Xfile1')
+ endfunc
+ 
+ func Test_duplicate_tagjump()
+   set tags=Xtags
+   call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+         \ "thesame\tXfile1\t1;\"\td\tfile:",
+         \ "thesame\tXfile1\t2;\"\td\tfile:",
+         \ "thesame\tXfile1\t3;\"\td\tfile:",
+         \ ],
+         \ 'Xtags')
+   new Xfile1
+   call setline(1, ['thesame one', 'thesame two', 'thesame three'])
+   write
+   tag thesame
+   call assert_equal(1, line('.'))
+   tnext
+   call assert_equal(2, line('.'))
+   tnext
+   call assert_equal(3, line('.'))
+ 
    bwipe!
+   set tags&
+   call delete('Xtags')
+   call delete('Xfile1')
  endfunc
  
  " Tests for [ CTRL-I and CTRL-W CTRL-I commands
*** ../vim-8.0.0392/src/version.c       2017-03-01 15:07:01.345621994 +0100
--- src/version.c       2017-03-01 15:27:14.853795967 +0100
***************
*** 766,767 ****
--- 766,769 ----
  {   /* Add new patch number below this line */
+ /**/
+     393,
  /**/

-- 
To define recursion, we must first define recursion.

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui