
* lisp/allout.el (allout-exposure-change-hook) (allout-structure-added-hook, allout-structure-deleted-hook) (allout-structure-shifted-hook): * lisp/arc-mode.el (archive-extract-hooks): * lisp/buff-menu.el (Buffer-menu-buffer+size-width): * lisp/calendar/timeclock.el (timeclock-modeline-display) (timeclock-modeline-display, timeclock-update-modeline): * lisp/cedet/semantic/db-el.el (semanticdb-elisp-sym-function-arglist): * lisp/cedet/semantic/db-file.el (semanticdb-save-database-hooks): * lisp/cedet/semantic/edit.el (semantic-change-hooks) (semantic-edits-new-change-hooks) (semantic-edits-delete-change-hooks) (semantic-edits-reparse-change-hooks): * lisp/cedet/semantic/lex.el (semantic-lex-reset-hooks): * lisp/comint.el (comint--unquote&expand-filename) (comint-unquote-filename): * lisp/custom.el (user-variable-p): * lisp/dired.el (dired-shrink-to-fit, dired-pop-to-buffer) (dired-sort-set-modeline): * lisp/ebuff-menu.el (Electric-buffer-menu-mode): * lisp/emacs-lisp/byte-run.el (macro-declaration-function): * lisp/emacs-lisp/checkdoc.el (custom-print-functions) (checkdoc-comment-style-hooks): * lisp/emacs-lisp/cl-lib.el (custom-print-functions): * lisp/emacs-lisp/edebug.el (gud-inhibit-global-bindings): * lisp/erc/erc-dcc.el (erc-dcc-chat-filter-hook): * lisp/eshell/esh-mode.el (eshell-status-in-modeline): * lisp/eshell/eshell.el (eshell-add-to-window-buffer-names) (eshell-remove-from-window-buffer-names): * lisp/faces.el (set-face-underline-p, font-list-limit): * lisp/files.el (automount-dir-prefix, toggle-read-only): * lisp/filesets.el (filesets-cache-fill-content-hooks): * lisp/frame.el (automatic-hscrolling): * lisp/generic-x.el (javascript-generic-mode) (javascript-generic-mode-hook): * lisp/gnus/gnus-start.el (gnus-subscribe-newsgroup-hooks): * lisp/gnus/nndiary.el (nndiary-request-create-group-hooks) (nndiary-request-update-info-hooks) (nndiary-request-accept-article-hooks): * lisp/htmlfontify.el (hfy-post-html-hooks): * lisp/international/mule-cmds.el (inactivate-current-input-method-function) (inactivate-input-method, input-method-inactivate-hook) (ucs-insert): * lisp/international/quail.el (quail-inactivate) (quail-inactivate-hook): * lisp/international/robin.el (robin-inactivate) (robin-inactivate-hook): * lisp/leim/quail/hangul.el (hangul-input-method-inactivate): * lisp/leim/quail/uni-input.el (ucs-input-inactivate): * lisp/mail/emacsbug.el (report-emacs-bug-info): * lisp/mh-e/mh-e.el (mh-kill-folder-suppress-prompt-hooks): * lisp/mpc.el (mpc-string-prefix-p): * lisp/net/rcirc.el (rcirc-print-hooks, rcirc-sentinel-hooks) (rcirc-receive-message-hooks, rcirc-activity-hooks): * lisp/obsolete/crisp.el (crisp-mode-modeline-string): * lisp/pcomplete.el (pcomplete-arg-quote-list) (pcomplete-quote-argument): * lisp/progmodes/cc-mode.el (c-prepare-bug-report-hooks): * lisp/progmodes/python.el (python-info-ppss-context) (python-info-ppss-context-type) (python-info-ppss-comment-or-string-p, python-indent) (python-guess-indent, python-buffer, python-preoutput-result) (python-proc, python-send-receive, python-send-string) (python-use-skeletons): * lisp/progmodes/sh-script.el (sh-maybe-here-document): * lisp/replace.el (query-replace-interactive): * lisp/strokes.el (strokes-modeline-string): * lisp/subr.el (redraw-modeline): * lisp/term.el (term-default-fg-color, term-default-bg-color): * lisp/textmodes/tex-mode.el (latex-string-prefix-p) (tex-string-prefix-p): * lisp/url/url-parse.el (url-recreate-url-attributes): * lisp/vc/add-log.el (change-log-acknowledgement): * lisp/vc/ediff-wind.el (ediff-choose-window-setup-function-automatically): * lisp/vc/pcvs-util.el (cvs-string-prefix-p): * lisp/vc/vc.el (vc-string-prefix-p): * lisp/window.el (display-buffer-function): * lisp/winner.el (winner-mode-leave-hook): Remove many functions and variables obsolete since 24.3. * lisp/buff-menu.el (list-buffers--refresh): * lisp/dired.el (dired-mode-map): * lisp/files.el (abbreviate-file-name): * lisp/generic-x.el (generic-default-modes): * lisp/mh-e/mh-funcs.el (mh-kill-folder): * lisp/progmodes/hideif.el (hide-ifdef-mode-submap): * lisp/replace.el (query-replace-read-from): * lisp/term.el (term): * lisp/window.el (display-buffer): Don't use above deleted functions and variables. * src/marker.c (Fbuffer_has_markers_at): Delete DEFUN obsolete since 24.3. (syms_of_marker) <Sbuffer_has_markers_at>: Delete defsubr. * lisp/subr.el (buffer-has-markers-at): Remove obsoletion of above deleted DEFUN. * etc/TODO: Doc fix; don't mention above deleted function. * admin/cus-test.el (cus-test-get-options): * lisp/pcomplete.el: Doc fixes; don't mention removed items. ; * etc/NEWS: List removed items.
347 lines
13 KiB
EmacsLisp
347 lines
13 KiB
EmacsLisp
;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp -*- lexical-binding: t; -*-
|
|
|
|
;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
|
|
|
|
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
|
;; Keywords: tags
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
;;
|
|
;; There are a lot of Emacs Lisp functions and variables available for
|
|
;; the asking. This adds on to the semanticdb programming interface to
|
|
;; allow all loaded Emacs Lisp functions to be queried via semanticdb.
|
|
;;
|
|
;; This allows you to use programs written for Semantic using the database
|
|
;; to also work in Emacs Lisp with no compromises.
|
|
;;
|
|
|
|
(require 'semantic/db)
|
|
(require 'eieio-opt)
|
|
|
|
(declare-function semantic-elisp-desymbolify "semantic/bovine/el")
|
|
(declare-function semantic-tag-similar-p "semantic/tag-ls")
|
|
|
|
;;; Code:
|
|
|
|
;;; Classes:
|
|
(defclass semanticdb-table-emacs-lisp (semanticdb-abstract-table)
|
|
((major-mode :initform #'emacs-lisp-mode)
|
|
)
|
|
"A table for returning search results from Emacs.")
|
|
|
|
(cl-defmethod semanticdb-refresh-table ((_obj semanticdb-table-emacs-lisp) &optional _force)
|
|
"Do not refresh Emacs Lisp table.
|
|
It does not need refreshing."
|
|
nil)
|
|
|
|
(cl-defmethod semanticdb-needs-refresh-p ((_obj semanticdb-table-emacs-lisp))
|
|
"Return nil, we never need a refresh."
|
|
nil)
|
|
|
|
(cl-defmethod semanticdb-debug-info ((_obj semanticdb-table-emacs-lisp))
|
|
(list "(proxy)"))
|
|
|
|
(cl-defmethod cl-print-object ((obj semanticdb-table-emacs-lisp) stream)
|
|
"Pretty printer extension for `semanticdb-table-emacs-lisp'."
|
|
(princ (eieio-object-name obj (semanticdb-debug-info obj))
|
|
stream))
|
|
|
|
(defclass semanticdb-project-database-emacs-lisp
|
|
(semanticdb-project-database eieio-singleton)
|
|
((new-table-class :initform 'semanticdb-table-emacs-lisp
|
|
:type class
|
|
:documentation
|
|
"New tables created for this database are of this class.")
|
|
)
|
|
"Database representing Emacs core.")
|
|
|
|
(cl-defmethod semanticdb-debug-info ((obj
|
|
semanticdb-project-database-emacs-lisp))
|
|
(let ((count 0))
|
|
(mapatoms (lambda (_sym) (setq count (1+ count))))
|
|
(append (cl-call-next-method obj)
|
|
(list (format "(%d known syms)" count)))))
|
|
|
|
(cl-defmethod cl-print-object ((obj semanticdb-project-database-emacs-lisp)
|
|
stream)
|
|
"Pretty printer extension for `semanticdb-table-emacs-lisp'.
|
|
Adds the number of tags in this file to the object print name."
|
|
(princ (eieio-object-name obj (semanticdb-debug-info obj))
|
|
stream))
|
|
|
|
;; Create the database, and add it to searchable databases for Emacs Lisp mode.
|
|
(defvar-mode-local emacs-lisp-mode semanticdb-project-system-databases
|
|
(list
|
|
(make-instance 'semanticdb-project-database-emacs-lisp))
|
|
"Search Emacs core for symbols.")
|
|
|
|
(defvar-mode-local emacs-lisp-mode semanticdb-find-default-throttle
|
|
'(project omniscience)
|
|
"Search project files, then search this omniscience database.
|
|
It is not necessary to do system or recursive searching because of
|
|
the omniscience database.")
|
|
|
|
;;; Filename based methods
|
|
;;
|
|
(cl-defmethod semanticdb-get-database-tables ((obj semanticdb-project-database-emacs-lisp))
|
|
"For an Emacs Lisp database, there are no explicit tables.
|
|
Create one of our special tables that can act as an intermediary."
|
|
;; We need to return something since there is always the "master table"
|
|
;; The table can then answer file name type questions.
|
|
(when (not (slot-boundp obj 'tables))
|
|
(let ((newtable (make-instance 'semanticdb-table-emacs-lisp)))
|
|
(oset obj tables (list newtable))
|
|
(oset newtable parent-db obj)
|
|
(oset newtable tags nil)
|
|
))
|
|
(cl-call-next-method))
|
|
|
|
(cl-defmethod semanticdb-file-table ((obj semanticdb-project-database-emacs-lisp) _filename)
|
|
"From OBJ, return FILENAME's associated table object.
|
|
For Emacs Lisp, creates a specialized table."
|
|
(car (semanticdb-get-database-tables obj))
|
|
)
|
|
|
|
(cl-defmethod semanticdb-get-tags ((_table semanticdb-table-emacs-lisp ))
|
|
"Return the list of tags belonging to TABLE."
|
|
;; specialty table ? Probably derive tags at request time.
|
|
nil)
|
|
|
|
(cl-defmethod semanticdb-equivalent-mode ((_table semanticdb-table-emacs-lisp) &optional buffer)
|
|
"Return non-nil if TABLE's mode is equivalent to BUFFER.
|
|
Equivalent modes are specified by the `semantic-equivalent-major-modes'
|
|
local variable."
|
|
(with-current-buffer buffer
|
|
(eq (or mode-local-active-mode major-mode) 'emacs-lisp-mode)))
|
|
|
|
(cl-defmethod semanticdb-full-filename ((_obj semanticdb-table-emacs-lisp))
|
|
"Fetch the full filename that OBJ refers to.
|
|
For Emacs Lisp system DB, there isn't one."
|
|
nil)
|
|
|
|
;;; Conversion
|
|
;;
|
|
(cl-defmethod semanticdb-normalize-tags ((obj semanticdb-table-emacs-lisp) tags)
|
|
"Convert tags, originating from Emacs OBJ, into standardized form."
|
|
(let ((newtags nil))
|
|
(dolist (T tags)
|
|
(let* ((ot (semanticdb-normalize-one-tag obj T))
|
|
(tag (cdr ot)))
|
|
(setq newtags (cons tag newtags))))
|
|
;; There is no promise to have files associated.
|
|
(nreverse newtags)))
|
|
|
|
(cl-defmethod semanticdb-normalize-one-tag ((obj semanticdb-table-emacs-lisp) tag)
|
|
"Convert one TAG, originating from Emacs OBJ, into standardized form.
|
|
If Emacs cannot resolve this symbol to a particular file, then return nil."
|
|
;; Here's the idea. For each tag, get the name, then use
|
|
;; Emacs's `symbol-file' to get the source. Once we have that,
|
|
;; we can use more typical semantic searching techniques to
|
|
;; get a regularly parsed tag.
|
|
(let* ((type (cond ((semantic-tag-of-class-p tag 'function)
|
|
'defun)
|
|
((semantic-tag-of-class-p tag 'variable)
|
|
'defvar)
|
|
))
|
|
(sym (intern (semantic-tag-name tag)))
|
|
(file (condition-case nil
|
|
(symbol-file sym type)
|
|
;; Older [X]Emacs don't have a 2nd argument.
|
|
(error (symbol-file sym))))
|
|
)
|
|
(if (or (not file) (not (file-exists-p file)))
|
|
;; The file didn't exist. Return nil.
|
|
;; We can't normalize this tag. Fake it out.
|
|
(cons obj tag)
|
|
(when (string-match "\\.elc" file)
|
|
(setq file (concat (file-name-sans-extension file)
|
|
".el"))
|
|
(when (and (not (file-exists-p file))
|
|
(file-exists-p (concat file ".gz")))
|
|
;; Is it a .gz file?
|
|
(setq file (concat file ".gz"))))
|
|
|
|
(let* ((tab (semanticdb-file-table-object file))
|
|
(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.
|
|
(if (null newtags)
|
|
(setq match tag)
|
|
;; Find the best match.
|
|
(dolist (T newtags)
|
|
(when (semantic-tag-similar-p T tag)
|
|
(setq match T)))
|
|
;; Backup system.
|
|
(when (not match)
|
|
(setq match (car newtags))))
|
|
;; Return it.
|
|
(when tab (cons tab match))))))
|
|
|
|
(autoload 'help-function-arglist "help-fns")
|
|
|
|
(defun semanticdb-elisp-sym->tag (sym &optional toktype)
|
|
"Convert SYM into a semantic tag.
|
|
TOKTYPE is a hint to the type of tag desired."
|
|
(if (stringp sym)
|
|
(setq sym (intern-soft sym)))
|
|
(when sym
|
|
(cond ((and (eq toktype 'function) (fboundp sym))
|
|
(require 'semantic/bovine/el)
|
|
(let ((arglist (help-function-arglist sym)))
|
|
(when (not (listp arglist))
|
|
;; Function might be autoloaded, in which case
|
|
;; the arglist is not available yet.
|
|
(setq arglist nil))
|
|
(semantic-tag-new-function
|
|
(symbol-name sym)
|
|
nil ;; return type
|
|
(semantic-elisp-desymbolify arglist)
|
|
:user-visible-flag (commandp sym))))
|
|
((and (eq toktype 'variable) (boundp sym))
|
|
(semantic-tag-new-variable
|
|
(symbol-name sym)
|
|
nil ;; type
|
|
nil ;; value - ignore for now
|
|
))
|
|
((and (eq toktype 'type) (class-p sym))
|
|
(semantic-tag-new-type
|
|
(symbol-name sym)
|
|
"class"
|
|
(semantic-elisp-desymbolify
|
|
(let ((class (find-class sym)))
|
|
(if (fboundp 'eieio--class-public-a) ; Emacs < 25.1
|
|
(eieio--class-public-a class)
|
|
(mapcar #'eieio-slot-descriptor-name
|
|
(eieio-class-slots class)))))
|
|
(semantic-elisp-desymbolify (eieio-class-parents sym)) ;; parents
|
|
))
|
|
((not toktype)
|
|
;; Figure it out on our own.
|
|
(cond ((class-p sym)
|
|
(semanticdb-elisp-sym->tag sym 'type))
|
|
((fboundp sym)
|
|
(semanticdb-elisp-sym->tag sym 'function))
|
|
((boundp sym)
|
|
(semanticdb-elisp-sym->tag sym 'variable))
|
|
(t nil))
|
|
)
|
|
(t nil))))
|
|
|
|
;;; Search Overrides
|
|
;;
|
|
(defvar semanticdb-elisp-mapatom-collector nil
|
|
"Variable used to collect `mapatoms' output.")
|
|
|
|
(cl-defmethod semanticdb-find-tags-by-name-method
|
|
((_table semanticdb-table-emacs-lisp) name &optional tags)
|
|
"Find all tags named NAME in TABLE.
|
|
Uses `intern-soft' to match NAME to Emacs symbols.
|
|
Return a list of tags."
|
|
(if tags (cl-call-next-method)
|
|
;; No need to search. Use `intern-soft' which does the same thing for us.
|
|
(let* ((sym (intern-soft name))
|
|
(fun (semanticdb-elisp-sym->tag sym 'function))
|
|
(var (semanticdb-elisp-sym->tag sym 'variable))
|
|
(typ (semanticdb-elisp-sym->tag sym 'type))
|
|
(taglst nil)
|
|
)
|
|
(when (or fun var typ)
|
|
;; If the symbol is any of these things, build the search table.
|
|
(when var (setq taglst (cons var taglst)))
|
|
(when typ (setq taglst (cons typ taglst)))
|
|
(when fun (setq taglst (cons fun taglst)))
|
|
taglst
|
|
))))
|
|
|
|
(cl-defmethod semanticdb-find-tags-by-name-regexp-method
|
|
((_table semanticdb-table-emacs-lisp) regex &optional tags)
|
|
"Find all tags with name matching REGEX in TABLE.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Uses `apropos-internal' to find matches.
|
|
Return a list of tags."
|
|
(if tags (cl-call-next-method)
|
|
(delq nil (mapcar #'semanticdb-elisp-sym->tag
|
|
(apropos-internal regex)))))
|
|
|
|
(cl-defmethod semanticdb-find-tags-for-completion-method
|
|
((_table semanticdb-table-emacs-lisp) prefix &optional tags)
|
|
"In TABLE, find all occurrences of tags matching PREFIX.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Returns a table of all matching tags."
|
|
(if tags (cl-call-next-method)
|
|
(delq nil (mapcar #'semanticdb-elisp-sym->tag
|
|
(all-completions prefix obarray)))))
|
|
|
|
(cl-defmethod semanticdb-find-tags-by-class-method
|
|
((_table semanticdb-table-emacs-lisp) _class &optional tags)
|
|
"In TABLE, find all occurrences of tags of CLASS.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Returns a table of all matching tags."
|
|
(if tags (cl-call-next-method)
|
|
;; We could implement this, but it could be messy.
|
|
nil))
|
|
|
|
;;; Deep Searches
|
|
;;
|
|
;; For Emacs Lisp deep searches are like top level searches.
|
|
(cl-defmethod semanticdb-deep-find-tags-by-name-method
|
|
((table semanticdb-table-emacs-lisp) name &optional tags)
|
|
"Find all tags name NAME in TABLE.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Like `semanticdb-find-tags-by-name-method' for Emacs Lisp."
|
|
(semanticdb-find-tags-by-name-method table name tags))
|
|
|
|
(cl-defmethod semanticdb-deep-find-tags-by-name-regexp-method
|
|
((table semanticdb-table-emacs-lisp) regex &optional tags)
|
|
"Find all tags with name matching REGEX in TABLE.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Like `semanticdb-find-tags-by-name-method' for Emacs Lisp."
|
|
(semanticdb-find-tags-by-name-regexp-method table regex tags))
|
|
|
|
(cl-defmethod semanticdb-deep-find-tags-for-completion-method
|
|
((table semanticdb-table-emacs-lisp) prefix &optional tags)
|
|
"In TABLE, find all occurrences of tags matching PREFIX.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Like `semanticdb-find-tags-for-completion-method' for Emacs Lisp."
|
|
(semanticdb-find-tags-for-completion-method table prefix tags))
|
|
|
|
;;; Advanced Searches
|
|
;;
|
|
(cl-defmethod semanticdb-find-tags-external-children-of-type-method
|
|
((_table semanticdb-table-emacs-lisp) type &optional tags)
|
|
"Find all nonterminals which are child elements of TYPE.
|
|
Optional argument TAGS is a list of tags to search.
|
|
Return a list of tags."
|
|
(if tags (cl-call-next-method)
|
|
;; EIEIO is the only time this matters
|
|
(when (featurep 'eieio)
|
|
(let* ((class (intern-soft type))
|
|
(taglst (when class
|
|
(delq nil
|
|
(mapcar #'semanticdb-elisp-sym->tag
|
|
;; Fancy eieio function that knows all about
|
|
;; built in methods belonging to CLASS.
|
|
(cl-generic-all-functions class)))))
|
|
)
|
|
taglst))))
|
|
|
|
(provide 'semantic/db-el)
|
|
|
|
;;; semantic/db-el.el ends here
|