Commit | Line | Data |
---|---|---|
20bfd709 CY |
1 | ;;; semantic/db-global.el --- Semantic database extensions for GLOBAL |
2 | ||
3 | ;;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008, 2009 | |
4 | ;;; Free Software Foundation, Inc. | |
5 | ||
6 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
7 | ;; Keywords: tags | |
8 | ||
9 | ;; This file is part of GNU Emacs. | |
10 | ||
11 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
12 | ;; it under the terms of the GNU General Public License as published by | |
13 | ;; the Free Software Foundation, either version 3 of the License, or | |
14 | ;; (at your option) any later version. | |
15 | ||
16 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
23 | ||
24 | ;;; Commentary: | |
25 | ;; | |
26 | ;; Use GNU Global for by-name database searches. | |
27 | ;; | |
28 | ;; This will work as an "omniscient" database for a given project. | |
29 | ;; | |
30 | ||
31 | (require 'cedet-global) | |
32 | (require 'semantic/db-search) | |
33 | (require 'semantic/symref/global) | |
34 | ||
35 | (eval-when-compile | |
36 | ;; For generic function searching. | |
37 | (require 'eieio) | |
38 | (require 'eieio-opt) | |
39 | ) | |
40 | ;;; Code: | |
41 | (defun semanticdb-enable-gnu-global-databases (mode) | |
42 | "Enable the use of the GNU Global SemanticDB back end for all files of MODE. | |
43 | This will add an instance of a GNU Global database to each buffer | |
44 | in a GNU Global supported hierarchy." | |
45 | (interactive | |
46 | (list (completing-read | |
47 | "Emable in Mode: " obarray | |
48 | #'(lambda (s) (get s 'mode-local-symbol-table)) | |
49 | t (symbol-name major-mode)))) | |
50 | ||
51 | ;; First, make sure the version is ok. | |
52 | (cedet-gnu-global-version-check) | |
53 | ||
54 | ;; Make sure mode is a symbol. | |
55 | (when (stringp mode) | |
56 | (setq mode (intern mode))) | |
57 | ||
58 | (let ((ih (mode-local-value mode 'semantic-init-mode-hooks))) | |
59 | (eval `(setq-mode-local | |
60 | ,mode semantic-init-mode-hooks | |
61 | (cons 'semanticdb-enable-gnu-global-hook ih)))) | |
62 | ||
63 | ) | |
64 | ||
65 | (defun semanticdb-enable-gnu-global-hook () | |
66 | "Add support for GNU Global in the current buffer via semantic-init-hook. | |
67 | MODE is the major mode to support." | |
68 | (semanticdb-enable-gnu-global-in-buffer t)) | |
69 | ||
70 | (defun semanticdb-enable-gnu-global-in-buffer (&optional dont-err-if-not-available) | |
71 | "Enable a GNU Global database in the current buffer. | |
72 | Argument DONT-ERR-IF-NOT-AVAILABLE will throw an error if GNU Global | |
73 | is not available for this directory." | |
74 | (interactive "P") | |
75 | (if (cedet-gnu-global-root) | |
76 | (setq | |
77 | ;; Add to the system database list. | |
78 | semanticdb-project-system-databases | |
79 | (cons (semanticdb-project-database-global "global") | |
80 | semanticdb-project-system-databases) | |
81 | ;; Apply the throttle. | |
82 | semanticdb-find-default-throttle | |
83 | (append semanticdb-find-default-throttle | |
84 | '(omniscience)) | |
85 | ) | |
86 | (if dont-err-if-not-available | |
87 | (message "No Global support in %s" default-directory) | |
88 | (error "No Global support in %s" default-directory)) | |
89 | )) | |
90 | ||
91 | ;;; Classes: | |
92 | (defclass semanticdb-table-global (semanticdb-search-results-table) | |
93 | ((major-mode :initform nil) | |
94 | ) | |
95 | "A table for returning search results from GNU Global.") | |
96 | ||
97 | (defclass semanticdb-project-database-global | |
98 | ;; @todo - convert to one DB per directory. | |
99 | (semanticdb-project-database eieio-instance-tracker) | |
100 | () | |
101 | "Database representing a GNU Global tags file.") | |
102 | ||
103 | (defmethod semanticdb-equivalent-mode ((table semanticdb-table-global) &optional buffer) | |
104 | "Return t, pretend that this table's mode is equivalent to BUFFER. | |
105 | Equivalent modes are specified by by `semantic-equivalent-major-modes' | |
106 | local variable." | |
107 | ;; @todo - hack alert! | |
108 | t) | |
109 | ||
110 | ;;; Filename based methods | |
111 | ;; | |
112 | (defmethod semanticdb-get-database-tables ((obj semanticdb-project-database-global)) | |
113 | "For a global database, there are no explicit tables. | |
114 | For each file hit, get the traditional semantic table from that file." | |
115 | ;; We need to return something since there is always the "master table" | |
116 | ;; The table can then answer file name type questions. | |
117 | (when (not (slot-boundp obj 'tables)) | |
118 | (let ((newtable (semanticdb-table-global "GNU Global Search Table"))) | |
119 | (oset obj tables (list newtable)) | |
120 | (oset newtable parent-db obj) | |
121 | (oset newtable tags nil) | |
122 | )) | |
123 | ||
124 | (call-next-method)) | |
125 | ||
126 | (defmethod semanticdb-file-table ((obj semanticdb-project-database-global) filename) | |
127 | "From OBJ, return FILENAME's associated table object." | |
128 | ;; We pass in "don't load". I wonder if we need to avoid that or not? | |
129 | (car (semanticdb-get-database-tables obj)) | |
130 | ) | |
131 | ||
132 | ;;; Search Overrides | |
133 | ;; | |
134 | ;; Only NAME based searches work with GLOBAL as that is all it tracks. | |
135 | ;; | |
136 | (defmethod semanticdb-find-tags-by-name-method | |
137 | ((table semanticdb-table-global) name &optional tags) | |
138 | "Find all tags named NAME in TABLE. | |
139 | Return a list of tags." | |
140 | (if tags | |
141 | ;; If TAGS are passed in, then we don't need to do work here. | |
142 | (call-next-method) | |
143 | ;; Call out to GNU Global for some results. | |
144 | (let* ((semantic-symref-tool 'global) | |
145 | (result (semantic-symref-find-tags-by-name name 'project)) | |
146 | ) | |
147 | (when result | |
148 | ;; We could ask to keep the buffer open, but that annoys | |
149 | ;; people. | |
150 | (semantic-symref-result-get-tags result)) | |
151 | ))) | |
152 | ||
153 | (defmethod semanticdb-find-tags-by-name-regexp-method | |
154 | ((table semanticdb-table-global) regex &optional tags) | |
155 | "Find all tags with name matching REGEX in TABLE. | |
156 | Optional argument TAGS is a list of tags to search. | |
157 | Return a list of tags." | |
158 | (if tags (call-next-method) | |
159 | ;; YOUR IMPLEMENTATION HERE | |
160 | (let* ((semantic-symref-tool 'global) | |
161 | (result (semantic-symref-find-tags-by-regexp regex 'project)) | |
162 | ) | |
163 | (when result | |
164 | (semantic-symref-result-get-tags result)) | |
165 | ))) | |
166 | ||
167 | (defmethod semanticdb-find-tags-for-completion-method | |
168 | ((table semanticdb-table-global) prefix &optional tags) | |
169 | "In TABLE, find all occurances of tags matching PREFIX. | |
170 | Optional argument TAGS is a list of tags to search. | |
171 | Returns a table of all matching tags." | |
172 | (if tags (call-next-method) | |
173 | (let* ((semantic-symref-tool 'global) | |
174 | (result (semantic-symref-find-tags-by-completion prefix 'project)) | |
175 | (faketags nil) | |
176 | ) | |
177 | (when result | |
178 | (dolist (T (oref result :hit-text)) | |
179 | ;; We should look up each tag one at a time, but I'm lazy! | |
180 | ;; Doing this may be good enough. | |
181 | (setq faketags (cons | |
182 | (semantic-tag T 'function :faux t) | |
183 | faketags)) | |
184 | ) | |
185 | faketags)))) | |
186 | ||
187 | ;;; Deep Searches | |
188 | ;; | |
189 | ;; If your language does not have a `deep' concept, these can be left | |
190 | ;; alone, otherwise replace with implementations similar to those | |
191 | ;; above. | |
192 | ;; | |
193 | (defmethod semanticdb-deep-find-tags-by-name-method | |
194 | ((table semanticdb-table-global) name &optional tags) | |
195 | "Find all tags name NAME in TABLE. | |
196 | Optional argument TAGS is a list of tags t | |
197 | Like `semanticdb-find-tags-by-name-method' for global." | |
198 | (semanticdb-find-tags-by-name-method table name tags)) | |
199 | ||
200 | (defmethod semanticdb-deep-find-tags-by-name-regexp-method | |
201 | ((table semanticdb-table-global) regex &optional tags) | |
202 | "Find all tags with name matching REGEX in TABLE. | |
203 | Optional argument TAGS is a list of tags to search. | |
204 | Like `semanticdb-find-tags-by-name-method' for global." | |
205 | (semanticdb-find-tags-by-name-regexp-method table regex tags)) | |
206 | ||
207 | (defmethod semanticdb-deep-find-tags-for-completion-method | |
208 | ((table semanticdb-table-global) prefix &optional tags) | |
209 | "In TABLE, find all occurances of tags matching PREFIX. | |
210 | Optional argument TAGS is a list of tags to search. | |
211 | Like `semanticdb-find-tags-for-completion-method' for global." | |
212 | (semanticdb-find-tags-for-completion-method table prefix tags)) | |
213 | ||
214 | ;;; TEST | |
215 | ;; | |
216 | ;; Here is a testing fcn to try out searches via the GNU Global database. | |
217 | (defvar semanticdb-test-gnu-global-startfile "~/src/global-5.7.3/global/global.c" | |
218 | "File to use for testing.") | |
219 | ||
220 | (defun semanticdb-test-gnu-global (searchfor &optional standardfile) | |
221 | "Test the GNU Global semanticdb. | |
222 | Argument SEARCHFOR is the text to search for. | |
223 | If optional arg STANDARDFILE is non nil, use a standard file w/ global enabled." | |
224 | (interactive "sSearch For Tag: \nP") | |
225 | ||
226 | (require 'data-debug) | |
227 | (save-excursion | |
228 | (when standardfile | |
229 | (set-buffer (find-file-noselect semanticdb-test-gnu-global-startfile))) | |
230 | ||
231 | (condition-case err | |
232 | (semanticdb-enable-gnu-global-in-buffer) | |
233 | (error (if standardfile | |
234 | (error err) | |
235 | (set-buffer (find-file-noselect semanticdb-test-gnu-global-startfile)) | |
236 | (semanticdb-enable-gnu-global-in-buffer)))) | |
237 | ||
238 | (let* ((db (semanticdb-project-database-global "global")) | |
239 | (tab (semanticdb-file-table db (buffer-file-name))) | |
240 | (result (semanticdb-deep-find-tags-for-completion-method tab searchfor)) | |
241 | ) | |
242 | (data-debug-new-buffer "*SemanticDB Gnu Global Result*") | |
243 | (data-debug-insert-thing result "?" "") | |
244 | ))) | |
245 | ||
246 | (provide 'semantic/db-global) | |
247 | ||
248 | ;;; semantic/db-global.el ends here |