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.