Commit | Line | Data |
---|---|---|
aa8724ae | 1 | ;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse. |
f273dfc6 | 2 | |
9bf6c65c GM |
3 | ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 |
4 | ;; Free Software Foundation, Inc. | |
f273dfc6 | 5 | |
aef8fbf1 GM |
6 | ;; Authors: Eric M. Ludlam <zappo@gnu.org> |
7 | ;; Joakim Verona | |
f273dfc6 CY |
8 | ;; Keywords: tags |
9 | ||
10 | ;; This file is part of GNU Emacs. | |
11 | ||
12 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
13 | ;; it under the terms of the GNU General Public License as published by | |
14 | ;; the Free Software Foundation, either version 3 of the License, or | |
15 | ;; (at your option) any later version. | |
16 | ||
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
24 | ||
25 | ;;; Commentary: | |
26 | ;; | |
27 | ;; This program was started by Eric Ludlam, and Joakim Verona finished | |
28 | ;; the implementation by adding searches and fixing bugs. | |
29 | ;; | |
30 | ;; Read in custom-created ebrowse BROWSE files into a semanticdb back | |
31 | ;; end. | |
32 | ;; | |
33 | ;; Add these databases to the 'system' search. | |
34 | ;; Possibly use ebrowse for local parsing too. | |
35 | ;; | |
36 | ;; When real details are needed out of the tag system from ebrowse, | |
37 | ;; we will need to delve into the originating source and parse those | |
38 | ;; files the usual way. | |
39 | ;; | |
40 | ;; COMMANDS: | |
41 | ;; `semanticdb-create-ebrowse-database' - Call EBROWSE to create a | |
42 | ;; system database for some directory. In general, use this for | |
43 | ;; system libraries, such as /usr/include, or include directories | |
44 | ;; large software projects. | |
45 | ;; Customize `semanticdb-ebrowse-file-match' to make sure the correct | |
46 | ;; file extensions are matched. | |
47 | ;; | |
48 | ;; `semanticdb-load-ebrowse-caches' - Load all the EBROWSE caches from | |
49 | ;; your semanticdb system database directory. Once they are | |
50 | ;; loaded, they become searchable as omnipotent databases for | |
51 | ;; all C++ files. This is called automatically by semantic-load. | |
52 | ;; Call it a second time to refresh the Emacs DB with the file. | |
53 | ;; | |
54 | ||
b90caf50 CY |
55 | (require 'ebrowse) |
56 | (require 'semantic) | |
57 | (require 'semantic/db-file) | |
58 | ||
f273dfc6 CY |
59 | (eval-when-compile |
60 | ;; For generic function searching. | |
61 | (require 'eieio) | |
62 | (require 'eieio-opt) | |
b90caf50 | 63 | (require 'semantic/find)) |
aa8724ae CY |
64 | |
65 | (declare-function semantic-add-system-include "semantic/dep") | |
f273dfc6 | 66 | |
f273dfc6 CY |
67 | ;;; Code: |
68 | (defvar semanticdb-ebrowse-default-file-name "BROWSE" | |
69 | "The EBROWSE file name used for system caches.") | |
70 | ||
71 | (defcustom semanticdb-ebrowse-file-match "\\.\\(hh?\\|HH?\\|hpp\\)" | |
72 | "Regular expression matching file names for ebrowse to parse. | |
73 | This expression should exclude C++ headers that have no extension. | |
74 | By default, include only headers since the semantic use of EBrowse | |
75 | is only for searching via semanticdb, and thus only headers would | |
76 | be searched." | |
77 | :group 'semanticdb | |
78 | :type 'string) | |
79 | ||
aa8724ae CY |
80 | ;;; SEMANTIC Database related Code |
81 | ;;; Classes: | |
82 | (defclass semanticdb-table-ebrowse (semanticdb-table) | |
83 | ((major-mode :initform c++-mode) | |
84 | (ebrowse-tree :initform nil | |
85 | :initarg :ebrowse-tree | |
86 | :documentation | |
87 | "The raw ebrowse tree for this file." | |
88 | ) | |
89 | (global-extract :initform nil | |
90 | :initarg :global-extract | |
91 | :documentation | |
92 | "Table of ebrowse tags specific to this file. | |
93 | This table is compisited from the ebrowse *Globals* section.") | |
94 | ) | |
95 | "A table for returning search results from ebrowse.") | |
96 | ||
97 | (defclass semanticdb-project-database-ebrowse | |
98 | (semanticdb-project-database) | |
99 | ((new-table-class :initform semanticdb-table-ebrowse | |
100 | :type class | |
101 | :documentation | |
102 | "New tables created for this database are of this class.") | |
103 | (system-include-p :initform nil | |
104 | :initarg :system-include | |
105 | :documentation | |
106 | "Flag indicating this database represents a system include directory.") | |
107 | (ebrowse-struct :initform nil | |
108 | :initarg :ebrowse-struct | |
109 | ) | |
110 | ) | |
111 | "Semantic Database deriving tags using the EBROWSE tool. | |
112 | EBROWSE is a C/C++ parser for use with `ebrowse' Emacs program.") | |
113 | ||
114 | ||
f273dfc6 CY |
115 | (defun semanticdb-ebrowse-C-file-p (file) |
116 | "Is FILE a C or C++ file?" | |
117 | (or (string-match semanticdb-ebrowse-file-match file) | |
118 | (and (string-match "/\\w+$" file) | |
119 | (not (file-directory-p file)) | |
120 | (let ((tmp (get-buffer-create "*semanticdb-ebrowse-tmp*"))) | |
121 | (save-excursion | |
122 | (set-buffer tmp) | |
123 | (condition-case nil | |
124 | (insert-file-contents file nil 0 100 t) | |
125 | (error (insert-file-contents file nil nil nil t))) | |
126 | (goto-char (point-min)) | |
127 | (looking-at "\\s-*/\\(\\*\\|/\\)") | |
128 | )) | |
129 | ))) | |
130 | ||
131 | (defun semanticdb-create-ebrowse-database (dir) | |
132 | "Create an EBROSE database for directory DIR. | |
133 | The database file is stored in ~/.semanticdb, or whichever directory | |
134 | is specified by `semanticdb-default-save-directory'." | |
135 | (interactive "DDirectory: ") | |
136 | (setq dir (file-name-as-directory dir)) ;; for / on end | |
137 | (let* ((savein (semanticdb-ebrowse-file-for-directory dir)) | |
138 | (filebuff (get-buffer-create "*SEMANTICDB EBROWSE TMP*")) | |
139 | (files (directory-files (expand-file-name dir) t)) | |
140 | (mma auto-mode-alist) | |
141 | (regexp nil) | |
142 | ) | |
143 | ;; Create the input to the ebrowse command | |
144 | (save-excursion | |
145 | (set-buffer filebuff) | |
146 | (buffer-disable-undo filebuff) | |
147 | (setq default-directory (expand-file-name dir)) | |
148 | ||
149 | ;;; @TODO - convert to use semanticdb-collect-matching-filenames | |
150 | ;; to get the file names. | |
151 | ||
152 | ||
a4bdf715 CY |
153 | (mapc (lambda (f) |
154 | (when (semanticdb-ebrowse-C-file-p f) | |
155 | (insert f) | |
156 | (insert "\n"))) | |
157 | files) | |
f273dfc6 CY |
158 | ;; Cleanup the ebrowse output buffer. |
159 | (save-excursion | |
160 | (set-buffer (get-buffer-create "*EBROWSE OUTPUT*")) | |
161 | (erase-buffer)) | |
162 | ;; Call the EBROWSE command. | |
163 | (message "Creating ebrowse file: %s ..." savein) | |
164 | (call-process-region (point-min) (point-max) | |
165 | "ebrowse" nil "*EBROWSE OUTPUT*" nil | |
166 | (concat "--output-file=" savein) | |
167 | "--very-verbose") | |
168 | ) | |
169 | ;; Create a short LOADER program for loading in this database. | |
170 | (let* ((lfn (concat savein "-load.el")) | |
171 | (lf (find-file-noselect lfn))) | |
172 | (save-excursion | |
173 | (set-buffer lf) | |
174 | (erase-buffer) | |
175 | (insert "(semanticdb-ebrowse-load-helper \"" | |
176 | (expand-file-name dir) | |
177 | "\")\n") | |
178 | (save-buffer) | |
179 | (kill-buffer (current-buffer))) | |
180 | (message "Creating ebrowse file: %s ... done" savein) | |
181 | ;; Reload that database | |
182 | (load lfn nil t) | |
183 | ))) | |
184 | ||
185 | (defun semanticdb-load-ebrowse-caches () | |
186 | "Load all semanticdb controlled EBROWSE caches." | |
187 | (interactive) | |
188 | (let ((f (directory-files semanticdb-default-save-directory | |
189 | t (concat semanticdb-ebrowse-default-file-name "-load.el$") t))) | |
190 | (while f | |
191 | (load (car f) nil t) | |
192 | (setq f (cdr f))) | |
193 | )) | |
194 | ||
195 | (defun semanticdb-ebrowse-load-helper (directory) | |
196 | "Create the semanticdb database via ebrowse for directory. | |
197 | If DIRECTORY is found to be defunct, it won't load the DB, and will | |
198 | warn instead." | |
199 | (if (file-directory-p directory) | |
200 | (semanticdb-create-database semanticdb-project-database-ebrowse | |
201 | directory) | |
202 | (let* ((BF (semanticdb-ebrowse-file-for-directory directory)) | |
203 | (BFL (concat BF "-load.el")) | |
204 | (BFLB (concat BF "-load.el~"))) | |
205 | (save-window-excursion | |
206 | (with-output-to-temp-buffer "*FILES TO DELETE*" | |
207 | (princ "The following BROWSE files are obsolete.\n\n") | |
208 | (princ BF) | |
209 | (princ "\n") | |
210 | (princ BFL) | |
211 | (princ "\n") | |
212 | (when (file-exists-p BFLB) | |
213 | (princ BFLB) | |
214 | (princ "\n")) | |
215 | ) | |
216 | (when (y-or-n-p (format | |
217 | "Warning: Obsolete BROWSE file for: %s\nDelete? " | |
218 | directory)) | |
219 | (delete-file BF) | |
220 | (delete-file BFL) | |
221 | (when (file-exists-p BFLB) | |
222 | (delete-file BFLB)) | |
223 | ))))) | |
224 | ||
f273dfc6 CY |
225 | ;JAVE this just instantiates a default empty ebrowse struct? |
226 | ; how would new instances wind up here? | |
227 | ; the ebrowse class isnt singleton, unlike the emacs lisp one | |
228 | (defvar-mode-local c++-mode semanticdb-project-system-databases | |
229 | () | |
230 | "Search Ebrowse for symbols.") | |
231 | ||
232 | (defmethod semanticdb-needs-refresh-p ((table semanticdb-table-ebrowse)) | |
233 | "EBROWSE database do not need to be refreshed. | |
234 | ||
235 | JAVE: stub for needs-refresh, because, how do we know if BROWSE files | |
236 | are out of date? | |
237 | ||
238 | EML: Our database should probably remember the timestamp/checksum of | |
239 | the most recently read EBROWSE file, and use that." | |
240 | nil | |
241 | ) | |
242 | ||
243 | ||
244 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
245 | ||
246 | ||
247 | ||
248 | ;;; EBROWSE code | |
249 | ;; | |
250 | ;; These routines deal with part of the ebrowse interface. | |
251 | (defun semanticdb-ebrowse-file-for-directory (dir) | |
252 | "Return the file name for DIR where the ebrowse BROWSE file is. | |
253 | This file should reside in `semanticdb-default-save-directory'." | |
254 | (let* ((semanticdb-default-save-directory | |
255 | semanticdb-default-save-directory) | |
256 | (B (semanticdb-file-name-directory | |
257 | 'semanticdb-project-database-file | |
258 | (concat (expand-file-name dir) | |
259 | semanticdb-ebrowse-default-file-name))) | |
260 | ) | |
261 | B)) | |
262 | ||
263 | (defun semanticdb-ebrowse-get-ebrowse-structure (dir) | |
264 | "Return the ebrowse structure for directory DIR. | |
265 | This assumes semantic manages the BROWSE files, so they are assumed to live | |
266 | where semantic cache files live, depending on your settings. | |
267 | ||
268 | For instance: /home/<username>/.semanticdb/!usr!include!BROWSE" | |
269 | (let* ((B (semanticdb-ebrowse-file-for-directory dir)) | |
270 | (buf (get-buffer-create "*semanticdb ebrowse*"))) | |
271 | (message "semanticdb-ebrowse %s" B) | |
272 | (when (file-exists-p B) | |
273 | (set-buffer buf) | |
274 | (buffer-disable-undo buf) | |
275 | (erase-buffer) | |
276 | (insert-file-contents B) | |
277 | (let ((ans nil) | |
278 | (efcn (symbol-function 'ebrowse-show-progress))) | |
279 | (fset 'ebrowse-show-progress #'(lambda (&rest junk) nil)) | |
280 | (unwind-protect ;; Protect against errors w/ ebrowse | |
281 | (setq ans (list B (ebrowse-read))) | |
282 | ;; These items must always happen | |
283 | (erase-buffer) | |
284 | (fset 'ebrowse-show-fcn efcn) | |
285 | ) | |
286 | ans)))) | |
287 | ||
288 | ;;; Methods for creating a database or tables | |
289 | ;; | |
290 | (defmethod semanticdb-create-database :STATIC ((dbeC semanticdb-project-database-ebrowse) | |
291 | directory) | |
292 | "Create a new semantic database for DIRECTORY based on ebrowse. | |
293 | If there is no database for DIRECTORY available, then | |
294 | {not implemented yet} create one. Return nil if that is not possible." | |
295 | ;; MAKE SURE THAT THE FILE LOADED DOESN'T ALREADY EXIST. | |
aa8724ae | 296 | (require 'semantic/dep) |
f273dfc6 CY |
297 | (let ((dbs semanticdb-database-list) |
298 | (found nil)) | |
299 | (while (and (not found) dbs) | |
300 | (when (semanticdb-project-database-ebrowse-p (car dbs)) | |
301 | (when (string= (oref (car dbs) reference-directory) directory) | |
302 | (setq found (car dbs)))) | |
303 | (setq dbs (cdr dbs))) | |
304 | ;;STATIC means DBE cant be used as object, only as a class | |
305 | (let* ((ebrowse-data (semanticdb-ebrowse-get-ebrowse-structure directory)) | |
306 | (dat (car (cdr ebrowse-data))) | |
307 | (ebd (car dat)) | |
308 | (db nil) | |
309 | (default-directory directory) | |
310 | ) | |
311 | (if found | |
312 | (setq db found) | |
313 | (setq db (make-instance | |
314 | dbeC | |
315 | directory | |
316 | :ebrowse-struct ebd | |
317 | )) | |
318 | (oset db reference-directory directory)) | |
319 | ||
320 | ;; Once we recycle or make a new DB, refresh the | |
321 | ;; contents from the BROWSE file. | |
322 | (oset db tables nil) | |
323 | ;; only possible after object creation, tables inited to nil. | |
324 | (semanticdb-ebrowse-strip-trees db dat) | |
325 | ||
326 | ;; Once our database is loaded, if we are a system DB, we | |
327 | ;; add ourselves to the include list for C++. | |
328 | (semantic-add-system-include directory 'c++-mode) | |
329 | (semantic-add-system-include directory 'c-mode) | |
330 | ||
331 | db))) | |
332 | ||
333 | (defmethod semanticdb-ebrowse-strip-trees ((dbe semanticdb-project-database-ebrowse) | |
334 | data) | |
335 | "For the ebrowse database DBE, strip all tables from DATA." | |
336 | ;JAVE what it actually seems to do is split the original tree in "tables" associated with files | |
337 | ; im not sure it actually works: | |
338 | ; the filename slot sometimes gets to be nil, | |
339 | ; apparently for classes which definition cant be found, yet needs to be included in the tree | |
340 | ; like library baseclasses | |
341 | ; a file can define several classes | |
342 | (let ((T (car (cdr data))));1st comes a header, then the tree | |
343 | (while T | |
344 | ||
345 | (let* ((tree (car T)) | |
346 | (class (ebrowse-ts-class tree)); root class of tree | |
347 | ;; Something funny going on with this file thing... | |
348 | (filename (or (ebrowse-cs-source-file class) | |
349 | (ebrowse-cs-file class))) | |
350 | ) | |
351 | (cond | |
352 | ((ebrowse-globals-tree-p tree) | |
353 | ;; We have the globals tree.. save this special. | |
354 | (semanticdb-ebrowse-add-globals-to-table dbe tree) | |
355 | ) | |
356 | (t | |
357 | ;; ebrowse will collect all the info from multiple files | |
358 | ;; into one tree. Semantic wants all the bits to be tied | |
359 | ;; into different files. We need to do a full dissociation | |
360 | ;; into semantic parsable tables. | |
361 | (semanticdb-ebrowse-add-tree-to-table dbe tree) | |
362 | )) | |
363 | (setq T (cdr T)))) | |
364 | )) | |
365 | ||
366 | ;;; Filename based methods | |
367 | ;; | |
368 | (defun semanticdb-ebrowse-add-globals-to-table (dbe tree) | |
369 | "For database DBE, add the ebrowse TREE into the table." | |
370 | (if (or (not (ebrowse-ts-p tree)) | |
371 | (not (ebrowse-globals-tree-p tree))) | |
372 | (signal 'wrong-type-argument (list 'ebrowse-ts-p tree))) | |
373 | ||
374 | (let* ((class (ebrowse-ts-class tree)) | |
375 | (fname (or (ebrowse-cs-source-file class) | |
376 | (ebrowse-cs-file class) | |
377 | ;; Not def'd here, assume our current | |
378 | ;; file | |
379 | (concat default-directory "/unknown-proxy.hh"))) | |
380 | (vars (ebrowse-ts-member-functions tree)) | |
381 | (fns (ebrowse-ts-member-variables tree)) | |
382 | (toks nil) | |
383 | ) | |
384 | (while vars | |
385 | (let ((nt (semantic-tag (ebrowse-ms-name (car vars)) | |
386 | 'variable)) | |
387 | (defpoint (ebrowse-bs-point class))) | |
388 | (when defpoint | |
389 | (semantic--tag-set-overlay nt | |
390 | (vector defpoint defpoint))) | |
391 | (setq toks (cons nt toks))) | |
392 | (setq vars (cdr vars))) | |
393 | (while fns | |
394 | (let ((nt (semantic-tag (ebrowse-ms-name (car fns)) | |
395 | 'function)) | |
396 | (defpoint (ebrowse-bs-point class))) | |
397 | (when defpoint | |
398 | (semantic--tag-set-overlay nt | |
399 | (vector defpoint defpoint))) | |
400 | (setq toks (cons nt toks))) | |
401 | (setq fns (cdr fns))) | |
402 | ||
403 | )) | |
404 | ||
405 | (defun semanticdb-ebrowse-add-tree-to-table (dbe tree &optional fname baseclasses) | |
406 | "For database DBE, add the ebrowse TREE into the table for FNAME. | |
9bf6c65c | 407 | Optional argument BASECLASSES specifies a baseclass to the tree being provided." |
f273dfc6 CY |
408 | (if (not (ebrowse-ts-p tree)) |
409 | (signal 'wrong-type-argument (list 'ebrowse-ts-p tree))) | |
410 | ||
411 | ;; Strategy overview: | |
412 | ;; 1) Calculate the filename for this tree. | |
413 | ;; 2) Find a matching namespace in TAB, or create a new one. | |
414 | ;; 3) Fabricate a tag proxy for CLASS | |
415 | ;; 4) Add it to the namespace | |
416 | ;; 5) Add subclasses | |
417 | ||
418 | ;; 1 - Find the filename | |
419 | (if (not fname) | |
420 | (setq fname (or (ebrowse-cs-source-file (ebrowse-ts-class tree)) | |
421 | (ebrowse-cs-file (ebrowse-ts-class tree)) | |
422 | ;; Not def'd here, assume our current | |
423 | ;; file | |
424 | (concat default-directory "/unknown-proxy.hh")))) | |
425 | ||
426 | (let* ((tab (or (semanticdb-file-table dbe fname) | |
427 | (semanticdb-create-table dbe fname))) | |
428 | (class (ebrowse-ts-class tree)) | |
429 | (scope (ebrowse-cs-scope class)) | |
aa8724ae | 430 | (ns (when scope (split-string scope ":" t))) |
f273dfc6 CY |
431 | (nst nil) |
432 | (cls nil) | |
433 | ) | |
434 | ||
435 | ;; 2 - Get the namespace tag | |
436 | (when ns | |
437 | (let ((taglst (if (slot-boundp tab 'tags) (oref tab tags) nil))) | |
438 | (setq nst (semantic-find-first-tag-by-name (car ns) taglst)) | |
439 | (when (not nst) | |
440 | (setq nst (semantic-tag (car ns) 'type :type "namespace")) | |
441 | (oset tab tags (cons nst taglst)) | |
442 | ))) | |
443 | ||
444 | ;; 3 - Create a proxy tg. | |
445 | (setq cls (semantic-tag (ebrowse-cs-name class) | |
446 | 'type | |
447 | :type "class" | |
448 | :superclasses baseclasses | |
449 | :faux t | |
450 | :filename fname | |
451 | )) | |
452 | (let ((defpoint (ebrowse-bs-point class))) | |
453 | (when defpoint | |
454 | (semantic--tag-set-overlay cls | |
455 | (vector defpoint defpoint)))) | |
456 | ||
457 | ;; 4 - add to namespace | |
458 | (if nst | |
459 | (semantic-tag-put-attribute | |
460 | nst :members (cons cls (semantic-tag-get-attribute nst :members))) | |
461 | (oset tab tags (cons cls (when (slot-boundp tab 'tags) | |
462 | (oref tab tags))))) | |
463 | ||
464 | ;; 5 - Subclasses | |
465 | (let* ((subclass (ebrowse-ts-subclasses tree)) | |
466 | (pname (ebrowse-cs-name class))) | |
467 | (when (ebrowse-cs-scope class) | |
468 | (setq pname (concat (mapconcat (lambda (a) a) (cdr ns) "::") "::" pname))) | |
469 | ||
470 | (while subclass | |
471 | (let* ((scc (ebrowse-ts-class (car subclass))) | |
472 | (fname (or (ebrowse-cs-source-file scc) | |
473 | (ebrowse-cs-file scc) | |
474 | ;; Not def'd here, assume our current | |
475 | ;; file | |
476 | fname | |
477 | ))) | |
478 | (when fname | |
479 | (semanticdb-ebrowse-add-tree-to-table | |
480 | dbe (car subclass) fname pname))) | |
481 | (setq subclass (cdr subclass)))) | |
482 | )) | |
483 | ||
484 | ;;; | |
485 | ;; Overload for converting the simple faux tag into something better. | |
486 | ;; | |
487 | (defmethod semanticdb-normalize-tags ((obj semanticdb-table-ebrowse) tags) | |
488 | "Convert in Ebrowse database OBJ a list of TAGS into a complete tag. | |
489 | The default tag provided by searches exclude many features of a | |
490 | semantic parsed tag. Look up the file for OBJ, and match TAGS | |
491 | against a semantic parsed tag that has all the info needed, and | |
492 | return that." | |
493 | (let ((tagret nil) | |
494 | ) | |
495 | ;; SemanticDB will automatically create a regular database | |
496 | ;; on top of the file just loaded by ebrowse during the set | |
497 | ;; buffer. Fetch that table, and use it's tag list to look | |
498 | ;; up the tag we just got, and thus turn it into a full semantic | |
499 | ;; tag. | |
500 | (while tags | |
501 | (let ((tag (car tags))) | |
502 | (save-excursion | |
503 | (semanticdb-set-buffer obj) | |
504 | (let ((ans nil)) | |
505 | ;; Gee, it would be nice to do this, but ebrowse LIES. Oi. | |
506 | (when (semantic-tag-with-position-p tag) | |
507 | (goto-char (semantic-tag-start tag)) | |
508 | (let ((foundtag (semantic-current-tag))) | |
509 | ;; Make sure the discovered tag is the same as what we started with. | |
510 | (when (string= (semantic-tag-name tag) | |
511 | (semantic-tag-name foundtag)) | |
512 | ;; We have a winner! | |
513 | (setq ans foundtag)))) | |
514 | ;; Sometimes ebrowse lies. Do a generic search | |
515 | ;; to find it within this file. | |
516 | (when (not ans) | |
517 | ;; We might find multiple hits for this tag, and we have no way | |
518 | ;; of knowing which one the user wanted. Return the first one. | |
519 | (setq ans (semantic-deep-find-tags-by-name | |
520 | (semantic-tag-name tag) | |
521 | (semantic-fetch-tags)))) | |
522 | (if (semantic-tag-p ans) | |
523 | (setq tagret (cons ans tagret)) | |
524 | (setq tagret (append ans tagret))) | |
525 | )) | |
526 | (setq tags (cdr tags)))) | |
527 | tagret)) | |
528 | ||
529 | (defmethod semanticdb-normalize-one-tag ((obj semanticdb-table-ebrowse) tag) | |
530 | "Convert in Ebrowse database OBJ one TAG into a complete tag. | |
531 | The default tag provided by searches exclude many features of a | |
532 | semantic parsed tag. Look up the file for OBJ, and match TAG | |
533 | against a semantic parsed tag that has all the info needed, and | |
534 | return that." | |
535 | (let ((tagret nil) | |
536 | (objret nil)) | |
537 | ;; SemanticDB will automatically create a regular database | |
538 | ;; on top of the file just loaded by ebrowse during the set | |
539 | ;; buffer. Fetch that table, and use it's tag list to look | |
540 | ;; up the tag we just got, and thus turn it into a full semantic | |
541 | ;; tag. | |
542 | (save-excursion | |
543 | (semanticdb-set-buffer obj) | |
544 | (setq objret semanticdb-current-table) | |
545 | (when (not objret) | |
546 | ;; What to do?? | |
547 | (debug)) | |
548 | (let ((ans nil)) | |
549 | ;; Gee, it would be nice to do this, but ebrowse LIES. Oi. | |
550 | (when (semantic-tag-with-position-p tag) | |
551 | (goto-char (semantic-tag-start tag)) | |
552 | (let ((foundtag (semantic-current-tag))) | |
553 | ;; Make sure the discovered tag is the same as what we started with. | |
554 | (when (string= (semantic-tag-name tag) | |
555 | (semantic-tag-name foundtag)) | |
556 | ;; We have a winner! | |
557 | (setq ans foundtag)))) | |
558 | ;; Sometimes ebrowse lies. Do a generic search | |
559 | ;; to find it within this file. | |
560 | (when (not ans) | |
561 | ;; We might find multiple hits for this tag, and we have no way | |
562 | ;; of knowing which one the user wanted. Return the first one. | |
563 | (setq ans (semantic-deep-find-tags-by-name | |
564 | (semantic-tag-name tag) | |
565 | (semantic-fetch-tags)))) | |
566 | (if (semantic-tag-p ans) | |
567 | (setq tagret ans) | |
568 | (setq tagret (car ans))) | |
569 | )) | |
570 | (cons objret tagret))) | |
571 | ||
572 | ;;; Search Overrides | |
573 | ;; | |
574 | ;; NOTE WHEN IMPLEMENTING: Be sure to add doc-string updates explaining | |
575 | ;; how your new search routines are implemented. | |
576 | ;; | |
577 | (defmethod semanticdb-find-tags-by-name-method | |
578 | ((table semanticdb-table-ebrowse) name &optional tags) | |
579 | "Find all tags named NAME in TABLE. | |
580 | Return a list of tags." | |
581 | ;;(message "semanticdb-find-tags-by-name-method name -- %s" name) | |
582 | (if tags | |
583 | ;; If TAGS are passed in, then we don't need to do work here. | |
584 | (call-next-method) | |
585 | ;; If we ever need to do something special, add here. | |
586 | ;; Since ebrowse tags are converted into semantic tags, we can | |
587 | ;; get away with this sort of thing. | |
588 | (call-next-method) | |
589 | ) | |
590 | ) | |
591 | ||
592 | (defmethod semanticdb-find-tags-by-name-regexp-method | |
593 | ((table semanticdb-table-ebrowse) regex &optional tags) | |
594 | "Find all tags with name matching REGEX in TABLE. | |
595 | Optional argument TAGS is a list of tags to search. | |
596 | Return a list of tags." | |
597 | (if tags (call-next-method) | |
598 | ;; YOUR IMPLEMENTATION HERE | |
599 | (call-next-method) | |
600 | )) | |
601 | ||
602 | (defmethod semanticdb-find-tags-for-completion-method | |
603 | ((table semanticdb-table-ebrowse) prefix &optional tags) | |
604 | "In TABLE, find all occurances of tags matching PREFIX. | |
605 | Optional argument TAGS is a list of tags to search. | |
606 | Returns a table of all matching tags." | |
607 | (if tags (call-next-method) | |
608 | ;; YOUR IMPLEMENTATION HERE | |
609 | (call-next-method) | |
610 | )) | |
611 | ||
612 | (defmethod semanticdb-find-tags-by-class-method | |
613 | ((table semanticdb-table-ebrowse) class &optional tags) | |
614 | "In TABLE, find all occurances of tags of CLASS. | |
615 | Optional argument TAGS is a list of tags to search. | |
616 | Returns a table of all matching tags." | |
617 | (if tags (call-next-method) | |
618 | (call-next-method))) | |
619 | ||
620 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
621 | ||
622 | ;;; Deep Searches | |
623 | ;; | |
624 | ;; If your language does not have a `deep' concept, these can be left | |
625 | ;; alone, otherwise replace with implementations similar to those | |
626 | ;; above. | |
627 | ;; | |
628 | ||
629 | (defmethod semanticdb-deep-find-tags-by-name-method | |
630 | ((table semanticdb-table-ebrowse) name &optional tags) | |
631 | "Find all tags name NAME in TABLE. | |
632 | Optional argument TAGS is a list of tags t | |
633 | Like `semanticdb-find-tags-by-name-method' for ebrowse." | |
634 | ;;(semanticdb-find-tags-by-name-method table name tags) | |
635 | (call-next-method)) | |
636 | ||
637 | (defmethod semanticdb-deep-find-tags-by-name-regexp-method | |
638 | ((table semanticdb-table-ebrowse) regex &optional tags) | |
639 | "Find all tags with name matching REGEX in TABLE. | |
640 | Optional argument TAGS is a list of tags to search. | |
641 | Like `semanticdb-find-tags-by-name-method' for ebrowse." | |
642 | ;;(semanticdb-find-tags-by-name-regexp-method table regex tags) | |
643 | (call-next-method)) | |
644 | ||
645 | (defmethod semanticdb-deep-find-tags-for-completion-method | |
646 | ((table semanticdb-table-ebrowse) prefix &optional tags) | |
647 | "In TABLE, find all occurances of tags matching PREFIX. | |
648 | Optional argument TAGS is a list of tags to search. | |
649 | Like `semanticdb-find-tags-for-completion-method' for ebrowse." | |
650 | ;;(semanticdb-find-tags-for-completion-method table prefix tags) | |
651 | (call-next-method)) | |
652 | ||
653 | ;;; Advanced Searches | |
654 | ;; | |
655 | (defmethod semanticdb-find-tags-external-children-of-type-method | |
656 | ((table semanticdb-table-ebrowse) type &optional tags) | |
657 | "Find all nonterminals which are child elements of TYPE | |
658 | Optional argument TAGS is a list of tags to search. | |
659 | Return a list of tags." | |
660 | (if tags (call-next-method) | |
661 | ;; Ebrowse collects all this type of stuff together for us. | |
662 | ;; but we can't use it.... yet. | |
663 | nil | |
664 | )) | |
665 | ||
f273dfc6 CY |
666 | (provide 'semantic/db-ebrowse) |
667 | ||
3999968a | 668 | ;; arch-tag: e7d15223-6074-4c87-baf0-98fdd22ff873 |
aa8724ae | 669 | ;;; semantic/db-ebrowse.el ends here |