]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.4518: the binary tag search feature is always enabled v8.2.4518
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 6 Mar 2022 14:27:10 +0000 (14:27 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 6 Mar 2022 14:27:10 +0000 (14:27 +0000)
Problem:    The binary tag search feature is always enabled.
Solution:   Remove the #ifdefs.  Add a few more tests. (Yegappan Lakshmanan,
            closes #9893)

src/evalfunc.c
src/feature.h
src/tag.c
src/testdir/test_tagjump.vim
src/testdir/test_taglist.vim
src/version.c

index 1b93200367952fb7c237c2cbb86f19cf1d4e0866..39a2fd276652621b45efdc98e5ac85a07baad252 100644 (file)
@@ -4382,7 +4382,8 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
 
     if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))
                                         || (is_funcref && trans_name == NULL))
-       semsg(_(e_invalid_argument_str), use_string ? tv_get_string(&argvars[0]) : s);
+       semsg(_(e_invalid_argument_str),
+                                 use_string ? tv_get_string(&argvars[0]) : s);
     // Don't check an autoload name for existence here.
     else if (trans_name != NULL && (is_funcref
                         ? find_func(trans_name, is_global) == NULL
@@ -6101,13 +6102,7 @@ f_has(typval_T *argvars, typval_T *rettv)
                0
 #endif
                },
-       {"tag_binary",
-#ifdef FEAT_TAG_BINS
-               1
-#else
-               0
-#endif
-               },
+       {"tag_binary", 1},      // graduated feature
        {"tcl",
 #if defined(FEAT_TCL) && !defined(DYNAMIC_TCL)
                1
index 9564f8e10007898ff0453e8ce914980ef1b70ab5..0f5bf1e016ea83c46b9af7155271b1893cd9993b 100644 (file)
 # define FEAT_EMACS_TAGS
 #endif
 
-/*
- * +tag_binary         Can use a binary search for the tags file.
- */
-#define FEAT_TAG_BINS
-
 /*
  * +cscope             Unix only: Cscope support.
  */
index 76558cb9e6957e1168f1f31aed1e38e336e9a944..65723ed57364e835b03985e29fcfdfdbcc1b7a38 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -1270,7 +1270,6 @@ do_tags(exarg_T *eap UNUSED)
        msg_puts("\n>");
 }
 
-#ifdef FEAT_TAG_BINS
 /*
  * Compare two strings, for length "len", ignoring case the ASCII way.
  * return 0 for match, < 0 for smaller, > 0 for bigger
@@ -1294,7 +1293,6 @@ tag_strnicmp(char_u *s1, char_u *s2, size_t len)
     }
     return 0;                          // strings match
 }
-#endif
 
 /*
  * Structure to hold info about the tag pattern being used.
@@ -1592,9 +1590,7 @@ typedef struct {
     int                did_open;               // did open a tag file
     int                mincount;               // MAXCOL: find all matches
                                        // other: minimal number of matches
-#ifdef FEAT_TAG_BINS
     int                linear;                 // do a linear search
-#endif
     char_u     *lbuf;                  // line buffer
     int                lbuf_size;              // length of lbuf
 #ifdef FEAT_EMACS_TAGS
@@ -1960,10 +1956,8 @@ tags_file_hdr_parse(findtags_state_T *st, vimconv_T *vcp, int *sorted_file)
        return FALSE;
 
     // Read header line.
-#ifdef FEAT_TAG_BINS
     if (STRNCMP(st->lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
        *sorted_file = st->lbuf[18];
-#endif
     if (STRNCMP(st->lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0)
     {
        // Prepare to convert every line from the specified
@@ -2264,23 +2258,18 @@ find_tags_in_file(
     int                help_pri = 0;
     char_u     help_lang[3] = "";      // lang of current tags file
 #endif
-#ifdef FEAT_TAG_BINS
     int                tag_file_sorted = NUL;  // !_TAG_FILE_SORTED value
     off_T      filesize;
     int                tagcmp;
     off_T      offset;
-#endif
     enum
     {
        TS_START,               // at start of file
-       TS_LINEAR               // linear searching forward, till EOF
-#ifdef FEAT_TAG_BINS
-       , TS_BINARY,            // binary searching
+       TS_LINEAR,              // linear searching forward, till EOF
+       TS_BINARY,              // binary searching
        TS_SKIP_BACK,           // skipping backwards
        TS_STEP_FORWARD         // stepping forwards
-#endif
     } state;                   // Current search state
-#ifdef FEAT_TAG_BINS
     struct tag_search_info     // Binary search file offsets
     {
        off_T   low_offset;     // offset for first char of first line that
@@ -2293,7 +2282,6 @@ find_tags_in_file(
        int     low_char;       // first char at low_offset
        int     high_char;      // first char at high_offset
     } search_info;
-#endif
 
     int                cmplen;
     int                match;          // matches
@@ -2305,11 +2293,9 @@ find_tags_in_file(
 
     hash_T     hash = 0;
 
-#ifdef FEAT_TAG_BINS
     int                sort_error = FALSE;             // tags file not sorted
     int                sortic = FALSE;                 // tag file sorted in nocase
     int                noic = (flags & TAG_NOIC);
-#endif
     int                line_error = FALSE;             // syntax error
     int                has_re = (flags & TAG_REGEXP);  // regexp used
 #ifdef FEAT_CSCOPE
@@ -2319,11 +2305,9 @@ find_tags_in_file(
 
     vimconv.vc_type = CONV_NONE;
 
-#ifdef FEAT_TAG_BINS
     // This is only to avoid a compiler warning for using search_info
     // uninitialised.
     CLEAR_FIELD(search_info);
-#endif
 
     // A file that doesn't exist is silently ignored.  Only when not a
     // single file is found, an error message is given (further on).
@@ -2359,12 +2343,10 @@ find_tags_in_file(
     // Read and parse the lines in the file one by one
     for (;;)
     {
-#ifdef FEAT_TAG_BINS
        // check for CTRL-C typed, more often when jumping around
        if (state == TS_BINARY || state == TS_SKIP_BACK)
            line_breakcheck();
        else
-#endif
            fast_breakcheck();
        if ((flags & TAG_INS_COMP))     // Double brackets for gcc
            ins_compl_check_keys(30, FALSE);
@@ -2382,7 +2364,6 @@ find_tags_in_file(
        }
        if (st->get_searchpat)
            goto line_read_in;
-#ifdef FEAT_TAG_BINS
        // For binary search: compute the next offset to use.
        if (state == TS_BINARY)
        {
@@ -2449,7 +2430,6 @@ find_tags_in_file(
         * Not jumping around in the file: Read the next line.
         */
        else
-#endif
        {
            // skip empty and blank lines
            do
@@ -2460,9 +2440,7 @@ find_tags_in_file(
                else
 #endif
                {
-#ifdef FEAT_TAG_BINS
                    search_info.curr_offset = vim_ftell(fp);
-#endif
                    eof = vim_fgets(st->lbuf, st->lbuf_size, fp);
                }
            } while (!eof && vim_isblankline(st->lbuf));
@@ -2525,7 +2503,6 @@ line_read_in:
 
            // Headers ends.
 
-#ifdef FEAT_TAG_BINS
            /*
             * When there is no tag head, or ignoring case, need to do a
             * linear search.
@@ -2561,11 +2538,7 @@ line_read_in:
                st->linear = TRUE;
                state = TS_LINEAR;
            }
-#else
-           state = TS_LINEAR;
-#endif
 
-#ifdef FEAT_TAG_BINS
            // When starting a binary search, get the size of the file and
            // compute the first offset.
            if (state == TS_BINARY)
@@ -2591,7 +2564,6 @@ line_read_in:
                }
                continue;
            }
-#endif
        }
 
 parse_line:
@@ -2615,14 +2587,12 @@ parse_line:
                return FAIL;
            }
 
-#ifdef FEAT_TAG_BINS
            if (state == TS_STEP_FORWARD)
                // Seek to the same position to read the same line again
                vim_fseek(fp, search_info.curr_offset, SEEK_SET);
            // this will try the same thing again, make sure the offset is
            // different
            search_info.curr_offset = 0;
-#endif
            continue;
        }
 
@@ -2659,7 +2629,6 @@ parse_line:
            else if (state == TS_LINEAR && st->orgpat.headlen != cmplen)
                continue;
 
-#ifdef FEAT_TAG_BINS
            if (state == TS_BINARY)
            {
                /*
@@ -2750,7 +2719,6 @@ parse_line:
                }
            }
            else
-#endif
                // skip this match if it can't match
                if (MB_STRNICMP(tagp.tagname, st->orgpat.head, cmplen) != 0)
                    continue;
@@ -2874,14 +2842,12 @@ parse_line:
     if (vimconv.vc_type != CONV_NONE)
        convert_setup(&vimconv, NULL, NULL);
 
-#ifdef FEAT_TAG_BINS
     tag_file_sorted = NUL;
     if (sort_error)
     {
        semsg(_(e_tags_file_not_sorted_str), st->tag_fname);
        sort_error = FALSE;
     }
-#endif
 
     /*
      * Stop searching if sufficient tags have been found.
@@ -2983,9 +2949,7 @@ find_tags(
     tagname_T  tn;                     // info for get_tagfname()
     int                first_file;             // trying first tag file
     int                retval = FAIL;          // return value
-#ifdef FEAT_TAG_BINS
     int                round;
-#endif
 
     int                save_emsg_off;
 
@@ -2995,10 +2959,8 @@ find_tags(
     char_u     *saved_pat = NULL;              // copy of pat[]
 #endif
 
-#ifdef FEAT_TAG_BINS
     int                findall = (mincount == MAXCOL || mincount == TAG_MANY);
                                                // find all matching tags
-#endif
     int                has_re = (flags & TAG_REGEXP);  // regexp used
     int                noic = (flags & TAG_NOIC);
 #ifdef FEAT_CSCOPE
@@ -3101,15 +3063,11 @@ find_tags(
      * When the tag file is case-fold sorted, it is either one or the other.
      * Only ignore case when TAG_NOIC not used or 'ignorecase' set.
      */
-#ifdef FEAT_TAG_BINS
     st.orgpat.regmatch.rm_ic = ((p_ic || !noic)
                        && (findall || st.orgpat.headlen == 0 || !p_tbs));
     for (round = 1; round <= 2; ++round)
     {
        st.linear = (st.orgpat.headlen == 0 || !p_tbs || round == 2);
-#else
-       st.orgpat.regmatch.rm_ic = (p_ic || !noic);
-#endif
 
       /*
        * Try tag file names from tags option one by one.
@@ -3139,7 +3097,6 @@ find_tags(
 #endif
            tagname_free(&tn);
 
-#ifdef FEAT_TAG_BINS
        // stop searching when already did a linear search, or when TAG_NOIC
        // used, and 'ignorecase' not set or already did case-ignore search
        if (st.stop_searching || st.linear || (!p_ic && noic) ||
@@ -3153,7 +3110,6 @@ find_tags(
        // try another time while ignoring case
        st.orgpat.regmatch.rm_ic = TRUE;
     }
-#endif
 
     if (!st.stop_searching)
     {
index 95a3c3113a2f138b2a705b45b001c3cec68a80e2..95652ef65fc614f8c0ae7bc4dfcb28b9e19a079a 100644 (file)
@@ -1503,4 +1503,77 @@ func Test_stag_close_window_on_error()
   set tags&
 endfunc
 
+" Test for 'tagbsearch' (binary search)
+func Test_tagbsearch()
+  " If a tags file header says the tags are sorted, but the tags are actually
+  " unsorted, then binary search should fail and linear search should work.
+  call writefile([
+        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+        \ "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/",
+        \ "third\tXfoo\t3",
+        \ "second\tXfoo\t2",
+        \ "first\tXfoo\t1"],
+        \ 'Xtags')
+  set tags=Xtags
+  let code =<< trim [CODE]
+    int first() {}
+    int second() {}
+    int third() {}
+  [CODE]
+  call writefile(code, 'Xfoo')
+
+  enew
+  set tagbsearch
+  call assert_fails('tag first', 'E426:')
+  call assert_equal('', bufname())
+  call assert_fails('tag second', 'E426:')
+  call assert_equal('', bufname())
+  tag third
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(3, line('.'))
+  %bw!
+
+  set notagbsearch
+  tag first
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(1, line('.'))
+  enew
+  tag second
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(2, line('.'))
+  enew
+  tag third
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(3, line('.'))
+  %bw!
+
+  " If a tags file header says the tags are unsorted, but the tags are
+  " actually sorted, then binary search should work.
+  call writefile([
+        \ "!_TAG_FILE_ENCODING\tutf-8\t//",
+        \ "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/",
+        \ "first\tXfoo\t1",
+        \ "second\tXfoo\t2",
+        \ "third\tXfoo\t3"],
+        \ 'Xtags')
+
+  set tagbsearch
+  tag first
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(1, line('.'))
+  enew
+  tag second
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(2, line('.'))
+  enew
+  tag third
+  call assert_equal('Xfoo', bufname())
+  call assert_equal(3, line('.'))
+  %bw!
+
+  call delete('Xtags')
+  call delete('Xfoo')
+  set tags& tagbsearch&
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 3ba5ec0943548d144d48959ca0f2eb2a128ab3ce..04ca02decf766aaedb80b63e87f6588e62262915 100644 (file)
@@ -37,6 +37,12 @@ func Test_taglist()
   call assert_equal('d', cmd[0]['kind'])
   call assert_equal('call cursor(3, 4)', cmd[0]['cmd'])
 
+  " Use characters with value > 127 in the tag extra field.
+  call writefile([
+       \ "vFoo\tXfoo\t4" .. ';"' .. "\ttypename:int\ta£££\tv",
+       \ ], 'Xtags')
+  call assert_equal('v', taglist('vFoo')[0].kind)
+
   call assert_fails("let l=taglist([])", 'E730:')
 
   call delete('Xtags')
@@ -216,6 +222,11 @@ func Test_format_error()
   endtry
   call assert_true(caught_exception)
 
+  " no field after the filename for a tag
+  call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+        \ "foo\tXfile"], 'Xtags')
+  call assert_fails("echo taglist('foo')", 'E431:')
+
   set tags&
   call delete('Xtags')
 endfunc
index 5e7d570914d279731e9ad9da1840b78d6826f186..771530adab53559926dc8528182ef4f78a24f035 100644 (file)
@@ -590,11 +590,7 @@ static char *(features[]) =
 #if defined(USE_SYSTEM) && defined(UNIX)
        "+system()",
 #endif
-#ifdef FEAT_TAG_BINS
        "+tag_binary",
-#else
-       "-tag_binary",
-#endif
        "-tag_old_static",
        "-tag_any_white",
 #ifdef FEAT_TCL
@@ -754,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4518,
 /**/
     4517,
 /**/