bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug in etags find-tag-in-order


From: Charles Rich
Subject: bug in etags find-tag-in-order
Date: Fri, 5 Jan 2001 09:45:19 -0500

In the Emacs-20.6 etags find-tag-in-order (see code below), I believe
that the outer while loop (which iterates over the list of tags
tables) and the inner while loop (which iterates over the list of
ordering predicates) are "inside out", i.e., the outer loop should be
over the predicates and the inner loop over the files.

Logically, find-tag should first look for the best match in _any_
file.  Btw, to illustrate that this is not an abstract problem, see
the asterisk-highlighted part of the attached message below for how
this causes a misbehavior for JDE.

(Btw, if this is recoded, please send us the new code so we can put
it as a temporary patch in JDE).  

Thanks, -C. Rich

   (defun find-tag-in-order (pattern
                             search-forward-func
                             order
                             next-line-after-failure-p
                             matching
                             first-search)
     (let (file                         ;name of file containing tag
           tag-info                     ;where to find the tag in FILE
           (first-table t)
           (tag-order order)
           (match-marker (make-marker))
           goto-func
           )
       (save-excursion

         (if first-search
             ;; This is the start of a search for a fresh tag.
             ;; Clear the list of tags matched by the previous search.
             ;; find-tag-noselect has already put us in the first tags table
             ;; buffer before we got called.
             (setq tag-lines-already-matched nil)
           ;; Continuing to search for the tag specified last time.
           ;; tag-lines-already-matched lists locations matched in previous
           ;; calls so we don't visit the same tag twice if it matches twice
           ;; during two passes with different qualification predicates.
           ;; Switch to the current tags table buffer.
           (visit-tags-table-buffer 'same))

         ;; Get a qualified match.
         (catch 'qualified-match-found

           ;; Iterate over the list of tags tables.
           (while (or first-table
                      (visit-tags-table-buffer t))

             (and first-search first-table
                  ;; Start at beginning of tags file.
                  (goto-char (point-min)))

             (setq first-table nil)

             ;; Iterate over the list of ordering predicates.
             (while order
               (while (funcall search-forward-func pattern nil t)
                 ;; Naive match found.  Qualify the match.
                 (and (funcall (car order) pattern)
                      ;; Make sure it is not a previous qualified match.
                      (not (member (set-marker match-marker (save-excursion
                                                              
(beginning-of-line)
                                                              (point)))
                                   tag-lines-already-matched))
                      (throw 'qualified-match-found nil))
                 (if next-line-after-failure-p
                     (forward-line 1)))
               ;; Try the next flavor of match.
               (setq order (cdr order))
               (goto-char (point-min)))
             (setq order tag-order))
           ;; We throw out on match, so only get here if there were no matches.
           ;; Clear out the markers we use to avoid duplicate matches so they
           ;; don't slow down editting and are immediately available for GC.
           (while tag-lines-already-matched
             (set-marker (car tag-lines-already-matched) nil nil)
             (setq tag-lines-already-matched (cdr tag-lines-already-matched)))
           (set-marker match-marker nil nil)
           (error "No %stags %s %s" (if first-search "" "more ")
                  matching pattern))

         ;; Found a tag; extract location info.
         (beginning-of-line)
         (setq tag-lines-already-matched (cons match-marker
                                               tag-lines-already-matched))
         ;; Expand the filename, using the tags table buffer's 
default-directory.
         (setq file (expand-file-name (file-of-tag))
               tag-info (funcall snarf-tag-function))

         ;; Get the local value in the tags table buffer before switching 
buffers.
         (setq goto-func goto-tag-location-function)

         ;; Find the right line in the specified file.
         (set-buffer (find-file-noselect file))
         (widen)
         (push-mark)
         (funcall goto-func tag-info)

         ;; Return the buffer where the tag was found.
         (current-buffer))))
________________________________________________________________

Date: Thu, 04 Jan 2001 13:07:13 -0500
To: Charles Rich <rich@merl.com>
From: Paul Kinnucan <paulk@mathworks.com>
Subject: Re: Improvement to find-tag for JDE
Cc: rich@merl.com

>Hi Paul,
>
>  I would like to contribute the following improvement to the behavior
>of find-tag for JDE.  The basic idea is, when looking for a tag which
>has multiple matches in the TAGS file, to prefer (find first) the
>occurrence in the _current_ buffer.
>
>  A good example of why this is the natural behavior for editing Java
>code is to imagine that you have many files (classes) with the
>toString() method defined.  If you are editing W.java and do
>M-. toString, you would almost always be happier jumping to the
>definition of toString in W.java, rather than the definition in
>A.java, B.java, etc., which happen to fall in alphabetical order
>before W.java in the TAGS file..
>
>  Also, note below that in addition to making the new predicate
>"current-buffer-exact-name-match-p" the first entry in the
>find-tag-tag-order, I removed the non-exact match predicates.  Again,
>I think when editing Java code, it is more natural to jump to an exact
>match only (you can always use the regexp option of find-tag if you
>really want to look for a pattern).  In particular, if you want to
>visit the multiple occurrences of tag Foo (using C-u M-.), you don't
>want to have to step through FooBar and FooBaz, etc., to get to them.
>

****************************************************************
****************************************************************

>  Finally, note the following code only works correctly when there is
>a _single_ tags table or the current buffer happens to be a member of
>the first table in tags-table-list.  This is because there is IMHB a
>bug in the way that find-tag-in-order is coded, i.e., the outside loop
>is over the tags-table-list and the inside loop is over the order
>predicates---I think it should be the other way around.

****************************************************************
****************************************************************
>
>________________________________________________________________
>
>(defun current-buffer-exact-name-match-p (tag)
>  (and (tag-exact-match-p tag)
>       (equal (buffer-file-name (window-buffer (selected-window))) 
>             (file-of-tag))))
>
>(defun jde-etags-recognize-tags-table () ; see etags-recognize-tags-table
>  (let ((recognized (etags-recognize-tags-table)))
>    (if recognized 
>       ;; prefer exact match in current buffer to other files
>       (setq find-tag-tag-order '(current-buffer-exact-name-match-p
>                                  tag-exact-file-name-match-p
>                                  tag-exact-match-p
>                                  ))
>      recognized)))
>
>(setq tags-table-format-hooks '(jde-etags-recognize-tags-table
>                               recognize-empty-tags-table))
>
>________________________________________________________________

-- 
    Charles Rich     |  Mitsubishi Electric Research Laboratories
 617-621-7507 phone  |                 201 Broadway
 617-621-7550 fax    |             Cambridge, MA 02139
   rich@merl.com     |             http://www.merl.com




reply via email to

[Prev in Thread] Current Thread [Next in Thread]