mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-13 17:40:22 -08:00
Remove a few more redundant `:group` args. Make use of lexical scoping to replace `(lambda...) with proper closures. * lisp/cedet/ede/custom.el (ede-project-sort-targets-list): Use `dotimes` and replace `(lambda..) with closures. * lisp/cedet/ede/proj-comp.el (proj-comp-insert-variable-once): * lisp/cedet/ede/pmake.el (ede-pmake-insert-variable-once): Remove unused var `addcr`. * lisp/cedet/semantic/complete.el: Use lexical-binding. (semantic-displayer-show-request): Remove unused var `typing-count`. Use `equal` instead of `stringp+string=`. * lisp/cedet/semantic/db-ebrowse.el: Use lexical-binding. (semanticdb-create-ebrowse-database): Remove unused vars `mma` and `regexp`. (semanticdb-ebrowse-strip-trees): Remove unused var `class` and `filename`. (semanticdb-ebrowse-add-globals-to-table): Remove unused var `fname`. * lisp/cedet/semantic/db-find.el: Use lexical-binding. (semanticdb-find-adebug-insert-scanned-tag-cons): Remove always-nil var `tip`. * lisp/cedet/semantic/db-global.el: Use lexical-binding. (semanticdb-enable-gnu-global-databases): Access local var `semantic--ih` by sticking its value in the code passed to `eval` rather than by dynamic scoping. * lisp/cedet/semantic/db-typecache.el: Use lexical-binding. (semanticdb-db-typecache-dump): Remove unused var `junk`. * lisp/cedet/semantic/debug.el: Use lexical-binding. * lisp/cedet/semantic/dep.el: Use lexical-binding. (semantic-add-system-include): Avoid `add-to-list` on a local variable. Access local var `value` by sticking its value in the code passed to `eval` rather than by dynamic scoping. (semantic-remove-system-include): Don't use `delete` on a list received from elsewhere. Access local var `value` by sticking its value in the code passed to `eval` rather than by dynamic scoping. (semantic-reset-system-include): Simplify a bit. * lisp/cedet/semantic/ede-grammar.el: Use lexical-binding. (project-compile-target): Remove unused vars `csrc` and `cb`. Use `cl-incf`. Remove apparently unneeded `with-no-warnings`. * lisp/cedet/semantic/edit.el: Use lexical-binding. (semantic-edits-change-over-tags): Remove unused var `inner-start`. (semantic-edits-incremental-parser-1): Silence warnings about intentionally unused var `last-cond`. * lisp/cedet/semantic/fw.el: Use lexical-binding. (recentf-exclude, semantic-init-hook, ede-auto-add-method) (flymake-start-syntax-check-on-find-file, auto-insert): Declare vars. * lisp/cedet/semantic/ia-sb.el: Use lexical-binding. (semantic-ia-sb-key-map): Move initialization into declaration. (semantic-ia-sb-more-buttons): Remove unused var `idx`. (semantic-ia-sb-line-path): Simplify `if` -> `or`. * lisp/cedet/semantic/idle.el (semantic-idle-breadcrumbs--tag-function): Make it a function returning a closure. * lisp/cedet/semantic/senator.el: Use lexical-binding. (senator-search-set-tag-class-filter): Replace `(lambda..) with a closure. * lisp/cedet/semantic/sort.el: Use lexical-binding. (semanticdb-search-system-databases): Declare var. (semantic-tag-external-member-children-default): Replace `(lambda..) with a closure. * lisp/cedet/semantic/tag-ls.el: Use lexical-binding. (semantic-tag-protection-default, semantic-tag-abstract-p-default): Simplify with `member`. * lisp/cedet/semantic/util.el: Use lexical-binding. (semantic-something-to-tag-table): Declare function `semanticdb-abstract-table--eieio-childp` called via `cl-typep`. * lisp/cedet/semantic/bovine/scm.el (semantic-default-scheme-setup): Remove duplicate setting of `imenu-create-index-function`. * lisp/cedet/semantic/decorate/mode.el (semantic-decoration-build-style-menu): Replace `(lambda..) with a closure. * lisp/cedet/srecode/cpp.el (srecode-semantic-apply-tag-to-dict): Remove always-t variable `member`. * lisp/cedet/srecode/mode.el (srecode-minor-mode-templates-menu): Replace `(lambda..) with a closure. Use `push`. * lisp/cedet/semantic/chart.el: Use lexical-binding. * lisp/cedet/semantic/db-debug.el: Use lexical-binding. * lisp/cedet/semantic/db-el.el: Use lexical-binding. * lisp/cedet/semantic/db-file.el: Use lexical-binding. * lisp/cedet/semantic/db-javascript.el: Use lexical-binding. * lisp/cedet/semantic/db-mode.el: Use lexical-binding. * lisp/cedet/semantic/db-ref.el: Use lexical-binding. * lisp/cedet/semantic/decorate.el: Use lexical-binding. * lisp/cedet/semantic/doc.el: Use lexical-binding. * lisp/cedet/semantic/find.el: Use lexical-binding. * lisp/cedet/semantic/format.el: Use lexical-binding. * lisp/cedet/semantic/html.el: Use lexical-binding. * lisp/cedet/semantic/ia.el: Use lexical-binding. * lisp/cedet/semantic/imenu.el: Use lexical-binding. * lisp/cedet/semantic/java.el: Use lexical-binding. * lisp/cedet/semantic/mru-bookmark.el: Use lexical-binding. * lisp/cedet/semantic/symref.el: Use lexical-binding. * lisp/cedet/semantic/tag-file.el: Use lexical-binding. * lisp/cedet/semantic/tag-write.el: Use lexical-binding. * lisp/cedet/semantic/texi.el: Use lexical-binding. * lisp/cedet/semantic/util-modes.el: Use lexical-binding.
352 lines
13 KiB
EmacsLisp
352 lines
13 KiB
EmacsLisp
;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp -*- lexical-binding: t; -*-
|
|
|
|
;; Copyright (C) 2002-2021 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 (condition-case nil
|
|
(interactive-form sym)
|
|
(error nil)))))
|
|
((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))))
|
|
|
|
(define-obsolete-function-alias 'semanticdb-elisp-sym-function-arglist
|
|
#'help-function-arglist "24.3")
|
|
|
|
(provide 'semantic/db-el)
|
|
|
|
;;; semantic/db-el.el ends here
|