Enabling semantic-mode in emacs-lisp buffers

Eric Ludlam <[email protected]> Sat, 12 Oct 2019 09:24:33 -0400
Newsgroups gmane.emacs.cedet
Message-ID <[email protected]>
Hi all,

I'm finally updating to using a version of CEDET that's built into 
Emacs.  With the version from source-forge, emacs-lisp buffers used 
CEDET features by default, but this is not the case with the version 
built into Emacs.  I feel it's important to include emacs lisp because 
other modes like srecode and some decoration features depend on it.

My assumption is that this was left out on-purpose, so I enabled it (see 
first part of patch below) and started using it and looking to see what 
annoying things might have caused this to be removed.

If you have any reasons why emacs-lisp-mode shoult stay unsupported by 
semantic by default (aside from what I'm fixing below) please let me 
know what they are.  Maybe I can fix them.

What I did find is a problem where completion-at-point (which I was 
using via company-mode) started parsing piles of files from Emacs' lisp 
directories.

The second part of the below patch fixes this problem.  It also speeds 
things up a bunch which is nice.

Repro steps:

emacs -q
M-x semantic-mode RET
;; Edit /tmp/foo.el
;; Type in: ;; comment a
;; put cursor directly after "a"
M-x completion-at-point RET

You'll see a ton of parsing messages from semantic rolling by.  Hit C-g 
and don't wait for it.  This is a worst-case scenario.

;; Exit emacs

In ~/.emacs.d/semanticdb you'll see lots of your emacs files tag caches 
stored away.  Delete them.  Apply the patch.

When you try again, there may be a message or 2 rolling by but no 
parsing.  In addition, no extra semanticdb files should be saved.


How this patch works (if you care):

The semantic parser parses buffers for tags.  semanticdb is a tool that 
makes it possible to search tags from multiple files from multiple 
directories.  It caches these into files in .emacs.d to speed up usage 
in future sessions, and allows searching of tags in files not in buffers.

For Emacs lisp, there is a special database used during search that uses 
Emacs' internal symbol lookup to find tags that haven't been parsed.  It 
can find the files they come from, and read tags from those files if 
needed. (ie - if you want to jump to that tag.)  Completion doesn't need 
that feature.  To convert the found tags from Emacs' internal search 
format to be useful, they need to be normalized, and that process was 
loading and parsing the extra files.

This isn't necessary for completion, so instead of loading the tags, the 
patched normalization process for emacs-lisp just saves the filename in 
the found tag and moves on.  The part the converts the tag list into the 
completion list then needs to access that filename more generically for 
cases where a found tag is already in a buffer.

An alternative to the below patch, or perhaps in addition to it, would 
be to remove the (require 'semantic/db-el) from the end of 
semantic/bovine/el.el.  There are many very good emacs-lisp based tools 
these days, so this feature is probably not necessary unless you are 
bought into the CEDET modes specifically.

Thanks for any input
Eric



diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 0b878cae52..e92c1ed363 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -269,6 +269,7 @@ semantic-inhibit-functions
  (defcustom semantic-new-buffer-setup-functions
    '((c-mode . semantic-default-c-setup)
      (c++-mode . semantic-default-c-setup)
+    (emacs-lisp-mode . semantic-default-elisp-setup)
      (html-mode . semantic-default-html-setup)
      (java-mode . wisent-java-default-setup)
      (js-mode . wisent-javascript-setup-parser)
diff --git a/lisp/cedet/semantic/db-el.el b/lisp/cedet/semantic/db-el.el
index 39d61fe789..70f023750c 100644
--- a/lisp/cedet/semantic/db-el.el
+++ b/lisp/cedet/semantic/db-el.el
@@ -176,15 +176,22 @@ emacs-lisp-mode
  	  ;; Is it a .gz file?
  	  (setq file (concat file ".gz"))))

-      (let* ((tab (semanticdb-file-table-object file))
+      ;; Use DONTLOAD opt for finding table obj associated w/ these tags.
+      ;; If we did load these syms, then simple completions for "a" for
+      ;; as-you-type completion systems will load half the libraries in
+      ;; emacs.
+      (let* ((tab (semanticdb-file-table-object file t))
  	     (newtags (when tab (semanticdb-find-tags-by-name-method
  				 tab (semantic-tag-name tag))))
  	     (match nil))
-	;; We might not have a parsed tag in this file, because it
-	;; might be generated through a macro like defstruct.
+	;; We might not have a parsed tag in this file due to
+	;; specifying DONTLOAD above, or the tag was generated with a
+	;; macro.  In that case, just use our found tag, and store
+	;; the filename in it.
  	(if (null newtags)
-	    (setq match tag)
-	  ;; Find the best match.
+            ;; In this case
+	    (setq match (semantic--tag-put-property tag :filename file))
+	  ;; Find the best match in the found tags.
  	  (dolist (T newtags)
  	    (when (semantic-tag-similar-p T tag)
  	      (setq match T)))
diff --git a/lisp/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el
index 18c749b098..114534bbf0 100644
--- a/lisp/cedet/semantic/db-find.el
+++ b/lisp/cedet/semantic/db-find.el
@@ -882,7 +882,7 @@ semanticdb-strip-find-results
  		;; Find-file-match allows a tool to make sure the tag is
  		;; 'live', somewhere in a buffer.
  		(cond ((eq find-file-match 'name)
-		       (or (semantic--tag-get-property ntag :filename)
+		       (or (semantic-tag-file-name ntag)
  			   (let ((f (semanticdb-full-filename nametable)))
  			     (semantic--tag-put-property ntag :filename f))))
  		      ((and find-file-match ntab)