Subject: bug#20629: 25.0.50; Regression: TAGS broken, can't find anything in C++ files.

From: Dmitry Gutov <[email-masked]>
Date: Thu, 28 May 2015 14:54:49 +0300

On 05/27/2015 12:01 AM, Stefan Monnier wrote:

> BTW, it might be worthwhile to try and replace the obarray with
> a function which directly searches the corresponding tags buffers.
> Searching those buffers might not be significantly slower than searching
> the obarray, with the advantage that we avoid the "building the
> completion table" step.

Having the table always up-to-date would be nice. But here's some 
numbers with a rough patch.

The project is of moderate size: Linux kernel.

TAGS is 159097 lines long.

Pre-built tags-completion-table:

Build it -> 1.34 seconds
(all-completions "" (tags-completion-table)) after that -> 0.02 seconds

Dynamic completion table:

(all-completions "" (tags-completion-table)) -> 0.78 seconds
                  ^-- same with any longer prefix, in this implementation

Patch:

diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 9ff164e..19de126 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -753,31 +753,18 @@ Assumes the tags table is the current buffer."
        (setq tags-included-tables (funcall 
tags-included-tables-function))))
  
  (defun tags-completion-table ()
-  "Build `tags-completion-table' on demand.
+  "Return tags completion table.
  The tags included in the completion table are those in the current
  tags table and its (recursively) included tags tables."
-  (or tags-completion-table
-      ;; No cached value for this buffer.
-      (condition-case ()
-	  (let (current-table combined-table)
-	    (message "Making tags completion table for %s..." buffer-file-name)
-	    (save-excursion
-	      ;; Iterate over the current list of tags tables.
-	      (while (visit-tags-table-buffer (and combined-table t))
-		;; Find possible completions in this table.
-		(setq current-table (funcall tags-completion-table-function))
-		;; Merge this buffer's completions into the combined table.
-		(if combined-table
-		    (mapatoms
-		     (lambda (sym) (intern (symbol-name sym) combined-table))
-		     current-table)
-		  (setq combined-table current-table))))
-	    (message "Making tags completion table for %s...done"
-		     buffer-file-name)
-	    ;; Cache the result in a buffer-local variable.
-	    (setq tags-completion-table combined-table))
-	(quit (message "Tags completion table construction aborted.")
-	      (setq tags-completion-table nil)))))
+  (completion-table-with-cache
+   (lambda (_string)
+     (let (cont tables)
+       (save-excursion
+         ;; Iterate over the current list of tags tables.
+         (while (visit-tags-table-buffer (or cont (progn (setq cont t) 
nil)))
+           ;; Find possible completions in this table.
+           (push (funcall tags-completion-table-function) tables)))
+       (nreverse (apply #'nconc tables))))))

  ;;;###autoload
  (defun tags-lazy-completion-table ()
@@ -1256,11 +1243,7 @@ buffer-local values of tags table format variables."

  (defun etags-tags-completion-table () ; Doc string?
-  (let ((table (make-vector 511 0))
-	(progress-reporter
-	 (make-progress-reporter
-	  (format "Making tags completion table for %s..." buffer-file-name)
-	  (point-min) (point-max))))
+  (let ((table nil))
      (save-excursion
        (goto-char (point-min))
        ;; This monster regexp matches an etags tag line.
@@ -1276,12 +1259,11 @@ buffer-local values of tags table format variables."
  \\([-a-zA-Z0-9_+*$?:]+\\)[^-a-zA-Z0-9_+*$?:\177]*\\)\177\
  \\(\\([^\n\001]+\\)\001\\)?\\([0-9]+\\)?,\\([0-9]+\\)?\n"
  	      nil t)
-	(intern	(prog1 (if (match-beginning 5)
+	(push	(prog1 (if (match-beginning 5)
  			   ;; There is an explicit tag name.
  			   (buffer-substring (match-beginning 5) (match-end 5))
  			 ;; No explicit tag name.  Best guess.
-			 (buffer-substring (match-beginning 3) (match-end 3)))
-		  (progress-reporter-update progress-reporter (point)))
+			 (buffer-substring (match-beginning 3) (match-end 3))))
  		table)))
      table))