]> code.delx.au - gnu-emacs/blob - lisp/cedet/semantic/tag-ls.el
Update copyright notices for 2013.
[gnu-emacs] / lisp / cedet / semantic / tag-ls.el
1 ;;; semantic/tag-ls.el --- Language Specific override functions for tags
2
3 ;; Copyright (C) 1999-2004, 2006-2013 Free Software Foundation, Inc.
4
5 ;; Author: Eric M. Ludlam <zappo@gnu.org>
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Commentary:
23 ;;
24 ;; There are some features of tags that are too language dependent to
25 ;; put in the core `semantic-tag' functionality. For instance, the
26 ;; protection of a tag (as specified by UML) could be almost anything.
27 ;; In Java, it is a type specifier. In C, there is a label. This
28 ;; information can be derived, and thus should not be stored in the tag
29 ;; itself. These are the functions that languages can use to derive
30 ;; the information.
31
32 (require 'semantic)
33 (require 'semantic/find)
34
35 ;;; Code:
36
37 ;;; TAG SIMILARITY:
38 ;;
39 ;; Two tags that represent the same thing are "similar", but not the "same".
40 ;; Similar tags might have the same name, but one is a :prototype, while
41 ;; the other is an implementation.
42 ;;
43 ;; Each language will have different things that can be ignored
44 ;; between two "similar" tags, so similarity checks involve a series
45 ;; of mode overridable features. Some are "internal" features.
46 (defvar semantic-tag-similar-ignorable-attributes '(:prototype-flag)
47 "The tag attributes that can be ignored during a similarity test.")
48
49 (define-overloadable-function semantic--tag-similar-names-p (tag1 tag2 blankok)
50 "Compare the names of TAG1 and TAG2.
51 If BLANKOK is false, then the names must exactly match.
52 If BLANKOK is true, then if either of TAG1 or TAG2 has blank
53 names, then that is ok, and this returns true, but if they both
54 have values, they must still match.")
55
56 (defun semantic--tag-similar-names-p-default (tag1 tag2 blankok)
57 "Compare the names of TAG1 and TAG2.
58 If BLANKOK is false, then the names must exactly match.
59 If BLANKOK is true, then if either of TAG1 or TAG2 has blank
60 names, then that is ok, and this returns true, but if they both
61 have values, they must still match."
62 (let ((n1 (semantic-tag-name tag1))
63 (n2 (semantic-tag-name tag2)))
64 (or (and blankok (or (null n1) (null n2) (string= n1 "") (string= n2 "")))
65 (string= n1 n2))))
66
67 (define-overloadable-function semantic--tag-similar-types-p (tag1 tag2)
68 "Compare the types of TAG1 and TAG2.
69 This function can be overridden, for example to compare a fully
70 qualified with an unqualified type."
71 (cond
72 ((and (null (semantic-tag-type tag1))
73 (null (semantic-tag-type tag2)))
74 t)
75 ((or (null (semantic-tag-type tag1))
76 (null (semantic-tag-type tag2)))
77 nil)
78 (t
79 (:override))))
80
81 (defun semantic--tag-similar-types-p-default (tag1 tag2)
82 "Compare the types of TAG1 and TAG2.
83 This function can be overridden, for example to compare a fully
84 qualified with an unqualified type."
85 (semantic-tag-of-type-p tag1 (semantic-tag-type tag2)))
86
87 (define-overloadable-function semantic--tag-attribute-similar-p (attr value1 value2 ignorable-attributes)
88 "Test to see if attribute ATTR is similar for VALUE1 and VALUE2.
89 IGNORABLE-ATTRIBUTES is described in `semantic-tag-similar-p'.
90 This function is internal, but allows customization of `semantic-tag-similar-p'
91 for a given mode at a more granular level.
92
93 Note that :type, :name, and anything in IGNORABLE-ATTRIBUTES will
94 not be passed to this function.
95
96 Modes that override this function can call `semantic--tag-attribute-similar-p-default'
97 to do the default equality tests if ATTR is not special for that mode.")
98
99 (defun semantic--tag-attribute-similar-p-default (attr value1 value2 ignorable-attributes)
100 "For ATTR, VALUE1, VALUE2 and IGNORABLE-ATTRIBUTES, test for similarity."
101 (cond
102 ;; Tag sublists require special testing.
103 ((and (listp value1) (semantic-tag-p (car value1))
104 (listp value2) (semantic-tag-p (car value2)))
105 (let ((ans t)
106 (taglist1 value1)
107 (taglist2 value2))
108 (when (not (eq (length taglist1) (length taglist2)))
109 (setq ans nil))
110 (while (and ans taglist1 taglist2)
111 (setq ans (apply 'semantic-tag-similar-p
112 (car taglist1) (car taglist2)
113 ignorable-attributes)
114 taglist1 (cdr taglist1)
115 taglist2 (cdr taglist2)))
116 ans))
117
118 ;; The attributes are not the same?
119 ((not (equal value1 value2))
120 nil)
121
122 (t t))
123 )
124
125 (define-overloadable-function semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
126 "Test to see if TAG1 and TAG2 are similar.
127 Two tags are similar if their name, datatype, and various attributes
128 are the same.
129
130 Similar tags that have sub-tags such as arg lists or type members,
131 are similar w/out checking the sub-list of tags.
132 Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity.
133 By default, `semantic-tag-similar-ignorable-attributes' is referenced for
134 attributes, and IGNORABLE-ATTRIBUTES will augment this list.
135
136 Note that even though :name is not an attribute, it can be used to
137 to indicate lax comparison of names via `semantic--tag-similar-names-p'")
138
139 ;; Note: optional thing is because overloadable fcns don't handle this
140 ;; quite right.
141 (defun semantic-tag-similar-p-default (tag1 tag2 &optional ignorable-attributes)
142 "Test to see if TAG1 and TAG2 are similar.
143 Two tags are similar if their name, datatype, and various attributes
144 are the same.
145
146 IGNORABLE-ATTRIBUTES are tag attributes that can be ignored.
147
148 See `semantic-tag-similar-p' for details."
149 (let* ((ignore (append ignorable-attributes semantic-tag-similar-ignorable-attributes))
150 (A1 (and (semantic--tag-similar-names-p tag1 tag2 (memq :name ignore))
151 (semantic--tag-similar-types-p tag1 tag2)
152 (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))))
153 (attr1 (semantic-tag-attributes tag1))
154 (attr2 (semantic-tag-attributes tag2))
155 (A2 t)
156 (A3 t)
157 )
158 ;; Test if there are non-ignorable attributes in A2 which are not present in A1
159 (while (and A2 attr2)
160 (let ((a (car attr2)))
161 (unless (or (eq a :type) (memq a ignore))
162 (setq A2 (semantic-tag-get-attribute tag1 a)))
163 (setq attr2 (cdr (cdr attr2)))))
164 (while (and A2 attr1 A3)
165 (let ((a (car attr1)))
166
167 (cond ((or (eq a :type) ;; already tested above.
168 (memq a ignore)) ;; Ignore them...
169 nil)
170
171 (t
172 (setq A3
173 (semantic--tag-attribute-similar-p
174 a (car (cdr attr1)) (semantic-tag-get-attribute tag2 a)
175 ignorable-attributes)))
176 ))
177 (setq attr1 (cdr (cdr attr1))))
178 (and A1 A2 A3)))
179
180 ;;; FULL NAMES
181 ;;
182 ;; For programmer convenience, a full name is not specified in source
183 ;; code. Instead some abbreviation is made, and the local environment
184 ;; will contain the info needed to determine the full name.
185 (define-overloadable-function semantic-tag-full-package (tag &optional stream-or-buffer)
186 "Return the fully qualified package name of TAG in a package hierarchy.
187 STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
188 but must be a toplevel semantic tag stream that contains TAG.
189 A Package Hierarchy is defined in UML by the way classes and methods
190 are organized on disk. Some languages use this concept such that a
191 class can be accessed via it's fully qualified name, (such as Java.)
192 Other languages qualify names within a Namespace (such as C++) which
193 result in a different package like structure.
194
195 Languages which do not override this function will just search the
196 stream for a tag of class 'package, and return that."
197 (let ((stream (semantic-something-to-tag-table
198 (or stream-or-buffer tag))))
199 (:override-with-args (tag stream))))
200
201 (defun semantic-tag-full-package-default (tag stream)
202 "Default method for `semantic-tag-full-package' for TAG.
203 Return the name of the first tag of class `package' in STREAM."
204 (let ((pack (car-safe (semantic-find-tags-by-class 'package stream))))
205 (when (and pack (semantic-tag-p pack))
206 (semantic-tag-name pack))))
207
208 (define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
209 "Return the fully qualified name of TAG in the package hierarchy.
210 STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
211 but must be a toplevel semantic tag stream that contains TAG.
212 A Package Hierarchy is defined in UML by the way classes and methods
213 are organized on disk. Some languages use this concept such that a
214 class can be accessed via it's fully qualified name, (such as Java.)
215 Other languages qualify names within a Namespace (such as C++) which
216 result in a different package like structure.
217
218 Languages which do not override this function with
219 `tag-full-name' will combine `semantic-tag-full-package' and
220 `semantic-tag-name', separated with language separator character.
221 Override functions only need to handle STREAM-OR-BUFFER with a
222 tag stream value, or nil.
223
224 TODO - this function should probably also take a PARENT to TAG to
225 resolve issues where a method in a class in a package is present."
226 (let ((stream (semantic-something-to-tag-table
227 (or stream-or-buffer tag))))
228 (:override-with-args (tag stream))))
229
230 (make-obsolete-overload 'semantic-nonterminal-full-name
231 'semantic-tag-full-name "23.2")
232
233 (defun semantic-tag-full-name-default (tag stream)
234 "Default method for `semantic-tag-full-name'.
235 Return the name of TAG found in the toplevel STREAM."
236 (let ((pack (semantic-tag-full-package tag stream))
237 (name (semantic-tag-name tag)))
238 (if pack
239 (concat pack
240 (car semantic-type-relation-separator-character)
241 name)
242 name)))
243
244 ;;; UML features:
245 ;;
246 ;; UML can represent several types of features of a tag
247 ;; such as the `protection' of a symbol, or if it is abstract,
248 ;; leaf, etc. Learn about UML to catch onto the lingo.
249
250 (define-overloadable-function semantic-tag-calculate-parent (tag)
251 "Attempt to calculate the parent of TAG.
252 The default behavior (if not overridden with `tag-calculate-parent')
253 is to search a buffer found with TAG, and if externally defined,
254 search locally, then semanticdb for that tag (when enabled.)")
255
256 (defun semantic-tag-calculate-parent-default (tag)
257 "Attempt to calculate the parent of TAG."
258 (when (semantic-tag-in-buffer-p tag)
259 (with-current-buffer (semantic-tag-buffer tag)
260 (save-excursion
261 (goto-char (semantic-tag-start tag))
262 (semantic-current-tag-parent))
263 )))
264
265 (define-overloadable-function semantic-tag-protection (tag &optional parent)
266 "Return protection information about TAG with optional PARENT.
267 This function returns on of the following symbols:
268 nil - No special protection. Language dependent.
269 'public - Anyone can access this TAG.
270 'private - Only methods in the local scope can access TAG.
271 'protected - Like private for outside scopes, like public for child
272 classes.
273 Some languages may choose to provide additional return symbols specific
274 to themselves. Use of this function should allow for this.
275
276 The default behavior (if not overridden with `tag-protection'
277 is to return a symbol based on type modifiers."
278 (and (not parent)
279 (semantic-tag-overlay tag)
280 (semantic-tag-in-buffer-p tag)
281 (setq parent (semantic-tag-calculate-parent tag)))
282 (:override))
283
284 (make-obsolete-overload 'semantic-nonterminal-protection
285 'semantic-tag-protection "23.2")
286
287 (defun semantic-tag-protection-default (tag &optional parent)
288 "Return the protection of TAG as a child of PARENT default action.
289 See `semantic-tag-protection'."
290 (let ((mods (semantic-tag-modifiers tag))
291 (prot nil))
292 (while (and (not prot) mods)
293 (if (stringp (car mods))
294 (let ((s (car mods)))
295 (setq prot
296 ;; A few silly defaults to get things started.
297 (cond ((or (string= s "public")
298 (string= s "extern")
299 (string= s "export"))
300 'public)
301 ((string= s "private")
302 'private)
303 ((string= s "protected")
304 'protected)
305 ((string= s "package")
306 'package)
307 ))))
308 (setq mods (cdr mods)))
309 prot))
310
311 (defun semantic-tag-package-protected-p (tag &optional parent currentpackage)
312 "Non-nil if TAG is not available via package access control.
313 For languages (such as Java) where a method is package protected,
314 this method will return nil if TAG, as found in PARENT is available
315 for access from a file in CURRENTPACKAGE.
316 If TAG is not protected by PACKAGE, also return t. Use
317 `semantic-tag-protected-p' instead.
318 If PARENT is not provided, it will be derived when passed to
319 `semantic-tag-protection'.
320 If CURRENTPACKAGE is not provided, it will be derived from the current
321 buffer."
322 (let ((tagpro (semantic-tag-protection tag parent)))
323 (if (not (eq tagpro 'package))
324 t ;; protected
325
326 ;; package protection, so check currentpackage.
327 ;; Deriving the package is better from the parent, as TAG is
328 ;; probably a field or method.
329 (if (not currentpackage)
330 (setq currentpackage (semantic-tag-full-package nil (current-buffer))))
331 (let ((tagpack (semantic-tag-full-package (or parent tag))))
332 (if (string= currentpackage tagpack)
333 nil
334 t)) )))
335
336 (defun semantic-tag-protected-p (tag protection &optional parent)
337 "Non-nil if TAG is protected.
338 PROTECTION is a symbol which can be returned by the method
339 `semantic-tag-protection'.
340 PARENT is the parent data type which contains TAG.
341
342 For these PROTECTIONs, true is returned if TAG is:
343 @table @asis
344 @item nil
345 Always true.
346 @item private
347 True if nil.
348 @item protected
349 True if private or nil.
350 @item public
351 True if private, protected, or nil.
352 @end table"
353 (if (null protection)
354 t
355 (let ((tagpro (semantic-tag-protection tag parent)))
356 (or (and (eq protection 'private)
357 (null tagpro))
358 (and (eq protection 'protected)
359 (or (null tagpro)
360 (eq tagpro 'private)))
361 (and (eq protection 'public)
362 (not (eq tagpro 'public)))))
363 ))
364
365 (define-overloadable-function semantic-tag-abstract-p (tag &optional parent)
366 "Return non nil if TAG is abstract.
367 Optional PARENT is the parent tag of TAG.
368 In UML, abstract methods and classes have special meaning and behavior
369 in how methods are overridden. In UML, abstract methods are italicized.
370
371 The default behavior (if not overridden with `tag-abstract-p'
372 is to return true if `abstract' is in the type modifiers.")
373
374 (make-obsolete-overload 'semantic-nonterminal-abstract
375 'semantic-tag-abstract-p "23.2")
376
377 (defun semantic-tag-abstract-p-default (tag &optional parent)
378 "Return non-nil if TAG is abstract as a child of PARENT default action.
379 See `semantic-tag-abstract-p'."
380 (let ((mods (semantic-tag-modifiers tag))
381 (abs nil))
382 (while (and (not abs) mods)
383 (if (stringp (car mods))
384 (setq abs (or (string= (car mods) "abstract")
385 (string= (car mods) "virtual"))))
386 (setq mods (cdr mods)))
387 abs))
388
389 (define-overloadable-function semantic-tag-leaf-p (tag &optional parent)
390 "Return non nil if TAG is leaf.
391 Optional PARENT is the parent tag of TAG.
392 In UML, leaf methods and classes have special meaning and behavior.
393
394 The default behavior (if not overridden with `tag-leaf-p'
395 is to return true if `leaf' is in the type modifiers.")
396
397 (make-obsolete-overload 'semantic-nonterminal-leaf
398 'semantic-tag-leaf-p "23.2")
399
400 (defun semantic-tag-leaf-p-default (tag &optional parent)
401 "Return non-nil if TAG is leaf as a child of PARENT default action.
402 See `semantic-tag-leaf-p'."
403 (let ((mods (semantic-tag-modifiers tag))
404 (leaf nil))
405 (while (and (not leaf) mods)
406 (if (stringp (car mods))
407 ;; Use java FINAL as example default. There is none
408 ;; for C/C++
409 (setq leaf (string= (car mods) "final")))
410 (setq mods (cdr mods)))
411 leaf))
412
413 (define-overloadable-function semantic-tag-static-p (tag &optional parent)
414 "Return non nil if TAG is static.
415 Optional PARENT is the parent tag of TAG.
416 In UML, static methods and attributes mean that they are allocated
417 in the parent class, and are not instance specific.
418 UML notation specifies that STATIC entries are underlined.")
419
420 (defun semantic-tag-static-p-default (tag &optional parent)
421 "Return non-nil if TAG is static as a child of PARENT default action.
422 See `semantic-tag-static-p'."
423 (let ((mods (semantic-tag-modifiers tag))
424 (static nil))
425 (while (and (not static) mods)
426 (if (stringp (car mods))
427 (setq static (string= (car mods) "static")))
428 (setq mods (cdr mods)))
429 static))
430
431 ;;;###autoload
432 (define-overloadable-function semantic-tag-prototype-p (tag)
433 "Return non nil if TAG is a prototype.
434 For some languages, such as C, a prototype is a declaration of
435 something without an implementation."
436 )
437
438 (defun semantic-tag-prototype-p-default (tag)
439 "Non-nil if TAG is a prototype."
440 (let ((p (semantic-tag-get-attribute tag :prototype-flag)))
441 (cond
442 ;; Trust the parser author.
443 (p p)
444 ;; Empty types might be a prototype.
445 ;; @todo - make this better.
446 ((eq (semantic-tag-class tag) 'type)
447 (not (semantic-tag-type-members tag)))
448 ;; No other heuristics.
449 (t nil))
450 ))
451
452 (provide 'semantic/tag-ls)
453
454 ;; Local variables:
455 ;; generated-autoload-file: "loaddefs.el"
456 ;; generated-autoload-load-name: "semantic/tag-ls"
457 ;; End:
458
459 ;;; semantic/tag-ls.el ends here